ψ Vikshep

Determinism

Why floating point is usually not reproducible,
and how VDS-1 makes it so.

Vikshep guarantees that the same input produces the same output bytes across every conforming backend. This page explains what that guarantee costs, what it covers, and how you can verify it yourself with the free open-source tool.

The problem

Why two runs of the same code can produce different numbers

1. Compiler reordering

Floating point addition is not associative: (a + b) + c may not equal a + (b + c) in binary32. An optimising compiler is permitted to reorder floating point operations unless you tell it not to (-fno-unsafe-math-optimizations, Rust #[deny(clippy::float_arithmetic_round_trip)]). Different optimisation levels, different pass orders, different compilers — different results.

2. Fused multiply-add (FMA)

A hardware FMA instruction computes a × b + c with one rounding, instead of two. Whether the compiler emits FMA depends on the CPU model, the compiler version, and the optimisation flags — not on the source code. A single FMA in the inner loop produces different low-order bits than the two-step version, and those bits accumulate through the computation.

3. Subnormal (denormal) numbers

Very small floating point values near zero are represented as subnormals, with reduced precision. Different hardware and compiler settings flush subnormals to zero at different points. A value that is 2.3 × 10⁻⁴⁵ on one machine becomes 0 on another. The difference is a handful of ULPs per operation, but in a cascade of several hundred wavelet convolutions it becomes measurable.

4. GPU non-determinism

GPU kernels launch thousands of threads; which threads execute in which order depends on the scheduler, the occupancy, and the driver version. Reductions and dot products are especially sensitive: summing 4096 values in a different order can change the last few bits. NVIDIA and Apple do not guarantee identical results across driver versions by default.

5. libm functions

Transcendental functions (exp, log, sin, cos, sqrt) vary by platform. glibc on x86_64 uses different hardware paths than macOS libm; CUDA uses its own polynomial approximations. Even for a correctly-rounded implementation, the last ULP may differ between platforms.

The solution

How VDS-1 eliminates each source of divergence

VDS-1 (Vikshep Determinism Specification) is a written, versioned specification published in the open vikshep-compute repository under CC-BY-4.0. It defines, for each computation, what "the same bytes" means and provides test vectors that any implementation can verify against.

No FMA in Tier-1 kernels

VDS-1 §2.4 bans FMA from Tier-1 code unless the specification explicitly permits it. The reference Rust implementation uses explicit split operations. The CUDA and Metal backends set the appropriate compiler flags to disable FMA contraction.

Explicit flush-to-zero at every operation

VDS-1 §8.1 defines flush-to-zero semantics: after every multiply and every add in a Tier-1 kernel, any subnormal result is flushed to +0 or -0 preserving sign. This is emulated in software by the CPU reference and enforced by hardware flags on CUDA and Metal. The specification records that Metal 2 on GCN 4th-gen sets DENORM_FLZ_IN and DENORM_FLZ_OUT by default for compute shaders.

No libm — portable exp/log/sin/cos implemented in crates/vikshep-detmath

All transcendental functions used anywhere in the specification — currently exp, ln, sin, cos (for Morlet wavelet construction) — are implemented in crates/vikshep-detmath using exact polynomial approximations that produce the same bits on x86_64 and AArch64. CI verifies that cargo tree -e features -i libm prints no output.

Stockham FFT with fixed butterfly order

The wavelet convolutions use a Stockham auto-sort FFT, which has a predictable butterfly structure with no data-dependent branching. The butterfly order within each level is fixed; all backends execute it identically.

Tier-2 computations run only in the Rust CPU reference

Filter table construction and statistical computations (dCorr_w, JSD) always run in the single Rust reference implementation, regardless of which backend is active. GPU backends receive the pre-built tables as inputs. This eliminates the GPU non-determinism problem for Tier-2 code.

VDS-1 tiers

Three tiers — one certificate per result

Every computation in Vikshep belongs to exactly one tier. The Determinism Certificate records the tier alongside the output OIDs, so a reviewer knows exactly what kind of reproducibility claim the certificate makes.

Tier 1

Bit-exact on every conforming backend

  • —All S₀, S₁, S₂ and r₂ = S₂/S₁ tensor computations
  • —All values are IEEE-754 binary32
  • —Explicit flush-to-zero (FTZ) applied after every multiply and add
  • —No FMA (fused multiply-add) unless this specification explicitly permits it
  • —No libm — all transcendental functions banned from Tier-1 kernels
  • —No compiler auto-vectorisation that would change the result order
  • —Verified identical on CPU (Rust reference), CUDA, and Metal for VDS-1.2 + numerics_version=3
Tier 2

Bit-exact on every platform — always runs in the Rust CPU reference

  • —Filter construction (Morlet wavelets) and twiddle tables
  • —DisCo statistics: dCorr_w (weighted distance correlation), JSD
  • —SW1 / HNSW anomaly search
  • —Report generation
  • —GPU backends must not re-implement Tier-2 code — they receive the pre-built tables as inputs
  • —Uses IEEE-754 binary64 internally; where a Tier-2 result becomes a Tier-1 input, it is rounded to binary32 before crossing
Tier 3

Provenance recorded — reproducibility not certified

  • —Geant4 simulation output
  • —Loader pre-processing from non-deterministic sources
  • —External model inference (if used)
  • —Studio records Tier-3 provenance: tool, version, build, platform, seed
  • —VDS-1 does not define conformance for Tier-3 operations

Conformance CI

Live status

The vikshep-compute repository runs a conformance suite on every commit across Linux x86_64 and macOS AArch64. The suite checks that every conformance vector in conformance/vectors/v3/ is reproduced bit-exactly. A backend may only claim conformance against one numerics version if it passes 100% of that version's vectors.

Conformance CI — GitHub Actions →

The CI badge reflects the current state of the main branch of samvardhan03/vikshep-compute. Conformance vectors are versioned; a new numerics version increments the vector directory and regenerates all hashes.

Free verifier

Verify any result yourself

The free verifier re-runs the recorded computation with the open CPU reference and compares every output OID. It requires only the certificate file and the original input directory. It works fully offline. It is also exposed in the Python package for use in analysis pipelines.

Install the verifier

git clone https://github.com/samvardhan03/vikshep-compute.git
cd vikshep-compute
cargo build --release -p vikshep-conformance

Verify a certificate

vikshep-conformance verify result.certificate.json --inputs ./inputs/

# Output:
# VERIFIED  output OIDs match (12 / 12)
# Tier-1 computations: 12  backend: cpu-rust  numerics_version: 3
# Certificate signed by: vsk_key_<id>  (Ed25519 — key not in trust store; signature valid)

The verifier prints VERIFIED if every output OID in the certificate matches the OID produced by re-running the computation, or MISMATCH with a per-OID diff table if any output differs. A valid signature identifies the installation; the reviewer need not trust the installation to trust the OID match.

Check the conformance hash report

cargo run -p vikshep-conformance -- hashes

Prints the expected hash report for the current numerics version. CI runs this on every commit across platforms and compares the output byte-for-byte.

vikshep-compute on GitHub →Studio — Prove pillar →