perf(checkpoint): reduce allocating grouped MoE load overhead - #3580
Open
yuhezhang-ai wants to merge 11 commits into
Open
perf(checkpoint): reduce allocating grouped MoE load overhead#3580yuhezhang-ai wants to merge 11 commits into
yuhezhang-ai wants to merge 11 commits into
Conversation
10 tasks
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
yuhezhang-ai
force-pushed
the
yuhez/perf/moe-checkpoint-direct-fill
branch
from
August 20, 2026 04:14
f723de1 to
da03590
Compare
Contributor
Author
|
/ok to test da03590 |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test 74f3539 |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
yuhezhang-ai
force-pushed
the
yuhez/perf/moe-checkpoint-direct-fill
branch
from
August 21, 2026 04:15
795ff44 to
879e064
Compare
Contributor
Author
|
/ok to test 8949e6b |
Contributor
|
/ok to test 2320d5a |
Signed-off-by: Yuhe Zhang <yuhez@nvidia.com>
Contributor
Author
|
/ok to test d6f3631 |
This was referenced Aug 21, 2026
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.
What this PR changes
This PR improves three grouped-MoE checkpoint paths left after #3574:
torch.cuda.empty_cache()while those views remain in use.The loader also reports destination preparation, storage read, adapter conversion, and model installation separately.
This PR optimizes the existing load pipeline. General sequential checkpoint streaming remains follow-up work in #3576.
Why the model paths differ
Qwen TE and Gemma4 both transform expert weights, but their checkpoint layouts are different:
For Gemma4 EP8, the old path expanded every rank's 16 experts into full 128-expert CPU tensors, read the full grouped checkpoint, and then sliced back to 16 experts. The new path gives DCP transposed, expert-sharded views of the model weights, so each rank reads only its own 16-expert slice. The small scale vector is applied in place after the read.
Performance
Gemma4 26B EP8
Both runs use the same 8×H100
gemma4_26b_a4b_moe_peftrelease recipe.A matched local 8-H100 A/B measured 190.44 s before versus 24.46 s on the first optimized read and 13.87 s warm. Per-rank peak process RSS fell from 86.85 GiB to 7.41 GiB. Rank-by-rank expert probes matched, every rank owned 16 experts, and no meta parameters remained.
For single-device Gemma4, matched warm runs reduced peak process RSS from 64.30 GiB to 47.62 GiB (16.68 GiB / 25.9%). Model-load time itself was approximately neutral; EP is the large speed improvement.
Qwen3 30B TE: corrected speed and memory explanation
The earlier explanation was incomplete. TE creates its virtual grouped tensor with
torch.stack(...).transpose(...). After the adapter slices and transposes an expert back to HF layout, that tensor is already contiguous. Therefore the old.contiguous()call reused the TE stack; it did not allocate a copy.The large destination-setup speedup comes from avoiding repeated full
gc.collect()calls. Full GC took roughly 19–23 seconds across the 46 expert projections. Generation-0 collection or no collection takes less than one second.torch.cuda.empty_cache()was not responsible for the old path's lower peak.The initially proposed blank destinations were fast but always allocated a second set of expert tensors. The final implementation instead reuses TE's already-contiguous checkpoint views:
catthenstackfrom_hfgeneration-0 GCThe first three rows are the matched EP8 job
16206220. The final row is job16219024, using the same cached Qwen3-30B checkpoint, EP8 topology, staged image, and load-only harness. Storage timing varies with filesystem state, so CUDA peak is the controlled comparison. In the final run, the loader's own phase timer reported 18.26 s total: 0.40 s destination setup, 17.42 s storage read, 0.31 s adapter conversion, and 0.13 s installation.All four states completed with zero meta parameters and matching rank-local expert fingerprints. The current path reduces the rejected implementation's peak by 6.610 GiB/rank (32.1%) and returns exactly to the direct-fill peak.
Nemotron Nano V3 single-device fallback
Matched one-GPU runs used the same 58.82 GB checkpoint, recipe, image, and one-step workload.
The time reduction comes from replacing 46 full Python-heap scans—two expert projections across 23 MoE layers—with generation-0 collection. Direct fill separately removes one final-size reconstruction scratch buffer. The run completed successfully with the same finite first-step metrics as the parent. This older job did not record a clean load-only CUDA peak; that measurement is tracked with the sequential-loading follow-up.
Correctness boundaries
load_model()is not called and model initialization remains unchanged.Validation
16219024.16219024, peak 13.999 GiB/rank, zero meta parameters, matching expert fingerprints.git diff --checkpass.Builds on #3574. Part of #3576.