A 1-terabyte model on one box: MiMo-V2.6-Pro, explained

Created September 22, 2026 · James Meadlock and Milo (rewritten September 22, 2026 at 10:27 PM CDT in a session on custom/mimo26-pro — the model this post is about — reasoning enabled) · one DGX Station GB300 · updated September 22, 2026 at 11:10 PM CDT · autotune callout corrected September 23, 2026 at 12:30 AM CDT on anthropic/claude-opus-5-5 (Milo)

Model1.02T / 42B active
Weights on disk527 GiB
GPU memory250 GiB HBM
Decode, agent traffic37.4 tok/s

This is the plain-language companion to Fourteen boots, one streamer bug, and a model that finally talks — the full lab-log version with every boot, table, and receipt. Here the same story is told in three pictures: why the model does not fit, the one flag that silently broke it, and the trick that made it fast. Every number is carried unchanged from the parent post; nothing is remeasured here.

Contents
  1. The puzzle: 527 GiB of weights on a 250 GiB card
  2. The break: one loader flag zeroed the weights
  3. The other walls: naming, pinning, and a shuffling kernel
  4. The fix for speed: keep the hot experts close
  5. Where it stands

1. The puzzle: 527 GiB of weights on a 250 GiB card

MiMo-V2.6-Pro is a mixture-of-experts model: 1.02 trillion parameters total, but each token only activates 42 billion of them. Most of the weight lives in 384 small "expert" networks per layer, and for every token the model picks 8 of those 384 per layer to actually run. The experts are also the bulk of the file: 494.9 GiB of the 527 GiB checkpoint is experts (the rest is 24.6 GiB of non-expert layers, 3.5 GiB embedding/head, and 4.2 GiB of drafter, vision, and audio towers).

The GPU in this box — a GB300 Station — has 250 GiB of HBM. So roughly two-thirds of the model has to live in the machine's host memory (494 GiB of Grace RAM) and be read over the CPU–GPU link every time a token needs an expert that is not on the GPU. That crossing is the whole campaign: the model works only if most reads stay local, and it is fast only if the reads that do cross are rare.

Where the 527 GiB model lives Checkpoint breakdown of 527 GiB: 494.9 GiB experts, 28.1 GiB attention and embedding, 4.2 GiB drafter vision audio. On the box: GPU HBM 250 GiB holds 194 GiB of experts (27 layers) plus non-expert weights and KV; Grace host RAM 494 GiB holds 301 GiB of experts (42 layers) pinned, read over the C2C link at about 6.9 GiB per token at first placement. 527 GiB of weights: 94% is experts, and experts can live anywhere CHECKPOINT ON DISK — 527 GiB experts 494.9 GiB (94%) 28.1 GiB attention + embed 4.2 GiB drafter, vision, audio GPU — 250 GiB HBM 194 GiB experts — 27 of 69 layers the layers closest to the output 32 GiB non-expert weights KV cache + CUDA graphs + activations whatever is left after the weights HOST — 494 GiB Grace RAM 301 GiB experts — 42 of 69 layers pinned in RAM, ready to read not on the GPU — fetched on demand survives only with exact-size pinning: torch pin_memory() asked for 504 GiB C2C link · 6.9 GiB/token The crossing is the budget: at first most expert reads crossed the link — 30 tok/s. Keep the reads local and it speeds up.

The memory puzzle. Left: what fits on the GPU. Right: the two-thirds of experts that must live in host RAM and cross the CPU–GPU link on demand. Figures from the parent post; the 28.1 GiB and 4.2 GiB bins group its 24.6 + 3.5 and 2.3 + 1.4 + 0.5 line items.

Concretely, at the settings used here, about 194 GiB of experts fit in HBM (27 of the 69 expert layers) and the remaining 301 GiB (42 layers) stay pinned in host RAM. At first placement that meant every token crossed the link for the majority of its expert reads — about 6.9 GiB per token — which is exactly the arithmetic behind the first measured speed of 30 tok/s.

2. The break: one loader flag zeroed the weights

For thirteen boots the model produced confident garbage — fluent-shaped text that meant nothing, byte-stable across runs. The cause was not the model, not the GPU offload, and not the two vLLM patches under test at the time. It was a single launch flag: --load-format runai_streamer, a streaming weight loader adopted earlier to survive host memory pressure.

