Repository navigation
[Core][PD] Allow FULL decode graphs for one-token prompt continuations on MRv2 - #58374
Closed
NickLucche wants to merge 5 commits into
Closed
NickLucche wants to merge 5 commits into
NickLucche wants to merge 5 commits into
Conversation
…V consumers On the decode side of P/D, a full-prompt KV import resumes with a single-token replay of the last prompt token. That request is still logically prefilling, so vllm-project#51865's strict has_prefill check pushes the whole batch off the FULL decode graph on every new arrival. With decode_query_len == 1 the replay is decode-shaped, and linear attention backends already treat one-token chunks with prior state as decodes. Relax only the graph classification for KV consumers; logical prefill state is unchanged. Co-authored-by: Claude Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
Co-authored-by: Claude Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
Co-authored-by: Claude Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
Add KVTransferConfig.is_pd_consumer: kv_consumer role with a known P/D connector (NIXL, Mooncake, MoRIIO), directly or inside MultiConnector. Co-authored-by: Claude Signed-off-by: NickLucche <nicolo.lucchesi@mistral.ai>
NickLucche
requested review from
ProExpertProg,
WoosukKwon,
houseroad,
mgoin,
njhill,
robertgshaw2-redhat,
tlrmchlsmth,
yewentao256 and
youkaichao
as code owners
September 23, 2026 14:24
Member
Author
Pre-PR vs Post-PRBaseline = Qwen3-0.6B, P/D TP1/TP1NixlConnector 1P+1D on B200, random dataset with
Llama-3-8B-Instruct, P/D TP1/TP1NixlConnector 1P+1D on B200, random dataset with
MRV1 vs MRV2, Qwen3-0.6B, P/D TP1/TP1NixlConnector 1P+1D on B200, random dataset with
gsm8k (5-shot, strict / flexible)
|
Contributor
|
This pull request has merge conflicts that must be resolved before it can be |
Member
Author
|
we merged Nick's #58400 |
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.
On MRV2, the decode node in P/D leaves FULL CUDA graphs every time a new request arrives.
This affects every KV connector. It was first reported with HiSparse (#57049 / #57939), but HiSparse doesn't cause it.
How it happens
Suppose D has speculation disabled and two requests already decoding.
A third request arrives with a 129-token prompt whose KV has been imported from P.
D replays the last prompt token to obtain logits for the first generated token.
The scheduler therefore sets num_computed_tokens = 128 and schedules one token:
Before: C makes has_prefill=True. MRV2 rejects the FULL decode graph for the entire batch, so A and B also fall back to PIECEWISE or eager execution. In P/D serving, every new arrival can trigger this.
After: MRV2 recognizes that every request schedules one token and already has context, making the batch eligible for a FULL decode graph. C remains logically prefilling, so input preparation still loads its token from the prompt.
The fix
This changes only graph classification in
gather_batch_req_state.On D nodes with
decode_query_len == 1,max_query_len == 1and no PCP, a prefilling request with prior state (num_computed_prefill_tokens > 0) no longer blocks FULL graphs.Fresh one-token prompts (
num_computed == 0) are still excluded; that is the #50532 bug #51865 fixed.This is safe because a one-token query over existing context is what the decode kernels already expect. Sparse MLA and the indexer split by query length, and Mamba, GDN and KDA already treat one-token chunks with prior state as decodes
(
mamba_attn.py:474,gdn_attn.py:250).Testing
Ignore ITL I will post bigger benchs soon
On PD checking
Yeah I know we're missing a cleaner way to answer the "am I P on a PD setup" question.
I will follow up with something better (it doesn't really belong to this PR), but that's why I am basically enumerating all PD connectors for this fix.
PS: Spec decode on D isn't covered: the scheduler pads the replay to K+1 tokens, which still trips
has_prefill.That will be a follow-up.
cc @njhill @S1ro1 @LucasWilkinson