/ proof-of-concept / cymbal2-webgpu
Sign in
proof-of-concept / cymbal2-webgpu
cymbal2-webgpu / src / heater.mjs
41 lines · 1.6 KBBlameHistoryRaw
1// Experiment: keep the GPU frequency governor boosted by running a small
2// continuous compute load (one workgroup) from a separate device, to
3// quantify how much of the multi-dispatch backend's time is the 300 MHz
4// idle clock rather than the work.
5import { installNodeWebGpu, requestDevice } from './gpu.mjs';
7async function main() {
8 await installNodeWebGpu();
9 const { device } = await requestDevice();
10 const code = `
11@group(0) @binding(0) var<storage, read_write> st: array<f32>;
12@compute @workgroup_size(64)
13fn main(@builtin(local_invocation_index) lid: u32) {
14 var x: f32 = st[lid];
15 for (var i: u32 = 0u; i < 15000u; i = i + 1u) {
16 x = x * 1.0000001 + 1e-8;
17 }
18 st[lid] = x;
19}`;
20 const module = device.createShaderModule({ code });
21 const pipeline = device.createComputePipeline({ layout: 'auto', compute: { module, entryPoint: 'main' } });
22 const buf = device.createBuffer({ size: 256, usage: GPUBufferUsage.STORAGE });
23 const bg = device.createBindGroup({
24 layout: pipeline.getBindGroupLayout(0),
25 entries: [{ binding: 0, resource: { buffer: buf } }],
26 });
27 const secs = Number(process.argv[2] ?? 30);
28 const t0 = performance.now();
29 while (performance.now() - t0 < secs * 1000) {
30 const enc = device.createCommandEncoder();
31 const pass = enc.beginComputePass();
32 pass.setPipeline(pipeline);
33 pass.setBindGroup(0, bg);
34 pass.dispatchWorkgroups(1);
35 pass.end();
36 device.queue.submit([enc.finish()]);
37 await device.queue.onSubmittedWorkDone();
38 }
41main().then(() => process.exit(0)).catch((e) => { console.error(e); process.exit(1); });
↑↓ move↵openescclose