Quazim0t0 commited on
Commit
867cc7f
·
verified ·
1 Parent(s): 617ba47

Upload web/public/webgpu.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. web/public/webgpu.js +21 -4
web/public/webgpu.js CHANGED
@@ -364,14 +364,31 @@
364
  const fPipes = { gemm: mkPipe(WGSL_FGEMM), reduce: mkPipe(WGSL_FREDUCE) };
365
  let fgemm = (A, Bm, d) => gpuFgemm(device, fPipes, A, Bm, d);
366
  let fgemm2 = (A, B1, d1, B2, d2) => gpuFgemm2(device, fPipes, A, B1, d1, B2, d2);
 
367
  try {
368
  const m0 = 7, k0 = 4500, n0 = 5; // k big enough to exercise split-K
369
  const A = Float32Array.from({ length: m0 * k0 }, () => Math.random() - 0.5);
370
  const Bm = Float32Array.from({ length: k0 * n0 }, () => Math.random() - 0.5);
371
- const hw = await fgemm(A, Bm, { m: m0, k: k0, n: n0 });
372
- const ref = root.TrainCore.matmul(A, Bm, m0, k0, n0);
373
- for (let i = 0; i < ref.length; i++)
374
- if (Math.abs(hw[i] - ref[i]) > Math.abs(ref[i]) * 1e-3 + 1e-3) throw new Error("fgemm mismatch");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
  // The shared-operand pair must equal the two calls it replaces, EXACTLY:
376
  // same buffer, same shader, same arithmetic, so bit-level equality is
377
  // the honest bar (not a tolerance). Both index patterns of A are
 
364
  const fPipes = { gemm: mkPipe(WGSL_FGEMM), reduce: mkPipe(WGSL_FREDUCE) };
365
  let fgemm = (A, Bm, d) => gpuFgemm(device, fPipes, A, Bm, d);
366
  let fgemm2 = (A, B1, d1, B2, d2) => gpuFgemm2(device, fPipes, A, B1, d1, B2, d2);
367
+ let fgemmFma = false; // set by the gate below
368
  try {
369
  const m0 = 7, k0 = 4500, n0 = 5; // k big enough to exercise split-K
370
  const A = Float32Array.from({ length: m0 * k0 }, () => Math.random() - 0.5);
371
  const Bm = Float32Array.from({ length: k0 * n0 }, () => Math.random() - 0.5);
372
+ // EXACT gate, replacing an allclose. The mirror reproduces split-K's
373
+ // partition and accumulation order, so bit-equality is achievable and
374
+ // is the honest bar. WGSL may contract `s + a*b` into an FMA, so try
375
+ // both rounding schedules and record which the device implements
376
+ // if NEITHER matches, the f32 backward is not bit-reproducible here
377
+ // and must not run, because its gradients set the weights the whole
378
+ // fleet is hashed against.
379
+ const dG = { m: m0, k: k0, n: n0 };
380
+ const hw = await fgemm(A, Bm, dG);
381
+ const mStep = root.Verified.fgemmMirror(A, Bm, dG, false);
382
+ const mFma = root.Verified.fgemmMirror(A, Bm, dG, true);
383
+ let okStep = true, okFma = true;
384
+ for (let i = 0; i < hw.length; i++) {
385
+ if (bitDiff(hw[i], mStep[i])) okStep = false;
386
+ if (bitDiff(hw[i], mFma[i])) okFma = false;
387
+ if (!okStep && !okFma) break;
388
+ }
389
+ if (!okStep && !okFma) throw new Error("fgemm matches neither rounding schedule — not bit-reproducible");
390
+ fgemmFma = !okStep; // remember what this device does
391
+ console.info(`split-K f32 GEMM is bit-exact (${okStep ? "two-rounding" : "fused"} multiply-add schedule)`);
392
  // The shared-operand pair must equal the two calls it replaces, EXACTLY:
393
  // same buffer, same shader, same arithmetic, so bit-level equality is
394
  // the honest bar (not a tolerance). Both index patterns of A are