Provenance: found during a memory review of the v20 r12 release image voipmonitor/vllm:gilded-gnosis-v20-vllmb46c3aa-si35aebc6-fi801d57a-cu132-20260730-r12; code refs are against the composed r12 tree, whose sparkinfer HEAD is de04125 (reachable on origin/fix/trellis-stable-profile-20260730 / pr/92), so blob links below point at that commit. Deployment used for impact math: GLM-5.2 753B MoE, EXL3 3.0bpw, 4x RTX 6000 Pro Blackwell (sm120, 188 SMs), TP4 rank-sliced Trellis MoE: k=6144, n=512 per rank (fc1_cols=1024), E=160, topk=8. These are proposals from a source review, not demands — happy to be corrected on intent.
1. Unpinned w4a16_block_size_m makes plan sizing sweep all block sizes and reserve the worst case (+~65 MiB/rank at a 64-token plan)
Where: sparkinfer/moe/fused_moe/_impl.py _plan_core_workspace, L2577-L2608:
block_sizes = (
(int(w4a16_block_size_m),)
if w4a16_block_size_m is not None
else _W4A16_ALLOWED_ROUTED_SIZES
)
for block_size in block_sizes:
route_slots = max_packed_route_slots(
routed_capacity,
int(block_size),
route_E,
)
...
fc1_c_tmp_elements = max(
fc1_c_tmp_elements,
packed_gemm_scratch_elements(
size_n=fc1_cols, route_slots=route_slots,
moe_block_size=int(block_size), sms=sms,
),
)
fc2_c_tmp_elements = max(...)
with _W4A16_ALLOWED_ROUTED_SIZES = (8, 16, 32, 48, 64) (host.py L16) and max_packed_route_slots(numel, b, E) = numel + E*(b-1) for numel >= E (host.py L222-L229).
What/Why: TPMoEScratchCaps.w4a16_block_size_m defaults to None (_impl.py L754), and plan_tp_moe_scratch / plan_tp_moe_arena_layout forward it verbatim (L6390, L6425, L6829). Any caller that does not pin the block size gets both c_tmp planes (and packed_route_indices/block_expert_ids) sized as the max over all five launch variants, dominated by block 64's padded route slots — capacity reserved for launch shapes a decode-window plan never picks.
Impact (recomputed, 64-token plan, routed_capacity=512, E=160, sms=188, fc1_cols=1024, k=6144):
| block |
route_slots |
fc1_c_tmp |
fc2_c_tmp |
| 8 (pinned) |
512+160·7 = 1,632 |
11.75 MiB |
11.75 MiB |
| 64 (sweep max) |
512+160·63 = 10,592 |
min(1024·10592, 188·4·64·256)·4 B = 41.38 MiB |
min(6144·10592, 12,320,768)·4 B = 47.0 MiB |
Pinned block 8: 23.5 MiB total; unpinned sweep: 88.375 MiB → +64.9 MiB per rank per plan. Against the production turnkey margin of ~4.1 GiB/GPU this is ~1.6% of the entire margin per unpinned plan, i.e. ≈4,600 KV tokens at DCP2/nvfp4 (100 MiB ≈ 7,100 tokens).
Reachability (honest): the shipped vLLM integration does not hit this — exl3.py _rank_sliced_runtime always passes w4a16_block_size_m (_positive_env_int("VLLM_EXL3_TRELLIS_BLOCK_M", 8) for the decode plan, VLLM_EXL3_PREFILL_BLOCK_M default 64 for the prefill plan), and the MTP draft layers share the same runtime constructor, so both plans are pinned even with the env vars unset. The exposure is any direct api.Caps(...) consumer (benchmarks, ad-hoc runs, future callers) that leaves the field at its None default: they silently pay the worst-case reserve.
Suggested fix: derive the sweep set from select_route_block_size_m over the planned token counts (or over {1..max_tokens} extremes) instead of the full allowed tuple when w4a16_block_size_m is None, so the reserve matches block sizes the launcher can actually select for that capacity.
Verification: on the r12 tree, build two TPMoEScratchCaps for the same trellis weight plan (max_tokens=64, num_topk=8) with w4a16_block_size_m=8 vs unset, call plan_tp_moe_scratch(caps).scratch_specs() and diff the arena byte totals; the delta is the ~65 MiB above (fc1/fc2 c_tmp fp32 tensor specs at _impl.py L2652-L2653).
2. plan_tp_moe_scratch scales unbounded with caps.max_tokens — no clamp/guard against Trellis capacity (~1.0 GiB/rank at 3072 tokens, ~2.6 GiB at 8192)
Where: sparkinfer/moe/fused_moe/_impl.py _plan_core_workspace full-rotation staging, L2641-L2683:
tensor_specs = [
_TensorAllocSpec(
"intermediate_cache13",
(routed_capacity * max(fc1_cols, int(k)),),
cache_dtype,
),
...
]
if full_rotation:
max_tokens = max(routed_capacity // max(int(num_topk), 1), 1)
tensor_specs.extend(
(
...
_TensorAllocSpec("full_rotation_output", (max_tokens, int(k)), torch.float32),
_TensorAllocSpec("rotation_a_gate", (routed_capacity, int(k)), torch.float16),
_TensorAllocSpec("rotation_a_up", (routed_capacity, int(k)), torch.float16),
...
)
)
routed_capacity = max_tokens × num_topk (via plan_tp_moe_execution, routed_rows = num_tokens * num_topk, L5365), and neither plan_tp_moe_scratch (L6368) nor TPMoEScratchCaps.__post_init__ (which only floors max_tokens at 1, L759) applies any upper clamp, capacity assertion, or even a log line.
What/Why: every staging tensor scales linearly in max_tokens × topk × k at fp16 (rotation_a_gate, rotation_a_up, intermediate_cache13) plus fp32 full_rotation_output at max_tokens × k. A single mis-sized caps.max_tokens (env typo in VLLM_EXL3_TRELLIS_MAX_M, a runtime-cache-key miss, a direct API caller passing a batch bound instead of a decode window) silently allocates a multi-GiB arena with no diagnostic.
Impact (recomputed, k=6144, topk=8, E=160, sms=188, block 64):
| max_tokens |
cache13 |
rotation_a_gate+up |
full_rotation_output |
c_tmp (fc1+fc2) |
plan total |
| 32 (decode plan, block 8) |
3.0 MiB |
6.0 MiB |
0.75 MiB |
22.5 MiB |
≈32.5 MiB |
| 3072 |
288 MiB |
576 MiB |
72 MiB |
94 MiB |
≈1,054 MiB/rank |
| 8192 |
768 MiB |
1,536 MiB |
192 MiB |
94 MiB |
≈2,654 MiB/rank |
Reachability (honest): this is not merely hypothetical. The shipped vLLM integration (exl3.py _rank_sliced_runtime) deliberately plans a second prefill Trellis arena at plan_max_tokens = max_num_batched_tokens whenever VLLM_EXL3_PREFILL_TRELLIS (default on) and max_batched_tokens > max_trellis_m — so at the production turnkey (max_num_batched_tokens=3072) the ~1.0 GiB/rank figure above is an intended allocation, and at the 8192-token release-gate config it is ~2.6 GiB/rank. That is by design on the caller side; the finding here is that sparkinfer's plan API gives the caller no guardrail. Notably, the vLLM code itself carries a comment documenting a past incident of exactly this failure mode ("any m above the planned capacity produced a cache MISS — silently planning a fresh ~1 GiB arena mid-serve"). On a deployment with ~4.1 GiB total margin/GPU, one accidental oversized plan is fatal (OOM) rather than a graceful error.
Suggested fix: in plan_tp_moe_scratch (or TPMoEScratchCaps.__post_init__), validate max_tokens against an explicit caller-supplied ceiling (e.g. a max_plan_tokens cap in the weight plan or an opt-in allow_large_plan flag), or at minimum emit a warning with the computed arena bytes when the full-rotation plan exceeds a threshold (say 256 MiB), so an accidental 3072/8192-token plan is loud instead of silent.
Verification: on the r12 tree, plan_tp_moe_scratch(Caps(max_tokens=3072, num_topk=8, quant_mode="w4a16", weight_plan=<trellis3_t256 plan with k=6144, n=512, E=160>, w4a16_block_size_m=64)).scratch_specs() — summing the spec byte sizes reproduces the ≈1,054 MiB above; no warning or error is raised at any max_tokens.
Also examined and not reported: the if moe_block_size == 8: elements *= 2 term in packed_gemm_scratch_elements (host.py L264-L270) initially looked like an over-ask applied after the min, but it matches real kernel addressing — block-8 kernels reserve a full 16-row m-block region per split-K lock slot (cta_m_blocks = _covering_count(8, 16) = 1; c_size_int4 = cta_m_blocks*16*cta_n_blocks*16 // 4, kernel.py L2479-L2480) and the m8 merge walks even slot indices {0,2,4,6} with stride active_threads across that region (kernel.py L2483-L2502, L2643), so the true full-materialization bound is 2 × size_n × route_slots and the doubled min is exact, not an overshoot.
Provenance: found during a memory review of the v20 r12 release image
voipmonitor/vllm:gilded-gnosis-v20-vllmb46c3aa-si35aebc6-fi801d57a-cu132-20260730-r12; code refs are against the composed r12 tree, whose sparkinfer HEAD isde04125(reachable onorigin/fix/trellis-stable-profile-20260730/pr/92), so blob links below point at that commit. Deployment used for impact math: GLM-5.2 753B MoE, EXL3 3.0bpw, 4x RTX 6000 Pro Blackwell (sm120, 188 SMs), TP4 rank-sliced Trellis MoE: k=6144, n=512 per rank (fc1_cols=1024), E=160, topk=8. These are proposals from a source review, not demands — happy to be corrected on intent.1. Unpinned
w4a16_block_size_mmakes plan sizing sweep all block sizes and reserve the worst case (+~65 MiB/rank at a 64-token plan)Where:
sparkinfer/moe/fused_moe/_impl.py_plan_core_workspace, L2577-L2608:with
_W4A16_ALLOWED_ROUTED_SIZES = (8, 16, 32, 48, 64)(host.py L16) andmax_packed_route_slots(numel, b, E) = numel + E*(b-1)fornumel >= E(host.py L222-L229).What/Why:
TPMoEScratchCaps.w4a16_block_size_mdefaults toNone(_impl.pyL754), andplan_tp_moe_scratch/plan_tp_moe_arena_layoutforward it verbatim (L6390, L6425, L6829). Any caller that does not pin the block size gets bothc_tmpplanes (andpacked_route_indices/block_expert_ids) sized as the max over all five launch variants, dominated by block 64's padded route slots — capacity reserved for launch shapes a decode-window plan never picks.Impact (recomputed, 64-token plan, routed_capacity=512, E=160, sms=188, fc1_cols=1024, k=6144):
Pinned block 8: 23.5 MiB total; unpinned sweep: 88.375 MiB → +64.9 MiB per rank per plan. Against the production turnkey margin of ~4.1 GiB/GPU this is ~1.6% of the entire margin per unpinned plan, i.e. ≈4,600 KV tokens at DCP2/nvfp4 (100 MiB ≈ 7,100 tokens).
Reachability (honest): the shipped vLLM integration does not hit this —
exl3.py_rank_sliced_runtimealways passesw4a16_block_size_m(_positive_env_int("VLLM_EXL3_TRELLIS_BLOCK_M", 8)for the decode plan,VLLM_EXL3_PREFILL_BLOCK_Mdefault 64 for the prefill plan), and the MTP draft layers share the same runtime constructor, so both plans are pinned even with the env vars unset. The exposure is any directapi.Caps(...)consumer (benchmarks, ad-hoc runs, future callers) that leaves the field at itsNonedefault: they silently pay the worst-case reserve.Suggested fix: derive the sweep set from
select_route_block_size_mover the planned token counts (or over{1..max_tokens}extremes) instead of the full allowed tuple whenw4a16_block_size_m is None, so the reserve matches block sizes the launcher can actually select for that capacity.Verification: on the r12 tree, build two
TPMoEScratchCapsfor the same trellis weight plan (max_tokens=64, num_topk=8) withw4a16_block_size_m=8vs unset, callplan_tp_moe_scratch(caps).scratch_specs()and diff the arena byte totals; the delta is the ~65 MiB above (fc1/fc2c_tmpfp32 tensor specs at_impl.pyL2652-L2653).2.
plan_tp_moe_scratchscales unbounded withcaps.max_tokens— no clamp/guard against Trellis capacity (~1.0 GiB/rank at 3072 tokens, ~2.6 GiB at 8192)Where:
sparkinfer/moe/fused_moe/_impl.py_plan_core_workspacefull-rotation staging, L2641-L2683:routed_capacity = max_tokens × num_topk(viaplan_tp_moe_execution,routed_rows = num_tokens * num_topk, L5365), and neitherplan_tp_moe_scratch(L6368) norTPMoEScratchCaps.__post_init__(which only floorsmax_tokensat 1, L759) applies any upper clamp, capacity assertion, or even a log line.What/Why: every staging tensor scales linearly in
max_tokens × topk × kat fp16 (rotation_a_gate,rotation_a_up,intermediate_cache13) plus fp32full_rotation_outputatmax_tokens × k. A single mis-sizedcaps.max_tokens(env typo inVLLM_EXL3_TRELLIS_MAX_M, a runtime-cache-key miss, a direct API caller passing a batch bound instead of a decode window) silently allocates a multi-GiB arena with no diagnostic.Impact (recomputed, k=6144, topk=8, E=160, sms=188, block 64):
Reachability (honest): this is not merely hypothetical. The shipped vLLM integration (
exl3.py_rank_sliced_runtime) deliberately plans a second prefill Trellis arena atplan_max_tokens = max_num_batched_tokenswheneverVLLM_EXL3_PREFILL_TRELLIS(default on) andmax_batched_tokens > max_trellis_m— so at the production turnkey (max_num_batched_tokens=3072) the ~1.0 GiB/rank figure above is an intended allocation, and at the 8192-token release-gate config it is ~2.6 GiB/rank. That is by design on the caller side; the finding here is that sparkinfer's plan API gives the caller no guardrail. Notably, the vLLM code itself carries a comment documenting a past incident of exactly this failure mode ("any m above the planned capacity produced a cache MISS — silently planning a fresh ~1 GiB arena mid-serve"). On a deployment with ~4.1 GiB total margin/GPU, one accidental oversized plan is fatal (OOM) rather than a graceful error.Suggested fix: in
plan_tp_moe_scratch(orTPMoEScratchCaps.__post_init__), validatemax_tokensagainst an explicit caller-supplied ceiling (e.g. amax_plan_tokenscap in the weight plan or an opt-inallow_large_planflag), or at minimum emit a warning with the computed arena bytes when the full-rotation plan exceeds a threshold (say 256 MiB), so an accidental 3072/8192-token plan is loud instead of silent.Verification: on the r12 tree,
plan_tp_moe_scratch(Caps(max_tokens=3072, num_topk=8, quant_mode="w4a16", weight_plan=<trellis3_t256 plan with k=6144, n=512, E=160>, w4a16_block_size_m=64)).scratch_specs()— summing the spec byte sizes reproduces the ≈1,054 MiB above; no warning or error is raised at anymax_tokens.Also examined and not reported: the
if moe_block_size == 8: elements *= 2term inpacked_gemm_scratch_elements(host.py L264-L270) initially looked like an over-ask applied after themin, but it matches real kernel addressing — block-8 kernels reserve a full 16-row m-block region per split-K lock slot (cta_m_blocks = _covering_count(8, 16) = 1;c_size_int4 = cta_m_blocks*16*cta_n_blocks*16 // 4, kernel.py L2479-L2480) and the m8 merge walks even slot indices{0,2,4,6}with strideactive_threadsacross that region (kernel.py L2483-L2502, L2643), so the true full-materialization bound is2 × size_n × route_slotsand the doubledminis exact, not an overshoot.