Humuhumu33 commited on
Commit
ac2b557
·
verified ·
1 Parent(s): d882c7e

roofline: fill buffer non-zero + exceed cache for real VRAM bw

Browse files
Files changed (1) hide show
  1. roofline.html +27 -3
roofline.html CHANGED
@@ -22,6 +22,19 @@ const MODEL_GB = 0.69, CUR_MS = 18.4;
22
  const say = (t,cls) => { st.textContent = t; st.className = "card" + (cls?" "+cls:""); };
23
  window.addEventListener("unhandledrejection", e => say("✗ unhandled: " + (e.reason && (e.reason.message||e.reason)), "no"));
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  const WGSL = `
26
  @group(0) @binding(0) var<storage, read> data : array<vec4<u32>>;
27
  @group(0) @binding(1) var<storage, read_write> sink : array<u32>;
@@ -48,15 +61,23 @@ fn main(@builtin(global_invocation_id) gid:vec3<u32>){
48
  dev.lost.then(i => say("✗ device lost: "+(i&&i.message||i.reason||""),"no"));
49
  dev.pushErrorScope("validation");
50
  const info=ad.info||{};
51
- // buffer capped by BOTH limits and 256 MB (safe on every GPU; we re-read it R times for signal)
52
- const bytes=Math.floor(Math.min(L.maxStorageBufferBindingSize, L.maxBufferSize, 256*1024*1024)/16)*16;
 
 
53
  const nVec=bytes/16;
54
  say("allocating "+(bytes/1048576).toFixed(0)+" MB…");
55
  const buf=dev.createBuffer({size:bytes, usage:GPUBufferUsage.STORAGE});
56
- const wg=Math.min(L.maxComputeWorkgroupsPerDimension,65535), TOTAL=wg*256, R=16;
57
  const sink=dev.createBuffer({size:TOTAL*4, usage:GPUBufferUsage.STORAGE});
58
  const P=dev.createBuffer({size:16, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});
59
  dev.queue.writeBuffer(P,0,new Uint32Array([nVec, TOTAL, R, 0]));
 
 
 
 
 
 
60
  const mod=dev.createShaderModule({code:WGSL});
61
  const ci=await mod.getCompilationInfo(); const er=ci.messages.filter(m=>m.type==="error");
62
  if(er.length){ say("✗ WGSL: "+er[0].message,"no"); return; }
@@ -65,6 +86,9 @@ fn main(@builtin(global_invocation_id) gid:vec3<u32>){
65
  const rb=dev.createBuffer({size:4, usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});
66
  const scopeErr = await dev.popErrorScope();
67
  if(scopeErr){ say("✗ GPU validation: "+scopeErr.message,"no"); return; }
 
 
 
68
  async function once(){ const e=dev.createCommandEncoder(); const p=e.beginComputePass(); p.setPipeline(pipe); p.setBindGroup(0,bg); p.dispatchWorkgroups(wg); p.end(); e.copyBufferToBuffer(sink,0,rb,0,4); const t0=performance.now(); dev.queue.submit([e.finish()]); await rb.mapAsync(GPUMapMode.READ); rb.unmap(); return performance.now()-t0; }
69
  say("timing "+(bytes/1048576*R).toFixed(0)+" MB reads…");
70
  await once();
 
22
  const say = (t,cls) => { st.textContent = t; st.className = "card" + (cls?" "+cls:""); };
23
  window.addEventListener("unhandledrejection", e => say("✗ unhandled: " + (e.reason && (e.reason.message||e.reason)), "no"));
24
 
25
+ // FILL: write a non-zero, non-compressible pattern so the read pass hits real VRAM
26
+ // (an uninitialised STORAGE buffer is zero/DCC-compressed → the memory controller
27
+ // never fetches it → measured bandwidth is fictional). Must run before timing.
28
+ const FILL = `
29
+ @group(0) @binding(0) var<storage, read_write> d : array<vec4<u32>>;
30
+ @group(0) @binding(1) var<uniform> P : vec4<u32>; // x=#vec4 elems, y=total threads
31
+ @compute @workgroup_size(256)
32
+ fn main(@builtin(global_invocation_id) gid:vec3<u32>){
33
+ let n=P.x; let stride=P.y; var i=gid.x;
34
+ loop { if(i>=n){break;}
35
+ d[i]=vec4<u32>(i*2654435761u+1u, i*40503u+7u, i^0x9e3779b9u, i*2246822519u+3u);
36
+ i=i+stride; }
37
+ }`;
38
  const WGSL = `
