Warn when DeepSpeed ZeRO silently changes custom optimizer semantics
Maintainers usually reply within 1 day
Nobody has claimed this yet.
- #4414 by @Eryx-Z — closed without merging
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Domain
- backend, machine-learning
Research direction
Start by tracing the DeepSpeed integration path that sets zero_allow_untested_optimizer, then inspect existing optimizer integration tests. Reproduce the reported ZeRO-1 behavior with the linked deterministic example and compare it with DDP. Done means the risk is made explicit through an opt-in or warning, with tests covering the behavior; the issue also proposes documentation and a ZeroRedundancyOptimizer recipe.
Written by the indexing model from the issue text.
Description
System Info
- Accelerate version: 1.15.0
- Platform: Linux 5.4.0 x86_64, glibc 2.31
- Python version: 3.12.13
- NumPy version: 2.5.3
- PyTorch version: 2.14.1+cu132
- PyTorch accelerator: CUDA
- DeepSpeed version: 0.19.7
- ProdigyPlusScheduleFree version: 2.0.1
- GPU: 2 x NVIDIA RTX A6000
- Accelerate default config: not used; all settings explicit
Information
- The official example scripts
- My own modified scripts
Tasks
- One of the scripts in the examples/ folder
- A deterministic optimizer-semantics test using a custom optimizer with DeepSpeed ZeRO-1
Reproduction
This is a follow-up to #4159, whose wrapper traversal is fixed in 1.15.0 and passed our test.
The remaining problem is independent: Accelerate accepts an arbitrary torch.optim.Optimizer
with DeepSpeed, automatically enables zero_allow_untested_optimizer, and the job can exit 0 even
when ZeRO partitioning changes the optimizer's mathematics.
With ProdigyPlusScheduleFree, DeepSpeed replaces the optimizer group with a local flattened FP32
master partition. Prodigy's group-level d estimate becomes rank-local, and original tensor
boundaries used by factorization, estimator slicing, and RMS scaling disappear.
Standalone two-rank reproduction: https://gist.github.com/XIONGPEILIN/c2d12d59fecd7ef7e347667e551e9fdd
Observed after 64 deterministic updates:
| execution | final rank d |
max model abs diff vs DDP |
|---|---|---|
| replicated DDP | 0.016384, 0.016384 |
reference |
| DeepSpeed ZeRO-1 | 0.00172216, 0.000215269 |
0.175511 |
| ZeRO-1 + globally summed d statistics | 0.00180069, 0.00180069 |
0.161856 |
All runs completed without an exception. The 1.15.0 optimizer.eval() / optimizer.train()
forwarding fix worked on both ranks.
We also tested a solution that keeps the stock optimizer recipe but uses tensor-wise PyTorch
ZeroRedundancyOptimizer: max model difference from DDP was 7.152557e-07 at a predeclared
1e-6 tolerance, with identical d on both ranks.
Expected behavior
I do not expect Accelerate to prove that every custom optimizer is partition-safe. I do expect the
integration to make this risk explicit rather than silently opting arbitrary optimizers into
zero_allow_untested_optimizer.
Possible improvements:
- require an explicit opt-in for untested custom optimizers under ZeRO, or emit a prominent
Accelerate warning explaining that ZeRO may replace original tensors with local flat masters; - document that optimizers using group-global statistics or tensor shapes/boundaries need a
partition-aware implementation; - add a documented Accelerate recipe for PyTorch
ZeroRedundancyOptimizerthat avoids optimizer
device-placementstate_dict()calls and supports Schedule-Freetrain()/eval()forwarding.
This would complement, rather than change, the fix already released for #4159.
- Dominant language
- Python
- Stars
- 9.9k
- Forks
- 1.6k
- Avg merge
- 20h 23m
- Merged PRs (30d)
- 12
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from huggingface/accelerate
-
FSDP2: prepare() keeps the whole unsharded model alive during sharding when cpu_ram_efficient_loading=FalsePossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
huggingface/accelerate#4511 ·
Maintainers usually reply within 1 day
-
BatchSamplerShard padding mutates retained sampler batches and changes original loader samplesPossibly taken @davrens101 claimed this 4 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
huggingface/accelerate#4505 ·
Maintainers usually reply within 1 day
-
accelerator.reduce(tensor, "mean") fails on integer tensors when more than one process is usedPossibly taken @MaiAditya claimed this 13 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
huggingface/accelerate#4469 ·
Maintainers usually reply within 1 day
-
merge_fsdp_weights with remove_checkpoint_dir=True deletes the merged model when output_path is inside checkpoint_dirPossibly taken @assass1nlike claimed this 2 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 25/100
huggingface/accelerate#4514 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 42/100
huggingface/accelerate#4510 ·
Maintainers usually reply within 1 day
All issues in huggingface/accelerate
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 75/100
SACGF/variantgrid#2791 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Maintainers usually reply within 1 day
-
bot-triaged oncall: cpu inductor
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
kubescape/cel-admission-library#141 · 1 comment ·
Maintainers usually reply within 1 day