Repository navigation
[Bugfix][ROCm] Fix Kimi K3 online quantization with padded projections - #61950
Conversation
Declare checkpoint-backed elements so each merged projection completes after its real shards arrive, and initialize declared padding on materialization. Exercise real KDA construction and loading to verify source release and padding preservation across TP ranks and shard orders. Co-authored-by: Codex <noreply@openai.com> Signed-off-by: whx-sjtu <xiaowang990929@gmail.com>
Online quantization (e.g. --quantization-config targeting the KDA input projection and the routed expert projections with mxfp8) broke three places in the Kimi K3 NVIDIA model: - The padded KDA input projection counted its alignment padding, which has no checkpoint shard, toward online loading completion, so the layer never finished loading and kept every checkpoint tensor alive. Declare the checkpoint-backed element count and re-zero the padding after each shard load (the padding is materialized from meta storage). - The routed output transform fused the residual add into an addmm on the raw up-projection weight, bypassing the quantized linear method and its scales. Fuse only for unquantized projections; otherwise call the layer and add. - The latent MoE tail kernels read the up-projection weight directly. Enable them only for unquantized up-projections. The KDA loader regression adapts the reproducer from vllm-project#61950. Co-authored-by: Codex <noreply@openai.com> Signed-off-by: wzhao18 <wzhao18.sz@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
✅ @whx-sjtu, CI is now available for this PR.
|
|
/ci run |
|
✅ Triggered Buildkite CI #97873 for commit |
The test imports the Kimi K3 KDA layer, which pulls numba into the shared model_executor pytest process and breaks the Triton dispatcher tests that run after it. Signed-off-by: whx-sjtu <xiaowang990929@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/ci run |
|
✅ Triggered Buildkite CI #97964 for commit |
simondanielsson
left a comment
There was a problem hiding this comment.
Thanks for the fix!
| ) | ||
| if self.in_proj_padding: | ||
| self.in_proj_qkvgfab.weight.data[-self.in_proj_padding :].zero_() | ||
| # Alignment rows are not part of the checkpoint. |
There was a problem hiding this comment.
Suggestion: can we instead fix this in the same way as nvidia, i.e. add a new _KimiGDNMergedColumnParallelLinear and add the padding/zeroing fix there? Alternatively just import their implementation directly
That way we don't have to touch any shared code
There was a problem hiding this comment.
Done — moved the padding handling into an AMD-local _PaddedKimiGDNMergedColumnParallelLinear (subclassing the shared Kimi-Linear one), mirroring the NVIDIA class; meta.py is no longer touched. I didn't import the NVIDIA class directly since nvidia/kda.py pulls the NVIDIA backend's ops into the ROCm path, and its block-scale replication would change AMD loading behavior.
Mirror the NVIDIA implementation: the merged projection declares its checkpoint-backed size and re-zeroes padding rows after each weight load, so online processing no longer needs the shared meta.py change. Signed-off-by: whx-sjtu <xiaowang990929@gmail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/ci run |
|
✅ Triggered Buildkite CI #98256 for commit |
Overview
Fix ROCm Kimi K3 online weight loading so its padded merged KDA projection finishes as soon as all checkpoint shards arrive. Following review, the fix lives in an AMD-local
_PaddedKimiGDNMergedColumnParallelLinear, mirroring the NVIDIA implementation; no shared loader code is changed.Summary
Claims
empty_stridedand drops the constructor's zero-init.vllm/models/kimi_k3/amd/kda.pychanges; the shared Kimi-Linear projection andreload/meta.pyare untouched.Validation
Evidence
Local regression on ROCm (
vllm/vllm-openai-rocm:nightlycontainer), using the KDA online-loading test from this PR's first revision as an out-of-tree harness: realKimiK3DeltaAttentionconstruction at TP8, two TP ranks × two shard orders × padded/unpadded head counts,empty_stridedpoisoned with NaN.mainruff passes; the mypy hook reports no new errors in
amd/kda.py(28 vs. 29 pre-existing onmain).No unit test is added. The first revision's test imported the Kimi K3 KDA layer into the shared
model_executorpytest process; that pulls in numba, which exposes a latenttriton_utils/dispatcherissue and fails the Triton dispatcher tests that run afterwards. That dispatcher issue is independent of this fix and is left to a separate PR.Full-model GPU validation used vLLM
81198e97ba7eee2a22540caaa756b7fdddcb4d93plus the first revision of this fix (sameweight_loader_numelaccounting; padding zeroed during materialization instead of in the loader), on 2 × 8 MI355X GPUs, TP8/DCP8, fastsafetensors, target-model FP8 PTPC, DSpark4 with synthetic AL=3.36, C48/3600s. Both runs had the same P/D hosts and started with ~287.707 GiB free per GPU. The current revision has not been rerun at full-model scale.Source-reference bytes overlap allocated/reserved memory and must not be added to those counters. This verifies loading and serving completion, not decoding accuracy or a throughput gain. The fixed run had 7 empty-content request errors and a 300s cancel-drain timeout, retained in the run logs.
Details
At TP8, KDA's local merged projection has 6284 real rows and 4 alignment rows. Without
weight_loader_numel, online processing waits for 6288 rows although the checkpoint only provides the six real projections, so it defers processing and retains every source until model finalization. With GPU-backed fastsafetensors inputs this exhausts VRAM before loading completes.During online loading the constructor's padding
zero_()runs on meta, and materialization allocates withempty_strided. Layerwise processing then replays the buffered calls through the layer's weight loader, so re-zeroing the padding rows there restores them.CopyCounteronly countscopy_, so the zeroing does not affect completion accounting. It adds no steady-state inference work.The subclass extends the shared Kimi-Linear projection instead of importing the NVIDIA class, which would pull NVIDIA backend modules into the ROCm path and change AMD loading through its block-scale replication.
Related work / duplicate check: #50523 fixes general zero initialization for rematerialized weights; it does not declare KDA's loadable size and does not resolve this source-retention failure. If it lands, the loader re-zeroing becomes redundant but harmless. Open KDA quantization PRs and #61287 were also checked; no matching KDA completion fix was found.
Merge Danger
Door: two-way. Blast Radius: Kimi K3 ROCm KDA weight loading.
AI assistance was used: Codex prepared the first revision; Claude Code prepared the review revision and the CI analysis. Results above describe agent-run validation.
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.
🤖 Generated with Claude Code