Spaces:
Running
Running
GitHub Actions commited on
Commit ·
1683f65
1
Parent(s): 92ad589
sync from abhijitramesh/webgpu-bench@f0e4a60c2d
Browse files- js/app.js +8 -11
- js/data.js +34 -0
- js/tables.js +1 -10
js/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import { loadData, filterResults, selectBestResults, expandCpuRows,
|
| 2 |
import { initFilters, populateQuantOptions, getFilters, resetFilters } from './filters.js';
|
| 3 |
import { renderDecodeChart, renderPrefillChart, renderSizeChart, renderMachineChart, renderCpuGpuChart, renderSpeedupChart } from './charts.js';
|
| 4 |
import { renderResultsTable, renderErrorTable, renderMachineInfo, renderCpuGpuTable } from './tables.js';
|
|
@@ -76,17 +76,14 @@ function render() {
|
|
| 76 |
Chart.defaults.plugins.tooltip.bodyColor = isDark ? '#a1a1aa' : '#71717a';
|
| 77 |
|
| 78 |
const filters = getFilters();
|
| 79 |
-
// Filter,
|
| 80 |
-
//
|
| 81 |
-
//
|
| 82 |
-
//
|
| 83 |
-
//
|
| 84 |
-
// duplicates. withSyntheticCpuRows expands each browser-flow record's
|
| 85 |
-
// cpu_baseline_* into a sibling CPU row so CPU runs (CLI or browser)
|
| 86 |
-
// appear as their own row in the main table.
|
| 87 |
const filtered = selectBestResults(
|
| 88 |
-
|
| 89 |
-
);
|
| 90 |
|
| 91 |
// Summary cards — counts tween from previous value to new on filter changes
|
| 92 |
// and from 0 on first paint (since `data-value` defaults to "0").
|
|
|
|
| 1 |
+
import { loadData, filterResults, selectBestResults, expandCpuRows, attachCpuBaselineFromCpuRecords } from './data.js';
|
| 2 |
import { initFilters, populateQuantOptions, getFilters, resetFilters } from './filters.js';
|
| 3 |
import { renderDecodeChart, renderPrefillChart, renderSizeChart, renderMachineChart, renderCpuGpuChart, renderSpeedupChart } from './charts.js';
|
| 4 |
import { renderResultsTable, renderErrorTable, renderMachineInfo, renderCpuGpuTable } from './tables.js';
|
|
|
|
| 76 |
Chart.defaults.plugins.tooltip.bodyColor = isDark ? '#a1a1aa' : '#71717a';
|
| 77 |
|
| 78 |
const filters = getFilters();
|
| 79 |
+
// Filter, attach CPU baseline values (folds CLI-flow CPU records onto
|
| 80 |
+
// their GPU sibling so both submission paths produce one row per cell),
|
| 81 |
+
// collapse to one canonical row per (machine, browser, model, variant,
|
| 82 |
+
// backend), then drop the now-redundant CPU rows. The CPU numbers stay
|
| 83 |
+
// visible via the cpu_baseline_* columns on each GPU row.
|
|
|
|
|
|
|
|
|
|
| 84 |
const filtered = selectBestResults(
|
| 85 |
+
attachCpuBaselineFromCpuRecords(filterResults(appData.results, filters)),
|
| 86 |
+
).filter(r => r.nGpuLayers !== 0);
|
| 87 |
|
| 88 |
// Summary cards — counts tween from previous value to new on filter changes
|
| 89 |
// and from 0 on first paint (since `data-value` defaults to "0").
|
js/data.js
CHANGED
|
@@ -160,6 +160,40 @@ export function selectBestResults(records) {
|
|
| 160 |
return [...bestByCell.values()];
|
| 161 |
}
|
| 162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
/* Synthesize a CPU row for every browser-flow GPU record (the in-page
|
| 164 |
bench measures one CPU pass per variant alongside the GPU iterations
|
| 165 |
and stamps the result on the same record via cpu_baseline_*). Returns
|
|
|
|
| 160 |
return [...bestByCell.values()];
|
| 161 |
}
|
| 162 |
|
| 163 |
+
/* For CLI-flow records that ship CPU and GPU as separate dataset entries,
|
| 164 |
+
look up each GPU record's matching CPU companion (same machine, browser,
|
| 165 |
+
model, variant) and copy its perf into cpu_baseline_*. After this pass,
|
| 166 |
+
GPU records from both submission paths (browser, CLI) carry their CPU
|
| 167 |
+
baseline inline, so the main table can render a single row per cell with
|
| 168 |
+
both numbers side-by-side. No-op on records that already have
|
| 169 |
+
cpu_baseline_* (e.g. browser-flow records, where controller.makeRecord
|
| 170 |
+
embeds it at write time). */
|
| 171 |
+
export function attachCpuBaselineFromCpuRecords(results) {
|
| 172 |
+
const cpuByCell = new Map();
|
| 173 |
+
for (const r of results) {
|
| 174 |
+
if (r.nGpuLayers === 0 && r.status === 'done' && (r.decode_tok_s != null || r.prefill_tok_s != null)) {
|
| 175 |
+
const key = `${r.machineSlug}|${r.browser}|${r.model}|${r.variant}`;
|
| 176 |
+
const cur = cpuByCell.get(key);
|
| 177 |
+
// Most-recent wins on tiebreak — matches selectBestResults() semantics.
|
| 178 |
+
if (!cur || (r.timestamp || '') > (cur.timestamp || '')) {
|
| 179 |
+
cpuByCell.set(key, r);
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
}
|
| 183 |
+
return results.map(r => {
|
| 184 |
+
if (r.nGpuLayers === 0) return r;
|
| 185 |
+
if (r.cpu_baseline_decode_tok_s != null || r.cpu_baseline_prefill_tok_s != null) return r;
|
| 186 |
+
const key = `${r.machineSlug}|${r.browser}|${r.model}|${r.variant}`;
|
| 187 |
+
const cpu = cpuByCell.get(key);
|
| 188 |
+
if (!cpu) return r;
|
| 189 |
+
return {
|
| 190 |
+
...r,
|
| 191 |
+
cpu_baseline_decode_tok_s: cpu.decode_tok_s ?? null,
|
| 192 |
+
cpu_baseline_prefill_tok_s: cpu.prefill_tok_s ?? null,
|
| 193 |
+
};
|
| 194 |
+
});
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
/* Synthesize a CPU row for every browser-flow GPU record (the in-page
|
| 198 |
bench measures one CPU pass per variant alongside the GPU iterations
|
| 199 |
and stamps the result on the same record via cpu_baseline_*). Returns
|
js/tables.js
CHANGED
|
@@ -8,7 +8,7 @@ const NUM_KEYS = new Set([
|
|
| 8 |
'sizeMB', 'decode_tok_s', 'prefill_tok_s',
|
| 9 |
'cpu_baseline_decode_tok_s', 'cpu_baseline_prefill_tok_s',
|
| 10 |
'n_eval', 't_eval_ms',
|
| 11 |
-
'n_p_eval', 't_p_eval_ms', 'wallTimeMs', 'consistency_rate',
|
| 12 |
]);
|
| 13 |
|
| 14 |
function sortResults(results, key, dir) {
|
|
@@ -72,7 +72,6 @@ export function renderResultsTable(results) {
|
|
| 72 |
{ key: 'sizeMB', label: 'Size (MB)', priority: 3 },
|
| 73 |
{ key: 'browser', label: 'Browser', priority: 2 },
|
| 74 |
{ key: 'submittedBy', label: 'Submitter', priority: 2 },
|
| 75 |
-
{ key: 'nGpuLayers', label: 'Backend', priority: 2 },
|
| 76 |
{ key: 'status', label: 'Status', priority: 1 },
|
| 77 |
{ key: 'buildType', label: 'Build', priority: 3 },
|
| 78 |
{ key: 'webgpuAvailable', label: 'WebGPU', priority: 3 },
|
|
@@ -117,14 +116,6 @@ export function renderResultsTable(results) {
|
|
| 117 |
? '<span class="badge badge--pass">PASS</span>'
|
| 118 |
: '<span class="badge badge--fail">FAIL</span>';
|
| 119 |
break;
|
| 120 |
-
case 'nGpuLayers':
|
| 121 |
-
if (r.nGpuLayers != null) {
|
| 122 |
-
const isCpu = r.nGpuLayers === 0;
|
| 123 |
-
html += `<span class="badge ${isCpu ? 'badge--cpu' : 'badge--webgpu'}">${isCpu ? 'CPU' : 'WebGPU'}</span>`;
|
| 124 |
-
} else {
|
| 125 |
-
html += '<span class="text-muted">\u2014</span>';
|
| 126 |
-
}
|
| 127 |
-
break;
|
| 128 |
case 'webgpuAvailable':
|
| 129 |
html += r.webgpuAvailable
|
| 130 |
? '<span class="badge badge--yes">Yes</span>'
|
|
|
|
| 8 |
'sizeMB', 'decode_tok_s', 'prefill_tok_s',
|
| 9 |
'cpu_baseline_decode_tok_s', 'cpu_baseline_prefill_tok_s',
|
| 10 |
'n_eval', 't_eval_ms',
|
| 11 |
+
'n_p_eval', 't_p_eval_ms', 'wallTimeMs', 'consistency_rate',
|
| 12 |
]);
|
| 13 |
|
| 14 |
function sortResults(results, key, dir) {
|
|
|
|
| 72 |
{ key: 'sizeMB', label: 'Size (MB)', priority: 3 },
|
| 73 |
{ key: 'browser', label: 'Browser', priority: 2 },
|
| 74 |
{ key: 'submittedBy', label: 'Submitter', priority: 2 },
|
|
|
|
| 75 |
{ key: 'status', label: 'Status', priority: 1 },
|
| 76 |
{ key: 'buildType', label: 'Build', priority: 3 },
|
| 77 |
{ key: 'webgpuAvailable', label: 'WebGPU', priority: 3 },
|
|
|
|
| 116 |
? '<span class="badge badge--pass">PASS</span>'
|
| 117 |
: '<span class="badge badge--fail">FAIL</span>';
|
| 118 |
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
case 'webgpuAvailable':
|
| 120 |
html += r.webgpuAvailable
|
| 121 |
? '<span class="badge badge--yes">Yes</span>'
|