GitHub Actions commited on
Commit
aa422b0
Β·
1 Parent(s): ee944ff

sync from abhijitramesh/webgpu-bench@958b2720c3

Browse files
Files changed (1) hide show
  1. js/run/controller.js +63 -29
js/run/controller.js CHANGED
@@ -1187,10 +1187,13 @@ async function onRunStudyClick() {
1187
  return;
1188
  }
1189
  logLine(`Run study: selected ${checked.length} variants β€” starting run.`);
1190
- await onRunClick();
 
 
 
1191
  }
1192
 
1193
- async function onRunClick() {
1194
  // Run accepts any checked variant β€” uncached ones download just-in-time.
1195
  const variants = getCheckedVariants();
1196
  if (variants.length === 0) return;
@@ -1277,31 +1280,52 @@ async function onRunClick() {
1277
  writeRunIntent(v);
1278
 
1279
  row.setStatus('running', '');
1280
- const start = performance.now();
1281
- const variantResult = await runVariantWithIterations(v, row);
1282
- const wallTimeMs = performance.now() - start;
1283
 
1284
- const record = makeRecord(v, variantResult, machine, browser, wallTimeMs);
1285
- state.results.push(record);
1286
- row.fillFromRecord(record);
 
 
 
 
 
 
 
 
 
 
 
 
 
1287
 
1288
- clearRunIntent();
 
 
1289
 
1290
- try {
1291
- // sessionStorage so results survive in-tab navigations (the OAuth
1292
- // sign-in redirect in particular) but reset when the user actually
1293
- // closes the tab β€” they don't want stale results on a fresh visit.
1294
- sessionStorage.setItem(RESULTS_STORAGE_KEY, JSON.stringify(state.results));
1295
- } catch { /* quota */ }
1296
-
1297
- if (state.surface === 'localhost' && $('save-local')?.checked) {
1298
- fetch('/api/results', {
1299
- method: 'POST',
1300
- headers: { 'Content-Type': 'application/json' },
1301
- body: JSON.stringify(record),
1302
- }).catch(err => logLine(`POST /api/results failed: ${err.message}`));
 
 
 
 
 
 
 
1303
  }
1304
 
 
 
1305
  // Evict if enabled and this variant was downloaded this session. Files
1306
  // the user had cached before the run are always preserved.
1307
  if (evictAfter && state.sessionDownloads.has(cacheKey(v))) {
@@ -1461,11 +1485,18 @@ async function runBenchmarkInWorker(v, params, callbacks) {
1461
  // does both consistency forced-decoding and the llama-bench-style perf
1462
  // sweep β€” pp + tg with warmup + nReps timed reps each).
1463
  // Returns an aggregate that makeRecord consumes.
1464
- async function runVariantWithIterations(v, row) {
 
 
 
 
 
 
1465
  const nReps = Math.max(1, state.iterations || DEFAULT_ITERATIONS);
1466
  const nPrompt = Math.max(0, state.nPrompt ?? DEFAULT_N_PROMPT);
1467
  const nGen = Math.max(0, state.nGen ?? DEFAULT_N_GEN);
1468
- const nDepth = Math.max(0, state.nDepth ?? DEFAULT_N_DEPTH);
 
1469
  // Per-test n_ctx mirrors llama-bench (line 1211 of
1470
  // tools/llama-bench/llama-bench.cpp): sized to fit prompt+gen+depth so a
1471
  // raised depth doesn't silently overflow the cache.
@@ -1480,12 +1511,15 @@ async function runVariantWithIterations(v, row) {
1480
  const needCpuPass = runConsistency || runCpuPerf;
1481
 
1482
  // ─── CPU baseline ───
1483
- // Skipped entirely if both toggles disable it. Otherwise the pass mixes
1484
- // and matches: consistency_run captures token_ids; perf phase runs at
1485
- // nReps=1 (single warmup+timed rep β€” enough to populate the dashboard's
1486
- // CPU/GPU comparison without doubling CPU runtime).
 
1487
  let cpuResult;
1488
- if (needCpuPass) {
 
 
1489
  const phaseLabel = runConsistency && runCpuPerf ? 'reference tokens + 1-rep perf'
1490
  : runConsistency ? 'reference tokens'
1491
  : '1-rep perf';
 
1187
  return;
1188
  }
1189
  logLine(`Run study: selected ${checked.length} variants β€” starting run.`);
1190
+ // studyMode flips on the depth-pairing branch in runVariantWithIterations
1191
+ // so each variant produces both d=0 and d=N_DEPTH records (matches the
1192
+ // CLI runner's --study behavior).
1193
+ await onRunClick({ studyMode: true });
1194
  }
1195
 
1196
+ async function onRunClick({ studyMode = false } = {}) {
1197
  // Run accepts any checked variant β€” uncached ones download just-in-time.
1198
  const variants = getCheckedVariants();
1199
  if (variants.length === 0) return;
 
1280
  writeRunIntent(v);
1281
 
1282
  row.setStatus('running', '');
 
 
 
1283
 
1284
+ // Depth schedule for this variant. Study mode pairs d=0 with the
1285
+ // configured d=N so the dashboard can compare cold-cache against
1286
+ // depth-loaded numbers; non-study runs do a single pass at the user's
1287
+ // configured depth (default 2048). Mirrors the runner.js depth loop.
1288
+ const baseDepth = Math.max(0, state.nDepth ?? DEFAULT_N_DEPTH);
1289
+ const depthsToRun = (studyMode && baseDepth > 0) ? [0, baseDepth] : [baseDepth];
1290
+
1291
+ let sharedCpu = null;
1292
+ for (const nDepth of depthsToRun) {
1293
+ if (state.aborted) break;
1294
+ const start = performance.now();
1295
+ const variantResult = await runVariantWithIterations(v, row, {
1296
+ nDepth,
1297
+ cpuResult: sharedCpu,
1298
+ });
1299
+ const wallTimeMs = performance.now() - start;
1300
 
1301
+ const record = makeRecord(v, variantResult, machine, browser, wallTimeMs);
1302
+ state.results.push(record);
1303
+ row.fillFromRecord(record);
1304
 
1305
+ // Cache the CPU pass from the first depth so subsequent depth runs
1306
+ // skip it (CPU baseline is depth-independent).
1307
+ if (!sharedCpu && variantResult.cpu?.status === 'done') {
1308
+ sharedCpu = variantResult.cpu;
1309
+ }
1310
+
1311
+ try {
1312
+ // sessionStorage so results survive in-tab navigations (the OAuth
1313
+ // sign-in redirect in particular) but reset when the user actually
1314
+ // closes the tab β€” they don't want stale results on a fresh visit.
1315
+ sessionStorage.setItem(RESULTS_STORAGE_KEY, JSON.stringify(state.results));
1316
+ } catch { /* quota */ }
1317
+
1318
+ if (state.surface === 'localhost' && $('save-local')?.checked) {
1319
+ fetch('/api/results', {
1320
+ method: 'POST',
1321
+ headers: { 'Content-Type': 'application/json' },
1322
+ body: JSON.stringify(record),
1323
+ }).catch(err => logLine(`POST /api/results failed: ${err.message}`));
1324
+ }
1325
  }
1326
 
1327
+ clearRunIntent();
1328
+
1329
  // Evict if enabled and this variant was downloaded this session. Files
1330
  // the user had cached before the run are always preserved.
1331
  if (evictAfter && state.sessionDownloads.has(cacheKey(v))) {
 
1485
  // does both consistency forced-decoding and the llama-bench-style perf
1486
  // sweep β€” pp + tg with warmup + nReps timed reps each).
1487
  // Returns an aggregate that makeRecord consumes.
1488
+ //
1489
+ // `opts.nDepth` overrides state.nDepth so the caller can sweep multiple
1490
+ // depths per variant (study mode pairs d=0 with d=N).
1491
+ // `opts.cpuResult` when provided short-circuits the CPU baseline phase β€”
1492
+ // study mode runs CPU once on the d=0 pass and reuses it for d=N, since
1493
+ // reference tokens and the 1-rep CPU comparator are depth-independent.
1494
+ async function runVariantWithIterations(v, row, opts = {}) {
1495
  const nReps = Math.max(1, state.iterations || DEFAULT_ITERATIONS);
1496
  const nPrompt = Math.max(0, state.nPrompt ?? DEFAULT_N_PROMPT);
1497
  const nGen = Math.max(0, state.nGen ?? DEFAULT_N_GEN);
1498
+ const nDepth = Math.max(0, opts.nDepth ?? state.nDepth ?? DEFAULT_N_DEPTH);
1499
+ const reuseCpu = opts.cpuResult || null;
1500
  // Per-test n_ctx mirrors llama-bench (line 1211 of
1501
  // tools/llama-bench/llama-bench.cpp): sized to fit prompt+gen+depth so a
1502
  // raised depth doesn't silently overflow the cache.
 
1511
  const needCpuPass = runConsistency || runCpuPerf;
1512
 
1513
  // ─── CPU baseline ───
1514
+ // Skipped entirely if both toggles disable it OR caller provided a cached
1515
+ // result from an earlier depth pass. Otherwise the pass mixes and matches:
1516
+ // consistency_run captures token_ids; perf phase runs at nReps=1 (single
1517
+ // warmup+timed rep β€” enough to populate the dashboard's CPU/GPU comparison
1518
+ // without doubling CPU runtime).
1519
  let cpuResult;
1520
+ if (reuseCpu) {
1521
+ cpuResult = reuseCpu;
1522
+ } else if (needCpuPass) {
1523
  const phaseLabel = runConsistency && runCpuPerf ? 'reference tokens + 1-rep perf'
1524
  : runConsistency ? 'reference tokens'
1525
  : '1-rep perf';