Upload web/public/webgpu.js with huggingface_hub
Browse files- web/public/webgpu.js +11 -28
web/public/webgpu.js
CHANGED
|
@@ -560,34 +560,17 @@
|
|
| 560 |
const mlpDp4Bad = (await gateMlp(mlpDp4)) || (await gateMlpDirty(mlpDp4));
|
| 561 |
if (mlpDp4Bad) { console.warn("B2B MLP chain (DP4A) failed verification — using the LUT chain:", mlpDp4Bad); mlpDp4 = mlpLut; }
|
| 562 |
|
| 563 |
-
// Both backends are exact-gated bit-identical, so
|
| 564 |
-
// free choice
|
| 565 |
-
//
|
| 566 |
-
//
|
| 567 |
-
//
|
| 568 |
-
//
|
| 569 |
-
//
|
| 570 |
-
//
|
| 571 |
-
//
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
try {
|
| 575 |
-
const d0 = { m: 256, k: 32, n: 32, batch: 3, relu: false };
|
| 576 |
-
const rnd8 = (len) => { const a = new Int8Array(len); for (let i = 0; i < len; i++) a[i] = (Math.random() * 256 - 128) | 0; return a; };
|
| 577 |
-
const Xq = rnd8(d0.batch * d0.m * d0.k), Wq = rnd8(d0.batch * d0.k * d0.n);
|
| 578 |
-
const rs = Float32Array.from({ length: d0.batch * d0.m }, () => Math.random() + 0.5);
|
| 579 |
-
const cs = Float32Array.from({ length: d0.batch * d0.n }, () => Math.random() + 0.5);
|
| 580 |
-
const time = async (fn) => {
|
| 581 |
-
await fn(Xq, Wq, rs, cs, d0); await fn(Xq, Wq, rs, cs, d0); // warm
|
| 582 |
-
const t0 = performance.now();
|
| 583 |
-
for (let r = 0; r < 6; r++) await fn(Xq, Wq, rs, cs, d0); // serialized, like training
|
| 584 |
-
return performance.now() - t0;
|
| 585 |
-
};
|
| 586 |
-
const tLut = await time(bgLut), tDp4 = await time(bg);
|
| 587 |
-
const winner = tDp4 <= tLut ? dp4 : viaLUT;
|
| 588 |
-
winner.label += ` · won init race ${Math.min(tLut, tDp4).toFixed(0)}ms vs ${Math.max(tLut, tDp4).toFixed(0)}ms`;
|
| 589 |
-
return winner;
|
| 590 |
-
} catch (e) { return dp4; }
|
| 591 |
} catch (e) { console.warn("WebGPU init failed, CPU fallback:", e); return cpu; }
|
| 592 |
}
|
| 593 |
|
|
|
|
| 560 |
const mlpDp4Bad = (await gateMlp(mlpDp4)) || (await gateMlpDirty(mlpDp4));
|
| 561 |
if (mlpDp4Bad) { console.warn("B2B MLP chain (DP4A) failed verification — using the LUT chain:", mlpDp4Bad); mlpDp4 = mlpLut; }
|
| 562 |
|
| 563 |
+
// Both backends are exact-gated bit-identical, so which one runs is a
|
| 564 |
+
// free choice — and an init race that timed them was tried and REMOVED.
|
| 565 |
+
// Measured on this NVIDIA part they tie on the shipped float path (DP4A's
|
| 566 |
+
// JS packing cancels its dot-throughput win at these sizes), so the race
|
| 567 |
+
// bought nothing, cost ~40 ms of init, and made the backend vary between
|
| 568 |
+
// page loads — which silently invalidated three separate A/B benchmarks
|
| 569 |
+
// before it was noticed. A knob that changes what you are measuring is
|
| 570 |
+
// worse than a fixed choice. DP4A ships: it wins the int8-backward mode
|
| 571 |
+
// by ~12% and ties elsewhere.
|
| 572 |
+
return { backend: "webgpu", label: `${gpuName} (DP4A int8 dot · exact-gated vs units)`,
|
| 573 |
+
bgemm: bg, att, fgemm, fgemm2, mlp: mlpDp4 };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 574 |
} catch (e) { console.warn("WebGPU init failed, CPU fallback:", e); return cpu; }
|
| 575 |
}
|
| 576 |
|