Repository navigation
feat(optim): support Muon with full CPU optimizer offload - #4124
Closed
faresobeid wants to merge 1 commit into
Closed
faresobeid wants to merge 1 commit into
faresobeid wants to merge 1 commit into
Conversation
faresobeid
marked this pull request as ready for review
October 16, 2026 17:15
This was referenced Oct 16, 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.
Summary
model.offload = "full"now supports Muon, so Muon no longer needs more trainer nodes than AdamW or SignSGD. GLM-4.5-Air Muon now trains on one trainer node.How it works:
momentum;momentum+variancefor Dion's AdamW group; the step count lives on the group), so checkpoints keep Dion's state keys.M = mu * M + scale * G. Dion's AdamW group (embeddings, lm_head, norms) runs on the existing native CPU AdamW kernel.step()walks Dion's batches of same-shaped matrices with two batches in flight. For each batch:muon_update_batch_asyncruns on GPU. This is the same Newton-Schulz path as offload=none, including local NS for EP-sharded experts and the all-to-all for FSDP-sharded matrices. It gets a zero gradient, unit momentum, and a zero parameter, so it returns exactly-adjusted_lr * NS(M).add_bfloat16_).qkv/gate_up) are taken from the model's parameters, because the optimizer owns CPU master shards.Results
Correctness: Qwen3-30B-A3B, 2 layers, EP8, 1 node, lr 1e-3
Each row is the relative error of the cumulative update against offload=none after steps 1 / 2 / 3.
GLM-4.5-Air: 1 node vs 2 nodes
Settings: real weights, fake data,
swe-budget.tomltrainer settings (cp 4 ulysses, AC + AC offload, compile, fused LM head 1024), 8 x 131k-token samples per step.swe.tomltrainer)swe.toml.Note
High Risk
Changes the distributed full-offload optimizer step and Muon’s GPU Newton–Schulz path; mistakes affect training correctness, checkpoints, and multi-node collectives.
Overview
model.offload = "full"now works with Muon, not just AdamW and SignSGD, so Muon training can fit on fewer trainer nodes when optimizer state and gradients live on CPU.FullCPUOffloadOptimizergains a Muon path: CPU chunks are split per param group; during backward Muon chunks only fold gradients into FP32 momentum on CPU; Dion’s AdamW subgroup still uses the existing native CPU AdamW kernel with Dion’s state keys. After backward,step()runs batched GPU Newton–Schulz via Dion’smuon_update_batch_async(BF16 momentum H2D, orthogonalized update D2H, FP32 master + compute weight refresh), with matrix partitions passed from the model for fused packed weights. Nesterov Muon is rejected under full offload.Config/runtime guards that raised on Muon + full offload are removed (
setup_optimizer, SFT/Trainer validators); docs and the start-run skill document Muon support and host RAM per parameter. The unit test expecting that validation error is deleted.Reviewed by Cursor Bugbot for commit 55be9e7. Bugbot is set up for automated code reviews on this repo. Configure here.