Summary. On v7.72.5 the P72 profile-run cap (GENESIS_PROFILE_RUN_CAP_M) lets the engine boot at --max-num-batched-tokens > 4096, but it also sizes the qwen3_next (GatedDeltaNet) compiled buffers at the cap value. So the runtime batch is bounded by GENESIS_PROFILE_RUN_CAP_M, not by --max-num-batched-tokens: any single combined forward whose token count lands in (cap, max_num_batched_tokens] overflows the GDN buffer and kills the worker. With the cap at 4096, 4096 is the effective runtime ceiling. First — thank you for the patch tree; it's the only thing that makes TurboQuant k8v4 + hybrid Qwen3.6 work on our hardware at all.
Environment
- Image:
vllm-qwen36-genesis-tq:v7.72.5-vllm01d4d1ad3 (your tree on nightly 01d4d1ad3)
- Hardware: 2× RTX 4090 (Ada, SM89), TP=2 + EP=2
- Model:
Qwen3.6-35B-A3B AWQ 4-bit, --kv-cache-dtype turboquant_k8v4, --max-model-len 262144, gpu-util 0.82
- KV cache ~2.0M tokens, full CUDA graphs, vision on. Stable for 7+ days at
--max-num-batched-tokens 4096.
What we tried. To lift throughput we set --max-num-batched-tokens 8192 with P72 (GENESIS_PROFILE_RUN_CAP_M=4096) + P74 (chunk-clamp). Two distinct failures, depending on the cap:
(A) Boot crash — P72 OFF, batch ramped to 32768. Dynamo fake-tensor mismatch in determine_available_memory()'s profiling forward:
mul(FakeTensor(..., 65536, 128), FakeTensor(..., 16*s59, 128)) # 65536 = 2 × max_num_batched_tokens
The TQ-k8v4 GQA/multi-query path (P40 / P67) can't specialize that symbolic shape at large batch → profiling forward never completes. This is why P72 exists.
(B) Runtime crash — P72 ON at 4096, batch 8192. Engine boots clean, a short bench passes, then ~1h25 into the deploy under real mixed traffic the worker dies:
RuntimeError: setStorage: sizes [5536, 16, 128], strides [2048, 128, 1], storage offset 0,
and itemsize 2 requiring a storage size of 22675456 are out of bounds for storage of size 16777216
# qwen3_next.py:495
The math is decisive:
16777216 = 4096 × 16 × 128 × 2 — GDN buffer sized for M = the P72 cap (4096)
22675456 = 5536 × 16 × 128 × 2 — a real combined forward batch of 5536 tokens
5536 > 4096 → overflow, via the inductor / cuda-graph as_strided aliasing path (gen_alias_from_base).
Why our pre-deploy bench missed it (a caution for others). An 80K single-prefill "crash test" is P74-chunked to ≤4096 per forward, and N=16 concurrent decode is ~16 tokens/step — neither ever produces a single forward in (4096, 8192]. It takes co-scheduled long-context prefill + decode in the same step to sum one forward past the cap. A valid test must force a single forward strictly in (cap, max_num_batched_tokens] (e.g. several concurrent ~2-3K-token prefills landing in one step).
The coupling, stated plainly. GENESIS_PROFILE_RUN_CAP_M does double duty: it bounds the memory-profiling shape (good — dodges crash A) and it sizes the qwen3_next GDN compiled buffers (bad — bounds the safe runtime batch). Raising both the cap and forcing a fresh compile to 8192 would re-expose crash A, so it's not a workaround we're willing to run on prod.
Question / ask. Is there a path to decouple the GDN buffer sizing from the profile cap — i.e. size the qwen3_next compiled buffers from --max-num-batched-tokens (or max_num_seqs × something) while keeping the determine_available_memory() profiling shape capped to dodge crash A? Or, alternatively, a large-batch profile route that lets the TQ-k8v4 path specialize at the real batch so P72 isn't needed at all? If 4096 is fundamental to the k8v4 GDN geometry on this model, that's a useful thing to document too.
Happy to test a candidate patch on Ada SM89 in a prod-adjacent setup and report back with the same crash-reproducing traffic shape. I can also provide fuller logs / the compile_ranges and boot summary if useful.
Summary. On v7.72.5 the P72 profile-run cap (
GENESIS_PROFILE_RUN_CAP_M) lets the engine boot at--max-num-batched-tokens > 4096, but it also sizes theqwen3_next(GatedDeltaNet) compiled buffers at the cap value. So the runtime batch is bounded byGENESIS_PROFILE_RUN_CAP_M, not by--max-num-batched-tokens: any single combined forward whose token count lands in(cap, max_num_batched_tokens]overflows the GDN buffer and kills the worker. With the cap at 4096, 4096 is the effective runtime ceiling. First — thank you for the patch tree; it's the only thing that makes TurboQuant k8v4 + hybrid Qwen3.6 work on our hardware at all.Environment
vllm-qwen36-genesis-tq:v7.72.5-vllm01d4d1ad3(your tree on nightly01d4d1ad3)Qwen3.6-35B-A3BAWQ 4-bit,--kv-cache-dtype turboquant_k8v4,--max-model-len 262144, gpu-util 0.82--max-num-batched-tokens 4096.What we tried. To lift throughput we set
--max-num-batched-tokens 8192with P72 (GENESIS_PROFILE_RUN_CAP_M=4096) + P74 (chunk-clamp). Two distinct failures, depending on the cap:(A) Boot crash — P72 OFF, batch ramped to 32768. Dynamo fake-tensor mismatch in
determine_available_memory()'s profiling forward:The TQ-k8v4 GQA/multi-query path (P40 / P67) can't specialize that symbolic shape at large batch → profiling forward never completes. This is why P72 exists.
(B) Runtime crash — P72 ON at 4096, batch 8192. Engine boots clean, a short bench passes, then ~1h25 into the deploy under real mixed traffic the worker dies:
The math is decisive:
16777216 = 4096 × 16 × 128 × 2— GDN buffer sized for M = the P72 cap (4096)22675456 = 5536 × 16 × 128 × 2— a real combined forward batch of 5536 tokens5536 > 4096 → overflow, via the inductor / cuda-graph
as_stridedaliasing path (gen_alias_from_base).Why our pre-deploy bench missed it (a caution for others). An 80K single-prefill "crash test" is P74-chunked to ≤4096 per forward, and N=16 concurrent decode is ~16 tokens/step — neither ever produces a single forward in
(4096, 8192]. It takes co-scheduled long-context prefill + decode in the same step to sum one forward past the cap. A valid test must force a single forward strictly in(cap, max_num_batched_tokens](e.g. several concurrent ~2-3K-token prefills landing in one step).The coupling, stated plainly.
GENESIS_PROFILE_RUN_CAP_Mdoes double duty: it bounds the memory-profiling shape (good — dodges crash A) and it sizes the qwen3_next GDN compiled buffers (bad — bounds the safe runtime batch). Raising both the cap and forcing a fresh compile to 8192 would re-expose crash A, so it's not a workaround we're willing to run on prod.Question / ask. Is there a path to decouple the GDN buffer sizing from the profile cap — i.e. size the qwen3_next compiled buffers from
--max-num-batched-tokens(ormax_num_seqs × something) while keeping thedetermine_available_memory()profiling shape capped to dodge crash A? Or, alternatively, a large-batch profile route that lets the TQ-k8v4 path specialize at the real batch so P72 isn't needed at all? If 4096 is fundamental to the k8v4 GDN geometry on this model, that's a useful thing to document too.Happy to test a candidate patch on Ada SM89 in a prod-adjacent setup and report back with the same crash-reproducing traffic shape. I can also provide fuller logs / the compile_ranges and boot summary if useful.