ngocdang83 commited on
Commit
031b7e1
·
verified ·
1 Parent(s): d99779e

moxhi be57a8a

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. assets/addln_embed-CzGikpaS.js +2 -0
  2. assets/addln_embed-CzGikpaS.js.map +1 -0
  3. assets/adreno_probe-CjpGrE_r.js +393 -0
  4. assets/adreno_probe-CjpGrE_r.js.map +1 -0
  5. assets/argmax-CNtdxM2K.js +2 -0
  6. assets/argmax-CNtdxM2K.js.map +1 -0
  7. assets/argmax_fuse-DcdFediE.js +2 -0
  8. assets/argmax_fuse-DcdFediE.js.map +1 -0
  9. assets/attention-CPOKnefi.js +64 -0
  10. assets/attention-CPOKnefi.js.map +1 -0
  11. assets/attn_sweep-C5U-KhDy.js +2 -0
  12. assets/attn_sweep-C5U-KhDy.js.map +1 -0
  13. assets/autotune-Cy4x-YB7.js +2 -0
  14. assets/autotune-Cy4x-YB7.js.map +1 -0
  15. assets/baseline-D00dppjV.js +2 -0
  16. assets/baseline-D00dppjV.js.map +1 -0
  17. assets/batch_cap_ab-DpomwYzZ.js +2 -0
  18. assets/batch_cap_ab-DpomwYzZ.js.map +1 -0
  19. assets/bench-BkXidq5p.js +29 -0
  20. assets/bench-BkXidq5p.js.map +1 -0
  21. assets/bench-C8ITpm5I.js +5 -0
  22. assets/bench-C8ITpm5I.js.map +1 -0
  23. assets/compact_equiv-BsjFDsn-.js +2 -0
  24. assets/compact_equiv-BsjFDsn-.js.map +1 -0
  25. assets/debug-Cn7EHWtJ.js +8 -0
  26. assets/debug-Cn7EHWtJ.js.map +1 -0
  27. assets/dims_generic-BTPBo91W.js +2 -0
  28. assets/dims_generic-BTPBo91W.js.map +1 -0
  29. assets/enc_pack-BEo0Mc8b.js +2 -0
  30. assets/enc_pack-BEo0Mc8b.js.map +1 -0
  31. assets/enc_profile-Cn8Ppz7u.js +2 -0
  32. assets/enc_profile-Cn8Ppz7u.js.map +1 -0
  33. assets/enc_v3_sweep-C1_eeFjm.js +2 -0
  34. assets/enc_v3_sweep-C1_eeFjm.js.map +1 -0
  35. assets/engine-BTyy_WlH.js +4 -0
  36. assets/engine-BTyy_WlH.js.map +0 -0
  37. assets/ffn_mt_sweep-bWrzWJ6f.js +2 -0
  38. assets/ffn_mt_sweep-bWrzWJ6f.js.map +1 -0
  39. assets/ffn_q8_sweep-CGfESiUo.js +2 -0
  40. assets/ffn_q8_sweep-CGfESiUo.js.map +1 -0
  41. assets/ffn_splitk-B1WT9pJ7.js +2 -0
  42. assets/ffn_splitk-B1WT9pJ7.js.map +1 -0
  43. assets/fuse_ln-DCGuPhdx.js +2 -0
  44. assets/fuse_ln-DCGuPhdx.js.map +1 -0
  45. assets/gemm-CQmO2bw5.js +2 -0
  46. assets/gemm-CQmO2bw5.js.map +1 -0
  47. assets/generate-C4ruG1zm.js +2 -0
  48. assets/generate-C4ruG1zm.js.map +1 -0
  49. assets/hachimi60-D0JkA1E4.js +2 -0
  50. assets/hachimi60-D0JkA1E4.js.map +1 -0
assets/addln_embed-CzGikpaS.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as w}from"./debug-Cn7EHWtJ.js";import{c as C,r as $,a as ee}from"./gpu-utils-BTh3AGTJ.js";import{g as L,a as te,e as ne}from"./pipelines-DD24nEJg.js";import{a as re,e as ae}from"./math-DNG-wiC0.js";import{e as M,f as se}from"./f16-wKKZr58e.js";import{L as oe,D as x,c as F,E as R}from"./constants-C8VbFpic.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";function N(n){let e=n>>>0;return()=>{e=e+1831565813|0;let t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296}}function S(n,e,t=1){const s=new Float32Array(n);for(let a=0;a<n;a++)s[a]=Math.fround((e()-.5)*t);return s}function fe(n){const e=new Uint16Array(n.length);for(let t=0;t<n.length;t++)e[t]=se(n[t]);return{half:e,ref:M(e)}}function U(n,e){if(e!=="f16")return{data:n,ref:n};const{half:t,ref:s}=fe(n);return{data:t,ref:s}}function I(n,e){const t=n.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});return new Uint32Array(t.getMappedRange()).set(e),t.unmap(),t}function K(n,e,t){const s=e*(t==="f16"?2:4);return n.createBuffer({size:Math.ceil(s/4)*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC})}async function Y(n,e,t,s,a,f,r){const m=n.createBindGroup({layout:e.getBindGroupLayout(0),entries:t.map((g,D)=>({binding:D,resource:{buffer:g}}))}),c=n.createCommandEncoder(),o=c.beginComputePass();o.setPipeline(e),o.setBindGroup(0,m),o.dispatchWorkgroups(s),o.end(),n.queue.submit([c.finish()]);const d=await $(n,a,f*(r==="f16"?2:4));return r==="f16"?M(new Uint16Array(d)):new Float32Array(d)}function z(n,e,t,s){const{failures:a,maxAbsDiff:f,worst:r}=ee(n,e,t);return{pass:a===0,detail:{...s,tol:t,failures:a,maxAbsDiff:String(f),...a>0?{worst:r,got:String(n[r]),want:String(e[r])}:{}}}}async function q(n,{rows:e,t,tol:s,seed:a}){const{device:f}=n,r=x,m=N(a),c=U(S(e*r,m,4),t),o=U(S(e*r,m,4),t),d=U(S(r,m,4),t),g=U(S(r,m,4),t),D=re(c.ref,o.ref,d.ref,g.ref,{rows:e,d:r}),b=L(f,"add_ln",te,{t,wg:256,defines:{D:r,EPS:oe}}),l=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,A=I(f,[e,0,0,0]),B=[c.data,o.data,d.data,g.data].map(_=>C(f,_,l)),P=K(f,e*r,t),y=await Y(f,b,[A,...B,P],e,P,e*r,t);for(const _ of[A,...B,P])_.destroy();return z(y,D,s,{kernel:"add_ln",rows:e,d:r,t})}async function h(n,{t:e,tol:t,seed:s,vocab:a,maxPos:f,enc:r=null,dec:m=null}){const{device:c}=n,o=x,d=N(s),g=U(S(a*o,d),e),D=U(S(f*o,d),e);let b,l,A,B,P,y;if(r){const{B:u,S:i}=r,E=u*i;b=new Uint32Array(E);for(let p=0;p<E;p++)b[p]=Math.floor(d()*a);l=Array.from(b),A=l.map((p,Z)=>Z%i),B=[E,0,u,i],P={D:o,EMBED_SCALE:R,SRC_IDS:!0,DECODE:!1,PACKED:!1,NOPACKED:!0},y={kernel:"embed",mode:"encoder",B:u,S:i,vocab:a,t:e}}else{const{batch:u,step:i,ring:E}=m;b=E,l=[];for(let p=0;p<u;p++)l.push(i===0?F:E[(i-1)*u+p]);A=l.map(()=>i),B=[u,i,u,0],P={D:o,EMBED_SCALE:R,SRC_IDS:!1,DECODE:!0,DECODER_START:F,PACKED:!1,NOPACKED:!0},y={kernel:"embed",mode:"decode",batch:u,step:i,vocab:a,t:e}}const _=B[0],j=ae(l,A,g.ref,D.ref,{d:o,scale:R}),v=L(c,"embed",ne,{t:e,wg:224,defines:P}),O=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,H=I(c,B),J=C(c,b,O),Q=C(c,g.data,O),V=C(c,D.data,O),T=K(c,_*o,e),k=[H,J,Q,V,T],X=await Y(c,v,k,_,T,_*o,e);for(const u of k)u.destroy();return z(X,j,t,y)}function W(n,e,t,s,a){const f=new Uint32Array(n*e).fill(a);return t>0&&f.set(s,(t-1)*e),f}function G(n,e){w(n,t=>t.hasF16?e(t):{skip:!0,reason:"no shader-f16"})}G("addln_f16",n=>q(n,{rows:5,t:"f16",tol:.02,seed:201}));w("addln_f32",n=>q(n,{rows:3,t:"f32",tol:1e-4,seed:202}));G("embed_enc_f16",n=>h(n,{t:"f16",tol:.01,seed:203,vocab:100,maxPos:16,enc:{B:2,S:16}}));G("embed_dec_t0_f16",n=>h(n,{t:"f16",tol:.01,seed:204,vocab:100,maxPos:8,dec:{batch:3,step:0,ring:W(8,3,0,[],55)}}));G("embed_dec_t5_f16",n=>h(n,{t:"f16",tol:.01,seed:205,vocab:100,maxPos:8,dec:{batch:3,step:5,ring:W(8,3,5,[7,42,99],55)}}));w("embed_enc_f32",n=>h(n,{t:"f32",tol:1e-5,seed:206,vocab:100,maxPos:16,enc:{B:1,S:16}}));
2
+ //# sourceMappingURL=addln_embed-CzGikpaS.js.map
assets/addln_embed-CzGikpaS.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"addln_embed-CzGikpaS.js","sources":["../../src/debug/tests/addln_embed.js"],"sourcesContent":["// GPU add+LayerNorm and embedding kernels vs the JS f64 references.\n// f16 test data is encoded to f16 and decoded back to f32 for the reference\n// input, so ref and GPU see IDENTICAL values (pattern from gemm.js).\n// Per-call uniform/bind-group creation is test-only plumbing — engine-level\n// uniform management arrives in Tasks 13-14.\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback, compareLanes } from '../gpu-utils.js';\nimport { getPipeline } from '../../engine/pipelines.js';\nimport { addLayerNormRef, embedRef } from '../../reference/math.js';\nimport { f32ToF16, expandF16 } from '../../engine/f16.js';\nimport { D_MODEL, LN_EPS, EMBED_SCALE, DECODER_START } from '../../engine/constants.js';\nimport addLnSource from '../../engine/kernels/add_layernorm.wgsl?raw';\nimport embedSource from '../../engine/kernels/embed.wgsl?raw';\n\nfunction mulberry32(seed) {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n// Random f32 in ±scale/2.\nfunction randF32(n, rng, scale = 1) {\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) out[i] = Math.fround((rng() - 0.5) * scale);\n return out;\n}\n\n// Encode to f16 for the GPU and decode back to f32 for the reference.\nfunction toF16(f32arr) {\n const half = new Uint16Array(f32arr.length);\n for (let i = 0; i < f32arr.length; i++) half[i] = f32ToF16(f32arr[i]);\n return { half, ref: expandF16(half) };\n}\n\n// {data, ref} pair for a given storage type.\nfunction prep(f32arr, t) {\n if (t !== 'f16') return { data: f32arr, ref: f32arr };\n const { half, ref } = toF16(f32arr);\n return { data: half, ref };\n}\n\nfunction makeUniform(device, vals) {\n const buf = device.createBuffer({\n size: 16,\n usage: GPUBufferUsage.UNIFORM,\n mappedAtCreation: true,\n });\n new Uint32Array(buf.getMappedRange()).set(vals);\n buf.unmap();\n return buf;\n}\n\nfunction makeOutBuffer(device, elems, t) {\n const bytes = elems * (t === 'f16' ? 2 : 4);\n return device.createBuffer({\n size: Math.ceil(bytes / 4) * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n}\n\n// Run one compute dispatch (nWorkgroups in x) and read back the result.\nasync function runAndRead(device, pipeline, buffers, nWorkgroups, outBuf, outElems, t) {\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: buffers.map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(nWorkgroups);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const raw = await readback(device, outBuf, outElems * (t === 'f16' ? 2 : 4));\n return t === 'f16' ? expandF16(new Uint16Array(raw)) : new Float32Array(raw);\n}\n\nfunction report(got, want, tol, extra) {\n const { failures, maxAbsDiff, worst } = compareLanes(got, want, tol);\n return {\n pass: failures === 0,\n detail: {\n ...extra, tol, failures,\n maxAbsDiff: String(maxAbsDiff), // string: JSON turns NaN/Infinity into null\n ...(failures > 0 ? { worst, got: String(got[worst]), want: String(want[worst]) } : {}),\n },\n };\n}\n\n// ---------------------------------------------------------------- add_ln ---\n\nasync function runAddLnCase(ctx, { rows, t, tol, seed }) {\n const { device } = ctx;\n const d = D_MODEL;\n const rng = mulberry32(seed);\n // ±2 activations to exercise the variance path.\n const x = prep(randF32(rows * d, rng, 4), t);\n const r = prep(randF32(rows * d, rng, 4), t);\n const gamma = prep(randF32(d, rng, 4), t);\n const beta = prep(randF32(d, rng, 4), t);\n const want = addLayerNormRef(x.ref, r.ref, gamma.ref, beta.ref, { rows, d });\n\n const pipeline = getPipeline(device, 'add_ln', addLnSource, {\n t, wg: 256, defines: { D: d, EPS: LN_EPS },\n });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const params = makeUniform(device, [rows, 0, 0, 0]);\n const bufs = [x.data, r.data, gamma.data, beta.data].map((a) => createBuffer(device, a, usage));\n const yBuf = makeOutBuffer(device, rows * d, t);\n const got = await runAndRead(device, pipeline, [params, ...bufs, yBuf], rows, yBuf, rows * d, t);\n for (const b of [params, ...bufs, yBuf]) b.destroy();\n return report(got, want, tol, { kernel: 'add_ln', rows, d, t });\n}\n\n// ----------------------------------------------------------------- embed ---\n\n// mode: {SRC_IDS: true} with {B, S} or {DECODE: true} with {batch, t, ring, tMax}.\nasync function runEmbedCase(ctx, { t, tol, seed, vocab, maxPos, enc = null, dec = null }) {\n const { device } = ctx;\n const d = D_MODEL;\n const rng = mulberry32(seed);\n const table = prep(randF32(vocab * d, rng), t);\n const posT = prep(randF32(maxPos * d, rng), t);\n\n let idsU32, refIds, refPositions, params, defines, label;\n if (enc) {\n const { B, S } = enc;\n const rows = B * S;\n idsU32 = new Uint32Array(rows);\n for (let i = 0; i < rows; i++) idsU32[i] = Math.floor(rng() * vocab);\n refIds = Array.from(idsU32);\n refPositions = refIds.map((_, i) => i % S);\n params = [rows, 0, B, S];\n defines = { D: d, EMBED_SCALE, SRC_IDS: true, DECODE: false, PACKED: false, NOPACKED: true };\n label = { kernel: 'embed', mode: 'encoder', B, S, vocab, t };\n } else {\n const { batch, step, ring } = dec; // ring: Uint32Array [tMax*batch]\n idsU32 = ring;\n refIds = [];\n for (let b = 0; b < batch; b++) {\n refIds.push(step === 0 ? DECODER_START : ring[(step - 1) * batch + b]);\n }\n refPositions = refIds.map(() => step);\n params = [batch, step, batch, 0];\n defines = { D: d, EMBED_SCALE, SRC_IDS: false, DECODE: true, DECODER_START, PACKED: false, NOPACKED: true };\n label = { kernel: 'embed', mode: 'decode', batch, step, vocab, t };\n }\n const rows = params[0];\n const want = embedRef(refIds, refPositions, table.ref, posT.ref, { d, scale: EMBED_SCALE });\n\n const pipeline = getPipeline(device, 'embed', embedSource, { t, wg: 224, defines });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const paramsBuf = makeUniform(device, params);\n const idsBuf = createBuffer(device, idsU32, usage);\n const tableBuf = createBuffer(device, table.data, usage);\n const posBuf = createBuffer(device, posT.data, usage);\n const yBuf = makeOutBuffer(device, rows * d, t);\n const all = [paramsBuf, idsBuf, tableBuf, posBuf, yBuf];\n const got = await runAndRead(device, pipeline, all, rows, yBuf, rows * d, t);\n for (const b of all) b.destroy();\n return report(got, want, tol, label);\n}\n\n// Decode token ring [tMax*batch]: sentinel-filled so a wrong ring index (or a\n// t=0 read of the ring at all) lands on a different embedding row and fails.\nfunction makeRing(tMax, batch, step, ids, sentinel) {\n const ring = new Uint32Array(tMax * batch).fill(sentinel);\n if (step > 0) ring.set(ids, (step - 1) * batch);\n return ring;\n}\n\nfunction registerF16(name, fn) {\n registerTest(name, (ctx) =>\n ctx.hasF16 ? fn(ctx) : { skip: true, reason: 'no shader-f16' });\n}\n\n// f16 tol 0.02 for LN: dividing by σ can grow relative error; embed is a\n// scaled gather (one multiply-add per lane), 0.01 covers f16 output rounding\n// at |y| ≲ 11 (table ±0.5 · √448).\nregisterF16('addln_f16', (ctx) => runAddLnCase(ctx, { rows: 5, t: 'f16', tol: 0.02, seed: 201 }));\nregisterTest('addln_f32', (ctx) => runAddLnCase(ctx, { rows: 3, t: 'f32', tol: 1e-4, seed: 202 }));\n\nregisterF16('embed_enc_f16', (ctx) =>\n runEmbedCase(ctx, { t: 'f16', tol: 0.01, seed: 203, vocab: 100, maxPos: 16, enc: { B: 2, S: 16 } }));\nregisterF16('embed_dec_t0_f16', (ctx) =>\n runEmbedCase(ctx, {\n t: 'f16', tol: 0.01, seed: 204, vocab: 100, maxPos: 8,\n dec: { batch: 3, step: 0, ring: makeRing(8, 3, 0, [], 55) },\n }));\nregisterF16('embed_dec_t5_f16', (ctx) =>\n runEmbedCase(ctx, {\n t: 'f16', tol: 0.01, seed: 205, vocab: 100, maxPos: 8,\n dec: { batch: 3, step: 5, ring: makeRing(8, 3, 5, [7, 42, 99], 55) },\n }));\n// f32 fallback-mode sanity for the embed template.\nregisterTest('embed_enc_f32', (ctx) =>\n runEmbedCase(ctx, { t: 'f32', tol: 1e-5, seed: 206, vocab: 100, maxPos: 16, enc: { B: 1, S: 16 } }));\n"],"names":["mulberry32","seed","a","randF32","rng","scale","out","i","toF16","f32arr","half","f32ToF16","expandF16","prep","t","ref","makeUniform","device","vals","buf","makeOutBuffer","elems","bytes","runAndRead","pipeline","buffers","nWorkgroups","outBuf","outElems","bindGroup","buffer","binding","encoder","pass","raw","readback","report","got","want","tol","extra","failures","maxAbsDiff","worst","compareLanes","runAddLnCase","ctx","rows","d","D_MODEL","x","r","gamma","beta","addLayerNormRef","getPipeline","addLnSource","LN_EPS","usage","params","bufs","createBuffer","yBuf","b","runEmbedCase","vocab","maxPos","enc","dec","table","posT","idsU32","refIds","refPositions","defines","label","B","S","_","EMBED_SCALE","batch","step","ring","DECODER_START","embedRef","embedSource","paramsBuf","idsBuf","tableBuf","posBuf","all","makeRing","tMax","ids","sentinel","registerF16","name","fn","registerTest"],"mappings":"iZAcA,SAASA,EAAWC,EAAM,CACxB,IAAIC,EAAID,IAAS,EACjB,MAAO,IAAM,CACXC,EAAKA,EAAI,WAAc,EACvB,IAAI,EAAI,KAAK,KAAKA,EAAKA,IAAM,GAAK,EAAIA,CAAC,EACvC,SAAK,EAAI,KAAK,KAAK,EAAK,IAAM,EAAI,GAAK,CAAC,EAAK,IACpC,EAAK,IAAM,MAAS,GAAK,UACpC,CACF,CAGA,SAASC,EAAQ,EAAGC,EAAKC,EAAQ,EAAG,CAClC,MAAMC,EAAM,IAAI,aAAa,CAAC,EAC9B,QAASC,EAAI,EAAGA,EAAI,EAAGA,IAAKD,EAAIC,CAAC,EAAI,KAAK,QAAQH,EAAG,EAAK,IAAOC,CAAK,EACtE,OAAOC,CACT,CAGA,SAASE,GAAMC,EAAQ,CACrB,MAAMC,EAAO,IAAI,YAAYD,EAAO,MAAM,EAC1C,QAASF,EAAI,EAAGA,EAAIE,EAAO,OAAQF,IAAKG,EAAKH,CAAC,EAAII,GAASF,EAAOF,CAAC,CAAC,EACpE,MAAO,CAAE,KAAAG,EAAM,IAAKE,EAAUF,CAAI,CAAC,CACrC,CAGA,SAASG,EAAKJ,EAAQK,EAAG,CACvB,GAAIA,IAAM,MAAO,MAAO,CAAE,KAAML,EAAQ,IAAKA,CAAM,EACnD,KAAM,CAAE,KAAAC,EAAM,IAAAK,GAAQP,GAAMC,CAAM,EAClC,MAAO,CAAE,KAAMC,EAAM,IAAAK,CAAG,CAC1B,CAEA,SAASC,EAAYC,EAAQC,EAAM,CACjC,MAAMC,EAAMF,EAAO,aAAa,CAC9B,KAAM,GACN,MAAO,eAAe,QACtB,iBAAkB,EACtB,CAAG,EACD,WAAI,YAAYE,EAAI,eAAc,CAAE,EAAE,IAAID,CAAI,EAC9CC,EAAI,MAAK,EACFA,CACT,CAEA,SAASC,EAAcH,EAAQI,EAAO,EAAG,CACvC,MAAMC,EAAQD,GAAS,IAAM,MAAQ,EAAI,GACzC,OAAOJ,EAAO,aAAa,CACzB,KAAM,KAAK,KAAKK,EAAQ,CAAC,EAAI,EAC7B,MAAO,eAAe,QAAU,eAAe,QACnD,CAAG,CACH,CAGA,eAAeC,EAAWN,EAAQO,EAAUC,EAASC,EAAaC,EAAQC,EAAUd,EAAG,CACrF,MAAMe,EAAYZ,EAAO,gBAAgB,CACvC,OAAQO,EAAS,mBAAmB,CAAC,EACrC,QAASC,EAAQ,IAAI,CAACK,EAAQC,KAAa,CAAE,QAAAA,EAAS,SAAU,CAAE,OAAAD,CAAM,CAAE,EAAG,CACjF,CAAG,EACKE,EAAUf,EAAO,qBAAoB,EACrCgB,EAAOD,EAAQ,iBAAgB,EACrCC,EAAK,YAAYT,CAAQ,EACzBS,EAAK,aAAa,EAAGJ,CAAS,EAC9BI,EAAK,mBAAmBP,CAAW,EACnCO,EAAK,IAAG,EACRhB,EAAO,MAAM,OAAO,CAACe,EAAQ,OAAM,CAAE,CAAC,EACtC,MAAME,EAAM,MAAMC,EAASlB,EAAQU,EAAQC,GAAYd,IAAM,MAAQ,EAAI,EAAE,EAC3E,OAAOA,IAAM,MAAQF,EAAU,IAAI,YAAYsB,CAAG,CAAC,EAAI,IAAI,aAAaA,CAAG,CAC7E,CAEA,SAASE,EAAOC,EAAKC,EAAMC,EAAKC,EAAO,CACrC,KAAM,CAAE,SAAAC,EAAU,WAAAC,EAAY,MAAAC,CAAK,EAAKC,GAAaP,EAAKC,EAAMC,CAAG,EACnE,MAAO,CACL,KAAME,IAAa,EACnB,OAAQ,CACN,GAAGD,EAAO,IAAAD,EAAK,SAAAE,EACf,WAAY,OAAOC,CAAU,EAC7B,GAAID,EAAW,EAAI,CAAE,MAAAE,EAAO,IAAK,OAAON,EAAIM,CAAK,CAAC,EAAG,KAAM,OAAOL,EAAKK,CAAK,CAAC,CAAC,EAAK,EACzF,CACA,CACA,CAIA,eAAeE,EAAaC,EAAK,CAAE,KAAAC,EAAM,EAAG,IAAAR,EAAK,KAAAtC,GAAQ,CACvD,KAAM,CAAE,OAAAgB,CAAM,EAAK6B,EACbE,EAAIC,EACJ7C,EAAMJ,EAAWC,CAAI,EAErBiD,EAAIrC,EAAKV,EAAQ4C,EAAOC,EAAG5C,EAAK,CAAC,EAAG,CAAC,EACrC+C,EAAItC,EAAKV,EAAQ4C,EAAOC,EAAG5C,EAAK,CAAC,EAAG,CAAC,EACrCgD,EAAQvC,EAAKV,EAAQ6C,EAAG5C,EAAK,CAAC,EAAG,CAAC,EAClCiD,EAAOxC,EAAKV,EAAQ6C,EAAG5C,EAAK,CAAC,EAAG,CAAC,EACjCkC,EAAOgB,GAAgBJ,EAAE,IAAKC,EAAE,IAAKC,EAAM,IAAKC,EAAK,IAAK,CAAE,KAAAN,EAAM,EAAAC,CAAC,CAAE,EAErExB,EAAW+B,EAAYtC,EAAQ,SAAUuC,GAAa,CAC1D,EAAG,GAAI,IAAK,QAAS,CAAE,EAAGR,EAAG,IAAKS,EAAM,CAC5C,CAAG,EACKC,EAAQ,eAAe,QAAU,eAAe,SAChDC,EAAS3C,EAAYC,EAAQ,CAAC8B,EAAM,EAAG,EAAG,CAAC,CAAC,EAC5Ca,EAAO,CAACV,EAAE,KAAMC,EAAE,KAAMC,EAAM,KAAMC,EAAK,IAAI,EAAE,IAAKnD,GAAM2D,EAAa5C,EAAQf,EAAGwD,CAAK,CAAC,EACxFI,EAAO1C,EAAcH,EAAQ8B,EAAOC,EAAG,CAAC,EACxCX,EAAM,MAAMd,EAAWN,EAAQO,EAAU,CAACmC,EAAQ,GAAGC,EAAME,CAAI,EAAGf,EAAMe,EAAMf,EAAOC,EAAG,CAAC,EAC/F,UAAWe,IAAK,CAACJ,EAAQ,GAAGC,EAAME,CAAI,EAAGC,EAAE,QAAO,EAClD,OAAO3B,EAAOC,EAAKC,EAAMC,EAAK,CAAE,OAAQ,SAAU,KAAAQ,EAAM,EAAAC,EAAG,EAAG,CAChE,CAKA,eAAegB,EAAalB,EAAK,CAAE,EAAAhC,EAAG,IAAAyB,EAAK,KAAAtC,EAAM,MAAAgE,EAAO,OAAAC,EAAQ,IAAAC,EAAM,KAAM,IAAAC,EAAM,IAAI,EAAI,CACxF,KAAM,CAAE,OAAAnD,CAAM,EAAK6B,EACbE,EAAIC,EACJ7C,EAAMJ,EAAWC,CAAI,EACrBoE,EAAQxD,EAAKV,EAAQ8D,EAAQjB,EAAG5C,CAAG,EAAGU,CAAC,EACvCwD,EAAOzD,EAAKV,EAAQ+D,EAASlB,EAAG5C,CAAG,EAAGU,CAAC,EAE7C,IAAIyD,EAAQC,EAAQC,EAAcd,EAAQe,EAASC,EACnD,GAAIR,EAAK,CACP,KAAM,CAAE,EAAAS,EAAG,EAAAC,CAAC,EAAKV,EACXpB,EAAO6B,EAAIC,EACjBN,EAAS,IAAI,YAAYxB,CAAI,EAC7B,QAASxC,EAAI,EAAGA,EAAIwC,EAAMxC,IAAKgE,EAAOhE,CAAC,EAAI,KAAK,MAAMH,EAAG,EAAK6D,CAAK,EACnEO,EAAS,MAAM,KAAKD,CAAM,EAC1BE,EAAeD,EAAO,IAAI,CAACM,EAAGvE,IAAMA,EAAIsE,CAAC,EACzClB,EAAS,CAACZ,EAAM,EAAG6B,EAAGC,CAAC,EACvBH,EAAU,CAAE,EAAG1B,EAAG,YAAA+B,EAAa,QAAS,GAAM,OAAQ,GAAO,OAAQ,GAAO,SAAU,EAAI,EAC1FJ,EAAQ,CAAE,OAAQ,QAAS,KAAM,UAAW,EAAAC,EAAG,EAAAC,EAAG,MAAAZ,EAAO,EAAAnD,CAAC,CAC5D,KAAO,CACL,KAAM,CAAE,MAAAkE,EAAO,KAAAC,EAAM,KAAAC,CAAI,EAAKd,EAC9BG,EAASW,EACTV,EAAS,CAAA,EACT,QAAST,EAAI,EAAGA,EAAIiB,EAAOjB,IACzBS,EAAO,KAAKS,IAAS,EAAIE,EAAgBD,GAAMD,EAAO,GAAKD,EAAQjB,CAAC,CAAC,EAEvEU,EAAeD,EAAO,IAAI,IAAMS,CAAI,EACpCtB,EAAS,CAACqB,EAAOC,EAAMD,EAAO,CAAC,EAC/BN,EAAU,CAAE,EAAG1B,EAAG,YAAA+B,EAAa,QAAS,GAAO,OAAQ,GAAM,cAAAI,EAAe,OAAQ,GAAO,SAAU,EAAI,EACzGR,EAAQ,CAAE,OAAQ,QAAS,KAAM,SAAU,MAAAK,EAAO,KAAAC,EAAM,MAAAhB,EAAO,EAAAnD,CAAC,CAClE,CACA,MAAMiC,EAAOY,EAAO,CAAC,EACfrB,EAAO8C,GAASZ,EAAQC,EAAcJ,EAAM,IAAKC,EAAK,IAAK,CAAE,EAAAtB,EAAG,MAAO+B,CAAW,CAAE,EAEpFvD,EAAW+B,EAAYtC,EAAQ,QAASoE,GAAa,CAAE,EAAAvE,EAAG,GAAI,IAAK,QAAA4D,EAAS,EAC5EhB,EAAQ,eAAe,QAAU,eAAe,SAChD4B,EAAYtE,EAAYC,EAAQ0C,CAAM,EACtC4B,EAAS1B,EAAa5C,EAAQsD,EAAQb,CAAK,EAC3C8B,EAAW3B,EAAa5C,EAAQoD,EAAM,KAAMX,CAAK,EACjD+B,EAAS5B,EAAa5C,EAAQqD,EAAK,KAAMZ,CAAK,EAC9CI,EAAO1C,EAAcH,EAAQ8B,EAAOC,EAAGlC,CAAC,EACxC4E,EAAM,CAACJ,EAAWC,EAAQC,EAAUC,EAAQ3B,CAAI,EAChDzB,EAAM,MAAMd,EAAWN,EAAQO,EAAUkE,EAAK3C,EAAMe,EAAMf,EAAOC,EAAGlC,CAAC,EAC3E,UAAWiD,KAAK2B,EAAK3B,EAAE,QAAO,EAC9B,OAAO3B,EAAOC,EAAKC,EAAMC,EAAKoC,CAAK,CACrC,CAIA,SAASgB,EAASC,EAAMZ,EAAOC,EAAMY,EAAKC,EAAU,CAClD,MAAMZ,EAAO,IAAI,YAAYU,EAAOZ,CAAK,EAAE,KAAKc,CAAQ,EACxD,OAAIb,EAAO,GAAGC,EAAK,IAAIW,GAAMZ,EAAO,GAAKD,CAAK,EACvCE,CACT,CAEA,SAASa,EAAYC,EAAMC,EAAI,CAC7BC,EAAaF,EAAOlD,GAClBA,EAAI,OAASmD,EAAGnD,CAAG,EAAI,CAAE,KAAM,GAAM,OAAQ,gBAAiB,CAClE,CAKAiD,EAAY,YAAcjD,GAAQD,EAAaC,EAAK,CAAE,KAAM,EAAG,EAAG,MAAO,IAAK,IAAM,KAAM,GAAG,CAAE,CAAC,EAChGoD,EAAa,YAAcpD,GAAQD,EAAaC,EAAK,CAAE,KAAM,EAAG,EAAG,MAAO,IAAK,KAAM,KAAM,GAAG,CAAE,CAAC,EAEjGiD,EAAY,gBAAkBjD,GAC5BkB,EAAalB,EAAK,CAAE,EAAG,MAAO,IAAK,IAAM,KAAM,IAAK,MAAO,IAAK,OAAQ,GAAI,IAAK,CAAE,EAAG,EAAG,EAAG,EAAE,CAAE,CAAE,CAAC,EACrGiD,EAAY,mBAAqBjD,GAC/BkB,EAAalB,EAAK,CAChB,EAAG,MAAO,IAAK,IAAM,KAAM,IAAK,MAAO,IAAK,OAAQ,EACpD,IAAK,CAAE,MAAO,EAAG,KAAM,EAAG,KAAM6C,EAAS,EAAG,EAAG,EAAG,CAAA,EAAI,EAAE,CAAC,CAC7D,CAAG,CAAC,EACJI,EAAY,mBAAqBjD,GAC/BkB,EAAalB,EAAK,CAChB,EAAG,MAAO,IAAK,IAAM,KAAM,IAAK,MAAO,IAAK,OAAQ,EACpD,IAAK,CAAE,MAAO,EAAG,KAAM,EAAG,KAAM6C,EAAS,EAAG,EAAG,EAAG,CAAC,EAAG,GAAI,EAAE,EAAG,EAAE,CAAC,CACtE,CAAG,CAAC,EAEJO,EAAa,gBAAkBpD,GAC7BkB,EAAalB,EAAK,CAAE,EAAG,MAAO,IAAK,KAAM,KAAM,IAAK,MAAO,IAAK,OAAQ,GAAI,IAAK,CAAE,EAAG,EAAG,EAAG,EAAE,CAAE,CAAE,CAAC"}
assets/adreno_probe-CjpGrE_r.js ADDED
@@ -0,0 +1,393 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/autotune-DBJGFXNj.js","assets/encoder-DX8MOfcH.js","assets/pipelines-DD24nEJg.js","assets/constants-C8VbFpic.js","assets/decoder-DI6VDxxO.js"])))=>i.map(i=>d[i]);
2
+ import{_ as he}from"./preload-helper-BXl3LOEh.js";import{r as S}from"./debug-Cn7EHWtJ.js";import{c as K,r as V}from"./gpu-utils-BTh3AGTJ.js";import{g as ee,a as le,b as Ge,c as ke,d as Be}from"./pipelines-DD24nEJg.js";import{L as J,D as ye}from"./constants-C8VbFpic.js";import{e as fe,f as Se}from"./f16-wKKZr58e.js";import"./modulepreload-polyfill-B5Qt9EMX.js";const re=256,z=4,N=(e,o)=>(Math.imul(e+1,2654435761)^Math.imul(o+1,40503))>>>0&1023,Pe=`
3
+ fn vhash(tid: u32, g: u32) -> f32 {
4
+ return f32((((tid + 1u) * 2654435761u) ^ ((g + 1u) * 40503u)) & 1023u);
5
+ }
6
+ `;async function x(e,o,{wg:r,outPerGroup:t,want:n,tol:i=0,dispatchY:l=1}){const _=e.createShaderModule({code:o}),b=(await _.getCompilationInfo()).messages.filter(A=>A.type==="error");if(b.length)return{pass:!1,detail:{compileErrors:b.map(A=>A.message).slice(0,3)}};const p=e.createComputePipeline({layout:"auto",compute:{module:_,entryPoint:"main"}}),c=re*l,f=c*t,P=e.createBuffer({size:f*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),h=e.createBindGroup({layout:p.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:P}}]});let F=0;const M=new Set;let W=null;const D=[];for(let A=0;A<z;A++){const s=e.createCommandEncoder(),u=s.beginComputePass();u.setPipeline(p),u.setBindGroup(0,h),u.dispatchWorkgroups(re,l),u.end(),e.queue.submit([s.finish()]);const a=new Float32Array(await V(e,P,f*4));let G=0;for(let k=0;k<c;k++)for(let w=0;w<t;w++){const v=n(k,w),d=a[k*t+w];Math.abs(d-v)<=i||(G++,M.add(k),W||(W={rep:A,g:k,lane:w,got:d,want:v}))}D.push(G),F+=G}return P.destroy(),{pass:F===0,detail:{wg:r,groups:c,reps:z,badLanes:F,badGroups:M.size,badPerRep:D,...W?{firstBad:W}:{}}}}const T=e=>`
7
+ @group(0) @binding(0) var<storage, read_write> out: array<f32>;
8
+ const WG: u32 = ${e}u;
9
+ ${Pe}
10
+ `;function ve(e){return`${T(e)}
11
+ var<workgroup> red: array<f32, WG>;
12
+ @compute @workgroup_size(${e})
13
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
14
+ let g = wid.x; let tid = lid.x;
15
+ red[tid] = vhash(tid, g);
16
+ workgroupBarrier();
17
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
18
+ if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }
19
+ workgroupBarrier();
20
+ }
21
+ out[g * WG + tid] = red[0];
22
+ }`}const ne=e=>o=>{let r=-1/0;for(let t=0;t<e;t++)r=Math.max(r,N(t,o));return r},ge=e=>o=>{let r=0;for(let t=0;t<e;t++)r+=N(t,o);return r};S("adreno_probe_tree_bcast_wg64",e=>x(e.device,ve(64),{wg:64,outPerGroup:64,want:ne(64)}));S("adreno_probe_tree_bcast_wg128",e=>x(e.device,ve(128),{wg:128,outPerGroup:128,want:ne(128)}));S("adreno_probe_tree_sum_wg256",e=>{const o=`${T(256)}
23
+ var<workgroup> red: array<f32, WG>;
24
+ @compute @workgroup_size(256)
25
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
26
+ let g = wid.x; let tid = lid.x;
27
+ red[tid] = vhash(tid, g);
28
+ workgroupBarrier();
29
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
30
+ if (tid < s) { red[tid] = red[tid] + red[tid + s]; }
31
+ workgroupBarrier();
32
+ }
33
+ out[g * WG + tid] = red[0];
34
+ }`;return x(e.device,o,{wg:256,outPerGroup:256,want:ge(256)})});S("adreno_probe_tree_single_wg128",e=>{const o=`${T(128)}
35
+ var<workgroup> red: array<f32, WG>;
36
+ @compute @workgroup_size(128)
37
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
38
+ let g = wid.x; let tid = lid.x;
39
+ red[tid] = vhash(tid, g);
40
+ workgroupBarrier();
41
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
42
+ if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }
43
+ workgroupBarrier();
44
+ }
45
+ if (tid == 0u) { out[g] = red[0]; }
46
+ }`;return x(e.device,o,{wg:128,outPerGroup:1,want:ne(128)})});S("adreno_probe_tree_twice_wg128",e=>{const o=`${T(128)}
47
+ var<workgroup> red: array<f32, WG>;
48
+ @compute @workgroup_size(128)
49
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
50
+ let g = wid.x; let tid = lid.x;
51
+ red[tid] = vhash(tid, g);
52
+ workgroupBarrier();
53
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
54
+ if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }
55
+ workgroupBarrier();
56
+ }
57
+ let m = red[0];
58
+ workgroupBarrier(); // red[0] reads done before the sum pass reuses red
59
+ red[tid] = vhash(tid, g) * 0.5 + 1.0;
60
+ workgroupBarrier();
61
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
62
+ if (tid < s) { red[tid] = red[tid] + red[tid + s]; }
63
+ workgroupBarrier();
64
+ }
65
+ out[g * WG + tid] = m + red[0];
66
+ }`,r=t=>{let n=-1/0,i=0;for(let l=0;l<128;l++){const _=N(l,t);n=Math.max(n,_),i+=_*.5+1}return n+i};return x(e.device,o,{wg:128,outPerGroup:128,want:r})});S("adreno_probe_skiploop_wg128",e=>{const o=`${T(128)}
67
+ const LEN: u32 = 16u;
68
+ var<workgroup> scores: array<f32, LEN>;
69
+ var<workgroup> red: array<f32, WG>;
70
+ @compute @workgroup_size(128)
71
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
72
+ let g = wid.x; let tid = lid.x;
73
+ var localMax: f32 = -1e30;
74
+ for (var j = tid; j < LEN; j = j + WG) {
75
+ let sc = vhash(j, g);
76
+ scores[j] = sc;
77
+ localMax = max(localMax, sc);
78
+ }
79
+ red[tid] = localMax;
80
+ workgroupBarrier();
81
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
82
+ if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }
83
+ workgroupBarrier();
84
+ }
85
+ // Consume scores too so the compiler cannot drop it: out = rowMax + scores[tid%LEN].
86
+ out[g * WG + tid] = red[0] + scores[tid % LEN];
87
+ }`,r=(t,n)=>{let i=-1/0;for(let l=0;l<16;l++)i=Math.max(i,N(l,t));return i+N(n%16,t)};return x(e.device,o,{wg:128,outPerGroup:128,want:r})});S("adreno_probe_share_wg128",e=>{const o=`${T(128)}
88
+ var<workgroup> sh: array<f32, WG>;
89
+ @compute @workgroup_size(128)
90
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
91
+ let g = wid.x; let tid = lid.x;
92
+ sh[tid] = vhash(tid, g);
93
+ workgroupBarrier();
94
+ out[g * WG + tid] = sh[(tid + 64u) % WG];
95
+ }`;return x(e.device,o,{wg:128,outPerGroup:128,want:(r,t)=>N((t+64)%128,r)})});S("adreno_probe_uload_wg128",e=>{const o=`${T(128)}
96
+ var<workgroup> red: array<f32, WG>;
97
+ @compute @workgroup_size(128)
98
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
99
+ let g = wid.x; let tid = lid.x;
100
+ red[tid] = vhash(tid, g);
101
+ workgroupBarrier();
102
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
103
+ if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }
104
+ workgroupBarrier();
105
+ }
106
+ out[g * WG + tid] = workgroupUniformLoad(&red[0]);
107
+ }`;return x(e.device,o,{wg:128,outPerGroup:128,want:ne(128)})});S("adreno_probe_sg_wg256",e=>{if(!e.hasSubgroups)return{skip:!0,reason:"subgroups feature unavailable"};const o=`enable subgroups;
108
+ ${T(256)}
109
+ var<workgroup> sgSum: array<f32, WG / 4u>;
110
+ @compute @workgroup_size(256)
111
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>,
112
+ @builtin(subgroup_size) sgSize: u32) {
113
+ let g = wid.x; let tid = lid.x;
114
+ let s1 = subgroupAdd(vhash(tid, g));
115
+ let sgId = tid / sgSize;
116
+ if (subgroupElect()) { sgSum[sgId] = s1; }
117
+ workgroupBarrier();
118
+ let nSg = (WG + sgSize - 1u) / sgSize;
119
+ var total = 0.0;
120
+ for (var i = 0u; i < nSg; i = i + 1u) { total = total + sgSum[i]; }
121
+ out[g * WG + tid] = total;
122
+ }`;return x(e.device,o,{wg:256,outPerGroup:256,want:ge(256)})});const Y=448,me=`
123
+ fn xval(i: u32, g: u32) -> f32 { return (vhash(i, g) - 512.0) / 256.0; }
124
+ fn rval(i: u32, g: u32) -> f32 { return (vhash(i + 7777u, g) - 512.0) / 256.0; }
125
+ fn gval(i: u32) -> f32 { return 1.0 + (vhash(i, 12345u) - 512.0) / 1024.0; }
126
+ fn bval(i: u32) -> f32 { return (vhash(i, 54321u) - 512.0) / 512.0; }
127
+ `,Z=(e,o)=>(N(e,o)-512)/256,te=(e,o)=>(N(e+7777,o)-512)/256,oe=e=>1+(N(e,12345)-512)/1024,ae=e=>(N(e,54321)-512)/512;function ie(e,o){const r=new Map;return(t,n)=>{let i=r.get(t);if(!i){const l=new Float64Array(e);let _=0;for(let c=0;c<e;c++)l[c]=Z(c,t)+te(c,t),_+=l[c];const B=_/e;let b=0;for(let c=0;c<e;c++)b+=(l[c]-B)*(l[c]-B);const p=1/Math.sqrt(b/e+J);i=new Float64Array(e);for(let c=0;c<e;c++)i[c]=o?l[c]-B:oe(c)*(l[c]-B)*p+ae(c);r.set(t,i)}return i[n]}}function _e(e){return`${T(256)}
128
+ const D: u32 = ${Y}u;
129
+ const EPS: f32 = ${J};
130
+ ${me}
131
+ var<workgroup> vbuf: array<f32, D>;
132
+ var<workgroup> scratch: array<f32, WG>;
133
+ @compute @workgroup_size(256)
134
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
135
+ let g = wid.x; let tid = lid.x;
136
+ var sum: f32 = 0.0;
137
+ for (var i = tid; i < D; i = i + WG) {
138
+ let v = xval(i, g) + rval(i, g);
139
+ vbuf[i] = v;
140
+ sum = sum + v;
141
+ }
142
+ scratch[tid] = sum;
143
+ workgroupBarrier();
144
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
145
+ if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }
146
+ workgroupBarrier();
147
+ }
148
+ let mu = scratch[0] / f32(D);
149
+ workgroupBarrier();
150
+ ${e?`
151
+ for (var i = tid; i < D; i = i + WG) { out[g * D + i] = vbuf[i] - mu; }
152
+ `:`
153
+ var sq: f32 = 0.0;
154
+ for (var i = tid; i < D; i = i + WG) {
155
+ let dev = vbuf[i] - mu;
156
+ sq = sq + dev * dev;
157
+ }
158
+ scratch[tid] = sq;
159
+ workgroupBarrier();
160
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
161
+ if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }
162
+ workgroupBarrier();
163
+ }
164
+ let inv = inverseSqrt(scratch[0] / f32(D) + EPS);
165
+ for (var i = tid; i < D; i = i + WG) {
166
+ out[g * D + i] = gval(i) * (vbuf[i] - mu) * inv + bval(i);
167
+ }
168
+ `}
169
+ }`}S("adreno_probe2_addln_gen",e=>x(e.device,_e(!1),{wg:256,outPerGroup:Y,want:ie(Y,!1),tol:.001}));S("adreno_probe2_addln_gen_mu",e=>x(e.device,_e(!0),{wg:256,outPerGroup:Y,want:ie(Y,!0),tol:.001}));async function be(e,o){const{device:r}=e,t=ye,n=re,i=new Float32Array(n*t),l=new Float32Array(n*t),_=new Float32Array(t),B=new Float32Array(t);for(let u=0;u<n;u++)for(let a=0;a<t;a++)i[u*t+a]=Z(a,u),l[u*t+a]=te(a,u);for(let u=0;u<t;u++)_[u]=oe(u),B[u]=ae(u);const b=ie(t,!1),p=ee(r,"add_ln",le,{t:"f32",wg:256,sg:o,defines:{D:t,EPS:J}}),c=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,f=r.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(f.getMappedRange()).set([n,0,0,0]),f.unmap();const P=[i,l,_,B].map(u=>K(r,u,c)),h=r.createBuffer({size:n*t*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),F=r.createBindGroup({layout:p.getBindGroupLayout(0),entries:[f,...P,h].map((u,a)=>({binding:a,resource:{buffer:u}}))}),M=.001;let W=0;const D=new Set;let A=null;const s=[];for(let u=0;u<z;u++){const a=r.createCommandEncoder(),G=a.beginComputePass();G.setPipeline(p),G.setBindGroup(0,F),G.dispatchWorkgroups(n),G.end(),r.queue.submit([a.finish()]);const k=new Float32Array(await V(r,h,n*t*4));let w=0;for(let v=0;v<n;v++)for(let d=0;d<t;d++){const y=b(v,d),m=k[v*t+d];Math.abs(m-y)<=M||(w++,D.add(v),A||(A={rep:u,g:v,lane:d,got:m,want:y}))}s.push(w),W+=w}for(const u of[f,...P,h])u.destroy();return{pass:W===0,detail:{kernel:o?"add_ln (real, f32, sg)":"add_ln (real, f32)",rows:n,d:t,reps:z,tol:M,badLanes:W,badGroups:D.size,badPerRep:s,...A?{firstBad:A}:{}}}}S("adreno_probe2_addln_real",e=>be(e,!1));const U={D:56,D4:14,WG:128,H:4,LEN:3},ce=(e,o,r)=>(N(e,o+3*r)-512)/512;function pe(e){return`${T(U.WG)}
170
+ const D: u32 = ${U.D}u;
171
+ const D4: u32 = ${U.D4}u;
172
+ const H: u32 = ${U.H}u;
173
+ const LEN: u32 = ${U.LEN}u;
174
+ const JT: u32 = WG / D4;
175
+ const SCORES_CAP: u32 = 352u;
176
+ const SCALE: f32 = ${1/Math.sqrt(U.D)};
177
+ fn elem(id: u32, salt: u32, g: u32) -> f32 { return (vhash(id, salt + 3u * g) - 512.0) / 512.0; }
178
+ fn qvec(g: u32, h: u32, i4: u32) -> vec4<f32> {
179
+ let base = h * 64u + i4 * 4u;
180
+ return vec4<f32>(elem(base, 11u, g), elem(base + 1u, 11u, g), elem(base + 2u, 11u, g), elem(base + 3u, 11u, g));
181
+ }
182
+ fn kvvec(g: u32, h: u32, j: u32, i4: u32, salt: u32) -> vec4<f32> {
183
+ let base = (j * H + h) * 64u + i4 * 4u;
184
+ return vec4<f32>(elem(base, salt, g), elem(base + 1u, salt, g), elem(base + 2u, salt, g), elem(base + 3u, salt, g));
185
+ }
186
+ var<workgroup> qs4: array<vec4<f32>, D4>;
187
+ var<workgroup> scores: array<f32, SCORES_CAP>;
188
+ var<workgroup> red: array<f32, WG>;
189
+ var<workgroup> part: array<vec4<f32>, WG>;
190
+ @compute @workgroup_size(${U.WG})
191
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
192
+ let row = wid.x; let h = wid.y; let tid = lid.x;
193
+ let gi = row * H + h;
194
+ for (var i = tid; i < D4; i = i + WG) { qs4[i] = qvec(row, h, i); }
195
+ workgroupBarrier();
196
+ var localMax: f32 = -1e30;
197
+ for (var j = tid; j < LEN; j = j + WG) {
198
+ var dot4 = vec4<f32>(0.0);
199
+ for (var i = 0u; i < D4; i = i + 1u) { dot4 = dot4 + qs4[i] * kvvec(row, h, j, i, 22u); }
200
+ let sc = (dot4.x + dot4.y + dot4.z + dot4.w) * SCALE;
201
+ scores[j] = sc;
202
+ localMax = max(localMax, sc);
203
+ }
204
+ red[tid] = localMax;
205
+ workgroupBarrier();
206
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
207
+ if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }
208
+ workgroupBarrier();
209
+ }
210
+ let rowMax = red[0];
211
+ workgroupBarrier();
212
+ var localSum: f32 = 0.0;
213
+ for (var j = tid; j < LEN; j = j + WG) {
214
+ let e = exp(scores[j] - rowMax);
215
+ scores[j] = e;
216
+ localSum = localSum + e;
217
+ }
218
+ red[tid] = localSum;
219
+ workgroupBarrier();
220
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
221
+ if (tid < s) { red[tid] = red[tid] + red[tid + s]; }
222
+ workgroupBarrier();
223
+ }
224
+ let denom = red[0];
225
+ ${e?`
226
+ out[gi * WG + tid] = rowMax + denom;
227
+ `:`
228
+ let dq = tid % D4;
229
+ let jg = tid / D4;
230
+ var acc = vec4<f32>(0.0);
231
+ if (jg < JT) {
232
+ for (var j = jg; j < LEN; j = j + JT) {
233
+ acc = acc + scores[j] * kvvec(row, h, j, dq, 33u);
234
+ }
235
+ }
236
+ part[tid] = acc;
237
+ workgroupBarrier();
238
+ if (tid < D4) {
239
+ var o = vec4<f32>(0.0);
240
+ for (var g2 = 0u; g2 < JT; g2 = g2 + 1u) { o = o + part[g2 * D4 + tid]; }
241
+ o = o / denom;
242
+ let yoff = gi * D + tid * 4u;
243
+ out[yoff] = o.x;
244
+ out[yoff + 1u] = o.y;
245
+ out[yoff + 2u] = o.z;
246
+ out[yoff + 3u] = o.w;
247
+ }
248
+ `}
249
+ }`}function ue(e){const{D:o,H:r,LEN:t}=U,n=Math.floor(e/r),i=e%r,l=new Float64Array(o);for(let f=0;f<o;f++)l[f]=ce(i*64+f,11,n);const _=new Float64Array(t);for(let f=0;f<t;f++){let P=0;for(let h=0;h<o;h++)P+=l[h]*ce((f*r+i)*64+h,22,n);_[f]=P/Math.sqrt(o)}const B=Math.max(..._),b=_.map(f=>Math.exp(f-B)),p=b.reduce((f,P)=>f+P,0),c=new Float64Array(o);for(let f=0;f<o;f++){let P=0;for(let h=0;h<t;h++)P+=b[h]*ce((h*r+i)*64+f,33,n);c[f]=P/p}return{rowMax:B,denom:p,out:c}}S("adreno_probe2_attn_gen",e=>{const o=new Map,r=(t,n)=>(o.has(t)||o.set(t,ue(t)),o.get(t).out[n]);return x(e.device,pe(!1),{wg:U.WG,outPerGroup:U.D,want:r,tol:.001,dispatchY:U.H})});S("adreno_probe2_attn_gen_p12",e=>{const o=new Map,r=t=>{if(!o.has(t)){const{rowMax:n,denom:i}=ue(t);o.set(t,n+i)}return o.get(t)};return x(e.device,pe(!0),{wg:U.WG,outPerGroup:U.WG,want:r,tol:.001,dispatchY:U.H})});S("adreno_probe3_addln_real_sg",e=>e.hasSubgroups?be(e,!0):{skip:!0,reason:"subgroups feature unavailable"});S("adreno_probe3_addln_gen_uload",e=>{const o=`${T(256)}
250
+ const D: u32 = ${Y}u;
251
+ const EPS: f32 = ${J};
252
+ ${me}
253
+ var<workgroup> vbuf: array<f32, D>;
254
+ var<workgroup> scratch: array<f32, WG>;
255
+ @compute @workgroup_size(256)
256
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
257
+ let g = wid.x; let tid = lid.x;
258
+ var sum: f32 = 0.0;
259
+ for (var i = tid; i < D; i = i + WG) {
260
+ let v = xval(i, g) + rval(i, g);
261
+ vbuf[i] = v;
262
+ sum = sum + v;
263
+ }
264
+ scratch[tid] = sum;
265
+ workgroupBarrier();
266
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
267
+ if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }
268
+ workgroupBarrier();
269
+ }
270
+ let mu = workgroupUniformLoad(&scratch[0]) / f32(D);
271
+ var sq: f32 = 0.0;
272
+ for (var i = tid; i < D; i = i + WG) {
273
+ let dev = vbuf[i] - mu;
274
+ sq = sq + dev * dev;
275
+ }
276
+ scratch[tid] = sq;
277
+ workgroupBarrier();
278
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
279
+ if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }
280
+ workgroupBarrier();
281
+ }
282
+ let inv = inverseSqrt(workgroupUniformLoad(&scratch[0]) / f32(D) + EPS);
283
+ for (var i = tid; i < D; i = i + WG) {
284
+ out[g * D + i] = gval(i) * (vbuf[i] - mu) * inv + bval(i);
285
+ }
286
+ }`;return x(e.device,o,{wg:256,outPerGroup:Y,want:ie(Y,!1),tol:.001})});S("adreno_probe3_attn_gen_sg",e=>{if(!e.hasSubgroups)return{skip:!0,reason:"subgroups feature unavailable"};const o=`enable subgroups;
287
+ ${T(U.WG)}
288
+ const D: u32 = ${U.D}u;
289
+ const D4: u32 = ${U.D4}u;
290
+ const H: u32 = ${U.H}u;
291
+ const LEN: u32 = ${U.LEN}u;
292
+ const JT: u32 = WG / D4;
293
+ const SCORES_CAP: u32 = 352u;
294
+ const SCALE: f32 = ${1/Math.sqrt(U.D)};
295
+ fn elem(id: u32, salt: u32, g: u32) -> f32 { return (vhash(id, salt + 3u * g) - 512.0) / 512.0; }
296
+ fn qvec(g: u32, h: u32, i4: u32) -> vec4<f32> {
297
+ let base = h * 64u + i4 * 4u;
298
+ return vec4<f32>(elem(base, 11u, g), elem(base + 1u, 11u, g), elem(base + 2u, 11u, g), elem(base + 3u, 11u, g));
299
+ }
300
+ fn kvvec(g: u32, h: u32, j: u32, i4: u32, salt: u32) -> vec4<f32> {
301
+ let base = (j * H + h) * 64u + i4 * 4u;
302
+ return vec4<f32>(elem(base, salt, g), elem(base + 1u, salt, g), elem(base + 2u, salt, g), elem(base + 3u, salt, g));
303
+ }
304
+ var<workgroup> qs4: array<vec4<f32>, D4>;
305
+ var<workgroup> scores: array<f32, SCORES_CAP>;
306
+ var<workgroup> sgm: array<f32, WG / 4u>;
307
+ var<workgroup> sgs: array<f32, WG / 4u>;
308
+ var<workgroup> part: array<vec4<f32>, WG>;
309
+ @compute @workgroup_size(${U.WG})
310
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>,
311
+ @builtin(subgroup_size) sgSize: u32) {
312
+ let row = wid.x; let h = wid.y; let tid = lid.x;
313
+ let gi = row * H + h;
314
+ let sgId = tid / sgSize;
315
+ let nSg = (WG + sgSize - 1u) / sgSize;
316
+ for (var i = tid; i < D4; i = i + WG) { qs4[i] = qvec(row, h, i); }
317
+ workgroupBarrier();
318
+ var localMax: f32 = -1e30;
319
+ for (var j = tid; j < LEN; j = j + WG) {
320
+ var dot4 = vec4<f32>(0.0);
321
+ for (var i = 0u; i < D4; i = i + 1u) { dot4 = dot4 + qs4[i] * kvvec(row, h, j, i, 22u); }
322
+ let sc = (dot4.x + dot4.y + dot4.z + dot4.w) * SCALE;
323
+ scores[j] = sc;
324
+ localMax = max(localMax, sc);
325
+ }
326
+ let m1 = subgroupMax(localMax);
327
+ if (subgroupElect()) { sgm[sgId] = m1; }
328
+ workgroupBarrier(); // also publishes scores for phase 2
329
+ var rowMax = sgm[0];
330
+ for (var i = 1u; i < nSg; i = i + 1u) { rowMax = max(rowMax, sgm[i]); }
331
+ var localSum: f32 = 0.0;
332
+ for (var j = tid; j < LEN; j = j + WG) {
333
+ let e = exp(scores[j] - rowMax);
334
+ scores[j] = e;
335
+ localSum = localSum + e;
336
+ }
337
+ let s2 = subgroupAdd(localSum);
338
+ if (subgroupElect()) { sgs[sgId] = s2; }
339
+ workgroupBarrier(); // publishes exp'd scores for phase 3
340
+ var denom = sgs[0];
341
+ for (var i = 1u; i < nSg; i = i + 1u) { denom = denom + sgs[i]; }
342
+ let dq = tid % D4;
343
+ let jg = tid / D4;
344
+ var acc = vec4<f32>(0.0);
345
+ if (jg < JT) {
346
+ for (var j = jg; j < LEN; j = j + JT) {
347
+ acc = acc + scores[j] * kvvec(row, h, j, dq, 33u);
348
+ }
349
+ }
350
+ part[tid] = acc;
351
+ workgroupBarrier();
352
+ if (tid < D4) {
353
+ var o = vec4<f32>(0.0);
354
+ for (var g2 = 0u; g2 < JT; g2 = g2 + 1u) { o = o + part[g2 * D4 + tid]; }
355
+ o = o / denom;
356
+ let yoff = gi * D + tid * 4u;
357
+ out[yoff] = o.x;
358
+ out[yoff + 1u] = o.y;
359
+ out[yoff + 2u] = o.z;
360
+ out[yoff + 3u] = o.w;
361
+ }
362
+ }`,r=new Map,t=(n,i)=>(r.has(n)||r.set(n,ue(n)),r.get(n).out[i]);return x(e.device,o,{wg:U.WG,outPerGroup:U.D,want:t,tol:.001,dispatchY:U.H})});S("adreno_probe3_attn_gen_uload",e=>{const o=pe(!1).replace(`let rowMax = red[0];
363
+ workgroupBarrier();`,"let rowMax = workgroupUniformLoad(&red[0]);").replace("let denom = red[0];","let denom = workgroupUniformLoad(&red[0]);");if(!o.includes("workgroupUniformLoad"))throw new Error("uload rewrite did not apply");const r=new Map,t=(n,i)=>(r.has(n)||r.set(n,ue(n)),r.get(n).out[i]);return x(e.device,o,{wg:U.WG,outPerGroup:U.D,want:t,tol:.001,dispatchY:U.H})});S("adreno_probe3_striped_sum_wg256",e=>{const o=`${T(256)}
364
+ const D: u32 = ${Y}u;
365
+ var<workgroup> red: array<f32, WG>;
366
+ @compute @workgroup_size(256)
367
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
368
+ let g = wid.x; let tid = lid.x;
369
+ var sum: f32 = 0.0;
370
+ for (var i = tid; i < D; i = i + WG) { sum = sum + (vhash(i, g) - 512.0) / 256.0; }
371
+ red[tid] = sum;
372
+ workgroupBarrier();
373
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
374
+ if (tid < s) { red[tid] = red[tid] + red[tid + s]; }
375
+ workgroupBarrier();
376
+ }
377
+ out[g * WG + tid] = red[0];
378
+ }`,r=t=>{let n=0;for(let i=0;i<Y;i++)n+=Z(i,t);return n};return x(e.device,o,{wg:256,outPerGroup:256,want:r})});S("adreno_probe3_vbuf_sum_wg256",e=>{const o=`${T(256)}
379
+ var<workgroup> vbuf: array<f32, WG>;
380
+ var<workgroup> red: array<f32, WG>;
381
+ @compute @workgroup_size(256)
382
+ fn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {
383
+ let g = wid.x; let tid = lid.x;
384
+ vbuf[tid] = vhash(tid, g);
385
+ red[tid] = vhash(tid, g);
386
+ workgroupBarrier();
387
+ for (var s = WG / 2u; s > 0u; s = s >> 1u) {
388
+ if (tid < s) { red[tid] = red[tid] + red[tid + s]; }
389
+ workgroupBarrier();
390
+ }
391
+ out[g * WG + tid] = red[0] + vbuf[(tid + 64u) % WG];
392
+ }`,r=(t,n)=>ge(256)(t)+N((n+64)%256,t);return x(e.device,o,{wg:256,outPerGroup:256,want:r})});S("adreno_probe4_detect",async e=>{const{detectTreeReductionBug:o}=await he(async()=>{const{detectTreeReductionBug:t}=await import("./autotune-DBJGFXNj.js");return{detectTreeReductionBug:t}},__vite__mapDeps([0,1,2,3,4])),r=await o(e.device);return{pass:typeof r=="boolean",detail:{treeBug:r,sgAvailable:!!e.hasSubgroups,willForceSg:r&&!!e.hasSubgroups}}});S("adreno_probe5_addln_sg_d576",async e=>{if(!e.hasSubgroups)return{skip:!0,reason:"subgroups feature unavailable"};const{device:o}=e,r=576,t=re,n=new Float32Array(t*r),i=new Float32Array(t*r),l=new Float32Array(r),_=new Float32Array(r);for(let s=0;s<t;s++)for(let u=0;u<r;u++)n[s*r+u]=Z(u,s),i[s*r+u]=te(u,s);for(let s=0;s<r;s++)l[s]=oe(s),_[s]=ae(s);const B=new Map,b=(s,u)=>{if(!B.has(s)){const a=new Float64Array(r);let G=0;for(let d=0;d<r;d++)a[d]=Z(d,s)+te(d,s),G+=a[d];const k=G/r;let w=0;for(let d=0;d<r;d++)w+=(a[d]-k)*(a[d]-k);const v=1/Math.sqrt(w/r+J);B.set(s,a.map((d,y)=>oe(y)*(d-k)*v+ae(y)))}return B.get(s)[u]},p=ee(o,"add_ln",le,{t:"f32",wg:256,sg:!0,defines:{D:r,EPS:J}}),c=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,f=o.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(f.getMappedRange()).set([t,0,0,0]),f.unmap();const P=[n,i,l,_].map(s=>K(o,s,c)),h=o.createBuffer({size:t*r*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),F=o.createBindGroup({layout:p.getBindGroupLayout(0),entries:[f,...P,h].map((s,u)=>({binding:u,resource:{buffer:s}}))}),M=.001;let W=0,D=null;const A=[];for(let s=0;s<z;s++){const u=o.createCommandEncoder(),a=u.beginComputePass();a.setPipeline(p),a.setBindGroup(0,F),a.dispatchWorkgroups(t),a.end(),o.queue.submit([u.finish()]);const G=new Float32Array(await V(o,h,t*r*4));let k=0;for(let w=0;w<t;w++)for(let v=0;v<r;v++){const d=b(w,v);Math.abs(G[w*r+v]-d)<=M||(k++,D||(D={rep:s,g:w,lane:v,got:G[w*r+v],want:d}))}A.push(k),W+=k}for(const s of[f,...P,h])s.destroy();return{pass:W===0,detail:{kernel:"add_ln (real, f32, sg, D=576)",rows:t,d:r,reps:z,tol:M,badLanes:W,badPerRep:A,...D?{firstBad:D}:{}}}});const I=(e,o)=>(N(e&1048575,o)-512)/512,we=e=>{const o=new Uint16Array(e.length);for(let r=0;r<e.length;r++)o[r]=Se(e[r]);return o};async function de(e,{H:o,D:r,B:t,M:n,L:i,lens:l,sg:_,t:B="f32"}){const{device:b}=e,p=o*r,c=t*n,f=new Float32Array(c*p),P=new Float32Array(t*i*p),h=new Float32Array(t*i*p);for(let m=0;m<f.length;m++)f[m]=I(m,51);for(let m=0;m<P.length;m++)P[m]=I(m,52);for(let m=0;m<h.length;m++)h[m]=I(m,53);const F=1/Math.sqrt(r),M=new Float64Array(c*p);for(let m=0;m<t;m++)for(let g=0;g<n;g++){const R=m*n+g;for(let j=0;j<o;j++){const q=l[m],O=new Float64Array(q);for(let $=0;$<q;$++){let E=0;for(let L=0;L<r;L++)E+=f[R*p+j*r+L]*P[(m*i+$)*p+j*r+L];O[$]=E*F}const C=Math.max(...O),H=O.map($=>Math.exp($-C)),se=H.reduce(($,E)=>$+E,0);for(let $=0;$<r;$++){let E=0;for(let L=0;L<q;L++)E+=H[L]*h[(m*i+L)*p+j*r+$];M[R*p+j*r+$]=E/se}}}const W=ee(b,"attention",ke,{t:B,wg:128,sg:_,defines:{H:o,D:r,SCORES_CAP:352,ATTN_SCALE:F,Q_STRIDE:p,Q_OFF:0,KV_STRIDE:p,K_OFF:0,V_OFF:0}}),D=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,A=b.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(A.getMappedRange()).set([t,n,i,1,0,0,0,0]),A.unmap();const s=B==="f16"?2:4,u=[f,P,h].map(m=>K(b,B==="f16"?we(m):m,D)),a=K(b,new Uint32Array(l),D),G=b.createBuffer({size:c*p*s,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),k=b.createBindGroup({layout:W.getBindGroupLayout(0),entries:[A,...u,a,G].map((m,g)=>({binding:g,resource:{buffer:m}}))}),w=B==="f16"?.01:.001;let v=0,d=null;const y=[];for(let m=0;m<z;m++){const g=b.createCommandEncoder(),R=g.beginComputePass();R.setPipeline(W),R.setBindGroup(0,k),R.dispatchWorkgroups(c,o),R.end(),b.queue.submit([g.finish()]);const j=await V(b,G,c*p*s),q=B==="f16"?fe(new Uint16Array(j)):new Float32Array(j);let O=0;for(let C=0;C<M.length;C++)Math.abs(q[C]-M[C])<=w||(O++,d||(d={rep:m,i:C,got:q[C],want:M[C]}));y.push(O),v+=O}for(const m of[A,...u,a,G])m.destroy();return{pass:v===0,detail:{kernel:`attention (real, ${B}, sg, H${o} D${r})`,B:t,M:n,L:i,lens:l.join(","),reps:z,tol:w,badLanes:v,badPerRep:y,...d?{firstBad:d}:{}}}}S("adreno_probe6_attn_sg_h60_short",e=>e.hasSubgroups?de(e,{H:8,D:72,B:2,M:16,L:16,lens:[16,9],sg:!0}):{skip:!0,reason:"subgroups feature unavailable"});S("adreno_probe6_attn_sg_h60_long",e=>e.hasSubgroups?de(e,{H:8,D:72,B:2,M:4,L:224,lens:[224,131],sg:!0}):{skip:!0,reason:"subgroups feature unavailable"});S("adreno_probe6_rowln_sg_d576",async e=>{if(!e.hasSubgroups)return{skip:!0,reason:"subgroups feature unavailable"};const{device:o}=e,r=576,t=576,n=64,i=new Float32Array(n*r),l=new Float32Array(r*t),_=new Float32Array(t),B=new Float32Array(n*t),b=new Float32Array(t),p=new Float32Array(t);for(let a=0;a<i.length;a++)i[a]=I(a,61)*2;for(let a=0;a<l.length;a++)l[a]=I(a,62);for(let a=0;a<B.length;a++)B[a]=I(a,63)*2;for(let a=0;a<t;a++)_[a]=I(a,64),b[a]=1+I(a,65)/2,p[a]=I(a,66);const c=new Float64Array(n*t);for(let a=0;a<n;a++){const G=new Float64Array(t);let k=0;for(let y=0;y<t;y++){let m=0;for(let g=0;g<r;g++)m+=i[a*r+g]*l[g*t+y];G[y]=m+_[y]+B[a*t+y],k+=G[y]}const w=k/t;let v=0;for(let y=0;y<t;y++)v+=(G[y]-w)*(G[y]-w);const d=1/Math.sqrt(v/t+J);for(let y=0;y<t;y++)c[a*t+y]=b[y]*(G[y]-w)*d+p[y]}const f=ee(o,"gemm_row_ln",Ge,{t:"f32",wg:128,sg:!0,defines:{KDIM:r,D:t,EPS:J}}),P=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,h=o.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(h.getMappedRange()).set([n,0,0,0]),h.unmap();const F=[i,l,_,B,b,p].map(a=>K(o,a,P)),M=o.createBuffer({size:n*t*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),W=o.createBindGroup({layout:f.getBindGroupLayout(0),entries:[h,...F,M].map((a,G)=>({binding:G,resource:{buffer:a}}))}),D=.002;let A=0,s=null;const u=[];for(let a=0;a<z;a++){const G=o.createCommandEncoder(),k=G.beginComputePass();k.setPipeline(f),k.setBindGroup(0,W),k.dispatchWorkgroups(n),k.end(),o.queue.submit([G.finish()]);const w=new Float32Array(await V(o,M,n*t*4));let v=0;for(let d=0;d<c.length;d++)Math.abs(w[d]-c[d])<=D||(v++,s||(s={rep:a,i:d,got:w[d],want:c[d]}));u.push(v),A+=v}for(const a of[h,...F,M])a.destroy();return{pass:A===0,detail:{kernel:"gemm_row_ln (real, f32, sg, K=D=576)",M:n,reps:z,tol:D,badLanes:A,badPerRep:u,...s?{firstBad:s}:{}}}});S("adreno_probe7_attn_sg_h60_short_f16",e=>e.hasSubgroups?e.hasF16?de(e,{H:8,D:72,B:2,M:16,L:16,lens:[16,9],sg:!0,t:"f16"}):{skip:!0,reason:"no shader-f16"}:{skip:!0,reason:"subgroups feature unavailable"});S("adreno_probe7_attn_sg_h60_long_f16",e=>e.hasSubgroups?e.hasF16?de(e,{H:8,D:72,B:2,M:4,L:224,lens:[224,131],sg:!0,t:"f16"}):{skip:!0,reason:"no shader-f16"}:{skip:!0,reason:"subgroups feature unavailable"});S("adreno_probe7_addln_sg_d576_f16",async e=>{if(!e.hasSubgroups)return{skip:!0,reason:"subgroups feature unavailable"};if(!e.hasF16)return{skip:!0,reason:"no shader-f16"};const{device:o}=e,r=576,t=re,n=new Float32Array(t*r),i=new Float32Array(t*r),l=new Float32Array(r),_=new Float32Array(r);for(let s=0;s<t;s++)for(let u=0;u<r;u++)n[s*r+u]=Z(u,s)/2,i[s*r+u]=te(u,s)/2;for(let s=0;s<r;s++)l[s]=oe(s),_[s]=ae(s);const B=new Map,b=(s,u)=>{if(!B.has(s)){const a=new Float64Array(r);let G=0;for(let d=0;d<r;d++)a[d]=n[s*r+d]+i[s*r+d],G+=a[d];const k=G/r;let w=0;for(let d=0;d<r;d++)w+=(a[d]-k)*(a[d]-k);const v=1/Math.sqrt(w/r+J);B.set(s,a.map((d,y)=>l[y]*(d-k)*v+_[y]))}return B.get(s)[u]},p=ee(o,"add_ln",le,{t:"f16",wg:256,sg:!0,defines:{D:r,EPS:J}}),c=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,f=o.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(f.getMappedRange()).set([t,0,0,0]),f.unmap();const P=[n,i,l,_].map(s=>K(o,we(s),c)),h=o.createBuffer({size:t*r*2,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),F=o.createBindGroup({layout:p.getBindGroupLayout(0),entries:[f,...P,h].map((s,u)=>({binding:u,resource:{buffer:s}}))}),M=.02;let W=0,D=null;const A=[];for(let s=0;s<z;s++){const u=o.createCommandEncoder(),a=u.beginComputePass();a.setPipeline(p),a.setBindGroup(0,F),a.dispatchWorkgroups(t),a.end(),o.queue.submit([u.finish()]);const G=fe(new Uint16Array(await V(o,h,t*r*2)));let k=0;for(let w=0;w<t;w++)for(let v=0;v<r;v++){const d=b(w,v);Math.abs(G[w*r+v]-d)<=M||(k++,D||(D={rep:s,g:w,lane:v,got:G[w*r+v],want:d}))}A.push(k),W+=k}for(const s of[f,...P,h])s.destroy();return{pass:W===0,detail:{kernel:"add_ln (real, f16, sg, D=576)",rows:t,d:r,reps:z,tol:M,badLanes:W,badPerRep:A,...D?{firstBad:D}:{}}}});async function X(e,{H:o,D:r,QB:t,JB:n,B:i,M:l,L:_,lens:B,t:b="f16"}){const{device:p}=e,c=o*r,f=i*l,P=new Float32Array(f*c),h=new Float32Array(i*_*c),F=new Float32Array(i*_*c);for(let g=0;g<P.length;g++)P[g]=I(g,71);for(let g=0;g<h.length;g++)h[g]=I(g,72);for(let g=0;g<F.length;g++)F[g]=I(g,73);const M=1/Math.sqrt(r),W=new Float64Array(f*c);for(let g=0;g<i;g++)for(let R=0;R<l;R++){const j=g*l+R;for(let q=0;q<o;q++){const O=B[g],C=new Float64Array(O);for(let E=0;E<O;E++){let L=0;for(let Q=0;Q<r;Q++)L+=P[j*c+q*r+Q]*h[(g*_+E)*c+q*r+Q];C[E]=L*M}const H=Math.max(...C),se=C.map(E=>Math.exp(E-H)),$=se.reduce((E,L)=>E+L,0);for(let E=0;E<r;E++){let L=0;for(let Q=0;Q<O;Q++)L+=se[Q]*F[(g*_+Q)*c+q*r+E];W[j*c+q*r+E]=L/$}}}const D=ee(p,"attention_block",Be,{t:b,defines:{H:o,D:r,QB:t,JB:n,ATTN_SCALE:M,Q_STRIDE:c,Q_OFF:0,KV_STRIDE:c,K_OFF:0,V_OFF:0,PACKED:!1,NOPACKED:!0}}),A=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,s=p.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});new Uint32Array(s.getMappedRange()).set([i,l,_,1,0,0,0,0]),s.unmap();const u=b==="f16"?2:4,a=[P,h,F].map(g=>K(p,b==="f16"?we(g):g,A)),G=K(p,new Uint32Array(B),A),k=p.createBuffer({size:f*c*u,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),w=p.createBindGroup({layout:D.getBindGroupLayout(0),entries:[s,...a,G,k].map((g,R)=>({binding:R,resource:{buffer:g}}))}),v=b==="f16"?.01:.001;let d=0,y=null;const m=[];for(let g=0;g<z;g++){const R=p.createCommandEncoder(),j=R.beginComputePass();j.setPipeline(D),j.setBindGroup(0,w),j.dispatchWorkgroups(Math.ceil(l/t),o,i),j.end(),p.queue.submit([R.finish()]);const q=await V(p,k,f*c*u),O=b==="f16"?fe(new Uint16Array(q)):new Float32Array(q);let C=0;for(let H=0;H<W.length;H++)Math.abs(O[H]-W[H])<=v||(C++,y||(y={rep:g,i:H,got:O[H],want:W[H]}));m.push(C),d+=C}for(const g of[s,...a,G,k])g.destroy();return{pass:d===0,detail:{kernel:`attention_block (real, ${b}, H${o} D${r} QB${t} JB${n})`,B:i,M:l,L:_,lens:B.join(","),reps:z,tol:v,badLanes:d,badPerRep:m,...y?{firstBad:y}:{}}}}S("adreno_probe8_attnblock_h60_f16",e=>e.hasF16?X(e,{H:8,D:72,QB:14,JB:32,B:2,M:33,L:33,lens:[33,17],t:"f16"}):{skip:!0,reason:"no shader-f16"});S("adreno_probe8_attnblock_h60_big_f16",e=>e.hasF16?X(e,{H:8,D:72,QB:14,JB:32,B:2,M:96,L:96,lens:[96,49],t:"f16"}):{skip:!0,reason:"no shader-f16"});S("adreno_probe8_weights_hash",async()=>{const e=(t,n)=>{for(let i=0;i<n.length;i++)t^=n[i],t=Math.imul(t,16777619)>>>0;return t},o=async t=>{const i=(await(await fetch(`${t}/manifest.json`)).json()).bins??["weights.bin"];let l=2166136261,_=0;for(const B of i){const b=new Uint8Array(await(await fetch(`${t}/${B}`)).arrayBuffer());_+=b.length,l=e(l,b)}return{hash:l.toString(16),bytes:_,bins:i.length}},r={moxhi:await o("/weights")};try{r.hachimi60=await o("/weights/hachimi60")}catch(t){r.hachimi60={error:String(t?.message??t)}}return{pass:!0,detail:r}});S("adreno_probe8b_attnblock_h60_qb8",e=>e.hasF16?X(e,{H:8,D:72,QB:8,JB:32,B:2,M:33,L:33,lens:[33,17],t:"f16"}):{skip:!0,reason:"no shader-f16"});S("adreno_probe8b_attnblock_h60_qb12",e=>e.hasF16?X(e,{H:8,D:72,QB:12,JB:32,B:2,M:33,L:33,lens:[33,17],t:"f16"}):{skip:!0,reason:"no shader-f16"});S("adreno_probe8b_attnblock_h60_qb14_jb16",e=>e.hasF16?X(e,{H:8,D:72,QB:14,JB:16,B:2,M:33,L:33,lens:[33,17],t:"f16"}):{skip:!0,reason:"no shader-f16"});S("adreno_probe8b_attnblock_h60_qb14_f32",e=>X(e,{H:8,D:72,QB:14,JB:32,B:2,M:33,L:33,lens:[33,17],t:"f32"}));S("adreno_probe8b_attnblock_d56_qb14",e=>e.hasF16?X(e,{H:8,D:56,QB:14,JB:32,B:2,M:33,L:33,lens:[33,17],t:"f16"}):{skip:!0,reason:"no shader-f16"});
393
+ //# sourceMappingURL=adreno_probe-CjpGrE_r.js.map
assets/adreno_probe-CjpGrE_r.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"mappings":"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","names":["GROUPS","REPS","payload","tid","g","WGSL_HASH","runProbe","device","code","wg","outPerGroup","want","tol","dispatchY","module","errors","m","pipeline","totalGroups","outElems","outBuf","bindGroup","badLanes","badGroups","firstBad","badPerRep","rep","encoder","pass","got","readback","repBad","i","w","v","header","treeBcastCode","maxWant","sumWant","s","registerTest","ctx","t","p","lane","j","ADDLN_D","WGSL_ADDLN_DATA","xval","rval","gval","bval","addLnWant","d","muOnly","cache","row","sum","mu","sq","inv","LN_EPS","addLnGenCode","runAddLnReal","sg","D_MODEL","rows","x","r","gamma","beta","getPipeline","addLnSource","usage","params","bufs","a","createBuffer","yBuf","buffer","binding","b","ATTN","attnElem","id","salt","attnGenCode","p12","attnRef","gi","D","H","LEN","h","q","scores","dot","e","denom","out","acc","rowMax","detectTreeReductionBug","__vitePreload","treeBug","xx","smallF","idx","toHalf","f32ToF16","runAttnRealDims","B","M","L","lens","HD","k","scale","len","mx","attentionSource","elem","lensBuf","raw","expandF16","K","vrow","n","kk","gemmRowLnSource","bb","runAttnBlockDims","QB","JB","attentionBlockSource","fnv","bytes","hashModel","root","bins","bin","buf","detail","err"],"ignoreList":[],"sources":["../../src/debug/tests/adreno_probe.js"],"sourcesContent":["// Adreno reduction-bug bisect probes (2026-07 Android \"dịch loạn\" regression).\n//\n// Evidence from the failing device (Adreno 7xx, subgroups min 64):\n// FAIL attention.wgsl (f16 AND f32, outputs ~0) add_layernorm.wgsl (both dtypes)\n// PASS attention_block, gemm_gemv, argmax_penalty — same tree-reduce idiom\n// The static discriminator between the two sets is unclear (argmax has an\n// early return + a WG-wide tree + barriers and passes), so these standalone\n// micro-kernels bisect the space on-device. Every probe is deterministic:\n// payloads are small-integer hashes (exact in f32), so expected values are\n// exact and tol is 0. Each runs GROUPS workgroups × REPS dispatches because\n// the real failures hit only SOME workgroups per dispatch (5/32 in\n// attn_encoder_f32) — a scheduling-dependent bug needs volume to show up.\n//\n// Probe map (expected on a healthy device: all PASS):\n// tree_bcast_wg64 tree reduce + all-thread read of red[0], single wave\n// tree_bcast_wg128 same at attention's WG (first tree step crosses waves)\n// tree_sum_wg256 sum tree + all-thread broadcast at add_ln's WG\n// tree_single_wg128 same tree, only tid 0 reads the result (argmax shape)\n// tree_twice_wg128 max tree, broadcast, then sum tree REUSING red\n// (attention's exact phase-1/2 sequence)\n// skiploop_wg128 attention phase 1 verbatim: len=16 so most threads\n// skip the scan loop and carry the -1e30 neutral\n// share_wg128 no tree — write shared, barrier, read another wave's\n// slot (attention_block-style visibility control)\n// uload_wg128 fix candidate A: workgroupUniformLoad(&red[0])\n// sg_wg256 fix candidate B: subgroupAdd + elect + serial fold\n// (add_layernorm's IF_SG variant shape)\n// ROUND 2 (probe2_*): round 1 all PASSED on the failing device — the naked\n// reduction idiom is fine on Adreno. The bug needs more of the real kernels'\n// context. Ladder: full structural replicas of add_ln / attention with\n// IN-SHADER synthetic data (no bindings) vs the REAL add_ln kernel at volume\n// (256 rows × 4 reps). gen FAIL → miscompile is in the shader structure\n// (bisect further via the _mu / _p12 cut-downs); gen PASS + real FAIL → the\n// trigger is in the binding/load path (uniform params, storage reads, layout).\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback } from '../gpu-utils.js';\nimport { getPipeline } from '../../engine/pipelines.js';\nimport { D_MODEL, LN_EPS } from '../../engine/constants.js';\nimport { f32ToF16, expandF16 } from '../../engine/f16.js';\nimport addLnSource from '../../engine/kernels/add_layernorm.wgsl?raw';\nimport attentionSource from '../../engine/kernels/attention.wgsl?raw';\nimport attentionBlockSource from '../../engine/kernels/attention_block.wgsl?raw';\nimport gemmRowLnSource from '../../engine/kernels/gemm_row_ln.wgsl?raw';\n\nconst GROUPS = 256;\nconst REPS = 4;\n\n// Deterministic payload, exact in f32: (((tid+1)·2654435761) ^ ((g+1)·40503)) & 1023.\n// WGSL u32 arithmetic wraps; Math.imul matches it bit-for-bit.\nconst payload = (tid, g) => ((Math.imul(tid + 1, 2654435761) ^ Math.imul(g + 1, 40503)) >>> 0) & 1023;\n\nconst WGSL_HASH = /* wgsl */ `\nfn vhash(tid: u32, g: u32) -> f32 {\n return f32((((tid + 1u) * 2654435761u) ^ ((g + 1u) * 40503u)) & 1023u);\n}\n`;\n\n// One probe run: build pipeline from `code`, dispatch GROUPS workgroups REPS\n// times (fresh encoder each rep), compare every lane against `want(g, tid)`.\n// outPerGroup = lanes written per workgroup (WG for broadcast probes, 1 for\n// the single-reader probe).\nasync function runProbe(device, code, { wg, outPerGroup, want, tol = 0, dispatchY = 1 }) {\n const module = device.createShaderModule({ code });\n const info = await module.getCompilationInfo();\n const errors = info.messages.filter((m) => m.type === 'error');\n if (errors.length) {\n return { pass: false, detail: { compileErrors: errors.map((m) => m.message).slice(0, 3) } };\n }\n const pipeline = device.createComputePipeline({\n layout: 'auto',\n compute: { module, entryPoint: 'main' },\n });\n const totalGroups = GROUPS * dispatchY;\n const outElems = totalGroups * outPerGroup;\n const outBuf = device.createBuffer({\n size: outElems * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [{ binding: 0, resource: { buffer: outBuf } }],\n });\n\n let badLanes = 0;\n const badGroups = new Set();\n let firstBad = null;\n const badPerRep = [];\n for (let rep = 0; rep < REPS; rep++) {\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(GROUPS, dispatchY);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const got = new Float32Array(await readback(device, outBuf, outElems * 4));\n let repBad = 0;\n for (let g = 0; g < totalGroups; g++) {\n for (let i = 0; i < outPerGroup; i++) {\n const w = want(g, i);\n const v = got[g * outPerGroup + i];\n if (!(Math.abs(v - w) <= tol)) {\n repBad++;\n badGroups.add(g);\n if (!firstBad) firstBad = { rep, g, lane: i, got: v, want: w };\n }\n }\n }\n badPerRep.push(repBad);\n badLanes += repBad;\n }\n outBuf.destroy();\n return {\n pass: badLanes === 0,\n detail: {\n wg, groups: totalGroups, reps: REPS, badLanes, badGroups: badGroups.size, badPerRep,\n ...(firstBad ? { firstBad } : {}),\n },\n };\n}\n\nconst header = (wg) => /* wgsl */ `\n@group(0) @binding(0) var<storage, read_write> out: array<f32>;\nconst WG: u32 = ${wg}u;\n${WGSL_HASH}\n`;\n\n// Tree reduce (max) over red[WG] + broadcast read by ALL threads — the shape\n// attention.wgsl and add_layernorm.wgsl share and argmax does not.\nfunction treeBcastCode(wg) {\n return /* wgsl */ `${header(wg)}\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(${wg})\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n red[tid] = vhash(tid, g);\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }\n workgroupBarrier();\n }\n out[g * WG + tid] = red[0];\n}`;\n}\n\nconst maxWant = (wg) => (g) => {\n let m = -Infinity;\n for (let t = 0; t < wg; t++) m = Math.max(m, payload(t, g));\n return m;\n};\nconst sumWant = (wg) => (g) => {\n let s = 0;\n for (let t = 0; t < wg; t++) s += payload(t, g);\n return s;\n};\n\nregisterTest('adreno_probe_tree_bcast_wg64', (ctx) =>\n runProbe(ctx.device, treeBcastCode(64), { wg: 64, outPerGroup: 64, want: maxWant(64) }));\n\nregisterTest('adreno_probe_tree_bcast_wg128', (ctx) =>\n runProbe(ctx.device, treeBcastCode(128), { wg: 128, outPerGroup: 128, want: maxWant(128) }));\n\n// Sum tree at add_ln's WG=256.\nregisterTest('adreno_probe_tree_sum_wg256', (ctx) => {\n const code = /* wgsl */ `${header(256)}\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(256)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n red[tid] = vhash(tid, g);\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = red[tid] + red[tid + s]; }\n workgroupBarrier();\n }\n out[g * WG + tid] = red[0];\n}`;\n return runProbe(ctx.device, code, { wg: 256, outPerGroup: 256, want: sumWant(256) });\n});\n\n// Same tree, but only tid 0 reads red[0] — argmax_penalty's (passing) shape.\nregisterTest('adreno_probe_tree_single_wg128', (ctx) => {\n const code = /* wgsl */ `${header(128)}\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(128)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n red[tid] = vhash(tid, g);\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }\n workgroupBarrier();\n }\n if (tid == 0u) { out[g] = red[0]; }\n}`;\n return runProbe(ctx.device, code, { wg: 128, outPerGroup: 1, want: maxWant(128) });\n});\n\n// Max tree → broadcast → sum tree reusing red — attention's exact phase-1/2\n// sequence. want = max + Σ(payload·0.5 + 1) (all halves: exact in f32).\nregisterTest('adreno_probe_tree_twice_wg128', (ctx) => {\n const code = /* wgsl */ `${header(128)}\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(128)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n red[tid] = vhash(tid, g);\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }\n workgroupBarrier();\n }\n let m = red[0];\n workgroupBarrier(); // red[0] reads done before the sum pass reuses red\n red[tid] = vhash(tid, g) * 0.5 + 1.0;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = red[tid] + red[tid + s]; }\n workgroupBarrier();\n }\n out[g * WG + tid] = m + red[0];\n}`;\n const want = (g) => {\n let m = -Infinity; let s = 0;\n for (let t = 0; t < 128; t++) {\n const p = payload(t, g);\n m = Math.max(m, p);\n s += p * 0.5 + 1;\n }\n return m + s;\n };\n return runProbe(ctx.device, code, { wg: 128, outPerGroup: 128, want });\n});\n\n// attention.wgsl phase 1 verbatim at encoder shape: len=16 « WG, so threads\n// 16..127 skip the scan loop entirely and carry the -1e30 neutral into the\n// max tree; all threads then broadcast-read the result.\nregisterTest('adreno_probe_skiploop_wg128', (ctx) => {\n const code = /* wgsl */ `${header(128)}\nconst LEN: u32 = 16u;\nvar<workgroup> scores: array<f32, LEN>;\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(128)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n var localMax: f32 = -1e30;\n for (var j = tid; j < LEN; j = j + WG) {\n let sc = vhash(j, g);\n scores[j] = sc;\n localMax = max(localMax, sc);\n }\n red[tid] = localMax;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }\n workgroupBarrier();\n }\n // Consume scores too so the compiler cannot drop it: out = rowMax + scores[tid%LEN].\n out[g * WG + tid] = red[0] + scores[tid % LEN];\n}`;\n const want = (g, lane) => {\n let m = -Infinity;\n for (let j = 0; j < 16; j++) m = Math.max(m, payload(j, g));\n return m + payload(lane % 16, g);\n };\n return runProbe(ctx.device, code, { wg: 128, outPerGroup: 128, want });\n});\n\n// No tree at all: write own slot, one barrier, read a slot 64 threads away\n// (guaranteed cross-wave at Adreno's wave 64). attention_block-style control.\nregisterTest('adreno_probe_share_wg128', (ctx) => {\n const code = /* wgsl */ `${header(128)}\nvar<workgroup> sh: array<f32, WG>;\n@compute @workgroup_size(128)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n sh[tid] = vhash(tid, g);\n workgroupBarrier();\n out[g * WG + tid] = sh[(tid + 64u) % WG];\n}`;\n return runProbe(ctx.device, code, {\n wg: 128, outPerGroup: 128, want: (g, lane) => payload((lane + 64) % 128, g),\n });\n});\n\n// Fix candidate A: broadcast via workgroupUniformLoad instead of a plain read.\nregisterTest('adreno_probe_uload_wg128', (ctx) => {\n const code = /* wgsl */ `${header(128)}\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(128)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n red[tid] = vhash(tid, g);\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }\n workgroupBarrier();\n }\n out[g * WG + tid] = workgroupUniformLoad(&red[0]);\n}`;\n return runProbe(ctx.device, code, { wg: 128, outPerGroup: 128, want: maxWant(128) });\n});\n\n// Fix candidate B: subgroupAdd + elect + serial fold (add_layernorm IF_SG\n// shape) with an all-thread broadcast of the folded total.\nregisterTest('adreno_probe_sg_wg256', (ctx) => {\n if (!ctx.hasSubgroups) return { skip: true, reason: 'subgroups feature unavailable' };\n const code = /* wgsl */ `enable subgroups;\n${header(256)}\nvar<workgroup> sgSum: array<f32, WG / 4u>;\n@compute @workgroup_size(256)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>,\n @builtin(subgroup_size) sgSize: u32) {\n let g = wid.x; let tid = lid.x;\n let s1 = subgroupAdd(vhash(tid, g));\n let sgId = tid / sgSize;\n if (subgroupElect()) { sgSum[sgId] = s1; }\n workgroupBarrier();\n let nSg = (WG + sgSize - 1u) / sgSize;\n var total = 0.0;\n for (var i = 0u; i < nSg; i = i + 1u) { total = total + sgSum[i]; }\n out[g * WG + tid] = total;\n}`;\n return runProbe(ctx.device, code, { wg: 256, outPerGroup: 256, want: sumWant(256) });\n});\n\n// ------------------------------------------------------------- round 2 ---\n\n// Shared synthetic-data formulas (exact small ints scaled by powers of two —\n// identical in WGSL f32 and JS f64). JS mirrors are below each probe.\nconst ADDLN_D = 448;\nconst WGSL_ADDLN_DATA = /* wgsl */ `\nfn xval(i: u32, g: u32) -> f32 { return (vhash(i, g) - 512.0) / 256.0; }\nfn rval(i: u32, g: u32) -> f32 { return (vhash(i + 7777u, g) - 512.0) / 256.0; }\nfn gval(i: u32) -> f32 { return 1.0 + (vhash(i, 12345u) - 512.0) / 1024.0; }\nfn bval(i: u32) -> f32 { return (vhash(i, 54321u) - 512.0) / 512.0; }\n`;\nconst xval = (i, g) => (payload(i, g) - 512) / 256;\nconst rval = (i, g) => (payload(i + 7777, g) - 512) / 256;\nconst gval = (i) => 1 + (payload(i, 12345) - 512) / 1024;\nconst bval = (i) => (payload(i, 54321) - 512) / 512;\n\n// f64 add_ln reference for row g: full output, or (v - mu) when muOnly.\nfunction addLnWant(d, muOnly) {\n const cache = new Map();\n return (g, i) => {\n let row = cache.get(g);\n if (!row) {\n const v = new Float64Array(d);\n let sum = 0;\n for (let j = 0; j < d; j++) { v[j] = xval(j, g) + rval(j, g); sum += v[j]; }\n const mu = sum / d;\n let sq = 0;\n for (let j = 0; j < d; j++) sq += (v[j] - mu) * (v[j] - mu);\n const inv = 1 / Math.sqrt(sq / d + LN_EPS);\n row = new Float64Array(d);\n for (let j = 0; j < d; j++) {\n row[j] = muOnly ? v[j] - mu : gval(j) * (v[j] - mu) * inv + bval(j);\n }\n cache.set(g, row);\n }\n return row[i];\n };\n}\n\n// Structural replica of add_layernorm.wgsl (f32, WG 256, D 448) with\n// in-shader data — no uniform, no storage reads. muOnly stops after the\n// first reduction (out = v - mu).\nfunction addLnGenCode(muOnly) {\n return /* wgsl */ `${header(256)}\nconst D: u32 = ${ADDLN_D}u;\nconst EPS: f32 = ${LN_EPS};\n${WGSL_ADDLN_DATA}\nvar<workgroup> vbuf: array<f32, D>;\nvar<workgroup> scratch: array<f32, WG>;\n@compute @workgroup_size(256)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n var sum: f32 = 0.0;\n for (var i = tid; i < D; i = i + WG) {\n let v = xval(i, g) + rval(i, g);\n vbuf[i] = v;\n sum = sum + v;\n }\n scratch[tid] = sum;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }\n workgroupBarrier();\n }\n let mu = scratch[0] / f32(D);\n workgroupBarrier();\n${muOnly ? `\n for (var i = tid; i < D; i = i + WG) { out[g * D + i] = vbuf[i] - mu; }\n` : `\n var sq: f32 = 0.0;\n for (var i = tid; i < D; i = i + WG) {\n let dev = vbuf[i] - mu;\n sq = sq + dev * dev;\n }\n scratch[tid] = sq;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }\n workgroupBarrier();\n }\n let inv = inverseSqrt(scratch[0] / f32(D) + EPS);\n for (var i = tid; i < D; i = i + WG) {\n out[g * D + i] = gval(i) * (vbuf[i] - mu) * inv + bval(i);\n }\n`}\n}`;\n}\n\nregisterTest('adreno_probe2_addln_gen', (ctx) =>\n runProbe(ctx.device, addLnGenCode(false), {\n wg: 256, outPerGroup: ADDLN_D, want: addLnWant(ADDLN_D, false), tol: 1e-3,\n }));\n\nregisterTest('adreno_probe2_addln_gen_mu', (ctx) =>\n runProbe(ctx.device, addLnGenCode(true), {\n wg: 256, outPerGroup: ADDLN_D, want: addLnWant(ADDLN_D, true), tol: 1e-3,\n }));\n\n// The REAL add_layernorm.wgsl (f32, via getPipeline exactly like production)\n// at probe volume: 256 rows, deterministic buffers, 4 dispatches. sg=true\n// builds the IF_SG (subgroupAdd) variant — production fix candidate.\nasync function runAddLnReal(ctx, sg) {\n const { device } = ctx;\n const d = D_MODEL;\n const rows = GROUPS;\n const x = new Float32Array(rows * d);\n const r = new Float32Array(rows * d);\n const gamma = new Float32Array(d);\n const beta = new Float32Array(d);\n for (let g = 0; g < rows; g++) {\n for (let i = 0; i < d; i++) {\n x[g * d + i] = xval(i, g);\n r[g * d + i] = rval(i, g);\n }\n }\n for (let i = 0; i < d; i++) { gamma[i] = gval(i); beta[i] = bval(i); }\n const want = addLnWant(d, false);\n\n const pipeline = getPipeline(device, 'add_ln', addLnSource, {\n t: 'f32', wg: 256, sg, defines: { D: d, EPS: LN_EPS },\n });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const params = device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });\n new Uint32Array(params.getMappedRange()).set([rows, 0, 0, 0]);\n params.unmap();\n const bufs = [x, r, gamma, beta].map((a) => createBuffer(device, a, usage));\n const yBuf = device.createBuffer({ size: rows * d * 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [params, ...bufs, yBuf].map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n\n const tol = 1e-3;\n let badLanes = 0;\n const badGroups = new Set();\n let firstBad = null;\n const badPerRep = [];\n for (let rep = 0; rep < REPS; rep++) {\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(rows);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const got = new Float32Array(await readback(device, yBuf, rows * d * 4));\n let repBad = 0;\n for (let g = 0; g < rows; g++) {\n for (let i = 0; i < d; i++) {\n const w = want(g, i);\n const v = got[g * d + i];\n if (!(Math.abs(v - w) <= tol)) {\n repBad++;\n badGroups.add(g);\n if (!firstBad) firstBad = { rep, g, lane: i, got: v, want: w };\n }\n }\n }\n badPerRep.push(repBad);\n badLanes += repBad;\n }\n for (const b of [params, ...bufs, yBuf]) b.destroy();\n return {\n pass: badLanes === 0,\n detail: {\n kernel: sg ? 'add_ln (real, f32, sg)' : 'add_ln (real, f32)',\n rows, d, reps: REPS, tol, badLanes,\n badGroups: badGroups.size, badPerRep, ...(firstBad ? { firstBad } : {}),\n },\n };\n}\n\nregisterTest('adreno_probe2_addln_real', (ctx) => runAddLnReal(ctx, false));\n\n// Structural replica of attention.wgsl (f32, WG 128, D 56, H 4, len 3 of\n// L 4 — the exact attn_encoder_f32 failing shape) with in-shader data.\n// p12 stops after phase 2 (out = rowMax + denom per thread).\nconst ATTN = { D: 56, D4: 14, WG: 128, H: 4, LEN: 3, JT: Math.floor(128 / 14) };\nconst attnElem = (id, salt, g) => (payload(id, salt + 3 * g) - 512) / 512;\n\nfunction attnGenCode(p12) {\n return /* wgsl */ `${header(ATTN.WG)}\nconst D: u32 = ${ATTN.D}u;\nconst D4: u32 = ${ATTN.D4}u;\nconst H: u32 = ${ATTN.H}u;\nconst LEN: u32 = ${ATTN.LEN}u;\nconst JT: u32 = WG / D4;\nconst SCORES_CAP: u32 = 352u;\nconst SCALE: f32 = ${1 / Math.sqrt(ATTN.D)};\nfn elem(id: u32, salt: u32, g: u32) -> f32 { return (vhash(id, salt + 3u * g) - 512.0) / 512.0; }\nfn qvec(g: u32, h: u32, i4: u32) -> vec4<f32> {\n let base = h * 64u + i4 * 4u;\n return vec4<f32>(elem(base, 11u, g), elem(base + 1u, 11u, g), elem(base + 2u, 11u, g), elem(base + 3u, 11u, g));\n}\nfn kvvec(g: u32, h: u32, j: u32, i4: u32, salt: u32) -> vec4<f32> {\n let base = (j * H + h) * 64u + i4 * 4u;\n return vec4<f32>(elem(base, salt, g), elem(base + 1u, salt, g), elem(base + 2u, salt, g), elem(base + 3u, salt, g));\n}\nvar<workgroup> qs4: array<vec4<f32>, D4>;\nvar<workgroup> scores: array<f32, SCORES_CAP>;\nvar<workgroup> red: array<f32, WG>;\nvar<workgroup> part: array<vec4<f32>, WG>;\n@compute @workgroup_size(${ATTN.WG})\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let row = wid.x; let h = wid.y; let tid = lid.x;\n let gi = row * H + h;\n for (var i = tid; i < D4; i = i + WG) { qs4[i] = qvec(row, h, i); }\n workgroupBarrier();\n var localMax: f32 = -1e30;\n for (var j = tid; j < LEN; j = j + WG) {\n var dot4 = vec4<f32>(0.0);\n for (var i = 0u; i < D4; i = i + 1u) { dot4 = dot4 + qs4[i] * kvvec(row, h, j, i, 22u); }\n let sc = (dot4.x + dot4.y + dot4.z + dot4.w) * SCALE;\n scores[j] = sc;\n localMax = max(localMax, sc);\n }\n red[tid] = localMax;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = max(red[tid], red[tid + s]); }\n workgroupBarrier();\n }\n let rowMax = red[0];\n workgroupBarrier();\n var localSum: f32 = 0.0;\n for (var j = tid; j < LEN; j = j + WG) {\n let e = exp(scores[j] - rowMax);\n scores[j] = e;\n localSum = localSum + e;\n }\n red[tid] = localSum;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = red[tid] + red[tid + s]; }\n workgroupBarrier();\n }\n let denom = red[0];\n${p12 ? `\n out[gi * WG + tid] = rowMax + denom;\n` : `\n let dq = tid % D4;\n let jg = tid / D4;\n var acc = vec4<f32>(0.0);\n if (jg < JT) {\n for (var j = jg; j < LEN; j = j + JT) {\n acc = acc + scores[j] * kvvec(row, h, j, dq, 33u);\n }\n }\n part[tid] = acc;\n workgroupBarrier();\n if (tid < D4) {\n var o = vec4<f32>(0.0);\n for (var g2 = 0u; g2 < JT; g2 = g2 + 1u) { o = o + part[g2 * D4 + tid]; }\n o = o / denom;\n let yoff = gi * D + tid * 4u;\n out[yoff] = o.x;\n out[yoff + 1u] = o.y;\n out[yoff + 2u] = o.z;\n out[yoff + 3u] = o.w;\n }\n`}\n}`;\n}\n\n// f64 reference per (gi = row·H + h): softmax attention over len 3.\nfunction attnRef(gi) {\n const { D, H, LEN } = ATTN;\n const row = Math.floor(gi / H);\n const h = gi % H;\n const q = new Float64Array(D);\n for (let d = 0; d < D; d++) q[d] = attnElem(h * 64 + d, 11, row);\n const scores = new Float64Array(LEN);\n for (let j = 0; j < LEN; j++) {\n let dot = 0;\n for (let d = 0; d < D; d++) dot += q[d] * attnElem((j * H + h) * 64 + d, 22, row);\n scores[j] = dot / Math.sqrt(D);\n }\n const m = Math.max(...scores);\n const e = scores.map((s) => Math.exp(s - m));\n const denom = e.reduce((a, b) => a + b, 0);\n const out = new Float64Array(D);\n for (let d = 0; d < D; d++) {\n let acc = 0;\n for (let j = 0; j < LEN; j++) acc += e[j] * attnElem((j * H + h) * 64 + d, 33, row);\n out[d] = acc / denom;\n }\n return { rowMax: m, denom, out };\n}\n\nregisterTest('adreno_probe2_attn_gen', (ctx) => {\n const cache = new Map();\n const want = (gi, lane) => {\n if (!cache.has(gi)) cache.set(gi, attnRef(gi));\n return cache.get(gi).out[lane];\n };\n return runProbe(ctx.device, attnGenCode(false), {\n wg: ATTN.WG, outPerGroup: ATTN.D, want, tol: 1e-3, dispatchY: ATTN.H,\n });\n});\n\nregisterTest('adreno_probe2_attn_gen_p12', (ctx) => {\n const cache = new Map();\n const want = (gi) => {\n if (!cache.has(gi)) {\n const { rowMax, denom } = attnRef(gi);\n cache.set(gi, rowMax + denom);\n }\n return cache.get(gi);\n };\n return runProbe(ctx.device, attnGenCode(true), {\n wg: ATTN.WG, outPerGroup: ATTN.WG, want, tol: 1e-3, dispatchY: ATTN.H,\n });\n});\n\n// ------------------------------------------------------------- round 3 ---\n//\n// Round 2 on the failing device: ALL gen replicas FAIL, identically to the\n// real kernel (addln_gen firstBad == addln_real firstBad) → binding path is\n// irrelevant, the miscompile is in the shader structure. addln failures are\n// perfectly DETERMINISTIC (same badLanes every rep); attn_gen_p12's\n// firstBad -6.4e31 = 64·(-1e30) → in the second reduction, one whole wave's\n// re-written red[] slots were read as their PHASE-1 leftovers.\n// Round 3: (a) run the fix candidates on the failing structures — the real\n// add_ln sg variant, sg attention, uload broadcasts; (b) two mechanism\n// probes isolating the remaining delta between passing round-1 shapes and\n// failing round-2 shapes (strided multi-trip partial loop; second shared\n// array consumed post-broadcast).\n\nregisterTest('adreno_probe3_addln_real_sg', (ctx) =>\n ctx.hasSubgroups ? runAddLnReal(ctx, true) : { skip: true, reason: 'subgroups feature unavailable' });\n\n// addln replica with workgroupUniformLoad broadcasts (mu and inv).\nregisterTest('adreno_probe3_addln_gen_uload', (ctx) => {\n const code = /* wgsl */ `${header(256)}\nconst D: u32 = ${ADDLN_D}u;\nconst EPS: f32 = ${LN_EPS};\n${WGSL_ADDLN_DATA}\nvar<workgroup> vbuf: array<f32, D>;\nvar<workgroup> scratch: array<f32, WG>;\n@compute @workgroup_size(256)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n var sum: f32 = 0.0;\n for (var i = tid; i < D; i = i + WG) {\n let v = xval(i, g) + rval(i, g);\n vbuf[i] = v;\n sum = sum + v;\n }\n scratch[tid] = sum;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }\n workgroupBarrier();\n }\n let mu = workgroupUniformLoad(&scratch[0]) / f32(D);\n var sq: f32 = 0.0;\n for (var i = tid; i < D; i = i + WG) {\n let dev = vbuf[i] - mu;\n sq = sq + dev * dev;\n }\n scratch[tid] = sq;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { scratch[tid] = scratch[tid] + scratch[tid + s]; }\n workgroupBarrier();\n }\n let inv = inverseSqrt(workgroupUniformLoad(&scratch[0]) / f32(D) + EPS);\n for (var i = tid; i < D; i = i + WG) {\n out[g * D + i] = gval(i) * (vbuf[i] - mu) * inv + bval(i);\n }\n}`;\n return runProbe(ctx.device, code, {\n wg: 256, outPerGroup: ADDLN_D, want: addLnWant(ADDLN_D, false), tol: 1e-3,\n });\n});\n\n// Attention replica, full output, with the reductions swapped for subgroup\n// ops (subgroupMax/subgroupAdd + elect + serial fold — decoder_mega IF_SG /\n// add_ln IF_SG shape; two separate partial arrays, no red[] reuse).\nregisterTest('adreno_probe3_attn_gen_sg', (ctx) => {\n if (!ctx.hasSubgroups) return { skip: true, reason: 'subgroups feature unavailable' };\n const code = /* wgsl */ `enable subgroups;\n${header(ATTN.WG)}\nconst D: u32 = ${ATTN.D}u;\nconst D4: u32 = ${ATTN.D4}u;\nconst H: u32 = ${ATTN.H}u;\nconst LEN: u32 = ${ATTN.LEN}u;\nconst JT: u32 = WG / D4;\nconst SCORES_CAP: u32 = 352u;\nconst SCALE: f32 = ${1 / Math.sqrt(ATTN.D)};\nfn elem(id: u32, salt: u32, g: u32) -> f32 { return (vhash(id, salt + 3u * g) - 512.0) / 512.0; }\nfn qvec(g: u32, h: u32, i4: u32) -> vec4<f32> {\n let base = h * 64u + i4 * 4u;\n return vec4<f32>(elem(base, 11u, g), elem(base + 1u, 11u, g), elem(base + 2u, 11u, g), elem(base + 3u, 11u, g));\n}\nfn kvvec(g: u32, h: u32, j: u32, i4: u32, salt: u32) -> vec4<f32> {\n let base = (j * H + h) * 64u + i4 * 4u;\n return vec4<f32>(elem(base, salt, g), elem(base + 1u, salt, g), elem(base + 2u, salt, g), elem(base + 3u, salt, g));\n}\nvar<workgroup> qs4: array<vec4<f32>, D4>;\nvar<workgroup> scores: array<f32, SCORES_CAP>;\nvar<workgroup> sgm: array<f32, WG / 4u>;\nvar<workgroup> sgs: array<f32, WG / 4u>;\nvar<workgroup> part: array<vec4<f32>, WG>;\n@compute @workgroup_size(${ATTN.WG})\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>,\n @builtin(subgroup_size) sgSize: u32) {\n let row = wid.x; let h = wid.y; let tid = lid.x;\n let gi = row * H + h;\n let sgId = tid / sgSize;\n let nSg = (WG + sgSize - 1u) / sgSize;\n for (var i = tid; i < D4; i = i + WG) { qs4[i] = qvec(row, h, i); }\n workgroupBarrier();\n var localMax: f32 = -1e30;\n for (var j = tid; j < LEN; j = j + WG) {\n var dot4 = vec4<f32>(0.0);\n for (var i = 0u; i < D4; i = i + 1u) { dot4 = dot4 + qs4[i] * kvvec(row, h, j, i, 22u); }\n let sc = (dot4.x + dot4.y + dot4.z + dot4.w) * SCALE;\n scores[j] = sc;\n localMax = max(localMax, sc);\n }\n let m1 = subgroupMax(localMax);\n if (subgroupElect()) { sgm[sgId] = m1; }\n workgroupBarrier(); // also publishes scores for phase 2\n var rowMax = sgm[0];\n for (var i = 1u; i < nSg; i = i + 1u) { rowMax = max(rowMax, sgm[i]); }\n var localSum: f32 = 0.0;\n for (var j = tid; j < LEN; j = j + WG) {\n let e = exp(scores[j] - rowMax);\n scores[j] = e;\n localSum = localSum + e;\n }\n let s2 = subgroupAdd(localSum);\n if (subgroupElect()) { sgs[sgId] = s2; }\n workgroupBarrier(); // publishes exp'd scores for phase 3\n var denom = sgs[0];\n for (var i = 1u; i < nSg; i = i + 1u) { denom = denom + sgs[i]; }\n let dq = tid % D4;\n let jg = tid / D4;\n var acc = vec4<f32>(0.0);\n if (jg < JT) {\n for (var j = jg; j < LEN; j = j + JT) {\n acc = acc + scores[j] * kvvec(row, h, j, dq, 33u);\n }\n }\n part[tid] = acc;\n workgroupBarrier();\n if (tid < D4) {\n var o = vec4<f32>(0.0);\n for (var g2 = 0u; g2 < JT; g2 = g2 + 1u) { o = o + part[g2 * D4 + tid]; }\n o = o / denom;\n let yoff = gi * D + tid * 4u;\n out[yoff] = o.x;\n out[yoff + 1u] = o.y;\n out[yoff + 2u] = o.z;\n out[yoff + 3u] = o.w;\n }\n}`;\n const cache = new Map();\n const want = (gi, lane) => {\n if (!cache.has(gi)) cache.set(gi, attnRef(gi));\n return cache.get(gi).out[lane];\n };\n return runProbe(ctx.device, code, {\n wg: ATTN.WG, outPerGroup: ATTN.D, want, tol: 1e-3, dispatchY: ATTN.H,\n });\n});\n\n// Attention replica with workgroupUniformLoad broadcasts (rowMax and denom),\n// tree reductions unchanged.\nregisterTest('adreno_probe3_attn_gen_uload', (ctx) => {\n const code = attnGenCode(false)\n .replace('let rowMax = red[0];\\n workgroupBarrier();', 'let rowMax = workgroupUniformLoad(&red[0]);')\n .replace('let denom = red[0];', 'let denom = workgroupUniformLoad(&red[0]);');\n if (!code.includes('workgroupUniformLoad')) throw new Error('uload rewrite did not apply');\n const cache = new Map();\n const want = (gi, lane) => {\n if (!cache.has(gi)) cache.set(gi, attnRef(gi));\n return cache.get(gi).out[lane];\n };\n return runProbe(ctx.device, code, {\n wg: ATTN.WG, outPerGroup: ATTN.D, want, tol: 1e-3, dispatchY: ATTN.H,\n });\n});\n\n// Mechanism A: round-1 naked sum tree + broadcast, but the partial comes\n// from a strided loop with NON-UNIFORM trip counts (2 iterations for\n// tid < 192, 1 for tid >= 192) — the delta add_ln adds over tree_sum_wg256.\nregisterTest('adreno_probe3_striped_sum_wg256', (ctx) => {\n const code = /* wgsl */ `${header(256)}\nconst D: u32 = ${ADDLN_D}u;\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(256)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n var sum: f32 = 0.0;\n for (var i = tid; i < D; i = i + WG) { sum = sum + (vhash(i, g) - 512.0) / 256.0; }\n red[tid] = sum;\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = red[tid] + red[tid + s]; }\n workgroupBarrier();\n }\n out[g * WG + tid] = red[0];\n}`;\n const want = (g) => {\n let s = 0;\n for (let i = 0; i < ADDLN_D; i++) s += xval(i, g);\n return s;\n };\n return runProbe(ctx.device, code, { wg: 256, outPerGroup: 256, want });\n});\n\n// Mechanism B: naked sum tree + broadcast, plus a SECOND shared array\n// written uniformly pre-reduction and read cross-wave post-broadcast.\nregisterTest('adreno_probe3_vbuf_sum_wg256', (ctx) => {\n const code = /* wgsl */ `${header(256)}\nvar<workgroup> vbuf: array<f32, WG>;\nvar<workgroup> red: array<f32, WG>;\n@compute @workgroup_size(256)\nfn main(@builtin(workgroup_id) wid: vec3<u32>, @builtin(local_invocation_id) lid: vec3<u32>) {\n let g = wid.x; let tid = lid.x;\n vbuf[tid] = vhash(tid, g);\n red[tid] = vhash(tid, g);\n workgroupBarrier();\n for (var s = WG / 2u; s > 0u; s = s >> 1u) {\n if (tid < s) { red[tid] = red[tid] + red[tid + s]; }\n workgroupBarrier();\n }\n out[g * WG + tid] = red[0] + vbuf[(tid + 64u) % WG];\n}`;\n const want = (g, lane) => sumWant(256)(g) + payload((lane + 64) % 256, g);\n return runProbe(ctx.device, code, { wg: 256, outPerGroup: 256, want });\n});\n\n// ------------------------------------------------------------- round 4 ---\n// The production fix (attention IF_SG + forced sg via autotune) shipped;\n// this reports what the engine's correctness probe decides on THIS device.\n// Expected: treeBug false on healthy devices, true on the affected Adreno\n// (where the app then forces sg at every reduction site). The kernel-level\n// verdicts live in attn_sg_* / addln (sg) / sg_golden / megasg_golden.\nregisterTest('adreno_probe4_detect', async (ctx) => {\n const { detectTreeReductionBug } = await import('../../engine/autotune.js');\n const treeBug = await detectTreeReductionBug(ctx.device);\n return {\n pass: typeof treeBug === 'boolean',\n detail: { treeBug, sgAvailable: !!ctx.hasSubgroups, willForceSg: treeBug && !!ctx.hasSubgroups },\n };\n});\n\n// ------------------------------------------------------------- round 5 ---\n// Hachimi-60 dims (d_model 576): the REAL add_ln sg kernel at D=576 —\n// WG 256 threads take 3/2 loop trips instead of moxhi-448's 2/2-or-1, and\n// the miscompile family is trip-count-sensitive. Mirrors runAddLnReal.\nregisterTest('adreno_probe5_addln_sg_d576', async (ctx) => {\n if (!ctx.hasSubgroups) return { skip: true, reason: 'subgroups feature unavailable' };\n const { device } = ctx;\n const d = 576;\n const rows = GROUPS;\n const x = new Float32Array(rows * d);\n const r = new Float32Array(rows * d);\n const gamma = new Float32Array(d);\n const beta = new Float32Array(d);\n for (let g = 0; g < rows; g++) {\n for (let i = 0; i < d; i++) {\n x[g * d + i] = xval(i, g);\n r[g * d + i] = rval(i, g);\n }\n }\n for (let i = 0; i < d; i++) { gamma[i] = gval(i); beta[i] = bval(i); }\n const cache = new Map();\n const want = (g, i) => {\n if (!cache.has(g)) {\n const v = new Float64Array(d);\n let sum = 0;\n for (let j = 0; j < d; j++) { v[j] = xval(j, g) + rval(j, g); sum += v[j]; }\n const mu = sum / d;\n let sq = 0;\n for (let j = 0; j < d; j++) sq += (v[j] - mu) * (v[j] - mu);\n const inv = 1 / Math.sqrt(sq / d + LN_EPS);\n cache.set(g, v.map((xx, j) => gval(j) * (xx - mu) * inv + bval(j)));\n }\n return cache.get(g)[i];\n };\n const pipeline = getPipeline(device, 'add_ln', addLnSource, {\n t: 'f32', wg: 256, sg: true, defines: { D: d, EPS: LN_EPS },\n });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const params = device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });\n new Uint32Array(params.getMappedRange()).set([rows, 0, 0, 0]);\n params.unmap();\n const bufs = [x, r, gamma, beta].map((a) => createBuffer(device, a, usage));\n const yBuf = device.createBuffer({ size: rows * d * 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [params, ...bufs, yBuf].map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n const tol = 1e-3;\n let badLanes = 0;\n let firstBad = null;\n const badPerRep = [];\n for (let rep = 0; rep < REPS; rep++) {\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(rows);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const got = new Float32Array(await readback(device, yBuf, rows * d * 4));\n let repBad = 0;\n for (let g = 0; g < rows; g++) {\n for (let i = 0; i < d; i++) {\n const w = want(g, i);\n if (!(Math.abs(got[g * d + i] - w) <= tol)) {\n repBad++;\n if (!firstBad) firstBad = { rep, g, lane: i, got: got[g * d + i], want: w };\n }\n }\n }\n badPerRep.push(repBad);\n badLanes += repBad;\n }\n for (const b of [params, ...bufs, yBuf]) b.destroy();\n return {\n pass: badLanes === 0,\n detail: { kernel: 'add_ln (real, f32, sg, D=576)', rows, d, reps: REPS, tol, badLanes, badPerRep, ...(firstBad ? { firstBad } : {}) },\n };\n});\n\n// ------------------------------------------------------------- round 6 ---\n// hachimi60 sg goldens read 0/30 (mega) and 10/30 (lean) on the affected\n// Adreno while every hachimi-dim f16 sg GEMV + add_ln@576 kernel passes.\n// Remaining lean-path kernels at hachimi dims, tested REAL, f32, CPU-checked:\n// attention (H8 D72 — D4 18, JT 7) short + long lens, and gemm_row_ln sg at\n// K=D=576 (the fused-LN b1 site; 576/WG loops turn 3-trip).\n\nconst smallF = (idx, salt) => (payload(idx & 0xfffff, salt) - 512) / 512;\n\n// Values from smallF are multiples of 1/512 in [-1, 1] — exact in f16, so\n// the f16 variants reuse the same f64 reference; only OUTPUT rounding needs\n// tolerance. toHalf packs an exact-f16 f32 array for storage.\nconst toHalf = (a) => {\n const h = new Uint16Array(a.length);\n for (let i = 0; i < a.length; i++) h[i] = f32ToF16(a[i]);\n return h;\n};\n\nasync function runAttnRealDims(ctx, { H, D, B, M, L, lens, sg, t = 'f32' }) {\n const { device } = ctx;\n const HD = H * D;\n const rows = B * M;\n const q = new Float32Array(rows * HD);\n const k = new Float32Array(B * L * HD);\n const v = new Float32Array(B * L * HD);\n for (let i = 0; i < q.length; i++) q[i] = smallF(i, 51);\n for (let i = 0; i < k.length; i++) k[i] = smallF(i, 52);\n for (let i = 0; i < v.length; i++) v[i] = smallF(i, 53);\n const scale = 1 / Math.sqrt(D);\n // f64 reference, all (b, m, h) rows\n const want = new Float64Array(rows * HD);\n for (let b = 0; b < B; b++) {\n for (let m = 0; m < M; m++) {\n const row = b * M + m;\n for (let h = 0; h < H; h++) {\n const len = lens[b];\n const scores = new Float64Array(len);\n for (let j = 0; j < len; j++) {\n let dot = 0;\n for (let d = 0; d < D; d++) {\n dot += q[row * HD + h * D + d] * k[(b * L + j) * HD + h * D + d];\n }\n scores[j] = dot * scale;\n }\n const mx = Math.max(...scores);\n const e = scores.map((x) => Math.exp(x - mx));\n const denom = e.reduce((a, x) => a + x, 0);\n for (let d = 0; d < D; d++) {\n let acc = 0;\n for (let j = 0; j < len; j++) acc += e[j] * v[(b * L + j) * HD + h * D + d];\n want[row * HD + h * D + d] = acc / denom;\n }\n }\n }\n }\n const pipeline = getPipeline(device, 'attention', attentionSource, {\n t, wg: 128, sg,\n defines: {\n H, D, SCORES_CAP: 352, ATTN_SCALE: scale,\n Q_STRIDE: HD, Q_OFF: 0, KV_STRIDE: HD, K_OFF: 0, V_OFF: 0,\n },\n });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const params = device.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });\n new Uint32Array(params.getMappedRange()).set([B, M, L, 1, 0, 0, 0, 0]);\n params.unmap();\n const elem = t === 'f16' ? 2 : 4;\n const bufs = [q, k, v].map((a) => createBuffer(device, t === 'f16' ? toHalf(a) : a, usage));\n const lensBuf = createBuffer(device, new Uint32Array(lens), usage);\n const yBuf = device.createBuffer({ size: rows * HD * elem, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [params, ...bufs, lensBuf, yBuf].map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n const tol = t === 'f16' ? 0.01 : 1e-3;\n let badLanes = 0;\n let firstBad = null;\n const badPerRep = [];\n for (let rep = 0; rep < REPS; rep++) {\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(rows, H);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const raw = await readback(device, yBuf, rows * HD * elem);\n const got = t === 'f16' ? expandF16(new Uint16Array(raw)) : new Float32Array(raw);\n let repBad = 0;\n for (let i = 0; i < want.length; i++) {\n if (!(Math.abs(got[i] - want[i]) <= tol)) {\n repBad++;\n if (!firstBad) firstBad = { rep, i, got: got[i], want: want[i] };\n }\n }\n badPerRep.push(repBad);\n badLanes += repBad;\n }\n for (const b of [params, ...bufs, lensBuf, yBuf]) b.destroy();\n return {\n pass: badLanes === 0,\n detail: { kernel: `attention (real, ${t}${sg ? ', sg' : ''}, H${H} D${D})`, B, M, L, lens: lens.join(','), reps: REPS, tol, badLanes, badPerRep, ...(firstBad ? { firstBad } : {}) },\n };\n}\n\nregisterTest('adreno_probe6_attn_sg_h60_short', (ctx) => (ctx.hasSubgroups\n ? runAttnRealDims(ctx, { H: 8, D: 72, B: 2, M: 16, L: 16, lens: [16, 9], sg: true })\n : { skip: true, reason: 'subgroups feature unavailable' }));\nregisterTest('adreno_probe6_attn_sg_h60_long', (ctx) => (ctx.hasSubgroups\n ? runAttnRealDims(ctx, { H: 8, D: 72, B: 2, M: 4, L: 224, lens: [224, 131], sg: true })\n : { skip: true, reason: 'subgroups feature unavailable' }));\n\n// gemm_row_ln sg at hachimi dims (K = D = 576): the fused-LN site b1 lean\n// decode routes through at fuseLnMaxB 4.\nregisterTest('adreno_probe6_rowln_sg_d576', async (ctx) => {\n if (!ctx.hasSubgroups) return { skip: true, reason: 'subgroups feature unavailable' };\n const { device } = ctx;\n const K = 576;\n const D = 576;\n const M = 64;\n const x = new Float32Array(M * K);\n const w = new Float32Array(K * D);\n const b = new Float32Array(D);\n const r = new Float32Array(M * D);\n const gamma = new Float32Array(D);\n const beta = new Float32Array(D);\n for (let i = 0; i < x.length; i++) x[i] = smallF(i, 61) * 2;\n for (let i = 0; i < w.length; i++) w[i] = smallF(i, 62);\n for (let i = 0; i < r.length; i++) r[i] = smallF(i, 63) * 2;\n for (let i = 0; i < D; i++) {\n b[i] = smallF(i, 64);\n gamma[i] = 1 + smallF(i, 65) / 2;\n beta[i] = smallF(i, 66);\n }\n const want = new Float64Array(M * D);\n for (let m = 0; m < M; m++) {\n const vrow = new Float64Array(D);\n let sum = 0;\n for (let n = 0; n < D; n++) {\n let dot = 0;\n for (let kk = 0; kk < K; kk++) dot += x[m * K + kk] * w[kk * D + n];\n vrow[n] = dot + b[n] + r[m * D + n];\n sum += vrow[n];\n }\n const mu = sum / D;\n let sq = 0;\n for (let n = 0; n < D; n++) sq += (vrow[n] - mu) * (vrow[n] - mu);\n const inv = 1 / Math.sqrt(sq / D + LN_EPS);\n for (let n = 0; n < D; n++) want[m * D + n] = gamma[n] * (vrow[n] - mu) * inv + beta[n];\n }\n const pipeline = getPipeline(device, 'gemm_row_ln', gemmRowLnSource, {\n t: 'f32', wg: 128, sg: true, defines: { KDIM: K, D, EPS: LN_EPS },\n });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const params = device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });\n new Uint32Array(params.getMappedRange()).set([M, 0, 0, 0]);\n params.unmap();\n const bufs = [x, w, b, r, gamma, beta].map((a) => createBuffer(device, a, usage));\n const yBuf = device.createBuffer({ size: M * D * 4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [params, ...bufs, yBuf].map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n const tol = 2e-3;\n let badLanes = 0;\n let firstBad = null;\n const badPerRep = [];\n for (let rep = 0; rep < REPS; rep++) {\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(M);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const got = new Float32Array(await readback(device, yBuf, M * D * 4));\n let repBad = 0;\n for (let i = 0; i < want.length; i++) {\n if (!(Math.abs(got[i] - want[i]) <= tol)) {\n repBad++;\n if (!firstBad) firstBad = { rep, i, got: got[i], want: want[i] };\n }\n }\n badPerRep.push(repBad);\n badLanes += repBad;\n }\n for (const bb of [params, ...bufs, yBuf]) bb.destroy();\n return {\n pass: badLanes === 0,\n detail: { kernel: 'gemm_row_ln (real, f32, sg, K=D=576)', M, reps: REPS, tol, badLanes, badPerRep, ...(firstBad ? { firstBad } : {}) },\n };\n});\n\n// ------------------------------------------------------------- round 7 ---\n// Round 6 (f32) passed everything at hachimi dims on the device, but\n// PRODUCTION runs f16 — if the second miscompile is f16-specific the f32\n// probes prove nothing. Same shapes, f16 storage (inputs exact in f16, same\n// f64 reference, tolerance covers output rounding only).\nregisterTest('adreno_probe7_attn_sg_h60_short_f16', (ctx) => (!ctx.hasSubgroups\n ? { skip: true, reason: 'subgroups feature unavailable' }\n : !ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runAttnRealDims(ctx, { H: 8, D: 72, B: 2, M: 16, L: 16, lens: [16, 9], sg: true, t: 'f16' })));\nregisterTest('adreno_probe7_attn_sg_h60_long_f16', (ctx) => (!ctx.hasSubgroups\n ? { skip: true, reason: 'subgroups feature unavailable' }\n : !ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runAttnRealDims(ctx, { H: 8, D: 72, B: 2, M: 4, L: 224, lens: [224, 131], sg: true, t: 'f16' })));\n// Moxhi-dim f16 sg attention passed on-device via attn_sg_*; this pins the\n// f16 × hachimi-dim cell of the matrix for add_ln too.\nregisterTest('adreno_probe7_addln_sg_d576_f16', async (ctx) => {\n if (!ctx.hasSubgroups) return { skip: true, reason: 'subgroups feature unavailable' };\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const { device } = ctx;\n const d = 576;\n const rows = GROUPS;\n const x = new Float32Array(rows * d);\n const r = new Float32Array(rows * d);\n const gamma = new Float32Array(d);\n const beta = new Float32Array(d);\n for (let g = 0; g < rows; g++) {\n for (let i = 0; i < d; i++) {\n x[g * d + i] = xval(i, g) / 2; // /2: keep f16-exact (multiples of 1/512)\n r[g * d + i] = rval(i, g) / 2;\n }\n }\n for (let i = 0; i < d; i++) { gamma[i] = gval(i); beta[i] = bval(i); }\n const cache = new Map();\n const want = (g, i) => {\n if (!cache.has(g)) {\n const v = new Float64Array(d);\n let sum = 0;\n for (let j = 0; j < d; j++) { v[j] = x[g * d + j] + r[g * d + j]; sum += v[j]; }\n const mu = sum / d;\n let sq = 0;\n for (let j = 0; j < d; j++) sq += (v[j] - mu) * (v[j] - mu);\n const inv = 1 / Math.sqrt(sq / d + LN_EPS);\n cache.set(g, v.map((xx, j) => gamma[j] * (xx - mu) * inv + beta[j]));\n }\n return cache.get(g)[i];\n };\n const pipeline = getPipeline(device, 'add_ln', addLnSource, {\n t: 'f16', wg: 256, sg: true, defines: { D: d, EPS: LN_EPS },\n });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const params = device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });\n new Uint32Array(params.getMappedRange()).set([rows, 0, 0, 0]);\n params.unmap();\n const bufs = [x, r, gamma, beta].map((a) => createBuffer(device, toHalf(a), usage));\n const yBuf = device.createBuffer({ size: rows * d * 2, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [params, ...bufs, yBuf].map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n const tol = 0.02;\n let badLanes = 0;\n let firstBad = null;\n const badPerRep = [];\n for (let rep = 0; rep < REPS; rep++) {\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(rows);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const got = expandF16(new Uint16Array(await readback(device, yBuf, rows * d * 2)));\n let repBad = 0;\n for (let g = 0; g < rows; g++) {\n for (let i = 0; i < d; i++) {\n const w = want(g, i);\n if (!(Math.abs(got[g * d + i] - w) <= tol)) {\n repBad++;\n if (!firstBad) firstBad = { rep, g, lane: i, got: got[g * d + i], want: w };\n }\n }\n }\n badPerRep.push(repBad);\n badLanes += repBad;\n }\n for (const b of [params, ...bufs, yBuf]) b.destroy();\n return {\n pass: badLanes === 0,\n detail: { kernel: 'add_ln (real, f16, sg, D=576)', rows, d, reps: REPS, tol, badLanes, badPerRep, ...(firstBad ? { firstBad } : {}) },\n };\n});\n\n// ------------------------------------------------------------- round 8 ---\n// Encoder blocked attention at HACHIMI dims: D=72 → D4=18 → default QB=14\n// (workgroup 252 threads) — an entirely different tile geometry than moxhi's\n// QB16/224 that the on-device attn_block tests covered. The hachimi sg\n// goldens share the encoder between their mega (0/30) and lean (10/30) arms\n// while every decode kernel checks out — encoder kernels are the remaining\n// suspects.\nasync function runAttnBlockDims(ctx, { H, D, QB, JB, B, M, L, lens, t = 'f16' }) {\n const { device } = ctx;\n const HD = H * D;\n const rows = B * M;\n const q = new Float32Array(rows * HD);\n const k = new Float32Array(B * L * HD);\n const v = new Float32Array(B * L * HD);\n for (let i = 0; i < q.length; i++) q[i] = smallF(i, 71);\n for (let i = 0; i < k.length; i++) k[i] = smallF(i, 72);\n for (let i = 0; i < v.length; i++) v[i] = smallF(i, 73);\n const scale = 1 / Math.sqrt(D);\n const want = new Float64Array(rows * HD);\n for (let b = 0; b < B; b++) {\n for (let m = 0; m < M; m++) {\n const row = b * M + m;\n for (let h = 0; h < H; h++) {\n const len = lens[b];\n const scores = new Float64Array(len);\n for (let j = 0; j < len; j++) {\n let dot = 0;\n for (let d = 0; d < D; d++) {\n dot += q[row * HD + h * D + d] * k[(b * L + j) * HD + h * D + d];\n }\n scores[j] = dot * scale;\n }\n const mx = Math.max(...scores);\n const e = scores.map((x) => Math.exp(x - mx));\n const denom = e.reduce((a, x) => a + x, 0);\n for (let d = 0; d < D; d++) {\n let acc = 0;\n for (let j = 0; j < len; j++) acc += e[j] * v[(b * L + j) * HD + h * D + d];\n want[row * HD + h * D + d] = acc / denom;\n }\n }\n }\n }\n const pipeline = getPipeline(device, 'attention_block', attentionBlockSource, {\n t,\n defines: {\n H, D, QB, JB, ATTN_SCALE: scale,\n Q_STRIDE: HD, Q_OFF: 0, KV_STRIDE: HD, K_OFF: 0, V_OFF: 0,\n PACKED: false, NOPACKED: true,\n },\n });\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const params = device.createBuffer({ size: 32, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });\n new Uint32Array(params.getMappedRange()).set([B, M, L, 1, 0, 0, 0, 0]);\n params.unmap();\n const elem = t === 'f16' ? 2 : 4;\n const bufs = [q, k, v].map((a) => createBuffer(device, t === 'f16' ? toHalf(a) : a, usage));\n const lensBuf = createBuffer(device, new Uint32Array(lens), usage);\n const yBuf = device.createBuffer({ size: rows * HD * elem, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [params, ...bufs, lensBuf, yBuf].map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n const tol = t === 'f16' ? 0.01 : 1e-3;\n let badLanes = 0;\n let firstBad = null;\n const badPerRep = [];\n for (let rep = 0; rep < REPS; rep++) {\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(Math.ceil(M / QB), H, B);\n pass.end();\n device.queue.submit([encoder.finish()]);\n const raw = await readback(device, yBuf, rows * HD * elem);\n const got = t === 'f16' ? expandF16(new Uint16Array(raw)) : new Float32Array(raw);\n let repBad = 0;\n for (let i = 0; i < want.length; i++) {\n if (!(Math.abs(got[i] - want[i]) <= tol)) {\n repBad++;\n if (!firstBad) firstBad = { rep, i, got: got[i], want: want[i] };\n }\n }\n badPerRep.push(repBad);\n badLanes += repBad;\n }\n for (const b of [params, ...bufs, lensBuf, yBuf]) b.destroy();\n return {\n pass: badLanes === 0,\n detail: { kernel: `attention_block (real, ${t}, H${H} D${D} QB${QB} JB${JB})`, B, M, L, lens: lens.join(','), reps: REPS, tol, badLanes, badPerRep, ...(firstBad ? { firstBad } : {}) },\n };\n}\n\nregisterTest('adreno_probe8_attnblock_h60_f16', (ctx) => (!ctx.hasF16\n ? { skip: true, reason: 'no shader-f16' }\n : runAttnBlockDims(ctx, { H: 8, D: 72, QB: 14, JB: 32, B: 2, M: 33, L: 33, lens: [33, 17], t: 'f16' })));\nregisterTest('adreno_probe8_attnblock_h60_big_f16', (ctx) => (!ctx.hasF16\n ? { skip: true, reason: 'no shader-f16' }\n : runAttnBlockDims(ctx, { H: 8, D: 72, QB: 14, JB: 32, B: 2, M: 96, L: 96, lens: [96, 49], t: 'f16' })));\n\n// Weights-bytes integrity: FNV-1a over every fetched shard of both models.\n// A deterministic 10/30 hachimi verdict with all kernels clean could also be\n// corrupted-but-cached weight bytes on the device — compare this hash across\n// devices (must be identical; the files are identical on the server).\nregisterTest('adreno_probe8_weights_hash', async () => {\n const fnv = (h, bytes) => {\n for (let i = 0; i < bytes.length; i++) {\n h ^= bytes[i];\n h = Math.imul(h, 16777619) >>> 0;\n }\n return h;\n };\n const hashModel = async (root) => {\n const manifest = await (await fetch(`${root}/manifest.json`)).json();\n const bins = manifest.bins ?? ['weights.bin'];\n let h = 2166136261 >>> 0;\n let bytes = 0;\n for (const bin of bins) {\n const buf = new Uint8Array(await (await fetch(`${root}/${bin}`)).arrayBuffer());\n bytes += buf.length;\n h = fnv(h, buf);\n }\n return { hash: h.toString(16), bytes, bins: bins.length };\n };\n const detail = { moxhi: await hashModel('/weights') };\n try {\n detail.hachimi60 = await hashModel('/weights/hachimi60');\n } catch (err) {\n detail.hachimi60 = { error: String(err?.message ?? err) };\n }\n return { pass: true, detail };\n});\n\n// Failure-surface map for the attention_block h60 break (QB14/D72/f16 FAILS\n// on the device): vary one axis at a time to find a safe routing.\nregisterTest('adreno_probe8b_attnblock_h60_qb8', (ctx) => (!ctx.hasF16\n ? { skip: true, reason: 'no shader-f16' }\n : runAttnBlockDims(ctx, { H: 8, D: 72, QB: 8, JB: 32, B: 2, M: 33, L: 33, lens: [33, 17], t: 'f16' })));\nregisterTest('adreno_probe8b_attnblock_h60_qb12', (ctx) => (!ctx.hasF16\n ? { skip: true, reason: 'no shader-f16' }\n : runAttnBlockDims(ctx, { H: 8, D: 72, QB: 12, JB: 32, B: 2, M: 33, L: 33, lens: [33, 17], t: 'f16' })));\nregisterTest('adreno_probe8b_attnblock_h60_qb14_jb16', (ctx) => (!ctx.hasF16\n ? { skip: true, reason: 'no shader-f16' }\n : runAttnBlockDims(ctx, { H: 8, D: 72, QB: 14, JB: 16, B: 2, M: 33, L: 33, lens: [33, 17], t: 'f16' })));\nregisterTest('adreno_probe8b_attnblock_h60_qb14_f32', (ctx) =>\n runAttnBlockDims(ctx, { H: 8, D: 72, QB: 14, JB: 32, B: 2, M: 33, L: 33, lens: [33, 17], t: 'f32' }));\n// QB14 at MOXHI head dim (D 56, 196 threads): separates the QB axis from D.\nregisterTest('adreno_probe8b_attnblock_d56_qb14', (ctx) => (!ctx.hasF16\n ? { skip: true, reason: 'no shader-f16' }\n : runAttnBlockDims(ctx, { H: 8, D: 56, QB: 14, JB: 32, B: 2, M: 33, L: 33, lens: [33, 17], t: 'f16' })));\n"],"file":"adreno_probe-CjpGrE_r.js"}
assets/argmax-CNtdxM2K.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as g}from"./debug-Cn7EHWtJ.js";import{c as b,r as P}from"./gpu-utils-BTh3AGTJ.js";import{g as V,f as I}from"./pipelines-DD24nEJg.js";import{p as K}from"./math-DNG-wiC0.js";import{V as q,B as j,P as G,e as d,R as M}from"./constants-C8VbFpic.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";const u=q,c=j,H=256;function J(n){let a=n>>>0;return()=>{a=a+1831565813|0;let t=Math.imul(a^a>>>15,1|a);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296}}function B(n,a){const t=new Float32Array(n*u);return a.forEach((s,o)=>{for(const[r,e]of s)t[o*u+r]=Math.fround(e)}),t}function R(n,a,t){n[a*c+(t>>5)]|=1<<(t&31)}function w(n,a,t){return n[a*c+(t>>5)]>>>(t&31)&1}function p(n,{B:a,bias:t,bitmask:s,done:o}){const r=new Uint32Array(n.length*a);let e=s,i=o;return n.forEach((l,f)=>{const k=K(l,t,e,i,{B:a,V:u,penalty:M});r.set(k.tokens,f*a),e=k.newBitmaskWords,i=k.newDone}),{tokens:r,done:i,bitmask:e}}function Q(n,a){const t=n.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});return new Uint32Array(t.getMappedRange()).set(a),t.unmap(),t}async function m(n,{B:a,stepsLogits:t,bias:s,bitmask:o,done:r}){const e=t.length,i=V(n,"argmax_penalty",I,{wg:H,defines:{V:u,EOS:d,PAD:G,PENALTY:M,MASK_WORDS:c}}),l=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC,f=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,k=b(n,s??new Float32Array(u),f),U=b(n,o??new Uint32Array(a*c),l),_=b(n,r??new Uint32Array(a),l),h=b(n,new Uint32Array(e*a).fill(3735928559),l),O=[],T=n.createCommandEncoder(),A=T.beginComputePass();A.setPipeline(i),t.forEach((x,W)=>{const S=Q(n,[a,W,0,0]),E=b(n,x,f);O.push(S,E);const Y=n.createBindGroup({layout:i.getBindGroupLayout(0),entries:[S,E,k,U,_,h].map((N,z)=>({binding:z,resource:{buffer:N}}))});A.setBindGroup(0,Y),A.dispatchWorkgroups(a)}),A.end(),n.queue.submit([T.finish()]);const F=new Uint32Array(await P(n,h,e*a*4)),C=new Uint32Array(await P(n,_,a*4)),L=new Uint32Array(await P(n,U,a*c*4));for(const x of[k,U,_,h,...O])x.destroy();return{tokens:F,done:C,bitmask:L}}function D(n,a){let t=0,s=-1;for(let o=0;o<a.length;o++)n[o]!==a[o]&&(t++,s<0&&(s=o));return{mismatches:t,first:s}}function y(n,a,t,s=[]){const o={...t};let r=!0;for(const[e,i]of[["tokens",a.tokens],["done",a.done],["bitmask",a.bitmask]]){const{mismatches:l,first:f}=D(n[e],i);l>0&&(r=!1,o[e]={mismatches:l,first:f,got:n[e][f],want:i[f]})}for(const[e,i,l]of s)i!==l&&(r=!1,o[e]={got:i,want:l});return{pass:r,detail:o}}g("argmax_random",async({device:n})=>{const t=J(1207),s=new Float32Array(4*u);for(let i=0;i<s.length;i++)s[i]=Math.fround((t()-.5)*20);const r=await m(n,{...{B:4,bias:null,bitmask:null,done:null},stepsLogits:[s]}),e=p([s],{B:4,bias:new Float32Array(u),bitmask:new Uint32Array(4*c),done:new Uint32Array(4)});return y(r,e,{kernel:"argmax_penalty",B:4,V:u,tokens:Array.from(r.tokens)})});g("argmax_penalty_flip",async({device:n})=>{const t=B(1,[[[7,5],[100,4.5]]]),s=new Uint32Array(1*c);R(s,0,7);const o=await m(n,{B:1,stepsLogits:[t],bias:null,bitmask:s,done:null}),r=p([t],{B:1,bias:new Float32Array(u),bitmask:s,done:new Uint32Array(1)});return y(o,r,{kernel:"argmax_penalty",case:"penalty_flip"},[["token",o.tokens[0],100]])});g("argmax_bias",async({device:n})=>{const t=B(1,[[[10,3],[200,2.5]]]),s=new Float32Array(u);s[200]=1;const o=await m(n,{B:1,stepsLogits:[t],bias:null,bitmask:null,done:null}),r=await m(n,{B:1,stepsLogits:[t],bias:s,bitmask:null,done:null}),e=p([t],{B:1,bias:s,bitmask:new Uint32Array(1*c),done:new Uint32Array(1)});return y(r,e,{kernel:"argmax_penalty",case:"bias"},[["zeroBiasToken",o.tokens[0],10],["biasedToken",r.tokens[0],200]])});g("argmax_done_row",async({device:n})=>{const t=B(3,[[[6,2]],[[7,9]],[[500,1.5]]]),s=new Uint32Array(3*c);R(s,1,7),R(s,1,12345);const o=Uint32Array.of(0,1,0),r=Uint32Array.from(s),e=await m(n,{B:3,stepsLogits:[t],bias:null,bitmask:s,done:o}),i=p([t],{B:3,bias:new Float32Array(u),bitmask:s,done:o}),l=D(e.bitmask.slice(c,2*c),r.slice(c,2*c));return y(e,i,{kernel:"argmax_penalty",case:"done_row"},[["row0Token",e.tokens[0],6],["row1Token",e.tokens[1],G],["row2Token",e.tokens[2],500],["row1Done",e.done[1],1],["row1MaskMismatches",l.mismatches,0],["row0Bit6",w(e.bitmask,0,6),1],["row2Bit500",w(e.bitmask,2,500),1]])});g("argmax_eos_then_pad",async({device:n})=>{const t=B(2,[[[d,6]],[[40,5],[41,4.5]]]),s=B(2,[[[5,7]],[[40,5],[41,4.5]]]),o=await m(n,{B:2,stepsLogits:[t,s],bias:null,bitmask:null,done:null}),r=p([t,s],{B:2,bias:new Float32Array(u),bitmask:new Uint32Array(2*c),done:new Uint32Array(2)});return y(o,r,{kernel:"argmax_penalty",case:"eos_then_pad"},[["t0Row0",o.tokens[0],d],["t0Row1",o.tokens[1],40],["t1Row0",o.tokens[2],G],["t1Row1",o.tokens[3],41],["row0Done",o.done[0],1],["row1Done",o.done[1],0],["row0EosBit",w(o.bitmask,0,d),1],["row0NoBit5",w(o.bitmask,0,5),0],["row1Bit40",w(o.bitmask,1,40),1],["row1Bit41",w(o.bitmask,1,41),1]])});g("argmax_tie_break",async({device:n})=>{const t=B(1,[[[100,7.5],[2e4,7.5]]]),s=await m(n,{B:1,stepsLogits:[t],bias:null,bitmask:null,done:null}),o=p([t],{B:1,bias:new Float32Array(u),bitmask:new Uint32Array(1*c),done:new Uint32Array(1)});return y(s,o,{kernel:"argmax_penalty",case:"tie_break"},[["token",s.tokens[0],100]])});
2
+ //# sourceMappingURL=argmax-CNtdxM2K.js.map
assets/argmax-CNtdxM2K.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"argmax-CNtdxM2K.js","sources":["../../src/debug/tests/argmax.js"],"sourcesContent":["// GPU penalty+argmax+writeback kernel vs the JS reference — EXACT integer\n// comparisons (no tolerance): token picks, done flags, and bitmask words must\n// match penaltyArgmaxRef bit-for-bit (the ref frounds every op, mirroring the\n// kernel's f32 adds/divides/multiplies). Crafted cases also assert hard-coded\n// winners so a bug shared by ref and kernel can't hide.\n// Per-call uniform/bind-group creation is test-only plumbing — engine-level\n// uniform management arrives in Tasks 13-14.\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback } from '../gpu-utils.js';\nimport { getPipeline } from '../../engine/pipelines.js';\nimport { penaltyArgmaxRef } from '../../reference/math.js';\nimport { VOCAB, EOS, PAD, REP_PENALTY, BITMASK_WORDS } from '../../engine/constants.js';\nimport argmaxSource from '../../engine/kernels/argmax_penalty.wgsl?raw';\n\nconst V = VOCAB;\nconst WORDS = BITMASK_WORDS;\nconst WG = 256;\n\nfunction mulberry32(seed) {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n// Float32Array [B·V]: rows[b] = [[v, logit], ...], unlisted lanes 0.\nfunction craftLogits(B, rows) {\n const a = new Float32Array(B * V);\n rows.forEach((entries, b) => {\n for (const [v, x] of entries) a[b * V + v] = Math.fround(x);\n });\n return a;\n}\n\nfunction setBit(mask, b, v) { mask[b * WORDS + (v >> 5)] |= 1 << (v & 31); }\nfunction getBit(mask, b, v) { return (mask[b * WORDS + (v >> 5)] >>> (v & 31)) & 1; }\n\n// Chain the reference over sequential steps (bitmask/done carry over).\n// Returns {tokens: Uint32Array[steps·B] (ring layout t·B+b), done, bitmask}.\nfunction refChain(stepsLogits, { B, bias, bitmask, done }) {\n const tokens = new Uint32Array(stepsLogits.length * B);\n let mask = bitmask, dn = done;\n stepsLogits.forEach((logits, t) => {\n const out = penaltyArgmaxRef(logits, bias, mask, dn, { B, V, penalty: REP_PENALTY });\n tokens.set(out.tokens, t * B);\n mask = out.newBitmaskWords;\n dn = out.newDone;\n });\n return { tokens, done: dn, bitmask: mask };\n}\n\nfunction makeUniform(device, vals) {\n const buf = device.createBuffer({\n size: 16,\n usage: GPUBufferUsage.UNIFORM,\n mappedAtCreation: true,\n });\n new Uint32Array(buf.getMappedRange()).set(vals);\n buf.unmap();\n return buf;\n}\n\n// Run stepsLogits.length sequential dispatches sharing bitmask/done/token-ring\n// state (one pass — WebGPU orders storage writes between dispatches, and queue\n// order covers cross-dispatch bitmask visibility). Ring is sentinel-filled so\n// a wrong t·B+b slot or a missed write fails the exact compare.\nasync function runArgmax(device, { B, stepsLogits, bias, bitmask, done }) {\n const tMax = stepsLogits.length;\n const pipeline = getPipeline(device, 'argmax_penalty', argmaxSource, {\n wg: WG, defines: { V, EOS, PAD, PENALTY: REP_PENALTY, MASK_WORDS: WORDS },\n });\n const rw = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\n const ro = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const biasBuf = createBuffer(device, bias ?? new Float32Array(V), ro);\n const maskBuf = createBuffer(device, bitmask ?? new Uint32Array(B * WORDS), rw);\n const doneBuf = createBuffer(device, done ?? new Uint32Array(B), rw);\n const ringBuf = createBuffer(device, new Uint32Array(tMax * B).fill(0xdeadbeef), rw);\n\n const scratch = [];\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n stepsLogits.forEach((logits, t) => {\n const params = makeUniform(device, [B, t, 0, 0]);\n const logitsBuf = createBuffer(device, logits, ro);\n scratch.push(params, logitsBuf);\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [params, logitsBuf, biasBuf, maskBuf, doneBuf, ringBuf]\n .map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(B);\n });\n pass.end();\n device.queue.submit([encoder.finish()]);\n\n const tokens = new Uint32Array(await readback(device, ringBuf, tMax * B * 4));\n const doneOut = new Uint32Array(await readback(device, doneBuf, B * 4));\n const maskOut = new Uint32Array(await readback(device, maskBuf, B * WORDS * 4));\n for (const b of [biasBuf, maskBuf, doneBuf, ringBuf, ...scratch]) b.destroy();\n return { tokens, done: doneOut, bitmask: maskOut };\n}\n\nfunction diffU32(got, want) {\n let mismatches = 0, first = -1;\n for (let i = 0; i < want.length; i++) {\n if (got[i] !== want[i]) {\n mismatches++;\n if (first < 0) first = i;\n }\n }\n return { mismatches, first };\n}\n\n// Exact-compare GPU state against the chained ref plus hard-coded expectations\n// (`expect` = [name, gotValue, wantValue] triples).\nfunction report(gpu, ref, extra, expectations = []) {\n const detail = { ...extra };\n let pass = true;\n for (const [field, w] of [['tokens', ref.tokens], ['done', ref.done], ['bitmask', ref.bitmask]]) {\n const { mismatches, first } = diffU32(gpu[field], w);\n if (mismatches > 0) {\n pass = false;\n detail[field] = { mismatches, first, got: gpu[field][first], want: w[first] };\n }\n }\n for (const [name, got, want] of expectations) {\n if (got !== want) {\n pass = false;\n detail[name] = { got, want };\n }\n }\n return { pass, detail };\n}\n\nregisterTest('argmax_random', async ({ device }) => {\n const B = 4;\n const rng = mulberry32(1207);\n const logits = new Float32Array(B * V);\n for (let i = 0; i < logits.length; i++) logits[i] = Math.fround((rng() - 0.5) * 20);\n const args = { B, bias: null, bitmask: null, done: null };\n const gpu = await runArgmax(device, { ...args, stepsLogits: [logits] });\n const ref = refChain([logits], {\n B, bias: new Float32Array(V), bitmask: new Uint32Array(B * WORDS), done: new Uint32Array(B),\n });\n return report(gpu, ref, { kernel: 'argmax_penalty', B, V, tokens: Array.from(gpu.tokens) });\n});\n\nregisterTest('argmax_penalty_flip', async ({ device }) => {\n // Seen 5.0 → 5/1.2 ≈ 4.1667 loses to unseen 4.5: only the pre-set bit\n // can make 100 win.\n const B = 1;\n const logits = craftLogits(B, [[[7, 5.0], [100, 4.5]]]);\n const bitmask = new Uint32Array(B * WORDS);\n setBit(bitmask, 0, 7);\n const gpu = await runArgmax(device, { B, stepsLogits: [logits], bias: null, bitmask, done: null });\n const ref = refChain([logits], {\n B, bias: new Float32Array(V), bitmask, done: new Uint32Array(B),\n });\n return report(gpu, ref, { kernel: 'argmax_penalty', case: 'penalty_flip' },\n [['token', gpu.tokens[0], 100]]);\n});\n\nregisterTest('argmax_bias', async ({ device }) => {\n // Same logits, zero vs crafted bias — the bias must change the winner.\n const B = 1;\n const logits = craftLogits(B, [[[10, 3.0], [200, 2.5]]]);\n const bias = new Float32Array(V);\n bias[200] = 1.0; // 2.5 + 1.0 = 3.5 > 3.0\n const zero = await runArgmax(device, { B, stepsLogits: [logits], bias: null, bitmask: null, done: null });\n const biased = await runArgmax(device, { B, stepsLogits: [logits], bias, bitmask: null, done: null });\n const ref = refChain([logits], {\n B, bias, bitmask: new Uint32Array(B * WORDS), done: new Uint32Array(B),\n });\n return report(biased, ref, { kernel: 'argmax_penalty', case: 'bias' }, [\n ['zeroBiasToken', zero.tokens[0], 10],\n ['biasedToken', biased.tokens[0], 200],\n ]);\n});\n\nregisterTest('argmax_done_row', async ({ device }) => {\n // done[1] pre-set → row 1 emits PAD and its bitmask words stay untouched;\n // rows 0 and 2 proceed normally.\n const B = 3;\n const logits = craftLogits(B, [[[6, 2.0]], [[7, 9.0]], [[500, 1.5]]]);\n const bitmask = new Uint32Array(B * WORDS);\n setBit(bitmask, 1, 7);\n setBit(bitmask, 1, 12345);\n const done = Uint32Array.of(0, 1, 0);\n const maskBefore = Uint32Array.from(bitmask);\n const gpu = await runArgmax(device, { B, stepsLogits: [logits], bias: null, bitmask, done });\n const ref = refChain([logits], {\n B, bias: new Float32Array(V), bitmask, done,\n });\n const row1Unchanged = diffU32(gpu.bitmask.slice(WORDS, 2 * WORDS), maskBefore.slice(WORDS, 2 * WORDS));\n return report(gpu, ref, { kernel: 'argmax_penalty', case: 'done_row' }, [\n ['row0Token', gpu.tokens[0], 6],\n ['row1Token', gpu.tokens[1], PAD],\n ['row2Token', gpu.tokens[2], 500],\n ['row1Done', gpu.done[1], 1],\n ['row1MaskMismatches', row1Unchanged.mismatches, 0],\n ['row0Bit6', getBit(gpu.bitmask, 0, 6), 1],\n ['row2Bit500', getBit(gpu.bitmask, 2, 500), 1],\n ]);\n});\n\nregisterTest('argmax_eos_then_pad', async ({ device }) => {\n // Two sequential dispatches sharing GPU state.\n // Row 0: picks EOS at t=0 → done; at t=1 (where v=5 would win) it must emit\n // PAD and set NO new bit.\n // Row 1: t=0 winner v=40; t=1 re-offers 40 (5.0) with runner-up 41 (4.5) —\n // 40 wins again UNLESS its t=0 bit persisted into the t=1 dispatch\n // (5/1.2 ≈ 4.1667 < 4.5), proving cross-dispatch bitmask writeback.\n const B = 2;\n const t0 = craftLogits(B, [[[EOS, 6.0]], [[40, 5.0], [41, 4.5]]]);\n const t1 = craftLogits(B, [[[5, 7.0]], [[40, 5.0], [41, 4.5]]]);\n const gpu = await runArgmax(device, { B, stepsLogits: [t0, t1], bias: null, bitmask: null, done: null });\n const ref = refChain([t0, t1], {\n B, bias: new Float32Array(V), bitmask: new Uint32Array(B * WORDS), done: new Uint32Array(B),\n });\n return report(gpu, ref, { kernel: 'argmax_penalty', case: 'eos_then_pad' }, [\n ['t0Row0', gpu.tokens[0 * B + 0], EOS],\n ['t0Row1', gpu.tokens[0 * B + 1], 40],\n ['t1Row0', gpu.tokens[1 * B + 0], PAD],\n ['t1Row1', gpu.tokens[1 * B + 1], 41],\n ['row0Done', gpu.done[0], 1],\n ['row1Done', gpu.done[1], 0],\n ['row0EosBit', getBit(gpu.bitmask, 0, EOS), 1],\n ['row0NoBit5', getBit(gpu.bitmask, 0, 5), 0],\n ['row1Bit40', getBit(gpu.bitmask, 1, 40), 1],\n ['row1Bit41', getBit(gpu.bitmask, 1, 41), 1],\n ]);\n});\n\nregisterTest('argmax_tie_break', async ({ device }) => {\n // Two exactly-equal maxima (7.5 is exact in f32) far apart, landing in\n // DIFFERENT threads' strides (100 % 256 = 100, 20000 % 256 = 32) — the tie\n // must be broken in the reduction comparator, not within one thread's scan.\n const B = 1;\n const logits = craftLogits(B, [[[100, 7.5], [20000, 7.5]]]);\n const gpu = await runArgmax(device, { B, stepsLogits: [logits], bias: null, bitmask: null, done: null });\n const ref = refChain([logits], {\n B, bias: new Float32Array(V), bitmask: new Uint32Array(B * WORDS), done: new Uint32Array(B),\n });\n return report(gpu, ref, { kernel: 'argmax_penalty', case: 'tie_break' },\n [['token', gpu.tokens[0], 100]]);\n});\n"],"names":["V","VOCAB","WORDS","BITMASK_WORDS","WG","mulberry32","seed","craftLogits","B","rows","a","entries","b","v","x","setBit","mask","getBit","refChain","stepsLogits","bias","bitmask","done","tokens","dn","logits","t","out","penaltyArgmaxRef","REP_PENALTY","makeUniform","device","vals","buf","runArgmax","tMax","pipeline","getPipeline","argmaxSource","EOS","PAD","rw","ro","biasBuf","createBuffer","maskBuf","doneBuf","ringBuf","scratch","encoder","pass","params","logitsBuf","bindGroup","buffer","binding","readback","doneOut","maskOut","diffU32","got","want","mismatches","first","i","report","gpu","ref","extra","expectations","detail","field","w","name","registerTest","rng","zero","biased","maskBefore","row1Unchanged","t0","t1"],"mappings":"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"}
assets/argmax_fuse-DcdFediE.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as P}from"./debug-Cn7EHWtJ.js";import{c as _,r as R}from"./gpu-utils-BTh3AGTJ.js";import{h as J,i as X,j as Z}from"./pipelines-DD24nEJg.js";import{l as j,q as M}from"./weights-B-okS09o.js";import{l as K,t as v}from"./tokenizer-Ex1u7wXD.js";import{t as H}from"./generate-C4ruG1zm.js";import{r as tt}from"./encoder-DX8MOfcH.js";import{c as st}from"./decoder-DI6VDxxO.js";import{t as et}from"./profile-DdyBUdtB.js";import{p as Q}from"./bench-C8ITpm5I.js";import{f as G}from"./f16-wKKZr58e.js";import{D as ot,V as nt,P as W,B as at}from"./constants-C8VbFpic.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./chapter3k-Bxq8ds-a.js";const U=nt,T=ot,F=at,rt=64,q=Math.ceil(U/rt);function ft(t){let e=t>>>0;return()=>{e=e+1831565813|0;let s=Math.imul(e^e>>>15,1|e);return s=s+Math.imul(s^s>>>7,61|s)^s,((s^s>>>14)>>>0)/4294967296}}const x=(t,e,s)=>{t[e*F+(s>>5)]|=1<<(s&31)},C=(t,e,s)=>t[e*F+(s>>>5)]>>>(s&31)&1;function it(t,e){let s=0,n=-1;for(let f=0;f<e.length;f++)t[f]!==e[f]&&(s++,n<0&&(n=f));return{mismatches:s,first:n}}async function z(t,{fused:e,wq8:s,M:n,x:f,w:k,lbias:p,bitmask:b,done:y,t:r,tm8:i}){const m=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC,d=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,a=_(t,f,d),h=_(t,s?k.packed:k.half,d),u=s?_(t,k.scales,d):null,w=_(t,p,d),B=_(t,b,m),c=_(t,y,m),A=_(t,new Uint32Array((r+1)*n).fill(3735928559),m),S=e?null:t.createBuffer({size:n*U*4,usage:m}),O=e?t.createBuffer({size:n*q*8,usage:m}):null,o={t:"f16",outT:"f32",wt:!0,tiled:!0,...s?{wq8:!0}:{},tm8:i},l=[],g=t.createCommandEncoder(),D=g.beginComputePass();l.push(...J(t,D,{x:a,w:h,...s?{scales:u}:{},y:S,...e?{fusedArgmax:{partials:O,lbias:w,seen:B}}:{},M:n,K:T,N:U,flags:o}).scratch),l.push(...(e?X(t,D,{partials:O,bitmask:B,done:c,tokens:A,B:n,t:r,NT:q}):Z(t,D,{logits:S,bias:w,bitmask:B,done:c,tokens:A,B:n,t:r})).scratch),D.end(),t.queue.submit([g.finish()]);const Y=new Uint32Array(await R(t,A,(r+1)*n*4)),I=new Uint32Array(await R(t,c,n*4)),L=new Uint32Array(await R(t,B,n*F*4));for(const $ of[a,h,u,w,B,c,A,S,O,...l])$?.destroy();return{tokens:Y.subarray(r*n),done:I,bitmask:L}}async function V(t,{wq8:e,tm8:s,seed:n}){const{device:f}=t,k=ft(n),p=65,b=2,y=new Uint16Array(p*T);for(let o=0;o<y.length;o++)y[o]=G(k()-.5);const r=new Float32Array(U*T);for(let o=0;o<r.length;o++)r[o]=k()-.5;const i=4097,m=[4098,12e3,U-1];for(const o of m)r.copyWithin(o*T,i*T,i*T+T);const d=new Float32Array(U);for(let o=0;o<U;o++)d[o]=k()-.5;for(const o of[i,...m])d[o]=50;let a;if(e)a=M(r,U,T);else{const o=new Uint16Array(U*T);for(let l=0;l<r.length;l++)o[l]=G(r[l]);a={half:o}}const h=new Set([i,...m]),u=new Uint32Array(p*F);for(let o=0;o<p;o++){x(u,o,0);for(let l=0;l<500;l++){const g=Math.floor(k()*U);h.has(g)||x(u,o,g)}}x(u,2,i);const w=new Uint32Array(p);w[3]=1,w[64]=1;const B={wq8:e,M:p,x:y,w:a,lbias:d,t:b,tm8:s},c=await z(f,{...B,fused:!0,bitmask:Uint32Array.from(u),done:Uint32Array.from(w)}),A=await z(f,{...B,fused:!1,bitmask:Uint32Array.from(u),done:Uint32Array.from(w)}),S={wq8:e,tm8:s,M:p,t:b,DUP:i,sampleTokens:Array.from(c.tokens.subarray(0,8))};let O=!0;for(const o of["tokens","done","bitmask"]){const{mismatches:l,first:g}=it(c[o],A[o]);l>0&&(O=!1,S[o]={mismatches:l,first:g,fused:c[o][g],plain:A[o][g]})}for(const[o,l,g]of[["row0Token",c.tokens[0],i],["row1Token",c.tokens[1],i],["row2Token",c.tokens[2],m[0]],["row3Token",c.tokens[3],W],["row64Token",c.tokens[64],W],["row0Bit",C(c.bitmask,0,i),1],["row2Bit",C(c.bitmask,2,m[0]),1],["row3BitUntouched",C(c.bitmask,3,i),0]])l!==g&&(O=!1,S[o]={got:l,want:g});return{pass:O,detail:S}}P("argmax_fuse_kernel",t=>t.hasF16?V(t,{wq8:!1,tm8:!1,seed:501}):{skip:!0,reason:"no shader-f16"});P("argmax_fuse_kernel_q8_tm8",t=>t.hasF16?V(t,{wq8:!0,tm8:!0,seed:502}):{skip:!0,reason:"no shader-f16"});P("argmax_fuse_equiv",async t=>{const{device:e}=t;if(!t.hasF16)return{skip:!0,reason:"no shader-f16"};const s={device:e,dtype:"f16",limits:t.limits},n=[...Q("file23k")].slice(0,32),f=await K(),k=[{name:"f16_tiled",loadOpts:{},runOpts:{lmHead:"tiled"}},{name:"q8_prod",loadOpts:{lmHeadQ8:!0,ffnWT:!0},runOpts:{lmHead:"auto",ffn:"auto"}}],p={};let b=!0;for(const{name:y,loadOpts:r,runOpts:i}of k){const m=await j(e,"/weights",{targetDtype:"f16",...r});try{const d=await H(s,m,f,n,{...i,lmHeadFuse:"off"}),a=await H(s,m,f,n,{...i,lmHeadFuse:"auto"});let h=0,u=-1;for(let w=0;w<n.length;w++){const B=d.rows[w].ids,c=a.rows[w].ids;(B.length!==c.length||B.some((A,S)=>A!==c[S]))&&(h++,u<0&&(u=w))}p[y]={mismatches:h,...u>=0?{firstRow:u,off:d.rows[u].text,on:a.rows[u].text}:{},compactions:{off:d.metrics.compactions,on:a.metrics.compactions}},h>0&&(b=!1)}finally{m.buffer.destroy()}}return{pass:b,detail:p}});const N=7,E=50,ct=[16,32,64,128],mt=t=>{const e=[...t].sort((n,f)=>n-f),s=e.length>>1;return e.length%2?e[s]:(e[s-1]+e[s])/2};P("argmax_fuse_sweep",async t=>{const{device:e}=t;if(!t.hasF16)return{skip:!0,reason:"no shader-f16"};const s=await j(e,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0});try{const n=await K(),f={device:e,dtype:"f16",limits:t.limits},k=[...Q("file23k")].sort((y,r)=>r.length-y.length),p=[{name:"off",lmHeadFuse:"off"},{name:"fused",lmHeadFuse:"auto"}],b=[];for(const y of ct){const r=await v(n,k.slice(0,y)),i=await tt(f,s,r);await e.queue.onSubmittedWorkDone();try{const m=async({lmHeadFuse:a})=>{const h=st(f,s,{B:r.B,S:i.S,maxSteps:E,lmHeadFuse:a}),{stepUs:u}=await et(f,s,i,h,{steps:E});return h.destroy(),u};for(const a of p)await m(a);const d=Object.fromEntries(p.map(a=>[a.name,[]]));for(let a=0;a<N;a++)for(const h of p)d[h.name].push(await m(h));b.push({B:r.B,...Object.fromEntries(p.map(a=>[`${a.name}StepUs`,Number(mt(d[a.name]).toFixed(1))])),runs:d})}finally{i.arena.destroy()}}return{pass:!0,detail:{steps:E,rounds:N,table:b}}}finally{s.buffer.destroy()}});
2
+ //# sourceMappingURL=argmax_fuse-DcdFediE.js.map
assets/argmax_fuse-DcdFediE.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"argmax_fuse-DcdFediE.js","sources":["../../src/debug/tests/argmax_fuse.js"],"sourcesContent":["// Fused lm_head argmax (gemm_tiled2 IF_ARGMAX + argmax_reduce) vs the unfused\n// store-logits + argmax_penalty path. The fused path performs the SAME f32\n// ops in the same (val, lowest idx) order, so all three gates here are EXACT\n// integer comparisons — no tolerance:\n// argmax_fuse_kernel one dispatch pair on crafted data: duplicated W rows\n// with equal boosted bias force exact ties (intra-quad,\n// cross-tile, and at vocab id V-1), a pre-seen bit must\n// penalty-flip one row's winner, done rows must emit\n// PAD. Fused vs unfused state must match bit-for-bit\n// AND hit the hard-coded winners.\n// argmax_fuse_equiv e2e translateBatch fused vs unfused (f16-tiled and\n// the production q8 config): token-exact.\n// argmax_fuse_sweep interleaved step-wall A/B at B=16..128 (perf only).\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback } from '../gpu-utils.js';\nimport { dispatchGemm, dispatchArgmaxPenalty, dispatchArgmaxReduce } from '../../engine/pipelines.js';\nimport { loadWeights, quantizeQ8Rows } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { translateBatch } from '../../engine/generate.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { createDecodeState } from '../../engine/decoder.js';\nimport { timeDecodeSteps } from '../../bench/profile.js';\nimport { presetChunks } from '../../bench/bench.js';\nimport { f32ToF16 } from '../../engine/f16.js';\nimport { VOCAB, D_MODEL, PAD, BITMASK_WORDS } from '../../engine/constants.js';\n\nconst V = VOCAB;\nconst K = D_MODEL;\nconst WORDS = BITMASK_WORDS;\nconst BN = 64;\nconst NT = Math.ceil(V / BN); // 375\n\nfunction mulberry32(seed) {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nconst setBit = (mask, b, v) => { mask[b * WORDS + (v >> 5)] |= 1 << (v & 31); };\nconst getBit = (mask, b, v) => (mask[b * WORDS + (v >>> 5)] >>> (v & 31)) & 1;\n\nfunction diffU32(got, want) {\n let mismatches = 0;\n let first = -1;\n for (let i = 0; i < want.length; i++) {\n if (got[i] !== want[i]) {\n mismatches++;\n if (first < 0) first = i;\n }\n }\n return { mismatches, first };\n}\n\n// One lm_head + argmax step, fused or unfused, on private bitmask/done/ring\n// copies. Returns the readbacks. `w` is {half} (f16 [N,K]) or {packed,\n// scales} (wq8).\nasync function runArm(device, { fused, wq8, M, x, w, lbias, bitmask, done, t, tm8 }) {\n const rw = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC;\n const ro = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const xBuf = createBuffer(device, x, ro);\n const wBuf = createBuffer(device, wq8 ? w.packed : w.half, ro);\n const sBuf = wq8 ? createBuffer(device, w.scales, ro) : null;\n const lbBuf = createBuffer(device, lbias, ro);\n const maskBuf = createBuffer(device, bitmask, rw);\n const doneBuf = createBuffer(device, done, rw);\n const ringBuf = createBuffer(device, new Uint32Array((t + 1) * M).fill(0xdeadbeef), rw);\n const yBuf = fused ? null : device.createBuffer({ size: M * V * 4, usage: rw });\n const pBuf = fused ? device.createBuffer({ size: M * NT * 8, usage: rw }) : null;\n\n const flags = { t: 'f16', outT: 'f32', wt: true, tiled: true, ...(wq8 ? { wq8: true } : {}), tm8 };\n const scratch = [];\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n scratch.push(...dispatchGemm(device, pass, {\n x: xBuf, w: wBuf, ...(wq8 ? { scales: sBuf } : {}), y: yBuf,\n ...(fused ? { fusedArgmax: { partials: pBuf, lbias: lbBuf, seen: maskBuf } } : {}),\n M, K, N: V, flags,\n }).scratch);\n scratch.push(...(fused\n ? dispatchArgmaxReduce(device, pass, {\n partials: pBuf, bitmask: maskBuf, done: doneBuf, tokens: ringBuf, B: M, t, NT,\n })\n : dispatchArgmaxPenalty(device, pass, {\n logits: yBuf, bias: lbBuf, bitmask: maskBuf, done: doneBuf, tokens: ringBuf, B: M, t,\n })).scratch);\n pass.end();\n device.queue.submit([encoder.finish()]);\n\n const tokens = new Uint32Array(await readback(device, ringBuf, (t + 1) * M * 4));\n const doneOut = new Uint32Array(await readback(device, doneBuf, M * 4));\n const maskOut = new Uint32Array(await readback(device, maskBuf, M * WORDS * 4));\n for (const b of [xBuf, wBuf, sBuf, lbBuf, maskBuf, doneBuf, ringBuf, yBuf, pBuf, ...scratch]) b?.destroy();\n return { tokens: tokens.subarray(t * M), done: doneOut, bitmask: maskOut };\n}\n\nasync function fuseKernelCase(ctx, { wq8, tm8, seed }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const M = 65; // row tail: grid y = 2, second workgroup only 1 valid row\n const t = 2;\n\n const x = new Uint16Array(M * K);\n for (let i = 0; i < x.length; i++) x[i] = f32ToF16(rng() - 0.5);\n const wF = new Float32Array(V * K); // [N,K] row-major (wt layout)\n for (let i = 0; i < wF.length; i++) wF[i] = rng() - 0.5;\n // Exact ties: duplicate row DUP into an intra-quad neighbor, a far tile,\n // and the last vocab id; equal boosted bias makes them the global max.\n const DUP = 4097;\n const DUPS = [4098, 12000, V - 1];\n for (const d of DUPS) wF.copyWithin(d * K, DUP * K, DUP * K + K);\n const lbias = new Float32Array(V);\n for (let i = 0; i < V; i++) lbias[i] = rng() - 0.5;\n for (const d of [DUP, ...DUPS]) lbias[d] = 50.0;\n\n let w;\n if (wq8) {\n w = quantizeQ8Rows(wF, V, K); // duplicated rows quantize identically\n } else {\n const half = new Uint16Array(V * K);\n for (let i = 0; i < wF.length; i++) half[i] = f32ToF16(wF[i]);\n w = { half };\n }\n\n // ~500 random seen bits per row (never on the tie ids), bit 0 like\n // production, DUP seen for row 2 → its winner must penalty-flip to 4098.\n const noTouch = new Set([DUP, ...DUPS]);\n const bitmask = new Uint32Array(M * WORDS);\n for (let b = 0; b < M; b++) {\n setBit(bitmask, b, 0);\n for (let i = 0; i < 500; i++) {\n const v = Math.floor(rng() * V);\n if (!noTouch.has(v)) setBit(bitmask, b, v);\n }\n }\n setBit(bitmask, 2, DUP);\n const done = new Uint32Array(M);\n done[3] = 1;\n done[64] = 1;\n\n const args = { wq8, M, x, w, lbias, t, tm8 };\n const fusedR = await runArm(device, { ...args, fused: true, bitmask: Uint32Array.from(bitmask), done: Uint32Array.from(done) });\n const plainR = await runArm(device, { ...args, fused: false, bitmask: Uint32Array.from(bitmask), done: Uint32Array.from(done) });\n\n const detail = { wq8, tm8, M, t, DUP, sampleTokens: Array.from(fusedR.tokens.subarray(0, 8)) };\n let pass = true;\n for (const field of ['tokens', 'done', 'bitmask']) {\n const { mismatches, first } = diffU32(fusedR[field], plainR[field]);\n if (mismatches > 0) {\n pass = false;\n detail[field] = { mismatches, first, fused: fusedR[field][first], plain: plainR[field][first] };\n }\n }\n // Hard-coded winners so a bug shared by both arms can't hide: ties break to\n // the LOWEST id, row 2's penalty flips it to the unpenalized duplicate,\n // done rows emit PAD and stay unmasked.\n for (const [name, got, want] of [\n ['row0Token', fusedR.tokens[0], DUP],\n ['row1Token', fusedR.tokens[1], DUP],\n ['row2Token', fusedR.tokens[2], DUPS[0]],\n ['row3Token', fusedR.tokens[3], PAD],\n ['row64Token', fusedR.tokens[64], PAD],\n ['row0Bit', getBit(fusedR.bitmask, 0, DUP), 1],\n ['row2Bit', getBit(fusedR.bitmask, 2, DUPS[0]), 1],\n ['row3BitUntouched', getBit(fusedR.bitmask, 3, DUP), 0],\n ]) {\n if (got !== want) {\n pass = false;\n detail[name] = { got, want };\n }\n }\n return { pass, detail };\n}\n\nregisterTest('argmax_fuse_kernel', (ctx) => (ctx.hasF16\n ? fuseKernelCase(ctx, { wq8: false, tm8: false, seed: 501 })\n : { skip: true, reason: 'no shader-f16' }));\nregisterTest('argmax_fuse_kernel_q8_tm8', (ctx) => (ctx.hasF16\n ? fuseKernelCase(ctx, { wq8: true, tm8: true, seed: 502 })\n : { skip: true, reason: 'no shader-f16' }));\n\n// e2e: fused vs unfused must be TOKEN-EXACT through ragged batches (EOS\n// compaction fires and must pin the fuse flag) in both the plain f16-tiled\n// and the production q8 lm_head configs.\nregisterTest('argmax_fuse_equiv', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const chunks = [...presetChunks('file23k')].slice(0, 32); // unsorted → ragged\n const tok = await loadTokenizer();\n\n const configs = [\n { name: 'f16_tiled', loadOpts: {}, runOpts: { lmHead: 'tiled' } },\n { name: 'q8_prod', loadOpts: { lmHeadQ8: true, ffnWT: true }, runOpts: { lmHead: 'auto', ffn: 'auto' } },\n ];\n const detail = {};\n let pass = true;\n for (const { name, loadOpts, runOpts } of configs) {\n const weights = await loadWeights(device, '/weights', { targetDtype: 'f16', ...loadOpts });\n try {\n const off = await translateBatch(gctx, weights, tok, chunks, { ...runOpts, lmHeadFuse: 'off' });\n const on = await translateBatch(gctx, weights, tok, chunks, { ...runOpts, lmHeadFuse: 'auto' });\n let mismatches = 0;\n let firstRow = -1;\n for (let i = 0; i < chunks.length; i++) {\n const a = off.rows[i].ids;\n const b = on.rows[i].ids;\n if (a.length !== b.length || a.some((v, j) => v !== b[j])) {\n mismatches++;\n if (firstRow < 0) firstRow = i;\n }\n }\n detail[name] = {\n mismatches,\n ...(firstRow >= 0 ? { firstRow, off: off.rows[firstRow].text, on: on.rows[firstRow].text } : {}),\n compactions: { off: off.metrics.compactions, on: on.metrics.compactions },\n };\n if (mismatches > 0) pass = false;\n } finally {\n weights.buffer.destroy();\n }\n }\n return { pass, detail };\n});\n\n// Perf A/B: production weights, arms interleaved per round in ONE session\n// (sequential runs drift ±30% with laptop thermals), medians of ROUNDS.\nconst ROUNDS = 7;\nconst STEPS = 50;\nconst BATCHES = [16, 32, 64, 128];\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nregisterTest('argmax_fuse_sweep', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const weights = await loadWeights(device, '/weights', { targetDtype: 'f16', lmHeadQ8: true, ffnWT: true });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n\n const ARMS = [\n { name: 'off', lmHeadFuse: 'off' },\n { name: 'fused', lmHeadFuse: 'auto' },\n ];\n const table = [];\n for (const B of BATCHES) {\n const batch = await tokenizeBatch(tok, chunks.slice(0, B));\n const encRun = await runEncoder(gctx, weights, batch);\n await device.queue.onSubmittedWorkDone();\n try {\n const timeArm = async ({ lmHeadFuse }) => {\n const state = createDecodeState(gctx, weights, {\n B: batch.B, S: encRun.S, maxSteps: STEPS, lmHeadFuse,\n });\n const { stepUs } = await timeDecodeSteps(gctx, weights, encRun, state, { steps: STEPS });\n state.destroy();\n return stepUs;\n };\n for (const arm of ARMS) await timeArm(arm); // pipeline warmup\n const times = Object.fromEntries(ARMS.map((a) => [a.name, []]));\n for (let r = 0; r < ROUNDS; r++) {\n for (const arm of ARMS) times[arm.name].push(await timeArm(arm));\n }\n table.push({\n B: batch.B,\n ...Object.fromEntries(ARMS.map((a) => [`${a.name}StepUs`, Number(median(times[a.name]).toFixed(1))])),\n runs: times,\n });\n } finally {\n encRun.arena.destroy();\n }\n }\n return { pass: true, detail: { steps: STEPS, rounds: ROUNDS, table } };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["V","VOCAB","K","D_MODEL","WORDS","BITMASK_WORDS","BN","NT","mulberry32","seed","a","t","setBit","mask","b","v","getBit","diffU32","got","want","mismatches","first","i","runArm","device","fused","wq8","M","x","w","lbias","bitmask","done","tm8","rw","ro","xBuf","createBuffer","wBuf","sBuf","lbBuf","maskBuf","doneBuf","ringBuf","yBuf","pBuf","flags","scratch","encoder","pass","dispatchGemm","dispatchArgmaxReduce","dispatchArgmaxPenalty","tokens","readback","doneOut","maskOut","fuseKernelCase","ctx","rng","f32ToF16","wF","DUP","DUPS","d","quantizeQ8Rows","half","noTouch","args","fusedR","plainR","detail","field","name","PAD","registerTest","gctx","chunks","presetChunks","tok","loadTokenizer","configs","loadOpts","runOpts","weights","loadWeights","off","translateBatch","on","firstRow","j","ROUNDS","STEPS","BATCHES","median","xs","s","m","ARMS","table","B","batch","tokenizeBatch","encRun","runEncoder","timeArm","lmHeadFuse","state","createDecodeState","stepUs","timeDecodeSteps","arm","times","r"],"mappings":"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"}
assets/attention-CPOKnefi.js ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as w}from"./debug-Cn7EHWtJ.js";import{c as A,r as X,a as Z}from"./gpu-utils-BTh3AGTJ.js";import{g as N,d as ee,c as ne}from"./pipelines-DD24nEJg.js";import{b as q}from"./math-DNG-wiC0.js";import{f as te,e as W}from"./f16-wKKZr58e.js";import{H as se,d as re,A as $,S as ae}from"./constants-C8VbFpic.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";const oe=`// Scatter fused projection output into [B, L, H, D] K/V buffers. One thread
2
+ // per (row, h·D+d) element, plain index math, no barriers. Within a fused row
3
+ // each 448-wide chunk is laid out h*D + d — identical to the H,D tail of the
4
+ // [B, L, H, D] cache index ((b*L + j)*H + h)*D + d = (b*L + j)*H*D + (h*D + d),
5
+ // so the copy is a contiguous-chunk scatter with no per-element shuffling.
6
+ //
7
+ // Two build-time modes (exactly one of APPEND / SPLIT):
8
+ // APPEND (decode step): fused is fusedQKV [B, 3·H·D] (q at 0, k at H·D,
9
+ // v at 2·H·D). Thread (b, i) writes BOTH caches at position t:
10
+ // Kc[(b*Lmax + t)*H*D + i] = fused[b*3HD + HD + i]
11
+ // Vc[(b*Lmax + t)*H*D + i] = fused[b*3HD + 2HD + i]
12
+ // Total threads B·H·D. Uses params.B, params.t, params.Lmax.
13
+ // SPLIT — currently unused by the engine (attention reads fused K/V buffers
14
+ // directly via its Q_STRIDE/KV_STRIDE/*_OFF defines); kept for tests and
15
+ // as a fallback. Cross K/V after encoder: fused is fusedKV [B·S, 2·H·D] (k at 0,
16
+ // v at H·D). Here the [B, L, H, D] buffers have L = S exactly (allocated
17
+ // to the padded bucket length), so row = b·S + j indexes both sides:
18
+ // Kc[row*H*D + i] = fused[row*2HD + i]
19
+ // Vc[row*H*D + i] = fused[row*2HD + HD + i]
20
+ // Total threads rows·H·D. Uses params.rows only.
21
+ //
22
+ // Template placeholders (buildShader in pipelines.js):
23
+ // ENABLE_F16 the f16 enable directive when T is f16, else empty
24
+ // T storage type of fused/Kc/Vc (f16|f32) — straight copy,
25
+ // no conversion
26
+ // WG workgroup size
27
+ // H, D heads (8), head dim (56)
28
+ // IF_APPEND/IF_SPLIT mode blocks
29
+ {{ENABLE_F16}}
30
+
31
+ struct Params {
32
+ B: u32, // APPEND: batch
33
+ t: u32, // APPEND: decode step (write position)
34
+ Lmax: u32, // APPEND: K/V cache position capacity (stride)
35
+ rows: u32, // SPLIT: B·S fused rows
36
+ }
37
+
38
+ @group(0) @binding(0) var<uniform> params: Params;
39
+ @group(0) @binding(1) var<storage, read> fused: array<{{T}}>;
40
+ @group(0) @binding(2) var<storage, read_write> Kc: array<{{T}}>;
41
+ @group(0) @binding(3) var<storage, read_write> Vc: array<{{T}}>;
42
+
43
+ const HD: u32 = {{H}}u * {{D}}u;
44
+
45
+ @compute @workgroup_size({{WG}})
46
+ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
47
+ {{IF_APPEND}}
48
+ if (gid.x >= params.B * HD) { return; }
49
+ let b = gid.x / HD;
50
+ let i = gid.x % HD; // h*D + d
51
+ let dst = (b * params.Lmax + params.t) * HD + i;
52
+ Kc[dst] = fused[b * 3u * HD + HD + i];
53
+ Vc[dst] = fused[b * 3u * HD + 2u * HD + i];
54
+ {{/IF_APPEND}}
55
+ {{IF_SPLIT}}
56
+ if (gid.x >= params.rows * HD) { return; }
57
+ let r = gid.x / HD; // b*S + j
58
+ let i = gid.x % HD; // h*D + d
59
+ Kc[r * HD + i] = fused[r * 2u * HD + i];
60
+ Vc[r * HD + i] = fused[r * 2u * HD + HD + i];
61
+ {{/IF_SPLIT}}
62
+ }
63
+ `,S=re,U=se,n=S*U;function v(e){let t=e>>>0;return()=>{t=t+1831565813|0;let s=Math.imul(t^t>>>15,1|t);return s=s+Math.imul(s^s>>>7,61|s)^s,((s^s>>>14)>>>0)/4294967296}}function O(e,t){const s=new Float32Array(e);for(let r=0;r<e;r++)s[r]=Math.fround(t()-.5);return s}function T(e,t){if(t!=="f16")return{data:e,ref:e};const s=new Uint16Array(e.length);for(let r=0;r<e.length;r++)s[r]=te(e[r]);return{data:s,ref:W(s)}}function z(e,t){const s=Math.ceil(t.length*4/16)*16,r=e.createBuffer({size:s,usage:GPUBufferUsage.UNIFORM,mappedAtCreation:!0});return new Uint32Array(r.getMappedRange()).set(t),r.unmap(),r}function C(e){return e==="f16"?2:4}function fe(e,t,s={},r=!1){return N(e,"attention",ne,{t,wg:128,sg:r,defines:{H:S,D:U,SCORES_CAP:ae,ATTN_SCALE:$,Q_STRIDE:n,Q_OFF:0,KV_STRIDE:n,K_OFF:0,V_OFF:0,...s}})}function ue(e,t,{qb:s,jb:r},o={}){return N(e,"attention_block",ee,{t,defines:{H:S,D:U,QB:s,JB:r,ATTN_SCALE:$,Q_STRIDE:n,Q_OFF:0,KV_STRIDE:n,K_OFF:0,V_OFF:0,PACKED:!1,NOPACKED:!0,...o}})}function x(e,t,s){return N(e,"kv_append",oe,{t,wg:128,defines:{H:S,D:U,APPEND:s==="append",SPLIT:s==="split"}})}function K(e,t,s,r,o=1,g=1){const D=e.createBindGroup({layout:t.getBindGroupLayout(0),entries:s.map((F,i)=>({binding:i,resource:{buffer:F}}))}),d=e.createCommandEncoder(),a=d.beginComputePass();a.setPipeline(t),a.setBindGroup(0,D),a.dispatchWorkgroups(r,o,g),a.end(),e.queue.submit([d.finish()])}async function V(e,t,{qBuf:s,kBuf:r,vBuf:o,lensBuf:g,B:D,M:d,L:a,lenMode:F,step:i,strides:c,block:l,sg:h},P,y,_){const b=l?ue(e,t,l,c):fe(e,t,c,h),m=z(e,[D,d,a,F,i??0,0,0,0]),B=[m];let f=g;f||(f=e.createBuffer({label:"attn dummy lens",size:4,usage:GPUBufferUsage.STORAGE}),B.push(f));const k=D*d*n,p=e.createBuffer({size:Math.ceil(k*C(t)/4)*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});l?K(e,b,[m,s,r,o,f,p],Math.ceil(d/l.qb),S,D):K(e,b,[m,s,r,o,f,p],D*d,S);const H=await X(e,p,k*C(t)),G=t==="f16"?W(new Uint16Array(H)):new Float32Array(H);for(const J of[...B,p])J.destroy();const{failures:L,maxAbsDiff:u,worst:M}=Z(G,P,y);return{pass:L===0,detail:{..._,tol:y,failures:L,maxAbsDiff:String(u),...L>0?{worst:M,got:String(G[M]),want:String(P[M])}:{}}}}async function E(e,{B:t,M:s,L:r,lens:o,t:g,tol:D,seed:d,block:a,sg:F=!1}){const{device:i}=e,c=v(d),l=T(O(t*s*n,c),g),h=T(O(t*r*n,c),g),P=T(O(t*r*n,c),g),y=q(l.ref,h.ref,P.ref,{B:t,M:s,H:S,D:U,L:r,lens:o}),_=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,b=A(i,l.data,_),m=A(i,h.data,_),B=A(i,P.data,_),f=A(i,new Uint32Array(o),_),k=await V(i,g,{qBuf:b,kBuf:m,vBuf:B,lensBuf:f,B:t,M:s,L:r,lenMode:1,block:a,sg:F},y,D,{kernel:a?`attention_block qb${a.qb} jb${a.jb}`:"attention",mode:"encoder",B:t,M:s,L:r,lens:o.join(","),t:g});for(const p of[b,m,B,f])p.destroy();return k}async function Q(e,{B:t,S:s,lens:r,t:o,tol:g,seed:D,block:d}){const{device:a}=e,F=v(D),i=t*s,c=T(O(i*3*n,F),o),l=new Float32Array(i*n),h=new Float32Array(i*n),P=new Float32Array(i*n);for(let f=0;f<i;f++)l.set(c.ref.subarray(f*3*n,f*3*n+n),f*n),h.set(c.ref.subarray(f*3*n+n,f*3*n+2*n),f*n),P.set(c.ref.subarray(f*3*n+2*n,f*3*n+3*n),f*n);const y=q(l,h,P,{B:t,M:s,H:S,D:U,L:s,lens:r}),_=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,b=A(a,c.data,_),m=A(a,new Uint32Array(r),_),B=await V(a,o,{qBuf:b,kBuf:b,vBuf:b,lensBuf:m,B:t,M:s,L:s,lenMode:1,block:d,strides:{Q_STRIDE:3*n,Q_OFF:0,KV_STRIDE:3*n,K_OFF:n,V_OFF:2*n}},y,g,{kernel:d?`attention_block qb${d.qb} jb${d.jb}`:"attention",mode:"encoder-fused",B:t,S:s,lens:r.join(","),t:o});for(const f of[b,m])f.destroy();return B}async function j(e,{B:t,Lmax:s,steps:r,t:o,tol:g,seed:D,sg:d=!1}){const{device:a}=e,F=v(D),i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,c=t*s*n*C(o),l=a.createBuffer({size:c,usage:GPUBufferUsage.STORAGE}),h=a.createBuffer({size:c,usage:GPUBufferUsage.STORAGE}),P=x(a,o,"append"),y=new Float32Array(t*s*n),_=new Float32Array(t*s*n),b=new Float32Array(t*n);for(let p=0;p<r;p++){const H=T(O(t*3*n,F),o),G=A(a,H.data,i),L=z(a,[t,p,s,0]);K(a,P,[L,G,l,h],Math.ceil(t*n/128));for(let u=0;u<t;u++){const M=(u*s+p)*n;y.set(H.ref.subarray(u*3*n+n,u*3*n+2*n),M),_.set(H.ref.subarray(u*3*n+2*n,u*3*n+3*n),M),p===r-1&&b.set(H.ref.subarray(u*3*n,u*3*n+n),u*n)}G.destroy()}const m=T(b,o),B=A(a,m.data,i),f=q(m.ref,y,_,{B:t,M:1,H:S,D:U,L:s,lens:Array(t).fill(r)}),k=await V(a,o,{qBuf:B,kBuf:l,vBuf:h,lensBuf:null,B:t,M:1,L:s,lenMode:0,step:r-1,sg:d},f,g,{kernel:"kv_append+attention",mode:"decode",B:t,Lmax:s,steps:r,t:o});for(const p of[B,l,h])p.destroy();return k}async function Y(e,{B:t,S:s,lens:r,t:o,tol:g,seed:D,sg:d=!1}){const{device:a}=e,F=v(D),i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,c=t*s,l=T(O(c*2*n,F),o),h=A(a,l.data,i),P=c*n*C(o),y=a.createBuffer({size:P,usage:GPUBufferUsage.STORAGE}),_=a.createBuffer({size:P,usage:GPUBufferUsage.STORAGE}),b=x(a,o,"split"),m=z(a,[t,0,0,c]);K(a,b,[m,h,y,_],Math.ceil(c*n/128));const B=new Float32Array(c*n),f=new Float32Array(c*n);for(let u=0;u<c;u++)B.set(l.ref.subarray(u*2*n,u*2*n+n),u*n),f.set(l.ref.subarray(u*2*n+n,u*2*n+2*n),u*n);const k=T(O(t*n,F),o),p=A(a,k.data,i),H=A(a,new Uint32Array(r),i),G=q(k.ref,B,f,{B:t,M:1,H:S,D:U,L:s,lens:r}),L=await V(a,o,{qBuf:p,kBuf:y,vBuf:_,lensBuf:H,B:t,M:1,L:s,lenMode:1,sg:d},G,g,{kernel:"kv_split+attention",mode:"cross",B:t,S:s,lens:r.join(","),t:o});for(const u of[h,p,y,_,H])u.destroy();return L}function R(e,t){w(e,s=>s.hasF16?t(s):{skip:!0,reason:"no shader-f16"})}R("attn_encoder_f16",e=>E(e,{B:2,M:16,L:16,lens:[16,9],t:"f16",tol:.03,seed:301}));R("attn_encoder_fused_f16",e=>Q(e,{B:2,S:16,lens:[16,9],t:"f16",tol:.03,seed:305}));R("attn_decode_f16",e=>j(e,{B:3,Lmax:32,steps:5,t:"f16",tol:.03,seed:302}));R("attn_cross_f16",e=>Y(e,{B:2,S:32,lens:[32,20],t:"f16",tol:.03,seed:303}));w("attn_encoder_f32",e=>E(e,{B:1,M:4,L:4,lens:[3],t:"f32",tol:1e-4,seed:304}));R("attn_block_encoder_f16",e=>E(e,{B:2,M:20,L:20,lens:[20,9],t:"f16",tol:.03,seed:311,block:{qb:8,jb:16}}));R("attn_block_encoder_fused_f16",e=>Q(e,{B:3,S:33,lens:[33,17,5],t:"f16",tol:.03,seed:312,block:{qb:16,jb:32}}));R("attn_block_encoder_fused_jb48_f16",e=>Q(e,{B:2,S:50,lens:[50,49],t:"f16",tol:.03,seed:313,block:{qb:8,jb:48}}));w("attn_block_encoder_f32",e=>E(e,{B:2,M:9,L:12,lens:[12,3],t:"f32",tol:1e-4,seed:314,block:{qb:8,jb:16}}));const I=e=>e.hasSubgroups?null:{skip:!0,reason:"subgroups feature unavailable"};w("attn_sg_encoder_f16",e=>I(e)??(e.hasF16?E(e,{B:2,M:16,L:16,lens:[16,9],t:"f16",tol:.03,seed:301,sg:!0}):{skip:!0,reason:"no shader-f16"}));w("attn_sg_decode_f16",e=>I(e)??(e.hasF16?j(e,{B:3,Lmax:32,steps:5,t:"f16",tol:.03,seed:302,sg:!0}):{skip:!0,reason:"no shader-f16"}));w("attn_sg_cross_f16",e=>I(e)??(e.hasF16?Y(e,{B:2,S:32,lens:[32,20],t:"f16",tol:.03,seed:303,sg:!0}):{skip:!0,reason:"no shader-f16"}));w("attn_sg_encoder_f32",e=>I(e)??E(e,{B:1,M:4,L:4,lens:[3],t:"f32",tol:1e-4,seed:304,sg:!0}));w("attn_sg_long_encoder_f16",e=>I(e)??(e.hasF16?E(e,{B:2,M:8,L:224,lens:[224,131],t:"f16",tol:.03,seed:321,sg:!0}):{skip:!0,reason:"no shader-f16"}));w("attn_sg_long_decode_f16",e=>I(e)??(e.hasF16?j(e,{B:2,Lmax:224,steps:160,t:"f16",tol:.03,seed:322,sg:!0}):{skip:!0,reason:"no shader-f16"}));w("attn_sg_long_cross_f16",e=>I(e)??(e.hasF16?Y(e,{B:2,S:192,lens:[192,130],t:"f16",tol:.03,seed:323,sg:!0}):{skip:!0,reason:"no shader-f16"}));w("attn_long_encoder_f16",e=>e.hasF16?E(e,{B:2,M:8,L:224,lens:[224,131],t:"f16",tol:.03,seed:321}):{skip:!0,reason:"no shader-f16"});w("attn_long_decode_f16",e=>e.hasF16?j(e,{B:2,Lmax:224,steps:160,t:"f16",tol:.03,seed:322}):{skip:!0,reason:"no shader-f16"});
64
+ //# sourceMappingURL=attention-CPOKnefi.js.map
assets/attention-CPOKnefi.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"attention-CPOKnefi.js","sources":["../../src/engine/kernels/kv_append.wgsl?raw","../../src/debug/tests/attention.js"],"sourcesContent":["export default \"// Scatter fused projection output into [B, L, H, D] K/V buffers. One thread\\n// per (row, h·D+d) element, plain index math, no barriers. Within a fused row\\n// each 448-wide chunk is laid out h*D + d — identical to the H,D tail of the\\n// [B, L, H, D] cache index ((b*L + j)*H + h)*D + d = (b*L + j)*H*D + (h*D + d),\\n// so the copy is a contiguous-chunk scatter with no per-element shuffling.\\n//\\n// Two build-time modes (exactly one of APPEND / SPLIT):\\n// APPEND (decode step): fused is fusedQKV [B, 3·H·D] (q at 0, k at H·D,\\n// v at 2·H·D). Thread (b, i) writes BOTH caches at position t:\\n// Kc[(b*Lmax + t)*H*D + i] = fused[b*3HD + HD + i]\\n// Vc[(b*Lmax + t)*H*D + i] = fused[b*3HD + 2HD + i]\\n// Total threads B·H·D. Uses params.B, params.t, params.Lmax.\\n// SPLIT — currently unused by the engine (attention reads fused K/V buffers\\n// directly via its Q_STRIDE/KV_STRIDE/*_OFF defines); kept for tests and\\n// as a fallback. Cross K/V after encoder: fused is fusedKV [B·S, 2·H·D] (k at 0,\\n// v at H·D). Here the [B, L, H, D] buffers have L = S exactly (allocated\\n// to the padded bucket length), so row = b·S + j indexes both sides:\\n// Kc[row*H*D + i] = fused[row*2HD + i]\\n// Vc[row*H*D + i] = fused[row*2HD + HD + i]\\n// Total threads rows·H·D. Uses params.rows only.\\n//\\n// Template placeholders (buildShader in pipelines.js):\\n// ENABLE_F16 the f16 enable directive when T is f16, else empty\\n// T storage type of fused/Kc/Vc (f16|f32) — straight copy,\\n// no conversion\\n// WG workgroup size\\n// H, D heads (8), head dim (56)\\n// IF_APPEND/IF_SPLIT mode blocks\\n{{ENABLE_F16}}\\n\\nstruct Params {\\n B: u32, // APPEND: batch\\n t: u32, // APPEND: decode step (write position)\\n Lmax: u32, // APPEND: K/V cache position capacity (stride)\\n rows: u32, // SPLIT: B·S fused rows\\n}\\n\\n@group(0) @binding(0) var<uniform> params: Params;\\n@group(0) @binding(1) var<storage, read> fused: array<{{T}}>;\\n@group(0) @binding(2) var<storage, read_write> Kc: array<{{T}}>;\\n@group(0) @binding(3) var<storage, read_write> Vc: array<{{T}}>;\\n\\nconst HD: u32 = {{H}}u * {{D}}u;\\n\\n@compute @workgroup_size({{WG}})\\nfn main(@builtin(global_invocation_id) gid: vec3<u32>) {\\n{{IF_APPEND}}\\n if (gid.x >= params.B * HD) { return; }\\n let b = gid.x / HD;\\n let i = gid.x % HD; // h*D + d\\n let dst = (b * params.Lmax + params.t) * HD + i;\\n Kc[dst] = fused[b * 3u * HD + HD + i];\\n Vc[dst] = fused[b * 3u * HD + 2u * HD + i];\\n{{/IF_APPEND}}\\n{{IF_SPLIT}}\\n if (gid.x >= params.rows * HD) { return; }\\n let r = gid.x / HD; // b*S + j\\n let i = gid.x % HD; // h*D + d\\n Kc[r * HD + i] = fused[r * 2u * HD + i];\\n Vc[r * HD + i] = fused[r * 2u * HD + HD + i];\\n{{/IF_SPLIT}}\\n}\\n\"","// GPU unified-attention + kv_append kernels vs the JS f64 reference\n// (attentionRef). f16 test data is encoded to f16 and decoded back to f32 for\n// the reference input, so ref and GPU see IDENTICAL values (pattern from\n// gemm.js). The decode test drives kv_append APPEND across 5 simulated steps\n// and validates its indexing THROUGH attention — the way the engine uses it.\n// Per-call uniform/bind-group creation is test-only plumbing.\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback, compareLanes } from '../gpu-utils.js';\nimport { getPipeline } from '../../engine/pipelines.js';\nimport { attentionRef } from '../../reference/math.js';\nimport { f32ToF16, expandF16 } from '../../engine/f16.js';\nimport { HEADS, HEAD_DIM, ATTN_SCALE, SCORES_CAP } from '../../engine/constants.js';\nimport attentionSource from '../../engine/kernels/attention.wgsl?raw';\nimport attentionBlockSource from '../../engine/kernels/attention_block.wgsl?raw';\nimport kvAppendSource from '../../engine/kernels/kv_append.wgsl?raw';\n\nconst H = HEADS, D = HEAD_DIM, HD = H * D; // 8 · 56 = 448 = D_MODEL\n\nfunction mulberry32(seed) {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nfunction randF32(n, rng) {\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) out[i] = Math.fround(rng() - 0.5); // ~±0.5\n return out;\n}\n\n// {data, ref} pair for a given storage type: encode to f16 for the GPU and\n// decode back to f32 for the reference so both see identical values.\nfunction prep(f32arr, t) {\n if (t !== 'f16') return { data: f32arr, ref: f32arr };\n const half = new Uint16Array(f32arr.length);\n for (let i = 0; i < f32arr.length; i++) half[i] = f32ToF16(f32arr[i]);\n return { data: half, ref: expandF16(half) };\n}\n\nfunction makeUniform(device, vals) {\n const size = Math.ceil((vals.length * 4) / 16) * 16;\n const buf = device.createBuffer({ size, usage: GPUBufferUsage.UNIFORM, mappedAtCreation: true });\n new Uint32Array(buf.getMappedRange()).set(vals);\n buf.unmap();\n return buf;\n}\n\nfunction elemBytes(t) { return t === 'f16' ? 2 : 4; }\n\n// strides overrides the default compact layouts (Q [B·M, HD], K/V [B, L, H, D])\n// with fused-buffer strides/offsets — see attention.wgsl.\nfunction attentionPipeline(device, t, strides = {}, sg = false) {\n return getPipeline(device, 'attention', attentionSource, {\n t, wg: 128, sg,\n defines: {\n H, D, SCORES_CAP, ATTN_SCALE,\n Q_STRIDE: HD, Q_OFF: 0, KV_STRIDE: HD, K_OFF: 0, V_OFF: 0,\n ...strides,\n },\n });\n}\n\n// Blocked encoder variant (attention_block.wgsl) — grid (ceil(M/QB), H, B).\nfunction attentionBlockPipeline(device, t, { qb, jb }, strides = {}) {\n return getPipeline(device, 'attention_block', attentionBlockSource, {\n t,\n defines: {\n H, D, QB: qb, JB: jb, ATTN_SCALE,\n Q_STRIDE: HD, Q_OFF: 0, KV_STRIDE: HD, K_OFF: 0, V_OFF: 0,\n PACKED: false, NOPACKED: true,\n ...strides,\n },\n });\n}\n\nfunction kvAppendPipeline(device, t, mode) {\n return getPipeline(device, 'kv_append', kvAppendSource, {\n t, wg: 128, defines: { H, D, APPEND: mode === 'append', SPLIT: mode === 'split' },\n });\n}\n\nfunction dispatch(device, pipeline, buffers, wgX, wgY = 1, wgZ = 1) {\n const bindGroup = device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: buffers.map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, bindGroup);\n pass.dispatchWorkgroups(wgX, wgY, wgZ);\n pass.end();\n device.queue.submit([encoder.finish()]);\n}\n\n// Run attention (grid B·M × H, or (ceil(M/QB), H, B) when block = {qb, jb}),\n// read back Y [B·M, HD], compare to ref.\nasync function runAttentionAndCompare(device, t, { qBuf, kBuf, vBuf, lensBuf, B, M, L, lenMode, step, strides, block, sg }, want, tol, label) {\n const pipeline = block\n ? attentionBlockPipeline(device, t, block, strides)\n : attentionPipeline(device, t, strides, sg);\n const params = makeUniform(device, [B, M, L, lenMode, step ?? 0, 0, 0, 0]);\n const scratch = [params];\n let lens = lensBuf;\n if (!lens) { // lenMode 0: dummy 4-byte buffer, never indexed\n lens = device.createBuffer({ label: 'attn dummy lens', size: 4, usage: GPUBufferUsage.STORAGE });\n scratch.push(lens);\n }\n const outElems = B * M * HD;\n const yBuf = device.createBuffer({\n size: Math.ceil((outElems * elemBytes(t)) / 4) * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n if (block) {\n dispatch(device, pipeline, [params, qBuf, kBuf, vBuf, lens, yBuf], Math.ceil(M / block.qb), H, B);\n } else {\n dispatch(device, pipeline, [params, qBuf, kBuf, vBuf, lens, yBuf], B * M, H);\n }\n const raw = await readback(device, yBuf, outElems * elemBytes(t));\n const got = t === 'f16' ? expandF16(new Uint16Array(raw)) : new Float32Array(raw);\n for (const b of [...scratch, yBuf]) b.destroy();\n\n const { failures, maxAbsDiff, worst } = compareLanes(got, want, tol);\n return {\n pass: failures === 0,\n detail: {\n ...label, tol, failures,\n maxAbsDiff: String(maxAbsDiff), // string: JSON turns NaN/Infinity into null\n ...(failures > 0 ? { worst, got: String(got[worst]), want: String(want[worst]) } : {}),\n },\n };\n}\n\n// --------------------------------------------------- encoder self / direct ---\n\n// K/V built directly in [B, L, H, D] layout; ragged lens via lenMode 1.\n// block = {qb, jb} routes through the blocked kernel instead.\nasync function runEncoderCase(ctx, { B, M, L, lens, t, tol, seed, block, sg = false }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const q = prep(randF32(B * M * HD, rng), t);\n const k = prep(randF32(B * L * HD, rng), t);\n const v = prep(randF32(B * L * HD, rng), t);\n const want = attentionRef(q.ref, k.ref, v.ref, { B, M, H, D, L, lens });\n\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const qBuf = createBuffer(device, q.data, usage);\n const kBuf = createBuffer(device, k.data, usage);\n const vBuf = createBuffer(device, v.data, usage);\n const lensBuf = createBuffer(device, new Uint32Array(lens), usage);\n const result = await runAttentionAndCompare(\n device, t, { qBuf, kBuf, vBuf, lensBuf, B, M, L, lenMode: 1, block, sg },\n want, tol, {\n kernel: block ? `attention_block qb${block.qb} jb${block.jb}` : 'attention',\n mode: 'encoder', B, M, L, lens: lens.join(','), t,\n });\n for (const b of [qBuf, kBuf, vBuf, lensBuf]) b.destroy();\n return result;\n}\n\n// ----------------------------------------------------- encoder self, fused ---\n\n// Attention reads q/k/v slices DIRECTLY from the fused QKV projection output\n// [B·S, 3·HD] via Q_STRIDE/KV_STRIDE + offsets (Q=K=V= the same buffer) — the\n// way the encoder pass uses it. Reference gets the slices extracted in JS.\nasync function runEncoderFusedCase(ctx, { B, S, lens, t, tol, seed, block }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const rows = B * S;\n const fused = prep(randF32(rows * 3 * HD, rng), t);\n const qRef = new Float32Array(rows * HD);\n const kRef = new Float32Array(rows * HD); // [B, S, H, D] == per-row slices\n const vRef = new Float32Array(rows * HD);\n for (let r = 0; r < rows; r++) {\n qRef.set(fused.ref.subarray(r * 3 * HD, r * 3 * HD + HD), r * HD);\n kRef.set(fused.ref.subarray(r * 3 * HD + HD, r * 3 * HD + 2 * HD), r * HD);\n vRef.set(fused.ref.subarray(r * 3 * HD + 2 * HD, r * 3 * HD + 3 * HD), r * HD);\n }\n const want = attentionRef(qRef, kRef, vRef, { B, M: S, H, D, L: S, lens });\n\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const fusedBuf = createBuffer(device, fused.data, usage);\n const lensBuf = createBuffer(device, new Uint32Array(lens), usage);\n const result = await runAttentionAndCompare(\n device, t,\n {\n qBuf: fusedBuf, kBuf: fusedBuf, vBuf: fusedBuf, lensBuf, B, M: S, L: S, lenMode: 1, block,\n strides: { Q_STRIDE: 3 * HD, Q_OFF: 0, KV_STRIDE: 3 * HD, K_OFF: HD, V_OFF: 2 * HD },\n },\n want, tol, {\n kernel: block ? `attention_block qb${block.qb} jb${block.jb}` : 'attention',\n mode: 'encoder-fused', B, S, lens: lens.join(','), t,\n });\n for (const b of [fusedBuf, lensBuf]) b.destroy();\n return result;\n}\n\n// ------------------------------------------- decode: kv_append + attention ---\n\n// Simulates 5 decode steps: each appends a random fused [B, 3·HD] row into the\n// K/V caches via kv_append APPEND, then attention runs with lenMode 0, t=4.\n// The reference assembles k/v in JS from the SAME fused rows, so kv_append's\n// cache indexing is cross-validated through attention.\nasync function runDecodeCase(ctx, { B, Lmax, steps, t, tol, seed, sg = false }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n\n // Zero-initialized caches, [B, Lmax, H, D]. Positions >= steps stay zero and\n // must never be read (len = t+1 = steps).\n const cacheBytes = B * Lmax * HD * elemBytes(t);\n const kBuf = device.createBuffer({ size: cacheBytes, usage: GPUBufferUsage.STORAGE });\n const vBuf = device.createBuffer({ size: cacheBytes, usage: GPUBufferUsage.STORAGE });\n\n const appendPipe = kvAppendPipeline(device, t, 'append');\n const kRef = new Float32Array(B * Lmax * HD);\n const vRef = new Float32Array(B * Lmax * HD);\n const qF32 = new Float32Array(B * HD);\n for (let step = 0; step < steps; step++) {\n const fused = prep(randF32(B * 3 * HD, rng), t); // [B, q|k|v]\n const fusedBuf = createBuffer(device, fused.data, usage);\n const params = makeUniform(device, [B, step, Lmax, 0]);\n dispatch(device, appendPipe, [params, fusedBuf, kBuf, vBuf], Math.ceil((B * HD) / 128));\n for (let b = 0; b < B; b++) {\n const dst = (b * Lmax + step) * HD;\n kRef.set(fused.ref.subarray(b * 3 * HD + HD, b * 3 * HD + 2 * HD), dst);\n vRef.set(fused.ref.subarray(b * 3 * HD + 2 * HD, b * 3 * HD + 3 * HD), dst);\n if (step === steps - 1) {\n // The last step's q slice feeds attention — matches how the engine\n // consumes the fused QKV projection during decode.\n qF32.set(fused.ref.subarray(b * 3 * HD, b * 3 * HD + HD), b * HD);\n }\n }\n fusedBuf.destroy();\n }\n const q = prep(qF32, t); // ref values are already f16-exact; re-encode is lossless\n const qBuf = createBuffer(device, q.data, usage);\n const want = attentionRef(q.ref, kRef, vRef, {\n B, M: 1, H, D, L: Lmax, lens: Array(B).fill(steps),\n });\n const result = await runAttentionAndCompare(\n device, t, { qBuf, kBuf, vBuf, lensBuf: null, B, M: 1, L: Lmax, lenMode: 0, step: steps - 1, sg },\n want, tol, { kernel: 'kv_append+attention', mode: 'decode', B, Lmax, steps, t });\n for (const b of [qBuf, kBuf, vBuf]) b.destroy();\n return result;\n}\n\n// -------------------------------------------- cross: kv_split + attention ---\n\n// kv_append SPLIT scatters fused [B·S, 2·HD] into K/V [B, S, H, D] (L = S),\n// then attention runs with lenMode 1 and ragged lens.\nasync function runCrossCase(ctx, { B, S, lens, t, tol, seed, sg = false }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const rows = B * S;\n\n const fused = prep(randF32(rows * 2 * HD, rng), t);\n const fusedBuf = createBuffer(device, fused.data, usage);\n const cacheBytes = rows * HD * elemBytes(t);\n const kBuf = device.createBuffer({ size: cacheBytes, usage: GPUBufferUsage.STORAGE });\n const vBuf = device.createBuffer({ size: cacheBytes, usage: GPUBufferUsage.STORAGE });\n const splitPipe = kvAppendPipeline(device, t, 'split');\n const params = makeUniform(device, [B, 0, 0, rows]);\n dispatch(device, splitPipe, [params, fusedBuf, kBuf, vBuf], Math.ceil((rows * HD) / 128));\n\n const kRef = new Float32Array(rows * HD);\n const vRef = new Float32Array(rows * HD);\n for (let r = 0; r < rows; r++) {\n kRef.set(fused.ref.subarray(r * 2 * HD, r * 2 * HD + HD), r * HD);\n vRef.set(fused.ref.subarray(r * 2 * HD + HD, r * 2 * HD + 2 * HD), r * HD);\n }\n const q = prep(randF32(B * HD, rng), t);\n const qBuf = createBuffer(device, q.data, usage);\n const lensBuf = createBuffer(device, new Uint32Array(lens), usage);\n const want = attentionRef(q.ref, kRef, vRef, { B, M: 1, H, D, L: S, lens });\n const result = await runAttentionAndCompare(\n device, t, { qBuf, kBuf, vBuf, lensBuf, B, M: 1, L: S, lenMode: 1, sg },\n want, tol, { kernel: 'kv_split+attention', mode: 'cross', B, S, lens: lens.join(','), t });\n for (const b of [fusedBuf, qBuf, kBuf, vBuf, lensBuf]) b.destroy();\n return result;\n}\n\nfunction registerF16(name, fn) {\n registerTest(name, (ctx) =>\n ctx.hasF16 ? fn(ctx) : { skip: true, reason: 'no shader-f16' });\n}\n\n// f16 tol 0.03: D=56 dots and up-to-352-term weighted sums accumulate in f32,\n// but f16 output rounding + softmax weight sensitivity warrant slack.\nregisterF16('attn_encoder_f16', (ctx) =>\n runEncoderCase(ctx, { B: 2, M: 16, L: 16, lens: [16, 9], t: 'f16', tol: 0.03, seed: 301 }));\nregisterF16('attn_encoder_fused_f16', (ctx) =>\n runEncoderFusedCase(ctx, { B: 2, S: 16, lens: [16, 9], t: 'f16', tol: 0.03, seed: 305 }));\nregisterF16('attn_decode_f16', (ctx) =>\n runDecodeCase(ctx, { B: 3, Lmax: 32, steps: 5, t: 'f16', tol: 0.03, seed: 302 }));\nregisterF16('attn_cross_f16', (ctx) =>\n runCrossCase(ctx, { B: 2, S: 32, lens: [32, 20], t: 'f16', tol: 0.03, seed: 303 }));\n// f32 fallback-mode sanity for the template.\nregisterTest('attn_encoder_f32', (ctx) =>\n runEncoderCase(ctx, { B: 1, M: 4, L: 4, lens: [3], t: 'f32', tol: 1e-4, seed: 304 }));\n\n// Blocked encoder kernel (attention_block.wgsl). Shapes chosen to exercise\n// every guard: M not a multiple of QB (query tail block), lens crossing\n// several JB tiles with a partial last tile, ragged lens including a len < JB\n// row, and both compact and fused-QKV layouts. Tol matches the unblocked f16\n// cases — online softmax changes summation order, not precision class.\nregisterF16('attn_block_encoder_f16', (ctx) =>\n runEncoderCase(ctx, {\n B: 2, M: 20, L: 20, lens: [20, 9], t: 'f16', tol: 0.03, seed: 311,\n block: { qb: 8, jb: 16 },\n }));\nregisterF16('attn_block_encoder_fused_f16', (ctx) =>\n runEncoderFusedCase(ctx, {\n B: 3, S: 33, lens: [33, 17, 5], t: 'f16', tol: 0.03, seed: 312,\n block: { qb: 16, jb: 32 },\n }));\nregisterF16('attn_block_encoder_fused_jb48_f16', (ctx) =>\n runEncoderFusedCase(ctx, {\n B: 2, S: 50, lens: [50, 49], t: 'f16', tol: 0.03, seed: 313,\n block: { qb: 8, jb: 48 },\n }));\nregisterTest('attn_block_encoder_f32', (ctx) =>\n runEncoderCase(ctx, {\n B: 2, M: 9, L: 12, lens: [12, 3], t: 'f32', tol: 1e-4, seed: 314,\n block: { qb: 8, jb: 16 },\n }));\n\n// Subgroup-reduction attention (flags.sg — IF_SG variant): tolerance-equal\n// to the tree (reduction order differs), and the CORRECTNESS route on\n// Adreno 7xx, whose driver miscompiles this kernel's tree reduce (2026-07\n// Android round; autotune force-enables sg there). Shapes mirror the plain\n// cases, same seeds → same data.\nconst sgSkip = (ctx) => (ctx.hasSubgroups ? null : { skip: true, reason: 'subgroups feature unavailable' });\nregisterTest('attn_sg_encoder_f16', (ctx) => sgSkip(ctx)\n ?? (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runEncoderCase(ctx, { B: 2, M: 16, L: 16, lens: [16, 9], t: 'f16', tol: 0.03, seed: 301, sg: true })));\nregisterTest('attn_sg_decode_f16', (ctx) => sgSkip(ctx)\n ?? (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runDecodeCase(ctx, { B: 3, Lmax: 32, steps: 5, t: 'f16', tol: 0.03, seed: 302, sg: true })));\nregisterTest('attn_sg_cross_f16', (ctx) => sgSkip(ctx)\n ?? (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runCrossCase(ctx, { B: 2, S: 32, lens: [32, 20], t: 'f16', tol: 0.03, seed: 303, sg: true })));\nregisterTest('attn_sg_encoder_f32', (ctx) => sgSkip(ctx)\n ?? runEncoderCase(ctx, { B: 1, M: 4, L: 4, lens: [3], t: 'f32', tol: 1e-4, seed: 304, sg: true }));\n\n// Long-L sg arms — the production shape the short goldens miss: app rows are\n// ~200 chars → decode self-attn len grows past WG=128 (the scan loop turns\n// multi-trip per thread) and cross len ≈ S ≈ 100-192. The Adreno miscompile\n// family is context-sensitive (multi-trip strided loops were an ingredient),\n// so the sg variant must be proven AT THESE LENGTHS on-device, not just at\n// golden-sentence lengths.\nregisterTest('attn_sg_long_encoder_f16', (ctx) => sgSkip(ctx)\n ?? (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runEncoderCase(ctx, { B: 2, M: 8, L: 224, lens: [224, 131], t: 'f16', tol: 0.03, seed: 321, sg: true })));\nregisterTest('attn_sg_long_decode_f16', (ctx) => sgSkip(ctx)\n ?? (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runDecodeCase(ctx, { B: 2, Lmax: 224, steps: 160, t: 'f16', tol: 0.03, seed: 322, sg: true })));\nregisterTest('attn_sg_long_cross_f16', (ctx) => sgSkip(ctx)\n ?? (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runCrossCase(ctx, { B: 2, S: 192, lens: [192, 130], t: 'f16', tol: 0.03, seed: 323, sg: true })));\n// Tree twins at the same long shapes: FAIL expected on the affected Adreno\n// (tree broken there) — they double as the on-device control that the long\n// shapes do exercise the broken paths.\nregisterTest('attn_long_encoder_f16', (ctx) => (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runEncoderCase(ctx, { B: 2, M: 8, L: 224, lens: [224, 131], t: 'f16', tol: 0.03, seed: 321 })));\nregisterTest('attn_long_decode_f16', (ctx) => (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : runDecodeCase(ctx, { B: 2, Lmax: 224, steps: 160, t: 'f16', tol: 0.03, seed: 322 })));\n"],"names":["kvAppendSource","H","HEADS","D","HEAD_DIM","HD","mulberry32","seed","a","t","randF32","n","rng","out","i","prep","f32arr","half","f32ToF16","expandF16","makeUniform","device","vals","size","buf","elemBytes","attentionPipeline","strides","sg","getPipeline","attentionSource","SCORES_CAP","ATTN_SCALE","attentionBlockPipeline","qb","jb","attentionBlockSource","kvAppendPipeline","mode","dispatch","pipeline","buffers","wgX","wgY","wgZ","bindGroup","buffer","binding","encoder","pass","runAttentionAndCompare","qBuf","kBuf","vBuf","lensBuf","B","M","L","lenMode","step","block","want","tol","label","params","scratch","lens","outElems","yBuf","raw","readback","got","b","failures","maxAbsDiff","worst","compareLanes","runEncoderCase","ctx","q","k","v","attentionRef","usage","createBuffer","result","runEncoderFusedCase","S","rows","fused","qRef","kRef","vRef","r","fusedBuf","runDecodeCase","Lmax","steps","cacheBytes","appendPipe","qF32","dst","runCrossCase","splitPipe","registerF16","name","fn","registerTest","sgSkip"],"mappings":"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"}
assets/attn_sweep-C5U-KhDy.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as D}from"./debug-Cn7EHWtJ.js";import{r as S,a as x}from"./gpu-utils-BTh3AGTJ.js";import{l as A}from"./weights-B-okS09o.js";import{l as F,t as B}from"./tokenizer-Ex1u7wXD.js";import{r as E}from"./encoder-DX8MOfcH.js";import{e as L}from"./f16-wKKZr58e.js";import{D as M}from"./constants-C8VbFpic.js";import{p as N}from"./bench-C8ITpm5I.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./pipelines-DD24nEJg.js";import"./generate-C4ruG1zm.js";import"./decoder-DI6VDxxO.js";import"./chapter3k-Bxq8ds-a.js";const g=7,y=.02,a=[{name:"v1",overrides:{block:!1}},{name:"qb8jb32",overrides:{qb:8,jb:32}},{name:"qb16jb32",overrides:{qb:16,jb:32}},{name:"qb8jb48",overrides:{qb:8,jb:48}},{name:"qb16jb16",overrides:{qb:16,jb:16}}],T=n=>{const e=[...n].sort((i,c)=>i-c),o=e.length>>1;return e.length%2?e[o]:(e[o-1]+e[o])/2};D("attn_sweep",async n=>{const{device:e}=n,o=n.hasF16?"f16":"f32",i=await A(e,"/weights",{targetDtype:o});try{const c=await F(),h={device:e,dtype:o},v=[...N("file23k")].sort((t,r)=>r.length-t.length),m=await B(c,v.slice(0,64)),f=async(t,{grabOut:r=!1}={})=>{const u=performance.now(),s=await E(h,i,m,{attnOverrides:t});await e.queue.onSubmittedWorkDone();const k=performance.now()-u;let d=null;if(r){const q=m.B*s.S*M*(o==="f16"?2:4),w=await S(e,s.encOut,q);d=o==="f16"?L(new Uint16Array(w)):new Float32Array(w)}return s.arena.destroy(),{ms:k,out:d}},O=(await f(a[0].overrides,{grabOut:!0})).out,b={};for(const t of a.slice(1)){const{out:r}=await f(t.overrides,{grabOut:!0}),{failures:u,maxAbsDiff:s}=x(r,O,y);b[t.name]={failures:u,maxAbsDiff:String(s)}}const p=Object.fromEntries(a.map(t=>[t.name,[]]));for(let t=0;t<g;t++)for(const r of a)p[r.name].push((await f(r.overrides)).ms);const j=a.map(t=>({config:t.name,medianMs:Number(T(p[t.name]).toFixed(1)),runs:p[t.name].map(r=>Number(r.toFixed(1)))})),l=Object.values(b).every(t=>t.failures===0);return{pass:l,detail:{dtype:o,B:m.B,S:m.S,rounds:g,tol:y,parityOk:l,parity:b,table:j}}}finally{i.buffer.destroy()}});
2
+ //# sourceMappingURL=attn_sweep-C5U-KhDy.js.map
assets/attn_sweep-C5U-KhDy.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"attn_sweep-C5U-KhDy.js","sources":["../../src/debug/tests/attn_sweep.js"],"sourcesContent":["// Blocked-attention A/B for the encoder self-attention site: unblocked v1\n// control vs QB×JB tile shapes of attention_block.wgsl — picks the default\n// QB/JB in pipelines.js. Arms measured ROUND-ROBIN in one session (sequential\n// runner invocations drift ±30% with laptop thermals); wall clock per run =\n// runEncoder submit → onSubmittedWorkDone, medians over ROUNDS.\n//\n// Correctness gate: every arm's encOut must match the v1 control within TOL\n// (online softmax reorders f32 sums — bit-equality is not expected, but after\n// 8 layers of f16 storage rounding the drift stays ~1e-3).\nimport { registerTest } from '../registry.js';\nimport { readback, compareLanes } from '../gpu-utils.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { expandF16 } from '../../engine/f16.js';\nimport { D_MODEL } from '../../engine/constants.js';\nimport { presetChunks } from '../../bench/bench.js';\n\nconst ROUNDS = 7;\nconst TOL = 0.02;\nconst ARMS = [\n { name: 'v1', overrides: { block: false } },\n { name: 'qb8jb32', overrides: { qb: 8, jb: 32 } },\n { name: 'qb16jb32', overrides: { qb: 16, jb: 32 } },\n { name: 'qb8jb48', overrides: { qb: 8, jb: 48 } },\n { name: 'qb16jb16', overrides: { qb: 16, jb: 16 } },\n];\n\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nregisterTest('attn_sweep', async (ctx) => {\n const { device } = ctx;\n const dtype = ctx.hasF16 ? 'f16' : 'f32';\n const weights = await loadWeights(device, '/weights', { targetDtype: dtype });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n const batch = await tokenizeBatch(tok, chunks.slice(0, 64));\n\n const runOne = async (overrides, { grabOut = false } = {}) => {\n const t0 = performance.now();\n const run = await runEncoder(gctx, weights, batch, { attnOverrides: overrides });\n await device.queue.onSubmittedWorkDone();\n const ms = performance.now() - t0;\n let out = null;\n if (grabOut) {\n const bytes = batch.B * run.S * D_MODEL * (dtype === 'f16' ? 2 : 4);\n const raw = await readback(device, run.encOut, bytes);\n out = dtype === 'f16' ? expandF16(new Uint16Array(raw)) : new Float32Array(raw);\n }\n run.arena.destroy();\n return { ms, out };\n };\n\n // Warmup (pipeline compiles) + parity gate vs the v1 control.\n const base = (await runOne(ARMS[0].overrides, { grabOut: true })).out;\n const parity = {};\n for (const arm of ARMS.slice(1)) {\n const { out } = await runOne(arm.overrides, { grabOut: true });\n const { failures, maxAbsDiff } = compareLanes(out, base, TOL);\n parity[arm.name] = { failures, maxAbsDiff: String(maxAbsDiff) };\n }\n\n const times = Object.fromEntries(ARMS.map((a) => [a.name, []]));\n for (let r = 0; r < ROUNDS; r++) {\n for (const a of ARMS) times[a.name].push((await runOne(a.overrides)).ms);\n }\n\n const table = ARMS.map((a) => ({\n config: a.name,\n medianMs: Number(median(times[a.name]).toFixed(1)),\n runs: times[a.name].map((x) => Number(x.toFixed(1))),\n }));\n const parityOk = Object.values(parity).every((p) => p.failures === 0);\n return { pass: parityOk, detail: { dtype, B: batch.B, S: batch.S, rounds: ROUNDS, tol: TOL, parityOk, parity, table } };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["ROUNDS","TOL","ARMS","median","xs","s","a","b","m","registerTest","ctx","device","dtype","weights","loadWeights","tok","loadTokenizer","gctx","chunks","presetChunks","batch","tokenizeBatch","runOne","overrides","grabOut","t0","run","runEncoder","ms","out","bytes","D_MODEL","raw","readback","expandF16","base","parity","arm","failures","maxAbsDiff","compareLanes","times","r","table","x","parityOk","p"],"mappings":"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"}
assets/autotune-Cy4x-YB7.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as w}from"./debug-Cn7EHWtJ.js";import{l as T}from"./weights-B-okS09o.js";import{autotuneRouting as M,DEFAULT_ROUTING as E,tunedOptions as F}from"./autotune-DBJGFXNj.js";import{r as N}from"./encoder-DX8MOfcH.js";import{c as U,e as A}from"./decoder-DI6VDxxO.js";import{V as W,e as j}from"./constants-C8VbFpic.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./f16-wKKZr58e.js";import"./pipelines-DD24nEJg.js";const b=t=>{const o=[...t].sort((s,e)=>s-e),n=o.length>>1;return o.length%2?o[n]:(o[n-1]+o[n])/2};async function O(t,o){const n=await T(t.device,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0,projWT:!0});try{return await o(n)}finally{n.buffer.destroy()}}w("autotune_policy",async t=>t.hasF16?O(t,async o=>{const n={device:t.device,dtype:"f16",limits:t.limits,hasSubgroups:t.hasSubgroups,subgroupMinSize:t.subgroupMinSize},s=performance.now(),{tuned:e,timings:m}=await M(n,o),i=Number((performance.now()-s).toFixed(0)),c=[0,4].includes(e.fuseLnMaxB)&&[16,32].includes(e.lmHeadMinB)&&["auto","off"].includes(e.lmHeadFuse)&&[32,64,128].includes(e.projTiledMinB)&&["auto","off"].includes(e.decodeMega)&&["on","off"].includes(e.sg),d=JSON.stringify(e)===JSON.stringify(E);return{pass:c,detail:{tuned:e,isDefault:d,tuneMs:i,timings:m}}}):{skip:!0,reason:"no shader-f16"});function k(t,o){const n=new Uint32Array(t*o);let s=625341585;for(let e=0;e<n.length;e++)s=Math.imul(s,1664525)+1013904223>>>0,n[e]=100+s%(W-200);for(let e=0;e<t;e++)n[e*o+o-1]=j;return{ids:n,lens:new Uint32Array(t).fill(o),B:t,S:o}}async function S(t,o,n,s,e,m){const{device:i}=t,c=U(t,o,{B:s,S:n.S,maxSteps:e,...m});try{const d=performance.now();for(let a=0;a<e;a+=8){const u=Math.min(a+8,e),p=i.createCommandEncoder(),f=p.beginComputePass(),l=[];for(let r=a;r<u;r++)l.push(...A(t,o,n,c,r,f).scratch);f.end(),i.queue.submit([p.finish()]);for(const r of l)r.destroy()}return await i.queue.onSubmittedWorkDone(),Number(((performance.now()-d)*1e3/e).toFixed(1))}finally{c.destroy()}}w("autotune_gate",async t=>t.hasF16?O(t,async o=>{const n={device:t.device,dtype:"f16",limits:t.limits,hasSubgroups:t.hasSubgroups,subgroupMinSize:t.subgroupMinSize},{tuned:s}=await M(n,o),e=[1,16,64],m=5,i=24,c=96,d=[];let a=!0;for(const u of e){const p=k(u,c),f=await N(n,o,p);await n.device.queue.onSubmittedWorkDone();try{const l={auto:{},tuned:F(s,u)};for(const g of Object.values(l))await S(n,o,f,u,i,g);const r={auto:[],tuned:[]};for(let g=0;g<m;g++)for(const[v,D]of Object.entries(l))r[v].push(await S(n,o,f,u,i,D));const y=b(r.auto),h=b(r.tuned);h>y*1.07&&(a=!1),d.push({B:u,autoUs:y,tunedUs:h,deltaPct:Number(((h-y)/y*100).toFixed(1)),runs:r})}finally{f.arena.destroy()}}return{pass:a,detail:{tuned:s,table:d}}}):{skip:!0,reason:"no shader-f16"},{slow:!0});
2
+ //# sourceMappingURL=autotune-Cy4x-YB7.js.map
assets/autotune-Cy4x-YB7.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"autotune-Cy4x-YB7.js","sources":["../../src/debug/tests/autotune.js"],"sourcesContent":["// Routing autotune: measure-then-pin the routing decisions whose winners\n// flip between adapters (see engine/autotune.js header).\n//\n// autotune_policy (fast, ~1s dGPU / ~10s iGPU): run autotuneRouting on THIS\n// adapter with the production weights and report the chosen thresholds plus\n// the raw arm medians. pass = the thresholds come from their allowed sets —\n// the point of the test is the printed policy per adapter.\n//\n// autotune_gate (SLOW): interleaved A/B of decoder.js 'auto' vs the tuned\n// policy at B ∈ {1, 16, 64} — asserts tuned is never worse than 'auto'\n// beyond noise (7%) at any measured batch, and reports what it buys. On the\n// 5070 Ti the policy should resolve to the defaults and read ~0%.\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { autotuneRouting, tunedOptions, DEFAULT_ROUTING } from '../../engine/autotune.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { createDecodeState, encodeDecodeStep } from '../../engine/decoder.js';\nimport { EOS, VOCAB } from '../../engine/constants.js';\n\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nasync function withProdWeights(ctx, fn) {\n const weights = await loadWeights(ctx.device, '/weights', {\n targetDtype: 'f16', lmHeadQ8: true, ffnWT: true, projWT: true,\n });\n try {\n return await fn(weights);\n } finally {\n weights.buffer.destroy();\n }\n}\n\nregisterTest('autotune_policy', async (ctx) => {\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n return withProdWeights(ctx, async (weights) => {\n const gctx = {\n device: ctx.device, dtype: 'f16', limits: ctx.limits,\n hasSubgroups: ctx.hasSubgroups, subgroupMinSize: ctx.subgroupMinSize,\n };\n const t0 = performance.now();\n const { tuned, timings } = await autotuneRouting(gctx, weights);\n const tuneMs = Number((performance.now() - t0).toFixed(0));\n const sane =\n [0, 4].includes(tuned.fuseLnMaxB) &&\n [16, 32].includes(tuned.lmHeadMinB) &&\n ['auto', 'off'].includes(tuned.lmHeadFuse) &&\n [32, 64, 128].includes(tuned.projTiledMinB) &&\n ['auto', 'off'].includes(tuned.decodeMega) &&\n ['on', 'off'].includes(tuned.sg);\n const isDefault = JSON.stringify(tuned) === JSON.stringify(DEFAULT_ROUTING);\n return { pass: sane, detail: { tuned, isDefault, tuneMs, timings } };\n });\n});\n\n// Same synthetic-batch step timing as autotuneRouting, reused for the gate's\n// independent A/B (fresh state per arm, grouped submits of 8).\nfunction syntheticBatch(B, S) {\n const ids = new Uint32Array(B * S);\n let x = 0x2545f491;\n for (let i = 0; i < ids.length; i++) {\n x = (Math.imul(x, 1664525) + 1013904223) >>> 0;\n ids[i] = 100 + (x % (VOCAB - 200));\n }\n for (let b = 0; b < B; b++) ids[b * S + S - 1] = EOS;\n return { ids, lens: new Uint32Array(B).fill(S), B, S };\n}\n\nasync function timeArm(ctx, weights, encRun, B, steps, opts) {\n const { device } = ctx;\n const state = createDecodeState(ctx, weights, { B, S: encRun.S, maxSteps: steps, ...opts });\n try {\n const t0 = performance.now();\n for (let g = 0; g < steps; g += 8) {\n const tEnd = Math.min(g + 8, steps);\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n const scratch = [];\n for (let t = g; t < tEnd; t++) {\n scratch.push(...encodeDecodeStep(ctx, weights, encRun, state, t, pass).scratch);\n }\n pass.end();\n device.queue.submit([encoder.finish()]);\n for (const b of scratch) b.destroy();\n }\n await device.queue.onSubmittedWorkDone();\n return Number((((performance.now() - t0) * 1000) / steps).toFixed(1));\n } finally {\n state.destroy();\n }\n}\n\nregisterTest(\n 'autotune_gate',\n async (ctx) => {\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n return withProdWeights(ctx, async (weights) => {\n const gctx = {\n device: ctx.device, dtype: 'f16', limits: ctx.limits,\n hasSubgroups: ctx.hasSubgroups, subgroupMinSize: ctx.subgroupMinSize,\n };\n const { tuned } = await autotuneRouting(gctx, weights);\n\n const BATCHES = [1, 16, 64];\n const ROUNDS = 5;\n const STEPS = 24;\n const S = 96;\n const table = [];\n let pass = true;\n for (const B of BATCHES) {\n const batch = syntheticBatch(B, S);\n const encRun = await runEncoder(gctx, weights, batch);\n await gctx.device.queue.onSubmittedWorkDone();\n try {\n const arms = { auto: {}, tuned: tunedOptions(tuned, B) };\n for (const opts of Object.values(arms)) await timeArm(gctx, weights, encRun, B, STEPS, opts);\n const runs = { auto: [], tuned: [] };\n for (let r = 0; r < ROUNDS; r++) {\n for (const [name, opts] of Object.entries(arms)) {\n runs[name].push(await timeArm(gctx, weights, encRun, B, STEPS, opts));\n }\n }\n const autoUs = median(runs.auto);\n const tunedUs = median(runs.tuned);\n if (tunedUs > autoUs * 1.07) pass = false;\n table.push({\n B, autoUs, tunedUs,\n deltaPct: Number((((tunedUs - autoUs) / autoUs) * 100).toFixed(1)),\n runs,\n });\n } finally {\n encRun.arena.destroy();\n }\n }\n return { pass, detail: { tuned, table } };\n });\n },\n { slow: true },\n);\n"],"names":["median","xs","s","a","b","m","withProdWeights","ctx","fn","weights","loadWeights","registerTest","gctx","t0","tuned","timings","autotuneRouting","tuneMs","sane","isDefault","DEFAULT_ROUTING","syntheticBatch","B","S","ids","x","i","VOCAB","EOS","timeArm","encRun","steps","opts","device","state","createDecodeState","g","tEnd","encoder","pass","scratch","t","encodeDecodeStep","BATCHES","ROUNDS","STEPS","table","batch","runEncoder","arms","tunedOptions","runs","r","name","autoUs","tunedUs"],"mappings":"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"}
assets/baseline-D00dppjV.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as u}from"./debug-Cn7EHWtJ.js";import{runReference as l}from"./reference-Dj87VRUN.js";import{g as h}from"./golden-BEvfygyg.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./constants-C8VbFpic.js";const b=8;u("baseline_reference",async()=>{const a=h.items.slice(0,b),i=a.map(e=>e.source),m=a.map(e=>e.text),p=[{device:"wasm",dtype:"q8",batch:1},{device:"wasm",dtype:"q8",batch:4},{device:"webgpu",dtype:"fp16",batch:1},{device:"webgpu",dtype:"fp16",batch:4}],r=[];for(const{device:e,dtype:o,batch:s}of p)try{const t=await l({device:e,dtype:o,sources:i,batchSize:s,onStatus:c=>console.log(`[baseline ${e}/${o} b${s}] ${c}`)}),n={runtime:e,dtype:o,batch:s,loadMs:Math.round(t.loadMs),translateMs:Math.round(t.translateMs),tokens:t.tokens,tokPerSec:Number(t.tokPerSec.toFixed(1)),charsPerSec:Number(t.charsPerSec.toFixed(1))};e==="wasm"&&s===1&&(n.exactVsGolden=t.texts.filter((c,d)=>c===m[d]).length),r.push(n)}catch(t){r.push({runtime:e,dtype:o,batch:s,error:String(t?.message??t)})}return{pass:r.some(e=>!e.error),detail:{runs:r}}},{slow:!0});
2
+ //# sourceMappingURL=baseline-D00dppjV.js.map
assets/baseline-D00dppjV.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"baseline-D00dppjV.js","sources":["../../src/debug/tests/baseline.js"],"sourcesContent":["// Early reference baseline (slow): Transformers.js wasm/q8 and webgpu/fp16\n// translation speed on the first 8 golden sources. Results are hand-copied\n// into docs/bench/baseline.json — they are the denominators for the spike's\n// success criteria.\nimport { registerTest } from '../registry.js';\nimport { runReference } from '../../bench/reference.js';\nimport golden from '../../../fixtures/golden.json';\n\nconst N_ITEMS = 8;\n\nregisterTest(\n 'baseline_reference',\n async () => {\n const items = golden.items.slice(0, N_ITEMS);\n const sources = items.map((it) => it.source);\n const goldenTexts = items.map((it) => it.text);\n\n const configs = [\n { device: 'wasm', dtype: 'q8', batch: 1 },\n { device: 'wasm', dtype: 'q8', batch: 4 },\n { device: 'webgpu', dtype: 'fp16', batch: 1 },\n { device: 'webgpu', dtype: 'fp16', batch: 4 },\n ];\n\n const runs = [];\n for (const { device, dtype, batch } of configs) {\n try {\n const res = await runReference({\n device,\n dtype,\n sources,\n batchSize: batch,\n onStatus: (msg) => console.log(`[baseline ${device}/${dtype} b${batch}] ${msg}`),\n });\n const run = {\n runtime: device,\n dtype,\n batch,\n loadMs: Math.round(res.loadMs),\n translateMs: Math.round(res.translateMs),\n tokens: res.tokens,\n tokPerSec: Number(res.tokPerSec.toFixed(1)),\n charsPerSec: Number(res.charsPerSec.toFixed(1)),\n };\n if (device === 'wasm' && batch === 1) {\n // Report-only: q8 vs fp32 golden will differ some; expect >=6/8.\n run.exactVsGolden = res.texts.filter((t, i) => t === goldenTexts[i]).length;\n }\n runs.push(run);\n } catch (err) {\n runs.push({ runtime: device, dtype, batch, error: String(err?.message ?? err) });\n }\n }\n\n const pass = runs.some((r) => !r.error); // fail only if ALL four runs errored\n return { pass, detail: { runs } };\n },\n { slow: true },\n);\n"],"names":["N_ITEMS","registerTest","items","golden","sources","it","goldenTexts","configs","runs","device","dtype","batch","res","runReference","msg","run","t","i","err","r"],"mappings":"uRAQA,MAAMA,EAAU,EAEhBC,EACE,qBACA,SAAY,CACV,MAAMC,EAAQC,EAAO,MAAM,MAAM,EAAGH,CAAO,EACrCI,EAAUF,EAAM,IAAKG,GAAOA,EAAG,MAAM,EACrCC,EAAcJ,EAAM,IAAKG,GAAOA,EAAG,IAAI,EAEvCE,EAAU,CACd,CAAE,OAAQ,OAAQ,MAAO,KAAM,MAAO,CAAC,EACvC,CAAE,OAAQ,OAAQ,MAAO,KAAM,MAAO,CAAC,EACvC,CAAE,OAAQ,SAAU,MAAO,OAAQ,MAAO,CAAC,EAC3C,CAAE,OAAQ,SAAU,MAAO,OAAQ,MAAO,CAAC,CACjD,EAEUC,EAAO,CAAA,EACb,SAAW,CAAE,OAAAC,EAAQ,MAAAC,EAAO,MAAAC,CAAK,IAAMJ,EACrC,GAAI,CACF,MAAMK,EAAM,MAAMC,EAAa,CAC7B,OAAAJ,EACA,MAAAC,EACA,QAAAN,EACA,UAAWO,EACX,SAAWG,GAAQ,QAAQ,IAAI,aAAaL,CAAM,IAAIC,CAAK,KAAKC,CAAK,KAAKG,CAAG,EAAE,CACzF,CAAS,EACKC,EAAM,CACV,QAASN,EACT,MAAAC,EACA,MAAAC,EACA,OAAQ,KAAK,MAAMC,EAAI,MAAM,EAC7B,YAAa,KAAK,MAAMA,EAAI,WAAW,EACvC,OAAQA,EAAI,OACZ,UAAW,OAAOA,EAAI,UAAU,QAAQ,CAAC,CAAC,EAC1C,YAAa,OAAOA,EAAI,YAAY,QAAQ,CAAC,CAAC,CACxD,EACYH,IAAW,QAAUE,IAAU,IAEjCI,EAAI,cAAgBH,EAAI,MAAM,OAAO,CAACI,EAAGC,IAAMD,IAAMV,EAAYW,CAAC,CAAC,EAAE,QAEvET,EAAK,KAAKO,CAAG,CACf,OAASG,EAAK,CACZV,EAAK,KAAK,CAAE,QAASC,EAAQ,MAAAC,EAAO,MAAAC,EAAO,MAAO,OAAOO,GAAK,SAAWA,CAAG,CAAC,CAAE,CACjF,CAIF,MAAO,CAAE,KADIV,EAAK,KAAMW,GAAM,CAACA,EAAE,KAAK,EACvB,OAAQ,CAAE,KAAAX,CAAI,CAAE,CACjC,EACA,CAAE,KAAM,EAAI,CACd"}
assets/batch_cap_ab-DpomwYzZ.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as T}from"./debug-Cn7EHWtJ.js";import{l as B}from"./weights-B-okS09o.js";import{l as M}from"./tokenizer-Ex1u7wXD.js";import{t as S}from"./generate-C4ruG1zm.js";import{g as D}from"./constants-C8VbFpic.js";import{s as A,p as C,a as E}from"./engine-BTyy_WlH.js";import{c as O}from"./chapter3k-Bxq8ds-a.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./f16-wKKZr58e.js";import"./encoder-DX8MOfcH.js";import"./pipelines-DD24nEJg.js";import"./decoder-DI6VDxxO.js";import"./device-Z_ibNtmX.js";import"./autotune-DBJGFXNj.js";const P=n=>{const e=[...n].sort((m,a)=>m-a),o=e.length>>1;return e.length%2?e[o]:(e[o-1]+e[o])/2},f=[128,192,256],w=5;T("batch_cap_ab",async n=>{const{device:e}=n;if(!n.hasF16)return{skip:!0,reason:"production stack needs shader-f16"};const o=await B(e,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0,projWT:!0});try{const m=await M(),a={device:e,dtype:"f16",limits:n.limits},c=O.repeat(16),u=A(c),{rows:i}=C(u.sentences,u.paras,200),k=i.map(t=>t.length),b=async t=>{const s=E(k,a,2,t),r=performance.now();let g=0;for(const[h,l]of s){const{metrics:x}=await S(a,o,m,i.slice(h,l),{maxNewTokens:D});g+=x.tokensGenerated}return{ms:performance.now()-r,tokens:g,batches:s.length,maxB:Math.max(...s.map(([h,l])=>l-h))}},p=Object.fromEntries(f.map(t=>[t,[]]));let d={};for(let t=0;t<w;t++)for(const s of f){const r=await b(s);p[s].push(r.ms),d[s]={batches:r.batches,maxB:r.maxB,tokens:r.tokens}}const y=f.map(t=>{const s=P(p[t]);return{cap:t,medianMs:Math.round(s*10)/10,charsPerSec:Math.round(c.length/s*1e3),...d[t],runs:p[t].map(r=>Math.round(r))}});return{pass:!0,detail:{chars:c.length,rows:i.length,rounds:w,table:y}}}finally{o.buffer.destroy()}},{slow:!0});
2
+ //# sourceMappingURL=batch_cap_ab-DpomwYzZ.js.map
assets/batch_cap_ab-DpomwYzZ.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"batch_cap_ab-DpomwYzZ.js","sources":["../../src/debug/tests/batch_cap_ab.js"],"sourcesContent":["// batch_cap_ab: e2e A/B for the app's planBatches hardCap at pack200 —\n// decode step scaling is sublinear in B (b64→b128 = 1.6× step for 2× rows),\n// so a bigger cap may buy throughput if VRAM/binding limits allow. Arms\n// share one source (chapter3k ×16 so the biggest cap still fills ≥2 batches).\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer } from '../../engine/tokenizer.js';\nimport { translateBatch } from '../../engine/generate.js';\nimport { DECODE_CAP } from '../../engine/constants.js';\nimport { segmentSource, packSentences } from '../../app/split.js';\nimport { planBatches } from '../../app/engine.js';\nimport chapterText from '../../../fixtures/chapter3k.txt?raw';\n\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nconst CAPS = [128, 192, 256];\nconst ROUNDS = 5;\n\nregisterTest('batch_cap_ab', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'production stack needs shader-f16' };\n const weights = await loadWeights(device, '/weights', {\n targetDtype: 'f16', lmHeadQ8: true, ffnWT: true, projWT: true,\n });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const text = chapterText.repeat(16);\n const seg = segmentSource(text);\n const { rows } = packSentences(seg.sentences, seg.paras, 200);\n const charLens = rows.map((r) => r.length);\n\n const runArm = async (cap) => {\n const ranges = planBatches(charLens, gctx, 2, cap);\n const t0 = performance.now();\n let tokens = 0;\n for (const [s, e] of ranges) {\n const { metrics } = await translateBatch(\n gctx, weights, tok, rows.slice(s, e), { maxNewTokens: DECODE_CAP });\n tokens += metrics.tokensGenerated;\n }\n return { ms: performance.now() - t0, tokens, batches: ranges.length, maxB: Math.max(...ranges.map(([s, e]) => e - s)) };\n };\n\n const runs = Object.fromEntries(CAPS.map((c) => [c, []]));\n let shape = {};\n for (let round = 0; round < ROUNDS; round++) {\n for (const cap of CAPS) {\n const r = await runArm(cap);\n runs[cap].push(r.ms);\n shape[cap] = { batches: r.batches, maxB: r.maxB, tokens: r.tokens };\n }\n }\n const table = CAPS.map((cap) => {\n const ms = median(runs[cap]);\n return {\n cap,\n medianMs: Math.round(ms * 10) / 10,\n charsPerSec: Math.round((text.length / ms) * 1000),\n ...shape[cap],\n runs: runs[cap].map((x) => Math.round(x)),\n };\n });\n return { pass: true, detail: { chars: text.length, rows: rows.length, rounds: ROUNDS, table } };\n } finally {\n weights.buffer.destroy();\n }\n}, { slow: true });\n"],"names":["median","xs","s","a","b","m","CAPS","ROUNDS","registerTest","ctx","device","weights","loadWeights","tok","loadTokenizer","gctx","text","chapterText","seg","segmentSource","rows","packSentences","charLens","r","runArm","cap","ranges","planBatches","t0","tokens","e","metrics","translateBatch","DECODE_CAP","runs","c","shape","round","table","ms","x"],"mappings":"ylBAaA,MAAMA,EAAUC,GAAO,CACrB,MAAMC,EAAI,CAAC,GAAGD,CAAE,EAAE,KAAK,CAACE,EAAGC,IAAMD,EAAIC,CAAC,EAChCC,EAAIH,EAAE,QAAU,EACtB,OAAOA,EAAE,OAAS,EAAIA,EAAEG,CAAC,GAAKH,EAAEG,EAAI,CAAC,EAAIH,EAAEG,CAAC,GAAK,CACnD,EAEMC,EAAO,CAAC,IAAK,IAAK,GAAG,EACrBC,EAAS,EAEfC,EAAa,eAAgB,MAAOC,GAAQ,CAC1C,KAAM,CAAE,OAAAC,CAAM,EAAKD,EACnB,GAAI,CAACA,EAAI,OAAQ,MAAO,CAAE,KAAM,GAAM,OAAQ,mCAAmC,EACjF,MAAME,EAAU,MAAMC,EAAYF,EAAQ,WAAY,CACpD,YAAa,MAAO,SAAU,GAAM,MAAO,GAAM,OAAQ,EAC7D,CAAG,EACD,GAAI,CACF,MAAMG,EAAM,MAAMC,EAAa,EACzBC,EAAO,CAAE,OAAAL,EAAQ,MAAO,MAAO,OAAQD,EAAI,MAAM,EACjDO,EAAOC,EAAY,OAAO,EAAE,EAC5BC,EAAMC,EAAcH,CAAI,EACxB,CAAE,KAAAI,CAAI,EAAKC,EAAcH,EAAI,UAAWA,EAAI,MAAO,GAAG,EACtDI,EAAWF,EAAK,IAAKG,GAAMA,EAAE,MAAM,EAEnCC,EAAS,MAAOC,GAAQ,CAC5B,MAAMC,EAASC,EAAYL,EAAUP,EAAM,EAAGU,CAAG,EAC3CG,EAAK,YAAY,IAAG,EAC1B,IAAIC,EAAS,EACb,SAAW,CAAC3B,EAAG4B,CAAC,IAAKJ,EAAQ,CAC3B,KAAM,CAAE,QAAAK,CAAO,EAAK,MAAMC,EACxBjB,EAAMJ,EAASE,EAAKO,EAAK,MAAMlB,EAAG4B,CAAC,EAAG,CAAE,aAAcG,EAAY,EACpEJ,GAAUE,EAAQ,eACpB,CACA,MAAO,CAAE,GAAI,YAAY,IAAG,EAAKH,EAAI,OAAAC,EAAQ,QAASH,EAAO,OAAQ,KAAM,KAAK,IAAI,GAAGA,EAAO,IAAI,CAAC,CAACxB,EAAG4B,CAAC,IAAMA,EAAI5B,CAAC,CAAC,CAAC,CACvH,EAEMgC,EAAO,OAAO,YAAY5B,EAAK,IAAK6B,GAAM,CAACA,EAAG,CAAA,CAAE,CAAC,CAAC,EACxD,IAAIC,EAAQ,CAAA,EACZ,QAASC,EAAQ,EAAGA,EAAQ9B,EAAQ8B,IAClC,UAAWZ,KAAOnB,EAAM,CACtB,MAAM,EAAI,MAAMkB,EAAOC,CAAG,EAC1BS,EAAKT,CAAG,EAAE,KAAK,EAAE,EAAE,EACnBW,EAAMX,CAAG,EAAI,CAAE,QAAS,EAAE,QAAS,KAAM,EAAE,KAAM,OAAQ,EAAE,MAAM,CACnE,CAEF,MAAMa,EAAQhC,EAAK,IAAKmB,GAAQ,CAC9B,MAAMc,EAAKvC,EAAOkC,EAAKT,CAAG,CAAC,EAC3B,MAAO,CACL,IAAAA,EACA,SAAU,KAAK,MAAMc,EAAK,EAAE,EAAI,GAChC,YAAa,KAAK,MAAOvB,EAAK,OAASuB,EAAM,GAAI,EACjD,GAAGH,EAAMX,CAAG,EACZ,KAAMS,EAAKT,CAAG,EAAE,IAAKe,GAAM,KAAK,MAAMA,CAAC,CAAC,CAChD,CACI,CAAC,EACD,MAAO,CAAE,KAAM,GAAM,OAAQ,CAAE,MAAOxB,EAAK,OAAQ,KAAMI,EAAK,OAAQ,OAAQb,EAAQ,MAAA+B,CAAK,CAAE,CAC/F,QAAC,CACC3B,EAAQ,OAAO,QAAO,CACxB,CACF,EAAG,CAAE,KAAM,GAAM"}
assets/bench-BkXidq5p.js ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import"./modulepreload-polyfill-B5Qt9EMX.js";import{initDevice as v}from"./device-Z_ibNtmX.js";import{l as L}from"./weights-B-okS09o.js";import{l as E}from"./tokenizer-Ex1u7wXD.js";import{t as R}from"./generate-C4ruG1zm.js";import{c as T}from"./verify-HJ8NImMM.js";import{r as B,b as q}from"./bench-C8ITpm5I.js";import{g as h}from"./golden-BEvfygyg.js";import"./shapes-BCQ9D81L.js";import"./constants-C8VbFpic.js";import"./f16-wKKZr58e.js";import"./encoder-DX8MOfcH.js";import"./pipelines-DD24nEJg.js";import"./decoder-DI6VDxxO.js";import"./preload-helper-BXl3LOEh.js";import"./chapter3k-Bxq8ds-a.js";const I=document.querySelector("#app");I.innerHTML=`
2
+ <h1>webMT bench</h1>
3
+ <p>
4
+ <button id="load">Load engine</button>
5
+ <button id="verify" disabled>Verify vs golden (30)</button>
6
+ <button id="bench" disabled>Benchmark</button>
7
+ <label><input type="checkbox" id="includeRef"> Include reference runtimes</label>
8
+ <button id="export" disabled>Export JSON</button>
9
+ </p>
10
+ <p id="status" style="color:#8bc"></p>
11
+ <div id="benchTable"></div>
12
+ <pre id="out" style="white-space:pre-wrap"></pre>
13
+ `;const b=document.querySelector("#load"),p=document.querySelector("#verify"),u=document.querySelector("#bench"),P=document.querySelector("#includeRef"),S=document.querySelector("#export"),f=document.querySelector("#status"),C=document.querySelector("#benchTable"),F=document.querySelector("#out"),c=t=>{F.textContent+=`${t}
14
+ `};let $=null;b.addEventListener("click",async()=>{b.disabled=!0;try{c("loading engine…");const t=await v(),n=t.hasF16?"f16":"f32",r=await L(t.device,"/weights",{targetDtype:n,lmHeadQ8:n==="f16",ffnWT:n==="f16",projWT:n==="f16"}),o=await E();$={ctx:{...t,dtype:n},weights:r,tok:o},c(`engine ready: ${t.adapterInfo.description||t.adapterInfo.vendor} (${n})`),p.disabled=!1,u.disabled=!1}catch(t){c(`LOAD FAILED: ${t?.message??t}`),b.disabled=!1}});p.addEventListener("click",async()=>{p.disabled=!0;const{ctx:t,weights:n,tok:r}=$;let o=0,e=0,a=0,y=0;try{for(let m=0;m<h.items.length;m++){const d=h.items[m],{rows:g,metrics:x}=await R(t,n,r,[d.source],{maxNewTokens:d.maxNewTokens});y+=x.tokPerSec;const i=T(g[0].ids,d.ids);i.verdict==="exact"?o++:i.verdict==="forced-eos"?e++:a++,c(`[${String(m).padStart(2)}] ${i.verdict.toUpperCase().padEnd(10)} ${x.tokPerSec.toFixed(0)} tok/s ${d.source}`),i.verdict==="mismatch"&&(c(` step ${i.step}`),c(` engine: ${g[0].text}`),c(` golden: ${d.text}`))}const s=h.items.length,k=Math.ceil(.95*s),w=o+e>=k;c(`
15
+ ${w?"PASS":"FAIL"}: exact=${o} forced-eos=${e} mismatch=${a} (need ${k}/${s}) avg ${(y/s).toFixed(1)} tok/s @ batch=1`)}catch(s){c(`VERIFY FAILED: ${s?.message??s}
16
+ ${s?.stack??""}`)}finally{p.disabled=!1}});let l=null;function M(t){const n=t.runs,r=(e,a)=>e.min?` (${e.min[a]}–${e.max[a]})`:"",o=n.map(e=>e.error?`<tr><td>${e.runtime}</td><td>${e.preset}</td><td>${e.batch}</td>
17
+ <td colspan="4" style="color:#f55">ERROR: ${e.error}</td></tr>`:`<tr><td>${e.runtime}</td><td>${e.preset}</td><td>${e.batch}</td>
18
+ <td>${e.median.tokPerSec}${r(e,"tokPerSec")}</td>
19
+ <td>${e.median.e2eCharsPerSec}${r(e,"e2eCharsPerSec")}</td>
20
+ <td>${e.median.tokens}</td>
21
+ <td>${e.median.decodeMs??e.median.translateMs}</td></tr>`).join("");C.innerHTML=`
22
+ <table border="1" cellpadding="4" style="border-collapse:collapse">
23
+ <tr><th>runtime</th><th>preset</th><th>batch</th>
24
+ <th>tok/s median (min–max)</th><th>chars/s median (min–max)</th>
25
+ <th>tokens</th><th>decode ms</th></tr>
26
+ ${o}
27
+ </table>`}u.addEventListener("click",async()=>{u.disabled=!0;const{ctx:t,weights:n,tok:r}=$;try{const o=await B(t,n,r,{includeReference:P.checked,referencePresets:["short32"],onStatus:e=>{f.textContent=e}});l=q(o,t.adapterInfo),M(l),f.textContent="benchmark complete",S.disabled=!1}catch(o){f.textContent="",c(`BENCH FAILED: ${o?.message??o}
28
+ ${o?.stack??""}`)}finally{u.disabled=!1}});S.addEventListener("click",()=>{if(!l)return;const t=new Blob([JSON.stringify(l,null,2)],{type:"application/json"}),n=document.createElement("a");n.href=URL.createObjectURL(t),n.download=`webmt-bench-${l.date}.json`,n.click(),URL.revokeObjectURL(n.href)});
29
+ //# sourceMappingURL=bench-BkXidq5p.js.map
assets/bench-BkXidq5p.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"bench-BkXidq5p.js","sources":["../../src/bench-main.js"],"sourcesContent":["// Minimal Verify + Benchmark UI: load the engine, run the 30 golden sentences\n// through the SAME translateBatch/compareToGolden path the M3 gate uses, and\n// run the M5 benchmark matrix (optionally with Transformers.js reference\n// rows) with JSON export.\nimport { initDevice } from './engine/device.js';\nimport { loadWeights } from './engine/weights.js';\nimport { loadTokenizer } from './engine/tokenizer.js';\nimport { translateBatch } from './engine/generate.js';\nimport { compareToGolden } from './bench/verify.js';\nimport { runBenchMatrix, buildReport } from './bench/bench.js';\nimport golden from '../fixtures/golden.json';\n\nconst app = document.querySelector('#app');\napp.innerHTML = `\n <h1>webMT bench</h1>\n <p>\n <button id=\"load\">Load engine</button>\n <button id=\"verify\" disabled>Verify vs golden (30)</button>\n <button id=\"bench\" disabled>Benchmark</button>\n <label><input type=\"checkbox\" id=\"includeRef\"> Include reference runtimes</label>\n <button id=\"export\" disabled>Export JSON</button>\n </p>\n <p id=\"status\" style=\"color:#8bc\"></p>\n <div id=\"benchTable\"></div>\n <pre id=\"out\" style=\"white-space:pre-wrap\"></pre>\n`;\nconst loadBtn = document.querySelector('#load');\nconst verifyBtn = document.querySelector('#verify');\nconst benchBtn = document.querySelector('#bench');\nconst includeRef = document.querySelector('#includeRef');\nconst exportBtn = document.querySelector('#export');\nconst statusEl = document.querySelector('#status');\nconst benchTable = document.querySelector('#benchTable');\nconst out = document.querySelector('#out');\nconst log = (line) => { out.textContent += `${line}\\n`; };\n\nlet engine = null; // {ctx, weights, tok}\n\nloadBtn.addEventListener('click', async () => {\n loadBtn.disabled = true;\n try {\n log('loading engine…');\n const ctx = await initDevice();\n const dtype = ctx.hasF16 ? 'f16' : 'f32';\n // lmHeadQ8: int8 lm_head (W8A16) — the perf default for real use; quality\n // gated at 29/30 golden (q8_lmhead_golden), same bar as f16's m3 gate.\n const weights = await loadWeights(ctx.device, '/weights', { targetDtype: dtype, lmHeadQ8: dtype === 'f16', ffnWT: dtype === 'f16', projWT: dtype === 'f16' });\n const tok = await loadTokenizer();\n engine = { ctx: { ...ctx, dtype }, weights, tok };\n log(`engine ready: ${ctx.adapterInfo.description || ctx.adapterInfo.vendor} (${dtype})`);\n verifyBtn.disabled = false;\n benchBtn.disabled = false;\n } catch (err) {\n log(`LOAD FAILED: ${err?.message ?? err}`);\n loadBtn.disabled = false;\n }\n});\n\nverifyBtn.addEventListener('click', async () => {\n verifyBtn.disabled = true;\n const { ctx, weights, tok } = engine;\n let exact = 0;\n let forcedEos = 0;\n let mismatches = 0;\n let tokPerSecSum = 0;\n try {\n for (let i = 0; i < golden.items.length; i++) {\n const item = golden.items[i];\n const { rows, metrics } = await translateBatch(ctx, weights, tok, [item.source],\n { maxNewTokens: item.maxNewTokens });\n tokPerSecSum += metrics.tokPerSec;\n const cmp = compareToGolden(rows[0].ids, item.ids);\n if (cmp.verdict === 'exact') exact++;\n else if (cmp.verdict === 'forced-eos') forcedEos++;\n else mismatches++;\n log(`[${String(i).padStart(2)}] ${cmp.verdict.toUpperCase().padEnd(10)} ` +\n `${metrics.tokPerSec.toFixed(0)} tok/s ${item.source}`);\n if (cmp.verdict === 'mismatch') {\n log(` step ${cmp.step}`);\n log(` engine: ${rows[0].text}`);\n log(` golden: ${item.text}`);\n }\n }\n const total = golden.items.length;\n const need = Math.ceil(0.95 * total);\n const ok = exact + forcedEos >= need;\n log(`\\n${ok ? 'PASS' : 'FAIL'}: exact=${exact} forced-eos=${forcedEos} ` +\n `mismatch=${mismatches} (need ${need}/${total}) ` +\n `avg ${(tokPerSecSum / total).toFixed(1)} tok/s @ batch=1`);\n } catch (err) {\n log(`VERIFY FAILED: ${err?.message ?? err}\\n${err?.stack ?? ''}`);\n } finally {\n verifyBtn.disabled = false;\n }\n});\n\n// --- Benchmark matrix (M5) ---\nlet lastReport = null;\n\nfunction renderBenchTable(report) {\n const rows = report.runs;\n const range = (r, f) => (r.min ? ` (${r.min[f]}–${r.max[f]})` : '');\n const cells = rows.map((r) => r.error\n ? `<tr><td>${r.runtime}</td><td>${r.preset}</td><td>${r.batch}</td>\n <td colspan=\"4\" style=\"color:#f55\">ERROR: ${r.error}</td></tr>`\n : `<tr><td>${r.runtime}</td><td>${r.preset}</td><td>${r.batch}</td>\n <td>${r.median.tokPerSec}${range(r, 'tokPerSec')}</td>\n <td>${r.median.e2eCharsPerSec}${range(r, 'e2eCharsPerSec')}</td>\n <td>${r.median.tokens}</td>\n <td>${r.median.decodeMs ?? r.median.translateMs}</td></tr>`).join('');\n benchTable.innerHTML = `\n <table border=\"1\" cellpadding=\"4\" style=\"border-collapse:collapse\">\n <tr><th>runtime</th><th>preset</th><th>batch</th>\n <th>tok/s median (min–max)</th><th>chars/s median (min–max)</th>\n <th>tokens</th><th>decode ms</th></tr>\n ${cells}\n </table>`;\n}\n\nbenchBtn.addEventListener('click', async () => {\n benchBtn.disabled = true;\n const { ctx, weights, tok } = engine;\n try {\n const rows = await runBenchMatrix(ctx, weights, tok, {\n includeReference: includeRef.checked,\n referencePresets: ['short32'], // reference runtimes are minutes-slow on chapter3k\n onStatus: (msg) => { statusEl.textContent = msg; },\n });\n lastReport = buildReport(rows, ctx.adapterInfo);\n renderBenchTable(lastReport);\n statusEl.textContent = 'benchmark complete';\n exportBtn.disabled = false;\n } catch (err) {\n statusEl.textContent = '';\n log(`BENCH FAILED: ${err?.message ?? err}\\n${err?.stack ?? ''}`);\n } finally {\n benchBtn.disabled = false;\n }\n});\n\nexportBtn.addEventListener('click', () => {\n if (!lastReport) return;\n const blob = new Blob([JSON.stringify(lastReport, null, 2)], { type: 'application/json' });\n const a = document.createElement('a');\n a.href = URL.createObjectURL(blob);\n a.download = `webmt-bench-${lastReport.date}.json`;\n a.click();\n URL.revokeObjectURL(a.href);\n});\n"],"names":["app","loadBtn","verifyBtn","benchBtn","includeRef","exportBtn","statusEl","benchTable","out","log","line","engine","ctx","initDevice","dtype","weights","loadWeights","tok","loadTokenizer","err","exact","forcedEos","mismatches","tokPerSecSum","i","golden","item","rows","metrics","translateBatch","cmp","compareToGolden","total","need","ok","lastReport","renderBenchTable","report","range","r","f","cells","runBenchMatrix","msg","buildReport","blob","a"],"mappings":"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"}
assets/bench-C8ITpm5I.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/reference-Dj87VRUN.js","assets/shapes-BCQ9D81L.js","assets/constants-C8VbFpic.js"])))=>i.map(i=>d[i]);
2
+ import{_ as F}from"./preload-helper-BXl3LOEh.js";import{t as j}from"./generate-C4ruG1zm.js";import{c as A,b as O}from"./shapes-BCQ9D81L.js";import{c as x}from"./chapter3k-Bxq8ds-a.js";function _(n,r=220){const o=String(n).replace(/\r\n/g,`
3
+ `).split(`
4
+ `),t=[],h=[],m=Math.max(80,Number(r)||220),b=/[^。!?!?;;]+[。!?!?;;]*/g;for(const S of o){const g=S.trim();if(!g){h.push(null);continue}const $=g.match(b)||[g];let s="";const u=[],a=()=>{s&&(u.push(t.length),t.push(s),s="")};for(const d of $){if(d.length>m){a();for(let k=0;k<d.length;k+=m)u.push(t.length),t.push(d.slice(k,k+m));continue}s&&(s+d).length>m&&a(),s+=d}a(),h.push(u)}return{chunks:t,plan:h}}const T=["他缓缓拔出长剑,目光冷得像冰。","夜色渐深,客栈里只剩下几盏残灯。","“你到底是什么人?”她低声问道。","山风呼啸,卷起满地的落叶。","老者捋了捋胡须,微微一笑。","这一掌的力道,足以开碑裂石!","“师父,弟子知错了。”少年跪在地上。","江湖上的恩怨,从来没有那么简单。","她转身离去,再也没有回头。","剑光一闪,血溅三尺。","大殿之内,众人鸦雀无声。","他喝了口酒,眼中闪过一丝痛楚。","“今晚三更,后山竹林见。”","马蹄声由远及近,尘土飞扬。","这门功夫,他练了整整二十年。","暮色四合之际,一行人马终于抵达了山脚下的小镇,镇口的酒旗在风中猎猎作响;为首的中年汉子翻身下马,环顾四周,见街道两旁的店铺早已关门闭户,只有远处一家客栈还透出昏黄的灯光,他皱了皱眉,低声吩咐众人收起兵刃,不要惊扰了镇上的百姓。","传闻中的藏剑山庄坐落在群山环抱之中,庄内古木参天,流水潺潺,青石铺就的小径蜿蜒曲折;每逢三月桃花盛开,四方豪杰便会齐聚于此,或论剑,或品茶,或只是远远地望一眼那位传说中的庄主,据说他已经三十年没有拔过剑了,可江湖上没有人敢小看他。","那一夜大雨倾盆,雷声滚滚,破庙里的火堆忽明忽暗;少年抱着怀中的剑谱,听着庙外杂乱的脚步声越来越近,心跳如鼓,他知道,追兵一旦破门而入,自己便再无生路,可师父临终前的嘱托犹在耳边,这本剑谱无论如何都不能落入奸人之手。","掌门之位悬空已有三年,门中各脉明争暗斗从未停歇;大师兄稳重却优柔寡断,二师姐剑法超群却性情孤傲,三师弟聪明伶俐却资历尚浅,长老们各怀心思,谁也不肯先开口,直到那个雪夜,山门外传来一声长啸,所有人都放下了手中的茶盏。","集市上人声鼎沸,卖艺的汉子赤膊耍着一杆铁枪,围观的人群不时爆发出阵阵喝彩声;忽然人群一阵骚动,几名黑衣人分开众人径直走向那名枪手,为首之人冷冷地丢下一块乌黑的令牌,喧闹的集市霎时安静了下来,连风都仿佛停了。","信使跪在堂下,双手呈上一封火漆密函,堂上众人面面相觑;老庄主拆开信笺,只看了一眼,脸色便骤然大变,他缓缓起身,望着窗外沉沉的夜色,半晌才道:传令下去,即刻封山,任何人不得进出,违令者一律逐出师门,永不再录。","三十年前的那场大火烧毁了半座城池,也烧断了两大世家百年的情谊;如今旧事重提,当年的幸存者死的死,散的散,唯有城南那口枯井旁的老槐树还记得一切,树下埋着的,不只是一坛陈年的女儿红,还有一个再也无人敢提起的名字。","渡口的老船夫眯着眼打量来客,见那书生衣衫褴褛却腰悬长剑,不由得多问了一句;书生笑而不答,只将一锭碎银放在船头,转身望向对岸茫茫的芦苇荡,江风吹起他的衣角,露出内衬上暗绣的金线纹样,老船夫握着船桨的手,忽然抖了一下。","林昭推门而入,林昭的剑还在滴着血,可林昭的声音却平静得可怕。","沈青山望着窗外,沈青山知道,今夜之后江湖上再无沈青山这个名字。","“林昭!林昭你给我站住!”她追出门外,可林昭的身影早已消失在夜色之中。","众人都说沈青山败了,可沈青山不这么认为,沈青山收剑入鞘,转身走下擂台。","林昭救过他一次,林昭也骗过他一次,所以当林昭再次出现时,他不知该拔剑还是敬酒。","沈青山的刀快,沈青山的心更狠,凡是见过沈青山出手的人,都不愿再与他为敌。","有人说林昭死在了雁门关外,有人说林昭隐居山林,还有人说,林昭根本就没有存在过。"],L=["刀出如龙,寒气逼人。","他在桥头站了一夜。","“放下剑,我饶你不死。”","钟声响起,山门缓缓开启。","她的暗器从不落空。","灯火摇曳,人影散乱。","一杯酒,敬当年的兄弟。","掌风过处,烛火尽灭。","他背上的伤疤又开始疼了。","“来者何人,报上名来!”","雪落无声,剑亦无声。","这条路,他走了半生。","密道尽头透出一线微光。","恩人一诺,死生不忘。","毒发之时,他咬碎了牙关。","旗帜倒下,城头易主。","江水东流,带不走旧恨。"];function R(n){if(n==="short32")return[...T.slice(0,15),...L];if(n==="chapter3k")return _(x).chunks;if(n==="file23k"){const r=_(x).chunks;return Array.from({length:8},()=>r).flat()}throw new Error(`unknown preset: ${n}`)}const B=n=>[...n].sort((r,o)=>o.length-r.length),w=n=>Number(n.toFixed(1));function q(n){const r=[...n].sort((t,h)=>t-h),o=r.length>>1;return r.length%2?r[o]:(r[o-1]+r[o])/2}async function C(n,r,o,t,h){let m=0,b=0,S=0,g=0;for(let s=0;s<t.length;s+=h){const u=t.slice(s,s+h),{metrics:a}=await j(n,r,o,u);m+=a.encoderMs,b+=a.decodeMs,S+=a.tokensGenerated,g+=a.submits}const $=t.reduce((s,u)=>s+u.length,0);return{encoderMs:w(m),decodeMs:w(b),tokens:S,submits:g,tokPerSec:w(S/b*1e3),e2eCharsPerSec:w($/(m+b)*1e3)}}const I=["encoderMs","decodeMs","tokens","tokPerSec","e2eCharsPerSec"],v={"tfjs-wasm-q8":{device:"wasm",dtype:"q8"},"tfjs-webgpu-fp16":{device:"webgpu",dtype:"fp16"}};async function U(n,r,o,{presets:t=["short32","chapter3k"],batches:h=[1,4,8,16],repeats:m=3,includeReference:b=!1,referencePresets:S=t,referenceBatches:g=[1,4],referenceCells:$=Object.keys(v).flatMap(u=>S.flatMap(a=>g.map(d=>({runtime:u,preset:a,batch:d})))),onStatus:s=()=>{}}={}){const u=[],a=Object.fromEntries(t.map(i=>[i,B(R(i))])),d=i=>Array.isArray(h)?h:h[i],k=r.dtype==="f16"?2:4,y=async i=>{const l=o.encode(a[i][0]),p=A(n,O(l.length),k),c=[];for(const f of d(i)){const e=Math.min(f,p);e!==f&&s(`${i}: batch ${f} clamped to device max ${e}`),c.some(P=>P.batch===e)||c.push({batch:e,...e!==f?{requestedBatch:f}:{}})}return c};s("warmup…"),await C(n,r,o,a[t[0]],(await y(t[0]))[0].batch);for(const i of t)for(const{batch:l,requestedBatch:p}of await y(i)){const c=[];for(let e=0;e<m;e++)s(`webmt ${i} b${l} repeat ${e+1}/${m}…`),c.push(await C(n,r,o,a[i],l));const f=Object.fromEntries(I.map(e=>[e,w(q(c.map(P=>P[e])))]));u.push({runtime:"webmt",preset:i,batch:l,...p?{requestedBatch:p}:{},repeats:c,median:f,min:{tokPerSec:Math.min(...c.map(e=>e.tokPerSec)),e2eCharsPerSec:Math.min(...c.map(e=>e.e2eCharsPerSec))},max:{tokPerSec:Math.max(...c.map(e=>e.tokPerSec)),e2eCharsPerSec:Math.max(...c.map(e=>e.e2eCharsPerSec))}})}if(b){const{runReference:i}=await F(async()=>{const{runReference:l}=await import("./reference-Dj87VRUN.js");return{runReference:l}},__vite__mapDeps([0,1,2]));for(const{runtime:l,preset:p,batch:c}of $){const{device:f,dtype:e}=v[l]??{};if(!f)throw new Error(`unknown reference runtime: ${l}`);const P=a[p]??B(R(p));s(`${l} ${p} b${c} (single run)…`);try{const M=await i({device:f,dtype:e,sources:P,batchSize:c,onStatus:D=>s(`${l} ${p} b${c}: ${D}`)}),E={loadMs:Math.round(M.loadMs),translateMs:Math.round(M.translateMs),tokens:M.tokens,tokPerSec:w(M.tokPerSec),e2eCharsPerSec:w(M.charsPerSec)};u.push({runtime:l,preset:p,batch:c,repeats:[E],median:E})}catch(M){u.push({runtime:l,preset:p,batch:c,error:String(M?.message??M)})}}}return u}function V(n,r,{date:o}={}){const t=new Date,h=`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`;return{schema:"webmt-bench-v1",date:o??h,adapterInfo:r,baselineRef:"docs/bench/baseline.json",runs:n}}export{V as b,R as p,U as r};
5
+ //# sourceMappingURL=bench-C8ITpm5I.js.map
assets/bench-C8ITpm5I.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"mappings":"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","names":["splitText","text","maxChars","lines","chunks","plan","limit","sentenceRe","rawLine","line","pieces","current","indexes","pushCurrent","piece","i","EXTRA_SHORT","presetChunks","name","goldenSources","chapterText","base","byLengthDesc","a","b","round1","x","median","values","s","mid","runEngineOnce","ctx","weights","tok","orderedChunks","batch","encoderMs","decodeMs","tokens","submits","group","metrics","translateBatch","srcChars","n","c","MEDIAN_FIELDS","REF_RUNTIMES","runBenchMatrix","presets","batches","repeats","includeReference","referencePresets","referenceBatches","referenceCells","runtime","preset","onStatus","rows","ordered","p","batchesFor","dtypeBytes","clampedBatches","ids","maxBatch","maxBatchForLimits","bucketFor","list","clamped","requestedBatch","reps","r","med","f","runReference","__vitePreload","device","dtype","res","msg","entry","err","buildReport","adapterInfo","date","d","localDate"],"ignoreList":[],"sources":["../../src/bench/chunk.js","../../src/bench/bench.js"],"sourcesContent":["// Text chunker, ported EXACTLY from the old app's worker\n// (moxhimt30-browser/src/worker/translator.worker.js) so the chapter benchmark\n// exercises the same chunk-size distribution the shipped app produces.\n//\n// splitText: newline → lines; each line split by the CJK/latin sentence regex,\n// sentences accumulated up to `maxChars` (clamped to ≥80, default 220);\n// oversized single sentences hard-split at the limit. Empty lines become a\n// null plan entry. Returns {chunks, plan} where plan[i] is the list of chunk\n// indexes for line i (null for blank lines).\nexport function splitText(text, maxChars = 220) {\n const lines = String(text || '').replace(/\\r\\n/g, '\\n').split('\\n');\n const chunks = [];\n const plan = [];\n const limit = Math.max(80, Number(maxChars) || 220);\n const sentenceRe = /[^。!?!?;;]+[。!?!?;;]*/g;\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (!line) {\n plan.push(null);\n continue;\n }\n const pieces = line.match(sentenceRe) || [line];\n let current = '';\n const indexes = [];\n const pushCurrent = () => {\n if (!current) return;\n indexes.push(chunks.length);\n chunks.push(current);\n current = '';\n };\n\n for (const piece of pieces) {\n if (piece.length > limit) {\n pushCurrent();\n for (let i = 0; i < piece.length; i += limit) {\n indexes.push(chunks.length);\n chunks.push(piece.slice(i, i + limit));\n }\n continue;\n }\n if (current && (current + piece).length > limit) {\n pushCurrent();\n }\n current += piece;\n }\n pushCurrent();\n plan.push(indexes);\n }\n return { chunks, plan };\n}\n\n// Reassemble translated chunks per the plan: chunks of one source line join\n// with ' ', lines join with '\\n', blank lines come back as ''.\nexport function joinChunks(translated, plan) {\n return plan.map((indexes) => {\n if (indexes === null) return '';\n return indexes.map((idx) => translated[idx]).filter(Boolean).join(' ');\n }).join('\\n');\n}\n","// M5 benchmark matrix: engine (webmt) across preset × batch, plus optional\n// Transformers.js reference rows, exported as a webmt-bench-v1 report.\n//\n// Metric semantics (documented, deliberate):\n// tokPerSec tokens / Σ decodeMs — DECODE-ONLY throughput, the kernel\n// story; comparable with m3/m4 numbers and baseline tok/s.\n// e2eCharsPerSec source chars / Σ(encoderMs + decodeMs) — the honest\n// end-user number: encoder + full decode loop including all\n// per-group readbacks (decodeMs contains mapAsync waits).\n// Excludes tokenize/detokenize JS (sub-ms per chunk).\n//\n// Batching hygiene: chunks are ordered LONGEST-FIRST before grouping into\n// translateBatch calls (mirrors the old worker's sortedChunkJobs) so a group\n// holds similar-length rows — padding and per-group decode caps are set by\n// the longest row, so mixing lengths wastes steps on the short rows.\nimport { translateBatch } from '../engine/generate.js';\nimport { maxBatchForLimits, bucketFor } from '../engine/shapes.js';\n// reference.js pulls in transformers.js + ORT (~24MB with the wasm) — loaded\n// on demand so plain engine benches never fetch it.\nimport { splitText } from './chunk.js';\nimport goldenSources from '../../fixtures/golden_sources.json';\nimport chapterText from '../../fixtures/chapter3k.txt?raw';\n\n// 17 extra short sentences (same wuxia register as golden_sources' first 15)\n// to bring the short preset to 32.\nconst EXTRA_SHORT = [\n '刀出如龙,寒气逼人。',\n '他在桥头站了一夜。',\n '“放下剑,我饶你不死。”',\n '钟声响起,山门缓缓开启。',\n '她的暗器从不落空。',\n '灯火摇曳,人影散乱。',\n '一杯酒,敬当年的兄弟。',\n '掌风过处,烛火尽灭。',\n '他背上的伤疤又开始疼了。',\n '“来者何人,报上名来!”',\n '雪落无声,剑亦无声。',\n '这条路,他走了半生。',\n '密道尽头透出一线微光。',\n '恩人一诺,死生不忘。',\n '毒发之时,他咬碎了牙关。',\n '旗帜倒下,城头易主。',\n '江水东流,带不走旧恨。',\n];\n\n// Preset name → chunk list. short32 = first 15 golden short sources + 17\n// extras; chapter3k = the fixture chapter through the ported app chunker;\n// file23k = the chapter3k chunk list repeated 8× (152 chunks, ~23k chars) —\n// simulates translating a real .txt file, where large batches actually fill.\nexport function presetChunks(name) {\n if (name === 'short32') return [...goldenSources.slice(0, 15), ...EXTRA_SHORT];\n if (name === 'chapter3k') return splitText(chapterText).chunks;\n if (name === 'file23k') {\n const base = splitText(chapterText).chunks;\n return Array.from({ length: 8 }, () => base).flat();\n }\n throw new Error(`unknown preset: ${name}`);\n}\n\nconst byLengthDesc = (chunks) => [...chunks].sort((a, b) => b.length - a.length);\nconst round1 = (x) => Number(x.toFixed(1));\n\nfunction median(values) {\n const s = [...values].sort((a, b) => a - b);\n const mid = s.length >> 1;\n return s.length % 2 ? s[mid] : (s[mid - 1] + s[mid]) / 2;\n}\n\n// One engine measurement of a preset at a batch size: sequential\n// translateBatch calls over longest-first groups of `batch` chunks.\nasync function runEngineOnce(ctx, weights, tok, orderedChunks, batch) {\n let encoderMs = 0;\n let decodeMs = 0;\n let tokens = 0;\n let submits = 0;\n for (let i = 0; i < orderedChunks.length; i += batch) {\n const group = orderedChunks.slice(i, i + batch);\n const { metrics } = await translateBatch(ctx, weights, tok, group);\n encoderMs += metrics.encoderMs;\n decodeMs += metrics.decodeMs;\n tokens += metrics.tokensGenerated;\n submits += metrics.submits;\n }\n const srcChars = orderedChunks.reduce((n, c) => n + c.length, 0);\n return {\n encoderMs: round1(encoderMs),\n decodeMs: round1(decodeMs),\n tokens,\n submits,\n tokPerSec: round1((tokens / decodeMs) * 1000),\n e2eCharsPerSec: round1((srcChars / (encoderMs + decodeMs)) * 1000),\n };\n}\n\nconst MEDIAN_FIELDS = ['encoderMs', 'decodeMs', 'tokens', 'tokPerSec', 'e2eCharsPerSec'];\n\nconst REF_RUNTIMES = {\n 'tfjs-wasm-q8': { device: 'wasm', dtype: 'q8' },\n 'tfjs-webgpu-fp16': { device: 'webgpu', dtype: 'fp16' },\n};\n\n// Runs the full matrix. Returns rows:\n// {runtime:'webmt', preset, batch, repeats:[{encoderMs, decodeMs, tokens,\n// submits, tokPerSec, e2eCharsPerSec}...], median:{...}, min:{tokPerSec,\n// e2eCharsPerSec}, max:{...}}\n// `batches` is either one array (all presets) or a per-preset map\n// {preset: [sizes]}. Sizes above the device binding limit (maxBatchForLimits\n// at the preset's longest-chunk bucket) are clamped to the max usable batch —\n// clamped rows carry `requestedBatch`.\n// Reference rows (includeReference) run ONCE each (they are slow):\n// {runtime:'tfjs-wasm-q8'|'tfjs-webgpu-fp16', preset, batch, repeats:[one],\n// median:{...}} or {..., error} if the runtime failed to load/run.\n// referenceCells [{runtime, preset, batch}...] picks exact cells; the default\n// preserves the old behavior (both runtimes × referencePresets × b1/b4).\nexport async function runBenchMatrix(ctx, weights, tok, {\n presets = ['short32', 'chapter3k'],\n batches = [1, 4, 8, 16],\n repeats = 3,\n includeReference = false,\n referencePresets = presets,\n referenceBatches = [1, 4],\n referenceCells = Object.keys(REF_RUNTIMES).flatMap((runtime) =>\n referencePresets.flatMap((preset) =>\n referenceBatches.map((batch) => ({ runtime, preset, batch })))),\n onStatus = () => {},\n} = {}) {\n const rows = [];\n const ordered = Object.fromEntries(\n presets.map((p) => [p, byLengthDesc(presetChunks(p))]),\n );\n const batchesFor = (preset) => (Array.isArray(batches) ? batches : batches[preset]);\n\n // Clamp a preset's batch list to what the device binding limit allows. S for\n // the guard = the bucket of the preset's LONGEST chunk (chunks are grouped\n // longest-first, so the first group is the worst case).\n const dtypeBytes = weights.dtype === 'f16' ? 2 : 4;\n const clampedBatches = async (preset) => {\n const ids = tok.encode(ordered[preset][0]);\n const maxBatch = maxBatchForLimits(ctx, bucketFor(ids.length), dtypeBytes);\n const list = [];\n for (const b of batchesFor(preset)) {\n const clamped = Math.min(b, maxBatch);\n if (clamped !== b) onStatus(`${preset}: batch ${b} clamped to device max ${clamped}`);\n if (!list.some((x) => x.batch === clamped)) {\n list.push({ batch: clamped, ...(clamped !== b ? { requestedBatch: b } : {}) });\n }\n }\n return list;\n };\n\n // One warmup before the first cell only: primes pipeline caches / GPU\n // clocks so repeat 1 of cell 1 is not an outlier. Uses the CLAMPED batch so\n // the warmup itself cannot exceed the device limit on smaller GPUs.\n onStatus('warmup…');\n await runEngineOnce(ctx, weights, tok, ordered[presets[0]], (await clampedBatches(presets[0]))[0].batch);\n\n for (const preset of presets) {\n for (const { batch, requestedBatch } of await clampedBatches(preset)) {\n const reps = [];\n for (let r = 0; r < repeats; r++) {\n onStatus(`webmt ${preset} b${batch} repeat ${r + 1}/${repeats}…`);\n reps.push(await runEngineOnce(ctx, weights, tok, ordered[preset], batch));\n }\n const med = Object.fromEntries(\n MEDIAN_FIELDS.map((f) => [f, round1(median(reps.map((x) => x[f])))]),\n );\n rows.push({\n runtime: 'webmt',\n preset,\n batch,\n ...(requestedBatch ? { requestedBatch } : {}),\n repeats: reps,\n median: med,\n min: {\n tokPerSec: Math.min(...reps.map((x) => x.tokPerSec)),\n e2eCharsPerSec: Math.min(...reps.map((x) => x.e2eCharsPerSec)),\n },\n max: {\n tokPerSec: Math.max(...reps.map((x) => x.tokPerSec)),\n e2eCharsPerSec: Math.max(...reps.map((x) => x.e2eCharsPerSec)),\n },\n });\n }\n }\n\n if (includeReference) {\n const { runReference } = await import('./reference.js');\n for (const { runtime, preset, batch } of referenceCells) {\n const { device, dtype } = REF_RUNTIMES[runtime] ?? {};\n if (!device) throw new Error(`unknown reference runtime: ${runtime}`);\n const chunks = ordered[preset] ?? byLengthDesc(presetChunks(preset));\n onStatus(`${runtime} ${preset} b${batch} (single run)…`);\n try {\n const res = await runReference({\n device, dtype, sources: chunks, batchSize: batch,\n onStatus: (msg) => onStatus(`${runtime} ${preset} b${batch}: ${msg}`),\n });\n const entry = {\n loadMs: Math.round(res.loadMs),\n translateMs: Math.round(res.translateMs),\n tokens: res.tokens,\n tokPerSec: round1(res.tokPerSec),\n // ORT's generate() interleaves encoder+decoder inside\n // translateMs, so its chars/s is already end-to-end.\n e2eCharsPerSec: round1(res.charsPerSec),\n };\n rows.push({ runtime, preset, batch, repeats: [entry], median: entry });\n } catch (err) {\n rows.push({ runtime, preset, batch, error: String(err?.message ?? err) });\n }\n }\n }\n\n return rows;\n}\n\nexport function buildReport(rows, adapterInfo, { date } = {}) {\n // Local calendar date, not UTC — a run before 07:00 Asia/Bangkok would\n // otherwise be stamped with yesterday's date.\n const d = new Date();\n const localDate = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n return {\n schema: 'webmt-bench-v1',\n date: date ?? localDate,\n adapterInfo,\n baselineRef: 'docs/bench/baseline.json',\n runs: rows,\n };\n}\n"],"file":"bench-C8ITpm5I.js"}
assets/compact_equiv-BsjFDsn-.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as w}from"./debug-Cn7EHWtJ.js";import{l as h}from"./weights-B-okS09o.js";import{l as u}from"./tokenizer-Ex1u7wXD.js";import{t as d}from"./generate-C4ruG1zm.js";import{p as k}from"./bench-C8ITpm5I.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./constants-C8VbFpic.js";import"./f16-wKKZr58e.js";import"./encoder-DX8MOfcH.js";import"./pipelines-DD24nEJg.js";import"./decoder-DI6VDxxO.js";import"./chapter3k-Bxq8ds-a.js";w("compact_equiv",async s=>{const{device:n}=s,i=s.hasF16?"f16":"f32",r=await h(n,"/weights",{targetDtype:i});try{const p=await u(),f={device:n,dtype:i,limits:s.limits},c=k("file23k").slice(0,64),o=await d(f,r,p,c,{compact:!1}),e=await d(f,r,p,c,{compact:!0});let m=0,a=null;for(let t=0;t<o.rows.length;t++)o.rows[t].ids.join(",")!==e.rows[t].ids.join(",")&&(m++,a??={row:t,off:o.rows[t].ids.slice(0,12).join(","),on:e.rows[t].ids.slice(0,12).join(",")});const l=e.metrics.compactions;return{pass:m===0&&l>0,detail:{dtype:i,B:c.length,mismatchRows:m,compactions:l,...a?{firstMismatch:a}:{},offDecodeMs:Number(o.metrics.decodeMs.toFixed(1)),onDecodeMs:Number(e.metrics.decodeMs.toFixed(1)),offTokPerSec:Number(o.metrics.tokPerSec.toFixed(0)),onTokPerSec:Number(e.metrics.tokPerSec.toFixed(0)),steps:{off:o.metrics.steps,on:e.metrics.steps}}}}finally{r.buffer.destroy()}});
2
+ //# sourceMappingURL=compact_equiv-BsjFDsn-.js.map
assets/compact_equiv-BsjFDsn-.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"compact_equiv-BsjFDsn-.js","sources":["../../src/debug/tests/compact_equiv.js"],"sourcesContent":["// EOS-compaction equivalence gate: translateBatch({compact: true}) must be\n// TOKEN-EXACT identical to {compact: false} on a ragged batch. Exactness is\n// by construction — compaction only moves rows (kernel routing is pinned\n// across the rebuild, per-row math never mixes rows) — so any diff is an\n// indexing bug in compactDecodeState (KV prefix, bitmask, ring seed, lens).\n//\n// Chunks are deliberately NOT length-sorted (unlike the bench) so rows hit\n// eos far apart and several compactions actually fire; the test fails if\n// none did (a policy regression would otherwise pass vacuously).\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer } from '../../engine/tokenizer.js';\nimport { translateBatch } from '../../engine/generate.js';\nimport { presetChunks } from '../../bench/bench.js';\n\nregisterTest('compact_equiv', async (ctx) => {\n const { device } = ctx;\n const dtype = ctx.hasF16 ? 'f16' : 'f32';\n const weights = await loadWeights(device, '/weights', { targetDtype: dtype });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype, limits: ctx.limits };\n const chunks = presetChunks('file23k').slice(0, 64);\n\n const off = await translateBatch(gctx, weights, tok, chunks, { compact: false });\n const on = await translateBatch(gctx, weights, tok, chunks, { compact: true });\n\n let mismatchRows = 0;\n let firstMismatch = null;\n for (let i = 0; i < off.rows.length; i++) {\n if (off.rows[i].ids.join(',') !== on.rows[i].ids.join(',')) {\n mismatchRows++;\n firstMismatch ??= {\n row: i,\n off: off.rows[i].ids.slice(0, 12).join(','),\n on: on.rows[i].ids.slice(0, 12).join(','),\n };\n }\n }\n const compactions = on.metrics.compactions;\n return {\n pass: mismatchRows === 0 && compactions > 0,\n detail: {\n dtype, B: chunks.length, mismatchRows, compactions,\n ...(firstMismatch ? { firstMismatch } : {}),\n offDecodeMs: Number(off.metrics.decodeMs.toFixed(1)),\n onDecodeMs: Number(on.metrics.decodeMs.toFixed(1)),\n offTokPerSec: Number(off.metrics.tokPerSec.toFixed(0)),\n onTokPerSec: Number(on.metrics.tokPerSec.toFixed(0)),\n steps: { off: off.metrics.steps, on: on.metrics.steps },\n },\n };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["registerTest","ctx","device","dtype","weights","loadWeights","tok","loadTokenizer","gctx","chunks","presetChunks","off","translateBatch","on","mismatchRows","firstMismatch","i","compactions"],"mappings":"sfAeAA,EAAa,gBAAiB,MAAOC,GAAQ,CAC3C,KAAM,CAAE,OAAAC,CAAM,EAAKD,EACbE,EAAQF,EAAI,OAAS,MAAQ,MAC7BG,EAAU,MAAMC,EAAYH,EAAQ,WAAY,CAAE,YAAaC,EAAO,EAC5E,GAAI,CACF,MAAMG,EAAM,MAAMC,EAAa,EACzBC,EAAO,CAAE,OAAAN,EAAQ,MAAAC,EAAO,OAAQF,EAAI,MAAM,EAC1CQ,EAASC,EAAa,SAAS,EAAE,MAAM,EAAG,EAAE,EAE5CC,EAAM,MAAMC,EAAeJ,EAAMJ,EAASE,EAAKG,EAAQ,CAAE,QAAS,GAAO,EACzEI,EAAK,MAAMD,EAAeJ,EAAMJ,EAASE,EAAKG,EAAQ,CAAE,QAAS,GAAM,EAE7E,IAAIK,EAAe,EACfC,EAAgB,KACpB,QAASC,EAAI,EAAGA,EAAIL,EAAI,KAAK,OAAQK,IAC/BL,EAAI,KAAKK,CAAC,EAAE,IAAI,KAAK,GAAG,IAAMH,EAAG,KAAKG,CAAC,EAAE,IAAI,KAAK,GAAG,IACvDF,IACAC,IAAkB,CAChB,IAAKC,EACL,IAAKL,EAAI,KAAKK,CAAC,EAAE,IAAI,MAAM,EAAG,EAAE,EAAE,KAAK,GAAG,EAC1C,GAAIH,EAAG,KAAKG,CAAC,EAAE,IAAI,MAAM,EAAG,EAAE,EAAE,KAAK,GAAG,CAClD,GAGI,MAAMC,EAAcJ,EAAG,QAAQ,YAC/B,MAAO,CACL,KAAMC,IAAiB,GAAKG,EAAc,EAC1C,OAAQ,CACN,MAAAd,EAAO,EAAGM,EAAO,OAAQ,aAAAK,EAAc,YAAAG,EACvC,GAAIF,EAAgB,CAAE,cAAAA,CAAa,EAAK,GACxC,YAAa,OAAOJ,EAAI,QAAQ,SAAS,QAAQ,CAAC,CAAC,EACnD,WAAY,OAAOE,EAAG,QAAQ,SAAS,QAAQ,CAAC,CAAC,EACjD,aAAc,OAAOF,EAAI,QAAQ,UAAU,QAAQ,CAAC,CAAC,EACrD,YAAa,OAAOE,EAAG,QAAQ,UAAU,QAAQ,CAAC,CAAC,EACnD,MAAO,CAAE,IAAKF,EAAI,QAAQ,MAAO,GAAIE,EAAG,QAAQ,KAAK,CAC7D,CACA,CACE,QAAC,CACCT,EAAQ,OAAO,QAAO,CACxB,CACF,CAAC"}
assets/debug-Cn7EHWtJ.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/smoke-Vpwd4qDs.js","assets/gpu-utils-BTh3AGTJ.js","assets/f16-wKKZr58e.js","assets/modulepreload-polyfill-B5Qt9EMX.js","assets/preload-helper-BXl3LOEh.js","assets/adreno_probe-CjpGrE_r.js","assets/pipelines-DD24nEJg.js","assets/constants-C8VbFpic.js","assets/baseline-D00dppjV.js","assets/reference-Dj87VRUN.js","assets/shapes-BCQ9D81L.js","assets/golden-BEvfygyg.js","assets/weights-DADAGEAT.js","assets/weights-B-okS09o.js","assets/gemm-CQmO2bw5.js","assets/math-DNG-wiC0.js","assets/addln_embed-CzGikpaS.js","assets/attention-CPOKnefi.js","assets/argmax-CNtdxM2K.js","assets/m1-C-LxyYqB.js","assets/tokenizer-Ex1u7wXD.js","assets/encoder-DX8MOfcH.js","assets/ref_encoder_hidden-CV0jITdC.js","assets/m2-BcBIqkZm.js","assets/decoder-DI6VDxxO.js","assets/m3-JRnmhs5W.js","assets/generate-C4ruG1zm.js","assets/verify-HJ8NImMM.js","assets/m4a-Cy5ByJvH.js","assets/bench-C8ITpm5I.js","assets/chapter3k-Bxq8ds-a.js","assets/m4b-CsMr2Dik.js","assets/profile-DdyBUdtB.js","assets/enc_profile-Cn8Ppz7u.js","assets/tiled_sweep-5Klbkz37.js","assets/attn_sweep-C5U-KhDy.js","assets/lm_head_sweep-BrML7PDB.js","assets/proj_sweep-DMgaMchb.js","assets/compact_equiv-BsjFDsn-.js","assets/q8_lmhead-DI6MTAKe.js","assets/argmax_fuse-DcdFediE.js","assets/ffn_q8_sweep-CGfESiUo.js","assets/autotune-DBJGFXNj.js","assets/ffn_mt_sweep-bWrzWJ6f.js","assets/fuse_ln-DCGuPhdx.js","assets/prod_profile-BvqwynxL.js","assets/proj_wt-Dq4RO2ng.js","assets/enc_v3_sweep-C1_eeFjm.js","assets/ffn_splitk-B1WT9pJ7.js","assets/proj_splitk-BW05ofQo.js","assets/enc_pack-BEo0Mc8b.js","assets/mega-BZJyxtcQ.js","assets/mega_compile-Bk_Gmpea.js","assets/autotune-Cy4x-YB7.js","assets/dims_generic-BTPBo91W.js","assets/pack_ab-euJcUZD3.js","assets/engine-BTyy_WlH.js","assets/device-Z_ibNtmX.js","assets/batch_cap_ab-DpomwYzZ.js","assets/sg-DxPzZIDE.js","assets/mega_sg-cPjfjSik.js","assets/hachimi60-D0JkA1E4.js","assets/m5-CHFNkx9G.js","assets/xdev-ChyZmnvQ.js"])))=>i.map(i=>d[i]);
2
+ import"./modulepreload-polyfill-B5Qt9EMX.js";import{_ as t}from"./preload-helper-BXl3LOEh.js";const l=[];function $(e,o,{slow:r=!1}={}){l.push({name:e,fn:o,slow:r})}async function A(e,{includeSlow:o=!1,only:r=null,onResult:_=null}={}){const n=[],s=a=>{n.push(a),_?.(a)},c=r?l.filter(({name:a})=>a.includes(r)):l;for(const{name:a,fn:R,slow:v}of c){if(v&&!o&&!r){s({name:a,skip:!0,reason:"slow",ms:0});continue}const m=performance.now();let u;try{const p=await R(e);p&&p.skip?u={name:a,skip:!0,reason:p.reason??"",ms:performance.now()-m}:u={name:a,pass:!!p?.pass,detail:p?.detail??"",ms:performance.now()-m}}catch(p){u={name:a,pass:!1,detail:{error:String(p?.message??p),stack:String(p?.stack??"")},ms:performance.now()-m}}s(u)}return n}const d=document.querySelector("#app"),E=new URLSearchParams(location.search),P=E.get("run"),L=E.get("autorun")==="1",O=E.get("slow")==="1",D=E.get("only");function i(e,o){const r=document.createElement(e);return o!==void 0&&(r.textContent=o),r}async function T(e){if(P)try{await fetch(`/__gpu-results?run=${encodeURIComponent(P)}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})}catch(o){d.append(i("pre",`POST failed: ${o}`))}}function f(e){const o=document.createElement("table");o.border="1";const r=o.insertRow();for(const _ of["test","status","ms","detail"])r.append(i("th",_));for(const _ of e){const n=o.insertRow(),s=_.skip?`SKIP (${_.reason})`:_.pass?"PASS":"FAIL";n.style.color=_.skip?"#aa5":_.pass?"#5d5":"#f55",n.append(i("td",_.name),i("td",s),i("td",_.ms.toFixed(1))),n.append(i("td",typeof _.detail=="string"?_.detail:JSON.stringify(_.detail??"")))}d.append(o)}async function I(e){d.append(i("pre",`FATAL: ${e}`)),await T({fatal:e,results:[]})}async function V(){d.append(i("h1","webMT GPU debug harness"));let e;try{const[{initDevice:_}]=await Promise.all([t(()=>import("./device-Z_ibNtmX.js"),[]),t(()=>import("./smoke-Vpwd4qDs.js"),__vite__mapDeps([0,1,2,3,4])),t(()=>import("./adreno_probe-CjpGrE_r.js"),__vite__mapDeps([5,4,1,6,7,2,3])),t(()=>import("./baseline-D00dppjV.js"),__vite__mapDeps([8,9,10,7,11,3,4])),t(()=>import("./weights-DADAGEAT.js"),__vite__mapDeps([12,13,10,7,2,3,4])),t(()=>import("./gemm-CQmO2bw5.js"),__vite__mapDeps([14,1,6,7,13,10,2,15,3,4])),t(()=>import("./addln_embed-CzGikpaS.js"),__vite__mapDeps([16,1,6,7,15,2,3,4])),t(()=>import("./attention-CPOKnefi.js"),__vite__mapDeps([17,1,6,7,15,2,3,4])),t(()=>import("./argmax-CNtdxM2K.js"),__vite__mapDeps([18,1,6,7,15,3,4])),t(()=>import("./m1-C-LxyYqB.js"),__vite__mapDeps([19,1,13,10,7,2,20,21,6,22,3,4])),t(()=>import("./m2-BcBIqkZm.js"),__vite__mapDeps([23,1,13,10,7,2,20,21,6,24,22,3,4])),t(()=>import("./m3-JRnmhs5W.js"),__vite__mapDeps([25,13,10,7,2,20,26,21,6,24,27,11,3,4])),t(()=>import("./m4a-Cy5ByJvH.js"),__vite__mapDeps([28,13,10,7,2,20,26,21,6,24,29,4,30,11,3])),t(()=>import("./m4b-CsMr2Dik.js"),__vite__mapDeps([31,13,10,7,2,20,21,6,24,32,29,4,26,30,11,3])),t(()=>import("./enc_profile-Cn8Ppz7u.js"),__vite__mapDeps([33,13,10,7,2,20,32,24,21,6,29,4,26,30,3])),t(()=>import("./tiled_sweep-5Klbkz37.js"),__vite__mapDeps([34,13,10,7,2,20,21,6,29,4,26,24,30,3])),t(()=>import("./attn_sweep-C5U-KhDy.js"),__vite__mapDeps([35,1,13,10,7,2,20,21,6,29,4,26,24,30,3])),t(()=>import("./lm_head_sweep-BrML7PDB.js"),__vite__mapDeps([36,13,10,7,2,20,21,6,24,32,29,4,26,30,3])),t(()=>import("./proj_sweep-DMgaMchb.js"),__vite__mapDeps([37,1,13,10,7,2,20,21,6,24,32,29,4,26,30,3])),t(()=>import("./compact_equiv-BsjFDsn-.js"),__vite__mapDeps([38,13,10,7,2,20,26,21,6,24,29,4,30,3])),t(()=>import("./q8_lmhead-DI6MTAKe.js"),__vite__mapDeps([39,13,10,7,2,20,26,21,6,24,27,11,3,4])),t(()=>import("./argmax_fuse-DcdFediE.js"),__vite__mapDeps([40,1,6,7,13,10,2,20,26,21,24,32,29,4,30,3])),t(()=>import("./ffn_q8_sweep-CGfESiUo.js"),__vite__mapDeps([41,13,10,7,2,20,21,6,24,32,29,4,26,30,42,3])),t(()=>import("./ffn_mt_sweep-bWrzWJ6f.js"),__vite__mapDeps([43,13,10,7,2,20,21,6,24,32,29,4,26,30,3])),t(()=>import("./fuse_ln-DCGuPhdx.js"),__vite__mapDeps([44,1,6,7,13,10,2,20,26,21,24,32,29,4,30,15,3])),t(()=>import("./prod_profile-BvqwynxL.js"),__vite__mapDeps([45,13,10,7,2,20,21,6,24,32,29,4,26,30,3])),t(()=>import("./proj_wt-Dq4RO2ng.js"),__vite__mapDeps([46,1,6,7,13,10,2,20,26,21,24,32,29,4,30,15,3])),t(()=>import("./enc_v3_sweep-C1_eeFjm.js"),__vite__mapDeps([47,13,10,7,2,20,21,6,29,4,26,24,30,3])),t(()=>import("./ffn_splitk-B1WT9pJ7.js"),__vite__mapDeps([48,1,6,7,13,10,2,20,26,21,24,32,29,4,30,15,3])),t(()=>import("./proj_splitk-BW05ofQo.js"),__vite__mapDeps([49,1,6,7,13,10,2,20,26,21,24,32,29,4,30,15,3])),t(()=>import("./enc_pack-BEo0Mc8b.js"),__vite__mapDeps([50,1,13,10,7,2,20,21,6,26,24,29,4,30,3])),t(()=>import("./mega-BZJyxtcQ.js"),__vite__mapDeps([51,13,10,7,2,20,26,21,6,24,32,29,4,30,27,11,3])),t(()=>import("./mega_compile-Bk_Gmpea.js"),__vite__mapDeps([52,6,7,13,10,2,3,4])),t(()=>import("./autotune-Cy4x-YB7.js"),__vite__mapDeps([53,13,10,7,2,42,21,6,24,3,4])),t(()=>import("./dims_generic-BTPBo91W.js"),__vite__mapDeps([54,1,13,10,7,2,21,6,24,15,3,4])),t(()=>import("./pack_ab-euJcUZD3.js"),__vite__mapDeps([55,13,10,7,2,20,26,21,6,24,56,57,42,30,3,4])),t(()=>import("./batch_cap_ab-DpomwYzZ.js"),__vite__mapDeps([58,13,10,7,2,20,26,21,6,24,56,57,42,30,3,4])),t(()=>import("./sg-DxPzZIDE.js"),__vite__mapDeps([59,6,7,13,10,2,20,26,21,24,32,29,4,30,27,11,3])),t(()=>import("./mega_sg-cPjfjSik.js"),__vite__mapDeps([60,6,7,13,10,2,20,26,21,24,32,29,4,30,27,11,3])),t(()=>import("./hachimi60-D0JkA1E4.js"),__vite__mapDeps([61,13,10,7,2,20,26,21,6,24,42,27,3,4])),t(()=>import("./m5-CHFNkx9G.js"),__vite__mapDeps([62,13,10,7,2,20,26,21,6,24,29,4,30,3])),t(()=>import("./xdev-ChyZmnvQ.js"),__vite__mapDeps([63,13,10,7,2,20,26,21,6,24,29,4,30,3]))]);e=await _()}catch(_){await I(`${_?.message??_}
3
+ ${_?.stack??""}`);return}const o=e.adapterInfo;d.append(i("pre",`adapter: vendor=${o.vendor} arch=${o.architecture} device=${o.device}
4
+ description=${o.description}
5
+ shader-f16=${e.hasF16} timestamp-query=${e.hasTimestamps} subgroups=${e.hasSubgroups} (min ${e.subgroupMinSize})`));const r=async()=>{try{const _=i("pre","");d.append(_);const n=await A(e,{includeSlow:O,only:D,onResult:s=>{const c=s.skip?`SKIP(${s.reason})`:s.pass?"PASS":"FAIL";_.append(`${c} ${s.name} ${(s.ms??0).toFixed(0)}ms
6
+ `)}});f(n),await T({adapterInfo:e.adapterInfo,hasF16:e.hasF16,hasTimestamps:e.hasTimestamps,results:n})}catch(_){await I(`${_?.message??_}
7
+ ${_?.stack??""}`)}};if(L)await r();else{const _=i("button","Run tests");_.addEventListener("click",()=>{_.disabled=!0,r()}),d.append(_)}}V();export{$ as r};
8
+ //# sourceMappingURL=debug-Cn7EHWtJ.js.map
assets/debug-Cn7EHWtJ.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"mappings":";8FAGA,MAAMA,EAAQ,GAEP,SAASC,EAAaC,EAAMC,EAAI,CAAE,KAAAC,EAAO,EAAK,EAAK,GAAI,CAC5DJ,EAAM,KAAK,CAAE,KAAAE,EAAM,GAAAC,EAAI,KAAAC,CAAI,CAAE,CAC/B,CAKO,eAAeC,EAAOC,EAAK,CAAE,YAAAC,EAAc,GAAO,KAAAC,EAAO,KAAM,SAAAC,EAAW,IAAI,EAAK,GAAI,CAC5F,MAAMC,EAAU,GACVC,EAAQC,GAAU,CACtBF,EAAQ,KAAKE,CAAK,EAClBH,IAAWG,CAAK,CAClB,EACMC,EAAWL,EAAOR,EAAM,OAAO,CAAC,CAAE,KAAAE,CAAI,IAAOA,EAAK,SAASM,CAAI,CAAC,EAAIR,EAC1E,SAAW,CAAE,KAAAE,EAAM,GAAAC,EAAI,KAAAC,CAAI,IAAMS,EAAU,CACzC,GAAIT,GAAQ,CAACG,GAAe,CAACC,EAAM,CACjCG,EAAK,CAAE,KAAAT,EAAM,KAAM,GAAM,OAAQ,OAAQ,GAAI,EAAG,EAChD,QACF,CACA,MAAMY,EAAK,YAAY,IAAG,EAC1B,IAAIF,EACJ,GAAI,CACF,MAAMG,EAAM,MAAMZ,EAAGG,CAAG,EACpBS,GAAOA,EAAI,KACbH,EAAQ,CAAE,KAAAV,EAAM,KAAM,GAAM,OAAQa,EAAI,QAAU,GAAI,GAAI,YAAY,IAAG,EAAKD,CAAE,EAEhFF,EAAQ,CAAE,KAAAV,EAAM,KAAM,CAAC,CAACa,GAAK,KAAM,OAAQA,GAAK,QAAU,GAAI,GAAI,YAAY,IAAG,EAAKD,CAAE,CAE5F,OAASE,EAAK,CACZJ,EAAQ,CACN,KAAAV,EACA,KAAM,GACN,OAAQ,CAAE,MAAO,OAAOc,GAAK,SAAWA,CAAG,EAAG,MAAO,OAAOA,GAAK,OAAS,EAAE,CAAC,EAC7E,GAAI,YAAY,IAAG,EAAKF,CAChC,CACI,CACAH,EAAKC,CAAK,CACZ,CACA,OAAOF,CACT,CC1CA,MAAMO,EAAM,SAAS,cAAc,MAAM,EACnCC,EAAS,IAAI,gBAAgB,SAAS,MAAM,EAC5CC,EAAQD,EAAO,IAAI,KAAK,EACxBE,EAAUF,EAAO,IAAI,SAAS,IAAM,IACpCX,EAAcW,EAAO,IAAI,MAAM,IAAM,IACrCV,EAAOU,EAAO,IAAI,MAAM,EAE9B,SAASG,EAAGC,EAAKC,EAAM,CACrB,MAAMC,EAAO,SAAS,cAAcF,CAAG,EACvC,OAAIC,IAAS,SAAWC,EAAK,YAAcD,GACpCC,CACT,CAEA,eAAeC,EAAYC,EAAS,CAClC,GAAKP,EACL,GAAI,CACF,MAAM,MAAM,sBAAsB,mBAAmBA,CAAK,CAAC,GAAI,CAC7D,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAkB,EAC7C,KAAM,KAAK,UAAUO,CAAO,CAClC,CAAK,CACH,OAASV,EAAK,CACZC,EAAI,OAAOI,EAAG,MAAO,gBAAgBL,CAAG,EAAE,CAAC,CAC7C,CACF,CAEA,SAASW,EAAcjB,EAAS,CAC9B,MAAMkB,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,OAAS,IACf,MAAMC,EAAOD,EAAM,UAAS,EAC5B,UAAWE,IAAK,CAAC,OAAQ,SAAU,KAAM,QAAQ,EAAGD,EAAK,OAAOR,EAAG,KAAMS,CAAC,CAAC,EAC3E,UAAWC,KAAKrB,EAAS,CACvB,MAAMsB,EAAMJ,EAAM,UAAS,EACrBK,EAASF,EAAE,KAAO,SAASA,EAAE,MAAM,IAAMA,EAAE,KAAO,OAAS,OACjEC,EAAI,MAAM,MAAQD,EAAE,KAAO,OAASA,EAAE,KAAO,OAAS,OACtDC,EAAI,OAAOX,EAAG,KAAMU,EAAE,IAAI,EAAGV,EAAG,KAAMY,CAAM,EAAGZ,EAAG,KAAMU,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,EACxEC,EAAI,OAAOX,EAAG,KAAM,OAAOU,EAAE,QAAW,SAAWA,EAAE,OAAS,KAAK,UAAUA,EAAE,QAAU,EAAE,CAAC,CAAC,CAC/F,CACAd,EAAI,OAAOW,CAAK,CAClB,CAEA,eAAeM,EAAMC,EAAS,CAC5BlB,EAAI,OAAOI,EAAG,MAAO,UAAUc,CAAO,EAAE,CAAC,EACzC,MAAMV,EAAY,CAAE,MAAOU,EAAS,QAAS,EAAE,CAAE,CACnD,CAEA,eAAeC,GAAO,CACpBnB,EAAI,OAAOI,EAAG,KAAM,yBAAyB,CAAC,EAC9C,IAAIf,EACJ,GAAI,CACF,KAAM,CAAC,CAAE,WAAA+B,CAAU,CAAE,EAAI,MAAM,QAAQ,IAAI,CAC1CC,EAAA,IAAC,OAAO,sBAAoB,MAC5BA,EAAA,IAAC,OAAO,qBAAwB,gCAChCA,EAAA,IAAC,OAAO,4BAA+B,oCACvCA,EAAA,IAAC,OAAO,wBAA2B,sCACnCA,EAAA,IAAC,OAAO,uBAA0B,uCAClCA,EAAA,IAAC,OAAO,oBAAuB,8CAC/BA,EAAA,IAAC,OAAO,2BAA8B,wCACtCA,EAAA,IAAC,OAAO,yBAA4B,wCACpCA,EAAA,IAAC,OAAO,sBAAyB,sCACjCA,EAAA,IAAC,OAAO,kBAAqB,oDAC7BA,EAAA,IAAC,OAAO,kBAAqB,uDAC7BA,EAAA,IAAC,OAAO,kBAAqB,2DAC7BA,EAAA,IAAC,OAAO,mBAAsB,8DAC9BA,EAAA,IAAC,OAAO,mBAAsB,iEAC9BA,EAAA,IAAC,OAAO,2BAA8B,8DACtCA,EAAA,IAAC,OAAO,2BAA8B,2DACtCA,EAAA,IAAC,OAAO,0BAA6B,6DACrCA,EAAA,IAAC,OAAO,6BAAgC,8DACxCA,EAAA,IAAC,OAAO,0BAA6B,gEACrCA,EAAA,IAAC,OAAO,6BAAgC,2DACxCA,EAAA,IAAC,OAAO,yBAA4B,2DACpCA,EAAA,IAAC,OAAO,2BAA8B,gEACtCA,EAAA,IAAC,OAAO,4BAA+B,iEACvCA,EAAA,IAAC,OAAO,4BAA+B,8DACvCA,EAAA,IAAC,OAAO,uBAA0B,mEAClCA,EAAA,IAAC,OAAO,4BAA+B,8DACvCA,EAAA,IAAC,OAAO,uBAA0B,mEAClCA,EAAA,IAAC,OAAO,4BAA+B,2DACvCA,EAAA,IAAC,OAAO,0BAA6B,mEACrCA,EAAA,IAAC,OAAO,2BAA8B,mEACtCA,EAAA,IAAC,OAAO,wBAA2B,6DACnCA,EAAA,IAAC,OAAO,oBAAuB,oEAC/BA,EAAA,IAAC,OAAO,4BAA+B,yCACvCA,EAAA,IAAC,OAAO,wBAA2B,kDACnCA,EAAA,IAAC,OAAO,4BAA+B,oDACvCA,EAAA,IAAC,OAAO,uBAA0B,iEAClCA,EAAA,IAAC,OAAO,4BAA+B,iEACvCA,EAAA,IAAC,OAAO,kBAAqB,oEAC7BA,EAAA,IAAC,OAAO,uBAA0B,oEAClCA,EAAA,IAAC,OAAO,yBAA4B,2DACpCA,EAAA,IAAC,OAAO,kBAAqB,2DAC7BA,EAAA,IAAC,OAAO,oBAAuB,0DACpC,CAAK,EACDhC,EAAM,MAAM+B,EAAU,CACxB,OAASrB,EAAK,CACZ,MAAMkB,EAAM,GAAGlB,GAAK,SAAWA,CAAG;AAAA,EAAKA,GAAK,OAAS,EAAE,EAAE,EACzD,MACF,CAEA,MAAMuB,EAAOjC,EAAI,YACjBW,EAAI,OAAOI,EAAG,MACZ,mBAAmBkB,EAAK,MAAM,SAASA,EAAK,YAAY,WAAWA,EAAK,MAAM;AAAA,cAC/DA,EAAK,WAAW;AAAA,aACjBjC,EAAI,MAAM,oBAAoBA,EAAI,aAAa,cAAcA,EAAI,YAAY,SAASA,EAAI,eAAe,GAAG,CAAC,EAE7H,MAAMkC,EAAM,SAAY,CACtB,GAAI,CAGF,MAAMC,EAAWpB,EAAG,MAAO,EAAE,EAC7BJ,EAAI,OAAOwB,CAAQ,EACnB,MAAM/B,EAAU,MAAML,EAAOC,EAAK,CAChC,YAAAC,EAAa,KAAAC,EACb,SAAWuB,GAAM,CACf,MAAME,EAASF,EAAE,KAAO,QAAQA,EAAE,MAAM,IAAMA,EAAE,KAAO,OAAS,OAChEU,EAAS,OAAO,GAAGR,CAAM,KAAKF,EAAE,IAAI,MAAMA,EAAE,IAAM,GAAG,QAAQ,CAAC,CAAC;AAAA,CAAM,CACvE,CACR,CAAO,EACDJ,EAAcjB,CAAO,EACrB,MAAMe,EAAY,CAChB,YAAanB,EAAI,YACjB,OAAQA,EAAI,OACZ,cAAeA,EAAI,cACnB,QAAAI,CACR,CAAO,CACH,OAASM,EAAK,CACZ,MAAMkB,EAAM,GAAGlB,GAAK,SAAWA,CAAG;AAAA,EAAKA,GAAK,OAAS,EAAE,EAAE,CAC3D,CACF,EAEA,GAAII,EACF,MAAMoB,EAAG,MACJ,CACL,MAAME,EAAMrB,EAAG,SAAU,WAAW,EACpCqB,EAAI,iBAAiB,QAAS,IAAM,CAClCA,EAAI,SAAW,GACfF,EAAG,CACL,CAAC,EACDvB,EAAI,OAAOyB,CAAG,CAChB,CACF,CAEAN,EAAI","names":["tests","registerTest","name","fn","slow","runAll","ctx","includeSlow","only","onResult","results","push","entry","selected","t0","out","err","app","params","runId","autorun","el","tag","text","node","postResults","payload","renderResults","table","head","h","r","row","status","fatal","message","main","initDevice","__vitePreload","info","run","progress","btn"],"ignoreList":[],"sources":["../../src/debug/registry.js","../../src/debug-main.js"],"sourcesContent":["// Tiny GPU test registry. Test fns receive the ctx object from initDevice()\n// and return {pass, detail} or {skip: true, reason} — or throw (throw = fail).\n\nconst tests = [];\n\nexport function registerTest(name, fn, { slow = false } = {}) {\n tests.push({ name, fn, slow });\n}\n\n// `only` (substring) filters the test list — iteration aid for tuning runs;\n// matching tests run even when marked slow (asking for one by name is opting\n// into its cost).\nexport async function runAll(ctx, { includeSlow = false, only = null, onResult = null } = {}) {\n const results = [];\n const push = (entry) => {\n results.push(entry);\n onResult?.(entry); // live-progress hook (manual-mode devices render per test)\n };\n const selected = only ? tests.filter(({ name }) => name.includes(only)) : tests;\n for (const { name, fn, slow } of selected) {\n if (slow && !includeSlow && !only) {\n push({ name, skip: true, reason: 'slow', ms: 0 });\n continue;\n }\n const t0 = performance.now();\n let entry;\n try {\n const out = await fn(ctx);\n if (out && out.skip) {\n entry = { name, skip: true, reason: out.reason ?? '', ms: performance.now() - t0 };\n } else {\n entry = { name, pass: !!out?.pass, detail: out?.detail ?? '', ms: performance.now() - t0 };\n }\n } catch (err) {\n entry = {\n name,\n pass: false,\n detail: { error: String(err?.message ?? err), stack: String(err?.stack ?? '') },\n ms: performance.now() - t0,\n };\n }\n push(entry);\n }\n return results;\n}\n","import { runAll } from './debug/registry.js';\n\nconst app = document.querySelector('#app');\nconst params = new URLSearchParams(location.search);\nconst runId = params.get('run');\nconst autorun = params.get('autorun') === '1';\nconst includeSlow = params.get('slow') === '1';\nconst only = params.get('only');\n\nfunction el(tag, text) {\n const node = document.createElement(tag);\n if (text !== undefined) node.textContent = text;\n return node;\n}\n\nasync function postResults(payload) {\n if (!runId) return;\n try {\n await fetch(`/__gpu-results?run=${encodeURIComponent(runId)}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n } catch (err) {\n app.append(el('pre', `POST failed: ${err}`));\n }\n}\n\nfunction renderResults(results) {\n const table = document.createElement('table');\n table.border = '1';\n const head = table.insertRow();\n for (const h of ['test', 'status', 'ms', 'detail']) head.append(el('th', h));\n for (const r of results) {\n const row = table.insertRow();\n const status = r.skip ? `SKIP (${r.reason})` : r.pass ? 'PASS' : 'FAIL';\n row.style.color = r.skip ? '#aa5' : r.pass ? '#5d5' : '#f55';\n row.append(el('td', r.name), el('td', status), el('td', r.ms.toFixed(1)));\n row.append(el('td', typeof r.detail === 'string' ? r.detail : JSON.stringify(r.detail ?? '')));\n }\n app.append(table);\n}\n\nasync function fatal(message) {\n app.append(el('pre', `FATAL: ${message}`));\n await postResults({ fatal: message, results: [] });\n}\n\nasync function main() {\n app.append(el('h1', 'webMT GPU debug harness'));\n let ctx;\n try {\n const [{ initDevice }] = await Promise.all([\n import('./engine/device.js'),\n import('./debug/tests/smoke.js'), // registers tests\n import('./debug/tests/adreno_probe.js'), // early: must run before any device-lost cascade\n import('./debug/tests/baseline.js'),\n import('./debug/tests/weights.js'),\n import('./debug/tests/gemm.js'),\n import('./debug/tests/addln_embed.js'),\n import('./debug/tests/attention.js'),\n import('./debug/tests/argmax.js'),\n import('./debug/tests/m1.js'),\n import('./debug/tests/m2.js'),\n import('./debug/tests/m3.js'),\n import('./debug/tests/m4a.js'),\n import('./debug/tests/m4b.js'),\n import('./debug/tests/enc_profile.js'),\n import('./debug/tests/tiled_sweep.js'),\n import('./debug/tests/attn_sweep.js'),\n import('./debug/tests/lm_head_sweep.js'),\n import('./debug/tests/proj_sweep.js'),\n import('./debug/tests/compact_equiv.js'),\n import('./debug/tests/q8_lmhead.js'),\n import('./debug/tests/argmax_fuse.js'),\n import('./debug/tests/ffn_q8_sweep.js'),\n import('./debug/tests/ffn_mt_sweep.js'),\n import('./debug/tests/fuse_ln.js'),\n import('./debug/tests/prod_profile.js'),\n import('./debug/tests/proj_wt.js'),\n import('./debug/tests/enc_v3_sweep.js'),\n import('./debug/tests/ffn_splitk.js'),\n import('./debug/tests/proj_splitk.js'),\n import('./debug/tests/enc_pack.js'),\n import('./debug/tests/mega.js'),\n import('./debug/tests/mega_compile.js'),\n import('./debug/tests/autotune.js'),\n import('./debug/tests/dims_generic.js'),\n import('./debug/tests/pack_ab.js'),\n import('./debug/tests/batch_cap_ab.js'),\n import('./debug/tests/sg.js'),\n import('./debug/tests/mega_sg.js'),\n import('./debug/tests/hachimi60.js'),\n import('./debug/tests/m5.js'),\n import('./debug/tests/xdev.js'),\n ]);\n ctx = await initDevice();\n } catch (err) {\n await fatal(`${err?.message ?? err}\\n${err?.stack ?? ''}`);\n return;\n }\n\n const info = ctx.adapterInfo;\n app.append(el('pre',\n `adapter: vendor=${info.vendor} arch=${info.architecture} device=${info.device}\\n` +\n `description=${info.description}\\n` +\n `shader-f16=${ctx.hasF16} timestamp-query=${ctx.hasTimestamps} subgroups=${ctx.hasSubgroups} (min ${ctx.subgroupMinSize})`));\n\n const run = async () => {\n try {\n // Live progress line per finished test — a phone screen (manual mode)\n // needs to show life long before the final table + POST.\n const progress = el('pre', '');\n app.append(progress);\n const results = await runAll(ctx, {\n includeSlow, only,\n onResult: (r) => {\n const status = r.skip ? `SKIP(${r.reason})` : r.pass ? 'PASS' : 'FAIL';\n progress.append(`${status} ${r.name} ${(r.ms ?? 0).toFixed(0)}ms\\n`);\n },\n });\n renderResults(results);\n await postResults({\n adapterInfo: ctx.adapterInfo,\n hasF16: ctx.hasF16,\n hasTimestamps: ctx.hasTimestamps,\n results,\n });\n } catch (err) {\n await fatal(`${err?.message ?? err}\\n${err?.stack ?? ''}`);\n }\n };\n\n if (autorun) {\n await run();\n } else {\n const btn = el('button', 'Run tests');\n btn.addEventListener('click', () => {\n btn.disabled = true;\n run();\n });\n app.append(btn);\n }\n}\n\nmain();\n"],"file":"debug-Cn7EHWtJ.js"}
assets/dims_generic-BTPBo91W.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as se}from"./debug-Cn7EHWtJ.js";import{r as I}from"./gpu-utils-BTh3AGTJ.js";import{u as oe}from"./weights-B-okS09o.js";import{r as ne}from"./encoder-DX8MOfcH.js";import{c as re,e as ae}from"./decoder-DI6VDxxO.js";import{e as ce,f as J,a as ie}from"./f16-wKKZr58e.js";import{e as Q,m as L,b as j,a as E,p as fe}from"./math-DNG-wiC0.js";import{a as le,b as de,E as Z,L as R,R as Y}from"./constants-C8VbFpic.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./pipelines-DD24nEJg.js";const A=Object.freeze({dModel:64,heads:4,headDim:16,ffn:160,encLayers:3,decLayers:2,vocab:96,maxPos:64,srcCap:32,decodeCap:32,eos:2,pad:0,decoderStart:0,lnEps:1e-5}),C=8,K=[7,5],ue=.01,z=.08,me=.05;function W(m){let n=m|0;return()=>{n=n+1831565813|0;let c=Math.imul(n^n>>>15,n|1);return c^=c+Math.imul(c^c>>>7,c|61),((c^c>>>14)>>>0)/4294967296}}const X=m=>ie(J(m));function pe(m){const{dModel:n,ffn:c,vocab:i,maxPos:g}=A,d=W(m),l=(e,o)=>{const p=new Float32Array(e);for(let y=0;y<e;y++)p[y]=X((d()*2-1)*o);return p},a=e=>{const o=new Float32Array(e);for(let p=0;p<e;p++)o[p]=X(1+(d()-.5)*.5);return o},r=[],t=(e,o,p)=>{r.push([`${e}.weight`,[o,p],l(o*p,1/Math.sqrt(o))]),r.push([`${e}.bias`,[p],l(p,.05)])},f=e=>{r.push([`${e}.weight`,[n],a(n)]),r.push([`${e}.bias`,[n],l(n,.1)])};r.push(["shared.weight",[i,n],l(i*n,.5)]),r.push(["pos_embed",[g,n],l(g*n,.5)]);const s=new Float32Array(i);for(let e=0;e<i;e++)s[e]=(d()*2-1)*8;r.push(["final_logits_bias",[i],s,"f32"]);for(let e=0;e<A.encLayers;e++){const o=`enc.${e}`;t(`${o}.qkv`,n,3*n),t(`${o}.out`,n,n),f(`${o}.ln1`),t(`${o}.fc1`,n,c),t(`${o}.fc2`,c,n),f(`${o}.ln2`)}for(let e=0;e<A.decLayers;e++){const o=`dec.${e}`;t(`${o}.self_qkv`,n,3*n),t(`${o}.self_out`,n,n),f(`${o}.ln1`),t(`${o}.cross_q`,n,n),t(`${o}.cross_kv`,n,2*n),t(`${o}.cross_out`,n,n),f(`${o}.ln2`),t(`${o}.fc1`,n,c),t(`${o}.fc2`,c,n),f(`${o}.ln3`)}const k=new Map,_=[];let h=0;const $=[];for(const[e,o,p,y="f16"]of r){k.set(e,p);const v=y==="f16"?new Uint8Array(Uint16Array.from(p,J).buffer):new Uint8Array(p.buffer.slice(0)),B=Math.ceil(h/256)*256;$.push([B,v]),_.push({name:e,dtype:y,shape:o,byteOffset:B,byteLength:v.byteLength}),h=B+v.byteLength}const b=new Uint8Array(Math.ceil(h/4)*4);for(const[e,o]of $)b.set(o,e);return{manifest:{version:1,dtypeDefault:"f16",model:{...A},tensors:_},bin:b,ref:k}}const O=(m,n,c,i,g)=>{const d=g-i,l=new Float32Array(n*d);for(let a=0;a<n;a++)for(let r=0;r<d;r++)l[a*d+r]=m[a*c+i+r];return l};function be(m,n){const{dModel:c,heads:i,headDim:g,ffn:d}=A,l=i*g,{ids:a,lens:r,B:t,S:f}=n,s=t*f,k=new Uint32Array(s),_=new Uint32Array(s);for(let b=0;b<s;b++)k[b]=a[b],_[b]=b%f;let h=Q(k,_,m.get("shared.weight"),m.get("pos_embed"),{d:c,scale:Z});for(let b=0;b<A.encLayers;b++){const e=B=>m.get(`enc.${b}.${B}`),o=L(h,e("qkv.weight"),e("qkv.bias"),{M:s,K:c,N:3*l}),p=j(O(o,s,3*l,0,l),O(o,s,3*l,l,2*l),O(o,s,3*l,2*l,3*l),{B:t,M:f,H:i,D:g,L:f,lens:r});let y=L(p,e("out.weight"),e("out.bias"),{M:s,K:l,N:c});h=E(y,h,e("ln1.weight"),e("ln1.bias"),{rows:s,d:c,eps:R});const v=L(h,e("fc1.weight"),e("fc1.bias"),{M:s,K:c,N:d,silu:!0});y=L(v,e("fc2.weight"),e("fc2.bias"),{M:s,K:d,N:c}),h=E(y,h,e("ln2.weight"),e("ln2.bias"),{rows:s,d:c,eps:R})}const $=[];for(let b=0;b<A.decLayers;b++)$.push(L(h,m.get(`dec.${b}.cross_kv.weight`),m.get(`dec.${b}.cross_kv.bias`),{M:s,K:c,N:2*l}));return{encOut:h,crossKV:$}}function ge(m,n,c,i,g){const{vocab:d}=A,l=Math.ceil(d/32);if(i[g])return 1/0;let a=-1/0,r=-1/0;for(let t=0;t<d;t++){let f=Math.fround(m[g*d+t]+n[t]);c[g*l+(t>>5)]>>>(t&31)&1&&(f=Math.fround(f>0?f/Math.fround(Y):f*Math.fround(Y))),f>a?(r=a,a=f):f>r&&(r=f)}return a-r}function he(m,n,c){const{dModel:i,heads:g,headDim:d,ffn:l,vocab:a,decodeCap:r}=A,t=g*d,{lens:f,B:s,S:k}=c,_=Math.ceil(a/32),h=[],$=[],b=[],e=[];for(let u=0;u<A.decLayers;u++)h.push(new Float32Array(s*r*t)),$.push(new Float32Array(s*r*t)),b.push(O(n.crossKV[u],s*k,2*t,0,t)),e.push(O(n.crossKV[u],s*k,2*t,t,2*t));const o=new Float32Array(i*a),p=m.get("shared.weight");for(let u=0;u<a;u++)for(let w=0;w<i;w++)o[w*a+u]=p[u*i+w];const y=m.get("final_logits_bias");let v=new Uint32Array(s*_);for(let u=0;u<s;u++)v[u*_+(A.decoderStart>>5)]=1<<(A.decoderStart&31);let B=new Uint32Array(s),q=new Uint32Array(s).fill(A.decoderStart);const D=[];let N=null;for(let u=0;u<C;u++){let w=Q(q,new Uint32Array(s).fill(u),p,m.get("pos_embed"),{d:i,scale:Z});for(let S=0;S<A.decLayers;S++){const M=x=>m.get(`dec.${S}.${x}`),V=L(w,M("self_qkv.weight"),M("self_qkv.bias"),{M:s,K:i,N:3*t});for(let x=0;x<s;x++)for(let P=0;P<t;P++)h[S][(x*r+u)*t+P]=V[x*3*t+t+P],$[S][(x*r+u)*t+P]=V[x*3*t+2*t+P];let H=j(O(V,s,3*t,0,t),h[S],$[S],{B:s,M:1,H:g,D:d,L:r,lens:new Uint32Array(s).fill(u+1)}),T=L(H,M("self_out.weight"),M("self_out.bias"),{M:s,K:t,N:i});w=E(T,w,M("ln1.weight"),M("ln1.bias"),{rows:s,d:i,eps:R});const ee=L(w,M("cross_q.weight"),M("cross_q.bias"),{M:s,K:i,N:t});H=j(ee,b[S],e[S],{B:s,M:1,H:g,D:d,L:k,lens:f}),T=L(H,M("cross_out.weight"),M("cross_out.bias"),{M:s,K:t,N:i}),w=E(T,w,M("ln2.weight"),M("ln2.bias"),{rows:s,d:i,eps:R});const te=L(w,M("fc1.weight"),M("fc1.bias"),{M:s,K:i,N:l,silu:!0});T=L(te,M("fc2.weight"),M("fc2.bias"),{M:s,K:l,N:i}),w=E(T,w,M("ln3.weight"),M("ln3.bias"),{rows:s,d:i,eps:R})}const U=L(w,o,null,{M:s,K:i,N:a});u===0&&(N=U);const G=Array.from({length:s},(S,M)=>ge(U,y,v,B,M)),F=fe(U,y,v,B,{B:s,V:a});D.push({tokens:F.tokens,bitmask:F.newBitmaskWords,done:F.newDone,gaps:G}),v=F.newBitmaskWords,B=F.newDone,q=F.tokens}return{steps:D,logits0:N}}function ye(m,n,c,i,g){let d=0,l=0,a=0;for(let r=0;r<c.length;r++)for(let t=0;t<c[r];t++){const f=(r*i+t)*g;for(let s=0;s<g;s++){const k=Math.abs(m[f+s]-n[f+s]),_=Number.isNaN(k)?1/0:k;d+=_,l++,_>a&&(a=_)}}return{meanAbs:d/l,maxAbs:a}}async function we(m,n,c,i,g){const{device:d}=m,{vocab:l}=A,a=K.length,r=re(m,n,{B:a,S:c.S,maxSteps:C,...g}),t=d.createBuffer({label:"dims_generic tokens",size:C*a*4,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC}),f=r.logits?d.createBuffer({label:"dims_generic logits0",size:a*l*4,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.COPY_SRC}):null;try{for(let e=0;e<C;e++){const o=d.createCommandEncoder({label:`dims_generic step ${e}`}),p=o.beginComputePass(),{scratch:y}=ae(m,n,c,r,e,p);p.end(),o.copyBufferToBuffer(r.tokenRing,e*a*4,t,e*a*4,a*4),e===0&&f&&o.copyBufferToBuffer(r.logits,0,f,0,a*l*4),d.queue.submit([o.finish()]);for(const B of y)B.destroy();const v=i.steps[e];d.queue.writeBuffer(r.tokenRing,e*a*4,v.tokens),d.queue.writeBuffer(r.bitmask,0,v.bitmask),d.queue.writeBuffer(r.done,0,v.done)}const s=new Uint32Array(await I(d,t,C*a*4)),k=f?new Float32Array(await I(d,f,a*l*4)):null;let _=0,h=0,$=1/0,b=null;for(let e=0;e<C;e++)for(let o=0;o<a;o++){const p=i.steps[e].gaps[o];if(p<$&&($=p),s[e*a+o]!==i.steps[e].tokens[o]){if(p<me){h++;continue}_++,b??={t:e,b:o,got:s[e*a+o],want:i.steps[e].tokens[o],gap:p}}}return{mismatches:_,excused:h,minGap:Number($.toFixed(4)),firstBad:b,logits0:k}}finally{t.destroy(),f?.destroy(),r.destroy()}}se("dims_generic",async m=>{const{device:n}=m,c=m.hasF16?"f16":"f32",i=le(),{manifest:g,bin:d,ref:l}=pe(12648430),a=oe(n,g,d,{targetDtype:c,ffnWT:!0,projWT:!0});try{const r={device:n,dtype:c,limits:m.limits},t=K.length,f=32,s=W(1592639215),k=new Uint32Array(t*f);for(let D=0;D<t;D++){for(let N=0;N<K[D]-1;N++)k[D*f+N]=3+Math.floor(s()*(A.vocab-3));k[D*f+K[D]-1]=A.eos}const _={ids:k,lens:new Uint32Array(K),B:t,S:f},h=be(l,_),$=he(l,h,_),b=await ne(r,a,_);await n.queue.onSubmittedWorkDone();const e=c==="f16"?2:4,o=await I(n,b.encOut,t*f*A.dModel*e),p=c==="f16"?ce(new Uint16Array(o)):new Float32Array(o),y=ye(p,h.encOut,K,f,A.dModel),v={lean:{lmHead:"gemv",lmHeadFuse:"off",fuseLn:"off",decodeMega:"off"},fused:{lmHead:"tiled",lmHeadFuse:"on",fuseLn:"on",decodeMega:"off",tiledProj:["fc1","fc2","self_out","cross_q","cross_out"],ffnSplitK:2,projSplitK:2},...c==="f16"?{mega:{decodeMega:"on"}}:{}},B={cfg:{...A},dtype:c,enc:y,arms:{}};let q=y.meanAbs<=ue&&y.maxAbs<=z;for(const[D,N]of Object.entries(v)){const u=await we(r,a,b,$,N);if(u.logits0){let w=0;for(let U=0;U<u.logits0.length;U++){const G=Math.abs(u.logits0[U]-$.logits0[U]),F=Number.isNaN(G)?1/0:G;F>w&&(w=F)}B.logits0MaxAbs=Number(w.toFixed(4)),w<=z||(q=!1)}B.arms[D]={mismatches:u.mismatches,excused:u.excused,minGap:u.minGap,...u.firstBad?{firstBad:u.firstBad}:{}},u.mismatches>0&&(q=!1)}return b.arena.destroy(),B.enc={meanAbs:Number(y.meanAbs.toFixed(5)),maxAbs:Number(y.maxAbs.toFixed(5))},{pass:q,detail:B}}finally{a.buffer.destroy(),de(i)}});
2
+ //# sourceMappingURL=dims_generic-BTPBo91W.js.map
assets/dims_generic-BTPBo91W.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"dims_generic-BTPBo91W.js","sources":["../../src/debug/tests/dims_generic.js"],"sourcesContent":["// Dims-generic parity gate: the engine is model-agnostic within the Marian\n// family — geometry comes from manifest.model (applyModelConfig at upload),\n// nothing may still be wired to MoxhiMT-30's numbers. Prove it ON THIS\n// ADAPTER with a synthetic random-weights model whose every dimension\n// differs from the shipped 448/8×56/1792/24k/8e2d:\n//\n// dModel 64 = 4 heads × 16, ffn 160, vocab 96, enc 3 / dec 2 layers,\n// maxPos 64, srcCap 32, decodeCap 32\n//\n// The GPU encoder + T teacher-forced decode steps run against the f64 JS\n// reference (reference/math.js) on three routing arms — the lean GEMV split\n// pipeline, the tiled/fused/split-K route, and the decode megakernel. After\n// every step the token ring, repetition bitmask and done flags are FORCED to\n// the reference's values, so each step sees identical inputs and the argmax\n// pick must match the reference exactly — a mismatch is excused only when\n// the reference's own top-2 processed-logit gap at that (step, row) is\n// inside f16 accumulation noise (GAP_TOL), independently per step.\n//\n// Catches: dims baked into WGSL templates, vec4 strides, shared-memory\n// sizing, workgroup-shape defaults (e.g. attention_block's QB at head dims\n// where QB=16 exceeds 256 threads), split-K partition arithmetic, and\n// hard-wired layer counts. Weights are random but f16-exact, so the\n// reference is directly comparable. ~1s. Restores the prior active model\n// config on exit, so later synthetic-only tests keep their boot-config dims.\nimport { registerTest } from '../registry.js';\nimport { readback } from '../gpu-utils.js';\nimport { uploadParsed } from '../../engine/weights.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { createDecodeState, encodeDecodeStep } from '../../engine/decoder.js';\nimport { f32ToF16, f16ToF32, expandF16 } from '../../engine/f16.js';\nimport {\n matmulRef, addLayerNormRef, embedRef, attentionRef, penaltyArgmaxRef,\n} from '../../reference/math.js';\nimport {\n EMBED_SCALE, LN_EPS, REP_PENALTY, activeModelConfig, applyModelConfig,\n} from '../../engine/constants.js';\n\nconst CFG = Object.freeze({\n dModel: 64, heads: 4, headDim: 16, ffn: 160,\n encLayers: 3, decLayers: 2,\n vocab: 96, maxPos: 64, srcCap: 32, decodeCap: 32,\n eos: 2, pad: 0, decoderStart: 0, lnEps: 1e-5,\n});\nconst T = 8; // teacher-forced decode steps\nconst LENS = [7, 5]; // B = 2 source rows\nconst MEAN_TOL = 0.01; // m1's encoder tolerances (3 layers here vs its 8)\nconst MAX_TOL = 0.08;\nconst GAP_TOL = 0.05; // ref top-2 gap below this excuses a token flip\n\nfunction mulberry32(seed) {\n let s = seed | 0;\n return () => {\n s = (s + 0x6d2b79f5) | 0;\n let t = Math.imul(s ^ (s >>> 15), s | 1);\n t ^= t + Math.imul(t ^ (t >>> 7), t | 61);\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nconst f16x = (v) => f16ToF32(f32ToF16(v)); // exact f16 value, as f32\n\n// Build the synthetic model: manifest + bin (f16 tensors, f32 logits bias)\n// plus the exact-f16 f32 views the JS reference computes with.\nfunction buildSyntheticModel(seed) {\n const { dModel: D, ffn: F, vocab: V, maxPos } = CFG;\n const rng = mulberry32(seed);\n const rand = (n, amp) => {\n const a = new Float32Array(n);\n for (let i = 0; i < n; i++) a[i] = f16x((rng() * 2 - 1) * amp);\n return a;\n };\n const gamma = (n) => {\n const a = new Float32Array(n);\n for (let i = 0; i < n; i++) a[i] = f16x(1 + (rng() - 0.5) * 0.5);\n return a;\n };\n\n const specs = [];\n const linear = (name, K, N) => {\n specs.push([`${name}.weight`, [K, N], rand(K * N, 1 / Math.sqrt(K))]);\n specs.push([`${name}.bias`, [N], rand(N, 0.05)]);\n };\n const ln = (name) => {\n specs.push([`${name}.weight`, [D], gamma(D)]);\n specs.push([`${name}.bias`, [D], rand(D, 0.1)]);\n };\n specs.push(['shared.weight', [V, D], rand(V * D, 0.5)]);\n specs.push(['pos_embed', [maxPos, D], rand(maxPos * D, 0.5)]);\n // Wide f32 bias so greedy picks are dominated by well-separated values.\n const lbias = new Float32Array(V);\n for (let i = 0; i < V; i++) lbias[i] = (rng() * 2 - 1) * 8;\n specs.push(['final_logits_bias', [V], lbias, 'f32']);\n for (let l = 0; l < CFG.encLayers; l++) {\n const p = `enc.${l}`;\n linear(`${p}.qkv`, D, 3 * D);\n linear(`${p}.out`, D, D);\n ln(`${p}.ln1`);\n linear(`${p}.fc1`, D, F);\n linear(`${p}.fc2`, F, D);\n ln(`${p}.ln2`);\n }\n for (let l = 0; l < CFG.decLayers; l++) {\n const p = `dec.${l}`;\n linear(`${p}.self_qkv`, D, 3 * D);\n linear(`${p}.self_out`, D, D);\n ln(`${p}.ln1`);\n linear(`${p}.cross_q`, D, D);\n linear(`${p}.cross_kv`, D, 2 * D);\n linear(`${p}.cross_out`, D, D);\n ln(`${p}.ln2`);\n linear(`${p}.fc1`, D, F);\n linear(`${p}.fc2`, F, D);\n ln(`${p}.ln3`);\n }\n\n const ref = new Map();\n const entries = [];\n let cursor = 0;\n const chunks = [];\n for (const [name, shape, data, dtype = 'f16'] of specs) {\n ref.set(name, data);\n const bytes = dtype === 'f16'\n ? new Uint8Array(Uint16Array.from(data, f32ToF16).buffer)\n : new Uint8Array(data.buffer.slice(0));\n const byteOffset = Math.ceil(cursor / 256) * 256;\n chunks.push([byteOffset, bytes]);\n entries.push({ name, dtype, shape, byteOffset, byteLength: bytes.byteLength });\n cursor = byteOffset + bytes.byteLength;\n }\n const bin = new Uint8Array(Math.ceil(cursor / 4) * 4);\n for (const [off, bytes] of chunks) bin.set(bytes, off);\n return { manifest: { version: 1, dtypeDefault: 'f16', model: { ...CFG }, tensors: entries }, bin, ref };\n}\n\n// --- JS reference forward (f64 math on the exact-f16 weights) ---\n\nconst colSlice = (src, rows, stride, c0, c1) => {\n const w = c1 - c0;\n const out = new Float32Array(rows * w);\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < w; c++) out[r * w + c] = src[r * stride + c0 + c];\n }\n return out;\n};\n\nfunction refEncoder(W, batch) {\n const { dModel: D, heads: H, headDim: Dh, ffn: F } = CFG;\n const HD = H * Dh;\n const { ids, lens, B, S } = batch;\n const rows = B * S;\n const rowIds = new Uint32Array(rows);\n const pos = new Uint32Array(rows);\n for (let r = 0; r < rows; r++) {\n rowIds[r] = ids[r];\n pos[r] = r % S;\n }\n let x = embedRef(rowIds, pos, W.get('shared.weight'), W.get('pos_embed'),\n { d: D, scale: EMBED_SCALE });\n for (let l = 0; l < CFG.encLayers; l++) {\n const p = (n) => W.get(`enc.${l}.${n}`);\n const qkv = matmulRef(x, p('qkv.weight'), p('qkv.bias'), { M: rows, K: D, N: 3 * HD });\n const attnOut = attentionRef(\n colSlice(qkv, rows, 3 * HD, 0, HD),\n colSlice(qkv, rows, 3 * HD, HD, 2 * HD),\n colSlice(qkv, rows, 3 * HD, 2 * HD, 3 * HD),\n { B, M: S, H, D: Dh, L: S, lens });\n let y = matmulRef(attnOut, p('out.weight'), p('out.bias'), { M: rows, K: HD, N: D });\n x = addLayerNormRef(y, x, p('ln1.weight'), p('ln1.bias'), { rows, d: D, eps: LN_EPS });\n const f1 = matmulRef(x, p('fc1.weight'), p('fc1.bias'), { M: rows, K: D, N: F, silu: true });\n y = matmulRef(f1, p('fc2.weight'), p('fc2.bias'), { M: rows, K: F, N: D });\n x = addLayerNormRef(y, x, p('ln2.weight'), p('ln2.bias'), { rows, d: D, eps: LN_EPS });\n }\n const crossKV = [];\n for (let l = 0; l < CFG.decLayers; l++) {\n crossKV.push(matmulRef(x, W.get(`dec.${l}.cross_kv.weight`), W.get(`dec.${l}.cross_kv.bias`),\n { M: rows, K: D, N: 2 * HD }));\n }\n return { encOut: x, crossKV };\n}\n\n// Top-2 gap of the PROCESSED logits (bias + penalty), penaltyArgmaxRef's\n// exact arithmetic — Infinity for done rows (forced PAD always matches).\nfunction top2Gap(logits, bias, bitmask, done, b) {\n const { vocab: V } = CFG;\n const words = Math.ceil(V / 32);\n if (done[b]) return Infinity;\n let best = -Infinity;\n let second = -Infinity;\n for (let v = 0; v < V; v++) {\n let x = Math.fround(logits[b * V + v] + bias[v]);\n const seen = (bitmask[b * words + (v >> 5)] >>> (v & 31)) & 1;\n if (seen) x = Math.fround(x > 0 ? x / Math.fround(REP_PENALTY) : x * Math.fround(REP_PENALTY));\n if (x > best) { second = best; best = x; } else if (x > second) { second = x; }\n }\n return best - second;\n}\n\nfunction refDecode(W, encRef, batch) {\n const { dModel: D, heads: H, headDim: Dh, ffn: F, vocab: V, decodeCap: CAP } = CFG;\n const HD = H * Dh;\n const { lens, B, S } = batch;\n const words = Math.ceil(V / 32);\n const kvK = [];\n const kvV = [];\n const crossK = [];\n const crossV = [];\n for (let l = 0; l < CFG.decLayers; l++) {\n kvK.push(new Float32Array(B * CAP * HD));\n kvV.push(new Float32Array(B * CAP * HD));\n crossK.push(colSlice(encRef.crossKV[l], B * S, 2 * HD, 0, HD));\n crossV.push(colSlice(encRef.crossKV[l], B * S, 2 * HD, HD, 2 * HD));\n }\n const sharedT = new Float32Array(D * V);\n const shared = W.get('shared.weight');\n for (let v = 0; v < V; v++) {\n for (let d = 0; d < D; d++) sharedT[d * V + v] = shared[v * D + d];\n }\n const lbias = W.get('final_logits_bias');\n\n let bitmask = new Uint32Array(B * words);\n for (let b = 0; b < B; b++) {\n bitmask[b * words + (CFG.decoderStart >> 5)] = 1 << (CFG.decoderStart & 31);\n }\n let done = new Uint32Array(B);\n let prev = new Uint32Array(B).fill(CFG.decoderStart);\n const steps = [];\n let logits0 = null;\n for (let t = 0; t < T; t++) {\n let x = embedRef(prev, new Uint32Array(B).fill(t), shared, W.get('pos_embed'),\n { d: D, scale: EMBED_SCALE });\n for (let l = 0; l < CFG.decLayers; l++) {\n const p = (n) => W.get(`dec.${l}.${n}`);\n const qkv = matmulRef(x, p('self_qkv.weight'), p('self_qkv.bias'), { M: B, K: D, N: 3 * HD });\n for (let b = 0; b < B; b++) {\n for (let i = 0; i < HD; i++) {\n kvK[l][(b * CAP + t) * HD + i] = qkv[b * 3 * HD + HD + i];\n kvV[l][(b * CAP + t) * HD + i] = qkv[b * 3 * HD + 2 * HD + i];\n }\n }\n let attnOut = attentionRef(colSlice(qkv, B, 3 * HD, 0, HD), kvK[l], kvV[l],\n { B, M: 1, H, D: Dh, L: CAP, lens: new Uint32Array(B).fill(t + 1) });\n let y = matmulRef(attnOut, p('self_out.weight'), p('self_out.bias'), { M: B, K: HD, N: D });\n x = addLayerNormRef(y, x, p('ln1.weight'), p('ln1.bias'), { rows: B, d: D, eps: LN_EPS });\n const cq = matmulRef(x, p('cross_q.weight'), p('cross_q.bias'), { M: B, K: D, N: HD });\n attnOut = attentionRef(cq, crossK[l], crossV[l], { B, M: 1, H, D: Dh, L: S, lens });\n y = matmulRef(attnOut, p('cross_out.weight'), p('cross_out.bias'), { M: B, K: HD, N: D });\n x = addLayerNormRef(y, x, p('ln2.weight'), p('ln2.bias'), { rows: B, d: D, eps: LN_EPS });\n const f1 = matmulRef(x, p('fc1.weight'), p('fc1.bias'), { M: B, K: D, N: F, silu: true });\n y = matmulRef(f1, p('fc2.weight'), p('fc2.bias'), { M: B, K: F, N: D });\n x = addLayerNormRef(y, x, p('ln3.weight'), p('ln3.bias'), { rows: B, d: D, eps: LN_EPS });\n }\n const logits = matmulRef(x, sharedT, null, { M: B, K: D, N: V });\n if (t === 0) logits0 = logits;\n const gaps = Array.from({ length: B }, (_, b) => top2Gap(logits, lbias, bitmask, done, b));\n const r = penaltyArgmaxRef(logits, lbias, bitmask, done, { B, V });\n steps.push({ tokens: r.tokens, bitmask: r.newBitmaskWords, done: r.newDone, gaps });\n bitmask = r.newBitmaskWords;\n done = r.newDone;\n prev = r.tokens;\n }\n return { steps, logits0 };\n}\n\n// --- comparisons ---\n\nfunction compareValidRows(got, want, lens, S, N) {\n let sum = 0;\n let lanes = 0;\n let maxAbs = 0;\n for (let b = 0; b < lens.length; b++) {\n for (let m = 0; m < lens[b]; m++) {\n const off = (b * S + m) * N;\n for (let i = 0; i < N; i++) {\n const diff = Math.abs(got[off + i] - want[off + i]);\n const rank = Number.isNaN(diff) ? Infinity : diff;\n sum += rank;\n lanes++;\n if (rank > maxAbs) maxAbs = rank;\n }\n }\n }\n return { meanAbs: sum / lanes, maxAbs };\n}\n\n// One teacher-forced GPU decode arm: per step, run the step, capture its ring\n// slot, then overwrite ring/bitmask/done with the reference's values so step\n// t+1 sees reference inputs regardless of near-tie flips at step t.\nasync function runArm(gctx, weights, encRun, ref, opts) {\n const { device } = gctx;\n const { vocab: V } = CFG;\n const B = LENS.length;\n const state = createDecodeState(gctx, weights, { B, S: encRun.S, maxSteps: T, ...opts });\n const results = device.createBuffer({\n label: 'dims_generic tokens', size: T * B * 4,\n usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,\n });\n const logitsCap = state.logits ? device.createBuffer({\n label: 'dims_generic logits0', size: B * V * 4,\n usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,\n }) : null;\n try {\n for (let t = 0; t < T; t++) {\n const encoder = device.createCommandEncoder({ label: `dims_generic step ${t}` });\n const pass = encoder.beginComputePass();\n const { scratch } = encodeDecodeStep(gctx, weights, encRun, state, t, pass);\n pass.end();\n encoder.copyBufferToBuffer(state.tokenRing, t * B * 4, results, t * B * 4, B * 4);\n if (t === 0 && logitsCap) {\n encoder.copyBufferToBuffer(state.logits, 0, logitsCap, 0, B * V * 4);\n }\n device.queue.submit([encoder.finish()]);\n for (const s of scratch) s.destroy();\n const step = ref.steps[t];\n device.queue.writeBuffer(state.tokenRing, t * B * 4, step.tokens);\n device.queue.writeBuffer(state.bitmask, 0, step.bitmask);\n device.queue.writeBuffer(state.done, 0, step.done);\n }\n const tokens = new Uint32Array(await readback(device, results, T * B * 4));\n const logits0 = logitsCap\n ? new Float32Array(await readback(device, logitsCap, B * V * 4)) : null;\n\n let mismatches = 0;\n let excused = 0;\n let minGap = Infinity;\n let firstBad = null;\n for (let t = 0; t < T; t++) {\n for (let b = 0; b < B; b++) {\n const gap = ref.steps[t].gaps[b];\n if (gap < minGap) minGap = gap;\n if (tokens[t * B + b] !== ref.steps[t].tokens[b]) {\n if (gap < GAP_TOL) { excused++; continue; }\n mismatches++;\n firstBad ??= { t, b, got: tokens[t * B + b], want: ref.steps[t].tokens[b], gap };\n }\n }\n }\n return { mismatches, excused, minGap: Number(minGap.toFixed(4)), firstBad, logits0 };\n } finally {\n results.destroy();\n logitsCap?.destroy();\n state.destroy();\n }\n}\n\nregisterTest('dims_generic', async (ctx) => {\n const { device } = ctx;\n const dtype = ctx.hasF16 ? 'f16' : 'f32';\n const prior = activeModelConfig();\n const { manifest, bin, ref: W } = buildSyntheticModel(0xc0ffee);\n // uploadParsed applies CFG as the active model config (constants.js).\n const weights = uploadParsed(device, manifest, bin, { targetDtype: dtype, ffnWT: true, projWT: true });\n try {\n const gctx = { device, dtype, limits: ctx.limits };\n const B = LENS.length;\n const S = 32; // bucketFor(max LENS)\n const rng = mulberry32(0x5eedbeef | 0);\n const ids = new Uint32Array(B * S);\n for (let b = 0; b < B; b++) {\n for (let m = 0; m < LENS[b] - 1; m++) {\n ids[b * S + m] = 3 + Math.floor(rng() * (CFG.vocab - 3));\n }\n ids[b * S + LENS[b] - 1] = CFG.eos;\n }\n const batch = { ids, lens: new Uint32Array(LENS), B, S };\n\n const encRef = refEncoder(W, batch);\n const decRef = refDecode(W, encRef, batch);\n\n const encRun = await runEncoder(gctx, weights, batch);\n await device.queue.onSubmittedWorkDone();\n const eb = dtype === 'f16' ? 2 : 4;\n const encBytes = await readback(device, encRun.encOut, B * S * CFG.dModel * eb);\n const encGot = dtype === 'f16'\n ? expandF16(new Uint16Array(encBytes)) : new Float32Array(encBytes);\n const enc = compareValidRows(encGot, encRef.encOut, LENS, S, CFG.dModel);\n\n // Arms: lean GEMV split pipeline / tiled+fused+split-K / megakernel.\n const arms = {\n lean: { lmHead: 'gemv', lmHeadFuse: 'off', fuseLn: 'off', decodeMega: 'off' },\n fused: {\n lmHead: 'tiled', lmHeadFuse: 'on', fuseLn: 'on', decodeMega: 'off',\n tiledProj: ['fc1', 'fc2', 'self_out', 'cross_q', 'cross_out'],\n ffnSplitK: 2, projSplitK: 2,\n },\n ...(dtype === 'f16' ? { mega: { decodeMega: 'on' } } : {}),\n };\n const detail = { cfg: { ...CFG }, dtype, enc, arms: {} };\n let pass = enc.meanAbs <= MEAN_TOL && enc.maxAbs <= MAX_TOL;\n for (const [name, opts] of Object.entries(arms)) {\n const r = await runArm(gctx, weights, encRun, decRef, opts);\n if (r.logits0) {\n let maxAbs = 0;\n for (let i = 0; i < r.logits0.length; i++) {\n const diff = Math.abs(r.logits0[i] - decRef.logits0[i]);\n const rank = Number.isNaN(diff) ? Infinity : diff;\n if (rank > maxAbs) maxAbs = rank;\n }\n detail.logits0MaxAbs = Number(maxAbs.toFixed(4));\n if (!(maxAbs <= MAX_TOL)) pass = false;\n }\n detail.arms[name] = {\n mismatches: r.mismatches, excused: r.excused, minGap: r.minGap,\n ...(r.firstBad ? { firstBad: r.firstBad } : {}),\n };\n if (r.mismatches > 0) pass = false;\n }\n encRun.arena.destroy();\n detail.enc = { meanAbs: Number(enc.meanAbs.toFixed(5)), maxAbs: Number(enc.maxAbs.toFixed(5)) };\n return { pass, detail };\n } finally {\n weights.buffer.destroy();\n applyModelConfig(prior);\n }\n});\n"],"names":["CFG","T","LENS","MEAN_TOL","MAX_TOL","GAP_TOL","mulberry32","seed","s","t","f16x","v","f16ToF32","f32ToF16","buildSyntheticModel","D","F","V","maxPos","rng","rand","n","amp","a","i","gamma","specs","linear","name","K","N","ln","lbias","l","p","ref","entries","cursor","chunks","shape","data","dtype","bytes","byteOffset","bin","off","colSlice","src","rows","stride","c0","c1","w","out","r","c","refEncoder","W","batch","H","Dh","HD","ids","lens","B","S","rowIds","pos","x","embedRef","EMBED_SCALE","qkv","matmulRef","attnOut","attentionRef","addLayerNormRef","LN_EPS","f1","crossKV","top2Gap","logits","bias","bitmask","done","b","words","best","second","REP_PENALTY","refDecode","encRef","CAP","kvK","kvV","crossK","crossV","sharedT","shared","d","prev","steps","logits0","y","cq","gaps","_","penaltyArgmaxRef","compareValidRows","got","want","sum","lanes","maxAbs","m","diff","rank","runArm","gctx","weights","encRun","opts","device","state","createDecodeState","results","logitsCap","encoder","pass","scratch","encodeDecodeStep","step","tokens","readback","mismatches","excused","minGap","firstBad","gap","registerTest","ctx","prior","activeModelConfig","manifest","uploadParsed","decRef","runEncoder","eb","encBytes","encGot","expandF16","enc","arms","detail","applyModelConfig"],"mappings":"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"}
assets/enc_pack-BEo0Mc8b.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as D}from"./debug-Cn7EHWtJ.js";import{r as O}from"./gpu-utils-BTh3AGTJ.js";import{l as T}from"./weights-B-okS09o.js";import{l as q,t as v}from"./tokenizer-Ex1u7wXD.js";import{r as P}from"./encoder-DX8MOfcH.js";import{t as A}from"./generate-C4ruG1zm.js";import{D as x}from"./constants-C8VbFpic.js";import{p as E}from"./bench-C8ITpm5I.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./f16-wKKZr58e.js";import"./pipelines-DD24nEJg.js";import"./decoder-DI6VDxxO.js";import"./chapter3k-Bxq8ds-a.js";const N=2*x,B=l=>{const r=[...l].sort((w,d)=>w-d),f=r.length>>1;return r.length%2?r[f]:(r[f-1]+r[f])/2};async function _(l,r){const{device:f}=l;if(!l.hasF16)return{skip:!0,reason:"production route is f16"};const w=await T(f,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0,projWT:!0});try{const d=await q();return await r({device:f,dtype:"f16",limits:l.limits},w,d)}finally{w.buffer.destroy()}}function F(l,r,f,{B:w,S:d,lens:b},k){let u=0,m=0,p=null;for(let i=0;i<w;i++)for(let e=0;e<d;e++){const o=(i*d+e)*k;if(e<b[i]){for(let t=0;t<k;t++)if(r[o+t]!==f[o+t]){u++,p??={name:l,b:i,m:e,i:t,got:r[o+t],want:f[o+t]};break}}else for(let t=0;t<k;t++)if(r[o+t]!==0){m++;break}}return{rowMismatches:u,padNonZero:m,firstDiff:p}}D("enc_pack_equiv",async l=>_(l,async(r,f,w)=>{const{device:d}=r,b=[...E("file23k")].sort((c,s)=>s.length-c.length),k=Array.from({length:64},(c,s)=>b[s*7%b.length]),u=await v(w,k),{B:m,S:p,lens:i}=u,e=i.reduce((c,s)=>c+s,0),o=async c=>{const s=await P(r,f,u,{packed:c}),y={packed:s.packed,encOut:new Uint16Array(await O(d,s.encOut,m*p*x*2)),ckv0:new Uint16Array(await O(d,s.crossKV[0],m*p*N*2)),ckv1:new Uint16Array(await O(d,s.crossKV[1],m*p*N*2))};return s.arena.destroy(),y},t=await o(!1),n=await o(!0),h=[F("encOut",n.encOut,t.encOut,u,x),F("crossKV0",n.ckv0,t.ckv0,u,N),F("crossKV1",n.ckv1,t.ckv1,u,N)],M=h.reduce((c,s)=>c+s.rowMismatches,0),a=h.reduce((c,s)=>c+s.padNonZero,0);return{pass:n.packed===!0&&t.packed===!1&&M===0&&a===0,detail:{B:m,S:p,total:e,fillPct:Number((100*e/(m*p)).toFixed(1)),basePacked:t.packed,pkPacked:n.packed,rowMismatches:M,padNonZero:a,firstDiff:h.map(c=>c.firstDiff).find(Boolean)??null}}}));D("enc_pack_sweep",async l=>_(l,async(r,f,w)=>{const{device:d}=r,b=7,k=[...E("file23k")].sort((i,e)=>e.length-i.length),u=async i=>{const e=await v(w,k.slice(0,i)),o=e.lens.reduce((a,c)=>a+c,0),t=async a=>{const c=performance.now(),s=await P(r,f,e,{packed:a});return await d.queue.onSubmittedWorkDone(),s.arena.destroy(),performance.now()-c};for(const a of[!1,!0])await t(a);const n={off:[],on:[]};for(let a=0;a<b;a++)n.off.push(await t(!1)),n.on.push(await t(!0));const h=B(n.off),M=B(n.on);return{B:e.B,S:e.S,fillPct:Number((100*o/(e.B*e.S)).toFixed(1)),offMedianMs:Number(h.toFixed(1)),onMedianMs:Number(M.toFixed(1)),deltaPct:Number((100*(M-h)/h).toFixed(1)),offRuns:n.off.map(a=>Number(a.toFixed(1))),onRuns:n.on.map(a=>Number(a.toFixed(1)))}},m=await u(64),p=await u(128);return{pass:!0,detail:{rounds:b,b64:m,b128:p}}}));D("enc_pack_e2e_ab",async l=>_(l,async(r,f,w)=>{const b=[...E("file23k")].sort((i,e)=>e.length-i.length),k=async(i,e)=>{const{rows:o,metrics:t}=await A(r,f,w,i,{encPacked:e});return{texts:o.map(n=>n.text),m:t}},u=async i=>{const e=b.slice(0,i);await k(e,!1);const o={off:[],on:[]};let t=!0;for(let s=0;s<5;s++){const y=await k(e,!1),g=await k(e,"auto");o.off.push(y.m),o.on.push(g.m),y.texts.some((S,R)=>S!==g.texts[R])&&(t=!1)}const n=(s,y)=>Number(B(s.map(g=>g[y])).toFixed(1)),h=n(o.off,"encoderMs"),M=n(o.on,"encoderMs"),a=n(o.off,"encoderMs")+n(o.off,"decodeMs"),c=n(o.on,"encoderMs")+n(o.on,"decodeMs");return{B:i,tokensEqual:t,encOffMs:h,encOnMs:M,encDeltaPct:Number((100*(M-h)/h).toFixed(1)),decOffMs:n(o.off,"decodeMs"),decOnMs:n(o.on,"decodeMs"),e2eOffMs:Number(a.toFixed(1)),e2eOnMs:Number(c.toFixed(1)),e2eDeltaPct:Number((100*(c-a)/a).toFixed(1))}},m=await u(64),p=await u(128);return{pass:m.tokensEqual&&p.tokensEqual,detail:{reps:5,b64:m,b128:p}}}),{slow:!0});
2
+ //# sourceMappingURL=enc_pack-BEo0Mc8b.js.map
assets/enc_pack-BEo0Mc8b.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"enc_pack-BEo0Mc8b.js","sources":["../../src/debug/tests/enc_pack.js"],"sourcesContent":["// Encoder row-packing round: drop the pad rows (file23k b128 batch fill\n// 80.8%) so every encoder GEMM runs at T = Σ lens rows and attention\n// early-exits query blocks past len; crossKV/encOut scatter back to the\n// padded layout inside the same pass (scatter_rows.wgsl).\n//\n// enc_pack_equiv correctness gate — packed vs unpacked runEncoder on real\n// ragged file23k batches must be BIT-exact on valid rows\n// (row-local math everywhere: GEMM rows, online-softmax\n// per query, LN per row), and packed pad rows must read\n// zero (arena zero-init, scatter never touches them).\n// enc_pack_sweep encoder wall off/on × b64/b128, interleaved medians of\n// ROUNDS (same methodology as enc_v3_sweep).\n// enc_pack_e2e_ab full translateBatch off/on interleaved medians of 5 —\n// the decider; packing is not pinned state (it lives\n// entirely inside runEncoder), but e2e is the record.\nimport { registerTest } from '../registry.js';\nimport { readback } from '../gpu-utils.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { translateBatch } from '../../engine/generate.js';\nimport { D_MODEL } from '../../engine/constants.js';\nimport { presetChunks } from '../../bench/bench.js';\n\nconst CROSS_KV_N = 2 * D_MODEL; // 896\n\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nasync function withEngine(ctx, fn) {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'production route is f16' };\n const weights = await loadWeights(device, '/weights', {\n targetDtype: 'f16', lmHeadQ8: true, ffnWT: true, projWT: true,\n });\n try {\n const tok = await loadTokenizer();\n return await fn({ device, dtype: 'f16', limits: ctx.limits }, weights, tok);\n } finally {\n weights.buffer.destroy();\n }\n}\n\n// Bit-compare one padded [B·S, N] f16 buffer pair: valid rows equal in the\n// packed and unpacked runs, pad rows zero in the packed run.\nfunction compareBuf(name, packedU16, baseU16, { B, S, lens }, N) {\n let rowMismatches = 0;\n let padNonZero = 0;\n let firstDiff = null;\n for (let b = 0; b < B; b++) {\n for (let m = 0; m < S; m++) {\n const off = (b * S + m) * N;\n if (m < lens[b]) {\n for (let i = 0; i < N; i++) {\n if (packedU16[off + i] !== baseU16[off + i]) {\n rowMismatches++;\n firstDiff ??= { name, b, m, i, got: packedU16[off + i], want: baseU16[off + i] };\n break;\n }\n }\n } else {\n for (let i = 0; i < N; i++) {\n if (packedU16[off + i] !== 0) { padNonZero++; break; }\n }\n }\n }\n }\n return { rowMismatches, padNonZero, firstDiff };\n}\n\nregisterTest('enc_pack_equiv', async (ctx) => withEngine(ctx, async (gctx, weights, tok) => {\n const { device } = gctx;\n // Mixed lengths on purpose: interleave long and short chunks so the batch\n // is genuinely ragged (sorted-by-length slices are near-uniform).\n const sorted = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n const chunks = Array.from({ length: 64 }, (_, i) => sorted[(i * 7) % sorted.length]);\n const batch = await tokenizeBatch(tok, chunks);\n const { B, S, lens } = batch;\n const total = lens.reduce((a, x) => a + x, 0);\n\n const grab = async (packed) => {\n const run = await runEncoder(gctx, weights, batch, { packed });\n const out = {\n packed: run.packed,\n encOut: new Uint16Array(await readback(device, run.encOut, B * S * D_MODEL * 2)),\n ckv0: new Uint16Array(await readback(device, run.crossKV[0], B * S * CROSS_KV_N * 2)),\n ckv1: new Uint16Array(await readback(device, run.crossKV[1], B * S * CROSS_KV_N * 2)),\n };\n run.arena.destroy();\n return out;\n };\n const base = await grab(false);\n const pk = await grab(true);\n\n const results = [\n compareBuf('encOut', pk.encOut, base.encOut, batch, D_MODEL),\n compareBuf('crossKV0', pk.ckv0, base.ckv0, batch, CROSS_KV_N),\n compareBuf('crossKV1', pk.ckv1, base.ckv1, batch, CROSS_KV_N),\n ];\n const rowMismatches = results.reduce((a, r) => a + r.rowMismatches, 0);\n const padNonZero = results.reduce((a, r) => a + r.padNonZero, 0);\n return {\n pass: pk.packed === true && base.packed === false && rowMismatches === 0 && padNonZero === 0,\n detail: {\n B, S, total, fillPct: Number((100 * total / (B * S)).toFixed(1)),\n basePacked: base.packed, pkPacked: pk.packed,\n rowMismatches, padNonZero,\n firstDiff: results.map((r) => r.firstDiff).find(Boolean) ?? null,\n },\n };\n}));\n\nregisterTest('enc_pack_sweep', async (ctx) => withEngine(ctx, async (gctx, weights, tok) => {\n const { device } = gctx;\n const ROUNDS = 7;\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n const sweepBatch = async (n) => {\n const batch = await tokenizeBatch(tok, chunks.slice(0, n));\n const total = batch.lens.reduce((a, x) => a + x, 0);\n const timeOne = async (packed) => {\n const t0 = performance.now();\n const run = await runEncoder(gctx, weights, batch, { packed });\n await device.queue.onSubmittedWorkDone();\n run.arena.destroy();\n return performance.now() - t0;\n };\n for (const p of [false, true]) await timeOne(p); // warmup compiles\n const times = { off: [], on: [] };\n for (let r = 0; r < ROUNDS; r++) {\n times.off.push(await timeOne(false));\n times.on.push(await timeOne(true));\n }\n const offMed = median(times.off);\n const onMed = median(times.on);\n return {\n B: batch.B, S: batch.S,\n fillPct: Number((100 * total / (batch.B * batch.S)).toFixed(1)),\n offMedianMs: Number(offMed.toFixed(1)),\n onMedianMs: Number(onMed.toFixed(1)),\n deltaPct: Number((100 * (onMed - offMed) / offMed).toFixed(1)),\n offRuns: times.off.map((x) => Number(x.toFixed(1))),\n onRuns: times.on.map((x) => Number(x.toFixed(1))),\n };\n };\n const b64 = await sweepBatch(64);\n const b128 = await sweepBatch(128);\n return { pass: true, detail: { rounds: ROUNDS, b64, b128 } };\n}));\n\nregisterTest(\n 'enc_pack_e2e_ab',\n async (ctx) => withEngine(ctx, async (gctx, weights, tok) => {\n const REPS = 5;\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n const runArm = async (srcs, encPacked) => {\n const { rows, metrics } = await translateBatch(gctx, weights, tok, srcs, { encPacked });\n return { texts: rows.map((r) => r.text), m: metrics };\n };\n const abBatch = async (n) => {\n const srcs = chunks.slice(0, n);\n await runArm(srcs, false); // warmup (compiles + clocks)\n const arms = { off: [], on: [] };\n let tokensEqual = true;\n for (let r = 0; r < REPS; r++) {\n const off = await runArm(srcs, false);\n const on = await runArm(srcs, 'auto');\n arms.off.push(off.m);\n arms.on.push(on.m);\n if (off.texts.some((t, i) => t !== on.texts[i])) tokensEqual = false;\n }\n const med = (xs, f) => Number(median(xs.map((m) => m[f])).toFixed(1));\n const offEnc = med(arms.off, 'encoderMs');\n const onEnc = med(arms.on, 'encoderMs');\n const offTot = med(arms.off, 'encoderMs') + med(arms.off, 'decodeMs');\n const onTot = med(arms.on, 'encoderMs') + med(arms.on, 'decodeMs');\n return {\n B: n, tokensEqual,\n encOffMs: offEnc, encOnMs: onEnc,\n encDeltaPct: Number((100 * (onEnc - offEnc) / offEnc).toFixed(1)),\n decOffMs: med(arms.off, 'decodeMs'), decOnMs: med(arms.on, 'decodeMs'),\n e2eOffMs: Number(offTot.toFixed(1)), e2eOnMs: Number(onTot.toFixed(1)),\n e2eDeltaPct: Number((100 * (onTot - offTot) / offTot).toFixed(1)),\n };\n };\n const b64 = await abBatch(64);\n const b128 = await abBatch(128);\n return { pass: b64.tokensEqual && b128.tokensEqual, detail: { reps: REPS, b64, b128 } };\n }),\n { slow: true },\n);\n"],"names":["CROSS_KV_N","D_MODEL","median","xs","s","a","b","m","withEngine","ctx","fn","device","weights","loadWeights","tok","loadTokenizer","compareBuf","name","packedU16","baseU16","B","S","lens","N","rowMismatches","padNonZero","firstDiff","off","i","registerTest","gctx","sorted","presetChunks","chunks","_","batch","tokenizeBatch","total","x","grab","packed","run","runEncoder","out","readback","base","pk","results","r","ROUNDS","sweepBatch","n","timeOne","t0","p","times","offMed","onMed","b64","b128","runArm","srcs","encPacked","rows","metrics","translateBatch","abBatch","arms","tokensEqual","on","t","med","f","offEnc","onEnc","offTot","onTot"],"mappings":"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"}
assets/enc_profile-Cn8Ppz7u.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as v}from"./debug-Cn7EHWtJ.js";import{l as y}from"./weights-B-okS09o.js";import{l as U,t as z}from"./tokenizer-Ex1u7wXD.js";import{a as S,b as T}from"./profile-DdyBUdtB.js";import{p as D}from"./bench-C8ITpm5I.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./constants-C8VbFpic.js";import"./f16-wKKZr58e.js";import"./decoder-DI6VDxxO.js";import"./encoder-DX8MOfcH.js";import"./pipelines-DD24nEJg.js";import"./generate-C4ruG1zm.js";import"./chapter3k-Bxq8ds-a.js";const h=10,E=s=>s.startsWith("E")?s.split(".")[1]:s.split(".")[0];v("enc_profile",async s=>{if(!s.hasTimestamps)return{skip:!0,reason:"no timestamp-query"};const{device:m}=s,i=s.hasF16?"f16":"f32",n=await y(m,"/weights",{targetDtype:i});try{const w=await U(),l={device:m,dtype:i,hasTimestamps:s.hasTimestamps},b=[...D("file23k")].sort((p,e)=>e.length-p.length),u=async p=>{const e=await z(w,b.slice(0,p)),k=await S(l,n,e,{repeats:h}),o=await T(l,n,e,{repeats:h}),c=new Map;for(const t of o.rows){const a=E(t.label),r=c.get(a)??{kind:a,avgUs:0,pct:0};r.avgUs=Number((r.avgUs+t.avgUs).toFixed(1)),r.pct=Number((r.pct+t.pct).toFixed(1)),c.set(a,r)}return{B:e.B,S:o.S,normalRunMs:k.runMs,profRunSumUs:o.runSumUs,zeroDeltaPct:o.zeroDeltaPct,byKind:[...c.values()].sort((t,a)=>a.pct-t.pct),topSites:o.rows.slice(0,10).map(t=>({site:t.label,avgUs:t.avgUs,pct:t.pct}))}},f=await u(32),d=await u(64),g=f.zeroDeltaPct>60||d.zeroDeltaPct>60;return{pass:!g,detail:{dtype:i,note:"pct = relative pass-split weights; profRunSumUs vs normalRunMs shows pass-split overhead",...g?{warning:"timestamps look quantized — numbers unusable"}:{},b32:f,b64:d}}}finally{n.buffer.destroy()}});
2
+ //# sourceMappingURL=enc_profile-Cn8Ppz7u.js.map
assets/enc_profile-Cn8Ppz7u.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"enc_profile-Cn8Ppz7u.js","sources":["../../src/debug/tests/enc_profile.js"],"sourcesContent":["// Encoder per-kernel timestamp profile at b32/b64 (file23k longest chunks) —\n// the data source for the tiled-GEMM work: the encoder was never tuned and\n// overtakes decode wall time at b64 (batch-scaling experiment, 2026-07-06).\n//\n// Emits, per batch size: the by-KIND rollup (qkv/attn/out/add_ln/fc1/fc2\n// summed across the 8 layers — the actionable view), the top sites table,\n// and runSumUs vs normal-mode wall clock (same caveat as m4b_profile: pass\n// splitting adds overhead, treat pct as relative weights).\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { profileEncoder, timeEncoder } from '../../bench/profile.js';\nimport { presetChunks } from '../../bench/bench.js';\n\nconst REPEATS = 10;\n\n// E3.fc1 → fc1; embed/crossKV.0 pass through.\nconst kindOf = (label) => (label.startsWith('E') ? label.split('.')[1] : label.split('.')[0]);\n\nregisterTest('enc_profile', async (ctx) => {\n if (!ctx.hasTimestamps) return { skip: true, reason: 'no timestamp-query' };\n const { device } = ctx;\n const dtype = ctx.hasF16 ? 'f16' : 'f32';\n const weights = await loadWeights(device, '/weights', { targetDtype: dtype });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype, hasTimestamps: ctx.hasTimestamps };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n\n const runOne = async (n) => {\n const batch = await tokenizeBatch(tok, chunks.slice(0, n));\n // Normal-mode wall clock first (warms pipelines for the profiled runs).\n const normal = await timeEncoder(gctx, weights, batch, { repeats: REPEATS });\n const prof = await profileEncoder(gctx, weights, batch, { repeats: REPEATS });\n\n const byKind = new Map();\n for (const r of prof.rows) {\n const k = kindOf(r.label);\n const e = byKind.get(k) ?? { kind: k, avgUs: 0, pct: 0 };\n e.avgUs = Number((e.avgUs + r.avgUs).toFixed(1));\n e.pct = Number((e.pct + r.pct).toFixed(1));\n byKind.set(k, e);\n }\n return {\n B: batch.B, S: prof.S,\n normalRunMs: normal.runMs,\n profRunSumUs: prof.runSumUs,\n zeroDeltaPct: prof.zeroDeltaPct,\n byKind: [...byKind.values()].sort((a, b) => b.pct - a.pct),\n topSites: prof.rows.slice(0, 10).map((r) => ({ site: r.label, avgUs: r.avgUs, pct: r.pct })),\n };\n };\n\n const b32 = await runOne(32);\n const b64 = await runOne(64);\n const quantized = b32.zeroDeltaPct > 60 || b64.zeroDeltaPct > 60;\n return {\n pass: !quantized,\n detail: {\n dtype,\n note: 'pct = relative pass-split weights; profRunSumUs vs normalRunMs shows pass-split overhead',\n ...(quantized ? { warning: 'timestamps look quantized — numbers unusable' } : {}),\n b32, b64,\n },\n };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["REPEATS","kindOf","label","registerTest","ctx","device","dtype","weights","loadWeights","tok","loadTokenizer","gctx","chunks","presetChunks","a","b","runOne","n","batch","tokenizeBatch","normal","timeEncoder","prof","profileEncoder","byKind","r","k","e","b32","b64","quantized"],"mappings":"kiBAcA,MAAMA,EAAU,GAGVC,EAAUC,GAAWA,EAAM,WAAW,GAAG,EAAIA,EAAM,MAAM,GAAG,EAAE,CAAC,EAAIA,EAAM,MAAM,GAAG,EAAE,CAAC,EAE3FC,EAAa,cAAe,MAAOC,GAAQ,CACzC,GAAI,CAACA,EAAI,cAAe,MAAO,CAAE,KAAM,GAAM,OAAQ,oBAAoB,EACzE,KAAM,CAAE,OAAAC,CAAM,EAAKD,EACbE,EAAQF,EAAI,OAAS,MAAQ,MAC7BG,EAAU,MAAMC,EAAYH,EAAQ,WAAY,CAAE,YAAaC,EAAO,EAC5E,GAAI,CACF,MAAMG,EAAM,MAAMC,EAAa,EACzBC,EAAO,CAAE,OAAAN,EAAQ,MAAAC,EAAO,cAAeF,EAAI,aAAa,EACxDQ,EAAS,CAAC,GAAGC,EAAa,SAAS,CAAC,EAAE,KAAK,CAACC,EAAGC,IAAMA,EAAE,OAASD,EAAE,MAAM,EAExEE,EAAS,MAAOC,GAAM,CAC1B,MAAMC,EAAQ,MAAMC,EAAcV,EAAKG,EAAO,MAAM,EAAGK,CAAC,CAAC,EAEnDG,EAAS,MAAMC,EAAYV,EAAMJ,EAASW,EAAO,CAAE,QAASlB,EAAS,EACrEsB,EAAO,MAAMC,EAAeZ,EAAMJ,EAASW,EAAO,CAAE,QAASlB,EAAS,EAEtEwB,EAAS,IAAI,IACnB,UAAWC,KAAKH,EAAK,KAAM,CACzB,MAAMI,EAAIzB,EAAOwB,EAAE,KAAK,EAClBE,EAAIH,EAAO,IAAIE,CAAC,GAAK,CAAE,KAAMA,EAAG,MAAO,EAAG,IAAK,CAAC,EACtDC,EAAE,MAAQ,QAAQA,EAAE,MAAQF,EAAE,OAAO,QAAQ,CAAC,CAAC,EAC/CE,EAAE,IAAM,QAAQA,EAAE,IAAMF,EAAE,KAAK,QAAQ,CAAC,CAAC,EACzCD,EAAO,IAAIE,EAAGC,CAAC,CACjB,CACA,MAAO,CACL,EAAGT,EAAM,EAAG,EAAGI,EAAK,EACpB,YAAaF,EAAO,MACpB,aAAcE,EAAK,SACnB,aAAcA,EAAK,aACnB,OAAQ,CAAC,GAAGE,EAAO,OAAM,CAAE,EAAE,KAAK,CAACV,EAAGC,IAAMA,EAAE,IAAMD,EAAE,GAAG,EACzD,SAAUQ,EAAK,KAAK,MAAM,EAAG,EAAE,EAAE,IAAKG,IAAO,CAAE,KAAMA,EAAE,MAAO,MAAOA,EAAE,MAAO,IAAKA,EAAE,GAAG,EAAG,CACnG,CACI,EAEMG,EAAM,MAAMZ,EAAO,EAAE,EACrBa,EAAM,MAAMb,EAAO,EAAE,EACrBc,EAAYF,EAAI,aAAe,IAAMC,EAAI,aAAe,GAC9D,MAAO,CACL,KAAM,CAACC,EACP,OAAQ,CACN,MAAAxB,EACA,KAAM,2FACN,GAAIwB,EAAY,CAAE,QAAS,8CAA8C,EAAK,CAAA,EAC9E,IAAAF,EAAK,IAAAC,CACb,CACA,CACE,QAAC,CACCtB,EAAQ,OAAO,QAAO,CACxB,CACF,CAAC"}
assets/enc_v3_sweep-C1_eeFjm.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as v}from"./debug-Cn7EHWtJ.js";import{l as y}from"./weights-B-okS09o.js";import{l as F,t as N}from"./tokenizer-Ex1u7wXD.js";import{r as O}from"./encoder-DX8MOfcH.js";import{p as _}from"./bench-C8ITpm5I.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./constants-C8VbFpic.js";import"./f16-wKKZr58e.js";import"./pipelines-DD24nEJg.js";import"./generate-C4ruG1zm.js";import"./decoder-DI6VDxxO.js";import"./chapter3k-Bxq8ds-a.js";const b=7,a=[{name:"base",overrides:{tm8:!0}},{name:"sh16",overrides:{tm8:!0,sh16:!0}},{name:"dbuf",overrides:{tm8:!0,dbuf:!0}},{name:"sh16dbuf",overrides:{tm8:!0,sh16:!0,dbuf:!0}},{name:"sh16_bk32",overrides:{tm8:!0,sh16:!0,bkk:32}},{name:"sh16dbuf_bk32",overrides:{tm8:!0,sh16:!0,dbuf:!0,bkk:32}}],d=n=>{const t=[...n].sort((i,m)=>i-m),r=t.length>>1;return t.length%2?t[r]:(t[r-1]+t[r])/2};v("enc_v3_sweep",async n=>{const{device:t}=n;if(!n.hasF16)return{skip:!0,reason:"no shader-f16 (sh16 arms pointless)"};const r=await y(t,"/weights",{targetDtype:"f16"});try{const i=await F(),m={device:t,dtype:"f16"},l=[..._("file23k")].sort((u,c)=>c.length-u.length),p=async u=>{const c=await N(i,l.slice(0,u)),f=async e=>{const s=performance.now(),g=await O(m,r,c,{gemmOverrides:e});return await t.queue.onSubmittedWorkDone(),g.arena.destroy(),performance.now()-s};for(const e of a)await f(e.overrides);const o=Object.fromEntries(a.map(e=>[e.name,[]]));for(let e=0;e<b;e++)for(const s of a)o[s.name].push(await f(s.overrides));const h=d(o.base);return a.map(e=>({config:e.name,medianMs:Number(d(o[e.name]).toFixed(1)),vsBasePct:Number((100*(d(o[e.name])-h)/h).toFixed(1)),runs:o[e.name].map(s=>Number(s.toFixed(1)))}))},w=await p(64),k=await p(128);return{pass:!0,detail:{rounds:b,b64:w,b128:k}}}finally{r.buffer.destroy()}});
2
+ //# sourceMappingURL=enc_v3_sweep-C1_eeFjm.js.map
assets/enc_v3_sweep-C1_eeFjm.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"enc_v3_sweep-C1_eeFjm.js","sources":["../../src/debug/tests/enc_v3_sweep.js"],"sourcesContent":["// Encoder GEMM v3 staging sweep (gemm_tiled2 SH16/DBUF): f16 shared tiles\n// and double-buffered staging against the production tm8 baseline. Same\n// methodology as tiled_sweep: configs ROUND-ROBIN in one session (sequential\n// runs drift ±30% with laptop thermals), wall clock = runEncoder submit →\n// onSubmittedWorkDone, medians over ROUNDS. Both b64 and b128 (the e2e batch)\n// are swept — the winner must hold at both.\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { presetChunks } from '../../bench/bench.js';\n\nconst ROUNDS = 7;\nconst CONFIGS = [\n { name: 'base', overrides: { tm8: true } },\n { name: 'sh16', overrides: { tm8: true, sh16: true } },\n { name: 'dbuf', overrides: { tm8: true, dbuf: true } },\n { name: 'sh16dbuf', overrides: { tm8: true, sh16: true, dbuf: true } },\n { name: 'sh16_bk32', overrides: { tm8: true, sh16: true, bkk: 32 } },\n { name: 'sh16dbuf_bk32', overrides: { tm8: true, sh16: true, dbuf: true, bkk: 32 } },\n];\n\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nregisterTest('enc_v3_sweep', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16 (sh16 arms pointless)' };\n const weights = await loadWeights(device, '/weights', { targetDtype: 'f16' });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype: 'f16' };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n\n const sweepBatch = async (n) => {\n const batch = await tokenizeBatch(tok, chunks.slice(0, n));\n const timeOne = async (overrides) => {\n const t0 = performance.now();\n const run = await runEncoder(gctx, weights, batch, { gemmOverrides: overrides });\n await device.queue.onSubmittedWorkDone();\n run.arena.destroy();\n return performance.now() - t0;\n };\n // Warmup compiles every config's pipelines outside the timed rounds.\n for (const c of CONFIGS) await timeOne(c.overrides);\n const times = Object.fromEntries(CONFIGS.map((c) => [c.name, []]));\n for (let r = 0; r < ROUNDS; r++) {\n for (const c of CONFIGS) times[c.name].push(await timeOne(c.overrides));\n }\n const baseMed = median(times.base);\n return CONFIGS.map((c) => ({\n config: c.name,\n medianMs: Number(median(times[c.name]).toFixed(1)),\n vsBasePct: Number((100 * (median(times[c.name]) - baseMed) / baseMed).toFixed(1)),\n runs: times[c.name].map((x) => Number(x.toFixed(1))),\n }));\n };\n\n const b64 = await sweepBatch(64);\n const b128 = await sweepBatch(128);\n return { pass: true, detail: { rounds: ROUNDS, b64, b128 } };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["ROUNDS","CONFIGS","median","xs","s","a","b","m","registerTest","ctx","device","weights","loadWeights","tok","loadTokenizer","gctx","chunks","presetChunks","sweepBatch","n","batch","tokenizeBatch","timeOne","overrides","t0","run","runEncoder","c","times","r","baseMed","x","b64","b128"],"mappings":"6fAYA,MAAMA,EAAS,EACTC,EAAU,CACd,CAAE,KAAM,OAAQ,UAAW,CAAE,IAAK,EAAI,CAAE,EACxC,CAAE,KAAM,OAAQ,UAAW,CAAE,IAAK,GAAM,KAAM,GAAM,EACpD,CAAE,KAAM,OAAQ,UAAW,CAAE,IAAK,GAAM,KAAM,GAAM,EACpD,CAAE,KAAM,WAAY,UAAW,CAAE,IAAK,GAAM,KAAM,GAAM,KAAM,GAAM,EACpE,CAAE,KAAM,YAAa,UAAW,CAAE,IAAK,GAAM,KAAM,GAAM,IAAK,GAAI,EAClE,CAAE,KAAM,gBAAiB,UAAW,CAAE,IAAK,GAAM,KAAM,GAAM,KAAM,GAAM,IAAK,EAAE,CAAE,CACpF,EAEMC,EAAUC,GAAO,CACrB,MAAMC,EAAI,CAAC,GAAGD,CAAE,EAAE,KAAK,CAACE,EAAGC,IAAMD,EAAIC,CAAC,EAChCC,EAAIH,EAAE,QAAU,EACtB,OAAOA,EAAE,OAAS,EAAIA,EAAEG,CAAC,GAAKH,EAAEG,EAAI,CAAC,EAAIH,EAAEG,CAAC,GAAK,CACnD,EAEAC,EAAa,eAAgB,MAAOC,GAAQ,CAC1C,KAAM,CAAE,OAAAC,CAAM,EAAKD,EACnB,GAAI,CAACA,EAAI,OAAQ,MAAO,CAAE,KAAM,GAAM,OAAQ,qCAAqC,EACnF,MAAME,EAAU,MAAMC,EAAYF,EAAQ,WAAY,CAAE,YAAa,MAAO,EAC5E,GAAI,CACF,MAAMG,EAAM,MAAMC,EAAa,EACzBC,EAAO,CAAE,OAAAL,EAAQ,MAAO,KAAK,EAC7BM,EAAS,CAAC,GAAGC,EAAa,SAAS,CAAC,EAAE,KAAK,CAACZ,EAAGC,IAAMA,EAAE,OAASD,EAAE,MAAM,EAExEa,EAAa,MAAOC,GAAM,CAC9B,MAAMC,EAAQ,MAAMC,EAAcR,EAAKG,EAAO,MAAM,EAAGG,CAAC,CAAC,EACnDG,EAAU,MAAOC,GAAc,CACnC,MAAMC,EAAK,YAAY,IAAG,EACpBC,EAAM,MAAMC,EAAWX,EAAMJ,EAASS,EAAO,CAAE,cAAeG,EAAW,EAC/E,aAAMb,EAAO,MAAM,oBAAmB,EACtCe,EAAI,MAAM,QAAO,EACV,YAAY,IAAG,EAAKD,CAC7B,EAEA,UAAWG,KAAK1B,EAAS,MAAMqB,EAAQK,EAAE,SAAS,EAClD,MAAMC,EAAQ,OAAO,YAAY3B,EAAQ,IAAK0B,GAAM,CAACA,EAAE,KAAM,CAAA,CAAE,CAAC,CAAC,EACjE,QAASE,EAAI,EAAGA,EAAI7B,EAAQ6B,IAC1B,UAAWF,KAAK1B,EAAS2B,EAAMD,EAAE,IAAI,EAAE,KAAK,MAAML,EAAQK,EAAE,SAAS,CAAC,EAExE,MAAMG,EAAU5B,EAAO0B,EAAM,IAAI,EACjC,OAAO3B,EAAQ,IAAK0B,IAAO,CACzB,OAAQA,EAAE,KACV,SAAU,OAAOzB,EAAO0B,EAAMD,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,EACjD,UAAW,QAAQ,KAAOzB,EAAO0B,EAAMD,EAAE,IAAI,CAAC,EAAIG,GAAWA,GAAS,QAAQ,CAAC,CAAC,EAChF,KAAMF,EAAMD,EAAE,IAAI,EAAE,IAAKI,GAAM,OAAOA,EAAE,QAAQ,CAAC,CAAC,CAAC,CAC3D,EAAQ,CACJ,EAEMC,EAAM,MAAMd,EAAW,EAAE,EACzBe,EAAO,MAAMf,EAAW,GAAG,EACjC,MAAO,CAAE,KAAM,GAAM,OAAQ,CAAE,OAAQlB,EAAQ,IAAAgC,EAAK,KAAAC,EAAM,CAC5D,QAAC,CACCtB,EAAQ,OAAO,QAAO,CACxB,CACF,CAAC"}
assets/engine-BTyy_WlH.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import{initDevice as J}from"./device-Z_ibNtmX.js";import{l as Q}from"./weights-B-okS09o.js";import{l as K}from"./tokenizer-Ex1u7wXD.js";import{t as X}from"./generate-C4ruG1zm.js";import{autotuneRouting as q,tunedOptions as V}from"./autotune-DBJGFXNj.js";import{a as Y,g as Z,f as tt}from"./constants-C8VbFpic.js";import{b as et,c as nt}from"./shapes-BCQ9D81L.js";const B=200,N=/[。。.!!??;;…]/,ot=/[”’』」)〉》"')\]]/,st=/[,、,]/;function it(t){const e=[];let o=0;for(let s=0;s<t.length;s++){if(!N.test(t[s]))continue;let n=s+1;for(;n<t.length&&(N.test(t[n])||ot.test(t[n]));)n++;const a=t.slice(o,n).trim();a&&e.push(a),o=n,s=n-1}const i=t.slice(o).trim();return i&&e.push(i),e}function C(t){if(t.length<=B)return[t];const e=t.length/2;let o=-1;for(let a=0;a<t.length-1;a++)st.test(t[a])&&(o<0||Math.abs(a-e)<Math.abs(o-e))&&(o=a);const i=o>=0?o+1:B,s=t.slice(0,i).trim(),n=t.slice(i).trim();return[...s?C(s):[],...n?C(n):[]]}function at(t){const e=[],o=[];for(const i of t.split(`
2
+ `)){let s=0;for(const n of it(i))for(const a of C(n))e.push(a),s++;o.push(s)}return{sentences:e,paras:o}}function ct(t,e,o=200){const i=[],s=[];let n=0;for(const a of e){let c="",l=0;for(let r=0;r<a;r++){const u=t[n+r];c&&c.length+u.length>o&&(i.push(c),l++,c=""),c+=u}c&&(i.push(c),l++),n+=a,s.push(l)}return{rows:i,rowParas:s}}function rt(t,e){const o=[];let i=0;for(const s of t)o.push(e.slice(i,i+s).join(" ").trim()),i+=s;return o.join(`
3
+ `)}const lt={㑯:"㑔",㑳:"㑇",㑶:"㐹",㓨:"刾",㗲:"𠵾",㘚:"㘎",㜄:"㚯",㜏:"㛣",㜢:"𡞱",㠏:"㟆",㠣:"𫵷",㥮:"㤘",㩜:"㨫",㩳:"㧐",㩵:"擜",㺏:"𤠋",䁪:"𥇢",䁻:"䀥",䃮:"鿎",䊷:"䌶",䋙:"䌺",䋚:"䌻",䋹:"䌿",䋻:"䌾",䍦:"䍠",䎱:"䎬",䓣:"𬜯",䙡:"䙌",䜀:"䜧",䝼:"䞍",䡵:"𫟦",䥇:"䦂",䥑:"鿏",䥕:"𬭯",䥱:"䥾",䦛:"䦶",䦟:"䦷",䧢:"𨸟",䮄:"𫠊",䯀:"䯅",䰾:"鲃",䱷:"䲣",䱽:"䲝",䲁:"鳚",䲘:"鳤",䴉:"鹮",丟:"丢",並:"并",乾:"干",亂:"乱",亙:"亘",亞:"亚",佇:"伫",佈:"布",佔:"占",併:"并",來:"来",侖:"仑",侶:"侣",侷:"局",俁:"俣",係:"系",俔:"伣",俠:"侠",俥:"伡",俬:"私",倀:"伥",倆:"俩",倈:"俫",倉:"仓",個:"个",們:"们",倖:"幸",倫:"伦",倲:"㑈",偉:"伟",偑:"㐽",側:"侧",偵:"侦",偽:"伪",傌:"㐷",傑:"杰",傖:"伧",傘:"伞",備:"备",傢:"家",傭:"佣",傯:"偬",傳:"传",傴:"伛",債:"债",傷:"伤",傾:"倾",僂:"偻",僅:"仅",僉:"佥",僑:"侨",僕:"仆",僞:"伪",僤:"𫢸",僥:"侥",僨:"偾",僱:"雇",價:"价",儀:"仪",儁:"俊",儂:"侬",億:"亿",儈:"侩",儉:"俭",儎:"傤",儐:"傧",儔:"俦",儕:"侪",儘:"尽",償:"偿",優:"优",儲:"储",儷:"俪",儸:"㑩",儺:"傩",儻:"傥",儼:"俨",兇:"凶",兌:"兑",兒:"儿",兗:"兖",內:"内",兩:"两",冊:"册",冑:"胄",冪:"幂",凈:"净",凍:"冻",凜:"凛",凱:"凯",別:"别",刪:"删",剄:"刭",則:"则",剋:"克",剎:"刹",剗:"刬",剛:"刚",剝:"剥",剮:"剐",剴:"剀",創:"创",剷:"铲",劃:"划",劄:"札",劇:"剧",劉:"刘",劊:"刽",劌:"刿",劍:"剑",劏:"㓥",劑:"剂",劚:"㔉",勁:"劲",動:"动",務:"务",勛:"勋",勝:"胜",勞:"劳",勢:"势",勣:"𪟝",勩:"勚",勱:"劢",勳:"勋",勵:"励",勸:"劝",勻:"匀",匭:"匦",匯:"汇",匱:"匮",區:"区",協:"协",卹:"恤",卻:"却",卽:"即",厙:"厍",厠:"厕",厤:"历",厭:"厌",厲:"厉",厴:"厣",參:"参",叄:"叁",叢:"丛",吒:"咤",吳:"吴",吶:"呐",呂:"吕",咼:"呙",員:"员",唄:"呗",唸:"念",問:"问",啓:"启",啞:"哑",啟:"启",啢:"唡",喎:"㖞",喚:"唤",喪:"丧",喫:"吃",喬:"乔",單:"单",喲:"哟",嗆:"呛",嗇:"啬",嗊:"唝",嗎:"吗",嗚:"呜",嗩:"唢",嗰:"𠮶",嗶:"哔",嘆:"叹",嘍:"喽",嘓:"啯",嘔:"呕",嘖:"啧",嘗:"尝",嘜:"唛",嘩:"哗",嘮:"唠",嘯:"啸",嘰:"叽",嘵:"哓",嘸:"呒",嘽:"啴",噁:"恶",噓:"嘘",噚:"㖊",噝:"咝",噠:"哒",噥:"哝",噦:"哕",噯:"嗳",噲:"哙",噴:"喷",噸:"吨",噹:"当",嚀:"咛",嚇:"吓",嚌:"哜",嚐:"尝",嚕:"噜",嚙:"啮",嚥:"咽",嚦:"呖",嚧:"𠰷",嚨:"咙",嚮:"向",嚲:"亸",嚳:"喾",嚴:"严",嚶:"嘤",囀:"啭",囁:"嗫",囂:"嚣",囅:"冁",囈:"呓",囉:"啰",囌:"苏",囑:"嘱",囪:"囱",圇:"囵",國:"国",圍:"围",園:"园",圓:"圆",圖:"图",團:"团",垻:"坝",埡:"垭",埨:"𫭢",埰:"采",執:"执",堅:"坚",堊:"垩",堖:"垴",堝:"埚",堯:"尧",報:"报",場:"场",塊:"块",塋:"茔",塏:"垲",塒:"埘",塗:"涂",塚:"冢",塢:"坞",塤:"埙",塵:"尘",塸:"𫭟",塹:"堑",塿:"𪣻",墊:"垫",墜:"坠",墠:"𫮃",墮:"堕",墰:"坛",墳:"坟",墶:"垯",墻:"墙",墾:"垦",壇:"坛",壋:"垱",壎:"埙",壓:"压",壗:"𡋤",壘:"垒",壙:"圹",壚:"垆",壜:"坛",壞:"坏",壟:"垄",壠:"垅",壢:"坜",壩:"坝",壪:"塆",壯:"壮",壺:"壶",壼:"壸",壽:"寿",夠:"够",夢:"梦",夥:"伙",夾:"夹",奐:"奂",奧:"奥",奩:"奁",奪:"夺",奬:"奖",奮:"奋",奼:"姹",妝:"妆",姍:"姗",姦:"奸",娙:"𫰛",娛:"娱",婁:"娄",婦:"妇",婭:"娅",媧:"娲",媯:"妫",媰:"㛀",媼:"媪",媽:"妈",嫋:"袅",嫗:"妪",嫵:"妩",嫺:"娴",嫻:"娴",嫿:"婳",嬀:"妫",嬃:"媭",嬈:"娆",嬋:"婵",嬌:"��",嬙:"嫱",嬡:"嫒",嬤:"嬷",嬪:"嫔",嬰:"婴",嬸:"婶",孃:"娘",孋:"㛤",孌:"娈",孫:"孙",學:"学",孻:"𡥧",孿:"孪",宮:"宫",寀:"采",寢:"寝",實:"实",寧:"宁",審:"审",寫:"写",寬:"宽",寵:"宠",寶:"宝",將:"将",專:"专",尋:"寻",對:"对",導:"导",尷:"尴",屆:"届",屍:"尸",屓:"屃",屜:"屉",屢:"屡",層:"层",屨:"屦",屬:"属",岡:"冈",峯:"峰",峴:"岘",島:"岛",峽:"峡",崍:"崃",崑:"昆",崗:"岗",崙:"仑",崢:"峥",崬:"岽",嵐:"岚",嵗:"岁",嵽:"𫶇",嵾:"㟥",嶁:"嵝",嶄:"崭",嶇:"岖",嶔:"嵚",嶗:"崂",嶠:"峤",嶢:"峣",嶧:"峄",嶨:"峃",嶮:"崄",嶸:"嵘",嶺:"岭",嶼:"屿",嶽:"岳",巋:"岿",巒:"峦",巔:"巅",巖:"岩",巘:"𪩘",巰:"巯",巹:"卺",帥:"帅",師:"师",帳:"帐",帶:"带",幀:"帧",幃:"帏",幓:"㡎",幗:"帼",幘:"帻",幟:"帜",幣:"币",幫:"帮",幬:"帱",幷:"并",幹:"干",幾:"几",庫:"库",廁:"厕",廂:"厢",廄:"厩",廈:"厦",廎:"庼",廕:"荫",廚:"厨",廝:"厮",廞:"𫷷",廟:"庙",廠:"厂",廡:"庑",廢:"废",廣:"广",廩:"廪",廬:"庐",廳:"厅",弒:"弑",弔:"吊",弳:"弪",張:"张",強:"强",彄:"𫸩",彆:"别",彈:"弹",彌:"弥",彎:"弯",彔:"录",彙:"汇",彠:"彟",彥:"彦",彫:"雕",彲:"彨",彿:"佛",後:"后",徑:"径",從:"从",徠:"徕",復:"复",徵:"征",徹:"彻",恆:"恒",恥:"耻",悅:"悦",悞:"悮",悵:"怅",悶:"闷",悽:"凄",惡:"恶",惱:"恼",惲:"恽",惻:"恻",愛:"爱",愜:"惬",愨:"悫",愴:"怆",愷:"恺",愾:"忾",慄:"栗",態:"态",慍:"愠",慘:"惨",慚:"惭",慟:"恸",慣:"惯",慤:"悫",慪:"怄",慫:"怂",慮:"虑",慳:"悭",慶:"庆",慺:"㥪",慼:"戚",慾:"欲",憂:"忧",憊:"惫",憐:"怜",憑:"凭",憒:"愦",憖:"慭",憚:"惮",憤:"愤",憫:"悯",憮:"怃",憲:"宪",憶:"忆",懇:"恳",應:"应",懌:"怿",懍:"懔",懞:"蒙",懟:"怼",懣:"懑",懤:"㤽",懨:"恹",懲:"惩",懶:"懒",懷:"怀",懸:"悬",懺:"忏",懼:"惧",懾:"慑",戀:"恋",戇:"戆",戔:"戋",戧:"戗",戩:"戬",戰:"战",戱:"戯",戲:"戏",戶:"户",扞:"捍",拋:"抛",拚:"拼",挩:"捝",挱:"挲",挾:"挟",捨:"舍",捫:"扪",捱:"挨",捲:"卷",掃:"扫",掄:"抡",掆:"㧏",掗:"挜",掙:"挣",掛:"挂",採:"采",揀:"拣",揚:"扬",換:"换",揮:"挥",揯:"搄",損:"损",搖:"摇",搗:"捣",搧:"扇",搵:"揾",搶:"抢",摑:"掴",摜:"掼",摟:"搂",摯:"挚",摳:"抠",摶:"抟",摺:"折",摻:"掺",撈:"捞",撏:"挦",撐:"撑",撓:"挠",撝:"㧑",撟:"挢",撣:"掸",撥:"拨",撫:"抚",撲:"扑",撳:"揿",撻:"挞",撾:"挝",撿:"捡",擁:"拥",擄:"掳",擇:"择",擊:"击",擋:"挡",擓:"㧟",擔:"担",據:"据",擠:"挤",擡:"抬",擣:"捣",擬:"拟",擯:"摈",擰:"拧",擱:"搁",擲:"掷",擴:"扩",擷:"撷",擺:"摆",擻:"擞",擼:"撸",擽:"㧰",擾:"扰",攄:"摅",攆:"撵",攏:"拢",攔:"拦",攖:"撄",攙:"搀",攛:"撺",攜:"携",攝:"摄",攢:"攒",攣:"挛",攤:"摊",攪:"搅",攬:"揽",敎:"教",敓:"敚",敗:"败",敘:"叙",敵:"敌",數:"数",斂:"敛",斃:"毙",斆:"敩",斕:"斓",斬:"斩",斷:"断",於:"于",旂:"旗",旣:"既",昇:"升",時:"时",晉:"晋",晛:"𬀪",晝:"昼",暈:"晕",暉:"晖",暐:"𬀩",暘:"旸",暢:"畅",暫:"暂",曄:"晔",曆:"历",曇:"昙",曉:"晓",曏:"向",曖:"暧",曠:"旷",曥:"𣆐",曨:"昽",曬:"晒",書:"书",會:"会",朥:"𦛨",朧:"胧",朮:"术",東:"东",枴:"拐",柵:"栅",柺:"拐",査:"查",桱:"𣐕",桿:"杆",梔:"栀",梘:"枧",梜:"𬂩",條:"条",梟:"枭",梲:"棁",棄:"弃",棊:"棋",棖:"枨",棗:"枣",棟:"栋",棡:"㭎",棧:"栈",棲:"栖",棶:"梾",椏:"桠",椲:"㭏",楊:"杨",楓:"枫",楨:"桢",業:"业",極:"极",榘:"矩",榦:"干",榪:"杩",榮:"荣",榲:"榅",榿:"桤",構:"构",槍:"枪",槓:"杠",槤:"梿",槧:"椠",槨:"椁",槮:"椮",槳:"桨",槶:"椢",槼:"椝",樁:"桩",樂:"乐",樅:"枞",樑:"梁",樓:"楼",標:"标",樞:"枢",樢:"㭤",樣:"样",樧:"榝",樫:"㭴",樳:"桪",樸:"朴",樹:"树",樺:"桦",樿:"椫",橈:"桡",橋:"桥",機:"机",橢:"椭",橫:"横",橯:"𣓿",檁:"檩",檉:"柽",檔:"档",檜:"桧",檟:"槚",檢:"检",檣:"樯",檮:"梼",檯:"台",檳:"槟",檸:"柠",檻:"槛",櫃:"柜",櫍:"𬃊",櫓:"橹",櫚:"榈",櫛:"栉",櫝:"椟",櫞:"橼",櫟:"栎",櫥:"橱",櫧:"槠",櫨:"栌",櫪:"枥",櫫:"橥",櫬:"榇",櫱:"蘖",櫳:"栊",櫸:"榉",櫻:"樱",欄:"栏",欅:"榉",權:"权",欏:"椤",欒:"栾",欓:"𣗋",欖:"榄",欞:"棂",欽:"钦",歎:"叹",歐:"欧",歟:"欤",歡:"欢",歲:"岁",歷:"历",歸:"归",歿:"殁",殘:"残",殞:"殒",殤:"殇",殨:"㱮",殫:"殚",殭:"僵",殮:"殓",殯:"殡",殰:"㱩",殲:"歼",殺:"杀",殻:"壳",殼:"壳",毀:"毁",毆:"殴",毿:"毵",氂:"牦",氈:"毡",氌:"氇",氣:"气",氫:"氢",氬:"氩",氳:"氲",氾:"泛",汎:"泛",汙:"污",決:"决",沒:"没",沖:"冲",況:"况",泝:"溯",洩:"泄",洶:"汹",浹:"浃",浿:"𬇙",涇:"泾",涗:"涚",涼:"凉",淒:"凄",淚:"泪",淥:"渌",淨:"净",淩:"凌",淪:"沦",淵:"渊",淶:"涞",淺:"浅",渙:"涣",減:"减",渢:"沨",渦:"涡",測:"测",渾:"浑",湊:"凑",湋:"𣲗",湞:"浈",湧:"涌",湯:"汤",溈:"沩",準:"准",溝:"沟",溫:"温",溮:"浉",溳:"涢",溼:"湿",滄:"沧",滅:"灭",���:"涤",滎:"荥",滙:"汇",滬:"沪",滯:"滞",滲:"渗",滷:"卤",滸:"浒",滻:"浐",滾:"滚",滿:"满",漁:"渔",漊:"溇",漍:"𬇹",漚:"沤",漢:"汉",漣:"涟",漬:"渍",漲:"涨",漵:"溆",漸:"渐",漿:"浆",潁:"颍",潑:"泼",潔:"洁",潕:"𣲘",潙:"沩",潚:"㴋",潛:"潜",潤:"润",潯:"浔",潰:"溃",潷:"滗",潿:"涠",澀:"涩",澆:"浇",澇:"涝",澐:"沄",澗:"涧",澠:"渑",澤:"泽",澦:"滪",澩:"泶",澫:"𬇕",澮:"浍",澱:"淀",澾:"㳠",濁:"浊",濃:"浓",濄:"㳡",濆:"𣸣",濕:"湿",濘:"泞",濚:"溁",濛:"蒙",濜:"浕",濟:"济",濤:"涛",濧:"㳔",濫:"滥",濰:"潍",濱:"滨",濺:"溅",濼:"泺",濾:"滤",瀂:"澛",瀅:"滢",瀆:"渎",瀇:"㲿",瀉:"泻",瀋:"沈",瀏:"浏",瀕:"濒",瀘:"泸",瀝:"沥",瀟:"潇",瀠:"潆",瀦:"潴",瀧:"泷",瀨:"濑",瀰:"弥",瀲:"潋",瀾:"澜",灃:"沣",灄:"滠",灑:"洒",灒:"𪷽",灕:"漓",灘:"滩",灙:"𣺼",灝:"灏",灡:"㳕",灣:"湾",灤:"滦",灧:"滟",灩:"滟",災:"灾",為:"为",烏:"乌",烴:"烃",無:"无",煉:"炼",煒:"炜",煙:"烟",煢:"茕",煥:"焕",煩:"烦",煬:"炀",煱:"㶽",熅:"煴",熒:"荧",熗:"炝",熰:"𬉼",熱:"热",熲:"颎",熾:"炽",燀:"𬊤",燁:"烨",燈:"灯",燉:"炖",燒:"烧",燖:"𬊈",燙:"烫",燜:"焖",營:"营",燦:"灿",燬:"毁",燭:"烛",燴:"烩",燶:"㶶",燻:"熏",燼:"烬",燾:"焘",爍:"烁",爐:"炉",爛:"烂",爭:"争",爲:"为",爺:"爷",爾:"尔",牀:"床",牆:"墙",牘:"牍",牴:"抵",牽:"牵",犖:"荦",犛:"牦",犢:"犊",犧:"牺",狀:"状",狹:"狭",狽:"狈",猙:"狰",猶:"犹",猻:"狲",獁:"犸",獃:"呆",獄:"狱",獅:"狮",獎:"奖",獨:"独",獪:"狯",獫:"猃",獮:"狝",獰:"狞",獱:"㺍",獲:"获",獵:"猎",獷:"犷",獸:"兽",獺:"獭",獻:"献",獼:"猕",玀:"猡",現:"现",琱:"雕",琺:"珐",琿:"珲",瑋:"玮",瑒:"玚",瑣:"琐",瑤:"瑶",瑩:"莹",瑪:"玛",瑲:"玱",璉:"琏",璊:"𫞩",璕:"𬍤",璗:"𬍡",璡:"琎",璣:"玑",璦:"瑷",璫:"珰",璯:"㻅",環:"环",璵:"玙",璸:"瑸",璽:"玺",璿:"璇",瓅:"𬍛",瓊:"琼",瓏:"珑",瓔:"璎",瓚:"瓒",瓛:"𤩽",甌:"瓯",甕:"瓮",產:"产",産:"产",畝:"亩",畢:"毕",畫:"画",異:"异",畵:"画",當:"当",疇:"畴",疊:"叠",痙:"痉",痠:"酸",痾:"疴",瘂:"痖",瘋:"疯",瘍:"疡",瘓:"痪",瘞:"瘗",瘡:"疮",瘧:"疟",瘮:"瘆",瘲:"疭",瘺:"瘘",瘻:"瘘",療:"疗",癆:"痨",癇:"痫",癉:"瘅",癒:"愈",癘:"疠",癟:"瘪",癡:"痴",癢:"痒",癤:"疖",癥:"症",癧:"疬",癩:"癞",癬:"癣",癭:"瘿",癮:"瘾",癰:"痈",癱:"瘫",癲:"癫",發:"发",皁:"皂",皚:"皑",皰:"疱",皸:"皲",皺:"皱",盃:"杯",盜:"盗",盞:"盏",盡:"尽",監:"监",盤:"盘",盧:"卢",盪:"荡",眞:"真",眥:"眦",眾:"众",睍:"𪾢",睏:"困",睜:"睁",睞:"睐",瞘:"眍",瞜:"䁖",瞞:"瞒",瞶:"瞆",瞼:"睑",矇:"蒙",矓:"眬",矚:"瞩",矯:"矫",硃:"朱",硜:"硁",硤:"硖",硨:"砗",硯:"砚",碕:"埼",碩:"硕",碭:"砀",碸:"砜",確:"确",碼:"码",碽:"䂵",磑:"硙",磚:"砖",磠:"硵",磣:"碜",磧:"碛",磯:"矶",磽:"硗",磾:"䃅",礄:"硚",礎:"础",礐:"𬒈",礙:"碍",礦:"矿",礪:"砺",礫:"砾",礬:"矾",礱:"砻",祕:"秘",祿:"禄",禍:"祸",禎:"祯",禕:"祎",禡:"祃",禦:"御",禪:"禅",禮:"礼",禰:"祢",禱:"祷",禿:"秃",秈:"籼",稅:"税",稈:"秆",稏:"䅉",稜:"棱",稟:"禀",種:"种",稱:"称",穀:"谷",穇:"䅟",穌:"稣",積:"积",穎:"颖",穠:"秾",穡:"穑",穢:"秽",穩:"稳",穫:"获",穭:"穞",窩:"窝",窪:"洼",窮:"穷",窯:"窑",窵:"窎",窶:"窭",窺:"窥",竄:"窜",竅:"窍",竇:"窦",竈:"灶",竊:"窃",竪:"竖",競:"竞",筆:"笔",筍:"笋",筧:"笕",筴:"䇲",箇:"个",箋:"笺",箏:"筝",箚:"札",節:"节",範:"范",築:"筑",篋:"箧",篔:"筼",篠:"筿",篢:"𬕂",篤:"笃",篩:"筛",篳:"筚",篸:"𥮾",簀:"箦",簍:"篓",簑:"蓑",簞:"箪",簡:"简",簣:"篑",簫:"箫",簹:"筜",簽:"签",簾:"帘",籃:"篮",籅:"𥫣",籌:"筹",籔:"䉤",籙:"箓",籛:"篯",籜:"箨",籟:"籁",籠:"笼",籤:"签",籩:"笾",籪:"簖",籬:"篱",籮:"箩",籲:"吁",粵:"粤",糉:"粽",糝:"糁",糞:"粪",糧:"粮",糰:"团",糲:"粝",糴:"籴",糶:"粜",糹:"纟",糾:"纠",紀:"纪",紂:"纣",紃:"𬘓",約:"约",紅:"红",紆:"纡",紇:"纥",紈:"纨",紉:"纫",紋:"纹",納:"纳",紐:"纽",紓:"纾",純:"纯",紕:"纰",紖:"纼",紗:"纱",紘:"纮",紙:"纸",級:"级",紛:"纷",紜:"纭",紝:"纴",紞:"𬘘",紡:"纺",紬:"䌷",紮:"扎",細:"细",紱:"绂",紲:"绁",紳:"绅",紵:"纻",紹:"绍",紺:"绀",紼:"绋",紿:"绐",絀:"绌",終:"终",絃:"弦",組:"组",絅:"䌹",絆:"绊",絎:"绗",結:"结",絕:"绝",絛:"绦",絝:"绔",絞:"绞",絡:"络",絢:"绚",給:"给",絨:"绒",絪:"𬘡",絰:"绖",統:"统",絲:"丝",絳:"绛",絶:"绝",絹:"绢",絺:"𫄨",綁:"绑",綃:"绡",綄:"𬘫",綆:"绠",綈:"绨",綉:"绣",綌:"绤",綎:"𬘩",綏:"绥",綐:"䌼",綑:"捆",經:"经",綖:"𫄧",綜:"综",綝:"𬘭",綞:"缍",綠:"绿",綡:"𫟅",綢:"绸",綣:"绻",綧:"𬘯",綪:"𬘬",綫:"线",綬:"绶",維:"维",綯:"绹",綰:"绾",綱:"纲",網:"网",綳:"绷",綴:"缀",綵:"彩",綸:"纶",綹:"绺",綺:"绮",綻:"绽",綽:"绰",綾:"绫",綿:"绵",緄:"绲",���:"缁",緊:"紧",緋:"绯",緑:"绿",緒:"绪",緓:"绬",緔:"绱",緗:"缃",緘:"缄",緙:"缂",線:"线",緝:"缉",緞:"缎",締:"缔",緡:"缗",緣:"缘",緦:"缌",編:"编",緩:"缓",緬:"缅",緯:"纬",緱:"缑",緲:"缈",練:"练",緶:"缏",緹:"缇",緻:"致",緼:"缊",縈:"萦",縉:"缙",縊:"缢",縋:"缒",縐:"绉",縑:"缣",縕:"缊",縗:"缞",縛:"缚",縝:"缜",縞:"缟",縟:"缛",縣:"县",縧:"绦",縫:"缝",縭:"缡",縮:"缩",縯:"𬙂",縱:"纵",縲:"缧",縳:"䌸",縴:"纤",縵:"缦",縶:"絷",縷:"缕",縹:"缥",總:"总",績:"绩",繃:"绷",繅:"缫",繆:"缪",繒:"缯",織:"织",繕:"缮",繚:"缭",繞:"绕",繡:"绣",繢:"缋",繩:"绳",繪:"绘",繫:"系",繭:"茧",繮:"缰",繯:"缳",繰:"缲",繳:"缴",繶:"𫄷",繸:"䍁",繹:"绎",繻:"𦈡",繼:"继",繽:"缤",繾:"缱",繿:"䍀",纁:"𫄸",纆:"𬙊",纇:"颣",纈:"缬",纊:"纩",續:"续",纍:"累",纏:"缠",纓:"缨",纔:"才",纕:"𬙋",纖:"纤",纘:"缵",纜:"缆",缽:"钵",罃:"䓨",罈:"坛",罌:"罂",罎:"坛",罰:"罚",罵:"骂",罷:"罢",羅:"罗",羆:"罴",羈:"羁",羋:"芈",羣:"群",羥:"羟",羨:"羡",義:"义",羶:"膻",習:"习",翫:"玩",翬:"翚",翹:"翘",翽:"翙",耬:"耧",耮:"耢",聖:"圣",聞:"闻",聯:"联",聰:"聪",聲:"声",聳:"耸",聵:"聩",聶:"聂",職:"职",聹:"聍",聽:"听",聾:"聋",肅:"肃",脅:"胁",脈:"脉",脛:"胫",脣:"唇",脩:"修",脫:"脱",脹:"胀",腎:"肾",腖:"胨",腡:"脶",腦:"脑",腫:"肿",腳:"脚",腸:"肠",膃:"腽",膕:"腘",膚:"肤",膞:"䏝",膠:"胶",膢:"𦝼",膩:"腻",膽:"胆",膾:"脍",膿:"脓",臉:"脸",臍:"脐",臏:"膑",臘:"腊",臚:"胪",臟:"脏",臠:"脔",臢:"臜",臥:"卧",臨:"临",臺:"台",與:"与",興:"兴",舉:"举",舊:"旧",舖:"铺",舘:"馆",艙:"舱",艤:"舣",艦:"舰",艫:"舻",艱:"艰",艷:"艳",芻:"刍",苧:"苎",茲:"兹",荊:"荆",莊:"庄",莖:"茎",莢:"荚",莧:"苋",華:"华",菴:"庵",菸:"烟",萇:"苌",萊:"莱",萬:"万",萴:"荝",萵:"莴",葉:"叶",葒:"荭",葤:"荮",葦:"苇",葯:"药",葷:"荤",蒍:"𫇭",蒐:"搜",蒓:"莼",蒔:"莳",蒕:"蒀",蒞:"莅",蒼:"苍",蓀:"荪",蓆:"席",蓋:"盖",蓮:"莲",蓯:"苁",蓴:"莼",蓽:"荜",蔄:"𬜬",蔔:"卜",蔘:"参",蔞:"蒌",蔣:"蒋",蔥:"葱",蔦:"茑",蔭:"荫",蔯:"𫈟",蔿:"𫇭",蕁:"荨",蕆:"蒇",蕎:"荞",蕒:"荬",蕓:"芸",蕕:"莸",蕘:"荛",蕢:"蒉",蕩:"荡",蕪:"芜",蕭:"萧",蕷:"蓣",薀:"蕰",薈:"荟",薊:"蓟",薌:"芗",薑:"姜",薔:"蔷",薘:"荙",薟:"莶",薦:"荐",薩:"萨",薳:"䓕",薴:"苧",薵:"䓓",薹:"苔",薺:"荠",藍:"蓝",藎:"荩",藝:"艺",藥:"药",藪:"薮",藭:"䓖",藴:"蕴",藶:"苈",藹:"蔼",藺:"蔺",蘀:"萚",蘄:"蕲",蘆:"芦",蘇:"苏",蘊:"蕴",蘋:"苹",蘚:"藓",蘞:"蔹",蘟:"𦻕",蘢:"茏",蘭:"兰",蘺:"蓠",蘿:"萝",虆:"蔂",虉:"𬟁",處:"处",虛:"虚",虜:"虏",號:"号",虧:"亏",虯:"虬",蛺:"蛱",蛻:"蜕",蜆:"蚬",蝀:"𬟽",蝕:"蚀",蝟:"猬",蝦:"虾",蝨:"虱",蝸:"蜗",螄:"蛳",螞:"蚂",螢:"萤",螮:"䗖",螻:"蝼",螿:"螀",蟄:"蛰",蟈:"蝈",蟎:"螨",蟣:"虮",蟬:"蝉",蟯:"蛲",蟲:"虫",蟳:"𫊻",蟶:"蛏",蟻:"蚁",蠁:"蚃",蠅:"蝇",蠆:"虿",蠍:"蝎",蠐:"蛴",蠑:"蝾",蠔:"蚝",蠟:"蜡",蠣:"蛎",蠨:"蟏",蠱:"蛊",蠶:"蚕",蠻:"蛮",衆:"众",衊:"蔑",術:"术",衕:"同",衚:"胡",衛:"卫",衝:"冲",袞:"衮",袷:"夹",裊:"袅",裏:"里",補:"补",裝:"装",裡:"里",製:"制",複:"复",褌:"裈",褘:"袆",褲:"裤",褳:"裢",褸:"褛",褻:"亵",襀:"𫌀",襇:"裥",襉:"裥",襏:"袯",襖:"袄",襝:"裣",襠:"裆",襤:"褴",襪:"袜",襬:"摆",襯:"衬",襲:"袭",襴:"襕",覈:"核",見:"见",覎:"觃",規:"规",覓:"觅",視:"视",覘:"觇",覡:"觋",覥:"觍",覦:"觎",親:"亲",覬:"觊",覯:"觏",覲:"觐",覷:"觑",覺:"觉",覽:"览",覿:"觌",觀:"观",觴:"觞",觶:"觯",觸:"触",訁:"讠",訂:"订",訃:"讣",計:"计",訊:"讯",訌:"讧",討:"讨",訏:"𬣙",訐:"讦",訒:"讱",訓:"训",訕:"讪",訖:"讫",託:"托",記:"记",訛:"讹",訝:"讶",訟:"讼",訢:"䜣",訣:"诀",訥:"讷",訩:"讻",訪:"访",設:"设",許:"许",訴:"诉",訶:"诃",診:"诊",註:"注",証:"证",詀:"𧮪",詁:"诂",詆:"诋",詎:"讵",詐:"诈",詒:"诒",詔:"诏",評:"评",詖:"诐",詗:"诇",詘:"诎",詛:"诅",詝:"𬣞",詞:"词",詠:"咏",詡:"诩",詢:"询",詣:"诣",試:"试",詩:"诗",詪:"𬣳",詫:"诧",詬:"诟",詭:"诡",詮:"诠",詰:"诘",話:"话",該:"该",詳:"详",詵:"诜",詷:"𫍣",詼:"诙",詿:"诖",誄:"诔",誅:"诛",誆:"诓",誇:"夸",誌:"志",認:"认",誑:"诳",誒:"诶",誕:"诞",誘:"诱",誚:"诮",語:"语",誠:"诚",誡:"诫",誣:"诬",誤:"误",誥:"诰",誦:"诵",誨:"诲",說:"说",説:"说",誰:"谁",課:"课",誶:"谇",誹:"诽",誼:"谊",誾:"訚",調:"调",諂:"谄",諄:"谆",談:"谈",諉:"诿",請:"请",諍:"诤",諏:"诹",諑:"诼",諒:"谅",諓:"𬣡",論:"论",諗:"谂",諛:"谀",諜:"谍",諝:"谞",諞:"谝",諟:"𬤊",諡:"谥",諢:"诨",諤:"谔",諦:"谛",諧:"谐",諫:"谏",諭:"谕",諮:"咨",諱:"讳",諲:"𬤇",諳:"谙",諴:"𫍯",諶:"谌",諷:"讽",諸:"诸",諺:"谚",諼:"谖",諾:"诺",謀:"谋",謁:"谒",謂:"谓",謄:"誊",謅:"���",謊:"谎",謎:"谜",謏:"𫍲",謐:"谧",謔:"谑",謖:"谡",謗:"谤",謙:"谦",謚:"谥",講:"讲",謝:"谢",謠:"谣",謡:"谣",謨:"谟",謫:"谪",謬:"谬",謭:"谫",謳:"讴",謹:"谨",謾:"谩",譁:"哗",證:"证",譎:"谲",譏:"讥",譓:"𬤝",譖:"谮",識:"识",譙:"谯",譚:"谭",譜:"谱",譞:"𫍽",譟:"噪",譫:"谵",譭:"毁",譯:"译",議:"议",譴:"谴",護:"护",譸:"诪",譽:"誉",譾:"谫",讀:"读",讅:"谉",變:"变",讋:"詟",讌:"䜩",讎:"雠",讒:"谗",讓:"让",讕:"谰",讖:"谶",讚:"赞",讜:"谠",讞:"谳",谿:"溪",豈:"岂",豎:"竖",豐:"丰",豔:"艳",豬:"猪",豶:"豮",貍:"狸",貓:"猫",貙:"䝙",貝:"贝",貞:"贞",貟:"贠",負:"负",財:"财",貢:"贡",貧:"贫",貨:"货",販:"贩",貪:"贪",貫:"贯",責:"责",貯:"贮",貰:"贳",貲:"赀",貳:"贰",貴:"贵",貶:"贬",買:"买",貸:"贷",貺:"贶",費:"费",貼:"贴",貽:"贻",貿:"贸",賀:"贺",賁:"贲",賂:"赂",賃:"赁",賄:"贿",賅:"赅",資:"资",賈:"贾",賊:"贼",賑:"赈",賒:"赊",賓:"宾",賕:"赇",賙:"赒",賚:"赉",賜:"赐",賞:"赏",賠:"赔",賡:"赓",賢:"贤",賣:"卖",賤:"贱",賦:"赋",賧:"赕",質:"质",賫:"赍",賬:"账",賭:"赌",賰:"䞐",賴:"赖",賵:"赗",賺:"赚",賻:"赙",購:"购",賽:"赛",賾:"赜",贄:"贽",贅:"赘",贇:"赟",贈:"赠",贊:"赞",贋:"赝",贍:"赡",贏:"赢",贐:"赆",贓:"赃",贔:"赑",贖:"赎",贗:"赝",贛:"赣",贜:"赃",赬:"赪",趕:"赶",趙:"赵",趨:"趋",趲:"趱",跡:"迹",踐:"践",踰:"逾",踴:"踊",蹌:"跄",蹕:"跸",蹟:"迹",蹠:"跖",蹣:"蹒",蹤:"踪",蹺:"跷",躂:"跶",躉:"趸",躊:"踌",躋:"跻",躍:"跃",躎:"䟢",躑:"踯",躒:"跞",躓:"踬",躕:"蹰",躚:"跹",躡:"蹑",躥:"蹿",躦:"躜",躪:"躏",軀:"躯",車:"车",軋:"轧",軌:"轨",軍:"军",軏:"𫐄",軑:"轪",軒:"轩",軔:"轫",軛:"轭",軝:"𬨂",軟:"软",軤:"轷",軫:"轸",軲:"轱",軸:"轴",軹:"轵",軺:"轺",軻:"轲",軼:"轶",軾:"轼",較:"较",輄:"𨐈",輅:"辂",輇:"辁",輈:"辀",載:"载",輊:"轾",輋:"𪨶",輒:"辄",輓:"挽",輔:"辅",輕:"轻",輗:"𫐐",輛:"辆",輜:"辎",輝:"辉",輞:"辋",輟:"辍",輥:"辊",輦:"辇",輩:"辈",輪:"轮",輬:"辌",輮:"𫐓",輯:"辑",輳:"辏",輶:"𬨎",輸:"输",輻:"辐",輼:"辒",輾:"辗",輿:"舆",轀:"辒",轂:"毂",轄:"辖",轅:"辕",轆:"辘",轉:"转",轍:"辙",轎:"轿",轔:"辚",轟:"轰",轡:"辔",轢:"轹",轤:"轳",辦:"办",辭:"辞",辮:"辫",辯:"辩",農:"农",迴:"回",逕:"径",這:"这",連:"连",週:"周",進:"进",遊:"游",運:"运",過:"过",達:"达",違:"违",遙:"遥",遜:"逊",遞:"递",遠:"远",遡:"溯",適:"适",遲:"迟",遶:"绕",遷:"迁",選:"选",遺:"遗",遼:"辽",邁:"迈",還:"还",邇:"迩",邊:"边",邏:"逻",邐:"逦",郟:"郏",郵:"邮",鄆:"郓",鄉:"乡",鄒:"邹",鄔:"邬",鄖:"郧",鄧:"邓",鄩:"𬩽",鄭:"郑",鄰:"邻",鄲:"郸",鄳:"𫑡",鄴:"邺",鄶:"郐",鄺:"邝",酇:"酂",酈:"郦",醃:"腌",醖:"酝",醜:"丑",醞:"酝",醟:"蒏",醣:"糖",醫:"医",醬:"酱",醱:"酦",醲:"𬪩",釀:"酿",釁:"衅",釃:"酾",釅:"酽",釋:"释",釐:"厘",釒:"钅",釓:"钆",釔:"钇",釕:"钌",釗:"钊",釘:"钉",釙:"钋",針:"针",釣:"钓",釤:"钐",釦:"扣",釧:"钏",釩:"钒",釴:"𬬩",釵:"钗",釷:"钍",釹:"钕",釺:"钎",釾:"䥺",釿:"𬬱",鈀:"钯",鈁:"钫",鈃:"钘",鈄:"钭",鈅:"钥",鈇:"𫓧",鈈:"钚",鈉:"钠",鈍:"钝",鈎:"钩",鈐:"钤",鈑:"钣",鈒:"钑",鈔:"钞",鈕:"钮",鈞:"钧",鈡:"钟",鈣:"钙",鈥:"钬",鈦:"钛",鈧:"钪",鈮:"铌",鈰:"铈",鈳:"钶",鈴:"铃",鈷:"钴",鈸:"钹",鈹:"铍",鈺:"钰",鈽:"钸",鈾:"铀",鈿:"钿",鉀:"钾",鉅:"巨",鉆:"钻",鉈:"铊",鉉:"铉",鉊:"𬬿",鉋:"铇",鉍:"铋",鉑:"铂",鉕:"钷",鉗:"钳",鉚:"铆",鉛:"铅",鉝:"𫟷",鉞:"钺",鉢:"钵",鉤:"钩",鉥:"𬬸",鉦:"钲",鉧:"𬭁",鉬:"钼",鉭:"钽",鉮:"𬬹",鉳:"锫",鉶:"铏",鉷:"𫟹",鉸:"铰",鉺:"铒",鉻:"铬",鉿:"铪",銀:"银",銃:"铳",銅:"铜",銈:"𫓯",銍:"铚",銑:"铣",銓:"铨",銖:"铢",銘:"铭",銚:"铫",銛:"铦",銜:"衔",銠:"铑",銣:"铷",銥:"铱",銦:"铟",銨:"铵",銩:"铥",銪:"铕",銫:"铯",銬:"铐",銱:"铞",銳:"锐",銶:"𨱇",銷:"销",銹:"锈",銻:"锑",銼:"锉",鋁:"铝",鋃:"锒",鋅:"锌",鋇:"钡",鋌:"铤",鋏:"铗",鋐:"𬭎",鋒:"锋",鋗:"𫓶",鋙:"铻",鋝:"锊",鋟:"锓",鋣:"铘",鋤:"锄",鋥:"锃",鋦:"锔",鋨:"锇",鋩:"铓",鋪:"铺",鋭:"锐",鋮:"铖",鋯:"锆",鋰:"锂",鋱:"铽",鋶:"锍",鋸:"锯",鋹:"𬬮",鋼:"钢",錀:"𬬭",錁:"锞",錄:"录",錆:"锖",錇:"锫",錈:"锩",錏:"铔",錐:"锥",錒:"锕",錕:"锟",錘:"锤",錙:"锱",錚:"铮",錛:"锛",錞:"𬭚",錟:"锬",錠:"锭",錡:"锜",錢:"钱",錤:"𫓹",錦:"锦",錨:"锚",錩:"锠",錫:"锡",錮:"锢",錯:"错",録:"录",錳:"锰",錶:"表",錸:"铼",錼:"镎",鍀:"锝",鍁:"锨",鍃:"锪",鍅:"钫",鍆:"钔",鍇:"锴",鍈:"锳",鍊:"炼",鍋:"锅",鍍:"镀",鍔:"锷",鍘:"铡",鍚:"钖",鍛:"锻",鍠:"锽",鍤:"锸",鍥:"锲",鍩:"锘",鍬:"锹",鍭:"𬭤",鍰:"锾",鍵:"键",鍶:"锶",鍺:"锗",鍼:"针",鍾:"钟",鎂:"镁",鎄:"锿",鎇:"镅",鎊:"镑",鎌:"镰",鎓:"𬭩",鎔:"镕",鎖:"锁",鎘:"镉",鎚:"锤",鎛:"镈",鎝:"𨱏",鎡:"镃",鎢:"钨",鎣:"蓥",鎦:"镏",鎧:"铠",鎩:"铩",鎪:"锼",鎬:"镐",鎭:"镇",鎮:"镇",鎰:"镒",鎲:"镋",鎳:"镍",鎵:"镓",鎶:"鿔",鎸:"镌",鎿:"镎",鏃:"镞",鏇:"旋",鏈:"链",鏌:"镆",鏍:"镙",鏏:"𬭬",鏐:"镠",鏑:"镝",鏗:"铿",鏘:"锵",鏜:"镗",鏝:"镘",鏞:"镛",鏟:"铲",鏡:"镜",鏢:"镖",鏤:"镂",鏨:"錾",鏰:"镚",鏵:"铧",鏷:"镤",鏹:"镪",鏺:"䥽",鏻:"𬭸",鏽:"锈",鐃:"铙",鐄:"𨱑",鐇:"𫔍",鐋:"铴",鐍:"𫔎",鐏:"𨱔",鐐:"镣",鐒:"铹",鐓:"镦",鐔:"镡",鐘:"钟",鐙:"镫",鐝:"镢",鐠:"镨",鐥:"䦅",鐦:"锎",鐧:"锏",鐨:"镄",鐩:"𬭼",鐫:"镌",鐮:"镰",鐯:"䦃",鐲:"镯",鐳:"镭",鐵:"铁",鐶:"镮",鐸:"铎",鐺:"铛",鐽:"𫟼",鐿:"镱",鑄:"铸",鑊:"镬",鑌:"镔",鑑:"鉴",鑒:"鉴",鑔:"镲",鑕:"锧",鑞:"镴",鑠:"铄",鑣:"镳",鑥:"镥",鑪:"𬬻",鑭:"镧",鑰:"钥",鑱:"镵",鑲:"镶",鑷:"镊",鑹:"镩",鑼:"锣",鑽:"钻",鑾:"銮",鑿:"凿",钁:"镢",钂:"镋",長:"长",門:"门",閂:"闩",閃:"闪",閆:"闫",閈:"闬",閉:"闭",開:"开",閌:"闶",閎:"闳",閏:"闰",閑:"闲",閒:"闲",間:"间",閔:"闵",閘:"闸",閡:"阂",閣:"阁",閤:"合",閥:"阀",閨:"闺",閩:"闽",閫:"阃",閬:"阆",閭:"闾",閱:"阅",閲:"阅",閶:"阊",閹:"阉",閻:"阎",閼:"阏",閽:"阍",閾:"阈",閿:"阌",闃:"阒",闆:"板",闇:"暗",闈:"闱",闉:"𬮱",闊:"阔",闋:"阕",闌:"阑",闍:"阇",闐:"阗",闑:"𫔶",闒:"阘",闓:"闿",闔:"阖",闕:"阙",闖:"闯",關:"关",闞:"阚",闠:"阓",闡:"阐",闢:"辟",闤:"阛",闥:"闼",陘:"陉",陝:"陕",陞:"升",陣:"阵",陰:"阴",陳:"陈",陸:"陆",陽:"阳",隉:"陧",隊:"队",階:"阶",隑:"𬮿",隕:"陨",際:"际",隤:"𬯎",隨:"随",險:"险",隮:"𬯀",隯:"陦",隱:"隐",隴:"陇",隸:"隶",隻:"只",雋:"隽",雖:"虽",雙:"双",雛:"雏",雜:"杂",雞:"鸡",離:"离",難:"难",雲:"云",電:"电",霑:"沾",霢:"霡",霧:"雾",霽:"霁",靂:"雳",靄:"霭",靆:"叇",靈:"灵",靉:"叆",靚:"靓",靜:"静",靝:"靔",靦:"腼",靨:"靥",鞏:"巩",鞝:"绱",鞦:"秋",鞽:"鞒",韁:"缰",韃:"鞑",韆:"千",韉:"鞯",韋:"韦",韌:"韧",韍:"韨",韓:"韩",韙:"韪",韜:"韬",韝:"鞲",韞:"韫",韻:"韵",響:"响",頁:"页",頂:"顶",頃:"顷",項:"项",順:"顺",頇:"顸",須:"须",頊:"顼",頌:"颂",頍:"𫠆",頎:"颀",頏:"颃",預:"预",頑:"顽",頒:"颁",頓:"顿",頔:"𬱖",頗:"颇",領:"领",頜:"颌",頠:"𬱟",頡:"颉",頤:"颐",頦:"颏",頫:"𫖯",頭:"头",頮:"颒",頰:"颊",頲:"颋",頴:"颕",頵:"𫖳",頷:"颔",頸:"颈",頹:"颓",頻:"频",頽:"颓",顆:"颗",題:"题",額:"额",顎:"颚",顏:"颜",顒:"颙",顓:"颛",顔:"颜",顗:"𫖮",願:"愿",顙:"颡",顛:"颠",類:"类",顢:"颟",顥:"颢",顧:"顾",顫:"颤",顬:"颥",顯:"显",顰:"颦",顱:"颅",顳:"颞",顴:"颧",風:"风",颭:"飐",颮:"飑",颯:"飒",颱:"台",颳:"刮",颶:"飓",颸:"飔",颺:"飏",颻:"飖",颼:"飕",飀:"飗",飄:"飘",飆:"飙",飈:"飚",飛:"飞",飠:"饣",飢:"饥",飣:"饤",飥:"饦",飩:"饨",飪:"饪",飫:"饫",飭:"饬",飯:"饭",飱:"飧",飲:"饮",飴:"饴",飼:"饲",飽:"饱",飾:"饰",飿:"饳",餃:"饺",餄:"饸",餅:"饼",餈:"糍",餉:"饷",養:"养",餌:"饵",餎:"饹",餏:"饻",餑:"饽",餒:"馁",餓:"饿",餕:"馂",餖:"饾",餗:"𫗧",餘:"余",餚:"肴",餛:"馄",餜:"馃",餞:"饯",餡:"馅",館:"馆",餬:"糊",餱:"糇",餳:"饧",餵:"喂",餶:"馉",餷:"馇",餸:"𩠌",餺:"馎",餼:"饩",餾:"馏",餿:"馊",饁:"馌",饃:"馍",饅:"馒",饈:"馐",饉:"馑",饊:"馓",饋:"馈",饌:"馔",饑:"饥",饒:"饶",饗:"飨",饘:"𫗴",饜:"餍",饞:"馋",饢:"馕",馬:"马",馭:"驭",馮:"冯",馱:"驮",馳:"驰",馴:"驯",馹:"驲",馼:"𫘜",駁:"驳",駃:"𫘝",駉:"𬳶",駐:"驻",駑:"驽",駒:"驹",駓:"𬳵",駔:"驵",駕:"驾",駘:"骀",駙:"驸",駛:"驶",駝:"驼",駟:"驷",駡:"骂",駢:"骈",駪:"𬳽",駭:"骇",駰:"骃",駱:"骆",駸:"骎",駼:"𬳿",駿:"骏",騁:"骋",騂:"骍",騄:"𫘧",騅:"骓",騊:"𫘦",騌:"骔",騍:"骒",騎:"骑",騏:"骐",騑:"𬴂",騖:"骛",騙:"骗",騞:"𬴃",騠:"𫘨",騤:"骙",騧:"䯄",騫:"骞",騭:"骘",騮:"骝",騰:"腾",騱:"𫘬",騵:"𫘪",騶:"驺",騷:"骚",騸:"骟",騾:"骡",驀:"蓦",驁:"骜",驂:"骖",驃:"骠",驄:"骢",驅:"驱",驊:"骅",驌:"骕",驍:"骁",驎:"𬴊",驏:"骣",驕:"骄",驗:"验",驚:"惊",驛:"驿",驟:"骤",驢:"驴",驤:"骧",驥:"骥",驦:"骦",驪:"骊",驫:"骉",骯:"肮",髏:"髅",髒:"脏",體:"体",髕:"髌",髖:"髋",髮:"发",鬆:"松",鬍:"胡",鬚:"须",鬢:"鬓",鬥:"斗",鬧:"闹",鬨:"哄",鬩:"阋",鬮:"阄",鬱:"郁",鬹:"鬶",魎:"魉",魘:"魇",魚:"鱼",魛:"鱽",魟:"𫚉",魢:"鱾",魨:"鲀",魯:"鲁",魴:"鲂",魷:"鱿",魺:"鲄",鮀:"𬶍",鮁:"鲅",鮃:"鲆",鮆:"𫚖",鮈:"𬶋",鮊:"鲌",鮋:"鲉",鮍:"鲏",鮎:"鲇",鮐:"鲐",鮑:"鲍",鮒:"鲋",鮓:"鲊",鮚:"鲒",鮜:"鲘",鮝:"鲞",鮞:"鲕",鮟:"𩽾",鮠:"𬶏",鮡:"𬶐",鮣:"䲟",鮦:"鲖",鮪:"鲔",鮫:"鲛",鮭:"鲑",鮮:"鲜",鮳:"鲓",鮶:"鲪",鮸:"𩾃",鮺:"鲝",鯀:"鲧",鯁:"鲠",鯇:"鲩",鯉:"鲤",鯊:"鲨",鯒:"鲬",鯔:"鲻",鯕:"鲯",鯖:"鲭",鯗:"鲞",鯛:"鲷",鯝:"鲴",鯡:"鲱",鯢:"鲵",鯤:"鲲",鯧:"鲳",鯨:"鲸",鯪:"鲮",鯫:"鲰",鯰:"鲶",鯴:"鲺",鯷:"鳀",鯻:"𬶟",鯽:"鲫",鯿:"鳊",鰁:"鳈",鰂:"鲗",鰃:"鳂",鰆:"䲠",鰈:"鲽",鰉:"鳇",鰊:"𬶠",鰌:"䲡",鰍:"鳅",鰏:"鲾",鰐:"鳄",鰒:"鳆",鰓:"鳃",鰛:"鳁",鰜:"鳒",鰟:"鳑",鰠:"鳋",鰣:"鲥",鰤:"𫚕",鰥:"鳏",鰧:"䲢",鰨:"鳎",鰩:"鳐",鰭:"鳍",鰮:"鳁",鰱:"鲢",鰲:"鳌",鰳:"鳓",鰵:"鳘",鰶:"𬶭",鰷:"鲦",鰹:"鲣",鰺:"鲹",鰻:"鳗",鰼:"鳛",鰾:"鳔",鱀:"𬶨",鱂:"鳉",鱅:"鳙",鱇:"𩾌",鱈:"鳕",鱉:"鳖",鱒:"鳟",鱔:"鳝",鱖:"鳜",鱗:"鳞",鱘:"鲟",鱚:"𬶮",鱝:"鲼",鱟:"鲎",鱠:"鲙",鱣:"鳣",鱤:"鳡",鱧:"鳢",鱨:"鲿",鱭:"鲚",鱯:"鳠",鱲:"𫚭",鱷:"鳄",鱸:"鲈",鱺:"鲡",鳥:"鸟",鳧:"凫",鳩:"鸠",鳬:"凫",鳲:"鸤",鳳:"凤",鳴:"鸣",鳶:"鸢",鳾:"䴓",鴆:"鸩",鴇:"鸨",鴉:"鸦",鴒:"鸰",鴕:"鸵",鴛:"鸳",鴝:"鸲",鴞:"鸮",鴟:"鸱",鴣:"鸪",鴦:"鸯",鴨:"鸭",鴯:"鸸",鴰:"鸹",鴴:"鸻",鴷:"䴕",鴻:"鸿",鴿:"鸽",鵁:"䴔",鵂:"鸺",鵃:"鸼",鵏:"𬷕",鵐:"鹀",鵑:"鹃",鵒:"鹆",鵓:"鹁",鵜:"鹈",鵝:"鹅",鵟:"𫛭",鵠:"鹄",鵡:"鹉",鵪:"鹌",鵬:"鹏",鵮:"鹐",鵯:"鹎",鵰:"雕",鵲:"鹊",鵷:"鹓",鵾:"鹍",鶄:"䴖",鶇:"鸫",鶉:"鹑",鶊:"鹒",鶓:"鹋",鶖:"鹙",鶘:"鹕",鶚:"鹗",鶠:"𬸘",鶡:"鹖",鶥:"鹛",鶩:"鹜",鶪:"䴗",鶬:"鸧",鶯:"莺",鶱:"𬸣",鶲:"鹟",鶴:"鹤",鶹:"鹠",鶺:"鹡",鶻:"鹘",鶼:"鹣",鶿:"鹚",鷀:"鹚",鷁:"鹢",鷂:"鹞",鷄:"鸡",鷉:"䴘",鷊:"鹝",鷓:"鹧",鷖:"鹥",鷗:"鸥",鷙:"鸷",鷚:"鹨",鷟:"𬸦",鷥:"鸶",鷦:"鹪",鷫:"鹔",鷭:"𬸪",鷯:"鹩",鷲:"鹫",鷳:"鹇",鷴:"鹇",鷸:"鹬",鷹:"鹰",鷺:"鹭",鷽:"鸴",鸂:"㶉",鸇:"鹯",鸊:"䴙",鸌:"鹱",鸏:"鹲",鸑:"𬸚",鸕:"鸬",鸘:"鹴",鸚:"鹦",鸛:"鹳",鸝:"鹂",鸞:"鸾",鹵:"卤",鹹:"咸",鹺:"鹾",鹼:"碱",鹽:"盐",麗:"丽",麥:"麦",麩:"麸",麪:"面",麫:"面",麬:"𤿲",麯:"曲",麳:"𪎌",麴:"曲",麵:"面",麼:"么",麽:"么",黃:"黄",黌:"黉",點:"点",黨:"党",黲:"黪",黴:"霉",黶:"黡",黷:"黩",黽:"黾",黿:"鼋",鼂:"鼌",鼉:"鼍",鼕:"冬",鼴:"鼹",齊:"齐",齋:"斋",齎:"赍",齏:"齑",齒:"齿",齔:"龀",齕:"龁",齗:"龂",齘:"𬹼",齙:"龅",齜:"龇",齟:"龃",齠:"龆",齡:"龄",齣:"出",齦:"龈",齧:"啮",齪:"龊",齬:"龉",齮:"𬺈",齯:"𫠜",齲:"龋",齶:"腭",齷:"龌",齼:"𬺓",龍:"龙",龎:"厐",龐:"庞",龑:"䶮",龔:"龚",龕:"龛",龜:"龟","鿁":"䜤","鿓":"鿒","𠁞":"𠀾","𠗣":"㓆","𡃕":"𠴛","𡅏":"𠲥","𡑍":"𫭼","𡑭":"𡋗","𡓾":"𡋀","𡔖":"𡍣","𡞵":"㛟","𡠹":"㛿","𡢃":"㛠","𡮉":"𡭜","𡮣":"𡭬","𡳳":"𡳃","𡻕":"岁","𡾱":"㟜","𢣚":"𢘝","𢶫":"𢫞","𢹿":"𢬦","𣈶":"暅","𣙎":"㭣","𣞻":"𣘓","𣠩":"𣞎","𣠲":"𣑶","𣯶":"毶","𣾷":"㳢","𤁣":"𣺽","𤅶":"𣷷","𤓩":"𤊰","𤪺":"㻘","𤫩":"㻏","𤳸":"𤳄","𥊝":"𥅿","𥌃":"𥅘","𥕥":"𥐰","𥖅":"𥐯","𥗽":"𬒗","𥢢":"䅪","𥸠":"𥮋","𥼽":"𥹥","𦘧":"𡳒","𦣎":"𦟗","𦪙":"䑽","𧜗":"䘞","𧜵":"䙊","𧝞":"䘛","𧟀":"𧝧","𧩙":"䜥","𧵳":"䞌","𧶧":"䞎","𨊰":"䢀","𨊸":"䢁","𨋢":"䢂","𨤻":"𨤰","𨦫":"䦀","𨧀":"𬭊","𨧜":"䦁","𨨏":"𬭛","𨭆":"𬭶","𨭎":"𬭳","𨯅":"䥿","𩞯":"䭪","𩠴":"𩠠","𩣑":"䯃","𩶘":"䲞","𰻞":"𰻝","「":"“","」":"”","『":"‘","』":"’"},R={一坏:"一坯",一目瞭然:"一目了然",七逕:"七迳",上逕:"上迳",上鍊:"上链",不可貲計:"不可赀計",不瞭解:"不了解",么麼:"幺麽",么麽:"幺麽",九逕山:"九迳山",乾佑縣:"乾佑县",乾元:"乾元",乾卦:"乾卦",乾嘉:"乾嘉",乾圖:"乾图",乾坤:"乾坤",乾坤一擲:"乾坤一掷",乾坤再造:"乾坤再造",乾坤大挪移:"乾坤大挪移",乾宅:"乾宅",乾安縣:"乾安县",乾安鎮:"乾安镇",乾州:"乾州",乾斷:"乾断",乾旦:"乾旦",乾曜:"乾曜",乾清宮:"乾清宫",乾盛世:"乾盛世",乾紅:"乾红",乾綱:"乾纲",乾縣:"乾县",乾象:"乾象",乾造:"乾造",乾道:"乾道",乾闥婆:"乾闼婆",乾陵:"乾陵",乾隆:"乾隆",乾隆年間:"乾隆年间",乾隆皇帝:"乾隆皇帝",二噁英:"二𫫇英",以免藉口:"以免借口",傢俱:"家具",允祕:"允祕",八濛山:"八濛山",其陰多蒐:"其阴多蒐",凌藉:"凌借",函覆:"函复",剋架:"剋架",剋毒:"剋毒",千鍾粟:"千锺粟",南氾:"南氾",南逕:"南迳",反反覆覆:"反反复复",反覆:"反复",反覆思維:"反复思维",反覆思量:"反复思量",反覆性:"反复性",名覆金甌:"名复金瓯",吳祕:"吴祕",吳育昇:"吴育昇",哪吒:"哪吒",回覆:"回复",土坏:"土坯",坏土:"坯土",坏子:"坯子",坏布:"坯布",坏戶:"坯户",墨沈沈:"墨沉沉",壺裏乾坤:"壶里乾坤",大目乾連冥間救母變文:"大目乾连冥间救母变文",宫商角徵羽:"宫商角徵羽",尼乾子:"尼乾子",尼乾陀:"尼乾陀",年釐:"年釐",幺麼:"幺麽",幺麼小丑:"幺麽小丑",幺麼小醜:"幺麽小丑",康乾:"康乾",張昇:"张昇",張法乾:"张法乾",彷彿:"���佛",徐胤昇:"徐胤昇",復甦:"复苏",徵弦:"徵弦",徵絃:"徵弦",徵羽摩柯:"徵羽摩柯",徵聲:"徵声",徵調:"徵调",徵音:"徵音",意志消沈:"意志消沉",憑藉:"凭借",憑藉着:"凭借着",懷釐:"怀釐",手鍊:"手链",打坏:"打坯",扞格:"扞格",扭轉乾坤:"扭转乾坤",批覆:"批复",找藉口:"找借口",折戟沈沙:"折戟沉沙",折戟沈河:"折戟沉河",拉坏:"拉坯",拉鍊:"拉链",拉鍊工程:"拉链工程",拜覆:"拜复",挨剋:"挨剋",捏坏:"捏坯",擊沈:"击沉",據瞭解:"据了解",於世成:"於世成",於乎:"於乎",於仲完:"於仲完",於倫:"於伦",於其一:"於其一",於則:"於则",於勇明:"於勇明",於呼哀哉:"於呼哀哉",於單:"於单",於坦:"於坦",於崇文:"於崇文",於忠祥:"於忠祥",於惟一:"於惟一",於戲:"於戏",於敖:"於敖",於梨華:"於梨华",於清言:"於清言",於潛:"於潜",於琳:"於琳",於穆:"於穆",於竹屋:"於竹屋",於菟:"於菟",於邑:"於邑",於陵子:"於陵子",旋乾轉坤:"旋乾转坤",旋轉乾坤:"旋转乾坤",旋轉乾坤之力:"旋转乾坤之力",明瞭:"明了",明覆:"明复",昏沈:"昏沉",春蒐:"春蒐",春釐:"春釐",暗沈沈:"暗沉沉",書中自有千鍾粟:"书中自有千锺粟",朝乾夕惕:"朝乾夕惕",木吒:"木吒",李乾德:"李乾德",李昇:"李昇",李昇勳:"李昇勋",李澤鉅:"李泽钜",李祕:"李祕",李鍊福:"李链福",李鍾郁:"李锺郁",束脩:"束脩",東氾:"东氾",梁昇卿:"梁昇卿",梁章鉅:"梁章钜",楊聯陞:"杨联陞",樊於期:"樊於期",死氣沈沈:"死气沉沉",段脩:"段脩",毛坏:"毛坯",水逕:"水迳",氾勝之:"氾胜之",氾南:"氾南",氾國:"氾国",氾水:"氾水",沈下:"沉下",沈不住氣:"沉不住气",沈住氣:"沉住气",沈冤:"沉冤",沈厚:"沉厚",沈吟:"沉吟",沈寂:"沉寂",沈得住氣:"沉得住气",沈思:"沉思",沈思往事:"沉思往事",沈悶:"沉闷",沈沒:"沉没",沈沒成本:"沉没成本",沈浮:"沉浮",沈浸:"沉浸",沈浸於:"沉浸于",沈淪:"沉沦",沈湎:"沉湎",沈湎酒色:"沉湎酒色",沈溺:"沉溺",沈滯:"沉滞",沈滯性:"沉滞性",沈澱:"沉淀",沈澱出來:"沉淀出来",沈澱劑:"沉淀剂",沈澱法:"沉淀法",沈澱物:"沉淀物",沈濁:"沉浊",沈甸甸:"沉甸甸",沈痛:"沉痛",沈痼:"沉痼",沈痾:"沉疴",沈睡:"沉睡",沈睡不醒:"沉睡不醒",沈砂池:"沉砂池",沈積:"沉积",沈積岩:"沉积岩",沈積石:"沉积石",沈筒:"沉筒",沈船:"沉船",沈落:"沉落",沈迷:"沉迷",沈迷不醒:"沉迷不醒",沈醉:"沉醉",沈重:"沉重",沈降:"沉降",沈陷:"沉陷",沈靜:"沉静",沈靜下來:"沉静下来",沈香:"沉香",沈鬱:"沉郁",沈魚落雁:"沉鱼落雁",沈默:"沉默",沈默不語:"沉默不语",沈默寡言:"沉默寡言",沙逕:"沙迳",河逕:"河迳",流徵:"流徵",浪蕩乾坤:"浪荡乾坤",浮沈:"浮沉",海哩:"海里",深沈:"深沉",深沈不露:"深沉不露",溫昇豪:"温昇豪",滑藉:"滑借",烏昇:"乌昇",烏沈沈:"乌沉沉",烏逕:"乌迳",狐藉虎威:"狐借虎威",王彥昇:"王彦昇",珍珠項鍊:"珍珠项链",甚鉅:"甚钜",甦生:"苏生",甦醒:"苏醒",申昇勳:"申昇勋",申覆:"申复",畢昇:"毕昇",盧象昇:"卢象昇",目劄:"目劄",瞭如:"了如",瞭如指掌:"了如指掌",瞭然:"了然",瞭然於心:"了然于心",瞭若指掌:"了若指掌",瞭解:"了解",瞭解到:"了解到",破釜沈舟:"破釜沉舟",磚坏:"砖坯",示覆:"示复",社逕:"社迳",祕丕笈:"祕丕笈",祕彭祖:"祕彭祖",祕瓊:"祕琼",祝釐:"祝釐",稟覆:"禀复",竺乾:"竺乾",答覆:"答复",篤麼:"笃麽",簡單明瞭:"简单明了",籌畫:"筹划",素藉:"素借",耳沈:"耳沉",肉脩:"肉脩",肘手鍊足:"肘手链足",胤祕:"胤祕",脩敬:"脩敬",脩炳:"脩炳",脩脡:"脩脡",脩脯:"脩脯",脩金:"脩金",脫坏:"脱坯",腶脩:"腶脩",英哩:"英里",茅蒐:"茅蒐",茵藉:"茵借",萬鍾:"万锺",落雁沈魚:"落雁沉鱼",蒐于紅:"蒐于红",蒐於紅:"蒐于红",蒐狩:"蒐狩",蒐獮:"蒐狝",蒐獵:"蒐猎",蒐田:"蒐田",蒐畋:"蒐畋",蒐苗:"蒐苗",蒜薹:"蒜薹",蔣昇:"蒋昇",蕓薹:"芸薹",蕭乾:"萧乾",藉代:"借代",藉以:"借以",藉助:"借助",藉助於:"借助于",藉卉:"借卉",藉口:"借口",藉喻:"借喻",藉寇兵:"借寇兵",藉寇兵齎盜糧:"借寇兵赍盗粮",藉手:"借手",藉據:"借据",藉故:"借故",藉故推辭:"借故推辞",藉方:"借方",藉條:"借条",藉槁:"借槁",藉機:"借机",藉此:"借此",藉此機會:"借此机会",藉甚:"借甚",藉由:"借由",藉着:"借着",藉端:"借端",藉端生事:"借端生事",藉箸代籌:"借箸代筹",藉草枕塊:"借草枕块",藉詞:"借词",藉讀:"借读",藉資:"借资",衹得:"只得",衹見樹木:"只见树木",衹見樹木不見森林:"只见树木不见森林",袁祕:"袁祕",袖裏乾坤:"袖里乾坤",袷袢:"袷袢",製坏:"制坯",覆信:"复信",覆呈:"复呈",覆命:"复命",覆墓:"复墓",覆帳:"复帐",覆按:"复按",覆文:"复文",覆校:"复校",覆電:"复电",見覆:"见复",角徵:"角徵",角徵羽:"角徵羽",計畫:"计划",變��:"变徵",變徵之聲:"变徵之声",變徵之音:"变徵之音",谿工:"谿工",赤石逕:"赤石迳",踅門瞭戶:"踅门了户",躪藉:"躏借",載沈載浮:"载沉载浮",載浮載沈:"载浮载沉",辛祕:"辛祕",逆釐:"逆釐",逕口:"迳口",逕聯:"迳联",逕頭:"迳头",郭子乾:"郭子乾",酒逢知己千鍾少:"酒逢知己千锺少",醞藉:"酝借",重覆:"重复",金吒:"金吒",金昇玟:"金昇玟",金鍊:"金链",鈞覆:"钧复",鉅子:"钜子",鉅萬:"钜万",鉅防:"钜防",鉸鍊:"铰链",銀鍊:"银链",鋼坏:"钢坯",錢鍾書:"钱锺书",鍊墜:"链坠",鍊子:"链子",鍊形:"链形",鍊條:"链条",鍊錘:"链锤",鍊鎖:"链锁",鍛鍾:"锻锺",鍾繇:"锺繇",鍾萬梅:"锺万梅",鍾重發:"锺重发",鍾鍛:"锺锻",鍾馗:"锺馗",鎖鍊:"锁链",鐵鍊:"铁链",鑽石項鍊:"钻石项链",鑿坏:"凿坯",閻鶴昇:"阎鹤昇",陰沈:"阴沉",陰沈沈:"阴沉沉",陰陰沈沈:"阴阴沉沉",陳志昇:"陈志昇",陳昇:"陈昇",陶坏:"陶坯",雁杳魚沈:"雁杳鱼沉",電覆:"电复",韓昇延:"韩昇延",項鍊:"项链",頸鍊:"颈链",顛乾倒坤:"颠乾倒坤",顛倒乾坤:"颠倒乾坤",顧藉:"顾借",魏徵:"魏徵",魚沈雁杳:"鱼沉雁杳",麪坏兒:"面坯儿",麼些族:"麽些族",黃鍾公:"黄锺公",黑沈沈:"黑沉沉",龔昇:"龚昇"};let O=null,w=null;function ft(){O=new Map(Object.entries(lt)),w=new Map;for(const t of Object.keys(R)){const e=t[0];let o=w.get(e);o||w.set(e,o=[]),o.push(t)}for(const t of w.values())t.sort((e,o)=>o.length-e.length)}function ut(t){O||ft();let e="",o=0,i=0;const s=t.length;for(;i<s;){const n=String.fromCodePoint(t.codePointAt(i)),a=w.get(n);if(a){let l=null;for(const r of a)if(t.startsWith(r,i)){l=r;break}if(l){e+=R[l],i+=l.length,o++;continue}}const c=O.get(n);c!==void 0?(e+=c,o++):e+=n,i+=n.length}return{text:e,changed:o}}const P=[{id:"moxhi",name:"Mặc Hi 30",weightsUrl:"/weights",tokenizerId:"moxhi",downloadMB:74},{id:"hachimi60",name:"Hachimi 60",weightsUrl:"/weights/hachimi60",tokenizerId:"hachimi60",downloadMB:113}],_="moxhi";function ht(t){return P.find(e=>e.id===t)??P.find(e=>e.id===_)}function mt(t,e,o){const i=t??{};return["moxhi.autotune.v4",i.vendor??"",i.architecture??"",i.device??"",`${e.dModel}x${e.heads}x${e.ffn}`,o].join("|")}function dt(t,e,o,i=192){const s=[];for(let n=0;n<t.length;){let a=Math.min(n+i,t.length),c=0;for(let u=n;u<a;u++)c=Math.max(c,t[u]);const l=et(Math.min(tt,c+8)),r=Math.max(1,Math.min(i,nt(e,l,o)));a=Math.min(n+r,t.length),s.push([n,a]),n=a}return s}async function yt({model:t=ht(_),onPhase:e,onProgress:o,onDeviceLost:i}={}){e?.("gpu");const s=await J(),n=s.hasF16?"f16":"f32";let a=null;s.device.lost.then(f=>{a={reason:f?.reason??"unknown",message:f?.message??""},console.error(`WebGPU device lost (${a.reason}): ${a.message}`),i?.(a)}),e?.("weights");const c=await Q(s.device,t.weightsUrl,{targetDtype:n,lmHeadQ8:n==="f16",ffnWT:n==="f16",projWT:n==="f16",onProgress:o});e?.("tokenizer");const l=await K(t.tokenizerId);e?.("autotune");let r=null,u="default";try{const f=mt(s.adapterInfo,Y(),n),p=localStorage.getItem(f);if(p)r=JSON.parse(p).tuned,u="cache";else{const d=await q({...s,dtype:n},c);r=d.tuned,u=d.partial?"partial":"measured",d.partial||localStorage.setItem(f,JSON.stringify({tuned:r,timings:d.timings,date:new Date().toISOString()}))}}catch(f){console.warn("autotune unavailable, falling back to auto routing:",f)}e?.("ready");const y=s.adapterInfo,H=y.description||[y.vendor,y.architecture].filter(Boolean).join(" ")||"GPU",U=n==="f16"?2:4;async function z(f,{onBatch:p,shouldStop:d,pack:A=!1,resume:b=null}={}){const D=ut(f);f=D.text;const $=at(f);let m=$.sentences,v=$.paras;if(A){const h=ct(m,v);m=h.rows,v=h.rowParas}if(m.length===0)return{text:"",cancelled:!1,stats:{sentences:0,tokens:0,ms:0,tokPerSec:0}};const g=b&&b.length===m.length?[...b]:new Array(m.length).fill(""),k=dt(m.map(h=>h.length),s,U);let E=0,M=0,j=!1;const F=performance.now();for(let h=0;h<k.length;h++){if(d?.()){j=!0;break}const[S,I]=k[h];if(g.slice(S,I).every(x=>x)){p?.(h+1,k.length,g);continue}if(a)throw new Error(`GPU device lost (${a.reason}): ${a.message}`);const{rows:W,metrics:G}=await X({...s},c,l,m.slice(S,I),{...V(r,I-S),...A?{maxNewTokens:Z}:{}});W.forEach((x,L)=>{g[S+L]=x.text.normalize("NFC"),x.forcedEos&&M++}),E+=G.tokensGenerated,p?.(h+1,k.length,g)}const T=performance.now()-F;return M>0&&console.warn(`translateText: ${M}/${m.length} rows hit the token cap (tail may be cut)`),{text:rt(v,g),rowTexts:g,cancelled:j,stats:{sentences:m.length,tokens:E,ms:T,forcedEos:M,t2s:D.changed,tokPerSec:T>0?E/T*1e3:0}}}return{info:{gpuName:H,dtype:n,lmHeadQ8:n==="f16",tunedFrom:u,modelId:t.id,modelName:t.name},translateText:z,isLost:()=>a}}export{_ as D,P as M,dt as a,yt as c,ht as m,ct as p,at as s};
4
+ //# sourceMappingURL=engine-BTyy_WlH.js.map
assets/engine-BTyy_WlH.js.map ADDED
The diff for this file is too large to render. See raw diff
 
assets/ffn_mt_sweep-bWrzWJ6f.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as S}from"./debug-Cn7EHWtJ.js";import{l as y}from"./weights-B-okS09o.js";import{l as k,t as b}from"./tokenizer-Ex1u7wXD.js";import{r as B}from"./encoder-DX8MOfcH.js";import{c as D}from"./decoder-DI6VDxxO.js";import{t as E}from"./profile-DdyBUdtB.js";import{p as F}from"./bench-C8ITpm5I.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./constants-C8VbFpic.js";import"./f16-wKKZr58e.js";import"./pipelines-DD24nEJg.js";import"./generate-C4ruG1zm.js";import"./chapter3k-Bxq8ds-a.js";const h=7,l=50,T=[16,32,64],A=o=>{const e=[...o].sort((i,r)=>i-r),s=e.length>>1;return e.length%2?e[s]:(e[s-1]+e[s])/2};S("ffn_mt_sweep",async o=>{const{device:e}=o;if(!o.hasF16)return{skip:!0,reason:"no shader-f16"};const s=await y(e,"/weights",{targetDtype:"f16",ffnWT:!0});try{const i=await k(),r={device:e,dtype:"f16",limits:o.limits},g=[...F("file23k")].sort((f,n)=>n.length-f.length),m=[{name:"mt8",ffnFlags:{mt:8}},{name:"mt16",ffnFlags:{mt:16}},{name:"mt32",ffnFlags:{mt:32}}],u=[];for(const f of T){const n=await b(i,g.slice(0,f)),c=await B(r,s,n);await e.queue.onSubmittedWorkDone();try{const d=async({ffnFlags:t})=>{const a=D(r,s,{B:n.B,S:c.S,maxSteps:l,lmHead:"tiled",ffn:"wt",ffnFlags:t}),{stepUs:w}=await E(r,s,c,a,{steps:l});return a.destroy(),w};for(const t of m)await d(t);const p=Object.fromEntries(m.map(t=>[t.name,[]]));for(let t=0;t<h;t++)for(const a of m)p[a.name].push(await d(a));u.push({B:n.B,...Object.fromEntries(m.map(t=>[`${t.name}StepUs`,Number(A(p[t.name]).toFixed(1))])),runs:p})}finally{c.arena.destroy()}}return{pass:!0,detail:{steps:l,rounds:h,table:u}}}finally{s.buffer.destroy()}});
2
+ //# sourceMappingURL=ffn_mt_sweep-bWrzWJ6f.js.map
assets/ffn_mt_sweep-bWrzWJ6f.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"ffn_mt_sweep-bWrzWJ6f.js","sources":["../../src/debug/tests/ffn_mt_sweep.js"],"sourcesContent":["// GEMV WT MT sweep for the decode-FFN sites: MT = rows served per W-tile\n// sweep (traffic ÷MT, workgroups ÷MT). MT does NOT change any per-output\n// accumulation order — outputs are BIT-IDENTICAL across arms — so this is a\n// pure perf knob; the winner can be adopted with zero parity risk.\n// lmHead pinned 'tiled' (f16) in every arm so the delta isolates the FFN\n// GEMV. Arms interleaved per round in one session, medians of ROUNDS.\n// B=128 is excluded: 'auto' routes the FFN through tiled WNT there.\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { createDecodeState } from '../../engine/decoder.js';\nimport { timeDecodeSteps } from '../../bench/profile.js';\nimport { presetChunks } from '../../bench/bench.js';\n\nconst ROUNDS = 7;\nconst STEPS = 50;\nconst BATCHES = [16, 32, 64];\n\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nregisterTest('ffn_mt_sweep', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const weights = await loadWeights(device, '/weights', { targetDtype: 'f16', ffnWT: true });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n\n const ARMS = [\n { name: 'mt8', ffnFlags: { mt: 8 } },\n { name: 'mt16', ffnFlags: { mt: 16 } },\n { name: 'mt32', ffnFlags: { mt: 32 } },\n ];\n const table = [];\n for (const B of BATCHES) {\n const batch = await tokenizeBatch(tok, chunks.slice(0, B));\n const encRun = await runEncoder(gctx, weights, batch);\n await device.queue.onSubmittedWorkDone();\n try {\n const timeArm = async ({ ffnFlags }) => {\n const state = createDecodeState(gctx, weights, {\n B: batch.B, S: encRun.S, maxSteps: STEPS, lmHead: 'tiled', ffn: 'wt', ffnFlags,\n });\n const { stepUs } = await timeDecodeSteps(gctx, weights, encRun, state, { steps: STEPS });\n state.destroy();\n return stepUs;\n };\n for (const arm of ARMS) await timeArm(arm); // pipeline warmup\n const times = Object.fromEntries(ARMS.map((a) => [a.name, []]));\n for (let r = 0; r < ROUNDS; r++) {\n for (const arm of ARMS) times[arm.name].push(await timeArm(arm));\n }\n table.push({\n B: batch.B,\n ...Object.fromEntries(ARMS.map((a) => [`${a.name}StepUs`, Number(median(times[a.name]).toFixed(1))])),\n runs: times,\n });\n } finally {\n encRun.arena.destroy();\n }\n }\n return { pass: true, detail: { steps: STEPS, rounds: ROUNDS, table } };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["ROUNDS","STEPS","BATCHES","median","xs","s","a","b","m","registerTest","ctx","device","weights","loadWeights","tok","loadTokenizer","gctx","chunks","presetChunks","ARMS","table","B","batch","tokenizeBatch","encRun","runEncoder","timeArm","ffnFlags","state","createDecodeState","stepUs","timeDecodeSteps","arm","times","r"],"mappings":"mjBAeA,MAAMA,EAAS,EACTC,EAAQ,GACRC,EAAU,CAAC,GAAI,GAAI,EAAE,EAErBC,EAAUC,GAAO,CACrB,MAAMC,EAAI,CAAC,GAAGD,CAAE,EAAE,KAAK,CAACE,EAAGC,IAAMD,EAAIC,CAAC,EAChCC,EAAIH,EAAE,QAAU,EACtB,OAAOA,EAAE,OAAS,EAAIA,EAAEG,CAAC,GAAKH,EAAEG,EAAI,CAAC,EAAIH,EAAEG,CAAC,GAAK,CACnD,EAEAC,EAAa,eAAgB,MAAOC,GAAQ,CAC1C,KAAM,CAAE,OAAAC,CAAM,EAAKD,EACnB,GAAI,CAACA,EAAI,OAAQ,MAAO,CAAE,KAAM,GAAM,OAAQ,eAAe,EAC7D,MAAME,EAAU,MAAMC,EAAYF,EAAQ,WAAY,CAAE,YAAa,MAAO,MAAO,GAAM,EACzF,GAAI,CACF,MAAMG,EAAM,MAAMC,EAAa,EACzBC,EAAO,CAAE,OAAAL,EAAQ,MAAO,MAAO,OAAQD,EAAI,MAAM,EACjDO,EAAS,CAAC,GAAGC,EAAa,SAAS,CAAC,EAAE,KAAK,CAACZ,EAAGC,IAAMA,EAAE,OAASD,EAAE,MAAM,EAExEa,EAAO,CACX,CAAE,KAAM,MAAO,SAAU,CAAE,GAAI,CAAC,CAAE,EAClC,CAAE,KAAM,OAAQ,SAAU,CAAE,GAAI,EAAE,CAAE,EACpC,CAAE,KAAM,OAAQ,SAAU,CAAE,GAAI,EAAE,CAAE,CAC1C,EACUC,EAAQ,CAAA,EACd,UAAWC,KAAKnB,EAAS,CACvB,MAAMoB,EAAQ,MAAMC,EAAcT,EAAKG,EAAO,MAAM,EAAGI,CAAC,CAAC,EACnDG,EAAS,MAAMC,EAAWT,EAAMJ,EAASU,CAAK,EACpD,MAAMX,EAAO,MAAM,oBAAmB,EACtC,GAAI,CACF,MAAMe,EAAU,MAAO,CAAE,SAAAC,KAAe,CACtC,MAAMC,EAAQC,EAAkBb,EAAMJ,EAAS,CAC7C,EAAGU,EAAM,EAAG,EAAGE,EAAO,EAAG,SAAUvB,EAAO,OAAQ,QAAS,IAAK,KAAM,SAAA0B,CAClF,CAAW,EACK,CAAE,OAAAG,CAAM,EAAK,MAAMC,EAAgBf,EAAMJ,EAASY,EAAQI,EAAO,CAAE,MAAO3B,CAAK,CAAE,EACvF,OAAA2B,EAAM,QAAO,EACNE,CACT,EACA,UAAWE,KAAOb,EAAM,MAAMO,EAAQM,CAAG,EACzC,MAAMC,EAAQ,OAAO,YAAYd,EAAK,IAAKb,GAAM,CAACA,EAAE,KAAM,CAAA,CAAE,CAAC,CAAC,EAC9D,QAAS4B,EAAI,EAAGA,EAAIlC,EAAQkC,IAC1B,UAAWF,KAAOb,EAAMc,EAAMD,EAAI,IAAI,EAAE,KAAK,MAAMN,EAAQM,CAAG,CAAC,EAEjEZ,EAAM,KAAK,CACT,EAAGE,EAAM,EACT,GAAG,OAAO,YAAYH,EAAK,IAAKb,GAAM,CAAC,GAAGA,EAAE,IAAI,SAAU,OAAOH,EAAO8B,EAAM3B,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EACpG,KAAM2B,CAChB,CAAS,CACH,QAAC,CACCT,EAAO,MAAM,QAAO,CACtB,CACF,CACA,MAAO,CAAE,KAAM,GAAM,OAAQ,CAAE,MAAOvB,EAAO,OAAQD,EAAQ,MAAAoB,EAAO,CACtE,QAAC,CACCR,EAAQ,OAAO,QAAO,CACxB,CACF,CAAC"}
assets/ffn_q8_sweep-CGfESiUo.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as y}from"./debug-Cn7EHWtJ.js";import{l as k}from"./weights-B-okS09o.js";import{l as B,t as T}from"./tokenizer-Ex1u7wXD.js";import{r as D}from"./encoder-DX8MOfcH.js";import{c as E}from"./decoder-DI6VDxxO.js";import{t as q}from"./profile-DdyBUdtB.js";import{p as z}from"./bench-C8ITpm5I.js";import{detectTreeReductionBug as R}from"./autotune-DBJGFXNj.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./constants-C8VbFpic.js";import"./f16-wKKZr58e.js";import"./pipelines-DD24nEJg.js";import"./generate-C4ruG1zm.js";import"./chapter3k-Bxq8ds-a.js";const S=7,d=50,A=[16,32,64,128],M=s=>{const e=[...s].sort((n,c)=>n-c),r=e.length>>1;return e.length%2?e[r]:(e[r-1]+e[r])/2};y("ffn_q8_sweep",async s=>{const{device:e}=s;if(!s.hasF16)return{skip:!0,reason:"no shader-f16"};const r="f16",n=await k(e,"/weights",{targetDtype:r,ffnQ8:!0,ffnWT:!0});try{const c=await B(),f={device:e,dtype:r,limits:s.limits,hasSubgroups:s.hasSubgroups,subgroupMinSize:s.subgroupMinSize},w=[...z("file23k")].sort((m,o)=>o.length-m.length),h=s.hasSubgroups&&await R(e)?"on":"auto",i=[{name:"f16",ffn:"f16"},{name:"wt",ffn:"wt"},{name:"q8",ffn:"q8"}],p=[];for(const m of A)try{const o=await T(c,w.slice(0,m)),u=await D(f,n,o);await e.queue.onSubmittedWorkDone();try{const g=async({ffn:t})=>{const a=E(f,n,{B:o.B,S:u.S,maxSteps:d,lmHead:"tiled",ffn:t,sg:h}),{stepUs:b}=await q(f,n,u,a,{steps:d});return a.destroy(),b};for(const t of i)await g(t);const l=Object.fromEntries(i.map(t=>[t.name,[]]));for(let t=0;t<S;t++)for(const a of i)l[a.name].push(await g(a));p.push({B:o.B,...Object.fromEntries(i.map(t=>[`${t.name}StepUs`,Number(M(l[t.name]).toFixed(1))])),runs:l})}finally{u.arena.destroy()}}catch(o){p.push({B:m,error:String(o?.message??o)})}return{pass:!0,detail:{dtype:r,sg:h,steps:d,rounds:S,table:p}}}finally{n.buffer.destroy()}});
2
+ //# sourceMappingURL=ffn_q8_sweep-CGfESiUo.js.map
assets/ffn_q8_sweep-CGfESiUo.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"ffn_q8_sweep-CGfESiUo.js","sources":["../../src/debug/tests/ffn_q8_sweep.js"],"sourcesContent":["// Decode-FFN W8A16 A/B: f16 fc1/fc2 (GEMV NWT / tiled at B>=128) vs int8\n// (GEMV WT / tiled WQ8) — measures whether halving FFN W traffic pays at\n// decode shapes. lmHead is pinned to 'tiled' (f16) in BOTH arms so the delta\n// isolates the FFN sites. Arms interleaved per round in one session,\n// medians of ROUNDS (sequential runs drift ±30% with laptop thermals).\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { createDecodeState } from '../../engine/decoder.js';\nimport { timeDecodeSteps } from '../../bench/profile.js';\nimport { presetChunks } from '../../bench/bench.js';\nimport { detectTreeReductionBug } from '../../engine/autotune.js';\n\nconst ROUNDS = 7;\nconst STEPS = 50;\nconst BATCHES = [16, 32, 64, 128];\n\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nregisterTest('ffn_q8_sweep', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const dtype = 'f16';\n const weights = await loadWeights(device, '/weights', { targetDtype: dtype, ffnQ8: true, ffnWT: true });\n try {\n const tok = await loadTokenizer();\n const gctx = {\n device, dtype, limits: ctx.limits,\n hasSubgroups: ctx.hasSubgroups, subgroupMinSize: ctx.subgroupMinSize,\n };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n // Mirror production routing on tree-bug devices (Adreno 7xx): the app\n // forces sg there, so the arms must time the sg kernel variants.\n const sg = (ctx.hasSubgroups && await detectTreeReductionBug(device)) ? 'on' : 'auto';\n\n // f16 = current NWT layout; wt = f16 TRANSPOSED (isolates the layout/\n // W-reuse win, zero precision change); q8 = int8 on top of wt.\n const ARMS = [\n { name: 'f16', ffn: 'f16' },\n { name: 'wt', ffn: 'wt' },\n { name: 'q8', ffn: 'q8' },\n ];\n const table = [];\n for (const B of BATCHES) {\n // Per-B try/catch: on phones the large-B points can exceed binding\n // limits or lose the device — report the points that did run.\n try {\n const batch = await tokenizeBatch(tok, chunks.slice(0, B));\n const encRun = await runEncoder(gctx, weights, batch);\n await device.queue.onSubmittedWorkDone();\n try {\n const timeArm = async ({ ffn }) => {\n const state = createDecodeState(gctx, weights, {\n B: batch.B, S: encRun.S, maxSteps: STEPS, lmHead: 'tiled', ffn, sg,\n });\n const { stepUs } = await timeDecodeSteps(gctx, weights, encRun, state, { steps: STEPS });\n state.destroy();\n return stepUs;\n };\n for (const arm of ARMS) await timeArm(arm); // pipeline warmup\n const times = Object.fromEntries(ARMS.map((a) => [a.name, []]));\n for (let r = 0; r < ROUNDS; r++) {\n for (const arm of ARMS) times[arm.name].push(await timeArm(arm));\n }\n table.push({\n B: batch.B,\n ...Object.fromEntries(ARMS.map((a) => [`${a.name}StepUs`, Number(median(times[a.name]).toFixed(1))])),\n runs: times,\n });\n } finally {\n encRun.arena.destroy();\n }\n } catch (err) {\n table.push({ B, error: String(err?.message ?? err) });\n }\n }\n return { pass: true, detail: { dtype, sg, steps: STEPS, rounds: ROUNDS, table } };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["ROUNDS","STEPS","BATCHES","median","xs","s","a","b","m","registerTest","ctx","device","dtype","weights","loadWeights","tok","loadTokenizer","gctx","chunks","presetChunks","sg","detectTreeReductionBug","ARMS","table","B","batch","tokenizeBatch","encRun","runEncoder","timeArm","ffn","state","createDecodeState","stepUs","timeDecodeSteps","arm","times","r","err"],"mappings":"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"}
assets/ffn_splitk-B1WT9pJ7.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as k}from"./debug-Cn7EHWtJ.js";import{c as K,r as Q,a as Y}from"./gpu-utils-BTh3AGTJ.js";import{h as L,t as I,s as J}from"./pipelines-DD24nEJg.js";import{l as R}from"./weights-B-okS09o.js";import{l as D,t as N}from"./tokenizer-Ex1u7wXD.js";import{t as T}from"./generate-C4ruG1zm.js";import{r as V}from"./encoder-DX8MOfcH.js";import{c as X}from"./decoder-DI6VDxxO.js";import{t as Z}from"./profile-DdyBUdtB.js";import{p as A}from"./bench-C8ITpm5I.js";import{m as $}from"./math-DNG-wiC0.js";import{e as W,f as tt}from"./f16-wKKZr58e.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./constants-C8VbFpic.js";import"./shapes-BCQ9D81L.js";import"./chapter3k-Bxq8ds-a.js";function et(o){let t=o>>>0;return()=>{t=t+1831565813|0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}async function C(o,{M:t,K:e,N:n,sk:l,silu:m,tol:d,seed:h}){const{device:r}=o,f=et(h),p=g=>{const _=new Uint16Array(g);for(let P=0;P<g;P++)_[P]=tt(f()-.5);return{half:_,ref:W(_)}},a=p(t*e),c=p(e*n),u=p(n),s=$(a.ref,c.ref,u.ref,{M:t,K:e,N:n,silu:m}),i=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,w=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC,{nz:y}=J(e,l),F=K(r,a.half,i),v=K(r,c.half,i),G=K(r,u.half,i),S=r.createBuffer({size:y*t*n*4,usage:GPUBufferUsage.STORAGE}),b=r.createBuffer({size:t*n*2,usage:w}),O=r.createCommandEncoder(),B=O.beginComputePass(),z=L(r,B,{x:F,w:v,y:null,M:t,K:e,N:n,splitK:{parts:S,sk:l},flags:{t:"f16",tiled:!0,tm8:!0}}),q=I(r,B,{parts:S,b:G,y:b,M:t,N:n,nz:y,flags:{t:"f16",silu:m}});B.end(),r.queue.submit([O.finish()]);for(const g of[...z.scratch,...q.scratch])g.destroy();const H=W(new Uint16Array(await Q(r,b,t*n*2)));for(const g of[F,v,G,S,b])g.destroy();const{failures:E,maxAbsDiff:M}=Y(H,s,d);return{pass:E===0,detail:{M:t,K:e,N:n,sk:l,nz:y,silu:m,tol:d,failures:E,maxAbsDiff:String(M)}}}k("splitk_kernel_fc2",o=>o.hasF16?C(o,{M:128,K:1792,N:448,sk:8,silu:!1,tol:.02,seed:801}):{skip:!0,reason:"no shader-f16"});k("splitk_kernel_fc1_tail",o=>o.hasF16?C(o,{M:65,K:448,N:1792,sk:8,silu:!0,tol:.01,seed:802}):{skip:!0,reason:"no shader-f16"});k("ffn_splitk_equiv",async o=>{const{device:t}=o;if(!o.hasF16)return{skip:!0,reason:"no shader-f16"};const e={device:t,dtype:"f16",limits:o.limits},n=await R(t,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0,projWT:!0});try{const l=await D(),m=[...A("file23k")].sort((a,c)=>c.length-a.length).slice(0,128),d=await T(e,n,l,m,{ffnSplitK:0}),h=await T(e,n,l,m,{ffnSplitK:8});let r=0,f=0;for(let a=0;a<m.length;a++){const c=d.rows[a].ids,u=h.rows[a].ids;c[1]!==u[1]&&r++,(c.length!==u.length||c.some((s,i)=>s!==u[i]))&&f++}const p=f/m.length;return{pass:r===0&&p<=.25,detail:{B:m.length,step0Mismatches:r,divergedRows:f,divergedRowRate:p}}}finally{n.buffer.destroy()}});const x=7,j=50,U=o=>{const t=[...o].sort((n,l)=>n-l),e=t.length>>1;return t.length%2?t[e]:(t[e-1]+t[e])/2};k("ffn_splitk_e2e_ab",async o=>{const{device:t}=o;if(!o.hasF16)return{skip:!0,reason:"no shader-f16"};const e={device:t,dtype:"f16",limits:o.limits},n=await R(t,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0,projWT:!0});try{const l=await D(),m=[...A("file23k")].sort((r,f)=>f.length-r.length),d=[{name:"off",opts:{ffnSplitK:0}},{name:"sk8",opts:{}}],h=[];for(const r of[64,128]){const f=m.slice(0,r),p=async({opts:s})=>{const{metrics:i}=await T(e,n,l,f,s);return i.decodeMs};for(const s of d)await p(s);const a=Object.fromEntries(d.map(s=>[s.name,[]]));for(let s=0;s<5;s++)for(const i of d)a[i.name].push(await p(i));const c=U(a.off),u=U(a.sk8);h.push({B:r,offDecodeMs:Number(c.toFixed(1)),sk8DecodeMs:Number(u.toFixed(1)),deltaPct:Number((100*(u-c)/c).toFixed(1)),runs:a})}return{pass:!0,detail:{table:h}}}finally{n.buffer.destroy()}});k("ffn_splitk_sweep",async o=>{const{device:t}=o;if(!o.hasF16)return{skip:!0,reason:"no shader-f16"};const e=await R(t,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0,projWT:!0});try{const n=await D(),l={device:t,dtype:"f16",limits:o.limits},m=[...A("file23k")].sort((r,f)=>f.length-r.length),d={16:[{name:"gemv",opts:{}},{name:"tiled_sk4",opts:{tiledProj:["fc1","fc2"],ffnSplitK:4}},{name:"tiled_sk8",opts:{tiledProj:["fc1","fc2"],ffnSplitK:8}}],32:[{name:"gemv",opts:{}},{name:"tiled_sk4",opts:{tiledProj:["fc1","fc2"],ffnSplitK:4}},{name:"tiled_sk8",opts:{tiledProj:["fc1","fc2"],ffnSplitK:8}}],64:[{name:"gemv",opts:{}},{name:"tiled",opts:{tiledProj:["fc1","fc2"],ffnSplitK:0}},{name:"tiled_sk4",opts:{tiledProj:["fc1","fc2"],ffnSplitK:4}},{name:"tiled_sk8",opts:{tiledProj:["fc1","fc2"],ffnSplitK:8}}],128:[{name:"off",opts:{ffnSplitK:0}},{name:"sk4",opts:{ffnSplitK:4}},{name:"sk8",opts:{ffnSplitK:8}},{name:"sk16",opts:{ffnSplitK:16}},{name:"fc2only_sk8",opts:{ffnSplitK:{fc1:0,fc2:8}}}]},h=[];for(const[r,f]of Object.entries(d)){const p=await N(n,m.slice(0,Number(r))),a=await V(l,e,p);await t.queue.onSubmittedWorkDone();try{const c=async({opts:s})=>{const i=X(l,e,{B:p.B,S:a.S,maxSteps:j,...s}),{stepUs:w}=await Z(l,e,a,i,{steps:j});return i.destroy(),w};for(const s of f)await c(s);const u=Object.fromEntries(f.map(s=>[s.name,[]]));for(let s=0;s<x;s++)for(const i of f)u[i.name].push(await c(i));h.push({B:p.B,medians:Object.fromEntries(f.map(s=>[s.name,Number(U(u[s.name]).toFixed(1))])),runs:u})}finally{a.arena.destroy()}}return{pass:!0,detail:{steps:j,rounds:x,table:h}}}finally{e.buffer.destroy()}});
2
+ //# sourceMappingURL=ffn_splitk-B1WT9pJ7.js.map
assets/ffn_splitk-B1WT9pJ7.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"ffn_splitk-B1WT9pJ7.js","sources":["../../src/debug/tests/ffn_splitk.js"],"sourcesContent":["// Split-K round for the starved tiled FFN sites (fc2 at b128: N=448 → 14\n// workgroups on a ~50-SM GPU; enc/prod profiles 2026-07-06 put fc1+fc2 at\n// ~21% of the b128 decode step).\n// splitk_kernel_* GEMM→reduce pair vs the f64 reference at both decode\n// FFN shapes — fc2 (K=1792, sk=8 → nz=8, bias) and fc1\n// (K=448, sk=8 → nz=7 ≠ sk, bias+SiLU, M tail).\n// ffn_splitk_equiv e2e sk8-vs-off at B=128 (the auto-tiled batch):\n// step-0 exact per row, whole-row divergence ≤ 25%\n// (f32 re-association at the nz seams is legal).\n// ffn_splitk_sweep interleaved step-wall arms — off/sk4/sk8/sk16 at\n// b128; gemv vs forced-tiled±sk at b64. Decides\n// FFN_SPLITK_AUTO in decoder.js.\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback, compareLanes } from '../gpu-utils.js';\nimport { dispatchGemm, dispatchGemmReduce, splitKParts } from '../../engine/pipelines.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { translateBatch } from '../../engine/generate.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { createDecodeState } from '../../engine/decoder.js';\nimport { timeDecodeSteps } from '../../bench/profile.js';\nimport { presetChunks } from '../../bench/bench.js';\nimport { matmulRef } from '../../reference/math.js';\nimport { f32ToF16, expandF16 } from '../../engine/f16.js';\n\nfunction mulberry32(seed) {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nasync function splitkKernelCase(ctx, { M, K, N, sk, silu, tol, seed }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const rand16 = (n) => {\n const half = new Uint16Array(n);\n for (let i = 0; i < n; i++) half[i] = f32ToF16(rng() - 0.5);\n return { half, ref: expandF16(half) };\n };\n const x = rand16(M * K);\n const w = rand16(K * N);\n const b = rand16(N);\n const want = matmulRef(x.ref, w.ref, b.ref, { M, K, N, silu });\n\n const ro = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const rw = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC;\n const { nz } = splitKParts(K, sk);\n const xBuf = createBuffer(device, x.half, ro);\n const wBuf = createBuffer(device, w.half, ro);\n const bBuf = createBuffer(device, b.half, ro);\n const partsBuf = device.createBuffer({ size: nz * M * N * 4, usage: GPUBufferUsage.STORAGE });\n const yBuf = device.createBuffer({ size: M * N * 2, usage: rw });\n\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n const flags = { t: 'f16', tiled: true, tm8: true };\n const d1 = dispatchGemm(device, pass, {\n x: xBuf, w: wBuf, y: null, M, K, N,\n splitK: { parts: partsBuf, sk }, flags,\n });\n const d2 = dispatchGemmReduce(device, pass, {\n parts: partsBuf, b: bBuf, y: yBuf, M, N, nz, flags: { t: 'f16', silu },\n });\n pass.end();\n device.queue.submit([encoder.finish()]);\n for (const buf of [...d1.scratch, ...d2.scratch]) buf.destroy();\n\n const got = expandF16(new Uint16Array(await readback(device, yBuf, M * N * 2)));\n for (const buf of [xBuf, wBuf, bBuf, partsBuf, yBuf]) buf.destroy();\n const { failures, maxAbsDiff } = compareLanes(got, want, tol);\n return {\n pass: failures === 0,\n detail: { M, K, N, sk, nz, silu, tol, failures, maxAbsDiff: String(maxAbsDiff) },\n };\n}\n\nregisterTest('splitk_kernel_fc2', (ctx) => (ctx.hasF16\n ? splitkKernelCase(ctx, { M: 128, K: 1792, N: 448, sk: 8, silu: false, tol: 0.02, seed: 801 })\n : { skip: true, reason: 'no shader-f16' }));\n\nregisterTest('splitk_kernel_fc1_tail', (ctx) => (ctx.hasF16\n ? splitkKernelCase(ctx, { M: 65, K: 448, N: 1792, sk: 8, silu: true, tol: 0.01, seed: 802 })\n : { skip: true, reason: 'no shader-f16' }));\n\nregisterTest('ffn_splitk_equiv', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const weights = await loadWeights(device, '/weights', {\n targetDtype: 'f16', lmHeadQ8: true, ffnWT: true, projWT: true,\n });\n try {\n const tok = await loadTokenizer();\n // B=128: the batch where 'auto' actually routes fc1/fc2 tiled.\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length).slice(0, 128);\n const off = await translateBatch(gctx, weights, tok, chunks, { ffnSplitK: 0 });\n const on = await translateBatch(gctx, weights, tok, chunks, { ffnSplitK: 8 });\n let step0Mismatches = 0;\n let divergedRows = 0;\n for (let i = 0; i < chunks.length; i++) {\n const a = off.rows[i].ids;\n const c = on.rows[i].ids;\n if (a[1] !== c[1]) step0Mismatches++; // ids[0] is decoder_start\n if (a.length !== c.length || a.some((v, j) => v !== c[j])) divergedRows++;\n }\n const divergedRowRate = divergedRows / chunks.length;\n return {\n pass: step0Mismatches === 0 && divergedRowRate <= 0.25,\n detail: { B: chunks.length, step0Mismatches, divergedRows, divergedRowRate },\n };\n } finally {\n weights.buffer.destroy();\n }\n});\n\nconst ROUNDS = 7;\nconst STEPS = 50;\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\n// Full-e2e A/B in ONE session (translateBatch incl. compaction + readbacks —\n// the honest end-user number, immune to the cross-session thermal drift that\n// makes bench-matrix deltas unusable). Decode-only medians; the encoder is\n// identical in both arms.\nregisterTest('ffn_splitk_e2e_ab', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const weights = await loadWeights(device, '/weights', {\n targetDtype: 'f16', lmHeadQ8: true, ffnWT: true, projWT: true,\n });\n try {\n const tok = await loadTokenizer();\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n const ARMS = [\n { name: 'off', opts: { ffnSplitK: 0 } },\n { name: 'sk8', opts: {} }, // auto = sk8 at B >= 32\n ];\n const table = [];\n for (const B of [64, 128]) {\n const group = chunks.slice(0, B);\n const timeArm = async ({ opts }) => {\n const { metrics } = await translateBatch(gctx, weights, tok, group, opts);\n return metrics.decodeMs;\n };\n for (const arm of ARMS) await timeArm(arm); // warmup\n const times = Object.fromEntries(ARMS.map((a) => [a.name, []]));\n for (let r = 0; r < 5; r++) {\n for (const arm of ARMS) times[arm.name].push(await timeArm(arm));\n }\n const off = median(times.off);\n const sk8 = median(times.sk8);\n table.push({\n B,\n offDecodeMs: Number(off.toFixed(1)),\n sk8DecodeMs: Number(sk8.toFixed(1)),\n deltaPct: Number((100 * (sk8 - off) / off).toFixed(1)),\n runs: times,\n });\n }\n return { pass: true, detail: { table } };\n } finally {\n weights.buffer.destroy();\n }\n});\n\nregisterTest('ffn_splitk_sweep', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const weights = await loadWeights(device, '/weights', {\n targetDtype: 'f16', lmHeadQ8: true, ffnWT: true, projWT: true,\n });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n\n // b64 sits below PROJ_TILED_MIN_B: its baseline is the production GEMV\n // route, and the tiled arms force tiledProj to see whether split-K\n // changes the b64 gemv-vs-tiled verdict. b128 is already tiled.\n const ARMS_BY_B = {\n 16: [\n { name: 'gemv', opts: {} },\n { name: 'tiled_sk4', opts: { tiledProj: ['fc1', 'fc2'], ffnSplitK: 4 } },\n { name: 'tiled_sk8', opts: { tiledProj: ['fc1', 'fc2'], ffnSplitK: 8 } },\n ],\n 32: [\n { name: 'gemv', opts: {} },\n { name: 'tiled_sk4', opts: { tiledProj: ['fc1', 'fc2'], ffnSplitK: 4 } },\n { name: 'tiled_sk8', opts: { tiledProj: ['fc1', 'fc2'], ffnSplitK: 8 } },\n ],\n 64: [\n { name: 'gemv', opts: {} },\n { name: 'tiled', opts: { tiledProj: ['fc1', 'fc2'], ffnSplitK: 0 } },\n { name: 'tiled_sk4', opts: { tiledProj: ['fc1', 'fc2'], ffnSplitK: 4 } },\n { name: 'tiled_sk8', opts: { tiledProj: ['fc1', 'fc2'], ffnSplitK: 8 } },\n ],\n 128: [\n { name: 'off', opts: { ffnSplitK: 0 } },\n { name: 'sk4', opts: { ffnSplitK: 4 } },\n { name: 'sk8', opts: { ffnSplitK: 8 } },\n { name: 'sk16', opts: { ffnSplitK: 16 } },\n { name: 'fc2only_sk8', opts: { ffnSplitK: { fc1: 0, fc2: 8 } } },\n ],\n };\n const table = [];\n for (const [Bstr, arms] of Object.entries(ARMS_BY_B)) {\n const batch = await tokenizeBatch(tok, chunks.slice(0, Number(Bstr)));\n const encRun = await runEncoder(gctx, weights, batch);\n await device.queue.onSubmittedWorkDone();\n try {\n const timeArm = async ({ opts }) => {\n const state = createDecodeState(gctx, weights, {\n B: batch.B, S: encRun.S, maxSteps: STEPS, ...opts,\n });\n const { stepUs } = await timeDecodeSteps(gctx, weights, encRun, state, { steps: STEPS });\n state.destroy();\n return stepUs;\n };\n for (const arm of arms) await timeArm(arm); // pipeline warmup\n const times = Object.fromEntries(arms.map((a) => [a.name, []]));\n for (let r = 0; r < ROUNDS; r++) {\n for (const arm of arms) times[arm.name].push(await timeArm(arm));\n }\n table.push({\n B: batch.B,\n medians: Object.fromEntries(arms.map((a) => [a.name, Number(median(times[a.name]).toFixed(1))])),\n runs: times,\n });\n } finally {\n encRun.arena.destroy();\n }\n }\n return { pass: true, detail: { steps: STEPS, rounds: ROUNDS, table } };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["mulberry32","seed","a","t","splitkKernelCase","ctx","M","K","N","sk","silu","tol","device","rng","rand16","n","half","i","f32ToF16","expandF16","x","w","b","want","matmulRef","ro","rw","nz","splitKParts","xBuf","createBuffer","wBuf","bBuf","partsBuf","yBuf","encoder","pass","d1","dispatchGemm","d2","dispatchGemmReduce","buf","got","readback","failures","maxAbsDiff","compareLanes","registerTest","gctx","weights","loadWeights","tok","loadTokenizer","chunks","presetChunks","off","translateBatch","on","step0Mismatches","divergedRows","c","v","j","divergedRowRate","ROUNDS","STEPS","median","xs","s","m","ARMS","table","B","group","timeArm","opts","metrics","arm","times","r","sk8","ARMS_BY_B","Bstr","arms","batch","tokenizeBatch","encRun","runEncoder","state","createDecodeState","stepUs","timeDecodeSteps"],"mappings":"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"}
assets/fuse_ln-DCGuPhdx.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as y}from"./debug-Cn7EHWtJ.js";import{c as Y,r as M,a as Q}from"./gpu-utils-BTh3AGTJ.js";import{k as $}from"./pipelines-DD24nEJg.js";import{l as G}from"./weights-B-okS09o.js";import{l as O,t as I}from"./tokenizer-Ex1u7wXD.js";import{t as E}from"./generate-C4ruG1zm.js";import{r as J}from"./encoder-DX8MOfcH.js";import{c as V}from"./decoder-DI6VDxxO.js";import{t as X}from"./profile-DdyBUdtB.js";import{p as v}from"./bench-C8ITpm5I.js";import{m as Z,a as K}from"./math-DNG-wiC0.js";import{e as A,f as N}from"./f16-wKKZr58e.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./constants-C8VbFpic.js";import"./shapes-BCQ9D81L.js";import"./chapter3k-Bxq8ds-a.js";function tt(s){let t=s>>>0;return()=>{t=t+1831565813|0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}function L(s){const t=new Uint16Array(s.length);for(let e=0;e<s.length;e++)t[e]=N(s[e]);return{half:t,ref:A(t)}}async function x(s,{M:t,K:e,N:o,tol:f,seed:u}){const{device:a}=s,g=tt(u),l=(p,B=1)=>{const C=new Float32Array(p);for(let U=0;U<p;U++)C[U]=Math.fround((g()-.5)*B);return C},n=(p,B)=>L(l(p,B)),d=n(t*e),i=n(e*o),c=n(o),r=n(t*o,4),m=n(o,2),w=n(o),W=Z(d.ref,i.ref,c.ref,{M:t,K:e,N:o}),q=A(L(W).half),T=K(q,r.ref,m.ref,w.ref,{rows:t,d:o}),z=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,h=[d,i,c,r,m,w].map(p=>Y(a,p.half,z)),b=a.createBuffer({size:t*o*2,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC}),_=a.createCommandEncoder(),D=_.beginComputePass(),{scratch:j}=$(a,D,{x:h[0],w:h[1],b:h[2],r:h[3],gamma:h[4],beta:h[5],y:b,M:t,K:e,N:o,flags:{t:"f16"}});D.end(),a.queue.submit([_.finish()]);const F=A(new Uint16Array(await M(a,b,t*o*2)));for(const p of[...h,b,...j])p.destroy();const{failures:k,maxAbsDiff:H,worst:S}=Q(F,T,f);return{pass:k===0,detail:{M:t,K:e,N:o,tol:f,failures:k,maxAbsDiff:String(H),...k>0?{worst:S,got:String(F[S]),want:String(T[S])}:{}}}}y("rowln_kernel_out",s=>s.hasF16?x(s,{M:5,K:448,N:448,tol:.02,seed:601}):{skip:!0,reason:"no shader-f16"});y("rowln_kernel_fc2",s=>s.hasF16?x(s,{M:3,K:1792,N:448,tol:.02,seed:602}):{skip:!0,reason:"no shader-f16"});y("fuse_ln_equiv",async s=>{const{device:t}=s;if(!s.hasF16)return{skip:!0,reason:"no shader-f16"};const e={device:t,dtype:"f16",limits:s.limits},o=await G(t,"/weights",{targetDtype:"f16",ffnWT:!0});try{const f=await O(),u=[...v("file23k")].slice(0,8),a=await E(e,o,f,u,{fuseLn:"off"}),g=await E(e,o,f,u,{fuseLn:"on"});let l=0,n=0;for(let i=0;i<u.length;i++){const c=a.rows[i].ids,r=g.rows[i].ids;c[1]!==r[1]&&l++,(c.length!==r.length||c.some((m,w)=>m!==r[w]))&&n++}const d=n/u.length;return{pass:l===0&&d<=.25,detail:{B:u.length,step0Mismatches:l,divergedRows:n,divergedRowRate:d}}}finally{o.buffer.destroy()}});const P=7,R=50,et=[1,4,8,16,32],st=s=>{const t=[...s].sort((o,f)=>o-f),e=t.length>>1;return t.length%2?t[e]:(t[e-1]+t[e])/2};y("fuse_ln_sweep",async s=>{const{device:t}=s;if(!s.hasF16)return{skip:!0,reason:"no shader-f16"};const e=await G(t,"/weights",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0});try{const o=await O(),f={device:t,dtype:"f16",limits:s.limits},u=[...v("file23k")].sort((l,n)=>n.length-l.length),a=[{name:"off",fuseLn:"off"},{name:"fused",fuseLn:"on"}],g=[];for(const l of et){const n=await I(o,u.slice(0,l)),d=await J(f,e,n);await t.queue.onSubmittedWorkDone();try{const i=async({fuseLn:r})=>{const m=V(f,e,{B:n.B,S:d.S,maxSteps:R,fuseLn:r,decodeMega:"off"}),{stepUs:w}=await X(f,e,d,m,{steps:R});return m.destroy(),w};for(const r of a)await i(r);const c=Object.fromEntries(a.map(r=>[r.name,[]]));for(let r=0;r<P;r++)for(const m of a)c[m.name].push(await i(m));g.push({B:n.B,...Object.fromEntries(a.map(r=>[`${r.name}StepUs`,Number(st(c[r.name]).toFixed(1))])),runs:c})}finally{d.arena.destroy()}}return{pass:!0,detail:{steps:R,rounds:P,table:g}}}finally{e.buffer.destroy()}});
2
+ //# sourceMappingURL=fuse_ln-DCGuPhdx.js.map
assets/fuse_ln-DCGuPhdx.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"fuse_ln-DCGuPhdx.js","sources":["../../src/debug/tests/fuse_ln.js"],"sourcesContent":["// Fused projection + residual + LayerNorm (gemm_row_ln.wgsl):\n// rowln_kernel_* GPU kernel vs the JS f64 reference chain (matmulRef →\n// f16 round → addLayerNormRef) at both site shapes\n// (K=448 out-proj, K=1792 fc2). Tolerance-based: f32\n// accumulation + one f16 rounding.\n// fuse_ln_equiv e2e fuseLn on-vs-off wiring gate (proj_sweep-style):\n// step-0 tokens must match exactly on every row (a wiring\n// bug corrupts everything from step 0); whole-row\n// divergence ≤ 25% (f32-ULP near-tie flips are legal).\n// fuse_ln_sweep interleaved step-wall A/B at B=1..32 — sets\n// FUSE_LN_MAX_B in decoder.js (fusion trades 6 dispatches\n// for one-workgroup-per-row GEMM occupancy).\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback, compareLanes } from '../gpu-utils.js';\nimport { dispatchGemmRowLn } from '../../engine/pipelines.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer, tokenizeBatch } from '../../engine/tokenizer.js';\nimport { translateBatch } from '../../engine/generate.js';\nimport { runEncoder } from '../../engine/encoder.js';\nimport { createDecodeState } from '../../engine/decoder.js';\nimport { timeDecodeSteps } from '../../bench/profile.js';\nimport { presetChunks } from '../../bench/bench.js';\nimport { matmulRef, addLayerNormRef } from '../../reference/math.js';\nimport { f32ToF16, expandF16 } from '../../engine/f16.js';\n\nfunction mulberry32(seed) {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nfunction toF16(f32arr) {\n const half = new Uint16Array(f32arr.length);\n for (let i = 0; i < f32arr.length; i++) half[i] = f32ToF16(f32arr[i]);\n return { half, ref: expandF16(half) };\n}\n\nasync function rowLnCase(ctx, { M, K, N, tol, seed }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const rand = (n, scale = 1) => {\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) out[i] = Math.fround((rng() - 0.5) * scale);\n return out;\n };\n const make = (n, scale) => toF16(rand(n, scale));\n const x = make(M * K);\n const w = make(K * N);\n const b = make(N);\n const r = make(M * N, 4); // residual dominates post-LN like real hidden states\n const gamma = make(N, 2);\n const beta = make(N);\n\n // Reference chain mirrors the kernel: f32/f64 GEMM+bias, ROUND THROUGH f16\n // (the unfused path's Y-buffer round trip), then the f64 add+LN.\n const gemm = matmulRef(x.ref, w.ref, b.ref, { M, K, N });\n const gemm16 = expandF16(toF16(gemm).half);\n const want = addLayerNormRef(gemm16, r.ref, gamma.ref, beta.ref, { rows: M, d: N });\n\n const ro = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const bufs = [x, w, b, r, gamma, beta].map((v) => createBuffer(device, v.half, ro));\n const yBuf = device.createBuffer({\n size: M * N * 2, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass();\n const { scratch } = dispatchGemmRowLn(device, pass, {\n x: bufs[0], w: bufs[1], b: bufs[2], r: bufs[3], gamma: bufs[4], beta: bufs[5],\n y: yBuf, M, K, N, flags: { t: 'f16' },\n });\n pass.end();\n device.queue.submit([encoder.finish()]);\n const got = expandF16(new Uint16Array(await readback(device, yBuf, M * N * 2)));\n for (const buf of [...bufs, yBuf, ...scratch]) buf.destroy();\n\n const { failures, maxAbsDiff, worst } = compareLanes(got, want, tol);\n return {\n pass: failures === 0,\n detail: {\n M, K, N, tol, failures,\n maxAbsDiff: String(maxAbsDiff),\n ...(failures > 0 ? { worst, got: String(got[worst]), want: String(want[worst]) } : {}),\n },\n };\n}\n\nregisterTest('rowln_kernel_out', (ctx) => (ctx.hasF16\n ? rowLnCase(ctx, { M: 5, K: 448, N: 448, tol: 0.02, seed: 601 })\n : { skip: true, reason: 'no shader-f16' }));\nregisterTest('rowln_kernel_fc2', (ctx) => (ctx.hasF16\n ? rowLnCase(ctx, { M: 3, K: 1792, N: 448, tol: 0.02, seed: 602 })\n : { skip: true, reason: 'no shader-f16' }));\n\nregisterTest('fuse_ln_equiv', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const weights = await loadWeights(device, '/weights', { targetDtype: 'f16', ffnWT: true });\n try {\n const tok = await loadTokenizer();\n const chunks = [...presetChunks('file23k')].slice(0, 8);\n const off = await translateBatch(gctx, weights, tok, chunks, { fuseLn: 'off' });\n const on = await translateBatch(gctx, weights, tok, chunks, { fuseLn: 'on' });\n let step0Mismatches = 0;\n let divergedRows = 0;\n for (let i = 0; i < chunks.length; i++) {\n const a = off.rows[i].ids;\n const c = on.rows[i].ids;\n if (a[1] !== c[1]) step0Mismatches++; // ids[0] is decoder_start\n if (a.length !== c.length || a.some((v, j) => v !== c[j])) divergedRows++;\n }\n const divergedRowRate = divergedRows / chunks.length;\n return {\n pass: step0Mismatches === 0 && divergedRowRate <= 0.25,\n detail: { B: chunks.length, step0Mismatches, divergedRows, divergedRowRate },\n };\n } finally {\n weights.buffer.destroy();\n }\n});\n\nconst ROUNDS = 7;\nconst STEPS = 50;\nconst BATCHES = [1, 4, 8, 16, 32];\nconst median = (xs) => {\n const s = [...xs].sort((a, b) => a - b);\n const m = s.length >> 1;\n return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;\n};\n\nregisterTest('fuse_ln_sweep', async (ctx) => {\n const { device } = ctx;\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const weights = await loadWeights(device, '/weights', { targetDtype: 'f16', lmHeadQ8: true, ffnWT: true });\n try {\n const tok = await loadTokenizer();\n const gctx = { device, dtype: 'f16', limits: ctx.limits };\n const chunks = [...presetChunks('file23k')].sort((a, b) => b.length - a.length);\n\n const ARMS = [\n { name: 'off', fuseLn: 'off' },\n { name: 'fused', fuseLn: 'on' },\n ];\n const table = [];\n for (const B of BATCHES) {\n const batch = await tokenizeBatch(tok, chunks.slice(0, B));\n const encRun = await runEncoder(gctx, weights, batch);\n await device.queue.onSubmittedWorkDone();\n try {\n const timeArm = async ({ fuseLn }) => {\n const state = createDecodeState(gctx, weights, {\n // mega off: at B ≤ 4 the megakernel replaces these sites entirely\n // and would make the fuseLn arms identical.\n B: batch.B, S: encRun.S, maxSteps: STEPS, fuseLn, decodeMega: 'off',\n });\n const { stepUs } = await timeDecodeSteps(gctx, weights, encRun, state, { steps: STEPS });\n state.destroy();\n return stepUs;\n };\n for (const arm of ARMS) await timeArm(arm); // pipeline warmup\n const times = Object.fromEntries(ARMS.map((a) => [a.name, []]));\n for (let r = 0; r < ROUNDS; r++) {\n for (const arm of ARMS) times[arm.name].push(await timeArm(arm));\n }\n table.push({\n B: batch.B,\n ...Object.fromEntries(ARMS.map((a) => [`${a.name}StepUs`, Number(median(times[a.name]).toFixed(1))])),\n runs: times,\n });\n } finally {\n encRun.arena.destroy();\n }\n }\n return { pass: true, detail: { steps: STEPS, rounds: ROUNDS, table } };\n } finally {\n weights.buffer.destroy();\n }\n});\n"],"names":["mulberry32","seed","a","t","toF16","f32arr","half","i","f32ToF16","expandF16","rowLnCase","ctx","M","K","N","tol","device","rng","rand","n","scale","out","make","x","w","b","gamma","beta","gemm","matmulRef","gemm16","want","addLayerNormRef","ro","bufs","v","createBuffer","yBuf","encoder","pass","scratch","dispatchGemmRowLn","got","readback","buf","failures","maxAbsDiff","worst","compareLanes","registerTest","gctx","weights","loadWeights","tok","loadTokenizer","chunks","presetChunks","off","translateBatch","on","step0Mismatches","divergedRows","c","j","divergedRowRate","ROUNDS","STEPS","BATCHES","median","xs","s","m","ARMS","table","B","batch","tokenizeBatch","encRun","runEncoder","timeArm","fuseLn","state","createDecodeState","stepUs","timeDecodeSteps","arm","times"],"mappings":"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"}
assets/gemm-CQmO2bw5.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as f}from"./debug-Cn7EHWtJ.js";import{c as N,r as Z,a as $}from"./gpu-utils-BTh3AGTJ.js";import{r as ee}from"./pipelines-DD24nEJg.js";import{q as ue}from"./weights-B-okS09o.js";import{m as te}from"./math-DNG-wiC0.js";import{e as W,f as ae}from"./f16-wKKZr58e.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./constants-C8VbFpic.js";import"./shapes-BCQ9D81L.js";function se(e){let s=e>>>0;return()=>{s=s+1831565813|0;let t=Math.imul(s^s>>>15,1|s);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296}}function T(e,s){const t=new Float32Array(e);for(let r=0;r<e;r++)t[r]=Math.fround(s()-.5);return t}function j(e){const s=new Uint16Array(e.length);for(let t=0;t<e.length;t++)s[t]=ae(e[t]);return{half:s,ref:W(s)}}function re(e,s,t){const r=new e.constructor(e.length);for(let o=0;o<s;o++)for(let l=0;l<t;l++)r[l*s+o]=e[o*t+l];return r}async function u(e,{M:s,K:t,N:r,t:o,outT:l=o,bias:w=!1,silu:m=!1,wt:v=!1,gemv:P=!1,tiled:D=!1,tiledV:O,tm8:H=!1,sh16:i=!1,dbuf:p=!1,bkk:B,sg:J=!1,tol:k,seed:I}){const{device:d}=e,F=se(I),q=T(s*t,F),S=T(t*r,F),U=w?T(r,F):null;let C=q,M=S,h=U,z=q,E=S,Y=U;o==="f16"&&({half:C,ref:z}=j(q),{half:M,ref:E}=j(S),w&&({half:h,ref:Y}=j(U))),v&&(M=re(M,t,r));const x=te(z,E,Y,{M:s,K:t,N:r,silu:m}),y=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,A=N(d,C,y),Q=N(d,M,y),V=w?N(d,h,y):null,R=s*r*(l==="f16"?2:4),L=d.createBuffer({size:Math.ceil(R/4)*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});ee(d,{x:A,w:Q,b:V,y:L,M:s,K:t,N:r,flags:{t:o,outT:l,silu:m,wt:v,gemv:P,tiled:D,tiledV:O,tm8:H,sh16:i,dbuf:p,bkk:B,sg:J}});const G=await Z(d,L,R),_=l==="f16"?W(new Uint16Array(G)):new Float32Array(G);for(const fe of[A,Q,V,L])fe?.destroy();const{failures:g,maxAbsDiff:X,worst:K}=$(_,x,k);return{pass:g===0,detail:{M:s,K:t,N:r,t:o,outT:l,bias:w,silu:m,wt:v,gemv:P,tiled:D,tol:k,...D?{tiledV:O??"auto",tm8:H,sh16:i,dbuf:p,bkk:B??16}:{},failures:g,maxAbsDiff:String(X),...g>0?{worst:K,got:String(_[K]),want:String(x[K])}:{}}}}function a(e,s){f(e,t=>t.hasF16?u(t,{...s,t:"f16"}):{skip:!0,reason:"no shader-f16"})}function b(e,s){f(e,t=>t.hasF16?s(t):{skip:!0,reason:"no shader-f16"})}a("gemm_f16_nobias",{M:3,K:448,N:1344,tol:.01,seed:101});a("gemm_f16_bias",{M:5,K:1792,N:448,bias:!0,tol:.02,seed:102});a("gemm_f16_bias_silu",{M:2,K:448,N:1792,bias:!0,silu:!0,tol:.01,seed:103});a("gemm_f16_outf32_vocab",{M:2,K:448,N:24e3,outT:"f32",tol:.01,seed:104});a("gemm_f16_wt_outf32_vocab",{M:2,K:448,N:24e3,outT:"f32",wt:!0,tol:.01,seed:106});f("gemm_f32_bias",e=>u(e,{M:3,K:448,N:448,t:"f32",bias:!0,tol:1e-5,seed:105}));a("gemv_f16_wt_outf32_vocab",{M:3,K:448,N:24e3,outT:"f32",wt:!0,gemv:!0,tol:.01,seed:201});a("gemv_f16_qkv",{M:3,K:448,N:1344,gemv:!0,tol:.01,seed:202});a("gemv_f16_fc1_bias_silu",{M:2,K:448,N:1792,bias:!0,silu:!0,gemv:!0,tol:.01,seed:203});a("gemv_f16_fc2_bias",{M:5,K:1792,N:448,bias:!0,gemv:!0,tol:.02,seed:204});a("tiled_f16_qkv",{M:96,K:448,N:1344,bias:!0,tiled:!0,tol:.01,seed:301});a("tiled_f16_fc1_bias_silu",{M:64,K:448,N:1792,bias:!0,silu:!0,tiled:!0,tol:.01,seed:302});a("tiled_f16_fc2_bias",{M:64,K:1792,N:448,bias:!0,tiled:!0,tol:.02,seed:303});a("tiled_f16_wt_outf32_vocab",{M:64,K:448,N:24e3,outT:"f32",wt:!0,tiled:!0,tol:.01,seed:304});f("tiled_f32_bias_tails",e=>u(e,{M:33,K:100,N:452,t:"f32",bias:!0,tiled:!0,tol:1e-5,seed:305}));f("tiled_f32_wt_tails",e=>u(e,{M:65,K:448,N:1002,t:"f32",wt:!0,tiled:!0,tol:1e-5,seed:306}));a("tiled1_f16_fc1_bias_silu",{M:64,K:448,N:1792,bias:!0,silu:!0,tiled:!0,tiledV:1,tol:.01,seed:302});f("tiled1_f32_wt_tails",e=>u(e,{M:65,K:448,N:1002,t:"f32",wt:!0,tiled:!0,tiledV:1,tol:1e-5,seed:306}));a("tiled2_tm8_f16_fc1_bias_silu",{M:96,K:448,N:1792,bias:!0,silu:!0,tiled:!0,tm8:!0,tol:.01,seed:307});a("tiled2_tm8_f16_wt_outf32_vocab",{M:65,K:448,N:24e3,outT:"f32",wt:!0,tiled:!0,tm8:!0,tol:.01,seed:308});f("tiled_f32_kodd_fallback",e=>u(e,{M:33,K:98,N:452,t:"f32",bias:!0,tiled:!0,tol:1e-5,seed:309}));a("tiled2_sh16_f16_fc1_bias_silu",{M:96,K:448,N:1792,bias:!0,silu:!0,tiled:!0,tm8:!0,sh16:!0,tol:.01,seed:310});a("tiled2_dbuf_f16_fc2_bias_tail",{M:65,K:1792,N:448,bias:!0,tiled:!0,tm8:!0,dbuf:!0,tol:.02,seed:311});a("tiled2_sh16dbuf_bk32_f16_qkv_tail",{M:65,K:448,N:1344,bias:!0,tiled:!0,tm8:!0,sh16:!0,dbuf:!0,bkk:32,tol:.01,seed:312});f("tiled2_dbuf_f32_tails",e=>u(e,{M:33,K:100,N:452,t:"f32",bias:!0,tiled:!0,dbuf:!0,tol:1e-5,seed:313}));async function c(e,{M:s,K:t,N:r,t:o,outT:l="f32",gemv:w=!1,bias:m=!1,silu:v=!1,tm8:P=!1,sg:D=!1,tol:O,seed:H}){const{device:i}=e,p=se(H),B=T(s*t,p),J=T(t*r,p),k=m?T(r,p):null;let I=B,d=B,F=k,q=k;o==="f16"&&({half:I,ref:d}=j(B),m&&({half:F,ref:q}=j(k)));const{packed:S,scales:U}=ue(re(J,t,r),r,t),C=new Float32Array(t*r);for(let _=0;_<r;_++)for(let g=0;g<t;g++){let K=S[_*t+g>>2]>>>8*(_*t+g&3)&255;K>127&&(K-=256),C[g*r+_]=Math.fround(K*U[_])}const M=te(d,C,q,{M:s,K:t,N:r,silu:v}),h=GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,z=N(i,I,h),E=N(i,S,h),Y=N(i,U,h),x=m?N(i,F,h):null,y=s*r*(l==="f16"?2:4),A=i.createBuffer({size:Math.ceil(y/4)*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});ee(i,{x:z,w:E,b:x,y:A,M:s,K:t,N:r,scales:Y,flags:{t:o,outT:l,wt:!0,wq8:!0,silu:v,sg:D,...w?{gemv:!0}:{tiled:!0,tm8:P}}});const Q=await Z(i,A,y),V=l==="f16"?W(new Uint16Array(Q)):new Float32Array(Q);for(const _ of[z,E,Y,x,A])_?.destroy();const{failures:R,maxAbsDiff:L,worst:G}=$(V,M,O);return{pass:R===0,detail:{M:s,K:t,N:r,t:o,outT:l,wq8:!0,gemv:w,bias:m,silu:v,tm8:P,tol:O,failures:R,maxAbsDiff:String(L),...R>0?{worst:G,got:String(V[G]),want:String(M[G])}:{}}}}b("wq8_f16_vocab",e=>c(e,{M:64,K:448,N:24e3,t:"f16",tol:.001,seed:401}));b("wq8_tm8_f16_vocab_tails",e=>c(e,{M:65,K:448,N:24e3,t:"f16",tm8:!0,tol:.001,seed:402}));f("wq8_f32_tails",e=>c(e,{M:33,K:448,N:1002,t:"f32",tol:.001,seed:403}));b("wq8_gemv_f16_fc1_bias_silu",e=>c(e,{M:3,K:448,N:1792,t:"f16",outT:"f16",gemv:!0,bias:!0,silu:!0,tol:.01,seed:404}));b("wq8_gemv_f16_fc2_bias",e=>c(e,{M:5,K:1792,N:448,t:"f16",outT:"f16",gemv:!0,bias:!0,tol:.02,seed:405}));b("wq8_tiled_f16_fc1_bias_silu",e=>c(e,{M:96,K:448,N:1792,t:"f16",outT:"f16",bias:!0,silu:!0,tm8:!0,tol:.01,seed:406}));f("gemv_f32_bias_tail",e=>u(e,{M:3,K:448,N:452,t:"f32",bias:!0,gemv:!0,tol:1e-5,seed:205}));f("gemv_f32_wt_tail",e=>u(e,{M:2,K:448,N:1002,t:"f32",wt:!0,gemv:!0,tol:1e-5,seed:206}));const n=e=>e.hasF16?e.hasSubgroups?(e.subgroupMinSize??0)<16?{skip:!0,reason:"subgroupMinSize < TK 16"}:null:{skip:!0,reason:"subgroups feature unavailable"}:{skip:!0,reason:"no shader-f16"};f("gemv_sg_f16_wt_qkv_m3",e=>n(e)??u(e,{M:3,K:448,N:1344,t:"f16",wt:!0,gemv:!0,sg:!0,tol:.01,seed:401}));f("gemv_sg_f16_wt_fc1_silu_m2",e=>n(e)??u(e,{M:2,K:448,N:1792,t:"f16",bias:!0,silu:!0,wt:!0,gemv:!0,sg:!0,tol:.01,seed:402}));f("gemv_sg_f16_wt_fc2_m5",e=>n(e)??u(e,{M:5,K:1792,N:448,t:"f16",bias:!0,wt:!0,gemv:!0,sg:!0,tol:.02,seed:403}));f("gemv_sg_f16_wt_vocab_m5",e=>n(e)??u(e,{M:5,K:448,N:24e3,t:"f16",outT:"f32",wt:!0,gemv:!0,sg:!0,tol:.01,seed:404}));f("gemv_sg_f16_wt_h60_qkv_m3",e=>n(e)??u(e,{M:3,K:576,N:1728,t:"f16",wt:!0,gemv:!0,sg:!0,tol:.01,seed:411}));f("gemv_sg_f16_wt_h60_fc1_silu_m2",e=>n(e)??u(e,{M:2,K:576,N:2304,t:"f16",bias:!0,silu:!0,wt:!0,gemv:!0,sg:!0,tol:.01,seed:412}));f("gemv_sg_f16_wt_h60_fc2_m5",e=>n(e)??u(e,{M:5,K:2304,N:576,t:"f16",bias:!0,wt:!0,gemv:!0,sg:!0,tol:.02,seed:413}));f("gemv_sg_f16_wt_h60_vocab_m3",e=>n(e)??u(e,{M:3,K:576,N:24e3,t:"f16",outT:"f32",wt:!0,gemv:!0,sg:!0,tol:.01,seed:414}));f("wq8_sg_gemv_vocab_m3",e=>n(e)??c(e,{M:3,K:448,N:24e3,t:"f16",gemv:!0,sg:!0,tol:.001,seed:421}));f("wq8_sg_gemv_vocab_h60_m3",e=>n(e)??c(e,{M:3,K:576,N:24e3,t:"f16",gemv:!0,sg:!0,tol:.001,seed:422}));b("tiled2_h60_qkv",e=>u(e,{M:96,K:576,N:1728,t:"f16",bias:!0,tiled:!0,tm8:!0,tol:.01,seed:431}));b("tiled2_h60_fc1_silu",e=>u(e,{M:64,K:576,N:2304,t:"f16",bias:!0,silu:!0,tiled:!0,tm8:!0,tol:.01,seed:432}));b("tiled2_h60_fc2",e=>u(e,{M:64,K:2304,N:576,t:"f16",bias:!0,tiled:!0,tm8:!0,tol:.02,seed:433}));
2
+ //# sourceMappingURL=gemm-CQmO2bw5.js.map
assets/gemm-CQmO2bw5.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"gemm-CQmO2bw5.js","sources":["../../src/debug/tests/gemm.js"],"sourcesContent":["// GPU GEMM kernel vs the JS f64 reference (matmulRef), model-shaped sizes.\n// f16 test data is encoded to f16 and decoded back to f32 for the reference\n// input, so ref and GPU see IDENTICAL values — remaining error is only the\n// f32-accumulation-order difference plus (for f16 out) one output rounding.\nimport { registerTest } from '../registry.js';\nimport { createBuffer, readback, compareLanes } from '../gpu-utils.js';\nimport { runGemmOnce } from '../../engine/pipelines.js';\nimport { quantizeQ8Rows } from '../../engine/weights.js';\nimport { matmulRef } from '../../reference/math.js';\nimport { f32ToF16, expandF16 } from '../../engine/f16.js';\n\nfunction mulberry32(seed) {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nfunction randF32(n, rng) {\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) out[i] = Math.fround(rng() - 0.5); // ~±0.5\n return out;\n}\n\n// Encode to f16 for the GPU and decode back to f32 for the reference.\nfunction toF16(f32arr) {\n const half = new Uint16Array(f32arr.length);\n for (let i = 0; i < f32arr.length; i++) half[i] = f32ToF16(f32arr[i]);\n return { half, ref: expandF16(half) };\n}\n\n// [K,N] row-major → [N,K] row-major, same element type (f16 u16 halves\n// transpose losslessly — the values are untouched).\nfunction transposeKN(src, K, N) {\n const out = new src.constructor(src.length);\n for (let k = 0; k < K; k++) {\n for (let n = 0; n < N; n++) out[n * K + k] = src[k * N + n];\n }\n return out;\n}\n\nasync function runCase(ctx, { M, K, N, t, outT = t, bias = false, silu = false, wt = false, gemv = false, tiled = false, tiledV, tm8 = false, sh16 = false, dbuf = false, bkk, sg = false, tol, seed }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const xF = randF32(M * K, rng);\n const wF = randF32(K * N, rng);\n const bF = bias ? randF32(N, rng) : null;\n\n let xData = xF, wData = wF, bData = bF;\n let xRef = xF, wRef = wF, bRef = bF;\n if (t === 'f16') {\n ({ half: xData, ref: xRef } = toF16(xF));\n ({ half: wData, ref: wRef } = toF16(wF));\n if (bias) ({ half: bData, ref: bRef } = toF16(bF));\n }\n // wt: the reference keeps W as [K,N]; the GPU gets the SAME data stored\n // transposed ([N,K] row-major) — proving the wt indexing, nothing else.\n if (wt) wData = transposeKN(wData, K, N);\n const want = matmulRef(xRef, wRef, bRef, { M, K, N, silu });\n\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const xBuf = createBuffer(device, xData, usage);\n const wBuf = createBuffer(device, wData, usage);\n const bBuf = bias ? createBuffer(device, bData, usage) : null;\n const outBytes = M * N * (outT === 'f16' ? 2 : 4);\n const yBuf = device.createBuffer({\n size: Math.ceil(outBytes / 4) * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n\n runGemmOnce(device, { x: xBuf, w: wBuf, b: bBuf, y: yBuf, M, K, N, flags: { t, outT, silu, wt, gemv, tiled, tiledV, tm8, sh16, dbuf, bkk, sg } });\n const raw = await readback(device, yBuf, outBytes);\n const got = outT === 'f16' ? expandF16(new Uint16Array(raw)) : new Float32Array(raw);\n for (const buf of [xBuf, wBuf, bBuf, yBuf]) buf?.destroy();\n\n const { failures, maxAbsDiff, worst } = compareLanes(got, want, tol);\n return {\n pass: failures === 0,\n detail: {\n M, K, N, t, outT, bias, silu, wt, gemv, tiled, tol,\n ...(tiled ? { tiledV: tiledV ?? 'auto', tm8, sh16, dbuf, bkk: bkk ?? 16 } : {}),\n failures,\n maxAbsDiff: String(maxAbsDiff), // string: JSON turns NaN/Infinity into null\n ...(failures > 0 ? { worst, got: String(got[worst]), want: String(want[worst]) } : {}),\n },\n };\n}\n\nfunction registerF16(name, opts) {\n registerTest(name, (ctx) =>\n ctx.hasF16 ? runCase(ctx, { ...opts, t: 'f16' }) : { skip: true, reason: 'no shader-f16' });\n}\n\nfunction registerF16Fn(name, fn) {\n registerTest(name, (ctx) =>\n ctx.hasF16 ? fn(ctx) : { skip: true, reason: 'no shader-f16' });\n}\n\n// Model-shaped f16-storage cases. Tolerances: f32 accumulate keeps GEMM tight;\n// 0.02 for K=1792 sums, 0.01 otherwise (f16 out adds one rounding, covered).\nregisterF16('gemm_f16_nobias', { M: 3, K: 448, N: 1344, tol: 0.01, seed: 101 });\nregisterF16('gemm_f16_bias', { M: 5, K: 1792, N: 448, bias: true, tol: 0.02, seed: 102 });\nregisterF16('gemm_f16_bias_silu', { M: 2, K: 448, N: 1792, bias: true, silu: true, tol: 0.01, seed: 103 });\nregisterF16('gemm_f16_outf32_vocab', { M: 2, K: 448, N: 24000, outT: 'f32', tol: 0.01, seed: 104 });\n// LM-head shape: W stored transposed [N,K] = shared.weight [24000,448].\nregisterF16('gemm_f16_wt_outf32_vocab', { M: 2, K: 448, N: 24000, outT: 'f32', wt: true, tol: 0.01, seed: 106 });\n\n// f32-storage fallback-mode sanity.\nregisterTest('gemm_f32_bias', (ctx) =>\n runCase(ctx, { M: 3, K: 448, N: 448, t: 'f32', bias: true, tol: 1e-5, seed: 105 }));\n\n// GEMV-style small-M variant (gemm_gemv.wgsl, Task 17) — decode-step shapes.\n// WT/vec4-K path (lm_head) and NWT/vec4-N path (projections), plus the tie-in\n// combos (bias+silu for fc1, f32 storage sanity). Odd M exercises grid y;\n// K=1792 covers lanes with K/4 not divisible by TK.\nregisterF16('gemv_f16_wt_outf32_vocab', { M: 3, K: 448, N: 24000, outT: 'f32', wt: true, gemv: true, tol: 0.01, seed: 201 });\nregisterF16('gemv_f16_qkv', { M: 3, K: 448, N: 1344, gemv: true, tol: 0.01, seed: 202 });\nregisterF16('gemv_f16_fc1_bias_silu', { M: 2, K: 448, N: 1792, bias: true, silu: true, gemv: true, tol: 0.01, seed: 203 });\nregisterF16('gemv_f16_fc2_bias', { M: 5, K: 1792, N: 448, bias: true, gemv: true, tol: 0.02, seed: 204 });\n// Tiled variant (gemm_tiled.wgsl) — encoder shapes at file-workload M plus\n// the lm_head WT shape. M=96 exercises multi-row workgroup grids; the f32\n// tail case hits all three tails at once (M=33 %64, N=452 %64, K=100 %16).\nregisterF16('tiled_f16_qkv', { M: 96, K: 448, N: 1344, bias: true, tiled: true, tol: 0.01, seed: 301 });\nregisterF16('tiled_f16_fc1_bias_silu', { M: 64, K: 448, N: 1792, bias: true, silu: true, tiled: true, tol: 0.01, seed: 302 });\nregisterF16('tiled_f16_fc2_bias', { M: 64, K: 1792, N: 448, bias: true, tiled: true, tol: 0.02, seed: 303 });\nregisterF16('tiled_f16_wt_outf32_vocab', { M: 64, K: 448, N: 24000, outT: 'f32', wt: true, tiled: true, tol: 0.01, seed: 304 });\nregisterTest('tiled_f32_bias_tails', (ctx) =>\n runCase(ctx, { M: 33, K: 100, N: 452, t: 'f32', bias: true, tiled: true, tol: 1e-5, seed: 305 }));\nregisterTest('tiled_f32_wt_tails', (ctx) =>\n runCase(ctx, { M: 65, K: 448, N: 1002, t: 'f32', wt: true, tiled: true, tol: 1e-5, seed: 306 }));\n// The cases above auto-route to v2 (all model shapes are vec4-eligible).\n// Below: v1 forced (fallback kernel must stay correct), the v2 8×4 subtile,\n// and a K%4!=0 shape that exercises the auto-fallback to v1.\nregisterF16('tiled1_f16_fc1_bias_silu', { M: 64, K: 448, N: 1792, bias: true, silu: true, tiled: true, tiledV: 1, tol: 0.01, seed: 302 });\nregisterTest('tiled1_f32_wt_tails', (ctx) =>\n runCase(ctx, { M: 65, K: 448, N: 1002, t: 'f32', wt: true, tiled: true, tiledV: 1, tol: 1e-5, seed: 306 }));\nregisterF16('tiled2_tm8_f16_fc1_bias_silu', { M: 96, K: 448, N: 1792, bias: true, silu: true, tiled: true, tm8: true, tol: 0.01, seed: 307 });\nregisterF16('tiled2_tm8_f16_wt_outf32_vocab', { M: 65, K: 448, N: 24000, outT: 'f32', wt: true, tiled: true, tm8: true, tol: 0.01, seed: 308 });\nregisterTest('tiled_f32_kodd_fallback', (ctx) =>\n runCase(ctx, { M: 33, K: 98, N: 452, t: 'f32', bias: true, tiled: true, tol: 1e-5, seed: 309 }));\n\n// v3 staging (gemm_tiled2 SH16/DBUF — encoder GEMMs): f16 shared tiles must\n// be bit-exact vs the f32-shared kernel (f16-origin values round-trip), so\n// tolerances stay the plain-tiled ones. Cases cover each flag alone, the\n// combined encoder config at BK=32, M tails, and dbuf on f32/tm4.\nregisterF16('tiled2_sh16_f16_fc1_bias_silu', { M: 96, K: 448, N: 1792, bias: true, silu: true, tiled: true, tm8: true, sh16: true, tol: 0.01, seed: 310 });\nregisterF16('tiled2_dbuf_f16_fc2_bias_tail', { M: 65, K: 1792, N: 448, bias: true, tiled: true, tm8: true, dbuf: true, tol: 0.02, seed: 311 });\nregisterF16('tiled2_sh16dbuf_bk32_f16_qkv_tail', { M: 65, K: 448, N: 1344, bias: true, tiled: true, tm8: true, sh16: true, dbuf: true, bkk: 32, tol: 0.01, seed: 312 });\nregisterTest('tiled2_dbuf_f32_tails', (ctx) =>\n runCase(ctx, { M: 33, K: 100, N: 452, t: 'f32', bias: true, tiled: true, dbuf: true, tol: 1e-5, seed: 313 }));\n\n// W8A16 int8 path (gemm_tiled2 WQ8): W quantized per-N-row via\n// quantizeQ8Rows (the production loader function), the reference sees the\n// DEQUANTIZED weights — so the comparison isolates kernel indexing/unpack\n// from quantization error, and the tolerance stays f32-accumulation tight.\nasync function runQ8Case(ctx, { M, K, N, t, outT = 'f32', gemv = false, bias = false, silu = false, tm8 = false, sg = false, tol, seed }) {\n const { device } = ctx;\n const rng = mulberry32(seed);\n const xF = randF32(M * K, rng);\n const wF = randF32(K * N, rng);\n const bF = bias ? randF32(N, rng) : null;\n let xData = xF;\n let xRef = xF;\n let bData = bF;\n let bRef = bF;\n if (t === 'f16') {\n ({ half: xData, ref: xRef } = toF16(xF));\n if (bias) ({ half: bData, ref: bRef } = toF16(bF));\n }\n const { packed, scales } = quantizeQ8Rows(transposeKN(wF, K, N), N, K);\n const wRef = new Float32Array(K * N); // dequantized, back in [K,N]\n for (let n = 0; n < N; n++) {\n for (let k = 0; k < K; k++) {\n const word = packed[(n * K + k) >> 2];\n let q = (word >>> (8 * ((n * K + k) & 3))) & 0xff;\n if (q > 127) q -= 256;\n wRef[k * N + n] = Math.fround(q * scales[n]);\n }\n }\n const want = matmulRef(xRef, wRef, bRef, { M, K, N, silu });\n\n const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST;\n const xBuf = createBuffer(device, xData, usage);\n const wBuf = createBuffer(device, packed, usage);\n const sBuf = createBuffer(device, scales, usage);\n const bBuf = bias ? createBuffer(device, bData, usage) : null;\n const outBytes = M * N * (outT === 'f16' ? 2 : 4);\n const yBuf = device.createBuffer({\n size: Math.ceil(outBytes / 4) * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n runGemmOnce(device, {\n x: xBuf, w: wBuf, b: bBuf, y: yBuf, M, K, N, scales: sBuf,\n flags: { t, outT, wt: true, wq8: true, silu, sg, ...(gemv ? { gemv: true } : { tiled: true, tm8 }) },\n });\n const raw = await readback(device, yBuf, outBytes);\n const got = outT === 'f16' ? expandF16(new Uint16Array(raw)) : new Float32Array(raw);\n for (const buf of [xBuf, wBuf, sBuf, bBuf, yBuf]) buf?.destroy();\n\n const { failures, maxAbsDiff, worst } = compareLanes(got, want, tol);\n return {\n pass: failures === 0,\n detail: {\n M, K, N, t, outT, wq8: true, gemv, bias, silu, tm8, tol, failures,\n maxAbsDiff: String(maxAbsDiff),\n ...(failures > 0 ? { worst, got: String(got[worst]), want: String(want[worst]) } : {}),\n },\n };\n}\n\nregisterF16Fn('wq8_f16_vocab', (ctx) =>\n runQ8Case(ctx, { M: 64, K: 448, N: 24000, t: 'f16', tol: 1e-3, seed: 401 }));\nregisterF16Fn('wq8_tm8_f16_vocab_tails', (ctx) =>\n runQ8Case(ctx, { M: 65, K: 448, N: 24000, t: 'f16', tm8: true, tol: 1e-3, seed: 402 }));\nregisterTest('wq8_f32_tails', (ctx) =>\n runQ8Case(ctx, { M: 33, K: 448, N: 1002, t: 'f32', tol: 1e-3, seed: 403 }));\n// FFN shapes: WQ8 with bias/silu on both kernels (2b). GEMV = the B<128\n// decode path (WT mode), tiled = the B>=128 path.\nregisterF16Fn('wq8_gemv_f16_fc1_bias_silu', (ctx) =>\n runQ8Case(ctx, { M: 3, K: 448, N: 1792, t: 'f16', outT: 'f16', gemv: true, bias: true, silu: true, tol: 0.01, seed: 404 }));\nregisterF16Fn('wq8_gemv_f16_fc2_bias', (ctx) =>\n runQ8Case(ctx, { M: 5, K: 1792, N: 448, t: 'f16', outT: 'f16', gemv: true, bias: true, tol: 0.02, seed: 405 }));\nregisterF16Fn('wq8_tiled_f16_fc1_bias_silu', (ctx) =>\n runQ8Case(ctx, { M: 96, K: 448, N: 1792, t: 'f16', outT: 'f16', bias: true, silu: true, tm8: true, tol: 0.01, seed: 406 }));\n\n// f32 sanity + workgroup-tail clamps: N=452 (%16 != 0) hits the NWT tail,\n// N=1002 (%8 != 0) hits the WT tail.\nregisterTest('gemv_f32_bias_tail', (ctx) =>\n runCase(ctx, { M: 3, K: 448, N: 452, t: 'f32', bias: true, gemv: true, tol: 1e-5, seed: 205 }));\nregisterTest('gemv_f32_wt_tail', (ctx) =>\n runCase(ctx, { M: 2, K: 448, N: 1002, t: 'f32', wt: true, gemv: true, tol: 1e-5, seed: 206 }));\n\n// Subgroup (sg) GEMV-WT arms at M > 1 — the production shape the b1 goldens\n// miss: the WT kernel's MT row loop goes multi-trip per workgroup while the\n// reduction is a subgroupShuffleDown butterfly. On Adreno the miscompile\n// family is context-sensitive (multi-trip loops were an ingredient), so\n// these must be proven on-device at M > 1, not just at M = 1.\nconst gemvSgSkip = (ctx) => (!ctx.hasF16 ? { skip: true, reason: 'no shader-f16' }\n : !ctx.hasSubgroups ? { skip: true, reason: 'subgroups feature unavailable' }\n : (ctx.subgroupMinSize ?? 0) < 16 ? { skip: true, reason: 'subgroupMinSize < TK 16' } : null);\nregisterTest('gemv_sg_f16_wt_qkv_m3', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 3, K: 448, N: 1344, t: 'f16', wt: true, gemv: true, sg: true, tol: 0.01, seed: 401 }));\nregisterTest('gemv_sg_f16_wt_fc1_silu_m2', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 2, K: 448, N: 1792, t: 'f16', bias: true, silu: true, wt: true, gemv: true, sg: true, tol: 0.01, seed: 402 }));\nregisterTest('gemv_sg_f16_wt_fc2_m5', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 5, K: 1792, N: 448, t: 'f16', bias: true, wt: true, gemv: true, sg: true, tol: 0.02, seed: 403 }));\nregisterTest('gemv_sg_f16_wt_vocab_m5', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 5, K: 448, N: 24000, t: 'f16', outT: 'f32', wt: true, gemv: true, sg: true, tol: 0.01, seed: 404 }));\n\n// sg GEMV-WT at HACHIMI-60 dims (d 576, ffn 2304, qkv 1728): hachimi60\n// sg_golden read 0/30 on the affected Adreno while every moxhi-dim sg kernel\n// passes — trip counts change with dims, and the miscompile family is\n// trip-count-sensitive. CPU-checked at the exact production shapes.\nregisterTest('gemv_sg_f16_wt_h60_qkv_m3', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 3, K: 576, N: 1728, t: 'f16', wt: true, gemv: true, sg: true, tol: 0.01, seed: 411 }));\nregisterTest('gemv_sg_f16_wt_h60_fc1_silu_m2', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 2, K: 576, N: 2304, t: 'f16', bias: true, silu: true, wt: true, gemv: true, sg: true, tol: 0.01, seed: 412 }));\nregisterTest('gemv_sg_f16_wt_h60_fc2_m5', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 5, K: 2304, N: 576, t: 'f16', bias: true, wt: true, gemv: true, sg: true, tol: 0.02, seed: 413 }));\nregisterTest('gemv_sg_f16_wt_h60_vocab_m3', (ctx) => gemvSgSkip(ctx)\n ?? runCase(ctx, { M: 3, K: 576, N: 24000, t: 'f16', outT: 'f32', wt: true, gemv: true, sg: true, tol: 0.01, seed: 414 }));\n\n// sg WQ8-GEMV (the b1 q8 lm_head path under forced sg): moxhi-dim control +\n// hachimi-dim arm — hachimi60 sg goldens fail on the affected Adreno while\n// every f16 sg kernel at those dims passes, so the q8 butterfly needs its\n// own on-device verdict per K.\nregisterTest('wq8_sg_gemv_vocab_m3', (ctx) => gemvSgSkip(ctx)\n ?? runQ8Case(ctx, { M: 3, K: 448, N: 24000, t: 'f16', gemv: true, sg: true, tol: 1e-3, seed: 421 }));\nregisterTest('wq8_sg_gemv_vocab_h60_m3', (ctx) => gemvSgSkip(ctx)\n ?? runQ8Case(ctx, { M: 3, K: 576, N: 24000, t: 'f16', gemv: true, sg: true, tol: 1e-3, seed: 422 }));\n\n// Encoder tiled-GEMM (gemm_tiled2 tm8) at HACHIMI dims — the encoder runs\n// these shapes on every layer; the lean hachimi sg golden reads 10/30 on the\n// affected Adreno with every decode kernel individually clean, so the\n// encoder-side kernels need per-shape device verdicts too.\nregisterF16Fn('tiled2_h60_qkv', (ctx) =>\n runCase(ctx, { M: 96, K: 576, N: 1728, t: 'f16', bias: true, tiled: true, tm8: true, tol: 0.01, seed: 431 }));\nregisterF16Fn('tiled2_h60_fc1_silu', (ctx) =>\n runCase(ctx, { M: 64, K: 576, N: 2304, t: 'f16', bias: true, silu: true, tiled: true, tm8: true, tol: 0.01, seed: 432 }));\nregisterF16Fn('tiled2_h60_fc2', (ctx) =>\n runCase(ctx, { M: 64, K: 2304, N: 576, t: 'f16', bias: true, tiled: true, tm8: true, tol: 0.02, seed: 433 }));\n"],"names":["mulberry32","seed","a","randF32","n","rng","out","i","toF16","f32arr","half","f32ToF16","expandF16","transposeKN","src","K","N","k","runCase","ctx","M","t","outT","bias","silu","wt","gemv","tiled","tiledV","tm8","sh16","dbuf","bkk","sg","tol","device","xF","wF","bF","xData","wData","bData","xRef","wRef","bRef","want","matmulRef","usage","xBuf","createBuffer","wBuf","bBuf","outBytes","yBuf","runGemmOnce","raw","readback","got","buf","failures","maxAbsDiff","worst","compareLanes","registerF16","name","opts","registerTest","registerF16Fn","fn","runQ8Case","packed","scales","quantizeQ8Rows","q","sBuf","gemvSgSkip"],"mappings":"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"}
assets/generate-C4ruG1zm.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{t as ie}from"./tokenizer-Ex1u7wXD.js";import{r as ue}from"./encoder-DX8MOfcH.js";import{c as le,a as pe,e as de}from"./decoder-DI6VDxxO.js";import{c as me,m as ge}from"./shapes-BCQ9D81L.js";import{g as he,e as K,c as Be}from"./constants-C8VbFpic.js";const T=8;async function ke(f,g,U,_,{maxNewTokens:V,onProgress:W,decodeAhead:F=!0,inFlight:h=2,compact:I=!0,encPacked:L="auto",lmHead:N="auto",ffn:Q="auto",lmHeadFuse:Y="auto",fuseLn:j="auto",proj:H="auto",ffnSplitK:J="auto",projSplitK:X="auto",decodeMega:Z="auto",sg:C="auto",encAttnSafe:ee=!1,tiledProj:te="auto"}={}){const{device:E}=f;if(h!==2&&h!==3)throw new Error(`translateBatch: inFlight must be 2 or 3, got ${h}`);const B=await ie(U,_),{B:r}=B,R=me(f,B.S,g.dtype==="f16"?2:4);if(r>R)throw new Error(`translateBatch: batch ${r} at S=${B.S} exceeds maxStorageBufferBindingSize=${f?.limits?.maxStorageBufferBindingSize??"default 134217728"} (encoder ffnTmp [B·S, 1792]); split into batches of ≤ ${R}`);const u=Math.min(he,V??Math.max(..._.map(e=>ge(e.length)))),oe=performance.now(),l=await ue(f,g,B,{packed:L,sg:C==="on",attnQbAlign8:ee});await E.queue.onSubmittedWorkDone();const ne=performance.now()-oe;let s={state:le(f,g,{B:r,S:l.S,maxSteps:u,lmHead:N,ffn:Q,lmHeadFuse:Y,fuseLn:j,proj:H,tiledProj:te,ffnSplitK:J,projSplitK:X,decodeMega:Z,sg:C}),crossKV:l.crossKV,lensBuf:l.lensBuf,S:l.S,arena:null},c=r,w=Array.from({length:r},(e,a)=>a);const y=Array.from({length:r},()=>[]),p=new Array(r).fill(!1);let x=0,b=0,G=0,v=0,O=0;const ae=(T*r+r)*4,D=Array.from({length:h},(e,a)=>E.createBuffer({label:`decode group staging ${a}`,size:ae,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ})),re=e=>{const a=performance.now(),n=Math.min(e+T,u),t=D[e/T%D.length];if(t.mapState!=="unmapped")throw new Error(`decode staging reused while ${t.mapState}`);const i=E.createCommandEncoder({label:`decode ${e}..${n}`}),o=i.beginComputePass({label:`decode ${e}..${n}`}),k=[];for(let m=e;m<n;m++)k.push(...de(f,g,s,s.state,m,o).scratch);o.end();const d=(n-e)*c;i.copyBufferToBuffer(s.state.tokenRing,e*c*4,t,0,d*4),i.copyBufferToBuffer(s.state.done,0,t,d*4,c*4),E.queue.submit([i.finish()]),x++;for(const m of k)m.destroy();return v+=performance.now()-a,{g:e,tEnd:n,nTok:d,staging:t,B:c,map:w}},se=()=>{if(!I||b===0)return!1;const e=w.reduce((a,n)=>a+(p[n]?0:1),0);return e>0&&c-e>=Math.max(8,c>>2)},ce=()=>{const e=[];for(let t=0;t<c;t++)p[w[t]]||e.push(t);const a=e.map(t=>w[t]),n=s;s=pe(f,g,n,{liveIdx:e,t0:b,cap:u,lens:new Uint32Array(a.map(t=>B.lens[t])),lastTok:new Uint32Array(a.map(t=>y[t].at(-1)))}),n.state.destroy(),n.arena?n.arena.destroy():l.arena.destroy(),c=e.length,w=a,G++},fe=performance.now();try{const e=F?h:1,a=[];let n=0,t=!1;for(;;){const i=!t&&n<u&&se();if(i&&a.length===0){ce();continue}for(;!t&&!i&&n<u&&a.length<e;)a.push(re(n)),n+=T;const o=a.shift();if(!o)break;if(t)continue;const k=performance.now();await o.staging.mapAsync(GPUMapMode.READ,0,(o.nTok+o.B)*4);const d=new Uint32Array(o.staging.getMappedRange(0,(o.nTok+o.B)*4).slice(0));o.staging.unmap(),O+=performance.now()-k;for(let S=o.g;S<o.tEnd;S++)for(let A=0;A<o.B;A++){const P=o.map[A];if(p[P])continue;const q=d[(S-o.g)*o.B+A];y[P].push(q),q===K&&(p[P]=!0)}b=o.tEnd,W?.({step:o.tEnd,cap:u,done:p.filter(Boolean).length,B:r}),d.subarray(o.nTok,o.nTok+o.B).every(S=>S===1)&&(t=!0)}}finally{for(const e of D)e.destroy();s.state.destroy(),s.arena?.destroy(),l.arena.destroy()}const M=performance.now()-fe,z=[];let $=0;for(let e=0;e<r;e++){const a=!p[e];$+=y[e].length;const n=[Be,...y[e]];a&&n.push(K);const t=U.decode(n,{skip_special_tokens:!0}).trim();z.push({ids:n,text:t,forcedEos:a,steps:y[e].length})}return{rows:z,metrics:{encoderMs:ne,decodeMs:M,cpuEncodeMs:v,awaitMs:O,submits:x,steps:b,compactions:G,tokensGenerated:$,tokPerSec:M>0?$/M*1e3:0}}}export{ke as t};
2
+ //# sourceMappingURL=generate-C4ruG1zm.js.map
assets/generate-C4ruG1zm.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"generate-C4ruG1zm.js","sources":["../../src/engine/generate.js"],"sourcesContent":["// Full GPU-resident greedy decode: tokenize → encoder (one submit) → decode\n// loop in groups of K=8 steps per submit. Within a group all 25·K dispatches\n// are recorded into one compute pass — the argmax kernel writes each step's\n// token into the ring and the next step's embed reads it, so the CPU never\n// sits between steps. After each group ONE readback (ring slice + done flags)\n// tells the CPU which tokens were produced and whether every row has hit eos.\n//\n// Decode-ahead (default): group g+1 is encoded and submitted BEFORE awaiting\n// group g's readback, so the GPU never drains while the CPU maps/collects.\n// GPU-side correctness is free — queue order guarantees group g's argmax\n// writes the ring before group g+1's embed reads it. The cost is that EOS\n// early-exit lags one group: when group g's flags show all rows done, group\n// g+1 has already been submitted (≤ (inFlight-1)·GROUP_STEPS wasted steps per\n// run; done rows just produce PAD, which never enters a sequence). inFlight\n// staging buffers rotate: a buffer is copied into, mapped, read, unmapped —\n// and only then reused (N groups in flight ⇒ N buffers is exactly enough).\n// Pass {decodeAhead: false} for the sequential A/B path.\n//\n// Timing semantics (spike-grade, documented not perfect):\n// encoderMs wall time from the runEncoder() call until\n// queue.onSubmittedWorkDone() resolves for its submit —\n// includes tokenized-batch upload + command recording overhead.\n// decodeMs wall time of the whole decode loop (GPU work + per-group\n// mapAsync readbacks + CPU collection).\n// cpuEncodeMs Σ per-group CPU time recording commands + submitting.\n// awaitMs Σ per-group time awaiting mapAsync + copying the readback.\nimport { tokenizeBatch } from './tokenizer.js';\nimport { runEncoder } from './encoder.js';\nimport { createDecodeState, compactDecodeState, encodeDecodeStep } from './decoder.js';\nimport { maxNewTokensFor, maxBatchForLimits } from './shapes.js';\nimport { EOS, DECODER_START, DECODE_CAP } from './constants.js';\n\nconst GROUP_STEPS = 8; // decode steps recorded per submit\n\n// translateBatch(ctx, weights, tok, sources,\n// {maxNewTokens?, onProgress?, decodeAhead?, inFlight?, compact?})\n// ctx {device, limits?, ...} from initDevice()\n// sources array of source strings (one batch)\n// inFlight decode-ahead depth: 2 (default, double-buffered staging) or 3\n// (triple-buffered). Measured on 64 file23k chunks at B=64\n// (m5_inflight_ab, 2026-07-06): median 28737 vs 28724 tok/s — a\n// wash; the readback gap is already hidden at depth 2, so 2 stays\n// the default.\n// compact EOS row compaction (default true): when ≥ max(8, B/4) rows of\n// the current batch have emitted eos, stop submitting, drain the\n// in-flight groups, and rebuild the decode context with only the\n// live rows (compactDecodeState) — finished rows otherwise keep\n// burning GEMM rows and attention workgroups until the whole\n// group hits eos. Kernel routing is pinned across compactions, so\n// output is token-exact vs {compact: false} (compact_equiv gate).\n// Returns:\n// rows [{ids, text, forcedEos, steps}] — ids = [0, ...tokens] trimmed at\n// the first eos inclusive; rows that never emitted eos within the\n// cap get one appended (forcedEos: true — HF max_length semantics)\n// metrics {encoderMs, decodeMs, cpuEncodeMs, awaitMs, submits, steps,\n// tokensGenerated, tokPerSec}\n// tokensGenerated counts argmax-produced tokens across ALL rows\n// (incl. an emitted eos, excl. a force-appended one); tokPerSec is\n// total tokens over decodeMs.\nexport async function translateBatch(ctx, weights, tok, sources, {\n maxNewTokens, onProgress, decodeAhead = true, inFlight = 2, compact = true,\n // runEncoder passthrough (row-packing A/B)\n encPacked = 'auto',\n // createDecodeState passthrough ('q8' / fusion / layout A/B tests, and the\n // per-batch options tunedOptions(tuned, B) resolves after an autotune run)\n lmHead = 'auto', ffn = 'auto', lmHeadFuse = 'auto', fuseLn = 'auto', proj = 'auto', ffnSplitK = 'auto', projSplitK = 'auto', decodeMega = 'auto', sg = 'auto', encAttnSafe = false,\n tiledProj = 'auto',\n} = {}) {\n const { device } = ctx;\n if (inFlight !== 2 && inFlight !== 3) {\n throw new Error(`translateBatch: inFlight must be 2 or 3, got ${inFlight}`);\n }\n const batch = await tokenizeBatch(tok, sources);\n const { B } = batch;\n\n // Memory guard: the encoder ffnTmp [B·S, 1792] binding is the ceiling. No\n // silent sub-batching — the bench/app layer owns batch-size policy, the\n // engine stays explicit.\n const maxB = maxBatchForLimits(ctx, batch.S, weights.dtype === 'f16' ? 2 : 4);\n if (B > maxB) {\n throw new Error(\n `translateBatch: batch ${B} at S=${batch.S} exceeds ` +\n `maxStorageBufferBindingSize=${ctx?.limits?.maxStorageBufferBindingSize ?? 'default 134217728'} ` +\n `(encoder ffnTmp [B·S, 1792]); split into batches of ≤ ${maxB}`,\n );\n }\n\n const cap = Math.min(\n DECODE_CAP,\n maxNewTokens ?? Math.max(...sources.map((s) => maxNewTokensFor(s.length))),\n );\n\n const tEnc0 = performance.now();\n const encRun = await runEncoder(ctx, weights, batch, { packed: encPacked, sg: sg === 'on', attnQbAlign8: encAttnSafe });\n await device.queue.onSubmittedWorkDone();\n const encoderMs = performance.now() - tEnc0;\n\n // The mutable decode context: state + the cross-attention view. Replaced\n // wholesale by each compaction; curMap maps current row -> original row.\n let cur = {\n state: createDecodeState(ctx, weights, { B, S: encRun.S, maxSteps: cap, lmHead, ffn, lmHeadFuse, fuseLn, proj, tiledProj, ffnSplitK, projSplitK, decodeMega, sg }),\n crossKV: encRun.crossKV, lensBuf: encRun.lensBuf, S: encRun.S, arena: null,\n };\n let curB = B;\n let curMap = Array.from({ length: B }, (_, i) => i);\n const rowTokens = Array.from({ length: B }, () => []);\n const rowDone = new Array(B).fill(false); // CPU mirror: saw eos in the ring\n let submits = 0;\n let steps = 0;\n let compactions = 0;\n let cpuEncodeMs = 0;\n let awaitMs = 0;\n\n // inFlight staging buffers, rotated by group index. Sized for a full group;\n // the (possibly shorter) last group copies less and reads accordingly.\n const stagingBytes = (GROUP_STEPS * B + B) * 4;\n const stagings = Array.from({ length: inFlight }, (_, i) => device.createBuffer({\n label: `decode group staging ${i}`,\n size: stagingBytes,\n usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ,\n }));\n\n // Record + submit one group [g, tEnd). Returns the in-flight descriptor —\n // it carries the batch geometry (B, row map) it was submitted with, since a\n // compaction may swap the context before its readback is processed.\n const encodeGroup = (g) => {\n const t0 = performance.now();\n const tEnd = Math.min(g + GROUP_STEPS, cap);\n const staging = stagings[(g / GROUP_STEPS) % stagings.length];\n if (staging.mapState !== 'unmapped') {\n throw new Error(`decode staging reused while ${staging.mapState}`);\n }\n const encoder = device.createCommandEncoder({ label: `decode ${g}..${tEnd}` });\n const pass = encoder.beginComputePass({ label: `decode ${g}..${tEnd}` });\n const scratch = [];\n for (let t = g; t < tEnd; t++) {\n scratch.push(...encodeDecodeStep(ctx, weights, cur, cur.state, t, pass).scratch);\n }\n pass.end();\n\n // One readback per group: ring slice [g·B, tEnd·B) + done[B].\n const nTok = (tEnd - g) * curB;\n encoder.copyBufferToBuffer(cur.state.tokenRing, g * curB * 4, staging, 0, nTok * 4);\n encoder.copyBufferToBuffer(cur.state.done, 0, staging, nTok * 4, curB * 4);\n device.queue.submit([encoder.finish()]);\n submits++;\n for (const buf of scratch) buf.destroy(); // safe post-submit\n cpuEncodeMs += performance.now() - t0;\n return { g, tEnd, nTok, staging, B: curB, map: curMap };\n };\n\n // Compact away the finished rows: pays when a decent slice of the batch is\n // dead AND there are steps left. The max(8, B/4) floor keeps small batches\n // (b1–b8 gates, latency runs) permanently on the no-compaction path.\n const compactWanted = () => {\n if (!compact || steps === 0) return false;\n const live = curMap.reduce((n, orig) => n + (rowDone[orig] ? 0 : 1), 0);\n return live > 0 && curB - live >= Math.max(8, curB >> 2);\n };\n const doCompact = () => {\n const liveIdx = [];\n for (let i = 0; i < curB; i++) if (!rowDone[curMap[i]]) liveIdx.push(i);\n const newMap = liveIdx.map((i) => curMap[i]);\n const prev = cur;\n cur = compactDecodeState(ctx, weights, prev, {\n liveIdx, t0: steps, cap,\n lens: new Uint32Array(newMap.map((orig) => batch.lens[orig])),\n lastTok: new Uint32Array(newMap.map((orig) => rowTokens[orig].at(-1))),\n });\n // Old buffers are queue-retained by the just-submitted copies; destroy()\n // only blocks future submissions. First compaction: the encoder arena\n // (encOut + old crossKV/lens) is no longer referenced either.\n prev.state.destroy();\n if (prev.arena) prev.arena.destroy();\n else encRun.arena.destroy();\n curB = liveIdx.length;\n curMap = newMap;\n compactions++;\n };\n\n const tDec0 = performance.now();\n try {\n const depth = decodeAhead ? inFlight : 1; // groups in flight (submitted, unread)\n const pending = []; // submitted-but-unread groups, oldest first\n let nextG = 0;\n let allDone = false;\n for (;;) {\n // A wanted compaction stalls new submits so the in-flight groups (built\n // against the OLD layout) drain first — one pipeline bubble per compact.\n const wantCompact = !allDone && nextG < cap && compactWanted();\n if (wantCompact && pending.length === 0) {\n doCompact();\n continue;\n }\n while (!allDone && !wantCompact && nextG < cap && pending.length < depth) {\n pending.push(encodeGroup(nextG));\n nextG += GROUP_STEPS;\n }\n const grp = pending.shift();\n if (!grp) break;\n if (allDone) continue; // submitted before all-done was seen; results are\n // PAD-only for done rows — safe to ignore unread.\n\n const tA0 = performance.now();\n await grp.staging.mapAsync(GPUMapMode.READ, 0, (grp.nTok + grp.B) * 4);\n const data = new Uint32Array(grp.staging.getMappedRange(0, (grp.nTok + grp.B) * 4).slice(0));\n grp.staging.unmap(); // staging is now free for group g+2\n awaitMs += performance.now() - tA0;\n\n // Collect per row (map current -> original), stopping at its first eos —\n // done rows produce PAD afterwards, which must NOT enter the sequence.\n for (let t = grp.g; t < grp.tEnd; t++) {\n for (let b = 0; b < grp.B; b++) {\n const orig = grp.map[b];\n if (rowDone[orig]) continue;\n const id = data[(t - grp.g) * grp.B + b];\n rowTokens[orig].push(id);\n if (id === EOS) rowDone[orig] = true;\n }\n }\n steps = grp.tEnd;\n onProgress?.({ step: grp.tEnd, cap, done: rowDone.filter(Boolean).length, B });\n\n // GPU done flags (queue-ordered snapshot after step tEnd-1).\n const doneFlags = data.subarray(grp.nTok, grp.nTok + grp.B);\n if (doneFlags.every((d) => d === 1)) allDone = true;\n }\n } finally {\n for (const s of stagings) s.destroy(); // deferred until GPU copies finish\n cur.state.destroy();\n cur.arena?.destroy();\n encRun.arena.destroy(); // idempotent — already emptied after compaction 1\n }\n const decodeMs = performance.now() - tDec0;\n\n const rows = [];\n let tokensGenerated = 0;\n for (let b = 0; b < B; b++) {\n const forcedEos = !rowDone[b];\n tokensGenerated += rowTokens[b].length; // argmax-produced (incl. emitted eos)\n const ids = [DECODER_START, ...rowTokens[b]];\n if (forcedEos) ids.push(EOS);\n const text = tok.decode(ids, { skip_special_tokens: true }).trim();\n rows.push({ ids, text, forcedEos, steps: rowTokens[b].length });\n }\n\n return {\n rows,\n metrics: {\n encoderMs, decodeMs, cpuEncodeMs, awaitMs, submits, steps, compactions, tokensGenerated,\n tokPerSec: decodeMs > 0 ? (tokensGenerated / decodeMs) * 1000 : 0,\n },\n };\n}\n"],"names":["GROUP_STEPS","translateBatch","ctx","weights","tok","sources","maxNewTokens","onProgress","decodeAhead","inFlight","compact","encPacked","lmHead","ffn","lmHeadFuse","fuseLn","proj","ffnSplitK","projSplitK","decodeMega","sg","encAttnSafe","tiledProj","device","batch","tokenizeBatch","B","maxB","maxBatchForLimits","cap","DECODE_CAP","s","maxNewTokensFor","tEnc0","encRun","runEncoder","encoderMs","cur","createDecodeState","curB","curMap","_","i","rowTokens","rowDone","submits","steps","compactions","cpuEncodeMs","awaitMs","stagingBytes","stagings","encodeGroup","g","t0","tEnd","staging","encoder","pass","scratch","t","encodeDecodeStep","nTok","buf","compactWanted","live","n","orig","doCompact","liveIdx","newMap","prev","compactDecodeState","tDec0","depth","pending","nextG","allDone","wantCompact","grp","tA0","data","b","id","EOS","d","decodeMs","rows","tokensGenerated","forcedEos","ids","DECODER_START","text"],"mappings":"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"}
assets/hachimi60-D0JkA1E4.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as s}from"./debug-Cn7EHWtJ.js";import{l as b}from"./weights-B-okS09o.js";import{l as w}from"./tokenizer-Ex1u7wXD.js";import{t as v}from"./generate-C4ruG1zm.js";import{detectTreeReductionBug as N}from"./autotune-DBJGFXNj.js";import{c as f}from"./verify-HJ8NImMM.js";import{a as S,b as L}from"./constants-C8VbFpic.js";import"./modulepreload-polyfill-B5Qt9EMX.js";import"./preload-helper-BXl3LOEh.js";import"./shapes-BCQ9D81L.js";import"./f16-wKKZr58e.js";import"./encoder-DX8MOfcH.js";import"./pipelines-DD24nEJg.js";import"./decoder-DI6VDxxO.js";const C={repetitionPenalty:1.2,greedy:!0,maxNewTokensFormula:"max(24, min(192, ceil(chars*3.2)+12))",dtype:"fp32"},q=JSON.parse('[{"source":"他缓缓拔出长剑,目光冷得像冰。","ids":[0,754,1237,1501,1594,1039,654,339,18937,821,475,1072,321,1951,18948,2],"maxNewTokens":60,"text":"Hắn chậm rãi rút trường kiếm ra, ánh mắt lạnh như băng."},{"source":"夜色渐深,客栈里只剩下几盏残灯。","ids":[0,4988,1082,2875,659,18937,332,1542,7495,394,404,329,889,1742,3286,1631,18948,2],"maxNewTokens":64,"text":"Đêm dần buông xuống, trong khách điếm chỉ còn lại vài ngọn đèn tàn."},{"source":"“你到底是什么人?”她低声问道。","ids":[0,337,11090,997,514,292,843,632,1958,1460,1298,848,18948,2],"maxNewTokens":64,"text":"\\"Rốt cuộc ngươi là ai?\\" Nàng thấp giọng hỏi."},{"source":"山风呼啸,卷起满地的落叶。","ids":[0,7521,976,2771,2813,18937,2164,448,2189,8052,916,871,18948,2],"maxNewTokens":54,"text":"Gió núi gào thét, cuốn lên lá rụng đầy đất."},{"source":"老者捋了捋胡须,微微一笑。","ids":[0,1577,732,3592,5089,18937,1820,708,18948,2],"maxNewTokens":54,"text":"Lão giả vuốt râu, mỉm cười."},{"source":"这一掌的力道,足以开碑裂石!","ids":[0,4522,565,313,1724,324,1004,469,1745,4088,3282,1155,19020,2],"maxNewTokens":57,"text":"Lực đạo của chưởng này đủ để khai bia nứt đá!"},{"source":"“师父,弟子知错了。”少年跪在地上。","ids":[0,337,4338,1129,18937,739,576,498,1621,483,482,2439,1356,3199,459,477,871,18948,2],"maxNewTokens":70,"text":"\\"Sư phụ, đệ tử biết sai rồi.\\" Thiếu niên quỳ trên mặt đất."},{"source":"江湖上的恩怨,从来没有那么简单。","ids":[0,4489,3247,5634,1071,667,616,1463,1790,321,488,18948,2],"maxNewTokens":64,"text":"Ân oán giang hồ chưa từng đơn giản như vậy."},{"source":"她转身离去,再也没有回头。","ids":[0,1958,1795,331,1044,367,18937,290,969,1143,437,329,18948,2],"maxNewTokens":54,"text":"Nàng xoay người rời đi, không hề quay đầu lại."},{"source":"剑光一闪,血溅三尺。","ids":[0,1089,1017,2213,448,18937,1073,5290,692,4479,18948,2],"maxNewTokens":44,"text":"Kiếm quang lóe lên, máu văng ba thước."},{"source":"大殿之内,众人鸦雀无声。","ids":[0,795,497,1140,18937,874,331,1170,6355,321,3728,18948,2],"maxNewTokens":51,"text":"Trong đại điện, mọi người lặng ngắt như tờ."},{"source":"他喝了口酒,眼中闪过一丝痛楚。","ids":[0,754,2184,309,3793,2251,18937,332,475,2213,448,775,1879,3822,18948,2],"maxNewTokens":60,"text":"Hắn uống một ngụm rượu, trong mắt lóe lên vẻ đau đớn."},{"source":"“今晚三更,后山竹林见。”","ids":[0,337,17917,781,2124,692,18937,5009,1035,453,2507,3016,465,976,482,2],"maxNewTokens":54,"text":"\\"Đêm nay canh ba, hẹn gặp ở rừng trúc sau núi.\\""},{"source":"马蹄声由远及近,尘土飞扬。","ids":[0,3469,10058,1853,389,863,563,935,18937,2772,871,1549,1033,18948,2],"maxNewTokens":54,"text":"Tiếng vó ngựa từ xa tới gần, bụi đất tung bay."},{"source":"这门功夫,他练了整整二十年。","ids":[0,1322,583,1895,324,18937,343,335,627,1293,4374,4028,480,1195,549,18948,2],"maxNewTokens":57,"text":"Môn công phu này, hắn đã luyện tập trọn vẹn hai mươi năm."},{"source":"暮色四合之际,一行人马终于抵达了山脚下的小镇,镇口的酒旗在风中猎猎作响;为首的中年汉子翻身下马,环顾四周,见街道两旁的店铺早已关门闭户,只有远处一家客栈还透出昏黄的灯光,他皱了皱眉,低声吩咐众人收起兵刃,不要惊扰了镇上的百姓。","ids":[0,1492,1601,2738,2875,659,18937,2161,331,870,434,334,372,1054,1722,810,777,640,976,18937,2542,2251,453,437,1722,1033,872,11837,332,1423,19873,5623,576,921,1356,1062,437,2187,659,1853,18937,439,1100,1156,559,18937,458,981,1159,480,569,653,335,2348,981,389,909,18937,394,298,309,2688,14099,863,863,404,10866,339,821,3286,1058,3305,18948,754,2012,1317,18937,1460,1298,1190,1964,874,331,493,1327,535,329,18937,290,369,4688,8675,1847,702,332,1722,18948,2],"maxNewTokens":192,"text":"Lúc hoàng hôn buông xuống, đoàn người cuối cùng cũng đến thị trấn nhỏ dưới chân núi, cờ rượu ở đầu trấn bay phần phật trong gió; hán tử trung niên dẫn đầu nhảy xuống ngựa, nhìn quanh bốn phía, thấy cửa hàng hai bên đường đã đóng cửa từ lâu, chỉ có một quán trọ xa xa còn hắt ra ánh đèn vàng vọt. Hắn nhíu mày, thấp giọng phân phó mọi người thu binh khí lại, không được quấy rầy dân chúng trong trấn."},{"source":"传闻中的藏剑山庄坐落在群山环抱之中,庄内古木参天,流水潺潺,青石铺就的小径蜿蜒曲折;每逢三月桃花盛开,四方豪杰便会齐聚于此,或论剑,或品茶,或只是远远地望一眼那位传说中的庄主,据说他已经三十年没有拔过剑了,可江湖上没有人敢小看他。","ids":[0,4694,1089,730,3664,332,813,2410,2494,1630,929,435,4822,976,796,1100,18937,332,1814,1160,1994,651,5765,862,18937,911,2133,15966,3276,18937,620,653,810,1576,1155,1402,10574,4220,4402,1134,19290,18939,19873,1224,455,1499,692,1391,2842,3389,6259,18937,2333,3778,1156,690,508,1410,1018,617,606,18937,1153,2013,654,18937,1153,2525,2686,18937,1153,394,439,389,863,466,559,555,1814,691,332,813,2410,598,309,625,18937,772,383,343,335,692,1195,549,290,1594,654,18937,428,459,5634,1071,290,843,1126,1179,705,343,18948,2],"maxNewTokens":192,"text":"Tàng Kiếm Sơn Trang trong truyền thuyết tọa lạc giữa những dãy núi bao quanh, trong trang cổ thụ cao ngất trời, nước chảy róc rách, con đường nhỏ lát đá xanh uốn lượn khúc khuỷu; mỗi khi tháng ba hoa đào nở rộ, hào kiệt bốn phương sẽ tụ hội tại đây, hoặc luận kiếm, hoặc thưởng trà, hoặc chỉ nhìn từ xa về phía vị trang chủ trong truyền thuyết kia một cái, nghe nói hắn đã ba mươi năm không rút kiếm, nhưng trên giang hồ không ai dám coi thường hắn."},{"source":"那一夜大雨倾盆,雷声滚滚,破庙里的火堆忽明忽暗;少年抱着怀中的剑谱,听着庙外杂乱的脚步声越来越近,心跳如鼓,他知道,追兵一旦破门而入,自己便再无生路,可师父临终前的嘱托犹在耳边,这本剑谱无论如何都不能落入奸人之手。","ids":[0,4988,393,2121,321,4987,911,18937,623,3950,2503,2008,18937,3342,1481,332,3279,5354,1654,561,857,561,1381,19873,1248,1356,2567,654,7636,332,626,18937,772,623,736,640,2564,1587,569,688,5354,696,715,935,18937,3825,2399,10836,15013,18948,754,498,18937,309,455,763,2062,1824,373,981,1996,416,18937,624,479,508,290,404,653,1037,18937,428,725,3323,1830,452,455,3028,2870,313,595,1129,521,404,5290,270,518,569,1776,18937,2164,654,7636,324,658,457,506,334,290,338,1132,416,464,757,680,18948,2],"maxNewTokens":192,"text":"Đêm đó mưa như trút nước, tiếng sấm cuồn cuộn, đống lửa trong ngôi miếu đổ lúc sáng lúc tối; thiếu niên ôm kiếm phổ trong lòng, nghe tiếng bước chân hỗn loạn bên ngoài miếu ngày càng gần, tim đập thình thịch. Hắn biết, một khi quân truy đuổi phá cửa xông vào, bản thân sẽ không còn đường sống, nhưng lời dặn dò trước khi lâm chung của sư phụ vẫn còn văng vẳng bên tai, cuốn kiếm phổ này dù thế nào cũng không thể rơi vào tay kẻ gian."},{"source":"掌门之位悬空已有三年,门中各脉明争暗斗从未停歇;大师兄稳重却优柔寡断,二师姐剑法超群却性情孤傲,三师弟聪明伶俐却资历尚浅,长老们各怀心思,谁也不肯先开口,直到那个雪夜,山门外传来一声长啸,所有人都放下了手中的茶盏。","ids":[0,2404,1092,1724,716,662,901,335,692,549,18937,591,1454,332,716,1347,1097,3852,667,616,1234,2653,19873,497,595,1144,1310,1870,428,2760,2575,7552,925,1124,1439,18937,1228,595,1691,654,496,3450,2745,428,832,803,1158,3324,18937,2108,595,739,833,1441,11877,1125,428,1020,2338,404,5002,18937,841,655,1224,331,309,649,1020,18937,290,843,1131,1057,1172,452,18937,2479,372,1368,2051,393,18937,569,688,1523,716,813,372,309,623,2813,1012,18937,948,363,874,331,471,2875,3969,2686,332,464,659,18948,2],"maxNewTokens":192,"text":"Vị trí chưởng môn Huyền Không đã ba năm, các mạch trong môn tranh đấu ngầm chưa từng ngừng nghỉ; đại sư huynh trầm ổn nhưng ưu nhu nhược ít quyết đoán, nhị sư tỷ kiếm pháp siêu quần nhưng tính tình cô ngạo, tam sư đệ thông minh lanh lợi nhưng tư lịch còn nông, trưởng lão mỗi người một tâm tư, không ai chịu mở miệng trước, mãi đến đêm tuyết đó, bên ngoài sơn môn truyền đến một tiếng thét dài, tất cả mọi người đều buông chén trà trong tay xuống."},{"source":"集市上人声鼎沸,卖艺的汉子赤膊耍着一杆铁枪,围观的人群不时爆发出阵阵喝彩声;忽然人群一阵骚动,几名黑衣人分开众人径直走向那名枪手,为首之人冷冷地丢下一块乌黑的令牌,喧闹的集市霎时安静了下来,连风都仿佛停了。","ids":[0,387,18988,331,383,631,5922,4759,18937,5623,576,1920,3938,8267,2961,4687,309,1328,1562,829,18937,1014,1421,1868,884,2287,2554,2571,1808,616,637,623,8860,7359,18948,4797,558,1014,1421,7694,6091,18937,889,790,2275,613,501,3671,339,874,331,367,1112,563,464,4279,598,18937,757,1400,437,1072,2527,2690,659,309,1844,1696,1739,1019,6325,18937,7196,3588,2359,519,636,1800,1239,329,18937,801,363,1423,334,321,1234,329,18948,2],"maxNewTokens":192,"text":"Chợ người nói chuyện ồn ào, hán tử bán nghệ cởi trần múa một cây thiết thương, đám đông vây xem thỉnh thoảng bùng nổ từng trận tiếng reo hò. Đột nhiên đám đông xôn xao, vài tên hắc y nhân tách ra mọi người đi thẳng tới tay súng kia, kẻ cầm đầu lạnh lùng ném xuống một tấm lệnh bài đen nhánh, chợ náo nhiệt nhất thời yên tĩnh lại, ngay cả gió cũng như ngừng lại."},{"source":"信使跪在堂下,双手呈上一封火漆密函,堂上众人面面相觑;老庄主拆开信笺,只看了一眼,脸色便骤然大变,他缓缓起身,望着窗外沉沉的夜色,半晌才道:传令下去,即刻封山,任何人不得进出,违令者一律逐出师门,永不再录。","ids":[0,7964,732,3199,777,653,18937,480,464,2549,448,309,906,1693,4791,15507,1383,18937,874,331,459,653,439,962,18948,1577,1814,691,1057,1300,339,18937,394,1982,475,309,625,18937,853,477,746,842,558,497,818,18948,754,1237,1501,844,1777,18937,439,1924,1368,2339,1133,688,981,2644,18937,1250,696,534,383,19026,3471,1696,659,18937,770,647,906,1523,18937,729,643,843,290,369,339,416,18937,757,506,1913,1696,471,449,7938,762,828,595,716,18937,4487,3830,290,2282,329,551,18948,2],"maxNewTokens":192,"text":"Sứ giả quỳ dưới đường, hai tay dâng lên một phong mật hàm sáp đỏ, mọi người trên đường nhìn nhau. Lão trang chủ mở thư ra, chỉ liếc mắt một cái, sắc mặt liền đột nhiên đại biến. Hắn chậm rãi đứng dậy, nhìn màn đêm dày đặc ngoài cửa sổ, nửa ngày mới nói: Truyền lệnh xuống, lập tức phong sơn, bất kỳ ai không được ra vào, kẻ nào trái lệnh đều bị trục xuất khỏi sư môn, vĩnh viễn không ghi lại nữa."},{"source":"三十年前的那场大火烧毁了半座城池,也烧断了两大世家百年的情谊;如今旧事重提,当年的幸存者死的死,散的散,唯有城南那口枯井旁的老槐树还记得一切,树下埋着的,不只是一坛陈年的女儿红,还有一个再也无人敢提起的名字。","ids":[0,1839,1624,14105,692,1195,549,452,335,3626,11367,1250,1888,442,1593,18937,334,3092,2536,803,1526,988,549,313,480,497,457,619,19873,781,631,2145,1663,329,18937,331,1037,2204,549,1791,784,508,1408,6677,18937,394,298,1328,7359,19014,1932,569,8833,3163,559,1582,442,521,404,1455,948,363,18937,777,2762,1328,290,394,292,309,4725,2280,1823,1199,335,909,549,18937,368,404,298,309,625,790,290,843,1126,1663,372,551,18948,2],"maxNewTokens":192,"text":"Trận hỏa hoạn ba mươi năm trước đã thiêu rụi nửa tòa thành trì, cũng đốt đứt tình nghĩa trăm năm của hai đại thế gia; nay chuyện cũ nhắc lại, người sống sót năm xưa chết sẽ tan rã, chỉ có cây hòe già bên giếng khô phía nam thành vẫn còn nhớ tất cả, dưới gốc cây không chỉ là một vò Nữ Nhi Hồng đã lâu năm, mà còn có một cái tên không ai dám nhắc đến nữa."},{"source":"渡口的老船夫眯着眼打量来客,见那书生衣衫褴褛却腰悬长剑,不由得多问了一句;书生笑而不答,只将一锭碎银放在船头,转身望向对岸茫茫的芦苇荡,江风吹起他的衣角,露出内衬上暗绣的金线纹样,老船夫握着船桨的手,忽然抖了一下。","ids":[0,1577,2200,1895,453,7445,263,19013,4280,475,793,1149,1542,18937,458,1300,687,598,2745,1290,3276,286,1984,428,6834,1390,3547,1039,654,18937,290,828,848,785,309,1055,19873,1300,687,708,368,290,1361,18937,394,1414,309,266,573,1807,2922,453,437,2200,18937,1795,331,439,466,559,5205,278,446,5032,3814,569,598,2658,18948,7521,2408,3424,1033,2747,1290,313,343,18937,950,339,1391,1634,394,1058,11130,2569,569,332,18937,464,655,2200,1895,1175,2670,17524,1689,558,2169,448,18948,2],"maxNewTokens":192,"text":"Lão thuyền phu ở bến đò nheo mắt đánh giá khách, thấy thư sinh kia quần áo rách rưới nhưng thắt lưng treo trường kiếm, không khỏi hỏi thêm một câu; thư sinh cười mà không đáp, chỉ đặt một thỏi bạc vụn ở đầu thuyền, xoay người nhìn về phía lau sậy mênh mông bên kia bờ. Gió sông thổi bay góc áo của hắn, lộ ra hoa văn chỉ vàng thêu mờ bên trong, tay lão thuyền phu nắm mái chèo bỗng nhiên run lên."},{"source":"林昭推门而入,林昭的剑还在滴着血,可林昭的声音却平静得可怕。","ids":[0,1090,4264,2182,981,736,416,18937,654,313,1090,4264,521,404,520,810,1073,18937,428,1298,383,313,1090,4264,329,815,1239,372,1094,953,18948,2],"maxNewTokens":108,"text":"Lâm Chiêu đẩy cửa bước vào, kiếm của Lâm Chiêu vẫn còn đang nhỏ máu, nhưng giọng nói của Lâm Chiêu lại bình tĩnh đến đáng sợ."},{"source":"沈青山望着窗外,沈青山知道,今夜之后江湖上再无沈青山这个名字。","ids":[0,3560,734,730,439,339,688,981,2644,18937,3560,734,730,498,776,18937,465,1368,781,459,5634,1071,508,290,404,625,790,3560,734,730,551,18948,2],"maxNewTokens":112,"text":"Thẩm Thanh Sơn nhìn ra ngoài cửa sổ, Thẩm Thanh Sơn biết rằng, sau đêm nay trên giang hồ sẽ không còn cái tên Thẩm Thanh Sơn nữa."},{"source":"“林昭!林昭你给我站住!”她追出门外,可林昭的身影早已消失在夜色之中。","ids":[0,415,18989,424,4264,19020,1090,4264,18937,514,844,329,432,382,568,1958,1824,339,688,981,18937,428,479,1249,1090,4264,335,1157,818,920,332,1924,1368,18948,2],"maxNewTokens":124,"text":"“Lâm Chiêu! Lâm Chiêu, ngươi đứng lại cho ta!” Nàng đuổi ra ngoài cửa, nhưng thân ảnh Lâm Chiêu đã sớm biến mất trong màn đêm."},{"source":"众人都说沈青山败了,可沈青山不这么认为,沈青山收剑入鞘,转身走下擂台。","ids":[0,3032,331,471,383,3560,734,730,335,2665,18937,428,3560,734,730,290,676,488,18937,3560,734,730,493,654,416,3998,18937,1143,331,736,659,1963,2058,18948,2],"maxNewTokens":124,"text":"Mọi người đều nói Thẩm Thanh Sơn đã thua, nhưng Thẩm Thanh Sơn không nghĩ vậy, Thẩm Thanh Sơn thu kiếm vào vỏ, quay người bước xuống lôi đài."},{"source":"林昭救过他一次,林昭也骗过他一次,所以当林昭再次出现时,他不知该拔剑还是敬酒。","ids":[0,1090,4264,335,1372,343,309,638,18937,1090,4264,334,3539,5136,343,309,638,18937,432,599,455,1090,4264,762,516,638,551,18937,343,290,498,599,1594,654,802,292,2352,2251,18948,2],"maxNewTokens":137,"text":"Lâm Chiêu đã cứu hắn một lần, Lâm Chiêu cũng lừa gạt hắn một lần, cho nên khi Lâm Chiêu xuất hiện lần nữa, hắn không biết nên rút kiếm hay là mời rượu."},{"source":"沈青山的刀快,沈青山的心更狠,凡是见过沈青山出手的人,都不愿再与他为敌。","ids":[0,3271,313,3560,734,730,894,18937,626,3560,734,730,715,1631,2492,539,18937,2033,292,331,616,458,3560,734,730,339,464,18937,471,290,582,491,757,1734,412,343,551,18948,2],"maxNewTokens":128,"text":"Đao của Thẩm Thanh Sơn nhanh, lòng Thẩm Thanh Sơn càng tàn nhẫn hơn, phàm là người từng thấy Thẩm Thanh Sơn ra tay, đều không muốn làm kẻ địch với hắn nữa."},{"source":"有人说林昭死在了雁门关外,有人说林昭隐居山林,还有人说,林昭根本就没有存在过。","ids":[0,1480,331,383,1090,4264,784,453,688,10521,1322,1592,18937,298,331,383,1090,4264,1279,3715,332,2507,976,18937,404,298,331,383,18937,1090,4264,1107,624,667,616,1512,617,18948,2],"maxNewTokens":137,"text":"Có người nói Lâm Chiêu chết ở ngoài Nhạn Môn Quan, có người nói Lâm Chiêu ẩn cư trong rừng núi, còn có người nói, Lâm Chiêu căn bản chưa từng tồn tại."}]'),o={config:C,items:q};async function x(n,g={}){if(!n.hasF16)return{skip:!0,reason:"no shader-f16"};const{device:h}=n,y=S();let e=null;try{try{e=await b(h,"/weights/hachimi60",{targetDtype:"f16",lmHeadQ8:!0,ffnWT:!0,projWT:!0})}catch(t){return{skip:!0,reason:`hachimi60 weights unavailable: ${t?.message??t}`}}const p=await w("hachimi60"),T={device:h,dtype:"f16",limits:n.limits,hasSubgroups:n.hasSubgroups,subgroupMinSize:n.subgroupMinSize};let a=0,c=0;const r=[];for(let t=0;t<o.items.length;t++){const i=o.items[t],{rows:k}=await v(T,e,p,[i.source],{maxNewTokens:i.maxNewTokens,lmHead:"q8",ffn:"wt",proj:"wt",...g}),m=f(k[0].ids,i.ids);m.verdict==="exact"?a++:m.verdict==="forced-eos"?c++:r.push({i:t,step:m.step,engineText:k[0].text,goldenText:i.text})}const u=o.items.length,l=Math.ceil(.95*u);return{pass:a+c>=l,detail:{exact:a,forcedEos:c,total:u,need:l,mismatches:r.slice(0,5)}}}finally{e?.buffer.destroy(),L(y)}}s("hachimi60_prod_golden",n=>x(n));async function d(n,g){if(!n.hasSubgroups)return{skip:!0,reason:"subgroups feature unavailable"};const h=await N(n.device);return x(n,{sg:"on",encAttnSafe:h,...h?{decodeMega:"off"}:{},...g})}s("hachimi60_sg_golden",n=>d(n,{}));s("hachimi60_sg_lean_golden",n=>d(n,{decodeMega:"off"}));
2
+ //# sourceMappingURL=hachimi60-D0JkA1E4.js.map
assets/hachimi60-D0JkA1E4.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"hachimi60-D0JkA1E4.js","sources":["../../src/debug/tests/hachimi60.js"],"sourcesContent":["// HachimiMT-60-QT gate: the second REAL family member (d_model 576, 8×72\n// heads, ffn 2304 — vs Moxhi's 448/8×56/1792) decoding its own 30 fp32\n// goldens on the PRODUCTION stack (int8 lm_head + f16 WT FFN/proj). The\n// engine side of model-agnosticism is proven by dims_generic; what this\n// adds is the real export + tokenizer + the q8 quality bar on the new\n// weights — quantization error is a property of the weights, so Moxhi's\n// 29/30 does not transfer automatically.\n//\n// Skips (not fails) when /weights/hachimi60 is absent: the weights are\n// gitignored build artifacts (scripts/export_weights.py), not repo files.\n// Restores Moxhi's active config afterwards — the rest of the suite dispatches\n// Moxhi weights against module-level dims (constants.js live bindings).\nimport { registerTest } from '../registry.js';\nimport { loadWeights } from '../../engine/weights.js';\nimport { loadTokenizer } from '../../engine/tokenizer.js';\nimport { translateBatch } from '../../engine/generate.js';\nimport { detectTreeReductionBug } from '../../engine/autotune.js';\nimport { compareToGolden } from '../../bench/verify.js';\nimport { activeModelConfig, applyModelConfig } from '../../engine/constants.js';\nimport golden from '../../../fixtures/golden-hachimi60.json';\n\nasync function runHachimiGolden(ctx, extraOpts = {}) {\n if (!ctx.hasF16) return { skip: true, reason: 'no shader-f16' };\n const { device } = ctx;\n const prior = activeModelConfig();\n let weights = null;\n try {\n try {\n weights = await loadWeights(device, '/weights/hachimi60', {\n targetDtype: 'f16', lmHeadQ8: true, ffnWT: true, projWT: true,\n });\n } catch (err) {\n return { skip: true, reason: `hachimi60 weights unavailable: ${err?.message ?? err}` };\n }\n const tok = await loadTokenizer('hachimi60');\n const gctx = {\n device, dtype: 'f16', limits: ctx.limits,\n hasSubgroups: ctx.hasSubgroups, subgroupMinSize: ctx.subgroupMinSize,\n };\n let exact = 0;\n let forcedEos = 0;\n const mismatches = [];\n for (let i = 0; i < golden.items.length; i++) {\n const item = golden.items[i];\n const { rows } = await translateBatch(gctx, weights, tok, [item.source], {\n maxNewTokens: item.maxNewTokens, lmHead: 'q8', ffn: 'wt', proj: 'wt', ...extraOpts,\n });\n const cmp = compareToGolden(rows[0].ids, item.ids);\n if (cmp.verdict === 'exact') exact++;\n else if (cmp.verdict === 'forced-eos') forcedEos++;\n else mismatches.push({ i, step: cmp.step, engineText: rows[0].text, goldenText: item.text });\n }\n const total = golden.items.length;\n const need = Math.ceil(0.95 * total);\n return {\n pass: exact + forcedEos >= need,\n detail: { exact, forcedEos, total, need, mismatches: mismatches.slice(0, 5) },\n };\n } finally {\n weights?.buffer.destroy();\n applyModelConfig(prior);\n }\n}\n\nregisterTest('hachimi60_prod_golden', (ctx) => runHachimiGolden(ctx));\n// sg arm — the config the app FORCES on tree-reduce-broken devices (Adreno):\n// hachimi dims (d 576, heads 8x72, ffn 2304) exercise the sg kernels at\n// different multi-trip loop counts than moxhi (e.g. add_ln D=576 over WG 256),\n// so the device verdict must be earned per model family, not assumed.\n// The sg arms mirror the APP on the device at hand: on tree-bug devices the\n// app forces sg AND the encoder QB alignment (tunedOptions encAttnSafe), so\n// the goldens must run the same combination to be a production verdict.\nasync function sgArm(ctx, extra) {\n if (!ctx.hasSubgroups) return { skip: true, reason: 'subgroups feature unavailable' };\n const treeBug = await detectTreeReductionBug(ctx.device);\n // Mirror tunedOptions on tree-bug devices: encoder QB alignment AND\n // decodeMega off (mega+sg is broken at hachimi dims on that driver).\n return runHachimiGolden(ctx, {\n sg: 'on', encAttnSafe: treeBug, ...(treeBug ? { decodeMega: 'off' } : {}), ...extra,\n });\n}\nregisterTest('hachimi60_sg_golden', (ctx) => sgArm(ctx, {}));\n// mega-vs-lean bisect at hachimi dims: sg_golden (decodeMega auto -> mega at\n// b1) read 0/30 on the affected Adreno while moxhi sg goldens are 30/30 —\n// dims change the kernels' loop trip counts. lean isolates mega@576.\nregisterTest('hachimi60_sg_lean_golden', (ctx) => sgArm(ctx, { decodeMega: 'off' }));\n"],"names":["runHachimiGolden","ctx","extraOpts","device","prior","activeModelConfig","weights","loadWeights","err","tok","loadTokenizer","gctx","exact","forcedEos","mismatches","i","golden","item","rows","translateBatch","cmp","compareToGolden","total","need","applyModelConfig","registerTest","sgArm","extra","treeBug","detectTreeReductionBug"],"mappings":"k7bAqBA,eAAeA,EAAiBC,EAAKC,EAAY,GAAI,CACnD,GAAI,CAACD,EAAI,OAAQ,MAAO,CAAE,KAAM,GAAM,OAAQ,eAAe,EAC7D,KAAM,CAAE,OAAAE,CAAM,EAAKF,EACbG,EAAQC,EAAiB,EAC/B,IAAIC,EAAU,KACd,GAAI,CACF,GAAI,CACFA,EAAU,MAAMC,EAAYJ,EAAQ,qBAAsB,CACxD,YAAa,MAAO,SAAU,GAAM,MAAO,GAAM,OAAQ,EACjE,CAAO,CACH,OAASK,EAAK,CACZ,MAAO,CAAE,KAAM,GAAM,OAAQ,kCAAkCA,GAAK,SAAWA,CAAG,EAAE,CACtF,CACA,MAAMC,EAAM,MAAMC,EAAc,WAAW,EACrCC,EAAO,CACX,OAAAR,EAAQ,MAAO,MAAO,OAAQF,EAAI,OAClC,aAAcA,EAAI,aAAc,gBAAiBA,EAAI,eAC3D,EACI,IAAIW,EAAQ,EACRC,EAAY,EAChB,MAAMC,EAAa,CAAA,EACnB,QAASC,EAAI,EAAGA,EAAIC,EAAO,MAAM,OAAQD,IAAK,CAC5C,MAAME,EAAOD,EAAO,MAAMD,CAAC,EACrB,CAAE,KAAAG,GAAS,MAAMC,EAAeR,EAAML,EAASG,EAAK,CAACQ,EAAK,MAAM,EAAG,CACvE,aAAcA,EAAK,aAAc,OAAQ,KAAM,IAAK,KAAM,KAAM,KAAM,GAAGf,CACjF,CAAO,EACKkB,EAAMC,EAAgBH,EAAK,CAAC,EAAE,IAAKD,EAAK,GAAG,EAC7CG,EAAI,UAAY,QAASR,IACpBQ,EAAI,UAAY,aAAcP,IAClCC,EAAW,KAAK,CAAE,EAAAC,EAAG,KAAMK,EAAI,KAAM,WAAYF,EAAK,CAAC,EAAE,KAAM,WAAYD,EAAK,IAAI,CAAE,CAC7F,CACA,MAAMK,EAAQN,EAAO,MAAM,OACrBO,EAAO,KAAK,KAAK,IAAOD,CAAK,EACnC,MAAO,CACL,KAAMV,EAAQC,GAAaU,EAC3B,OAAQ,CAAE,MAAAX,EAAO,UAAAC,EAAW,MAAAS,EAAO,KAAAC,EAAM,WAAYT,EAAW,MAAM,EAAG,CAAC,CAAC,CACjF,CACE,QAAC,CACCR,GAAS,OAAO,QAAO,EACvBkB,EAAiBpB,CAAK,CACxB,CACF,CAEAqB,EAAa,wBAA0BxB,GAAQD,EAAiBC,CAAG,CAAC,EAQpE,eAAeyB,EAAMzB,EAAK0B,EAAO,CAC/B,GAAI,CAAC1B,EAAI,aAAc,MAAO,CAAE,KAAM,GAAM,OAAQ,+BAA+B,EACnF,MAAM2B,EAAU,MAAMC,EAAuB5B,EAAI,MAAM,EAGvD,OAAOD,EAAiBC,EAAK,CAC3B,GAAI,KAAM,YAAa2B,EAAS,GAAIA,EAAU,CAAE,WAAY,KAAK,EAAK,CAAA,EAAK,GAAGD,CAClF,CAAG,CACH,CACAF,EAAa,sBAAwBxB,GAAQyB,EAAMzB,EAAK,CAAA,CAAE,CAAC,EAI3DwB,EAAa,2BAA6BxB,GAAQyB,EAAMzB,EAAK,CAAE,WAAY,KAAK,CAAE,CAAC"}