Run Muon once per optimizer step under ZeRO-3, not once per micro-batch - #8600
Open
alanhuangyoo wants to merge 1 commit into
Open
alanhuangyoo wants to merge 1 commit into
alanhuangyoo wants to merge 1 commit into
Conversation
ZeRO-3 applied Muon inside the gradient reduce, which runs every micro-batch. With gradient_accumulation_steps n, the momentum advanced n times per step and Newton-Schulz orthogonalized partial gradients, so training with accumulation diverged from the same batch taken in one micro-batch. ZeRO-1/2 were correct. Without optimizer offload, the reduce path now leaves Muon out and the partitions accumulate the raw gradient. At the step, after the overflow check and before the norm, each Muon sub-group's accumulated gradients are gathered in bounded chunks, orthogonalized once through the same round-robin update, and written back to the partitions. The per-subgroup update is factored out of _apply_distributed_muon_update so both paths share it. The offload path is unchanged. Fixes deepspeedai#8443 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: alanhuangyoo <alanhuangyoo@gmail.com>
alanhuangyoo
requested review from
loadams,
tjruwase and
tohtana
as code owners
September 19, 2026 09:49
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.
Fixes #8443.
The problem
ZeRO-3 applies Muon inside the gradient reduce (
_apply_distributed_muon_update, called from__avg_scatter_contiguous_grads), and that runs every micro-batch. Withgradient_accumulation_steps: n, the momentum advancesntimes per optimizer step, and Newton-Schulz orthogonalizes each micro-batch's partial gradient instead of the accumulated one. ZeRO-1/2 apply Muon at the accumulation boundary and are correct.On 2 GPUs, fp32, with the same 8 samples per step either way (one micro-batch of 8 at
gas=1, four of 2 atgas=4), three steps, relative difference in the weights:gas=1vsgas=4gas=1vsgas=4gas=4ZeRO-3 now lands on exactly ZeRO-2's figure.
The change
This is option 1 from the discussion in #8443. It is scoped to ZeRO-3 without optimizer offload.
step()calls_apply_muon_to_accumulated_grads()after the overflow check and before the gradient norm. For each Muon sub-group, it:reduce_bucket_sizeas the reduce buckets were;_apply_distributed_muon_updateis moved into_muon_update_sub_group. It takes the full-shape gradients explicitly, because at step time the parameters are partitioned andparam.gradcan't hold them. The reduce path calls it withparam.gradas before.gas=nthat isntimes fewer.The optimizer-offload path is unchanged; #8464 is working on it. jinyouzhi added a pointer to this shape in #8464, and the overlap is limited to
_apply_distributed_muon_update.Testing
On 2×H20:
tests/unit/v1/ops/muon/test_muon_zero3_grad_accum.py. Both tests fail on master and pass here.test_newton_schulz_runs_once_per_matrix_per_step: Newton-Schulz calls summed over ranks come to 2 × steps, not 2 × steps × gas.test_gradient_accumulation_matches_one_large_micro_batch[2, 3]:gas=1andgas=4agree to within half-precision Newton-Schulz noise at both stages.tests/unit/v1/ops/muon/plustests/unit/runtime/zero/test_per_head_muon.py: 260 passed.