Skip to content
DeepForgeby svx

DeepForge Research · 2026-09-19

REPROGPU: Cross-Adapter Bit-Reproducible WebGPU Kernels and a Conformance Harness for a Declared Integer Subset

  • Technical report
  • Artifact
  • Not peer reviewed

A conformance harness for a declared integer WGSL subset, recorded as a narrow artifact contribution rather than a new method.

Abstract

GPU results are not reproducible across vendors. The WGSL specification leaves rounding direction, reassociation, fusion, and subnormal flushing unspecified (section 15.7), so a floating-point kernel is free to return different bytes on different adapters. REPROGPU is a browser/WebGPU library and cross-adapter conformance harness that pins byte-identical SHA-256 outputs for a declared integer and fixed-point WGSL kernel subset - exact f32 summation by a 320-bit integer superaccumulator (K1), Philox4x32-10 (K2), Q16.16 GEMM with one arithmetic floor shift (K3), and integer SHA-256 (K4) - and declares general floating-point results out of scope, on the specification's own boundary. K5 is an f32 matmul negative control that the browser lab runs and records; it carries no pass criterion and no pinned hash, and no outcome for it is recorded in this artifact, so this paper does not claim an observed float divergence. The CPU-only gate reproduces the pinned reference hashes byte-for-byte in five of five criteria: K1 at count 4,104 with hash c046384e, K2 at 65,536 with f9004cf3, K3 at 65,536 with fbe13a3b, and K4 at 16,385 with eea119f4. It also matches three Random123 Philox known-answer tests and the FIPS SHA-256 vectors, pins all five WGSL source hashes, and scans the integer kernels for float types, atomics, discard, and unmasked runtime shifts. The gate cannot compile WGSL or run a GPU; the browser lab is the demonstration, and no CI artifact is evidence of GPU agreement.

  • webgpu
  • reproducibility
  • integer kernels
  • conformance harness
  • superaccumulator
  • philox
  • sha-256
Reading

1. Introduction & motivation

