[RFC] Skip collectives on absent or single-rank groups with deepspeed.comm.pg_utils.is_parallel
I maintainer di solito rispondono entro 2 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 35/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Ambito
- backend, distributed-systems
Direzione di ricerca
Start with deepspeed/comm/comm.py and its existing collective helpers, then read the tests for deepspeed.comm and the guarded call sites in deepspeed/sequence/cross_entropy.py. Implement and test the proposed synchronous helper so absent and single-rank groups skip the reduction while multi-rank groups preserve existing behavior. Done means the helper is exported through deepspeed.comm and the cross-entropy callers use it; the naming and scope still need maintainer feedback.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Update (2026-10-16): the proposal changed during review of #8815. Instead of an exported
all_reduce_if_parallelwrapper, DeepSpeed gets a single predicate,deepspeed.comm.pg_utils.is_parallel(group), which guards every collective. The sections below reflect the current design; see the status table for progress.
Motivation
Following @delock's suggestion in #8791: many modules guard collectives with the same hand-written check, so that code written for an optional parallel group also runs without it:
if tp_group is not None and dist.get_world_size(tp_group) > 1:
dist.all_reduce(tensor, op=..., group=tp_group)
This pattern (or a close variant) appeared in sequence parallel / vocab-parallel ops, MoE, inference v1 kernels, ZeRO model-parallel reductions, AutoTP layers and runtime norm helpers. #8791 added yet another local copy (_tp_active / _all_reduce in deepspeed/sequence/vocab_parallel_ops.py).
The copies differ in subtle ways (some only check group is None, some only check the size), and they all rely on a convention that conflicts with deepspeed.comm: in these helpers group=None means "this parallel dimension is absent", while dist.all_reduce(group=None) reduces over the world group. Dropping the guard therefore silently turns "no reduction" into a world reduction, which is wrong whenever DP > 1.
Proposal (current)
Add deepspeed/comm/pg_utils.py with one predicate:
def is_parallel(group):
"""Return whether ``group`` spans more than one rank. ``None`` marks an absent parallel dimension."""
return group is not None and dist.get_world_size(group) > 1
Call sites keep their own collective:
from deepspeed.comm import pg_utils
if pg_utils.is_parallel(group):
dist.all_reduce(tensor, group=group)
Design points:
- One predicate for every primitive. Sync and async all-reduce, all-gather, inference all-reduce, etc. all use the same guard, so there is no per-collective wrapper and no question of what a skipped
async_op=Truecall should return. Nonemeans "no parallelism", documented and tested. It never touches the process group, so it works beforetorch.distributedis initialized.- Not star-exported from
deepspeed.comm. Callers writepg_utils.is_parallel, so the two meanings ofNone(absent dimension vs. world group) stay visibly apart. - Non-members skip. For a group that excludes the current rank,
get_world_sizereturns-1, and> 1skips it. - Hot paths can cache it. AutoTP layers compute
is_tp_parallel = is_parallel(mp_group)once at construction, soforward/backwardpay no extra cost. - The backend collectives (
cdb.*,timed_op, comms logger) are unchanged.
Why not skip inside dist.all_reduce itself? That would change behavior for every caller (group=None = world, async handles, comms logging), so an opt-in predicate is safer.
Status
| Step | Scope | Status |
|---|---|---|
| PR-1 | pg_utils.is_parallel + tests; migrate sequence (vocab_parallel_ops.py, cross_entropy.py, linear_cross_entropy.py), MoE, inference v1, ZeRO MP reductions, AutoTP layers, runtime norm helpers |
#8815 (originally planned as PR-1 + PR-2) |
| Out of scope | Guards on a separately supplied size (len(partition_sizes), a tp_world_size argument), mpu-based world sizes, sites where None means the world group (kv_cache warm-up, moe_inference._alltoall), AutoEP folding correction |
kept as is, listed in #8815 |
| Performance (separate, optional) | At DP=1 the engine / ZeRO-1/2 gradient paths still flatten, all-reduce over a single rank and copy back, and ZeRO-2 overlap keeps an IPG double buffer. Caller-level short-circuit, not this predicate: skip the stage-0 reduction and disable the IPG double buffer when DP=1. Measured on 1× Arc Pro B70: stage 0 saves ~13 ms/step (4.3% at 8K tokens, 12.8% at 1K), ZeRO-1/2 average_tensor skip ~4 ms/step (1–3%), double buffer costs +0.94 GiB; losses bit-identical |
planned, small PR |
Related fix found during the migration (independent of this RFC): #8837 — dist.all_reduce(x.contiguous()) in RowParallel / ColumnParallel / AsyncColumnParallel discarded the reduced result for non-contiguous tensors.
Questions
- Naming: resolved as
pg_utils.is_parallel(group)in #8815 review. Objections welcome. - Feedback on the out-of-scope list is welcome.
- Lingua principale
- Python
- Stelle
- 43.3k
- Fork
- 5.1k
- Merge medio
- 4g 7h
- PR unite (30g)
- 66
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di deepspeedai/DeepSpeed
-
[BUG] OneCycle applies the minimum momentum to the first Adam updateForse già presa @ai-yang l’ha presa 1 giorno fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
deepspeedai/DeepSpeed#8951 ·
I maintainer di solito rispondono entro 2 giorni
-
[BUG] Universal checkpoint resume puts CPU `step` into fused/capturable optimizer stateForse già presa @ArjunPakhan l’ha presa 9 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
deepspeedai/DeepSpeed#8884 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
init_inference rejects dtype=torch.int8 on every acceleratorForse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
deepspeedai/DeepSpeed#8577 ·
I maintainer di solito rispondono entro 2 giorni
-
[BUG] AutoTP checkpoint load raises AttributeError on a model containing nn.InstanceNorm1dForse già presa @vineethsaivs l’ha presa 47 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
deepspeedai/DeepSpeed#8514 ·
I maintainer di solito rispondono entro 2 giorni
-
[BUG] Python checkpoint writers fail to reload full ZeRO-3 state with default torch.loadForse già presa @ai-yang l’ha presa 48 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
deepspeedai/DeepSpeed#8500 ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di deepspeedai/DeepSpeed
Issue simili
-
ReadQwen3PaperTask5 rejects correct answers that differ only in order, case, or underscore formForse già presa @Kingpython123 l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 90/100
Tongyi-MAI/MobileWorld#72 ·
-
_threads/application: Update typing annotations using `pyupgrade --py311-plus`Forse già presa @gudnimg l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Health probes return 401 when authentication is enabled and the API is served under /orbForse già presa @fgogolli l’ha presa oggi. Apertaarea: api priority: p2 size: S type: bug
Difficoltà 2/5 Mezza giornata Idoneità per principianti 75/100
finos/open-resource-broker#704 ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
BCDA-APS/polar-bits#93 ·
-
bug
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
GoogleCloudPlatform/gce-rescue#218 ·
I maintainer di solito rispondono entro 2 giorni