Repository navigation
[ROCm][Kimi-K3] Keep KDA prefill checkpoints with the gluon backend - #63297
Conversation
The gluon KDA prefill backend (AITER chunk_kda) cannot export mid-prefill state checkpoints, so selecting it turned prefill checkpoints off and made the scheduler split the last prefill chunk at the block boundary instead. Keep the checkpoint block reserved for gluon when the fused HIP kernel is built, and run only the prefill steps that carry checkpoint metadata through the fused kernel. All other steps stay on gluon. Signed-off-by: seungrokj <seungrok.jung@amd.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment Once the PR is approved or has the If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
ChuanLi1101
left a comment
There was a problem hiding this comment.
This can land. Gluon cannot write the mid-prefill state, so the scheduler splits the last chunk into an extra step. This PR keeps the checkpoint and runs only that step on the fused kernel. The other steps stay on gluon. That is why TTFT goes from 413 ms to 237 ms at 4K and from 484 ms to 374 ms at 8K. 32K does not change, because the checkpoint is already on a chunk boundary.
|
✅ @seungrokj, CI is now available for this PR.
|
|
/ci run |
|
✅ Triggered Buildkite CI #96999 for commit |
|
/ci run |
|
✅ Triggered Buildkite CI #97581 for commit ℹ️ This PR is 1 commit behind upstream |
dllehr-amd
left a comment
There was a problem hiding this comment.
Looks good! Thanks @seungrokj!
|
lgtm |
|
/ci run |
|
✅ Triggered Buildkite CI #97984 for commit ℹ️ This PR is 15 commits behind upstream |
|
/ci run |
|
✅ Triggered Buildkite CI #98396 for commit |
…st stub GDNAttentionMetadataBuilder now reads speculative_config.enable_adaptive_verification (vllm-project#60229), which the test's stub speculative config did not define. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: seungrokj <seungrok.jung@amd.com>
|
/ci run |
|
✅ Triggered Buildkite CI #98449 for commit ℹ️ This PR is 12 commits behind upstream |
…ckpoint Signed-off-by: seungrokj <seungrok.jung@amd.com> # Conflicts: # tests/models/kimi_k3/test_amd_kda_checkpoint.py
|
/ci run |
|
✅ Triggered Buildkite CI #98790 for commit |
Overview
Since #59552, the gluon KDA prefill backend (AITER
chunk_kda) is the default on CDNA4. It switches Kimi-K3's KDA prefill checkpoints off, because AITERchunk_kdacannot export the mid-prefill state. This PR keeps the checkpoints on with gluon: only prefill steps that carry checkpoint metadata go to the fused HIP kernel, and every other step stays on gluon.Claims
kda_prefill_backend="gluon"and the fused kernel built,get_kv_cache_specreserves the prefill checkpoint block (alignmentKDA_CHECKPOINT_ALIGNMENT), as thefusedbackend does. Previously it reported 0 blocks.checkpointmetadata is set runschunk_kda_prefill(backend="fused"). Steps without checkpoint metadata keep the configured backend.is_fused_kda_chunk_supported()is False), gluon still opts out of checkpoints, so behavior is unchanged.Validation
Kernel and spec tests, run on MI355X (1 GPU) in
vllm/vllm-openai-rocm:nightly-rocm100-df6603f0583375f244d1ac6d36265462b7490392, with this diff applied to the image's vLLM (itskimi_k3/amd/kda.pymatches the base commit):pytest tests/models/kimi_k3/test_amd_kda_checkpoint.py -k gluon_backendtest_gluon_backend_keeps_the_checkpointfails:assert 0 == 1onnum_prefill_checkpoint_blockspytest tests/models/kimi_k3/test_amd_kda_checkpoint.pyVLLM_ROCM_USE_AITER=1 pytest tests/models/kimi_k3/test_amd_kda_chunk.pypytest tests/models/kimi_k3/test_amd_kda_checkpoint.py tests/models/kimi_k3/test_amd_kda_chunk.py(no AITER)The new
test_gluon_hands_checkpoint_steps_to_fusedtest prefills one 1024-token sequence in three steps: gluon[0, 256), then fused[256, 768)with a checkpoint at token 512, then gluon[768, 1024). It compares the result with a single Triton prefill of the whole sequence:With
VLLM_ROCM_USE_AITER=1,test_amd_kda_checkpoint.pyhas 11 metadata-builder failures (KimiK3ROCmKDAMetadataBuilder builds its own FLA chunk metadata ... 'aiter_flydsl'). They fail the same way on the unpatched image, and this PR does not touch them.End-to-end check: Kimi-K3 TP8, DCP8, DSpark with 4 drafts and real rejection sampling,
--enable-prefix-caching(mamba cache modealign),--max-num-batched-tokens 8192, on the same image. Both arms use the defaultautoKDA prefill backend, which resolves to gluon.KDA prefill backend: gluonKDA prefill backend: gluon,KDA prefill checkpoint enabled.The GSM8K prompts are shorter than one mamba block, so they never reach a checkpoint (
prefix_cache_hits_totalgrows only during the prefix check). GSM8K therefore shows that steps without a checkpoint still serve correctly on gluon. The prefix check is what exercises the checkpoint.The prefix check sends four prompts of about 3.8k / 9.4k / 20.6k / 45.2k tokens. Each prompt is a list of facts plus a question about one of them, run with greedy decoding:
/reset_prefix_cache.Cached lengths are the same with and without the PR. Without it, the scheduler gets the same snapshot by ending the prefill step at the block boundary and running the tail as an extra step. With the PR, the snapshot comes out of the fused kernel inside the step, and the warm answers, which resume from it, are correct. This host is thermally throttled, so the time saved by dropping the extra step was measured on another node (below).
Time to first token. Kimi-K3 TP8 on one unthrottled MI355X node, same image, default
auto(gluon) backend,--enable-prefix-caching, DSpark with synthetic acceptance. Two server configurations from the InferenceX Kimi-K3 recipe:--max-num-batched-tokens 16384.--max-num-batched-tokens 8192.The client sends one random prompt at a time with 1 output token, after a warmup, using the same seeds in both arms. No prompt hit the prefix cache. Each cell is the median of 10 prompts (6 at 32768 and 65536), in ms.
Where the PR removes the split, it saves 107–176 ms per prompt. The unchanged rows are expected:
prefix_check.py
Details
can_checkpointrequiredkda_prefill_backend == "fused". Whenautoresolved to gluon, the spec reserved no checkpoint block. The scheduler then fell back to splitting the final prefill chunk at the block boundary (scheduler.py), which costs an extra step per prompt and drops the interior checkpoints.chunk_kda(amd-aiter 0.1.25 / 0.1.26 and AITER main) has no checkpoint output. The proper fix is to export the state from the chunk walk inside the kernel; that needs an AITER change first. This PR is the vLLM-only bridge. When AITER grows that output, the routing can be replaced by a signature check.flashkdaprefill backend and does not touch checkpoint gating.MambaBase.get_prefill_checkpoint_alignment()and edits the sameget_kv_cache_spec. Whichever lands second needs a small rebase; the gating condition here carries over unchanged.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 Opus 5.5 (
claude-opus-5-5, Claude Code) drafted the change, the tests and this description, and ran the validation above. The human submitter reviews every changed line before marking the PR ready.🤖 Generated with Claude Code