perf(checkpoint): avoid full CPU loads for single-GPU MoE - #3610
Draft
yuhezhang-ai wants to merge 10 commits into
Draft
perf(checkpoint): avoid full CPU loads for single-GPU MoE#3610yuhezhang-ai wants to merge 10 commits into
yuhezhang-ai wants to merge 10 commits into
Conversation
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.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.
Summary
This replaces #3601, which GitHub automatically closed when its head branch was renamed. The old draft had no human reviews or discussion to migrate.
This PR lets two real single-GPU MoE configurations use AutoModel's existing DCP checkpoint loader instead of first building the complete checkpoint on CPU:
Ling still needs a small exception for its fused attention weights:
There is no new streaming executor, load-group API, or per-adapter iteration protocol. The implementation reuses one standard DCP load and the adapters' existing
to_hf/from_hfconversion.Adapters opt into this route with one capability:
supports_low_memory_dcp_load. It means that most checkpoint tensors load directly into the model's existing weight memory, while any remaining temporary tensors are small enough to be safe on one GPU. Adapters that need another model-sized set of tensors keep the CPU fallback.This is stacked on #3580. That PR makes the existing MoE conversion path faster and more memory-efficient. This PR changes which single-GPU configurations can skip the full-CPU-checkpoint fallback entirely.
Why Nemotron can load directly
Nemotron Nano V3's one-GPU recipe is configured with TE experts and a DeepEP dispatcher. However, the MoE layer cannot use expert parallelism with one process, so it deliberately constructs ordinary
GroupedExpertsinstead.The adapter previously looked only at the configured backend. It therefore assumed the expert tensors were TE temporary stacks and selected the full CPU fallback, even though the actual one-GPU model has ordinary grouped parameters that DCP can fill directly.
This PR makes the shared MoE adapter check match the MoE constructor:
Nemotron's expert checkpoint tensors are non-contiguous transposed views of the grouped model weights. DCP writes through those views into the model's existing memory.
Why Ling no longer needs load groups
Ling's expert and ordinary weights already have safe DCP destinations. Only its checkpoint QKV layout differs: the checkpoint stores one fused tensor while the model owns three Q, K, and V parameters.
The normal adapter path already handles this correctly:
The adapter now declares that this small temporary state is safe, so the loader does not materialize the complete 30.28 GiB checkpoint on CPU.
The discarded prototype loaded one dependency group at a time and reduced Ling peak host RSS further, from 11.27 GiB to 2.75 GiB. It required more than 1,000 lines of generic executor, validation, and adapter-specific planning code. The standard DCP implementation is slightly faster in the matched measurements below, keeps host memory 80.6% below the parent, and removes that framework/API complexity.
Small shared cleanup
AutoModel asks adapters for their Hugging Face checkpoint key names before sharding. The base implementation previously performed this keys-only operation with real model tensors, so an allocating adapter could accidentally convert real weights just to discover names.
The base adapter now performs key discovery with shape-only meta tensors. This also replaces Gemma4's model-specific version of the same workaround.
Performance
Nemotron Nano V3, one GPU
The 58.82 GiB checkpoint files were not already in the compute node's RAM cache (
mincore: 0.0 GiB resident before construction). The run used an H100. The timed loader phase includes DCP planning, storage access, destination writes, and synchronization; it is not a pure filesystem-read timer.162252811933190d5)16275130Compared with the parent, this is:
The run loaded all parameters, left no meta parameters, and reproduced the established pretrained embedding, expert gate/up, expert down, and shared-expert fingerprints.
Ling-mini-2.0, one GPU
Job
16275108used the same 30.28 GiB Hugging Face checkpoint files, H100, staged image, and alternating fresh Python processes. The initial treatment process placed the files in the compute node's RAM cache and is excluded from the means.d6f363166)1933190d5)Compared with the parent, this is:
Every sample produced identical Q/K/V, expert, and routing-bias probes, the same forward checksum (
176.02343750) and top token (670), finite logits, and no meta parameters.Scope
The measurable route change is for single-device, non-quantized custom-model safetensors initialization.
.bincheckpoints, and adapters with full-size transformations keep their existing fallback and remain follow-up work under Roadmap: checkpoint I/O architecture, correctness, performance, and memory聽#3576.Validation
git diff --checkpass.16275130: exact rebased SHA, 0.0 GiB initial page residency, expected fingerprints, no meta parameters, and 9.3 MiB GPU peak overhead.16275108: exact rebased SHA, identical parameter/forward probes across parent and treatment, finite logits, and no meta parameters.1933190d5): pipeline63890795passed bothnemotron_nano_v3_singlegpu_loraand the distributednemotron_nano_v3_hellaswagcheckpoint-robustness job. The restored AutoModel logits matched exactly (max KL0.0), and the consolidated checkpoint loaded by vanilla HF remained within tolerance (max KL0.01525, threshold0.07). The subsequent change only consolidates and renames the capability flag.