Repository navigation
Conversation
…ping SWA groups get_exchange_clipped_blocks keeps the last blocks_per_sw blocks of each sliding-window group. The two legs can hold different tails past the prompt: the decoder reserves speculative lookahead slots when it admits a synchronous READ, while the prefiller only does so if it runs speculative decoding itself. When the tail crosses a block boundary on one leg only, the clipped windows are shifted by one block and the decoder reads the wrong KV for the end of the prompt. A prefill-only tail also shifts the full-attention pairing, because _align_read_blocks treats the longer remote list as a local prefix hit. Trim every transfer group to cdiv(num_prompt_tokens, block_size) before clipping, on both the producer (request_finished) and the consumer (update_state_after_alloc). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: benzhuzhu <zhutaoyu97@gmail.com>
|
✅ @benenzhu, CI is now available for this PR.
|
|
/ci run |
|
✅ Triggered Buildkite CI #95684 for commit ℹ️ This PR is 31 commits behind upstream |
|
/ci run |
|
✅ Triggered Buildkite CI #95806 for commit ℹ️ This PR is 1 commit behind upstream |
|
This pull request has merge conflicts that must be resolved before it can be |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Taoyu Zhu <zhutaoyu97@gmail.com>
|
/ci run |
|
✅ Triggered Buildkite CI #98900 for commit ℹ️ This PR is 42 commits behind upstream |


Overview
MoRIIO READ pairs prefill and decode sliding-window blocks by clipping each block list from its end. A lookahead tail that only one leg allocated shifts the decoder's window by one block, so the decoder reads the wrong KV for the end of the prompt. This PR trims both lists to the prompt's blocks before clipping.
Claims
Validation
test_moriio_hma_scheduler.py+test_moriio_routing.py(macOS, CPU)test_moriio_connector.py(ROCm, MI355X)test_moriio_connector.py+test_moriio_hma_scheduler.py+test_moriio_routing.py: main 139 passed; this PR 143 passed (the 4 new cases). 0 failed, 0 skipped on both.Details
Flow. Example: DSv4-Pro SWA cache,
block_size=64,sliding_window=128, soblocks_per_sw = cdiv(128, 64) + 1 = 3. PromptN = 440tokens fills 7 blocks. The decoder reservesklookahead slots and the prefiller none; the observed failure range(N - 1) % 64 ∈ [55, 63]impliesk = 9.request_finished): 440 slots, 7 blocksP0..P6. Clip keeps[P4, P5, P6]and sends them asremote_block_ids.load_kv_async=False, so the scheduler allocates440 + 9slots, 8 blocksD0..D7. The async-load path sets lookahead to 0 to keep block counts equal, but synchronous READ does not take it.update_state_after_alloc): clip keeps[D5, D6, D7]._align_read_blockssees equal lengths and pairsP4→D5, P5→D6, P6→D7.D4..D6. It gets wrong or missing KV, so the model answers as if the end of the prompt were missing.The failure condition with no prefill-side lookahead is
(N - 1) % block_size >= block_size - k._align_read_blockscannot detect the shift because it runs after the clip.Fix.
get_exchange_clipped_blockstakes an optionalnum_prompt_tokens. When it is set, every transfer group is first trimmed tocdiv(num_prompt_tokens, block_size)blocks, using the existing_group_block_sizes. Both exchange points pass it:request_finishedon the producer andupdate_state_after_allocon the consumer, both on the non-mamba path. The list lengths then depend only on the prompt, not on either leg's lookahead.Safety.
update_state_after_allocreceiveskv_cache_manager.get_blocks(request_id). That is the full position-indexed list, including prefix-hit blocks, so the trim never drops a prompt block._clamp_to_prompt_blocks(WRITE save path) is not reused. Its non-mamba branch skips sliding-window groups, which are the groups this fix needs.Limitation.
_group_block_sizesandblocks_per_swuse the spec block size without the DCP factor. Under DCP > 1 the trim keeps too many blocks and does not fix the shift. It does not regress either.Duplicate check. I searched
gh pr list --repo vllm-project/vllm --state open --search "moriio","moriio sliding window"and"moriio hybrid READ". No open PR trims before the SWA clip. Two PRs are related:get_exchange_clipped_blockscaller insplit_block_groups. That caller can passnum_prompt_tokensthe same way.Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.
AI assistance (Claude Code) was used to prepare this change.
🤖 Generated with Claude Code