[Feature][Spec] Support disabling trailing prefix-cache block dropping - #53388
Merged
ZJY0516 merged 6 commits intoSep 1, 2026
Merged
Conversation
ZeldaHuang
requested review from
ApostaC,
NickLucche,
ProExpertProg,
WoosukKwon,
alexm-redhat,
heheda12345,
houseroad,
ivanium,
mgoin,
njhill,
orozery,
robertgshaw2-redhat,
tlrmchlsmth,
xuechendi,
yewentao256,
youkaichao and
ywang96
as code owners
August 22, 2026 16:16
ZeldaHuang
marked this pull request as draft
August 22, 2026 16:16
Contributor
|
This pull request has merge conflicts that must be resolved before it can be |
ivanium
approved these changes
Sep 1, 2026
ZJY0516
approved these changes
Sep 1, 2026
ZJY0516
left a comment
Member
There was a problem hiding this comment.
Let's merge this first to unblock perf
Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Ziming Huang <zelda.huanghuang@gmail.com>
Member
|
/ci run |
|
✅ Triggered Buildkite CI #86514 for commit |
Signed-off-by: Ziming Huang <48115868+ZeldaHuang@users.noreply.github.com>
Contributor
Author
|
/ci run |
|
✅ Triggered Buildkite CI #86534 for commit |
Signed-off-by: Ziming Huang <48115868+ZeldaHuang@users.noreply.github.com>
Contributor
Author
|
/ci run |
|
✅ Triggered Buildkite CI #86546 for commit |
am-cohere
pushed a commit
to am-cohere/vllm
that referenced
this pull request
Sep 1, 2026
vllm-project#53388) Signed-off-by: Ziming Huang <zelda.huanghuang@gmail.com> Signed-off-by: Ziming Huang <48115868+ZeldaHuang@users.noreply.github.com> Co-authored-by: OpenAI Codex <codex@openai.com>
Ledgero
added a commit
to Ledgero/vllm
that referenced
this pull request
Sep 1, 2026
…che block SpeculativeConfig.use_eagle() is a stand-in for "spec decode that reads target hidden states" and returns True for dflash/dspark too. vllm-project#53388's use_eagle_block_drop() inherited that: DFlash/DSpark still got the trailing-block drop unless the new disable flag was set. Redefine use_eagle_block_drop() to compose with the precise capability bit: only eagle-family drafters (eagle/eagle3/mtp) share (and pollute) the target's full-attention KV cache groups; DFlash/DSpark draft from their own KV cache and never write target blocks. The spurious back-off made every prompt shorter than two mamba blocks skip the final block-aligned chunk, so the mamba recurrent state never materialized on a block boundary and the next turn's prefix-cache lookup converged to 0 -> the whole context was recomputed on every reply. use_eagle() keeps its existing semantics (encoder shift, lookahead budget, num_prefill_lookahead); only the prefix-cache last-block drop is scoped precisely, and vllm-project#53388's disable_eagle_block_drop flag still applies to the eagle family. The scheduler warning for a disabled drop is now gated on eagle-family drafters. Tests: - pytest tests/v1/core/test_mamba_align_chunk_split.py -q - pytest tests/v1/core/test_scheduler.py -q -k mamba_align Co-authored-by: OpenAI Codex <noreply@openai.com> Signed-off-by: ouzq <ouzq@seu.edu.cn>
puririshi98
added a commit
to puririshi98/vllm
that referenced
this pull request
Sep 1, 2026
PR vllm-project#53388 added SpeculativeConfig.disable_eagle_block_drop and routed every EAGLE trailing prefix-cache block-drop site through a single use_eagle_block_drop() predicate. Adopt that mechanism to make the safe default drafter-method aware: the flag becomes `bool | None = None`, and when unset, use_eagle_block_drop() resolves from the method -- eagle/eagle3/mtp keep the drop (behavior unchanged), dflash/dspark disable it. An explicit user setting always wins, and the experimental warning now fires only on an explicit opt-out. The drop exists because EAGLE-family drafters combine the prefill-lookahead token (one past a chunked-prefill boundary) with the chunk's final hidden state and write the result into the drafter KV cache, so the last block of a prefix-cache hit may hold KV polluted by a continuation the matching request does not share. dflash/dspark drafters structurally cannot cache lookahead-polluted KV: their context KV is projected from target hidden states and positions only (precompute_and_store_context_kv), and the lookahead (anchor) token writes KV only at positions past the chunk end, in a block that is overwritten with clean context KV before it can be completed and hashed. The drop therefore protects nothing for them, while costing one full scheduler block of recompute on every prefix-cache hit. On hybrid mamba models in align mode both gates -- the FullAttn hit drop and the chunk-split last_cache_position backoff -- ride the same predicate, so they move together and the recovered block is actually usable. Behavior matches the previously measured explicit exemption: with a dspark drafter on a hybrid mamba target (32K-token shared prefix, 2K unique suffix, 256 output, temp 0, scheduler block 2192), steady-state cache-hit cached_tokens rise 28,496 -> 30,688 (hit recompute 6,336 -> 4,144 tokens) in every repeat on two GPU generations, cache-hit TTFT improves ~20-22%, decode throughput is flat within run-to-run noise, and acceptance length stays pinned at 3.00 with identical per-position acceptance rates. Hit-vs-miss logit deltas on the reused block sit below the within-hit noise floor and at the same order as the unpatched control's, with the greedy argmax stable. A None default resolves fail-closed: new eagle-family methods keep the drop until their drafter KV provenance is audited. Signed-off-by: Rishi Puri <riship@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
puririshi98
added a commit
to puririshi98/vllm
that referenced
this pull request
Sep 1, 2026
PR vllm-project#53388 added SpeculativeConfig.disable_eagle_block_drop and routed every EAGLE trailing prefix-cache block-drop site through a single use_eagle_block_drop() predicate. Adopt that mechanism to make the safe default drafter-method aware: the flag becomes `bool | None = None`, and when unset, use_eagle_block_drop() resolves from the method -- eagle/eagle3/mtp keep the drop (behavior unchanged), dflash/dspark disable it. An explicit user setting always wins, and the experimental warning now fires only on an explicit opt-out. The drop exists because EAGLE-family drafters combine the prefill-lookahead token (one past a chunked-prefill boundary) with the chunk's final hidden state and write the result into the drafter KV cache, so the last block of a prefix-cache hit may hold KV polluted by a continuation the matching request does not share. dflash/dspark drafters structurally cannot cache lookahead-polluted KV: their context KV is projected from target hidden states and positions only (precompute_and_store_context_kv), and the lookahead (anchor) token writes KV only at positions past the chunk end, in a block that is overwritten with clean context KV before it can be completed and hashed. The drop therefore protects nothing for them, while costing one full scheduler block of recompute on every prefix-cache hit. On hybrid mamba models in align mode both gates -- the FullAttn hit drop and the chunk-split last_cache_position backoff -- ride the same predicate, so they move together and the recovered block is actually usable. Behavior matches the previously measured explicit exemption: with a dspark drafter on a hybrid mamba target (32K-token shared prefix, 2K unique suffix, 256 output, temp 0, scheduler block 2192), steady-state cache-hit cached_tokens rise 28,496 -> 30,688 (hit recompute 6,336 -> 4,144 tokens) in every repeat on two GPU generations, cache-hit TTFT improves ~20-22%, decode throughput is flat within run-to-run noise, and acceptance length stays pinned at 3.00 with identical per-position acceptance rates. Hit-vs-miss logit deltas on the reused block sit below the within-hit noise floor and at the same order as the unpatched control's, with the greedy argmax stable. A None default resolves fail-closed: new eagle-family methods keep the drop until their drafter KV provenance is audited. Signed-off-by: Rishi Puri <riship@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ptorsten
added a commit
to ptorsten/vllm
that referenced
this pull request
Sep 2, 2026
…hetero tests, xfail vllm-project#53388 boundary test under grid stops, mixed-page fallback, keep packed path as upstream Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
mylibrar
pushed a commit
to tanyuqian/vllm
that referenced
this pull request
Sep 3, 2026
vllm-project#53388) Signed-off-by: Ziming Huang <zelda.huanghuang@gmail.com> Signed-off-by: Ziming Huang <48115868+ZeldaHuang@users.noreply.github.com> Co-authored-by: OpenAI Codex <codex@openai.com>
This was referenced Sep 6, 2026
Open
sheralskumar
pushed a commit
to sheralskumar/vllm
that referenced
this pull request
Sep 8, 2026
vllm-project#53388) Signed-off-by: Ziming Huang <zelda.huanghuang@gmail.com> Signed-off-by: Ziming Huang <48115868+ZeldaHuang@users.noreply.github.com> Co-authored-by: OpenAI Codex <codex@openai.com>
puririshi98
added a commit
to puririshi98/vllm
that referenced
this pull request
Sep 9, 2026
PR vllm-project#53388 added SpeculativeConfig.disable_eagle_block_drop and routed every EAGLE trailing prefix-cache block-drop site through a single use_eagle_block_drop() predicate. Adopt that mechanism to make the safe default drafter-method aware: the flag becomes `bool | None = None`, and when unset, use_eagle_block_drop() resolves from the method -- eagle/eagle3/mtp keep the drop (behavior unchanged), dflash/dspark disable it. An explicit user setting always wins, and the experimental warning now fires only on an explicit opt-out. The drop exists because EAGLE-family drafters combine the prefill-lookahead token (one past a chunked-prefill boundary) with the chunk's final hidden state and write the result into the drafter KV cache, so the last block of a prefix-cache hit may hold KV polluted by a continuation the matching request does not share. dflash/dspark drafters structurally cannot cache lookahead-polluted KV: their context KV is projected from target hidden states and positions only (precompute_and_store_context_kv), and the lookahead (anchor) token writes KV only at positions past the chunk end, in a block that is overwritten with clean context KV before it can be completed and hashed. The drop therefore protects nothing for them, while costing one full scheduler block of recompute on every prefix-cache hit. On hybrid mamba models in align mode both gates -- the FullAttn hit drop and the chunk-split last_cache_position backoff -- ride the same predicate, so they move together and the recovered block is actually usable. Behavior matches the previously measured explicit exemption: with a dspark drafter on a hybrid mamba target (32K-token shared prefix, 2K unique suffix, 256 output, temp 0, scheduler block 2192), steady-state cache-hit cached_tokens rise 28,496 -> 30,688 (hit recompute 6,336 -> 4,144 tokens) in every repeat on two GPU generations, cache-hit TTFT improves ~20-22%, decode throughput is flat within run-to-run noise, and acceptance length stays pinned at 3.00 with identical per-position acceptance rates. Hit-vs-miss logit deltas on the reused block sit below the within-hit noise floor and at the same order as the unpatched control's, with the greedy argmax stable. A None default resolves fail-closed: new eagle-family methods keep the drop until their drafter KV provenance is audited. Overlap: open PR vllm-project#54163 (Fixes vllm-project#53477) stops the same dflash/dspark block drop by redefining use_eagle_block_drop() over a method list (use_eagle_preserves_target_kv_cache(): eagle, eagle3, mtp) in the same predicate and the same scheduler warning block, reaching the same default outcome. This commit keeps the explicit flag and resolves its None default per method inside use_eagle_block_drop(), so an explicit user setting still wins for every method. Whichever lands first, the other reduces to a rebase. Signed-off-by: Rishi Puri <riship@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Add an opt-in
disable_eagle_block_dropspeculative-decoding option forEAGLE-family methods, including dSpark. When enabled, vLLM keeps the trailing
prefix-cache block instead of conservatively dropping it after speculative-model
prefill.
This does not bypass target-model verification. The option can change which
draft tokens are proposed and therefore may affect speculative-token acceptance
rates, but accepted output tokens are still verified by the target model.
Test Plan
Run an A/B prefix-cache benchmark with the following configuration:
moonshotai/Kimi-K3MXFP4 weightsInferact/Kimi-K3-DSparkFLASHINFER_MLARun the following command on both nodes. Set
NODE_RANK=0on the API node andNODE_RANK=1on the worker node; only the worker uses--headless.For the default baseline, use the same command but omit
"disable_eagle_block_drop": true.After resetting the prefix cache, send one untimed request to populate the
12,288-token shared prefix, capture the Prometheus counters, and then run the
timed benchmark:
vllm bench serve \ --backend openai \ --base-url http://${MASTER_ADDR}:8000 \ --model moonshotai/Kimi-K3 \ --tokenizer moonshotai/Kimi-K3 \ --trust-remote-code \ --dataset-name prefix_repetition \ --num-prompts 160 \ --prefix-repetition-prefix-len 12288 \ --prefix-repetition-suffix-len 256 \ --prefix-repetition-num-prefixes 1 \ --prefix-repetition-output-len 1 \ --disable-shuffle \ --request-rate inf \ --max-concurrency 16 \ --temperature 0 \ --ignore-eos \ --percentile-metrics ttft,e2el \ --metric-percentiles 50,90,99The shared prefix is aligned to Kimi-K3's 1,536-token Mamba state interval.
With the default behavior, the final aligned block is dropped, so each timed
request re-computes 1,536 additional prompt tokens.
For acceptance rate, run a second A/B on the complete GSM8K test split. The
official
openai/gsm8ktest parquet was exported one-to-one to ShareGPT JSONbecause the runtime image does not include the optional Hugging Face
datasetsdependency. Both variants use all 1,319 questions in the same order, a maximum
output length of 256, concurrency 16, temperature 0, and EOS handling enabled.
Run one untimed request before capturing the Prometheus counters, then run:
vllm bench serve \ --backend openai \ --base-url http://${MASTER_ADDR}:8000 \ --model moonshotai/Kimi-K3 \ --tokenizer moonshotai/Kimi-K3 \ --trust-remote-code \ --dataset-name sharegpt \ --dataset-path gsm8k-test-sharegpt.json \ --sharegpt-output-len 256 \ --num-prompts 1319 \ --no-oversample \ --disable-shuffle \ --request-rate inf \ --max-concurrency 16 \ --temperature 0 \ --percentile-metrics ttft,tpot,e2el \ --metric-percentiles 50,90,99Test Result
All timed prefix-cache requests succeeded (
160/160) in both variants.disable_eagle_block_drop=trueAll GSM8K requests also succeeded (
1,319/1,319) in both variants. Timed-passPrometheus counter deltas matched the benchmark summary:
disable_eagle_block_drop=trueNo acceptance-rate regression was observed on the complete GSM8K test split;
the no-drop variant increased acceptance by 0.153 percentage points. GSM8K's
independent prompts produced a 0% prefix-cache hit rate, so this result checks
for a general acceptance regression rather than the long-prefix cache-hit path.
Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model.