Upload web/public/webgpu.js with huggingface_hub
Browse files- web/public/webgpu.js +42 -1
web/public/webgpu.js
CHANGED
|
@@ -940,6 +940,43 @@
|
|
| 940 |
const cs = Float32Array.from({ length: batch * n }, () => 1);
|
| 941 |
return { Xq, Wq, rs, cs, d: { ...PROBE, acc: true } };
|
| 942 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 943 |
async function kernelProbe(compute, L) {
|
| 944 |
const { Xq, Wq, rs, cs, d } = probeInputs();
|
| 945 |
const out = compute && compute.bgemm
|
|
@@ -948,8 +985,12 @@
|
|
| 948 |
let h = 0x811c9dc5; // FNV-1a over the exact int32 results
|
| 949 |
const b = new Uint8Array(out.buffer, out.byteOffset, out.byteLength);
|
| 950 |
for (let i = 0; i < b.length; i++) { h ^= b[i]; h = Math.imul(h, 0x01000193); }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 951 |
return h >>> 0;
|
| 952 |
}
|
| 953 |
|
| 954 |
-
root.Compute = { initCompute, loadLUTs, kernelProbe };
|
| 955 |
})(self);
|
|
|
|
| 940 |
const cs = Float32Array.from({ length: batch * n }, () => 1);
|
| 941 |
return { Xq, Wq, rs, cs, d: { ...PROBE, acc: true } };
|
| 942 |
}
|
| 943 |
+
// ---- transcendental probe ---------------------------------------------------
|
| 944 |
+
// The kernel probe covers int8 GEMM arithmetic. It does NOT cover the JS
|
| 945 |
+
// transcendentals, and ECMA-262 does not require Math.exp/log/cos/sin to be
|
| 946 |
+
// correctly rounded — it calls them "implementation-approximated", so V8,
|
| 947 |
+
// SpiderMonkey and JSC are all permitted to return different bits.
|
| 948 |
+
//
|
| 949 |
+
// One use of them can fork a fleet: weight INIT. Peers build their own
|
| 950 |
+
// starting weights from a shared seed rather than broadcasting them
|
| 951 |
+
// (Box-Muller, so Math.log/cos/sin), and one ulp of engine disagreement
|
| 952 |
+
// means peers begin from different models. The per-step uses (softmax, loss)
|
| 953 |
+
// cannot fork anything — every peer averages the same received gradient
|
| 954 |
+
// BYTES, so a differently-rounded local gradient is still a gradient the
|
| 955 |
+
// whole group then agrees on.
|
| 956 |
+
//
|
| 957 |
+
// This hashes the exact f64 bits of those four functions over a fixed grid,
|
| 958 |
+
// so a browser whose math library differs is IDENTIFIED instead of showing
|
| 959 |
+
// up later as an unexplained weight-hash mismatch. Cost: microseconds, once.
|
| 960 |
+
// Detection, not correction — pinning the algorithms would be a fleet-wide
|
| 961 |
+
// numerics change, and is only worth doing if this ever reports a mismatch.
|
| 962 |
+
function mathProbe() {
|
| 963 |
+
const buf = new ArrayBuffer(8), dv = new DataView(buf);
|
| 964 |
+
let h = 0x811c9dc5;
|
| 965 |
+
const eat = (x) => {
|
| 966 |
+
dv.setFloat64(0, x);
|
| 967 |
+
for (let i = 0; i < 8; i++) { h ^= dv.getUint8(i); h = Math.imul(h, 0x01000193); }
|
| 968 |
+
};
|
| 969 |
+
for (let i = 1; i <= 400; i++) {
|
| 970 |
+
const u = i / 401; // (0,1): the Box-Muller domain
|
| 971 |
+
eat(Math.log(u));
|
| 972 |
+
eat(Math.cos(2 * Math.PI * u));
|
| 973 |
+
eat(Math.sin(2 * Math.PI * u));
|
| 974 |
+
eat(Math.sqrt(-2 * Math.log(u))); // the exact composite randn uses
|
| 975 |
+
eat(Math.exp(-u * 12)); // the softmax domain
|
| 976 |
+
}
|
| 977 |
+
return h >>> 0;
|
| 978 |
+
}
|
| 979 |
+
|
| 980 |
async function kernelProbe(compute, L) {
|
| 981 |
const { Xq, Wq, rs, cs, d } = probeInputs();
|
| 982 |
const out = compute && compute.bgemm
|
|
|
|
| 985 |
let h = 0x811c9dc5; // FNV-1a over the exact int32 results
|
| 986 |
const b = new Uint8Array(out.buffer, out.byteOffset, out.byteLength);
|
| 987 |
for (let i = 0; i < b.length; i++) { h ^= b[i]; h = Math.imul(h, 0x01000193); }
|
| 988 |
+
// fold in the transcendental hash: same question ("is your arithmetic the
|
| 989 |
+
// same as mine?"), same broadcast slot, no wire-format change
|
| 990 |
+
const mh = mathProbe();
|
| 991 |
+
for (let i = 0; i < 4; i++) { h ^= (mh >>> (i * 8)) & 0xFF; h = Math.imul(h, 0x01000193); }
|
| 992 |
return h >>> 0;
|
| 993 |
}
|
| 994 |
|
| 995 |
+
root.Compute = { initCompute, loadLUTs, kernelProbe, mathProbe };
|
| 996 |
})(self);
|