Repository navigation
Conversation
…at cold start A BF16 checkpoint quantized at load is the one case the kernel storage cannot hold the checkpoint tensor, so direct reload cannot view it back. Those modules (quant_method.uses_meta_device) reload the way they cold start: begin stages them on the meta device through the layerwise loaders, finish quantizes each complete module and copies the result into its kernel tensors (addresses kept), and restores the kernel tensors of a module the update left out. Their one-shot post-load guard stays, so the rerun for the other modules does not quantize the kernel bytes again. The per-layer staging is the loop body of initialize_layerwise_reload, factored into stage_layer_for_reload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: aoshen <aoshen524@gmail.com>
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.
Problem
VLLM_RELOAD_MODE=direct(vllm-project#58382) writes checkpoint tensors into the live tensors, viewed back to their checkpoint layout. Online quantization (a BF16 checkpoint quantized at load,quant_method.uses_meta_device) is the one case that cannot work: the FP8 kernel storage cannot hold the BF16 checkpoint tensor, so there is nothing to view back to.Fix
Those modules reload the way they cold start. At cold start they are created on the meta device and the layerwise loaders stage their checkpoint tensors until the module is complete, then quantize. Direct reload reuses exactly that:
beginstages every online-quantized module (stage_layer_for_reload: keep the kernel tensors aside, restore the module on meta, wrap its loaders).finishrunsfinalize_layerwise_processingfirst: a complete module is quantized and the result copied into its kernel tensors (addresses kept for CUDA graphs); a module the update left out gets its kernel tensors back. Their one-shot post-load guard stays, so the post-load rerun for the other modules does not quantize the kernel bytes again.stage_layer_for_reloadis the loop body ofinitialize_layerwise_reload, factored out; layerwise mode is unchanged.Tests
tests/model_executor/model_loader/test_direct_reload.py: the toy model gets an online-quantized layer (meta BF16 checkpoint tensor, int8 kernel tensor + scale built at load). A reload equals a cold start on the new weights, at the startup addresses; an unsent module keeps its bytes. 13 passed (GB300, slurm 25132).E2E on GB300 (verda), Qwen3.5-35B-A3B (BF16 MoE + GDN), TP2, online quantization at load, 2 same-weight updates per run, stacked on vllm-project#57733 + vllm-project#62407 + vllm-project#58382 + #179 + #180. Direct and layerwise run side by side; the oracle is a batch-1 fixed-token generation compared before/after.
--quantization)mxfp8(linear + MoE)mxfp8mxfp4(linear + MoE)mxfp4nvfp4_per_token(MoE)nvfp4_per_tokenfp8_per_channel(CUTLASS MoE)--quantization-config '{"ignore":["*visual*"]}'): its 4304-wide projections split to 2152 per TP2 rank, which MX formats refuse at startup.mxfp4runs on nightly00b6c4c5with the Python half of [Perf][MXFP4] Optimize activation quant for mxfp4. 3x kernel speedup, 5% throughput improvement vllm-project/vllm#63101 reverted in the overlay, because the image'sget_cutlass_moe_mm_datapredates its new argument.fp8_per_channelneeds [Model Loader] Write weight-derived tensors back in place on reload #180's CUTLASS stride constants: without them a reload leaves the CUDA graphs on freed strides (illegal memory access, GSM8K 0.618 → 0.0).fp8_per_tensor, direct, 0.892 → 0.892 (0 flips of 1319), oracle equal (25144).Known limitation
Online
fp8_per_tensoron Qwen3.5-35B-A3B: GSM8K holds and no tensor changes, but the batch-1 fixed-token oracle differs after a reload. Plain nightly layerwise does the same, and it persists with no post-load rerun at all, so it is not specific to this PR; the per-tensor dynamic activation scale of the MoE is the suspect. Not investigated further here.Dependencies
Stacked on vllm-project#58382 (
wu/stack/direct-g).fp8_per_channel(CUTLASS MoE) also needs #180. Follow-up F8 of vllm-project#54477.🤖 Generated with Claude Code