39
  @group(0) @binding(0) var<storage, read> data : array<vec4<u32>>;
40
  @group(0) @binding(1) var<storage, read_write> sink : array<u32>;
 
61
  dev.lost.then(i => say("✗ device lost: "+(i&&i.message||i.reason||""),"no"));
62
  dev.pushErrorScope("validation");
63
  const info=ad.info||{};
64
+ // Buffer must exceed the GPU's last-level cache (RDNA-3 Infinity Cache is up to 96 MB)
65
+ // so re-reads actually miss to VRAM. Aim as large as the device allows, floor 512 MB.
66
+ const wantBytes=Math.min(L.maxStorageBufferBindingSize, L.maxBufferSize, 1024*1024*1024);
67
+ const bytes=Math.floor(Math.max(512*1024*1024, wantBytes)/16)*16;
68
  const nVec=bytes/16;
69
  say("allocating "+(bytes/1048576).toFixed(0)+" MB…");
70
  const buf=dev.createBuffer({size:bytes, usage:GPUBufferUsage.STORAGE});
71
+ const wg=Math.min(L.maxComputeWorkgroupsPerDimension,65535), TOTAL=wg*256, R=4;
72
  const sink=dev.createBuffer({size:TOTAL*4, usage:GPUBufferUsage.STORAGE});
73
  const P=dev.createBuffer({size:16, usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});
74
  dev.queue.writeBuffer(P,0,new Uint32Array([nVec, TOTAL, R, 0]));
75
+ // fill pipeline (non-zero pattern) — its own bind group, same buffer
76
+ const fmod=dev.createShaderModule({code:FILL});
77
+ const fci=await fmod.getCompilationInfo(); const fer=fci.messages.filter(m=>m.type==="error");
78
+ if(fer.length){ say("✗ FILL WGSL: "+fer[0].message,"no"); return; }
79
+ const fpipe=dev.createComputePipeline({layout:"auto",compute:{module:fmod,entryPoint:"main"}});
80
+ const fbg=dev.createBindGroup({layout:fpipe.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:buf}},{binding:1,resource:{buffer:P}}]});
81
  const mod=dev.createShaderModule({code:WGSL});
82
  const ci=await mod.getCompilationInfo(); const er=ci.messages.filter(m=>m.type==="error");
83
  if(er.length){ say("✗ WGSL: "+er[0].message,"no"); return; }
 
86
  const rb=dev.createBuffer({size:4, usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});
87
  const scopeErr = await dev.popErrorScope();
88
  if(scopeErr){ say("✗ GPU validation: "+scopeErr.message,"no"); return; }
89
+ // write the non-zero pattern into VRAM before we time reads
90
+ say("filling "+(bytes/1048576).toFixed(0)+" MB with non-zero pattern…");
91
+ { const e=dev.createCommandEncoder(); const p=e.beginComputePass(); p.setPipeline(fpipe); p.setBindGroup(0,fbg); p.dispatchWorkgroups(wg); p.end(); dev.queue.submit([e.finish()]); await dev.queue.onSubmittedWorkDone(); }
92
  async function once(){ const e=dev.createCommandEncoder(); const p=e.beginComputePass(); p.setPipeline(pipe); p.setBindGroup(0,bg); p.dispatchWorkgroups(wg); p.end(); e.copyBufferToBuffer(sink,0,rb,0,4); const t0=performance.now(); dev.queue.submit([e.finish()]); await rb.mapAsync(GPUMapMode.READ); rb.unmap(); return performance.now()-t0; }
93
  say("timing "+(bytes/1048576*R).toFixed(0)+" MB reads…");
94
  await once();