One flag, two loaders: garbage or sane text Same model, same GPU, two weight loaders. Top path: runai_streamer loader fragments the fused qkv_proj weight-and-scale pair, loads attention weights as all zeros and mangles MXFP4 experts, output is stable garbage. Bottom path: default safetensors loader keeps the pair intact, output matches the CPU reference at every op and produces sane text. Thirteen boots of confident garbage — one launch flag MiMo-V2.6-Pro 527 GiB checkpoint --load-format runai_streamer streaming loader, v3 through v13 weight + scale pair dropped qkv attention weights → all zeros MXFP4 experts → mangled confident, byte-stable garbage: schGoodzial') · Matcher · 识别驗Nit… That line is boot v10's whole sequence, quoted unchanged. Boot v11 returned a different string: 暖婤Ք0Ք0… default safetensors loader boot v14 onward pair intact matches CPU reference at every op qkv out norm 45.7, cosine 1.0000 “capital of France, one word”: Paris Only the loader differs. The proof: an op-by-op diff against a CPU reference, first divergence at the attention projection.

The break and the fix. Garbage strings are quoted from the parent post verbatim, one boot per label (v10 and v11 returned different strings). Op-by-op figures are its in-process vLLM hook measurements on the 16-layer probe.

What the streamer does wrong on this checkpoint: the fused qkv_proj attention weights are FP8 with a separate block-scale tensor, and the pairing between weight and scale must survive loading intact. Any loader that fragments that group drops the pair — the attention weights silently load as all zeros and the MXFP4 expert weights come out mangled. The mechanism was found independently six hours earlier by vllmellm in vLLM PR #58142 on a different GPU and loader; the work here is the second-hardware, second-loader confirmation. The proof was an op-by-op comparison against an independent CPU reference built from Xiaomi's own modeling code: the default safetensors loader matched the reference at every operation, and the streamer diverged at the very first attention projection.

The lesson that made it findable: compare against a reference that is known good, one operation at a time, and let the first divergence name the bug. Guessing at the whole pipeline had produced a wrong hypothesis (a 6 AM theory about tensor-parallel sharding that the op-by-op diff disproved).

3. The other walls: naming, pinning, and a shuffling kernel

Before the garbage saga, three separate walls had to fall for a 527 GiB offload to load at all. Each was invisible until instrumented:

WallWhat happenedFix
Naming trapThe offload flag named expert tensors as experts.w13_weight, but vLLM wraps them as mlp.experts.routed_experts.*. The name matched nothing, so nothing offloaded and the whole model landed in GPU memory — instant OOM.Use the full names: routed_experts.w13_weight routed_experts.w2_weight.
Power-of-two pinningPyTorch's pin_memory() rounds every pinned block up to a power of two. One 4.5 GiB tensor pinned 8 GiB of host memory. Forty-two offloaded layers asked ~504 GiB of host for a 301 GiB set — and the machine died at 486 GB, twice.Pin with cudaHostRegister at exact size (vLLM PR #58185). GPU reads measured 336 GiB/s registered vs 355 GiB/s torch-pinned, so it costs almost nothing.
MXFP4 shuffleAt load, the TRT-LLM MXFP4 backend re-shuffles expert weights into kernel layout and installs the result with replace_parameter() — registering a new GPU tensor and silently dropping the host-pinned view. Every offloaded layer quietly moved back to GPU (+7 GiB per layer).A 40-line patch: if the existing parameter is a host view and the byte size matches, copy into the pinned storage and re-view it (bind-mounted, now filed).

None of these caused the garbage. They caused the crashes. A fourth item deserves its own warning, because it cost a night:

The autotune trap. On the MoE backend vLLM picks by default, FlashInfer's FP4 MoE autotune crawled — 100 minutes of "100% GPU" at 256 W with no cache written. The fix is not more patience: run --moe-backend marlin and VLLM_USE_DEEP_GEMM=0, the same flags every documented working V2.6 serve uses. Marlin turns the same autotune into 9 seconds, "Saved 0 configs". (Reported on vLLM issue #58031. Corrected September 23, 2026: an earlier version said the kernel is built for sm_100a only. It is not; the slow tune tracks how the experts are split between HBM and Grace, not the GPU generation.)

4. The fix for speed: keep the hot experts close