A GPU result is not a portable number. The WGSL CRD of 2026-09-15 specifies floating-point arithmetic only loosely: section 15.7.4.1 gives x+y, x-y, and x*y as correctly rounded to either neighbour with the rounding direction unspecified, gives x/y as 2.5 ULP rather than correctly rounded, permits reassociation and fusion in section 15.7.5, permits subnormal flushing and an indeterminate value for runtime overflow and NaN in section 15.7.2, and says the sign of zero may be ignored. Two drivers on the same machine may therefore return different bits for the same shader, and two vendors need not agree at all. This is not a defect in a particular engine; it is the specification's declared boundary. NVIDIA's own reproducibility team states that bit-exactness is not expected across GPU architectures (framework-reproducibility issue #28), and the WebGPU CTS tests floating-point accuracy within ULP tolerances rather than bit-exact cross-adapter equality.

The consequence is that a browser GPU computation cannot currently be re-run and compared by a third party. Scientific reproduction of a GPU-assisted result, verifiable browser compute, and automated grading of a computational answer all need the same missing property: the same declared program on a different adapter either produces the same bytes or is reported as a divergence. The smaller observation, and the one this paper builds on, is that a well-defined subset of WGSL already has that property. Integer wrapping arithmetic, bitwise operations, comparisons, bitcast between i32 and u32, and the little-endian host-shared buffer layout are all specified exactly. If every real step of a kernel is reduced to those operations, then the output bytes are a function of the input bytes alone, independent of adapter, workgroup schedule, or compiler reassociation. The hard part stops being the arithmetic and becomes the discipline of staying inside the subset, pinning the source bytes, and building a harness that can tell a genuine divergence from a partial or stale run.

  • A declared integer subset with a written boundary: only i32/u32 arithmetic, bitwise operations, comparisons, bitcast between i32/u32, and host-shared little-endian layout are relied upon; all f32 values are transported and decoded as opaque u32 bit patterns, and no float arithmetic, conversion, or bitcast through float occurs in K1 to K4.
  • Five kernels: K1 exact f32 summation by a 10-limb (320-bit) integer superaccumulator; K2 Philox4x32-10 counter RNG against published Random123 vectors; K3 Q16.16 256x256x256 GEMM with a 3-limb (96-bit) accumulator and a single arithmetic floor shift; K4 integer SHA-256 over a fixed 1 MiB message; and K5, an f32 matmul negative control that carries no pass criterion, no pinned hash, and no recorded outcome in this artifact.
  • A CPU-only permanent gate that reproduces every pinned reference hash and count, runs the known-answer tests, pins the WGSL source bytes, and scans the integer kernels for float types, atomics, discard, and unmasked dynamic shifts.
  • A cross-adapter manifest spec: per-record adapter identity, dispatch shape, output bytes and raw-byte SHA-256, status count and flags, compile errors, and outcome, serialized canonically and hashed.
  • An explicit negative control and an explicit honesty rule: K5 is an f32 matmul with no pass criterion, no pinned hash, and no recorded outcome in this artifact; the gate checks references and vectors, the browser lab is the demonstration, and no CI artifact may be cited as evidence of GPU agreement.
  • A limitations list that names non-finite inputs, out-of-range wrap, the one-machine sample, self-reported adapter identity, machine-checkable exceptions, the absence of any recorded cross-adapter comparison, and the non-claim about general float.

3. The WGSL exactness audit and the declared boundary

The subset is chosen from the specification, not from benchmarking. The following are guaranteed portable and exact, and the kernels are built only from them. Expressions on concrete integer types that overflow produce a result modulo 2^bitwidth (section 6.2.3), and i32 is two's complement, so i32 and u32 addition, subtraction, multiplication, and unary negation all wrap exactly. Bitwise and, or, xor, and complement are exact and component-wise (section 8.10). Comparisons and select are exact (section 8.9). Shifts are specified as the shift value modulo the bit width of the left operand, so u32 right shift is logical and i32 right shift is arithmetic (section 8.10). Bitcast between i32 and u32, and between their vectors, is an exact bit reinterpretation (section 17.2.1 with layout in section 14.4.4). Numeric values in host-shared buffers are stored little-endian (section 14.4.4), so readback can be byte-addressed.

The following are excluded because the specification leaves them implementation-defined. All f32 and f16 arithmetic is out, because section 15.7.4.1 gives the rounding direction as either neighbour for add, subtract, and multiply, because division is 2.5 ULP rather than correctly rounded, and because section 15.7.5 explicitly permits reassociation and fusion, so a*b+c may or may not contract to fma and fma itself may expand. Subnormal inputs and outputs may be flushed to zero, the sign of zero may be ignored, and runtime overflow, infinity, and NaN may become an indeterminate value (section 15.7.2, the Finite Math Assumption). Transcendentals, determinant, smoothstep edges, and out-of-bounds indexing are likewise excluded. Mapping a floating-point value to an integer is also not exact (section 15.7.6), so K1 never converts an f32 value; it only decodes its bit pattern as u32.

Declared boundary. Only integer (i32/u32) and bit operations, bitcast between i32/u32, comparisons, and host-shared buffer layout are relied upon. In K1–K4 all f32 values are transported and decoded as opaque u32 bit patterns; no floating-point arithmetic, conversion, or bitcast-through-float occurs. All floating-point results are out of scope for the reproducibility guarantee.

4. Kernels K1-K5

Every kernel follows the same discipline. It reads only u32 or i32 words, performs only exact operations, and writes a status word first. Multi-limb integer addition is associative and exact on bounded values, so any workgroup schedule produces identical limbs; this is a proof, not an empirical result, and the fixed reduction tree is pinned anyway so that the byte serialization is recomputable without depending on a schedule. No kernel uses discard, an unmasked dynamic shift count, a floating-point operation, or atomic. Every input buffer is pre-filled with the sentinel 0xDEADBEEF and every output begins with a count canary, so a partial run or a stale buffer is detectable rather than silently hashed. The five kernels and their pinned reference outputs are below.

T2. The five kernels as shipped, with pinned reference output hashes
KernelInputsAlgorithmOutput layoutCountPinned SHA-256
K1 exact f32 sum4,096 LCG u32 binary32 patterns (seed 0x2545F491, exponent 0xFF skipped) plus 8 specials = 4,104 wordsDecode sign, exponent, mantissa; subnormals at shift 0; non-finites set sticky flags and are skipped; sum in a 10-limb (320-bit) two's-complement integer superaccumulator12 u32 little-endian: A[0..9], flags, n_seen; 48 bytes4,104c046384ed6580b8111b8ef34f5d0932289209f4920666477bc76ffe724dfa27a
K1-flagThe K1 word list plus 0x7F800000 (+Inf) and 0x7FC00000 (NaN)Same accumulator; non-finites contribute zero and set flags bit 0; the gate treats this vector as an out-of-domain flag test, never as an exact-sum oracle12 u32 little-endian: A[0..9], flags, n_seen; 48 bytes; flags must read 14,106cc7dca6d69fec7162cf610b0170076aec74d3d5bec47b2ea80d0b74afb3c9ecb
K2 Philox4x32-10 streamFixed key (0x12345678, 0x9ABCDEF0); block i uses counter (i, 0, 0, 0), 65,536 blocksRandom123 Philox4x32-10; 32x32 to 64 mulhilo by 16-bit halves; exactly 10 rounds; key bumps W0/W1 after rounds 1 to 9u32 little-endian: [n_blocks=65536, then 65,536 x 4 RNG words]; 1,048,580 bytes65,536f9004cf3ed50db5cdb6351a3eb090a498586ade2e3f7499744c951bf77f86d01
K3 Q16.16 GEMM 256x256x256A and B are 256x256 i32 row-major, Q16.16, seeded from LCG 0x1234ABCD; each raw value in [-2^20, 2^20)Exact 64-bit products from 16-bit halves accumulated in a 3-limb (96-bit) two's-complement accumulator over k = 0..255; one arithmetic right shift by 16 at the end; low 32 bits wrap256x256 i32 row-major plus status [256,256,256,n_ok]; 262,160 bytes65,536fbe13a3b4e2fc7bf3a4b38c838912651151c03460bd9d1d7f1ea81190af3932e
K4 integer SHA-2561 MiB message (2^20 bytes; byte i = LCG state_{i+1} >> 24, seed 0x2545F491), padded to 16,385 blocksFIPS 180-4 SHA-256 in u32; 64 constants; rotr message schedule; big-endian block load; final H words byte-swapped so the 32 bytes after the count equal the standard big-endian digest9 u32 little-endian: [n_blocks=16385, H0..H7]; 36 bytes16,385eea119f4059566875ceaf784400d519fd8ff2148d9f221e0004fd04944a21797
K5 f32 negative control256x256 f32 matrices with a wide exponent rangeacc = acc + A[i,k]*B[k,j] for k = 0..255; no reduction-tree and no fusion promise256x256 f32 row-major; 262,144 bytes65,536(none: no pass criterion)

Counts are the status canary the harness compares: for K1 the full consumed word count including the eight appended specials (4,104), for K2/K3/K5 the block or element count (65,536), and for K4 the block count (16,385). K5 is the float negative control: it has no pass criterion, so its hash column is empty, and no K5 outcome is recorded anywhere in this artifact. The pinned hashes are the CPU reference outputs; the gate recomputes them and the browser lab compares live GPU outputs against them.

K1 limb placement (no 64-bit intermediate)

term = (-1)^s * M * 2^shift, with M = m for a subnormal (shift = 0) and M = 0x800000 | m for a normal (shift = e - 1); let b = shift mod 32 and L = floor(shift / 32); if b == 0 add M at limb L, otherwise add (M << b) & 0xFFFFFFFF at limb L and M >> (32 - b) at limb L + 1; the accumulator is A[0..9] with value sum over i of A[i] * 2^(32i), and a negative term is negated by inverting all ten limbs and adding one with a carry from limb 0. Terms and partials are then added with carries propagated from limb 0 to limb 9.

Bound: a term is below 2^277 and N is at most 2^24, so the magnitude stays below 2^301, inside the 320-bit two's-complement range. The reference is computed in BigInt as A mod 2^320 and reduced to ten u32 limbs; the permanent gate pins its serialization and recomputes it on every run.

K3 exact accumulation and the single floor shift

S = sum over k of u32(A[i,k]) * u32(B[k,j]) mod 2^96, accumulated exactly as a 3-limb two's-complement value; result32 = (S arithmetic-right-shift 16) & 0xFFFFFFFF; the stored i32 is the low 32 bits and wraps modulo 2^32 when the floored value leaves the i32 range (section 6.2.3). The k loop is fixed at k = 0..255 and the accumulator is 96 bits because |product| < 2^62 and |S| < 2^70.

The seeded vectors draw each raw value from [-2^20, 2^20), so |product| < 2^40 and each 256-term row sum is below 2^48, comfortably inside the 96-bit bound; the wider spec bound is the design ceiling, not the pinned vector range. Wrap is documented, never presented as a correct result.

5. The cross-adapter conformance harness

The harness runs each kernel on each available adapter, reads the output buffer back, hashes the raw bytes, and emits a manifest. Its per-record fields are fixed: kernel, kernelVersion, wgslSha256, adapter identity (vendor, architecture, device, description, features, and a subset of limits), dispatch shape, output byte length, output SHA-256, status count and flags, duration, timestamp, user agent, compile errors, and an outcome of pass, fail, exception, or skip. The source hash is shared: all adapters run the same module bytes, the manifest records wgslSha256 once per kernel, and the gate pins it.

The manifest record (frozen shape)
export interface ManifestRecord {
  kernel: KernelId;                 // K1 | K2 | K3 | K4 | K5
  kernelVersion: number;
  wgslSha256: string;               // SHA-256 of the module bytes, CRLF -> LF
  adapter: AdapterInfo;             // vendor, architecture, device, description, features, limits
  dispatch: { workgroups: number[]; workgroupSize: number[] };
  outputBytes: number;
  outputSha256: string;             // SHA-256 of the raw readback bytes
  status: { count: number; flags: number };
  durationMs: number;
  timestampISO: string;
  userAgent: string;
  compileErrors: string[];
  outcome: "pass" | "fail" | "exception" | "skip";
}

// Canonical manifest JSON: UTF-8, keys sorted, arrays sorted by kernel then
// adapterKey (vendor|architecture|device|description), no insignificant
// whitespace; manifestSha256 = SHA-256(serialized manifest) is included in the
// artifact and re-derived by the gate.

Readback is byte-exact by construction: copyBufferToBuffer, then mapAsync in read mode, then copy to a fresh Uint8Array and unmap, and hash the raw bytes rather than a typed-array numeric view, because a Uint32Array view would make the hash depend on host endianness. The sentinel and canary rules close the silent-no-run hole: every input buffer is pre-filled with 0xDEADBEEF, every output begins with a count word, the harness rejects a kernel whose output equals the sentinel or whose count differs from the pinned expected count, createShaderModule is followed by a compilation-info check that must report zero errors, validation and out-of-memory error scopes are pushed, and onSubmittedWorkDone is awaited. A mismatch that matches a pre-declared entry of exceptions.json becomes an exception with the adapter identity, kernel, observed and expected hash, reason, and an evidence URL; anything else is a fail. A compile or limit failure is a skip with the reason recorded, and if every GPU skips, the demonstration is empty and the paper must say so.

The pass rule for K1 to K4 is exact: every non-skipped record passes if and only if outputSha256 equals the pinned expected hash for that kernel, the status count equals the pinned expected count, and compileErrors is empty. K5, the float negative control, has no pass criterion at all. Its per-adapter hash is recorded, a second dispatch gives a run-to-run measurement, and the run is classified as divergent, run-to-run only, or agreeing. If every adapter agrees, that is recorded as an observation about that hardware set and this one time, with no generalization to floating point. The gate checks none of this, because it has no GPU, and no K5 record is committed to this repository: a reader who runs the lab is the first to observe it, which is why the abstract and the claim ceiling describe K5 as a control rather than as a demonstration.

6. Experiments and known-answer tests

The experiments here are deterministic and CPU-only. They establish the reference side of the claim: that the shipped TypeScript references reproduce the pinned hashes and counts, that the integer implementations match external known-answer tests, that the WGSL source bytes are pinned, and that the integer kernels stay inside the declared subset. The cross-adapter side is not an experiment in this paper; it is the browser lab of section 8, and the only honest statement about it is that a local manifest is a small, time-stamped, self-reported sample. The gate runs in about one second on the authoring machine, and every number in T3, T4, and T5 is re-derived on each run with no auto-update path.

T3. Known-answer tests as the gate runs them
TestVectorExpectedOracle
Philox KAT 1ctr 00000000 00000000 00000000 00000000; key 00000000 000000006627e8d5 e169c58d bc57ac4c 9b00dbd8Random123 kat_vectors
Philox KAT 2ctr ffffffff ffffffff ffffffff ffffffff; key ffffffff ffffffff408f276d 41c83b0e a20bc7c6 6d5451fdRandom123 kat_vectors
Philox KAT 3ctr 243f6a88 85a308d3 13198a2e 03707344; key a4093822 299f31d0d16cfe09 94fdcceb 5001e420 24126ea1Random123 kat_vectors
SHA-256 KAT, empty message"" (0 bytes)e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855FIPS 180-4
SHA-256 KAT, abc"abc" (3 bytes)ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015adFIPS 180-4
K4 oracle digest1 MiB LCG message, seed 0x2545F49179bfb41c6346bc10d842265e62eb4e35ce77ac3bc2d3c21ebe068d808acc1361Node/Web Crypto SHA-256 oracle, pinned in tests/reprogpu.test.ts

The Philox lines are the published Random123 kat_vectors values, word-compared in order (c0, c1, c2, c3). The SHA-256 lines are FIPS 180-4 vectors. The K4 digest is the SHA-256 of the exact 1 MiB LCG message; it is pinned from an independent Node/Web Crypto oracle in the test suite (tests/reprogpu.test.ts), while the permanent gate recomputes the shipped reference and compares it to the frozen digest. The frozen artifact carries these two FIPS vectors; the longer NIST 448-bit and 896-bit vectors named in the amended spec were not added to the shipped test list.

T4. Permanent gate criteria (scripts/verify-reprogpu.ts)
#CriterionStatusDetail as printed
1References reproduce pinsPASSK1/K1-flag/K2/K3/K4 all match
2Known-answer testsPASS3 Philox KATs + FIPS SHA-256 + K4 oracle match
3WGSL source pinsPASSall five sources match the pins
4Integer kernel purityPASSno float/atomics/discard; shifts masked; canaries present
5SummaryPASSall criteria passed

The gate is pure deterministic TypeScript on the CPU. It exits 1 on any failure and prints the final line REPROGPU_GATE {"passed":5,"failed":0,"runtimeMs":1049}. Runtime is wall time on the authoring machine and will vary; the pinned content is the pass/fail result, not the millisecond count.

T5. Pinned reference outputs: counts, sizes, and hashes
KernelPinned countOutput bytesReference output SHA-256
K14,10448c046384ed6580b8111b8ef34f5d0932289209f4920666477bc76ffe724dfa27a
K1-flag4,10648cc7dca6d69fec7162cf610b0170076aec74d3d5bec47b2ea80d0b74afb3c9ecb
K265,5361,048,580f9004cf3ed50db5cdb6351a3eb090a498586ade2e3f7499744c951bf77f86d01
K365,536262,160fbe13a3b4e2fc7bf3a4b38c838912651151c03460bd9d1d7f1ea81190af3932e
K416,38536eea119f4059566875ceaf784400d519fd8ff2148d9f221e0004fd04944a21797

These are the values in docs/research/reprogpu/expected-hashes.json, re-derived byte-for-byte by the gate. Output bytes is the length of the byte serialization that is hashed. K1-flag has no separate count pin in the artifact; its count is 4,104 plus the two appended non-finite words, and only its hash is pinned. The WGSL source pins are listed in section 9.

F1. Kernel output size (log10 of bytes hashed)Output buffer sizes span five orders of magnitude, so the bars are log10 of the byte length and the transform is labelled here. K1 is 48 bytes (12 u32), K2 is 1,048,580 bytes (the count word plus 65,536 Philox blocks of four u32), K3 is 262,160 bytes (65,536 i32 plus a four-word status), K4 is 36 bytes (the block count plus eight digest words), and K5 is 262,144 bytes (65,536 f32). Size is an implementation property, not a measure of importance: the hardest pin to reproduce is the 36-byte K4 digest.log10(output bytes)02.34.771.6816.0215.4191.5565.419K1K2K3K4K5
F1. Kernel output size (log10 of bytes hashed). Output buffer sizes span five orders of magnitude, so the bars are log10 of the byte length and the transform is labelled here. K1 is 48 bytes (12 u32), K2 is 1,048,580 bytes (the count word plus 65,536 Philox blocks of four u32), K3 is 262,160 bytes (65,536 i32 plus a four-word status), K4 is 36 bytes (the block count plus eight digest words), and K5 is 262,144 bytes (65,536 f32). Size is an implementation property, not a measure of importance: the hardest pin to reproduce is the 36-byte K4 digest. log10(output buffer size in bytes).

What the known-answer tests do and do not buy. The three Philox lines and the two FIPS SHA-256 lines are external oracles: they were not produced by this codebase, so agreement is evidence that the integer algorithms are the standard ones rather than that the pins are self-consistent. The K4 message digest is checked against a Node/Web Crypto SHA-256 oracle on the exact 1 MiB LCG message in the test suite. The K1 reference is an exact BigInt reconstruction; the K3 reference is compared against a naive O(n^3) BigInt implementation on small seeded sizes in the test suite. The pins themselves are regression anchors: the same reference computes both the expected constant and the observed value, so a pin can only catch drift, and correctness rests on the external oracles and on the exactness argument, not on the pin.

7. Failure cases & limitations

The limitations below are the amended spec's, quoted verbatim. Each names a real envelope of the shipped system or of the experiment, not a caveat added after the fact.

  1. The guarantee covers only K1–K4 and only the shapes/domains declared above; float is out of scope (WGSL CRD 2026-09-15 §15.7.2/§15.7.4/§15.7.5).
  2. The gate verifies the references, KATs, pins, and source integrity; it cannot execute WGSL or test cross-adapter equality. The browser lab is the demonstration, not the CI gate.
  3. Cross-adapter results are a small, time-stamped sample on one machine; adapter.info is self-reported and not cryptographically attested; engine support is limited and may change.
  4. K1 excludes non-finite inputs (flagged and rejected); K3 documents mod-2^32 wrap on out-of-range output, which is a design ceiling rather than something the shipped seeded vector exercises; none of K1–K4 covers general float.
  5. Any adapter mismatch is a fail unless it is a pre-declared, reproducible exceptions.json driver bug; exceptions are reported, not hidden.
  6. K5 divergence is permitted and K5 agreement is possible; neither outcome is recorded in this artifact, and K5 agreement on any hardware set is not evidence of general float reproducibility.

8. Product: the /reprogpu lab

The product is a single browser page at /reprogpu. It requests a WebGPU adapter, renders an adapter card with the self-reported vendor, architecture, device, and description, and lets the reader run the five kernels. For K1 to K4 the page shows the pinned expected hash next to the live output hash and the status count next to the expected count, so a reader sees pass or fail directly rather than a summary. For K5 the page shows the per-adapter hash and the second-dispatch comparison, classified as divergent, run-to-run only, or agreeing, with copy that says agreement is an observation and not a reproducibility claim. The run produces the full manifest of section 5, which the reader can copy or download; the page re-derives manifestSha256 so a third party can compare it against the committed artifact. The run is local: inputs never leave the device and only output hashes are publishable.

  • Ships: the adapter card, the per-kernel expected-versus-observed hash table with counts, the K5 negative-control panel, and a copy/download manifest action with a re-derivable manifestSha256.
  • Ships: an always-visible statement of the declared boundary and of what the gate cannot do, placed next to the run control rather than hidden in a footnote.
  • Ships: a link to the committed expected-hashes.json and to the pinned WGSL source hashes, so a reader can compare a downloaded manifest without trusting the page.
  • Cut: any claim that a matching hash proves the adapter or the driver is correct; any claim that adapter info is an attestation; any extension of the integer result to float; any server call, storage, account, or telemetry.

9. Reproducibility

Everything reported here is offline, deterministic, and dependency-free. The evidence script and the gate are pure TypeScript and use no clocks, no randomness, no network, and no GPU. The evidence script computes the reference outputs, hashes their byte serializations and the WGSL sources, and writes docs/research/reprogpu/expected-hashes.json; it never writes expected.ts, so there is no auto-update path. The gate recomputes every value and compares against the committed constants; drift fails the gate until the constant and this paper are changed together in one reviewed commit. Scratch paths are not recorded and no absolute path enters the artifact.

Reproducing the reported results
# evidence: reference outputs, KATs, WGSL source hashes;
# writes docs/research/reprogpu/expected-hashes.json
bun run scripts/reprogpu-evidence.ts

# permanent gate: 5 criteria, pinned hashes, KATs, source pins, purity scan
bun run verify:reprogpu

# paper and reference checks
bun test tests/reprogpu*.test.ts

The pinned WGSL source hashes are the values the gate compares after normalizing CRLF to LF and stripping any byte-order mark. They are the same for every adapter in a run, and they change whenever a kernel source changes, which is the point: a kernel edit must be accompanied by a deliberate pin update. The five pins, in K1 to K5 order, are:

  • K1: ea7c46670ea2a3258b7522db6a8b09af1f2e7895021870a32669ca7ec9b2df3f
  • K2: 010e4d4db8cc43cf95f9d4329da09d5bd3a4d3d764c20d63490df81c6c0d4dbe
  • K3: 1013c964ff0a25721558503d391bd6630e96f848973c7198668dfcd14988132d
  • K4: d9d8db073c560de60fead78f846afbb4feec2b2626d2d74c072ed6a1c6b23489
  • K5: 3f003ca3d1bba17b2052b5cba08a42211eba3fae742177ad52d9f109541e3cbe

No result in this paper depends on a cited URL resolving to the same content it held on 2026-09-19. The WGSL section numbers, the Random123 vectors, and the FIPS vectors are quoted with their sources; if any cited specification section or URL changes, the corresponding kernel, vector, or claim must be re-checked and the pins re-frozen before the paper is treated as current. The evidence script's runtime was 1.08 seconds in the recorded run, with the 256^3 BigInt K3 reference taking 833 milliseconds of it; these are machine-local timings and are not part of any pin.

10. Future work

The subset is deliberately small, and each of the following extensions keeps the same discipline of declaring the boundary first and pinning the evidence. None of them changes the claim of section 1.

  • WASI and WebGPU compute reuse: run the same integer kernels under a WASI runtime backed by WebGPU so a non-browser host can reproduce a browser result without a second implementation.
  • More kernels inside the declared subset: integer sorting by deterministic sample and bucket passes, exact integer dot products over binned lanes, and additional counter-RNG streams such as Threefry-2x32 against their published vectors.
  • A cross-language harness: one manifest schema implemented in TypeScript, Rust, and Python so three independent hosts emit the same canonical JSON and the same manifestSha256.
  • An attestation envelope in the DEVSIG direction: bind a kernel source hash, an adapter identity, and an output hash into one offline-checkable artifact, while keeping adapter identity clearly distinct from a cryptographically attested driver.
  • A wider adapter sample and a committed exceptions register: record reproducible, pre-declared driver divergences with evidence so that a future mismatch is classified rather than silently broadened.
  • A formal statement of the accumulator bounds for shapes larger than the fixed ones, so a new shape is admitted only with a re-derived proof rather than by scaling the existing constants.

References

  1. [1]Demmel & Nguyen 2020, Parallel reproducible summation, ACM TOMS 46(3). https://doi.org/10.1145/3389360
  2. [2]Iakymchuk, Collange, Defour & Graillat 2015, Numerical reproducibility for the parallel reduction, NRE / Parallel Computing 49. https://doi.org/10.1016/j.parco.2015.09.001
  3. [3]Ozaki et al. 2024, Error-free transformations for reproducible GEMM on tensor cores, IJHPCA. https://dl.acm.org/doi/abs/10.1177/10943420241239588
  4. [4]Ozaki-II: round-correct reproducible matrix multiplication (arXiv 2504.08009). https://arxiv.org/abs/2504.08009
  5. [5]NVIDIA CCCL 3.1, Controlling floating-point determinism with a reproducible accumulator (2026-03-05). https://developer.nvidia.com/blog/controlling-floating-point-determinism-in-nvidia-cccl/
  6. [6]NVIDIA framework-reproducibility issue #28, bit-exactness across GPU architectures. https://github.com/NVIDIA/framework-reproducibility/issues/28
  7. [7]RepDL: bitwise-reproducible deep-learning training and inference (arXiv 2510.09180). https://arxiv.org/abs/2510.09180
  8. [8]Hawkeye: reverse-engineering Tensor-Core numerics for bit-exact replay (arXiv 2603.20421). https://arxiv.org/abs/2603.20421
  9. [9]Deterministic Atomic Buffering, MICRO 2020. https://microarch.org/micro53/papers/738300a981.pdf
  10. [10]Jooybar et al. 2013, GPUDet: a deterministic GPU architecture, ASPLOS. https://people.ece.ubc.ca/aamodt/publications/papers/jooybar.asplos2013.pdf
  11. [11]Intel oneMKL developer guide, obtaining numerically reproducible results (CNR). https://www.intel.com/content/www/us/en/docs/onemkl/developer-guide-linux/2023-1/obtaining-numerically-reproducible-results.html
  12. [12]Salmon, Moraes, Dror & Shaw, Random123 / Philox counter-based RNG. https://github.com/DEShawResearch/random123
  13. [13]PyTorch torch.use_deterministic_algorithms documentation. https://docs.pytorch.org/docs/stable/generated/torch.use_deterministic_algorithms.html
  14. [14]TensorFlow tf.config.experimental.enable_op_determinism documentation. https://www.tensorflow.org/api_docs/python/tf/config/experimental/enable_op_determinism
  15. [15]zkML: zero-knowledge proofs of machine-learning inference, EuroSys 2024. https://dl.acm.org/doi/10.1145/3627703.3650088
  16. [16]Survey of verifiable machine learning (arXiv 2502.18535). https://arxiv.org/abs/2502.18535
  17. [17]Ivanov et al. 2023, SAGE: software-based attestation for GPU execution, USENIX ATC. https://www.usenix.org/system/files/atc23-ivanov.pdf
  18. [18]WebGPU conformance test suite, floating-point primer. https://chromium.googlesource.com/external/github.com/gpuweb/cts/+/07f15b8e1e73c5cc52d94ab9916a59c04f9c95ec/docs/fp_primer.md
  19. [19]W3C WebGPU Shading Language, Candidate Recommendation Draft 2026-09-15. https://www.w3.org/TR/2026/CRD-WGSL-20260915/
  20. [20]WGSL CRD 2026-09-15, section 15.7 floating-point evaluation. https://www.w3.org/TR/2026/CRD-WGSL-20260915/#floating-point-evaluation
  21. [21]WgPy: a NumPy-like GPU array library for the browser (arXiv 2503.00279). https://arxiv.org/abs/2503.00279
  22. [22]RustyBamboo/hash-shader, SHA-256 WebGPU compute shader. https://github.com/RustyBamboo/hash-shader
  23. [23]aaravkohli1/BitExact, deterministic CUDA kernels. https://github.com/aaravkohli1/BitExact
  24. [24]11vated/PAradigm cross-vendor GPU determinism brief. https://github.com/11vated/PAradigm-reference/blob/main/research/001-gpu-determinism-cross-vendor.md

Cite this paper

DeepForge Research (2026). REPROGPU: Cross-Adapter Bit-Reproducible WebGPU Kernels and a Conformance Harness for a Declared Integer Subset. DeepForge. https://deepforge.srivtx.xyz/inventions/reprogpu