Following the v14 recipe as closely as possible, we get ~3x lower single-stream decode throughput than the published numbers, with a clear spin-wait signature. Full diagnostics below — the box is available for any experiments you suggest.
Environment
- Host: 2x AMD EPYC 9565 (Turin, 72c), 2 NUMA nodes, 768 GB RAM, Ubuntu 24.04, kernel 6.8.0-1045-nvidia, driver 595.71.05 / CUDA 13.2,
iommu=pt, pcie_aspm=off, processor.max_cstate=1
- GPUs: 8x RTX PRO 6000 Blackwell Server Edition 96 GB, behind 2x Broadcom PEX89144 (4 GPUs per chip; each PEX partitioned into 2 virtual switches x 2 GPUs)
- PCIe fabric verified healthy: p2pBandwidthLatencyTest shows P2P-enabled latency 0.44-0.53 us uniformly across all 28 GPU pairs (incl. cross-NUMA), unidirectional 48-55 GB/s
- Image:
voipmonitor/vllm:dev-eldritch-enlightenment-vllmc382f1d-fp8d005934-b12xe44cb77-it85e7c5f-cu132-20260706 (running digest sha256:2dfb16d1... with the embedded launcher; pinned e15f3946... also verified)
- Checkpoint:
lukealonso/GLM-5.2-NVFP4, all 90 shards incl. layer-78 MTP
- Config: TP=8, DCP=1, MTP=3, MOE_MODE=a4, MAX_NUM_SEQS=64, GRAPH=256, fp8 KV, B12X_MLA_SPARSE, b12x MoE backend, 78-char index_topk_pattern
LOAD_FORMAT=fastsafetensors — InstantTensor open throws RuntimeError: std::exception on all workers on this host (io_uring is enabled); separate issue, shouldn't affect inference speed
Symptom
- cc1 decode: 41-44 tok/s vs your 125.9-136.5 (MTP3, a4)
- MTP acceptance is healthy (mean length 2.8-3.5, per-position 0.85-0.95 / 0.6-0.8 / 0.4-0.7) — matching your benchmark values, so the draft path is fine
- cc2 scales linearly to ~76 tok/s → fixed per-step cost, not compute-bound
- During decode: SM=100% on all 8 GPUs but only ~140 W/GPU, mem-util 10-11%, pclk 2280-2340 MHz (no throttling, temps 38-41 C) — spin-wait signature, not real compute
- Startup log is clean: 57 indexer-skip lines,
Configured b12x PCIe crossovers: oneshot/fused max=86016, DMA min=6291456, ['B12X_PCIE_ONESHOT_DMA', 'PYNCCL'] for tp:0, PYNCCL for ep:0, AOT cache hit, JIT monitor silent during inference
What we ruled out (each a separate restart, 2 measurements each)
- NCCL tuning (graph XML, P2P_LEVEL=SYS, MIN_NCHANNELS etc.): no change — expected, decode allreduce dispatches to B12X_PCIE_ONESHOT_DMA
DCP_BACKEND=ag_rs: 43 tok/s, no change
- Pure image defaults (no host env overrides at all): 41/44 tok/s
VLLM_USE_B12X_DCP_A2A=0 (the launcher exports =1 unconditionally at line 83, and envs.py does not flag this variable as unknown, so the code reads it): 42/42 tok/s
- Clocks / power / thermal / IOMMU: all healthy (see above),
iommu=pt, P2P matrix perfect
- MTP=0 baseline: 37 tok/s vs your 87.99 (i.e. ~27 ms per forward vs ~11.4 ms implied by your tables)
Key observation
Combining (6) with the MTP=3 numbers: at MTP=3 we see ~71 ms per engine step at acceptance ~3.0, and each step is 4 model forwards (target + 3 MTP drafts). At MTP=0 we see ~27 ms per step = 1 forward. In both cases the excess over your numbers works out to ~12-16 ms per model forward pass — proportional to the number of forwards, not per scheduler step. So whatever is spinning executes on every forward (the per-layer allreduce chain / b12x oneshot completion barriers / decode graph launch path), and is not related to MTP logic, sampling, or the scheduler.
Question
What differs between this setup and your bench environment that could add ~12-16 ms of spin per forward? Anything topology-specific we should check or flip (e.g. barrier behavior of the oneshot path on PEX89144 virtual-switch partitions, PCIe switch config expectations)? Happy to run nsys traces or any other diagnostics — turnaround on this box is fast.
Following the v14 recipe as closely as possible, we get ~3x lower single-stream decode throughput than the published numbers, with a clear spin-wait signature. Full diagnostics below — the box is available for any experiments you suggest.
Environment
iommu=pt,pcie_aspm=off,processor.max_cstate=1voipmonitor/vllm:dev-eldritch-enlightenment-vllmc382f1d-fp8d005934-b12xe44cb77-it85e7c5f-cu132-20260706(running digestsha256:2dfb16d1...with the embedded launcher; pinnede15f3946...also verified)lukealonso/GLM-5.2-NVFP4, all 90 shards incl. layer-78 MTPLOAD_FORMAT=fastsafetensors— InstantTensoropenthrowsRuntimeError: std::exceptionon all workers on this host (io_uring is enabled); separate issue, shouldn't affect inference speedSymptom
Configured b12x PCIe crossovers: oneshot/fused max=86016, DMA min=6291456,['B12X_PCIE_ONESHOT_DMA', 'PYNCCL']for tp:0, PYNCCL for ep:0, AOT cache hit, JIT monitor silent during inferenceWhat we ruled out (each a separate restart, 2 measurements each)
DCP_BACKEND=ag_rs: 43 tok/s, no changeVLLM_USE_B12X_DCP_A2A=0(the launcher exports=1unconditionally at line 83, and envs.py does not flag this variable as unknown, so the code reads it): 42/42 tok/siommu=pt, P2P matrix perfectKey observation
Combining (6) with the MTP=3 numbers: at MTP=3 we see ~71 ms per engine step at acceptance ~3.0, and each step is 4 model forwards (target + 3 MTP drafts). At MTP=0 we see ~27 ms per step = 1 forward. In both cases the excess over your numbers works out to ~12-16 ms per model forward pass — proportional to the number of forwards, not per scheduler step. So whatever is spinning executes on every forward (the per-layer allreduce chain / b12x oneshot completion barriers / decode graph launch path), and is not related to MTP logic, sampling, or the scheduler.
Question
What differs between this setup and your bench environment that could add ~12-16 ms of spin per forward? Anything topology-specific we should check or flip (e.g. barrier behavior of the oneshot path on PEX89144 virtual-switch partitions, PCIe switch config expectations)? Happy to run nsys traces or any other diagnostics — turnaround on this box is fast.