Quazim0t0 commited on
Commit
465d605
·
verified ·
1 Parent(s): 75f9477

Upload web/test_gates.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. web/test_gates.js +24 -2
web/test_gates.js CHANGED
@@ -32,7 +32,9 @@ function inputs(d) {
32
  return { Xq, Wq, rs, cs };
33
  }
34
 
35
- // exact gate: int32 accumulator with !==, then f32 epilogue with !==
 
 
36
  function gateExact(kernel, shapes) {
37
  for (const d of shapes) {
38
  const { Xq, Wq, rs, cs } = inputs(d);
@@ -41,7 +43,7 @@ function gateExact(kernel, shapes) {
41
  for (let i = 0; i < accRef.length; i++) if (accHw[i] !== accRef[i]) return `acc @${i}`;
42
  const hw = kernel(Xq, Wq, rs, cs, d, L);
43
  const ref = V.bgemmJS(Xq, Wq, rs, cs, d, L);
44
- for (let i = 0; i < ref.length; i++) if (hw[i] !== ref[i]) return `epilogue @${i}`;
45
  }
46
  return null;
47
  }
@@ -113,6 +115,26 @@ ok(oldMissedRounding && newCatchesRounding,
113
  const oldMissedStride = gateOld(mutant("batchStride")) === null;
114
  console.log(` note batchStride under the old gate: ${oldMissedStride ? "MISSED" : "caught (batch>1 was in the shape)"}`);
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  console.log(pass ? "\nGATE TEST PASSED — the gate rejects real bugs and accepts the real kernel."
117
  : "\nGATE TEST FAILED");
118
  process.exit(pass ? 0 : 1);
 
32
  return { Xq, Wq, rs, cs };
33
  }
34
 
35
+ // exact gate: int32 accumulator with !==, then f32 epilogue compared AT THE
36
+ // BIT LEVEL (V.bitDiff) — `!==` can't see -0 vs +0, and the fleet's replica
37
+ // checks hash raw bytes, so the gate must compare what the hash sees.
38
  function gateExact(kernel, shapes) {
39
  for (const d of shapes) {
40
  const { Xq, Wq, rs, cs } = inputs(d);
 
43
  for (let i = 0; i < accRef.length; i++) if (accHw[i] !== accRef[i]) return `acc @${i}`;
44
  const hw = kernel(Xq, Wq, rs, cs, d, L);
45
  const ref = V.bgemmJS(Xq, Wq, rs, cs, d, L);
46
+ for (let i = 0; i < ref.length; i++) if (V.bitDiff(hw[i], ref[i])) return `epilogue @${i}`;
47
  }
48
  return null;
49
  }
 
115
  const oldMissedStride = gateOld(mutant("batchStride")) === null;
116
  console.log(` note batchStride under the old gate: ${oldMissedStride ? "MISSED" : "caught (batch>1 was in the shape)"}`);
117
 
118
+ // ---- the sign of zero -------------------------------------------------------
119
+ // Real ISAs have non-IEEE modes that flush -0 to +0 (RDNA2 output modifiers /
120
+ // DX9-legacy multiplies). JS `!==` treats -0 === 0, so a value-level gate is
121
+ // BLIND to that flush — yet the sync guard hashes raw bits, so it would fork
122
+ // the fleet. The audit must therefore compare bit patterns.
123
+ console.log("\nthe audit must see the sign of zero (`!==` cannot):");
124
+ {
125
+ const d = { m: 2, k: 4, n: 2 };
126
+ const Xq = new Int8Array(d.m * d.k); // all zero -> acc = 0 -> epi = +0
127
+ const Wq = rnd(d.k * d.n, () => (Math.random() * 256 - 128) | 0);
128
+ const rs = Float32Array.from({ length: d.m }, () => Math.random() + 0.5);
129
+ const cs = Float32Array.from({ length: d.n }, () => Math.random() + 0.5);
130
+ const got = V.bgemmJS(Xq, Wq, rs, cs, { ...d, batch: 1 }, L);
131
+ ok(got.every((v) => !V.bitDiff(v, 0)), "sanity: the units produce +0 here");
132
+ got[1] = -0; // what a -0-flushing device's INVERSE would look like; either direction diverges the hash
133
+ ok(got.every((v) => v === 0), "sanity: `!==` cannot tell the corrupted output apart");
134
+ const bad = V.auditTile(Xq, Wq, rs, cs, d, got, L, 400); // 400 samples over 4 cells: hits the bad cell w.p. 1-(3/4)^400
135
+ ok(bad !== null, `auditTile flags the -0 (${bad || "NOT CAUGHT"})`);
136
+ }
137
+
138
  console.log(pass ? "\nGATE TEST PASSED — the gate rejects real bugs and accepts the real kernel."
139
  : "\nGATE TEST FAILED");
140
  process.exit(pass ? 0 : 1);