95 % busy, 1–7 % multiplying: why a sparse MoE leaves GPU compute idle
TFLOPs only come from big multiplications. A mixture-of-experts layer splits each batch 512 ways, so each expert’s weights are read from memory and used for a handful of rows — the GPU’s cores spend their time waiting for weights and launching small kernels, not multiplying.
6,144 CUDA cores, three workloads
One square = one core, time-averaged; nvidia-smi reads ~95 % in all three.
| multiplying | waiting on memory | other | nvidia-smi | |
|---|---|---|---|---|
| Dense benchmark | 5,898 | 246 | 0 | ~95 % |
| Prefill step | ≤ 430 | 1,167 | 4,547 | ~95 % |
| Decode step | ~37 | 3,686 | 2,421 | ~95 % (91–94 % with one request running) |
A core holding a kernel counts as busy while it waits.
Same arithmetic, three shapes
Rows per expert per step = tokens × 10 ÷ 512 (each token goes to 10 of 512 experts).
| Step | tokens | rows per expert |
|---|---|---|
| Decode | 80 | 1.6 |
| Prefill | ~2,000 | 39 |
| Break-even | ~17,000 | 334 |
| Dense benchmark | — | 8,192 |
One expert: 5.1 µs to read, 0.024 µs to use
One expert in one layer on one GPU is 1.38 MB — 5.1 µs at 273 GB/s — and one row through it is 4.9 MFLOP.
| value | |
|---|---|
| Expert weights per GPU | 34.0 GB (67.95 GB of a 105.2 GB checkpoint) |
| One expert, one layer, one GPU | 34 GB ÷ 48 ÷ 512 ≈ 1.38 MB |
| Read at 273 GB/s | 5.1 µs |
| FLOPs per row | 2 × 2560 × 3 × 320 ≈ 4.9 MFLOP |
A whole step, as timed
Prefill steps take 71 % of wall time; a step takes ~850 ms with prefill in it or ~180 ms without (two-mode fit R² 0.98).
| Prefill step, 850 ms | count × each | ms |
|---|---|---|
| Linear-attention and MoE blocks | 84 × 5.9 ms | 494 |
| Full-attention blocks | 12 × 13.8 ms | 166 |
| All-reduces between the two machines | 96 | ≈ 101 |
| Remainder | ≈ 89 |
7 FLOP per byte against a ridge of 1,184
| value | |
|---|---|
| NVFP4 dense kernel peak, measured | 323 TFLOP/s |
| Memory bandwidth, nameplate | 273 GB/s |
| Roofline ridge | 323 ÷ 273 ≈ 1,184 FLOP/byte |
| Decode arithmetic intensity | ≈ 7 FLOP/byte |
The batch cannot simply be made bigger
| Lever | have | break-even needs |
|---|---|---|
| Decode tokens per step | 16 concurrent requests × 5 (1 + 4 speculative) = 80 | ~17,000 |
| Concurrent requests | 16 | ~3,400 |
| KV-cache memory | fits ~26 sessions at 62k context | — |
| Prefill tokens per step 2048 / 4096 / 8192 | all ≈ 2,900 tok/s ceiling (0.34 ms per token) | — |
| Prefill tokens per step 16,384 | hung both machines | — |
What moves throughput: not prefilling
gen tok/s ≈ 250 × (1 − prefill tok/s ÷ 2,900), R² 0.85 — so a cached prefix is worth ~2×. Working set = KV-cache demand ÷ capacity; past 1.0, cached prefixes are evicted.
| Working set | minutes | prefix hit | prefill tok/s | gen tok/s |
|---|---|---|---|---|
| < 0.8 | 105 | 89 % | 1,312 | 160 |
| 0.8–0.95 | 35 | 86 % | 1,396 | 128 |
| 0.95–1.05 | 11 | 89 % | 1,764 | 113 |
| 1.05–1.2 | 30 | 64 % | 2,294 | 60 |
| > 1.2 | 24 | 52 % | 2,191 | 49 |
vLLM’s own estimator overstates compute 7×
vLLM’s built-in compute-utilisation estimate models all 48 layers as dense full-context attention; this model has 12 layers that attend to 2,048 keys and 36 linear-attention layers.
| estimator showed | real | phantom | |
|---|---|---|---|
| Compute | 48.8 TFLOP/s | ≈ 7 TFLOP/s | 87 % of counted FLOPs |
| Bandwidth | 92 % | ≈ 50 % | ~53 % of counted bytes |
The estimator-based figures in NVFP4 vs 2:4 sparse are the inflated ones; the numbers here replace them.
Setup and caveats
| Hardware | two NVIDIA DGX Spark (GB10), every layer split across both (tensor parallel), vLLM 0.29 |
| Model | Qwen3.8-Flash-Next, NVFP4 (NVIDIA’s 4-bit float format) — 48 layers, 512 experts, top-10 routing, hidden 2560, expert intermediate 640 (320 per GPU) |
| Measured | 2026-10-02 |
| Per-expert rows | calculated, not profiled |
| ”Other” | by subtraction, not profiled |
| 6,144 cores | nameplate; counts are time-averaged equivalents |
| Memory traffic | calculated; the GB10 chip has no memory-traffic counter |
| Working-set table | compared across separate server runs, not a controlled A/B |
TL;DR: a decode step gives each expert 1.6 rows — 0.024 µs of multiplying after a 5.1 µs weight read. ~37 of 6,144 cores multiply,
nvidia-smisays 95 %. Break-even is ~17,000 tokens per step; the engine has 80. The lever is the prefix cache: 160 vs 49 gen tok/s.