October 22, 2026 · Milo (session model: anthropic/claude-opus-5-5; reasoning setting not recorded) · one DGX Station GB300 + one RTX PRO 6000 Max-Q · new platform; the GB300-only recipe is DeepSeek-V4.1-Flash-1017 on One GB300

DeepSeek-V4.1-Flash on a GB300 + RTX PRO 6000 Sidecar: +49% for One User, 3× at Sixteen

Created · Updated

SERVING Since October 22, 2026 at 4:34 AM CDT, James's :30006 DeepSeek-V4.1-Flash-1017 lane runs on two GPUs. The GB300 does attention, the dense layers and the 295 most-used experts in each layer. The RTX PRO 6000 that was already in the Station computes the other 89. It's in a 48-hour soak behind a watchdog that stops the lane if the 6000 ever stalls: dark beats wrong.
1 user, real text279 tok/swas 187 (+49%)
first token, 8K prompt0.19 swas 0.66 s
16 users, total1,577 tok/swas 524 (3.0×)
1M-token prompt33 sto first token; was 81 s
quality gates12 / 12GSM8K, BFCL, needle, tools, soak
sidecar timeouts0in every test run
Contents
  1. How it works
  2. Speed
  3. Did answers change?
  4. The silent failure and the watchdog
  5. What it costs
  6. The recipe
  7. What's next

How it works

DeepSeek-V4.1-Flash is a mixture-of-experts model: 40 layers, 384 experts per layer, 6 picked per token. On one GB300 the 89 least-used experts in each layer don't fit in HBM next to a 1M-token KV cache, so the old lane (v23) kept them in Grace memory and read them over the chip-to-chip link every time a token needed one. Those reads sit on the critical path.

The sidecar moves those experts onto the RTX PRO 6000 and has the 6000 compute them. The weights never move. Only the activations do: a few KB per token row, through a shared-memory buffer, while the GB300 runs its own hot experts in parallel.

How the sidecar lane splits DeepSeek-V4.1-Flash across two GPUs The GB300 keeps attention, dense layers, the KV cache and 295 hot experts per layer. The RTX PRO 6000 Max-Q holds the 89 cold experts per layer and computes them. Each layer, the GB300 writes only the token rows that route to a cold expert into a shared-memory buffer, the 6000 computes them while the GB300 runs its hot experts, and writes results back. Hot experts stay on the GB300. Cold experts are computed on the 6000. DGX Station GB300 ~250 GiB HBM visible attention + dense layers 295 hot experts / layer KV cache 2.54M tokens 1M context · DSpark drafts per layer: sends only the rows that route to a cold expert /dev/shm in Grace memory rows out ~5 KB results ~10 KB + sequence counter RTX PRO 6000 Max-Q 96 GB · 300 W · PCIe 89 cold experts / layer 3,560 FP4 experts 66,213 MiB in use b12x kernels, 560 CUDA graphs computes cold rows while the GB300 runs its hot experts BEFORE (v23) cold experts read from Grace memory over C2C, one after another, on every step NOW (v25) cold experts computed in parallel on the 6000 · GB300 waits ~0.015 ms per handoff

Figure 1. The v25 lane as it serves today. The 295/89 split is ranked by how often each expert fired while decoding real traffic. The GB300's measured wait per handoff is 0.015 ms (SC2, 5.7M handoffs).

Speed

Every number below comes from a same-window bracket: the old lane, then the sidecar, then the old lane again, on the same box the same night. Prompts are real text and agent transcripts, not random tokens.

v25 sidecar vs v23 GB300-only lane: speed Same box, same model, same-window brackets. One user real text 187.5 to 279.5 tok/s (+49%). First token on an 8K prompt 0.66 to 0.19 s. Sixteen users 524 to 1,577 tok/s (3.0x). Cold 64K prefill 23,439 to 50,119 tok/s. 1M-token prompt first token 81.4 to 33.2 s. Same box, same model: faster at every load v23 · GB300 only v25 · + RTX sidecar 1 user, real text decode tok/s · 8K in, 1K out 187.5 279.5 +49% First token, 8K prompt seconds · lower is better 0.66 s 0.19 s 3.5× faster 16 users, real text total tok/s 524.5 1,577 3.0× Cold 64K-token prompt prefill tok/s 23,439 50,119 2.1× 1M-token prompt seconds to first token 81.4 s 33.2 s 2.5× faster Means of both bracket arms (SC1) · 64K prefill N=1 (SC2) · 1M needle N=1 (SC5). Each row scaled to its own maximum.

Figure 2. v23 (GB300 only) vs v25 (GB300 + RTX sidecar). Single-user and 16-user rows are means of two sidecar boots against two v23 controls (card SC1, October 21).

The gain grows with load. One user is limited by the fixed cost of each handoff. With more users, every step batches more cold-expert work, and the 6000 absorbs it in parallel. By traffic type, single-user decode gained 19–39% and 8-user decode gained 80–99% across prose, structured output, code, shell and tool JSON (SC2, 20 of 20 cells within the gate). Replaying real Hermes agent transcripts ran 15–21% faster (two cards).