With sane tokens at last, the question became speed. The naive placement — whole layers at a time — keeps the last 27 layers' experts in GPU memory and the first 42 in host RAM. But expert usage is not uniform: measured on real agent traffic, the late layers concentrate their traffic on very few experts (about 48–66 of 384 carry half the traffic), while early layers spread more evenly. So a small set of experts carries a large share of reads — wherever those experts sit.

Hotsplit re-homes experts individually instead of by layer: rank every expert by measured decode usage, keep the top-ranked ones in GPU memory within the same budget stock placement had, and leave the rest in host RAM. The outputs of the hot and cold passes are summed, so the math is unchanged — 16-layer parity tests were token-identical 6/6.

Hotsplit: keep the measured hot experts in GPU memory Stock placement keeps whole late layers in GPU memory and serves 30.4 percent of held-out decode reads from HBM at 31.2 tok/s. Hotsplit ranks all 69 layers experts by measured decode usage and keeps the top-ranked experts in GPU memory within the same budget, serving 62.2 percent from HBM at 37.4 tok/s. Parity is token-identical 6 of 6. Same memory budget, smarter placement: 30% → 62% of reads served locally Stock: whole layers, late 27 in GPU 69 layers × 384 experts, one row per layer blue = expert reads answered from GPU, per row 30.4% from GPU · 31.2 tok/s decode Hotsplit: top experts by measured usage same budget — hot experts scattered across all 69 blue = same experts, placed where the traffic actually is 62.2% from GPU · 37.4 tok/s decode HELD-OUT DECODE READS FROM GPU MEMORY (270 real agent windows) stock 30.4% hotsplit 62.2% (oracle: 62.5%) Parity: 16-layer greedy outputs token-identical 6/6 — placement changed speed, not math. Workload-specific caveat: on one synthetic prose prompt, hotsplit is ~5% slower. v23 re-ranks weekly from live counts. The lever was placement, not kernels: measure which experts your traffic uses, keep exactly those close.

Stock placement versus hotsplit at the same GPU memory budget. Row bars are schematic (identical budgets, different placement), and the two coverage and speed figures carry the measurements from the parent post: 30.4% → 62.2% held-out decode from HBM; 31.2 → 37.4 tok/s at an 11.5K-token prompt.

On held-out conversation windows from real Hermes agent turns (270 windows, 26,357 generated tokens), the same GPU budget served 30.4% of decode reads from HBM at stock placement, 62.2% with the measured hot list — close to the 62.5% oracle, and better than ranking by prefill counts alone (54.9%). That coverage is the speed:

Warm A/B, same recipe, only hotsplit differsStock placementHotsplit (v22, 152.8 GiB hot)
Decode, 11.5K-token prompt31.2 tok/s37.4 tok/s
Agent tool-call JSON29.5 tok/s36.6 tok/s
Plain prose~30 tok/s~30 tok/s (unchanged)
8 streams at once (aggregate)56.2–60.863.7

Gains land where the hot list was ranked — tool calls, shell, structured output. Prose is flat, and on one synthetic prose prompt hotsplit is ~5% slower; the hot list is workload-specific, which is why v23 keeps a live routing counter and re-ranks weekly. Two side findings from the profile: speculative decoding (DFlash) loses under offload, because every drafted token that gets verified pays its own host-read cost (measured: 30.2 → 24.5 tok/s at k=3, 17.2 at k=7), and the remaining hot spot is the cold expert path — 39% of traffic but 80% of expert time.

5. Where it stands

Recipe v23 "Hotsplit" is released (experimental) and daily-driving in Hermes: J-M-Recipes — MiMo-V2.6-Pro on one GB300, vLLM UVA offload + hotsplit, with pinned image digest, patched files with sha256s, launch and eval scripts, and every receipt. Through the real Hermes harness: 10/10 tool-call turns correct.

Bottom line. A 1.02T-parameter model serves on one box because 96% of its weight is experts, and experts are the part you can put anywhere. Two silent loader bugs and a power-of-two allocator had to fall first; then the winning move was not a faster kernel but better placement: measure which experts your traffic actually uses, and keep exactly those close. Weights unchanged, token-exact, +20% on agent traffic.

Still open: a full-depth teacher-forced quality check on the FP8 o_proj experiment (quantizing it would save ~1.2 ms per token but changes the weights — needs a quality gate first), the first live weekly re-rank once 50,000 decode tokens per layer accumulate, and DFlash on the omni class.

For every number's provenance, the fourteen-boot table, and the reproducible launch block, see the parent post.