Sync from HWu0101/Local-LLM-Hardware-Explorer via hub-sync
Browse files- index.html +69 -44
index.html
CHANGED
|
@@ -1122,7 +1122,18 @@
|
|
| 1122 |
const fast = ks.slice().sort((x, y) => GPUC[y].bw - GPUC[x].bw)[0];
|
| 1123 |
// Prefill compute is set by the FASTEST card, not the harmonic mean:
|
| 1124 |
// a GEMM runs on one device at a time under layer split.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1125 |
const pfKey = fast;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1126 |
// A build counts as server-class if ANY card in it is. Those are passive-cooled
|
| 1127 |
// parts that need chassis airflow, so they are kept out of the machine cards
|
| 1128 |
// (reachable through the custom builder) but still plotted on the staircase.
|
|
@@ -1141,7 +1152,7 @@
|
|
| 1141 |
return {
|
| 1142 |
k: ks.map(k => k + (c[k] > 1 ? 'x' + c[k] : '')).join('_'), n: nm, s: nm, mine: mine, c: c,
|
| 1143 |
vram: vram, bw: bw, slots: slots, p: price,
|
| 1144 |
-
pfKey: pfKey, srv: srv,
|
| 1145 |
alt: ks.length > 1 ? { vram: GPUC[fast].vram, bwFast: GPUC[fast].bw } : null,
|
| 1146 |
tp: (ks.length === 1 && c[ks[0]] >= 2) ? TPF[c[ks[0]]] : null,
|
| 1147 |
tpSet: (ks.length > 1 && tpSet) ? tpSet : null
|
|
@@ -1177,6 +1188,36 @@
|
|
| 1177 |
};
|
| 1178 |
const myCpu = () => CPUP[RIG.cpu] || CPUP.arrow;
|
| 1179 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1180 |
// PCIe effective bandwidth, GB/s, by generation at x16.
|
| 1181 |
const PCIE = { 3: 11, 4: 24, 5: 55 };
|
| 1182 |
|
|
@@ -1450,7 +1491,8 @@
|
|
| 1450 |
vram: g.vram, ram: r.ram, bwFast: g.bw,
|
| 1451 |
bwSlow: pl.cpuKey ? numaBW(CPUP[pl.cpuKey], 'distribute').bw : r.bw,
|
| 1452 |
res: pl.res, gpus: g.slots, plat: pl.k, cpuKey: pl.cpuKey,
|
| 1453 |
-
pfKey: g.pfKey,
|
|
|
|
| 1454 |
alt: g.alt, tp: g.tp, tpSet: g.tpSet, mine: (pl.k === 'd' && g.mine && r.k === 'cur'),
|
| 1455 |
price: pl.base + g.p + r.p, ovh: .0012
|
| 1456 |
});
|
|
@@ -1459,31 +1501,31 @@
|
|
| 1459 |
HW.push(
|
| 1460 |
{
|
| 1461 |
id: 'halo', name: 'Framework Desktop', meta: 'Strix Halo \u00b7 128GB unified \u00b7 215 GB/s',
|
| 1462 |
-
vram: 128, ram: 0, bwFast: 165, bwSlow: 165, res: 14, price: 6069, unified: 1, ovh: .0012
|
| 1463 |
},
|
| 1464 |
{
|
| 1465 |
id: 'spark', name: 'NVIDIA DGX Spark', meta: 'GB10 \u00b7 128GB unified \u00b7 273 GB/s',
|
| 1466 |
-
vram: 128, ram: 0, bwFast: 175, bwSlow: 175, res: 14, price: 7999, unified: 1, ovh: .0012
|
| 1467 |
},
|
| 1468 |
{
|
| 1469 |
id: 'mac', name: 'Mac Studio M3 Ultra', meta: '96GB unified \u00b7 819 GB/s \u00b7 96GB is the max sold',
|
| 1470 |
-
vram: 96, ram: 0, bwFast: 214, bwSlow: 214, res: 14, price: 9099, unified: 1, ovh: .0012
|
| 1471 |
},
|
| 1472 |
{
|
| 1473 |
id: 'm5max', name: 'MacBook Pro M5 Max', meta: '128GB unified \u00b7 614 GB/s \u00b7 40-core \u00b7 buyable new',
|
| 1474 |
-
vram: 128, ram: 0, bwFast: 262, bwSlow: 262, res: 16, price: 9999, unified: 1, ovh: .0012
|
| 1475 |
},
|
| 1476 |
{
|
| 1477 |
id: 'mac256', name: 'Mac Studio 256GB (grey)', meta: 'M3 Ultra 256GB \u00b7 pulled May 2026 \u00b7 AU resale',
|
| 1478 |
-
vram: 256, ram: 0, bwFast: 214, bwSlow: 214, res: 14, price: 29999, unified: 1, ovh: .0012
|
| 1479 |
},
|
| 1480 |
{
|
| 1481 |
id: 'mac512', name: 'Mac Studio 512GB (grey)', meta: 'M3 Ultra 512GB \u00b7 pulled Mar 2026 \u00b7 US resale',
|
| 1482 |
-
vram: 512, ram: 0, bwFast: 214, bwSlow: 214, res: 14, price: 36800, unified: 1, ovh: .0012
|
| 1483 |
},
|
| 1484 |
{
|
| 1485 |
id: 'gb300', name: 'DGX Station GB300', meta: '252GB HBM3e + 496GB LPDDR5X \u00b7 Grace Blackwell Ultra',
|
| 1486 |
-
vram: 252, ram: 496, bwFast: 2400, bwSlow: 350, res: 20, price: 134600, ovh: .0012,
|
| 1487 |
gpus: 1, plat: 'g', link: 'NVLink-C2C at 900 GB/s, not PCIe'
|
| 1488 |
});
|
| 1489 |
|
|
@@ -1514,7 +1556,8 @@
|
|
| 1514 |
id: 'custom', name: 'Custom build',
|
| 1515 |
meta: g.n + ' \u00b7 ' + ramGB + 'GB \u00b7 ' + plName + (g.slots > 1 ? ' \u00b7 layer-split' : ''),
|
| 1516 |
vram: g.vram, ram: ramGB, bwFast: g.bw, bwSlow: bw, res: res, gpus: g.slots, plat: CUSTOM.plat,
|
| 1517 |
-
pfKey: g.pfKey,
|
|
|
|
| 1518 |
alt: g.alt, tp: g.tp, tpSet: g.tpSet, custom: 1,
|
| 1519 |
price: pl.base + g.p + ramP, ovh: .0012
|
| 1520 |
};
|
|
@@ -1600,35 +1643,6 @@
|
|
| 1600 |
// only 33.8%, with the gap being per-token dispatch structure, not matmul
|
| 1601 |
// speed. Discrete GPUs suffer most; unified memory sees a milder version;
|
| 1602 |
// CPU-resident experts do not pay it at all (no kernel launches).
|
| 1603 |
-
// ---- prefill ------------------------------------------------------------
|
| 1604 |
-
// Prefill is a different physical regime from decode. Decode is a batch-1 GEMV:
|
| 1605 |
-
// it reads every active byte to emit one token, so it is memory-bound. Prefill
|
| 1606 |
-
// is a GEMM over the whole prompt: weights are read once and reused across the
|
| 1607 |
-
// batch, so it is compute-bound while resident, and TRANSFER-bound when the
|
| 1608 |
-
// weights live in system RAM.
|
| 1609 |
-
//
|
| 1610 |
-
// pf = effective prefill TFLOPS, i.e. what the runtime actually sustains, not
|
| 1611 |
-
// the marketing figure. Only two clean anchors exist:
|
| 1612 |
-
// Qwen3.5-35B-A3B Q4, RTX 5090, fully resident: pp about 6900 t/s
|
| 1613 |
-
// -> 6900 x 2 x 3e9 = 41.4 TFLOPS (SRC.prefill)
|
| 1614 |
-
// V4-Flash, RTX PRO 6000 + dual EPYC, saturated: pp 3144 t/s
|
| 1615 |
-
// -> 3144 x 2 x 13e9 = 81.7 TFLOPS, but ~47% of weights were off the card,
|
| 1616 |
-
// so this is a LOWER bound on resident compute (SRC.userbench)
|
| 1617 |
-
// Everything else is scaled by class off those two and is an ESTIMATE. The
|
| 1618 |
-
// implied PRO 6000 / 5090 ratio is 1.97x where the dies are within ~1.1x, so
|
| 1619 |
-
// the spread is runtime and model, not silicon -- which is exactly why these
|
| 1620 |
-
// are not presented as measurements.
|
| 1621 |
-
const PFTF = {
|
| 1622 |
-
'4060ti': 8, '4060ti16': 8, '5060ti': 12, '5070': 18, '4070tis': 20,
|
| 1623 |
-
'5070ti': 26, '4080s': 24, '5080': 28, '3090': 16, '4090': 32,
|
| 1624 |
-
'5090': 41.4, 'pro6000': 81.7, 'pro4000': 20, 'pro4500': 30,
|
| 1625 |
-
'pro5000': 55, '6000ada': 30, 'a6000': 18,
|
| 1626 |
-
// Server parts. Scaled by class off the 5090 anchor; datacentre silicon has
|
| 1627 |
-
// far more peak FP16 than llama.cpp extracts, so these are deliberately well
|
| 1628 |
-
// below the marketing figure and remain estimates.
|
| 1629 |
-
'v100': 18, 'a30': 26, 'l4': 14, 'a40': 20, 'l40s': 42,
|
| 1630 |
-
'a100': 55, 'a100x': 60, 'h100': 110, 'h100n': 125, 'h200': 130
|
| 1631 |
-
};
|
| 1632 |
// llama.cpp streams CPU-resident experts to the GPU for any batch over this
|
| 1633 |
// many tokens (GGML_OP_OFFLOAD_MIN_BATCH). Below it the experts are computed on
|
| 1634 |
// the CPU instead. This threshold is why offloaded prefill and offloaded decode
|
|
@@ -1833,8 +1847,13 @@
|
|
| 1833 |
const r = calc(m, hw);
|
| 1834 |
if (r.fit === 'none') return { fit: 'none' };
|
| 1835 |
const act = m.active; // billions, active per token
|
| 1836 |
-
|
| 1837 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1838 |
|
| 1839 |
// Unified-memory machines have no link to cross: weights are already where
|
| 1840 |
// the compute is, so prefill is purely compute-bound.
|
|
@@ -1844,8 +1863,7 @@
|
|
| 1844 |
|
| 1845 |
// Resident compute. On a CPU-only or unified box, fall back to a bandwidth
|
| 1846 |
// proxy rather than asserting a FLOPS figure we do not have.
|
| 1847 |
-
const Rcomp = tf ?
|
| 1848 |
-
: Math.max(60, hw.bwFast / Math.max(0.5, act) * 4);
|
| 1849 |
|
| 1850 |
const lanes = hw.pcieGBs || PCIE[5];
|
| 1851 |
const passes = Math.max(1, Math.ceil(N / UBATCH));
|
|
@@ -2670,7 +2688,14 @@
|
|
| 2670 |
: pp.bound === 'attention'
|
| 2671 |
? 'Attention is dominating at this prompt length; it grows with the square of the prompt, ' +
|
| 2672 |
'so doubling the prompt roughly quadruples this share.'
|
| 2673 |
-
: 'Compute-bound, which is the healthy case: the weights are on the card and the GPU is busy.'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2674 |
0.6);
|
| 2675 |
}
|
| 2676 |
|
|
|
|
| 1122 |
const fast = ks.slice().sort((x, y) => GPUC[y].bw - GPUC[x].bw)[0];
|
| 1123 |
// Prefill compute is set by the FASTEST card, not the harmonic mean:
|
| 1124 |
// a GEMM runs on one device at a time under layer split.
|
| 1125 |
+
// pfKey stays the highest-BANDWIDTH card because that is what decides PCIe
|
| 1126 |
+
// generation. Prefill compute is a different question and must not reuse it:
|
| 1127 |
+
// a 3090 has more bandwidth than a 5080 but less compute, so picking by
|
| 1128 |
+
// bandwidth made adding one LOWER prefill.
|
| 1129 |
const pfKey = fast;
|
| 1130 |
+
// Layer split runs layers in sequence, each on the card that holds it, so the
|
| 1131 |
+
// build's prefill rate is the capacity-weighted harmonic mean of its cards --
|
| 1132 |
+
// the same structure already used for memory bandwidth.
|
| 1133 |
+
const pfTF = vram / ks.reduce((t, k) => t + GPUC[k].vram * c[k] / (PFTF[k] || 20), 0);
|
| 1134 |
+
// If the model fits on the best-compute card alone you would simply run it
|
| 1135 |
+
// there, so carry that card's rate and its VRAM as the alternative.
|
| 1136 |
+
const pfCard = ks.slice().sort((x, y) => (PFTF[y] || 20) - (PFTF[x] || 20))[0];
|
| 1137 |
// A build counts as server-class if ANY card in it is. Those are passive-cooled
|
| 1138 |
// parts that need chassis airflow, so they are kept out of the machine cards
|
| 1139 |
// (reachable through the custom builder) but still plotted on the staircase.
|
|
|
|
| 1152 |
return {
|
| 1153 |
k: ks.map(k => k + (c[k] > 1 ? 'x' + c[k] : '')).join('_'), n: nm, s: nm, mine: mine, c: c,
|
| 1154 |
vram: vram, bw: bw, slots: slots, p: price,
|
| 1155 |
+
pfKey: pfKey, pfTF: pfTF, pfBest: (PFTF[pfCard] || 20), pfBestVram: GPUC[pfCard].vram, srv: srv,
|
| 1156 |
alt: ks.length > 1 ? { vram: GPUC[fast].vram, bwFast: GPUC[fast].bw } : null,
|
| 1157 |
tp: (ks.length === 1 && c[ks[0]] >= 2) ? TPF[c[ks[0]]] : null,
|
| 1158 |
tpSet: (ks.length > 1 && tpSet) ? tpSet : null
|
|
|
|
| 1188 |
};
|
| 1189 |
const myCpu = () => CPUP[RIG.cpu] || CPUP.arrow;
|
| 1190 |
|
| 1191 |
+
// ---- prefill ------------------------------------------------------------
|
| 1192 |
+
// Prefill is a different physical regime from decode. Decode is a batch-1 GEMV:
|
| 1193 |
+
// it reads every active byte to emit one token, so it is memory-bound. Prefill
|
| 1194 |
+
// is a GEMM over the whole prompt: weights are read once and reused across the
|
| 1195 |
+
// batch, so it is compute-bound while resident, and TRANSFER-bound when the
|
| 1196 |
+
// weights live in system RAM.
|
| 1197 |
+
//
|
| 1198 |
+
// pf = effective prefill TFLOPS, i.e. what the runtime actually sustains, not
|
| 1199 |
+
// the marketing figure. Only two clean anchors exist:
|
| 1200 |
+
// Qwen3.5-35B-A3B Q4, RTX 5090, fully resident: pp about 6900 t/s
|
| 1201 |
+
// -> 6900 x 2 x 3e9 = 41.4 TFLOPS (SRC.prefill)
|
| 1202 |
+
// V4-Flash, RTX PRO 6000 + dual EPYC, saturated: pp 3144 t/s
|
| 1203 |
+
// -> 3144 x 2 x 13e9 = 81.7 TFLOPS, but ~47% of weights were off the card,
|
| 1204 |
+
// so this is a LOWER bound on resident compute (SRC.userbench)
|
| 1205 |
+
// Everything else is scaled by class off those two and is an ESTIMATE. The
|
| 1206 |
+
// implied PRO 6000 / 5090 ratio is 1.97x where the dies are within ~1.1x, so
|
| 1207 |
+
// the spread is runtime and model, not silicon -- which is exactly why these
|
| 1208 |
+
// are not presented as measurements.
|
| 1209 |
+
const PFTF = {
|
| 1210 |
+
'4060ti': 8, '4060ti16': 8, '5060ti': 12, '5070': 18, '4070tis': 20,
|
| 1211 |
+
'5070ti': 26, '4080s': 24, '5080': 28, '3090': 16, '4090': 32,
|
| 1212 |
+
'5090': 41.4, 'pro6000': 81.7, 'pro4000': 20, 'pro4500': 30,
|
| 1213 |
+
'pro5000': 55, '6000ada': 30, 'a6000': 18,
|
| 1214 |
+
// Server parts. Scaled by class off the 5090 anchor; datacentre silicon has
|
| 1215 |
+
// far more peak FP16 than llama.cpp extracts, so these are deliberately well
|
| 1216 |
+
// below the marketing figure and remain estimates.
|
| 1217 |
+
'v100': 18, 'a30': 26, 'l4': 14, 'a40': 20, 'l40s': 42,
|
| 1218 |
+
'a100': 55, 'a100x': 60, 'h100': 110, 'h100n': 125, 'h200': 130
|
| 1219 |
+
};
|
| 1220 |
+
|
| 1221 |
// PCIe effective bandwidth, GB/s, by generation at x16.
|
| 1222 |
const PCIE = { 3: 11, 4: 24, 5: 55 };
|
| 1223 |
|
|
|
|
| 1491 |
vram: g.vram, ram: r.ram, bwFast: g.bw,
|
| 1492 |
bwSlow: pl.cpuKey ? numaBW(CPUP[pl.cpuKey], 'distribute').bw : r.bw,
|
| 1493 |
res: pl.res, gpus: g.slots, plat: pl.k, cpuKey: pl.cpuKey,
|
| 1494 |
+
pfKey: g.pfKey, pfTF: g.pfTF, pfBest: g.pfBest, pfBestVram: g.pfBestVram,
|
| 1495 |
+
srv: g.srv, pcieGBs: pcieFor(pl.k, g.slots, g.pfKey),
|
| 1496 |
alt: g.alt, tp: g.tp, tpSet: g.tpSet, mine: (pl.k === 'd' && g.mine && r.k === 'cur'),
|
| 1497 |
price: pl.base + g.p + r.p, ovh: .0012
|
| 1498 |
});
|
|
|
|
| 1501 |
HW.push(
|
| 1502 |
{
|
| 1503 |
id: 'halo', name: 'Framework Desktop', meta: 'Strix Halo \u00b7 128GB unified \u00b7 215 GB/s',
|
| 1504 |
+
vram: 128, ram: 0, bwFast: 165, bwSlow: 165, res: 14, pfTF: 6.6, pfBestVram: 9999, pfBest: 6.6, price: 6069, unified: 1, ovh: .0012
|
| 1505 |
},
|
| 1506 |
{
|
| 1507 |
id: 'spark', name: 'NVIDIA DGX Spark', meta: 'GB10 \u00b7 128GB unified \u00b7 273 GB/s',
|
| 1508 |
+
vram: 128, ram: 0, bwFast: 175, bwSlow: 175, res: 14, pfTF: 18.4, pfBestVram: 9999, pfBest: 18.4, price: 7999, unified: 1, ovh: .0012
|
| 1509 |
},
|
| 1510 |
{
|
| 1511 |
id: 'mac', name: 'Mac Studio M3 Ultra', meta: '96GB unified \u00b7 819 GB/s \u00b7 96GB is the max sold',
|
| 1512 |
+
vram: 96, ram: 0, bwFast: 214, bwSlow: 214, res: 14, pfTF: 6.6, pfBestVram: 9999, pfBest: 6.6, price: 9099, unified: 1, ovh: .0012
|
| 1513 |
},
|
| 1514 |
{
|
| 1515 |
id: 'm5max', name: 'MacBook Pro M5 Max', meta: '128GB unified \u00b7 614 GB/s \u00b7 40-core \u00b7 buyable new',
|
| 1516 |
+
vram: 128, ram: 0, bwFast: 262, bwSlow: 262, res: 16, pfTF: 8.7, pfBestVram: 9999, pfBest: 8.7, price: 9999, unified: 1, ovh: .0012
|
| 1517 |
},
|
| 1518 |
{
|
| 1519 |
id: 'mac256', name: 'Mac Studio 256GB (grey)', meta: 'M3 Ultra 256GB \u00b7 pulled May 2026 \u00b7 AU resale',
|
| 1520 |
+
vram: 256, ram: 0, bwFast: 214, bwSlow: 214, res: 14, pfTF: 6.6, pfBestVram: 9999, pfBest: 6.6, price: 29999, unified: 1, ovh: .0012
|
| 1521 |
},
|
| 1522 |
{
|
| 1523 |
id: 'mac512', name: 'Mac Studio 512GB (grey)', meta: 'M3 Ultra 512GB \u00b7 pulled Mar 2026 \u00b7 US resale',
|
| 1524 |
+
vram: 512, ram: 0, bwFast: 214, bwSlow: 214, res: 14, pfTF: 6.6, pfBestVram: 9999, pfBest: 6.6, price: 36800, unified: 1, ovh: .0012
|
| 1525 |
},
|
| 1526 |
{
|
| 1527 |
id: 'gb300', name: 'DGX Station GB300', meta: '252GB HBM3e + 496GB LPDDR5X \u00b7 Grace Blackwell Ultra',
|
| 1528 |
+
vram: 252, ram: 496, bwFast: 2400, bwSlow: 350, res: 20, pfTF: 60, pfBestVram: 9999, pfBest: 60, price: 134600, ovh: .0012,
|
| 1529 |
gpus: 1, plat: 'g', link: 'NVLink-C2C at 900 GB/s, not PCIe'
|
| 1530 |
});
|
| 1531 |
|
|
|
|
| 1556 |
id: 'custom', name: 'Custom build',
|
| 1557 |
meta: g.n + ' \u00b7 ' + ramGB + 'GB \u00b7 ' + plName + (g.slots > 1 ? ' \u00b7 layer-split' : ''),
|
| 1558 |
vram: g.vram, ram: ramGB, bwFast: g.bw, bwSlow: bw, res: res, gpus: g.slots, plat: CUSTOM.plat,
|
| 1559 |
+
pfKey: g.pfKey, pfTF: g.pfTF, pfBest: g.pfBest, pfBestVram: g.pfBestVram,
|
| 1560 |
+
pcieGBs: pcieFor(CUSTOM.plat, g.slots, g.pfKey),
|
| 1561 |
alt: g.alt, tp: g.tp, tpSet: g.tpSet, custom: 1,
|
| 1562 |
price: pl.base + g.p + ramP, ovh: .0012
|
| 1563 |
};
|
|
|
|
| 1643 |
// only 33.8%, with the gap being per-token dispatch structure, not matmul
|
| 1644 |
// speed. Discrete GPUs suffer most; unified memory sees a milder version;
|
| 1645 |
// CPU-resident experts do not pay it at all (no kernel launches).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1646 |
// llama.cpp streams CPU-resident experts to the GPU for any batch over this
|
| 1647 |
// many tokens (GGML_OP_OFFLOAD_MIN_BATCH). Below it the experts are computed on
|
| 1648 |
// the CPU instead. This threshold is why offloaded prefill and offloaded decode
|
|
|
|
| 1847 |
const r = calc(m, hw);
|
| 1848 |
if (r.fit === 'none') return { fit: 'none' };
|
| 1849 |
const act = m.active; // billions, active per token
|
| 1850 |
+
// Effective prefill TFLOPS for this machine. Every machine now has one --
|
| 1851 |
+
// fixed and unified boxes carry pfTF directly -- so no build falls through to
|
| 1852 |
+
// a different formula. Comparing a PFTF-derived rate against a bandwidth proxy
|
| 1853 |
+
// was what made Strix Halo read as 0.0x against a 5080.
|
| 1854 |
+
const disp0 = hw.unified ? 0 : (OSVRAM[RIG.os] !== undefined ? OSVRAM[RIG.os] : 3);
|
| 1855 |
+
const fitsBest = hw.pfBestVram && (m.gb + kvGB(m) + 1) <= (hw.pfBestVram - disp0);
|
| 1856 |
+
const tf = fitsBest ? hw.pfBest : (hw.pfTF || null);
|
| 1857 |
|
| 1858 |
// Unified-memory machines have no link to cross: weights are already where
|
| 1859 |
// the compute is, so prefill is purely compute-bound.
|
|
|
|
| 1863 |
|
| 1864 |
// Resident compute. On a CPU-only or unified box, fall back to a bandwidth
|
| 1865 |
// proxy rather than asserting a FLOPS figure we do not have.
|
| 1866 |
+
const Rcomp = (tf ? tf : 20) * 1e12 / (2 * act * 1e9);
|
|
|
|
| 1867 |
|
| 1868 |
const lanes = hw.pcieGBs || PCIE[5];
|
| 1869 |
const passes = Math.max(1, Math.ceil(N / UBATCH));
|
|
|
|
| 2688 |
: pp.bound === 'attention'
|
| 2689 |
? 'Attention is dominating at this prompt length; it grows with the square of the prompt, ' +
|
| 2690 |
'so doubling the prompt roughly quadruples this share.'
|
| 2691 |
+
: 'Compute-bound, which is the healthy case: the weights are on the card and the GPU is busy.' +
|
| 2692 |
+
((hw.gpus || 0) > 1 && hw.pfTF && hw.pfBest && hw.pfTF < hw.pfBest * 0.9
|
| 2693 |
+
? ' Note the mixed pair costs you here: layer split runs layers in SEQUENCE, so the '
|
| 2694 |
+
+ 'slower card sets the pace in proportion to how many layers its VRAM holds. This build '
|
| 2695 |
+
+ 'converts ' + hw.pfTF.toFixed(0) + ' effective TFLOPS against ' + hw.pfBest.toFixed(0)
|
| 2696 |
+
+ ' for its fastest card alone. Extra VRAM buys decode residency and costs prefill compute '
|
| 2697 |
+
+ '— a real trade, not a rounding error.'
|
| 2698 |
+
: ''),
|
| 2699 |
0.6);
|
| 2700 |
}
|
| 2701 |
|