Quazim0t0 commited on
Commit
be30a1a
·
verified ·
1 Parent(s): b90d951

Upload web/public/webgpu.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. web/public/webgpu.js +16 -6
web/public/webgpu.js CHANGED
@@ -271,6 +271,16 @@
271
  return out;
272
  }
273
 
 
 
 
 
 
 
 
 
 
 
274
  async function initCompute(L) {
275
  const cpu = { backend: "cpu", label: "CPU (JS)",
276
  matmulInt8: (Xq, Wq, m, k, n, LL) => root.Verified.lutMatmulJS(Xq, Wq, m, k, n, LL) };
@@ -342,8 +352,8 @@
342
  for (let i = 0; i < refAccC.length; i++) if (accC[i] !== refAccC[i]) throw new Error(`ctx accumulator mismatch @${i} shape ${JSON.stringify(d0)}`);
343
  const refS = root.Verified.attScoresJS(qq, kq, qs, ks, d0, L);
344
  const refC = root.Verified.attCtxJS(aq, vq, as, vs, d0, L);
345
- for (let i = 0; i < refS.length; i++) if (hwS[i] !== refS[i]) throw new Error(`scores epilogue mismatch @${i}`);
346
- for (let i = 0; i < refC.length; i++) if (hwC[i] !== refC[i]) throw new Error(`ctx epilogue mismatch @${i}`);
347
  }
348
  } catch (e) {
349
  console.warn("fused attention kernels failed verification — using CPU LUT mirrors:", e.message);
@@ -389,7 +399,7 @@
389
  const hw = await bgFn(Xq, Wq, rs, cs, d0);
390
  const ref = root.Verified.bgemmJS(Xq, Wq, rs, cs, d0, L);
391
  for (let i = 0; i < ref.length; i++)
392
- if (hw[i] !== ref[i]) return `epilogue mismatch @${i} (${shape}): ${hw[i]} vs ${ref[i]}`;
393
  }
394
  return null;
395
  }
@@ -412,9 +422,9 @@
412
  const ref = await root.Verified.vmlpBlock(Xf, W1, W2, d0, L, null, null);
413
  const shape = `${d0.m}x${d0.k}x${d0.h}x${d0.n}`;
414
  for (let i = 0; i < ref.h1.length; i++)
415
- if (hw.h1[i] !== ref.h1[i]) return `h1 mismatch @${i} (${shape}): ${hw.h1[i]} vs ${ref.h1[i]}`;
416
  for (let i = 0; i < ref.out.length; i++)
417
- if (hw.out[i] !== ref.out[i]) return `out mismatch @${i} (${shape}): ${hw.out[i]} vs ${ref.out[i]}`;
418
  }
419
  // DISCRIMINATING case: the sweep above passes vacuously if no value
420
  // lands on a rounding boundary — the old round(x/scale) spec would
@@ -439,7 +449,7 @@
439
  const refNew = V.bgemmJS(qNew, w2.q, sc.scale, w2.s, { m: d1.m, k: d1.h, n: d1.n, batch: 1 }, L);
440
  const refOld = V.bgemmJS(qOld, w2.q, sc.scale, w2.s, { m: d1.m, k: d1.h, n: d1.n, batch: 1 }, L);
441
  let eqNew = true, eqOld = true;
442
- for (let i = 0; i < refNew.length; i++) { if (gpu.out[i] !== refNew[i]) eqNew = false; if (gpu.out[i] !== refOld[i]) eqOld = false; }
443
  if (!eqNew) return "discriminating boundary case: GPU chain does not match the respec mirror";
444
  if (eqOld) return "discriminating boundary case: GPU chain matches the OLD quantize spec";
445
  return null; // proven: respec, not merely gate-compatible
 
271
  return out;
272
  }
273
 
