Repository navigation
[Bugfix][Core] Keep Mamba-aligned prefill chunks out of the MTP lookahead window - #61845
apex-mochen wants to merge 1 commit into
Conversation
…head window With Mamba "align" prefix caching and multi-module MTP (num_prefill_lookahead = L >= 2), a prompt ending 1..L-1 tokens past a Mamba block boundary could stop being scheduled after its first chunks. _mamba_block_aligned_split ended a chunk on that boundary, _reserve_prefill_lookahead moved the end back off it, and on the next step the chunk (starting mid-block, stopping at the boundary) was shortened to zero tokens, on every step. This happens with EAGLE block drop on (the default) whenever the chunk reaching the last boundary is budget-limited, and for any prompt with disable_eagle_block_drop=True. Resolve the lookahead inside the split: finish the prefill if that crosses no boundary from mid-block, else stop at the last block boundary before the window. If neither is possible, keep the aligned end, and let _reserve_prefill_lookahead leave Mamba-aligned ends alone, so the next chunk finishes the prefill and no slot is published at the wrong offset. Fixes vllm-project#61762 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: apex-mochen <2756823972@qq.com>
|
Hi @njhill — would you be able to take a look at this when you have a moment? With Mamba "align" prefix caching and multi-module MTP (num_prefill_lookahead >= 2), The fix resolves the lookahead inside the split (finish the prefill, else stop at the last boundary before the window, else keep the aligned end) and lets One review focus for you: in the "keep the aligned end" case the drafter reads sampled tokens at that one boundary; I chose that over ending a chunk mid-block (which would publish a Mamba slot at the wrong offset, #43559). Happy to adjust if you'd prefer a different trade-off. |
|
Hi @ZJY0516 — this one hasn't had a review yet (first ask on Oct 16), and since #61181 put Mamba and KV cache under your CODEOWNERS and you've been merging Mamba changes lately (#61497), I wanted to ask you directly. Quick context: with Mamba Head is |
Purpose
Fixes #61762.
With Mamba
alignprefix caching (the default for hybrid models once prefix caching is on) and multi-module MTP (num_prefill_lookahead = num_speculative_tokens = L >= 2), a prompt that ends 1..L-1 tokens past a Mamba block boundary can stop being scheduled. Two clamps inScheduler.schedule()disagree about the same position:_mamba_block_aligned_splitends a chunk on a block boundary (a cacheable checkpoint, or a budget-limited chunk floored to a boundary)._reserve_prefill_lookaheadsees fewer than L tokens left and moves the end back byL - remaining, off the boundary.The report in #61762 (and my follow-up there) only showed this with
disable_eagle_block_drop=True. While writing the fix I found it also happens with EAGLE block drop on (the default) whenever the chunk that reaches the last boundary is budget-limited. Block size 16, L=3, 49-token prompt, 16-token budget: the chunks end at 16, 32, then 46, and from then on 0 tokens per step. With a shared per-step budget, a long prompt's last full chunk can be budget-limited in this way.Fix. The lookahead is now resolved inside
_mamba_block_aligned_split, which knows where chunks may end. If a chunk would end inside the window, the split does the first of these that applies:_reserve_prefill_lookaheadnow leaves Mamba-aligned ends alone, so the next chunk finishes the prefill. In that case the drafter reads sampled tokens at this one boundary, which is what the reservation tries to avoid. That is a draft-quality cost; the alternatives are a livelock, or a chunk ending mid-block followed by one crossing the boundary, which publishes a Mamba slot at the wrong offset ([Bug]: Accuracy drops ~20% when--enable-prefix-cachingis used together with MTP speculative decoding (Qwen3.6 35B-A3B) #43559).Unaligned (sub-block) chunk ends are still shortened by
_reserve_prefill_lookaheadas before. Nothing changes whennum_prefill_lookahead <= 1(EAGLE-family drafters, or no drafter). The window conditionN - L < end < Ncannot hold in that case.Reachability
As far as I can tell, no public checkpoint reaches this today:
nemotron_h_mtp.pyasserts a single MTP layer.qwen3_next_mtp.pyandbailing_moe_v3_mtp.pyalready iterate overnum_nextn_predict_layers, and nothing rejects multi-module MTP withalign. A hybrid checkpoint with two or more MTP layers would hit it. All evidence below is scheduler-level on CPU. I have not run a model, and I am not claiming end-to-end validation.Test Plan
tests/v1/core/test_mamba_align_chunk_split.py::test_mamba_split_respects_multi_module_mtp_prefill_lookahead(216 cases)._mamba_block_aligned_splitand then_reserve_prefill_lookahead, allocating through a real hybridKVCacheManager._count_cached_boundary_statescheck, which verifies that every hash-cached Mamba slot holds the state its hash claims.test_mamba_split_lookahead_window_is_noop_without_multi_module_mtp: L=0/1 keep today's split.tests/v1/core/test_scheduler.py::test_mamba_align_multi_module_mtp_prefill_does_not_livelock: the realScheduler, with the cases from [Bug]: Scheduler livelock with multi-module MTP + Mamba align prefix caching when prompt_len % block_size < num_speculative_tokens #61762.selfto_mamba_block_aligned_splitin four test files gainnum_prefill_lookahead=0, so those tests are unchanged.Test Result
(CPU only, WSL Ubuntu 24.04, Python 3.12; my local environment lacks
torchvision, which affects a few unrelated tests on both trees.)71536bd5f8): 124 failed, 143 passed. Of the failures, 72 are block-drop-off cases, 48 are block-drop-on (default) cases, all with a budget of one block or less, and 4 are theSchedulercases. With this PR: 267 passed.tests/v1/corein full, main vs this PR: the failed/errored sets are identical (68 environment failures on both trees: missingtorchvisionand offline model configs), with 0 failures only on this PR; passes go from 940 to 1161 (the new tests).Scheduleron a hybrid attention+Mamba config, 40 seeds × 300 steps per config. It flags a running request that gets 0 tokens while the step has budget left for its whole remainder.pre-commit run --files <changed files>: all hooks pass (ruff check/format, typos, mypy, SPDX, new-test CI wiring).AI assistance
AI-assisted (Claude Code). I reviewed the change and ran the tests listed above myself.
🤖 Generated with Claude Code