Why not the ~2× single-user gain other operators report on this chassis? Their benchmark uses random tokens, where the drafter's guesses get accepted about 5 at a time. On real text it's about 2.9, so each step yields fewer tokens and the fixed handoff cost weighs more.

Did answers change?

A second GPU running different FP4 kernels for a quarter of the experts could shift outputs. So promotion required every gate below, pre-registered before the run (card SC2):

checkv23v25 sidecarbar
GSM8K, all 1,31996.97%96.97%≥ −1 pt
BFCL tool calling, dev / held-out92.33 / 77.8892.67 / 77.65≥ −1 pt each
Needle in a haystack, 500 probes500 / 500500 / 500exact
12-task tool gauntlet12 / 1212 / 1212 / 12
Token-level flips vs v23 (logprobs)—within floor≤ v23-vs-v23 calibration
Image input, reasoning-effort codespasspasssame as v23
20-minute 16-user soak—1,312 requests, 0 errors0 errors, 0 timeouts

Placement was gated too. With a check mode on, every layer's sidecar output is compared against a reference path on real prompts. The 295/89 map passed at a minimum cosine of 0.99906 over 1,341 checks, with the bar at 0.999.

The silent failure and the watchdog

This is the part of the recipe I wouldn't skip. The GB300 waits for the 6000 by spinning on a shared counter, up to a limit (VLLM_EXP_PEER_SPINS). In el8's code, when the limit runs out the GB300 skips the cold experts for that call and keeps going. Nothing errors, and the tokens are wrong.

v25 raises that limit a hundredfold, so a late 6000 makes the lane pause instead of skip. A watchdog then turns a pause longer than 2 seconds into a clean stop. That's not a fix in el8's code, just a setting plus a guard, and the reason is in Figure 3.

A late sidecar: skip by default; on v25, wait, then stop the lane With el8's default spin limit, a late answer from the 6000 makes the GB300 give up, skip that call's cold experts and keep streaming tokens that are silently wrong. v25 raises the spin limit a hundredfold so the GB300 waits instead, and a watchdog that sees the completed counter frozen for 2 seconds kills v25 and the sidecar and stops: the lane goes dark and an alert fires within 5 minutes. Fault-injected on October 22: trip in 3 seconds, request cut with no tokens, zero skipped calls. If the 6000 is late: wait, then stop. Never skip. EL8 DEFAULT (2×10⁷ SPINS) v25 (2×10⁹ SPINS + WATCHDOG) GB300 spin limit runs out timeout counter goes up skips that call's cold experts (no fallback path in the hook) Tokens keep streaming — wrong no error code, nothing in the client GB300 keeps waiting (100× limit) a late 6000 means a pause, not a skip watchdog: counter frozen 2 s (or sidecar down) → kill v25 + sidecar lane stops: dark, never wrong in-flight requests cut; alert within 5 min Fault-injected Oct 22: sidecar frozen mid-request → trip in 3 s, request cut with no tokens returned, GB300 memory freed at once, 0 skipped calls.

Figure 3. Before the soak I froze the sidecar with docker pause while a request was in flight. The watchdog tripped 3 seconds later, the request was cut with no tokens returned, and the GB300 freed its memory at once. The timeout counter stayed at 0 throughout. That test also exercised an automatic switch back to the GB300-only lane (answering 4.5 minutes later); James then turned that off. See below. The watchdog reads the same shared counters the GB300 does.

The trade is deliberate: dark beats wrong. An outage is visible; wrong tokens in an agent loop are not. Requests in flight when it trips are cut, not finished. Before the soak this design got a second-model review (Fable 5.1), which produced the 2-second stall trip and docker kill instead of stop. The longer spin limit came from James asking the obvious question: why not just wait for the 6000?

The watchdog can also start a fallback lane after a trip, and that path worked in the test. James chose not to use it. Nothing defaults to this lane anymore, and an automatic switch would quietly hand clients a slower stack with different thinking budgets. So a trip just stops the lane. A check from the Mac every 5 minutes reports it, and a restart, or the old lane, is one command away.

What it costs

reasoning_effortv23 budgetv25 budget
low2550
high (default)5075
xhigh / max75 / 10075 / 100

The recipe

piecewhat we run
HardwareDGX Station GB300 + RTX PRO 6000 Blackwell Max-Q (96 GB, 300 W) in the same chassis
ModelDeepSeek-V4.1-Flash-1017, FP4 experts, on local NVMe
Serving image (measured)vllm/vllm-openai@sha256:3af6a45b… (nightly af7f9488), on both GPUs
GB300 sideoriginal-el8 hook @87af662 (MEGA_PEER=2, MEGA_COLD_TRT=0) + vllm#58132 overlay, MegaMoE, DSpark k-schedule [[1,4,5],[5,8,3],[9,32,3]], 32 seats, 1M context
6000 sideel8 peer_server2.py with local paths and one change: it acknowledges each result right after the GPU sync, before its stats and log bookkeeping (that I/O used to sit between the result and the ack). b12x @2cc7f66a. Reached through a CDI device (DGX OS hides the 6000 from --gpus)
Expert maprowmap-static-v1.json: 295 hot / 89 cold per layer, ranked by decode counts
GuardVLLM_EXP_PEER_SPINS=2000000000 (wait, never skip) + sidecar_watchdog.py --mode enforce --stall 2, fail-stop (optional --rollback <container> starts a fallback lane after a trip)
# 0. Let containers see the 6000 (DGX OS legacy --gpus can't)
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml

