Quazim0t0 commited on
Commit
ca0e49c
·
verified ·
1 Parent(s): 1c53ff6

Upload web/public/webgpu.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. 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 WHICH one runs is a
564
- // free choice. On our NVIDIA part they TIE on the shipped float path
565
- // (packing overhead cancels the dot-throughput win at these sizes) and
566
- // DP4A is ~12% faster in int8-backward mode but the ordering is
567
- // device-dependent in principle (a driver with slow dot4I8Packed or a
568
- // fast cache path for the LUT flips it). The race below costs ~40ms at
569
- // init and self-calibrates per device instead of trusting one machine's
570
- // benchmark. First run of a fresh build is warm-up-skewed; the race
571
- // warms both before timing.
572
- const dp4 = { backend: "webgpu", label: `${gpuName} (DP4A int8 dot · exact-gated vs units)`,
573
- bgemm: bg, att, fgemm, fgemm2, mlp: mlpDp4 };
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