274
+ // f32 gate equality AT THE BIT LEVEL. JS `!==` says -0 === 0, but the fleet
275
+ // compares devices by hashing raw bit patterns (FNV over the byte buffer), so
276
+ // a kernel that flushes -0 to +0 — real hardware has instructions that do
277
+ // exactly this (RDNA2 output modifiers and DX9-legacy multiplies are
278
+ // documented as "not IEEE compatible: -0 is flushed to +0") — would pass a
279
+ // `!==` gate and still fork the weights at the sync guard. The gates must
280
+ // compare the same thing the hash sees: the bits.
281
+ const _fb = new Float32Array(1), _ub = new Uint32Array(_fb.buffer);
282
+ function bitDiff(a, b) { _fb[0] = a; const u = _ub[0]; _fb[0] = b; return u !== _ub[0]; }
283
+
284
  async function initCompute(L) {
285
  const cpu = { backend: "cpu", label: "CPU (JS)",
286
  matmulInt8: (Xq, Wq, m, k, n, LL) => root.Verified.lutMatmulJS(Xq, Wq, m, k, n, LL) };
 
352
  for (let i = 0; i < refAccC.length; i++) if (accC[i] !== refAccC[i]) throw new Error(`ctx accumulator mismatch @${i} shape ${JSON.stringify(d0)}`);
353
  const refS = root.Verified.attScoresJS(qq, kq, qs, ks, d0, L);
354
  const refC = root.Verified.attCtxJS(aq, vq, as, vs, d0, L);
355
+ for (let i = 0; i < refS.length; i++) if (bitDiff(hwS[i], refS[i])) throw new Error(`scores epilogue mismatch @${i}`);
356
+ for (let i = 0; i < refC.length; i++) if (bitDiff(hwC[i], refC[i])) throw new Error(`ctx epilogue mismatch @${i}`);
357
  }
358
  } catch (e) {
359
  console.warn("fused attention kernels failed verification — using CPU LUT mirrors:", e.message);
 
399
  const hw = await bgFn(Xq, Wq, rs, cs, d0);
400
  const ref = root.Verified.bgemmJS(Xq, Wq, rs, cs, d0, L);
401
  for (let i = 0; i < ref.length; i++)
402
+ if (bitDiff(hw[i], ref[i])) return `epilogue mismatch @${i} (${shape}): ${hw[i]} vs ${ref[i]}`;
403
  }
404
  return null;
405
  }
 
422
  const ref = await root.Verified.vmlpBlock(Xf, W1, W2, d0, L, null, null);
423
  const shape = `${d0.m}x${d0.k}x${d0.h}x${d0.n}`;
424
  for (let i = 0; i < ref.h1.length; i++)
425
+ if (bitDiff(hw.h1[i], ref.h1[i])) return `h1 mismatch @${i} (${shape}): ${hw.h1[i]} vs ${ref.h1[i]}`;
426
  for (let i = 0; i < ref.out.length; i++)
427
+ if (bitDiff(hw.out[i], ref.out[i])) return `out mismatch @${i} (${shape}): ${hw.out[i]} vs ${ref.out[i]}`;
428
  }
429
  // DISCRIMINATING case: the sweep above passes vacuously if no value
430
  // lands on a rounding boundary — the old round(x/scale) spec would
 
449
  const refNew = V.bgemmJS(qNew, w2.q, sc.scale, w2.s, { m: d1.m, k: d1.h, n: d1.n, batch: 1 }, L);
450
  const refOld = V.bgemmJS(qOld, w2.q, sc.scale, w2.s, { m: d1.m, k: d1.h, n: d1.n, batch: 1 }, L);
451
  let eqNew = true, eqOld = true;
452
+ for (let i = 0; i < refNew.length; i++) { if (bitDiff(gpu.out[i], refNew[i])) eqNew = false; if (bitDiff(gpu.out[i], refOld[i])) eqOld = false; }
453
  if (!eqNew) return "discriminating boundary case: GPU chain does not match the respec mirror";
454
  if (eqOld) return "discriminating boundary case: GPU chain matches the OLD quantize spec";
455
  return null; // proven: respec, not merely gate-compatible