Upload web/public/webgpu.js with huggingface_hub
Browse files- 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 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|