Repository navigation
Conversation
b5a9c19 to
af630cf
Compare
|
This pull request has merge conflicts that must be resolved before it can be |
fb9f9d3 to
12b48d9
Compare
12b48d9 to
2d70df0
Compare
2d70df0 to
38e1e36
Compare
CI selector (shadow): 45 test steps (93 jobs) instead of 66 (99 jobs)Shadow mode: this changes nothing about what CI runs. It shows what the evidence-based selector would pick for this PR, next to today's rules. How it works. Feedback welcome: reply here if it would skip a step this change needs, or runs something unrelated.
Selector would run (45)
Would skip (today's rules run them) (40)
Would add (today's rules do not run them) (19)
AMD mirrors: would skip (58)
AMD mirrors: would add (4)
22 changed files · base |
38e1e36 to
cc553c6
Compare
…of linear post-load order MegaMoE fuses the DeepSeek-V4 shared expert from its block-FP8 UE8M0 scales, which the shared linears' DeepGEMM post-load hook repacks into int32 in place. _finalize_shared_expert_weights only converted scales still in checkpoint layout and passed packed ones straight to MegaMoE, so it was correct only when it ran before that hook. A dummy load finalizes after it, and DeepGEMM asserted at startup. The packed layout already holds one UE8M0 byte per (row, k-block). _prepare_shared_expert_scale now reads per-row exponents from either layout and builds the same 1x32 MegaMoE scale. Real loads still finalize before the hook and are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
… hook Several models finalized weight-derived state from inside load_weights, from forward(), or not at all. BaseModelLoader.load_model already dispatches the model's process_weights_after_loading once per cold load, including dummy loads, which never call load_weights. Move that work to the hook so every cold load path runs it exactly once after all weights are in place. Moved to process_weights_after_loading: - Kimi-K3 MTP: MegaMoE finalize_weights (was in load_weights). - DeepSeek-V4 (NVIDIA and XPU) target, MTP and DSpark: finalize_mega_moe_weights (was in load_weights). The VL wrapper drops its finalizes_weights_during_load handshake and always delegates the hook. - MiniCPM-V/O: moving the resampler to the device (was in load_weights, so a dummy load left pos_embed on CPU and the first forward failed). - OpenPangu: the text root and the MTP model sweep post_weight_load over submodules; the VL root delegates to its language model. The MTP model previously never refreshed its sink keys after loading. OpenPanguModel.load_weights keeps its own sweep. Removed lazy fallbacks: - Kimi-K3 and DeepSeek-V4 XPU MegaMoE forward() and DeepSeek-V4 NVIDIA get_expert_weights() no longer call finalize_weights(); they assert that the transformed weights exist. The NVIDIA MegaMoE shared-expert fusion now always sees scales the linear hook has already packed, which the parent commit makes correct. DeepSeek-V4.1 still finalizes inside load_weights: its mega-attention finalize permutes the wq_b / wo_a weight scales in place, and running it after the linear hook is not verified yet. Loaders: - TensorizerLoader: a raw (not vLLM-serialized) tensorizer checkpoint now loads through BaseModelLoader.load_model instead of a private helper that called model.load_weights and returned, skipping per-layer quant processing and the model hook. Block-FP8 checkpoints crashed in their first forward on that path. Delegating also builds the model from the passed model_config and honours load_config.device, as other loaders do. Same change and test as vllm-project#55318. - BaseModelLoader.load_weights documents that a cold load bypassing load_model must dispatch the hook itself, and the vLLM-serialized tensorizer exception. - finalize_layerwise_reload gets a typed signature and a docstring stating it does not dispatch the model hook. Also: drop a no-op token_map.to() in Medusa whose result was discarded, and move the DeepSeek-V4 VL wrapper tests out of the ROCm-gated file. Co-authored-by: nicole-lihui <44200120+nicole-lihui@users.noreply.github.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: aoshen02 <aoshen@inferact.ai>
cc553c6 to
b853938
Compare
|
This pull request has merge conflicts that must be resolved before it can be |
Overview
Several models finalized weight-derived state from inside
load_weights, lazily fromforward()/ EPLBget_expert_weights(), or not at all.BaseModelLoader.load_modelalready dispatches the model'sprocess_weights_after_loadingonce per cold load, includingload_format="dummy", which never callsload_weights. This PR moves that work to the hook, so every cold-load path runs it once after all weights are in place. It also routes raw (non-vLLM-serialized) tensorizer checkpoints throughBaseModelLoader.load_model, the same change as #55318.Context: weight reload (RFC #54477, tracker #50079) needs
load_weightsto only load. RFC #59502 assumes the model hook is cold-start-only, as it is here.What changes
finalize_weightsinload_weights; also lazily fromforward()KimiK3MTP.process_weights_after_loading;forward()assertsforward()forward()assertsfinalize_mega_moe_weightsinload_weightsfinalize_mega_moe_weightsinload_weights, plus a lazy call inforward()forward()assertsload_weights(finalizes_weights_during_load)get_expert_weights()(EPLB)load_weightsOpenPanguModel.load_weights; MTP: never refreshed sink keyspost_weight_loadfrom the hook; VL root delegates to its language modelload_weights, then return (no per-layer quant processing, no model hook)BaseModelLoader.load_modeltoken_map.to(...)with the result discardedMoving DeepSeek-V4 NVIDIA to the hook means the MegaMoE shared-expert fusion always runs after the linear hook has packed its scales; #59927 (the first commit here) makes that correct.
Not changed: DeepSeek-V4.1 still finalizes inside
load_weights. Its mega-attention finalize permutes thewq_b/wo_aweight scales in place, and running it after the linear hook is not verified yet.Evidence
A/B on GB200, image
vllm/vllm-openai:nightly-dev-arm64-cu130-ac9126e58aa7(sha256:8bafba97…, built fromac9126e58aa7).Fixed (fails before, works after):
fp8_gemm_nt, first forward)dummylayout.hpp:114dummyindices should be either on cpu or on the same device as the indexed tensor (cpu)pos_embedoncuda:0dummydummyk_layernorm(param_sink_key)(max abs diff 1.52)dummyforward(); 32 morefinalize_weightscalls during generationKimiK3MTP.process_weights_after_loading; 0 calls during generationUnchanged (bit-identical before/after, real weights):
fp8, default and raw tensorizervllm serveDeepSeek-V4-Flash-deepgemm-mega-moe.yaml)Reproduction
Scripts are in the PR author's validation directory; each records token ids and raw logprobs to JSON, compared with
cmp_ab.py.g3_suite.sh: every "fixed" row.g1_ab.py/g1_serve.py: the "unchanged" rows.--probe sinkcomparesattn.sink_keywithk_layernorm(param_sink_key)per layer.compress_ratios[0, 0, 4, 128, 0]. The existing 4-layer Base proxy has FP8 experts, which MegaMoE rejects.Unit tests (local,
humming-kernels==0.1.16as pinned):The two new behaviour tests fail on
mainand pass here:'Linear' object has no attribute 'cpu_linear'. It is adapted from [Bugfix][Model Loader] Run post-load processing for raw Tensorizer weights #55318's test.pre-commitpasses, exceptmypy-3.10onvllm/models/deepseek_v4/xpu/model.py, which reports the same fivedeep_gemmattr-definederrors on unmodifiedmain. The new and moved test files are wired into the "Basic Models (Other)" Buildkite job, NVIDIA and AMD.Still running (results will be added here):
Not validated:
merge_convmodule; R-72B-2512's config lacksfirst_k_dense_replace.Limitations (found, not fixed here)
finalize_layerwise_reloaddoes not dispatch the model hook. Derived state that only the hook rebuilds is not refreshed by a layerwise weight reload; reload-time refresh is RFC [RFC]: Direct Weight Reload for RL Training #54477's scope. OpenPangu's text model also sweeps inload_weights; its MTP drafter does not.Overlap. The raw-tensorizer change is the same as draft #55318 (nicole-lihui), and its test is adapted from there. This PR needs it: it moves MiniCPM's device fix-up out of
load_weights, which was the only finalization that path got. Whichever lands first, the other drops the hunk.Not a duplicate. I searched for
finalize_mega_moe_weights,process_weights_after_loading load_weights,tensorizer process_weights_after_loadingandpost-load finalization loader. Related open PRs: #55318 (above), #58889 (runtime state for the vLLM-tensorized branch) and #42823 (makesload_weightsre-entrant via layerwise reload; complementary).AI assistance. Written with Claude Code. Audited adversarially by Claude Fable 5.1, Codex (gpt-6-astra) and Kimi K3 over three rounds. Round 1 found two problems:
The submitter reviewed every changed line and ran the tests and A/B above.
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