oxide-conservation 0.1.0

Conservation law verification for GPU computations — energy, mass, and information conservation across kernel boundaries
Documentation
  • Coverage
  • 100%
    43 out of 43 items documented0 out of 26 items with examples
  • Size
  • Source code size: 26.72 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 681.33 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 2s Average build duration of successful builds.
  • all releases: 2s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • SuperInstance/oxide-conservation
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • SuperInstance

oxide-conservation

Conservation law verification for GPU computations.

A Rust library that checks whether energy, mass, and information quantities are conserved across GPU kernel boundaries — catching numerical drift, rounding errors, and algorithmic bugs before they cascade through your compute pipeline.

Why Conservation Verification?

GPU kernels manipulate massive arrays of floating-point values in parallel. Between kernel launches, data flows through global memory, shared memory, registers, and back again. At every boundary, subtle bugs can introduce drift:

  • Floating-point rounding in reductions, scans, and matrix operations
  • Race conditions in atomic operations that lose updates
  • Algorithmic errors where a kernel inadvertently drops or duplicates data
  • Numerical instability where error compounds across thousands of iterations

In scientific computing, physics simulation, and financial modeling, these bugs are catastrophic. A mass conservation violation of 0.01% in a fluid dynamics simulation might be invisible in a single frame but render a 10,000-step integration completely wrong.

Conservation verification is the assertion layer for numerical correctness. Just as you assert invariants in software, you should assert conservation invariants in compute pipelines.

The Math

Ternary Verification

For any conserved quantity Q measured before and after a kernel execution:

Δ = |Q_after - Q_before|

The ternary verdict is:

Condition Verdict Value
Δ = 0 Conserved +1
0 < Δ ≤ ε Approximate 0
Δ > ε Violated −1

Where ε (epsilon) is a configurable tolerance that reflects the expected numerical precision of your computation.

Cumulative Drift

Across N kernel executions, cumulative drift is:

D_total = Σᵢ |Δᵢ|

When D_total > threshold, an alert is raised. This catches slow leaks that would pass any single-kernel check but accumulate over a full simulation run.

Conservation Laws

Three built-in laws are provided:

  • Energy — Total energy before = total energy after. Critical for physics simulations, Hamiltonian systems, and N-body integrators.
  • Mass — Total mass/particle count is preserved. Essential for fluid dynamics, particle transport, and chemical reaction modeling.
  • Information — Entropy bounds, data integrity, bit-level preservation. Relevant for compression, encryption, and lossless transform pipelines.

Custom laws can be defined for domain-specific invariants (angular momentum, charge, baryon number, etc.).

Key Types

ConservationLaw

pub enum ConservationLaw {
    Energy,
    Mass,
    Information,
    Custom(String),
}

The law being verified. Custom variants let you define domain-specific invariants like "angular_momentum" or "electric_charge".

Ternary

pub enum Ternary {
    Conserved = 1,   // exact match
    Approximate = 0,  // within epsilon
    Violated = -1,    // exceeds threshold
}

Three-valued logic that distinguishes "perfectly conserved" from "close enough" from "broken." This is more informative than a simple boolean pass/fail.

ConservationMonitor

Takes snapshots of quantities before kernel execution and verifies them after:

let mut monitor = ConservationMonitor::new(1e-6); // epsilon
monitor.snapshot(ConservationLaw::Energy, "nbody_step", total_energy);
// ... launch GPU kernel ...
let result = monitor.verify(&ConservationLaw::Energy, "nbody_step", new_total_energy);
assert!(result.unwrap().verdict.is_ok());

VerificationResult

Holds the full picture: law, before/after values, delta, epsilon, and the ternary verdict.

ConservationBudget

Tracks cumulative drift across an entire compute pipeline:

let mut budget = ConservationBudget::new(0.1); // alert threshold

for step in 0..10000 {
    let result = monitor.verify(&ConservationLaw::Energy, "sim", energy_after);
    budget.record(&result.unwrap());
    
    if let Some(alert) = budget.check_alert() {
        eprintln!("WARNING: {}", alert);
        break;
    }
}

println!("Average drift: {}", budget.average_drift());
println!("Violation rate: {:.2}%", budget.violation_rate() * 100.0);

Alert

Raised when cumulative drift exceeds the budget threshold. Includes the total drift, the threshold, and the worst-offending conservation law.

Usage

Add to Cargo.toml:

[dependencies]
oxide-conservation = "0.1"

Basic Verification

use oxide_conservation::{ConservationLaw, VerificationResult, Ternary};

let result = VerificationResult::check(
    ConservationLaw::Mass,
    1000.0,   // before
    999.9998, // after
    0.001,    // epsilon
);

assert_eq!(result.verdict, Ternary::Approximate);
println!("{}", result); // [ 0 (approximate)] 1000 → 999.9998 (Δ=0.0002, ε=0.001)

Multi-Kernel Pipeline

use oxide_conservation::{ConservationMonitor, ConservationLaw, ConservationBudget};

let mut monitor = ConservationMonitor::new(1e-9);
let mut budget = ConservationBudget::new(1e-3);

// Snapshot before kernel chain
monitor.snapshot(ConservationLaw::Energy, "fft_forward", energy_in);
monitor.snapshot(ConservationLaw::Information, "fft_forward", entropy_in);

// ... run FFT kernel on GPU ...

// Verify after
let energy_result = monitor.verify(&ConservationLaw::Energy, "fft_forward", energy_out);
let info_result = monitor.verify(&ConservationLaw::Information, "fft_forward", entropy_out);

budget.record(&energy_result.unwrap());
budget.record(&info_result.unwrap());

if let Some(alert) = budget.check_alert() {
    log::error!("Conservation drift alert: {}", alert);
}

Batch Verification

monitor.snapshot(ConservationLaw::Energy, "kernel_a", 42.0);
monitor.snapshot(ConservationLaw::Mass, "kernel_b", 100.0);
monitor.snapshot(ConservationLaw::Custom("charge".into()), "kernel_c", 0.0);

// Provide after-values for all pending snapshots
let results = monitor.verify_all(|law, label| {
    match label {
        "kernel_a" => 42.0000001,
        "kernel_b" => 100.0,
        "kernel_c" => 0.0,
        _ => 0.0,
    }
});

for r in &results {
    println!("{}: {}", r.law, r.verdict);
}

Statistics

ConservationBudget provides aggregate statistics across your entire workload:

Method Description
verification_count() Total number of verifications recorded
violation_count() Number of verifications that returned Violated
violation_rate() Fraction of verifications that were violations
average_drift() Mean absolute drift across all verifications
drift_for(law) Cumulative drift for a specific conservation law
total_drift() Sum of drift across all laws

Connection to the Oxide Stack

oxide-conservation is part of the Oxide family of crates for robust GPU compute in Rust:

  • oxide-conservation — Conservation law verification (this crate)
  • Works alongside any GPU compute framework (wgpu, CUDA, OpenCL)
  • Designed to integrate into CI pipelines for numerical regression testing
  • Zero dependencies — add verification without bloating your build

The Oxide philosophy: numerical correctness is not optional. Every GPU compute pipeline should verify its invariants. This crate makes it easy.

License

MIT