Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Commit Β·
1dd6b75
1
Parent(s): 4a65a6b
made throughput visualization nicer
Browse files
app/src/content/embeds/d3-optimization-sweep.html
CHANGED
|
@@ -98,7 +98,6 @@
|
|
| 98 |
}
|
| 99 |
.d3-optimization-sweep .d3-tooltip .tip-label { color: var(--muted-color); }
|
| 100 |
.d3-optimization-sweep .d3-tooltip .tip-val { font-weight: 600; }
|
| 101 |
-
.d3-optimization-sweep .d3-tooltip .tip-best { color: var(--primary-color); font-weight: 700; }
|
| 102 |
.d3-optimization-sweep .d3-tooltip .tip-regression { color: #e05252; }
|
| 103 |
.d3-optimization-sweep .y-label-text {
|
| 104 |
font-size: 11px;
|
|
@@ -177,17 +176,18 @@
|
|
| 177 |
|
| 178 |
const familyPalette = getFamilyColors();
|
| 179 |
const familyColor = (family) => familyPalette[FAMILIES.indexOf(family)] || 'var(--primary-color)';
|
| 180 |
-
const BEST_COLOR = '#ee8a2a';
|
| 181 |
|
| 182 |
// D3 symbol generators for each tier
|
| 183 |
-
const SHAPE_SIZE =
|
| 184 |
-
const SHAPE_SIZE_BEST = 80;
|
| 185 |
const shapeGenerators = {
|
| 186 |
'Baseline': d3.symbol().type(d3.symbolCircle),
|
| 187 |
-
'Tier 0': d3.symbol().type(d3.
|
| 188 |
'Tier 1': d3.symbol().type(d3.symbolTriangle),
|
| 189 |
};
|
| 190 |
|
|
|
|
|
|
|
|
|
|
| 191 |
// ββ Tooltip ββ
|
| 192 |
let tip = container.querySelector('.d3-tooltip');
|
| 193 |
let tipInner;
|
|
@@ -235,12 +235,12 @@
|
|
| 235 |
}
|
| 236 |
|
| 237 |
// ββ Layout ββ
|
| 238 |
-
const margin = { top:
|
| 239 |
let width = 800, height = 500;
|
| 240 |
|
| 241 |
function updateSize() {
|
| 242 |
width = container.clientWidth || 800;
|
| 243 |
-
height = Math.max(400, DATA.length *
|
| 244 |
svg.attr('width', width).attr('height', height);
|
| 245 |
gRoot.attr('transform', `translate(${margin.left},${margin.top})`);
|
| 246 |
return { iw: width - margin.left - margin.right, ih: height - margin.top - margin.bottom };
|
|
@@ -289,6 +289,17 @@
|
|
| 289 |
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', '11px');
|
| 290 |
});
|
| 291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 292 |
// ββ X axis label ββ
|
| 293 |
const xLabel = state.metric === 'throughput' ? 'Tokens per second per GPU' : 'Speedup vs baseline';
|
| 294 |
gRoot.selectAll('.x-label').data([0]).join('text').attr('class', 'x-label')
|
|
@@ -332,36 +343,41 @@
|
|
| 332 |
// Remove speedup bars
|
| 333 |
gRoot.selectAll('.speedup-bar').remove();
|
| 334 |
|
| 335 |
-
// Connecting lines
|
| 336 |
-
const
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 343 |
.attr('class', 'conn-line')
|
| 344 |
-
.attr('
|
| 345 |
-
.attr('
|
| 346 |
.attr('stroke', d => familyColor(d.family))
|
| 347 |
-
.attr('stroke-width',
|
| 348 |
|
| 349 |
-
// Dots: 3 per model (baseline, tier0, tier1)
|
| 350 |
const dots = [];
|
| 351 |
data.forEach(d => {
|
| 352 |
-
const
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
|
|
|
| 356 |
});
|
| 357 |
|
| 358 |
gRoot.selectAll('.dot').data(dots, d => d.model + '-' + d.tier).join('path')
|
| 359 |
.attr('class', 'dot')
|
| 360 |
-
.attr('d', d => shapeGenerators[d.tier].size(
|
| 361 |
.attr('transform', d => `translate(${d.cx},${d.cy})`)
|
| 362 |
-
.attr('fill', d =>
|
| 363 |
-
.attr('stroke',
|
| 364 |
-
.attr('stroke-width', d => d.isBest ? 1.5 : 0)
|
| 365 |
.attr('opacity', 0.9)
|
| 366 |
.attr('cursor', 'pointer')
|
| 367 |
.on('mouseenter', function (event, d) {
|
|
@@ -384,8 +400,7 @@
|
|
| 384 |
.attr('x', iw + 6)
|
| 385 |
.attr('y', d => yScale(d.model) + bandH / 2)
|
| 386 |
.attr('dy', '0.35em')
|
| 387 |
-
.attr('fill',
|
| 388 |
-
.attr('font-weight', d => d.bestSpeedup >= 1.3 ? 700 : 400)
|
| 389 |
.text(d => d.bestSpeedup.toFixed(2) + 'x');
|
| 390 |
}
|
| 391 |
|
|
@@ -436,23 +451,20 @@
|
|
| 436 |
.attr('x', iw + 6)
|
| 437 |
.attr('y', d => yScale(d.model) + bandH / 2)
|
| 438 |
.attr('dy', '0.35em')
|
| 439 |
-
.attr('fill',
|
| 440 |
-
.attr('font-weight', d => d.bestSpeedup >= 1.3 ? 700 : 400)
|
| 441 |
.text(d => d.bestSpeedup.toFixed(2) + 'x');
|
| 442 |
}
|
| 443 |
|
| 444 |
function buildTooltip(d) {
|
| 445 |
const fmt = (v) => v.toLocaleString();
|
| 446 |
const spd = (v) => v.toFixed(2) + 'x';
|
| 447 |
-
const cls = (v) => v < 1.0 ? 'tip-regression' :
|
| 448 |
return `<div style="margin-bottom:4px"><strong>${d.model}</strong> <span class="tip-label">(${d.family})</span></div>`
|
| 449 |
+ `<div><span class="tip-label">Baseline:</span> <span class="tip-val">${fmt(d.baseTps)}</span> tps/gpu <span class="tip-label">(tp=${d.baseTp})</span></div>`
|
| 450 |
+ `<div><span class="tip-label">Tier 0:</span> <span class="${cls(d.t0Speedup)}">${fmt(d.t0Tps)}</span> tps/gpu <span class="${cls(d.t0Speedup)}">${spd(d.t0Speedup)}</span></div>`
|
| 451 |
+ `<div style="font-size:10px;color:var(--muted-color);margin-left:8px">${d.t0Params}</div>`
|
| 452 |
+ `<div><span class="tip-label">Tier 1:</span> <span class="${cls(d.t1Speedup)}">${fmt(d.t1Tps)}</span> tps/gpu <span class="${cls(d.t1Speedup)}">${spd(d.t1Speedup)}</span></div>`
|
| 453 |
-
+ `<div style="font-size:10px;color:var(--muted-color);margin-left:8px">${d.t1Params}</div>`
|
| 454 |
-
+ `<div style="margin-top:4px;border-top:1px solid var(--border-color);padding-top:4px"><span class="tip-label">Best:</span> <span class="tip-best">${fmt(d.bestTps)} tps/gpu (${spd(d.bestSpeedup)})</span></div>`
|
| 455 |
-
+ `<div style="font-size:10px;color:var(--muted-color);margin-left:8px">${d.bestParams}</div>`;
|
| 456 |
}
|
| 457 |
|
| 458 |
// ββ Controls ββ
|
|
@@ -462,7 +474,7 @@
|
|
| 462 |
const metricGroup = document.createElement('div'); metricGroup.className = 'control-group';
|
| 463 |
const metricLabel = document.createElement('label'); metricLabel.textContent = 'Metric'; metricLabel.setAttribute('for', 'metric-sel-optsweep');
|
| 464 |
const metricSel = document.createElement('select'); metricSel.id = 'metric-sel-optsweep';
|
| 465 |
-
[['throughput', 'Throughput
|
| 466 |
const o = document.createElement('option'); o.value = v; o.textContent = t; metricSel.appendChild(o);
|
| 467 |
});
|
| 468 |
metricSel.value = state.metric;
|
|
@@ -506,12 +518,6 @@
|
|
| 506 |
const txt = document.createElement('span'); txt.textContent = tier;
|
| 507 |
item.appendChild(swWrap); item.appendChild(txt); tierSection.appendChild(item);
|
| 508 |
});
|
| 509 |
-
// "Best" indicator
|
| 510 |
-
const bestItem = document.createElement('span'); bestItem.className = 'item';
|
| 511 |
-
const bestSw = document.createElement('span'); bestSw.className = 'swatch';
|
| 512 |
-
bestSw.style.background = BEST_COLOR; bestSw.style.border = '1.5px solid var(--text-color)';
|
| 513 |
-
const bestTxt = document.createElement('span'); bestTxt.textContent = 'Best';
|
| 514 |
-
bestItem.appendChild(bestSw); bestItem.appendChild(bestTxt); tierSection.appendChild(bestItem);
|
| 515 |
legend.appendChild(tierSection);
|
| 516 |
|
| 517 |
// Family colors section
|
|
|
|
| 98 |
}
|
| 99 |
.d3-optimization-sweep .d3-tooltip .tip-label { color: var(--muted-color); }
|
| 100 |
.d3-optimization-sweep .d3-tooltip .tip-val { font-weight: 600; }
|
|
|
|
| 101 |
.d3-optimization-sweep .d3-tooltip .tip-regression { color: #e05252; }
|
| 102 |
.d3-optimization-sweep .y-label-text {
|
| 103 |
font-size: 11px;
|
|
|
|
| 176 |
|
| 177 |
const familyPalette = getFamilyColors();
|
| 178 |
const familyColor = (family) => familyPalette[FAMILIES.indexOf(family)] || 'var(--primary-color)';
|
|
|
|
| 179 |
|
| 180 |
// D3 symbol generators for each tier
|
| 181 |
+
const SHAPE_SIZE = 42;
|
|
|
|
| 182 |
const shapeGenerators = {
|
| 183 |
'Baseline': d3.symbol().type(d3.symbolCircle),
|
| 184 |
+
'Tier 0': d3.symbol().type(d3.symbolSquare),
|
| 185 |
'Tier 1': d3.symbol().type(d3.symbolTriangle),
|
| 186 |
};
|
| 187 |
|
| 188 |
+
// Vertical offsets within each band: spread tiers apart
|
| 189 |
+
const TIER_Y_OFFSET = { 'Baseline': -0.5, 'Tier 0': 0, 'Tier 1': 0.5 };
|
| 190 |
+
|
| 191 |
// ββ Tooltip ββ
|
| 192 |
let tip = container.querySelector('.d3-tooltip');
|
| 193 |
let tipInner;
|
|
|
|
| 235 |
}
|
| 236 |
|
| 237 |
// ββ Layout ββ
|
| 238 |
+
const margin = { top: 24, right: 62, bottom: 42, left: 148 };
|
| 239 |
let width = 800, height = 500;
|
| 240 |
|
| 241 |
function updateSize() {
|
| 242 |
width = container.clientWidth || 800;
|
| 243 |
+
height = Math.max(400, DATA.length * 36 + margin.top + margin.bottom);
|
| 244 |
svg.attr('width', width).attr('height', height);
|
| 245 |
gRoot.attr('transform', `translate(${margin.left},${margin.top})`);
|
| 246 |
return { iw: width - margin.left - margin.right, ih: height - margin.top - margin.bottom };
|
|
|
|
| 289 |
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', '11px');
|
| 290 |
});
|
| 291 |
|
| 292 |
+
// ββ X axis top (mirrored ticks) ββ
|
| 293 |
+
const xAxisTopGen = state.metric === 'throughput'
|
| 294 |
+
? d3.axisTop(xScale).ticks(8).tickFormat(d => d >= 1000 ? (d / 1000) + 'k' : d)
|
| 295 |
+
: d3.axisTop(xScale).ticks(8).tickFormat(d => d.toFixed(1) + 'x');
|
| 296 |
+
gRoot.selectAll('.axis-x-top').data([0]).join('g').attr('class', 'axis-x-top')
|
| 297 |
+
.call(xAxisTopGen)
|
| 298 |
+
.call(g => {
|
| 299 |
+
g.selectAll('path, line').attr('stroke', 'var(--axis-color)');
|
| 300 |
+
g.selectAll('text').attr('fill', 'var(--tick-color)').style('font-size', '11px');
|
| 301 |
+
});
|
| 302 |
+
|
| 303 |
// ββ X axis label ββ
|
| 304 |
const xLabel = state.metric === 'throughput' ? 'Tokens per second per GPU' : 'Speedup vs baseline';
|
| 305 |
gRoot.selectAll('.x-label').data([0]).join('text').attr('class', 'x-label')
|
|
|
|
| 343 |
// Remove speedup bars
|
| 344 |
gRoot.selectAll('.speedup-bar').remove();
|
| 345 |
|
| 346 |
+
// Connecting lines between the three staggered dots
|
| 347 |
+
const connData = [];
|
| 348 |
+
data.forEach(d => {
|
| 349 |
+
const cyCenter = yScale(d.model) + bandH / 2;
|
| 350 |
+
const points = [
|
| 351 |
+
{ x: xScale(d.baseTps), y: cyCenter + TIER_Y_OFFSET['Baseline'] * bandH },
|
| 352 |
+
{ x: xScale(d.t0Tps), y: cyCenter + TIER_Y_OFFSET['Tier 0'] * bandH },
|
| 353 |
+
{ x: xScale(d.t1Tps), y: cyCenter + TIER_Y_OFFSET['Tier 1'] * bandH },
|
| 354 |
+
];
|
| 355 |
+
connData.push({ model: d.model, family: d.family, points });
|
| 356 |
+
});
|
| 357 |
+
const lineGen = d3.line().x(p => p.x).y(p => p.y);
|
| 358 |
+
gRoot.selectAll('.conn-line').data(connData, d => d.model).join('path')
|
| 359 |
.attr('class', 'conn-line')
|
| 360 |
+
.attr('d', d => lineGen(d.points))
|
| 361 |
+
.attr('fill', 'none')
|
| 362 |
.attr('stroke', d => familyColor(d.family))
|
| 363 |
+
.attr('stroke-width', 1.5).attr('opacity', 0.35);
|
| 364 |
|
| 365 |
+
// Dots: 3 per model (baseline, tier0, tier1) with vertical stagger
|
| 366 |
const dots = [];
|
| 367 |
data.forEach(d => {
|
| 368 |
+
const cyCenter = yScale(d.model) + bandH / 2;
|
| 369 |
+
['Baseline', 'Tier 0', 'Tier 1'].forEach(tier => {
|
| 370 |
+
const val = tier === 'Baseline' ? d.baseTps : tier === 'Tier 0' ? d.t0Tps : d.t1Tps;
|
| 371 |
+
dots.push({ ...d, tier, val, cx: xScale(val), cy: cyCenter + TIER_Y_OFFSET[tier] * bandH });
|
| 372 |
+
});
|
| 373 |
});
|
| 374 |
|
| 375 |
gRoot.selectAll('.dot').data(dots, d => d.model + '-' + d.tier).join('path')
|
| 376 |
.attr('class', 'dot')
|
| 377 |
+
.attr('d', d => shapeGenerators[d.tier].size(SHAPE_SIZE)())
|
| 378 |
.attr('transform', d => `translate(${d.cx},${d.cy})`)
|
| 379 |
+
.attr('fill', d => familyColor(d.family))
|
| 380 |
+
.attr('stroke', 'none')
|
|
|
|
| 381 |
.attr('opacity', 0.9)
|
| 382 |
.attr('cursor', 'pointer')
|
| 383 |
.on('mouseenter', function (event, d) {
|
|
|
|
| 400 |
.attr('x', iw + 6)
|
| 401 |
.attr('y', d => yScale(d.model) + bandH / 2)
|
| 402 |
.attr('dy', '0.35em')
|
| 403 |
+
.attr('fill', 'var(--muted-color)')
|
|
|
|
| 404 |
.text(d => d.bestSpeedup.toFixed(2) + 'x');
|
| 405 |
}
|
| 406 |
|
|
|
|
| 451 |
.attr('x', iw + 6)
|
| 452 |
.attr('y', d => yScale(d.model) + bandH / 2)
|
| 453 |
.attr('dy', '0.35em')
|
| 454 |
+
.attr('fill', 'var(--muted-color)')
|
|
|
|
| 455 |
.text(d => d.bestSpeedup.toFixed(2) + 'x');
|
| 456 |
}
|
| 457 |
|
| 458 |
function buildTooltip(d) {
|
| 459 |
const fmt = (v) => v.toLocaleString();
|
| 460 |
const spd = (v) => v.toFixed(2) + 'x';
|
| 461 |
+
const cls = (v) => v < 1.0 ? 'tip-regression' : 'tip-val';
|
| 462 |
return `<div style="margin-bottom:4px"><strong>${d.model}</strong> <span class="tip-label">(${d.family})</span></div>`
|
| 463 |
+ `<div><span class="tip-label">Baseline:</span> <span class="tip-val">${fmt(d.baseTps)}</span> tps/gpu <span class="tip-label">(tp=${d.baseTp})</span></div>`
|
| 464 |
+ `<div><span class="tip-label">Tier 0:</span> <span class="${cls(d.t0Speedup)}">${fmt(d.t0Tps)}</span> tps/gpu <span class="${cls(d.t0Speedup)}">${spd(d.t0Speedup)}</span></div>`
|
| 465 |
+ `<div style="font-size:10px;color:var(--muted-color);margin-left:8px">${d.t0Params}</div>`
|
| 466 |
+ `<div><span class="tip-label">Tier 1:</span> <span class="${cls(d.t1Speedup)}">${fmt(d.t1Tps)}</span> tps/gpu <span class="${cls(d.t1Speedup)}">${spd(d.t1Speedup)}</span></div>`
|
| 467 |
+
+ `<div style="font-size:10px;color:var(--muted-color);margin-left:8px">${d.t1Params}</div>`;
|
|
|
|
|
|
|
| 468 |
}
|
| 469 |
|
| 470 |
// ββ Controls ββ
|
|
|
|
| 474 |
const metricGroup = document.createElement('div'); metricGroup.className = 'control-group';
|
| 475 |
const metricLabel = document.createElement('label'); metricLabel.textContent = 'Metric'; metricLabel.setAttribute('for', 'metric-sel-optsweep');
|
| 476 |
const metricSel = document.createElement('select'); metricSel.id = 'metric-sel-optsweep';
|
| 477 |
+
[['throughput', 'Throughput'], ['speedup', 'Speedup']].forEach(([v, t]) => {
|
| 478 |
const o = document.createElement('option'); o.value = v; o.textContent = t; metricSel.appendChild(o);
|
| 479 |
});
|
| 480 |
metricSel.value = state.metric;
|
|
|
|
| 518 |
const txt = document.createElement('span'); txt.textContent = tier;
|
| 519 |
item.appendChild(swWrap); item.appendChild(txt); tierSection.appendChild(item);
|
| 520 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 521 |
legend.appendChild(tierSection);
|
| 522 |
|
| 523 |
// Family colors section
|