// Development check: run an example on the CPU and on the GPU and compare. // From the browser console: (await import('/src/devcompare.ts')).compare('drum', 0.1) import { relDiff } from "./sim/analysis"; import { simulateGPU } from "./sim/gpu"; import { runScript } from "./sim/runScript"; import { simulate } from "./sim/solver"; const helperSources = import.meta.glob("../matlab/helpers/*.m", { query: "?raw", import: "default", eager: true }) as Record; const exampleSources = import.meta.glob("../matlab/examples/*.m", { query: "?raw", import: "default", eager: true }) as Record; const helpers = Object.entries(helperSources).map(([path, source]) => ({ name: path.split("/").pop()!, source })); export async function compare(name: string, duration: number, edit: (s: string) => string = s => s) { const src = edit(exampleSources[`../matlab/examples/${name}.m`]); const { sys } = runScript(src, helpers, () => {}); sys.duration = duration; const cpu = simulate(sys); const gpu = await simulateGPU(sys); const fs = cpu.sampleRate; const peak = (a: Float32Array) => a.reduce((m, x) => Math.max(m, Math.abs(x)), 0); return { n: sys.n, substeps: cpu.substeps, cpuRealTime: cpu.elapsedMs / 1000 / duration, gpuRealTime: gpu.elapsedMs / 1000 / duration, aborted: gpu.aborted, diff: [0.001, 0.003, 0.01, 0.03, 0.1, duration].filter(t => t <= duration).map(t => [t, relDiff(cpu.audio, gpu.audio, Math.round(t * fs))]), peakCpu: peak(cpu.audio), peakGpu: peak(gpu.audio), driftCpu: cpu.energyDrift, driftGpu: gpu.energyDrift, energyEnd: [cpu.energy[cpu.energy.length - 1], gpu.energy[gpu.energy.length - 1]], dissEnd: [cpu.dissipated[cpu.dissipated.length - 1], gpu.dissipated[gpu.dissipated.length - 1]], }; }