Skip to content

[Attention][MLA] Per-request scheduling for MLA chunked context - #50613

Merged
MatthewBonanni merged 14 commits into
vllm-project:mainfrom
MatthewBonanni:mla-per-request-context-chunks
Aug 6, 2026
Merged

MatthewBonanni merged 14 commits into
vllm-project:mainfrom
MatthewBonanni:mla-per-request-context-chunks

Conversation

@MatthewBonanni

@MatthewBonanni MatthewBonanni commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

Implements #50497. MLA prefill chunks are fit into the available workspace rather than forced to be the same size. This can reduce the overall number of chunks and improve prefill latency.

Validation

Correctness

pytest tests/v1/attention/test_mla_context_chunks.py -q passes

GSM8K with DeepSeek-V2-Lite-Chat, TP=4, DCP=2, FlashMLA, prefix caching:

Revision Strict exact match Flexible extract
main 861/1,319 — 65.277% (1.311%) 863/1,319 — 65.428% (1.310%)
PR 867/1,319 — 65.732% (1.307%) 881/1,319 — 66.793% (1.297%)
Delta +6 — +0.455 pp +18 — +1.365 pp

Performance

This is a worst-case scenario but it highlights the optimization. We run a batch of size 32: 1 request has 60k context and rest have have 16. (60,496 total context tokens)

On main, the workspace (65,536 tok) gets divided evenly among the requests, so it uses 30 chunks for the batch. On PR, all context fits in the workspace, so it's all processed in a single chunk.

Run on H100:

python benchmarks/attention_benchmarks/benchmark.py \
  --backend FLASH_ATTN_MLA \
  --prefill-backends fa3 \
  --batch-specs q513s60513_31q513s529 \
  --num-layers 1 \
  --head-dim 576 \
  --num-q-heads 16 \
  --num-kv-heads 1 \
  --block-size 16

main:

Prefill Backend Results:
             Attention Benchmark Results             
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━━━━┓
┃ Batch                 ┃        ┃ Batch ┃      fa3 ┃
┃ Spec                  ┃ Type   ┃  Size ┃ Time (s) ┃
┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━━━━┩
│ q513s60513_31q513s529 │ extend │    32 │ 0.008712 │
└───────────────────────┴────────┴───────┴──────────┘

PR:

Prefill Backend Results:
             Attention Benchmark Results             
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━┳━━━━━━━━━━┓
┃ Batch                 ┃        ┃ Batch ┃      fa3 ┃
┃ Spec                  ┃ Type   ┃  Size ┃ Time (s) ┃
┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━╇━━━━━━━━━━┩
│ q513s60513_31q513s529 │ extend │    32 │ 0.002141 │
└───────────────────────┴────────┴───────┴──────────┘

AI assistance was used to develop and validate this change.

Replace the batch-column chunked-context schedule with a flat list of
per-request chunks (RFC vllm-project#50497).

Previously the workspace was split evenly across every prefill with
context and each iteration processed the same context window of every
prefill, so a heterogeneous batch wasted most of the workspace per launch
and paid attention/merge over the whole prefill batch on every iteration.
The workspace also had to be floored at `max_num_seqs * block_size`, which
overrides the deliberate 64k cap on models whose page size is inflated to
cover a hybrid state page.

Chunks now greedily pack whole requests and split a request only when its
context alone exceeds the workspace, so a chunk covers a contiguous run of
prefills and charges attention, up-projection and merging only to those
requests. Because chunks stay in request order, only a chunk's first
request can continue an earlier chunk: accumulating the context partial is
one request-slice merge plus one bulk write.

- `mask_empty_context` and `has_empty_context` are deleted; a chunk cannot
  contain an empty context span by construction.
- The workspace floor drops from `max_num_seqs * block_size` to one page,
  making workspace memory independent of `max_num_seqs`.
- `prefill_tokens_with_context` is now the query end of the last prefill
  with context, and the builder reports the token ranges of context-free
  prefills inside it so the partial is neutralized there. This fixes a
  latent mismatch when the prefills with context were not a contiguous
  prefix of the batch.
- `run_prefill_context_chunk` takes the `ContextChunk` instead of a chunk
  index, since every sequence-length field is now chunk-local.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
MatthewBonanni and others added 11 commits August 4, 2026 14:25
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Co-authored-by: OpenAI Codex <noreply@openai.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

Comment thread tests/v1/attention/test_mla_context_chunks.py Outdated
Comment thread tests/v1/attention/test_mla_context_chunks.py Outdated
Comment thread vllm/model_executor/layers/attention/mla_attention.py Outdated
Comment thread vllm/model_executor/layers/attention/mla_attention.py Outdated
Comment thread vllm/model_executor/layers/attention/mla_attention.py Outdated
Comment thread vllm/model_executor/layers/attention/mla_attention.py Outdated
Signed-off-by: Matthew Bonanni <mbonanni@redhat.com>
@mergify mergify Bot added the kimi label Aug 6, 2026
@mergify mergify Bot added the k3 label Aug 6, 2026

@LucasWilkinson LucasWilkinson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thank you!!!

@github-project-automation github-project-automation Bot moved this to Ready in NVIDIA Aug 6, 2026
@LucasWilkinson LucasWilkinson added the ready ONLY add when PR is ready to merge/full CI is needed label Aug 6, 2026
@LucasWilkinson

Copy link
Copy Markdown
Collaborator

/run ci

@MatthewBonanni

Copy link
Copy Markdown
Member Author

/ci run

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

✅ Triggered Buildkite CI #82693 for commit baa94e768828.

@MatthewBonanni
MatthewBonanni enabled auto-merge (squash) August 6, 2026 15:14
@MatthewBonanni
MatthewBonanni merged commit b38e111 into vllm-project:main Aug 6, 2026
109 of 110 checks passed
@github-project-automation github-project-automation Bot moved this from Ready to Done in NVIDIA Aug 6, 2026
@MatthewBonanni
MatthewBonanni deleted the mla-per-request-context-chunks branch August 6, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

k3 kimi nvidia ready ONLY add when PR is ready to merge/full CI is needed

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants