Fix convolution flattening in megabatches and NorMuon normalization - #121
Zherui Yang (Adversarr) wants to merge 7 commits into
Conversation
Preserve the leading layer axis in stacked and distributed Newton-Schulz inputs, and leave stacks of 2D parameters as independent matrices. Add standalone regression coverage for Conv1d/2d/3d, Linear, LR geometry, row splitting, replicated communication, and sharded packing with two and four CPU ranks. Validation: 216 passed, 137 CUDA-dependent tests skipped. Historical helper negative control: 15 stacked failures and 5 single-parameter passes.
|
@microsoft-github-policy-service agree |
ReviewVerdict: the bug is real, the diagnosis is right, and the 4-line fix is correct at all four call sites. I'd merge after a CHANGELOG entry, one flaky assertion tightened, and one optimizer-level test added. Correctness — confirmedPre-fix, Independent confirmation that the new geometry is the intended one: All four call sites check out: The The zero-pad interaction under sharding is sound: padding along a non- Design
A more elegant alternative, which I would reject: the flag only exists because the Tests — thorough, three issues
Minor: monkeypatching module-level ThroughputThe fix raises orthogonalization FLOPs by design: old was one Gram of an Backward compatibilityThis silently changes numerics for anyone running Adjacent bug this PR does not fixNorMuon and NorDion2 with conv + That is out of scope here, but it interacts directly with this PR's stated goal. Either handle Security: nothing of concern — no I/O, no deserialization, no new dependencies. — posted as John's reviewbot |
Follow-on: the NorMuon half of the same bugI put together the NorMuon fix for the adjacent bug I flagged above, branched directly on your head commit Branch: https://github.com/JohnLangford/dion/tree/feat/normuon-conv-flatten Why it belongs here rather than in a separate PRThe two halves only work together, in both directions. Your patch alone leaves My patch alone is equally incomplete: without your fix, NS still flattens a stacked megabatch to One of the new tests ( What it does
The oracle throughout is exact equivalence: a Two things to knowIt is a checkpoint break for 3D+ parameters under One test is unexecuted. — posted as John's reviewbot |
Adapt the flattened variance geometry proposed in JohnLangford/dion commit 61e3404. Add explicit checkpoint layout validation and safe rejection before any low-rank update. Co-authored-by: JohnLangford <jl@hunch.net>
|
Thanks John (@JohnLangford) — I incorporated the review feedback and adapted your
For the sharded test, I used an equivalent equally sharded 2D matrix as the Validation: actual FSDP2 with both 2 and 4 A100 GPUs, sharded state reload, The description and CHANGELOG now explain the LR/NS geometry agreement, |
|
The core fix looks right to me, and the validation is unusually thorough — I verified the NS geometry rewrite at all four call sites, the singleton and A. The Dion2/NorDion2 rejection is broader than its stated cause, and fires too late. (blocking) The justification is that submatrix selection isn't flatten-aware. That's true of the local selection scope, which does pre-comm top-k on the raw tensor. But in the global scope, Two smaller points on the same guard:
B. Per-step revalidation in The new loop calls C.
D. Rather than teaching NS whether a stack axis is present, reshape each local Two things push back, and they're why I think the flag is defensible as written: the If the flag stays, please pass Minor: |
Problem and fix
With
flatten=True, stacked convolution weights[N, out, ...]were reshapedto
[N, numel], so Newton–Schulz orthogonalized across layers. Preserve themegabatch axis and orthogonalize
[N, out, prod(rest)]instead. This also fixesstacked Linear parameters with
flatten=True.The existing LR adjustment already uses the individual parameter's shape:
fan_out=out,fan_in=prod(rest). The corrected NS geometry now agrees withthat scaling; the LR formulas themselves are unchanged. The single-parameter
NS dispatch,
flatten=False, and row-split geometry are preserved.Following John (@JohnLangford)'s review and proposed patch, this PR also:
flatten=Falsedimensionality handling.The variance buffer holds one value per output channel. Local, replicated,
and output-channel-sharded convolution parameters are supported; convolution
column shards are explicitly rejected. Empty row shards are handled.
flatten=Truefor 3D+ parameters in Dion2 and NorDion2/Dion3 beforeany parameter update: their submatrix selection/error feedback is not yet
flatten-aware. AdamW/Lion fallback groups are exempt.
flatten=Falsehasdifferent batch-of-spatial-matrices semantics, not equivalent conv flattening.
Compatibility
NorMuon retains its existing shard-local norm-preserving rescale. The sharded
oracle is an equivalent 2D parameter under the same sharding, not an
unsharded optimizer; this PR does not make normalization world-size invariant.
Old NorMuon flattened-convolution optimizer checkpoints are explicitly rejected
before replacing live state. A layout-version marker detects legacy states even
when singleton dimensions make the old and new variance shapes coincide. Load
model weights and construct a fresh optimizer to restart; no automatic migration
or silent variance reset is performed. Unaffected state layouts are preserved.
Correct convolution NS can cost more than the old layer-mixing operation; old
step times are not equivalent-work throughput baselines. CHANGELOG entries and
optimizer docstrings describe these behavior changes.
Validation
Validated with PyTorch 2.11.0+cu128:
Failure IDs match the original PR revision exactly; all 241 previous passes
remain passing, with 131 new tests passing.
failures. Failure IDs match a full original-revision GPU run exactly; all
520 previous passes remain passing, with 136 new tests passing and 18 formerly
skipped distributed tests executing successfully.
Muon and NorMuon execute actual FSDP2 with 2 and 4 workers.
module passes 207/207 tests, no skips, on both RTX 3090 and A100.
before that test-only adjustment. Eight failures were the BF16 comparison
assumption fixed above. Combining the full run with the complete modified
module rerun gives 685 passed, 18 baseline failures, no skips (an aggregate,
not a second full-suite invocation). All 138 added tests pass, and no
verified baseline passing test is lost.
The 16 GPU baseline failures are existing wrapper-subclass compiler failures
and optional Gram/CuTe schema failures, reproduced on the original PR revision
e9b9042. A100 also reproduces two unchanged Triton-vs-cuBLAS accuracy assertionson that original revision. These kernels/tests are outside this patch and were
not disabled or loosened. CPU-only runs additionally encounter CUDA-only Triton
execution failures. Full-suite counts above precede the final test-only oracle
adjustment; that modified module was rerun completely afterward on both GPUs.
Coverage includes optimizer-level Muon grouping, Conv1d/2d/3d versus equivalent
matrices, multiple steps and LR-adjustment modes, state/checkpoint compatibility,
actual FSDP2 forward/backward with BF16 computation and FP32 master parameters,
uneven/empty row shards,
production Polar Express, and CUDA-graph replay. FP64 tests compare against
independent unbatched matrices with tight tolerances. BF16 GPU layer-isolation
tests preserve the BMM shape: direct PE GEMM/BMM calls differ by up to 0.0703125
on A100 even without the optimizer/flatten helper. Identical batched dispatch
remains exact; no production numerical tolerance or kernel was changed.
Negative controls reproduce both defects: the pre-fix Muon step presents
[2, 288]instead of[2, 8, 36]to NS, and the NS-only fix still fails theNorMuon convolution/matrix update oracle.
The normalization work is adapted from JohnLangford's proposed
61e3404,with attribution in the commit. The distributed tests use all-rank collectives
and same-sharding references instead of the proposed unsharded comparison.
Existing training ablations — Muon only
These plots compare pre-fix Muon, AdamW, and fixed Muon. They are training-loss
examples, not NorMuon/Dion2/Dion3 convergence results or evidence of a universal
optimizer ranking. No full training campaign was rerun for the review follow-up.
Speech Commands v0.02: 35-keyword audio classification with Conv1d.
Food-101: 101-class food classification with the ConvNeXt-T UNet classifier.
ModelNet40: 40-class classification of voxelized point clouds with sparse Conv3d.