Fix NaN for full-parameter SFT with DeepSpeed ZeRO-1/2 on torch<2.9 (AdamW int32 flat-partition overflow) - #10023
Merged
Merged
Conversation
Contributor
Author
|
Hi @tastelikefeet , when you have a chance, could you please take a look at this PR? Thanks! |
Collaborator
|
Thanks for your code contribution! I will read the PR asap, thanks again! |
Collaborator
|
Hi, how about make a patch of: |
Contributor
Author
Thanks for the suggestion — agreed, this is much simpler and avoids changing the optimizer’s group layout or checkpoint format. Done. Re-verified end-to-end on 4× A100s: the loss stays finite with the fix, but goes NaN from step 2 without it. |
tastelikefeet
approved these changes
Sep 3, 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.
Problem
On torch<2.9,
torch._foreach_*kernels index tensors with signed int32 elements and write out of bounds when a flat tensor exceedsINT32_MAX(2,147,483,647) elements. DeepSpeed ZeRO-1/2 flattens each optimizer param group into one FP32 flat partition per DP rank, so full-parameter training of large models crosses this boundary and the AdamW step corrupts memory — loss turns NaN right after the first optimizer step.Reproduced with Qwen3.5-9B full SFT (
--optim adamw_torch --deepspeed zero1, bf16, 4×A100):torch._foreach_add_probe on a 2,238,382,272-element tensor writes 65,344 elements past the end (guard corrupted, 3/3 repeats);AdamW(foreach=False)and a chunked reference are clean;Fix
In
SwiftMixin.create_optimizer, after the HF Trainer creates the optimizer and before DeepSpeed receives it: ontorch<2.9+ ZeRO stage 1/2 +torch.optim.AdamW, setforeach=Falseon the optimizer defaults and every param group so the update takes the single-tensor path. ZeRO-3 (per-parameter partitioning, no oversized flat), torch≥2.9, and non-AdamW optimizers are untouched.The fallback costs ~2% on a 2 GiB flat (ZeRO feeds the base optimizer a few large flat tensors, where foreach has little advantage), and it does not change the optimizer's group layout or checkpoint format.
Verification