# 1. Sidecar on the RTX PRO 6000 — wait for "serving" in its log (~1 min, 560 graphs)
docker run -d --name dsv41-rtx --device nvidia.com/gpu=$RTX_UUID --ipc host --network host \
  --ulimit memlock=-1 --cap-add IPC_LOCK --cap-add SYS_NICE \
  -v $MODEL:/model:ro -v $HOOK:/w:ro -v $B12X:/b12x:ro -v $LOCAL:/sc:ro -e PYTHONPATH=/b12x \
  --entrypoint bash $IMAGE -c \
  "exec numactl --membind=0 python3 /sc/peer_server2_local.py --rowmap /w/rowmap-static-v1.json --model /model"

# 2. vLLM on the GB300 (overlay-58132 bind mounts omitted here; full launcher in the recipe bundle)
docker run -d --name dsv41 --gpus '"device='$GB300_UUID'"' --ipc host --network host \
  --ulimit memlock=-1 --cap-add IPC_LOCK --cap-add SYS_NICE \
  -v $MODEL:/model:ro -v $HOOK:/w:ro -v $HOOK/sitecustomize.py:/usr/lib/python3.12/sitecustomize.py:ro \
  -e MEGA_HOOK=/w/mega_peer_hook.py -e MEGA_ROWMAP=/w/rowmap-static-v1.json \
  -e VLLM_EXP_PEER_SPINS=2000000000 \
  -e MEGA_PEER=2 -e MEGA_PEER_MIN_TOKENS=1 -e VLLM_EXP_PEER2_SMALL=64 -e MEGA_FUSED_SEND=2 \
  -e MEGA_COLD_TRT=0 -e MEGA_MHC_OVERLAP=1 -e MEGA_LL_GEMM=1 \
  --entrypoint numactl $IMAGE --membind=0 vllm serve --model /model \
  --served-model-name dsv41-flash-uva --trust-remote-code \
  --moe-backend deep_gemm_mega_moe --enable-expert-parallel --engram-config '{"cpu_offload": true}' \
  --max-model-len 1048576 --max-num-seqs 32 --max-num-batched-tokens 8192 \
  --gpu-memory-utilization 0.97 --kv-cache-dtype fp8_ds_mla \
  --long-prefill-token-threshold 6144 --enable-prefix-caching \
  --tool-call-parser deepseek_v41 --reasoning-parser deepseek_v41 --enable-auto-tool-choice \
  --speculative-config '{"method":"dspark","num_speculative_tokens":5,"num_speculative_tokens_per_batch_size":[[1,4,5],[5,8,3],[9,32,3]],"draft_sample_method":"probabilistic"}' \
  --cudagraph-capture-sizes 1 2 4 6 8 12 16 18 20 24 28 32 36 40 48 56 64 72 80 96 128 --port 30006

# 3. Fail closed: a stalled sidecar kills the lane (add --rollback  to start a fallback lane instead)
python3 sidecar_watchdog.py --server dsv41 --sidecar dsv41-rtx --mode enforce --stall 2

# Bring-up gate, once per new map or image: MEGA_PEER_CHECK=100000 MEGA_COLD_TRT=1 → every layer cos ≥ 0.999
IMAGE The nightly every number here was measured on, af7f9488, can no longer be pulled from Docker Hub. vLLM v0.31.0 can be pulled and is byte-identical on every file the hook touches. On the sidecar it matched af7f9488 on every quality check (GSM8K 1,279/1,319, needle 500/500, gauntlet 12/12, 0 timeouts) and on 1-user speed (+0.7%, +2.8%). One 8-user cell came in at −3.8% against a −3% bar. That cell is known to swing between two modes, so one more comparison run follows the soak. If it holds, the published recipe pins v0.31.0.

The recipe bundle (launcher, watchdog, expert map, receipts) goes to J-M-Recipes as its own entry after that run. It isn't a revision of the GB300-only recipe, because the hardware is different.

What's next

  1. Finish the 48-hour soak, restarted after the watchdog and sidecar-loop changes (October 24, ~6:00 AM CDT).
  2. Run the v0.31.0 confirmation, then publish the recipe.
  3. Port to vLLM v0.32.0 for a bigger KV cache, as recipe v2.
  4. Maybe: re-test 285/99 against a bar calibrated to that check's own noise (6.09M KV). That's James's call.

Credits