Navigation
🌐 Distributed GPU Systems· 14 min read

Communication Primitives

Point-to-point send/recv and the five key collectives — Broadcast, AllReduce, AllGather, ReduceScatter, All-to-All — what data moves and how much.

distributedcollective-communicationallreduceallgatherreduce-scatterall-to-all

Before understanding distributed training or inference, you need the vocabulary of multi-GPU communication. There are only 7 operations — learn these and you can analyze any parallelism strategy.


1. Point-to-Point: The Foundation

The simplest operation: one GPU sends data to another.

# GPU 0 sends tensor to GPU 1
if rank == 0:
    dist.send(tensor, dst=1)
elif rank == 1:
    dist.recv(tensor, src=0)

All collective operations are built from point-to-point sends under the hood. But you rarely use point-to-point directly — collectives are more efficient.


2. The Five Key Collectives

Collective Operations

Broadcast: One → All

One GPU’s data is copied to all GPUs:

Before:  GPU0=[A]  GPU1=[_]  GPU2=[_]  GPU3=[_]
After:   GPU0=[A]  GPU1=[A]  GPU2=[A]  GPU3=[A]

Use case: Distributing model weights from GPU 0 to all GPUs at initialization.

Data moved: NN bytes × (P−1)(P-1) copies, where NN = tensor size, PP = GPU count.

Reduce: All → One

All GPUs contribute data, reduced (summed/averaged) to one GPU:

Before:  GPU0=[1]  GPU1=[2]  GPU2=[3]  GPU3=[4]
After:   GPU0=[10] GPU1=[_]  GPU2=[_]  GPU3=[_]   (sum = 10)

Use case: Rare in practice — AllReduce is almost always preferred.

AllReduce: All → Reduce → All ⭐

The most important collective in AI. All GPUs contribute, result available on all GPUs:

Before:  GPU0=[1]  GPU1=[2]  GPU2=[3]  GPU3=[4]
After:   GPU0=[10] GPU1=[10] GPU2=[10] GPU3=[10]  (sum on every GPU)

Use case: Gradient synchronization in data parallelism. Each GPU computes gradients on its data shard, AllReduce averages gradients across all GPUs, then every GPU has the same averaged gradient for the optimizer step.

The fundamental identity:

AllReduce=ReduceScatter+AllGather\text{AllReduce} = \text{ReduceScatter} + \text{AllGather}

This decomposition is how NCCL actually implements AllReduce, and it’s the basis for ZeRO.

ReduceScatter: All → Reduce → Scatter

Reduce all data, then each GPU keeps only its shard of the result:

Before:  GPU0=[a0,a1,a2,a3]  GPU1=[b0,b1,b2,b3]  GPU2=[c0,c1,c2,c3]  GPU3=[d0,d1,d2,d3]
After:   GPU0=[a0+b0+c0+d0]  GPU1=[a1+b1+c1+d1]  GPU2=[a2+b2+c2+d2]  GPU3=[a3+b3+c3+d3]

Each GPU gets 1/P of the total reduced result.

Use case: ZeRO Stage 1-3. After backward pass, ReduceScatter gives each GPU the averaged gradient shard it needs for its optimizer partition.

AllGather: Scattered → All

The inverse of ReduceScatter — each GPU has a shard, AllGather assembles the full tensor on all GPUs:

Before:  GPU0=[s0]  GPU1=[s1]  GPU2=[s2]  GPU3=[s3]
After:   GPU0=[s0,s1,s2,s3]  GPU1=[s0,s1,s2,s3]  GPU2=[s0,s1,s2,s3]  GPU3=[s0,s1,s2,s3]

Use case: FSDP/ZeRO-3 forward pass. Parameters are sharded — before each layer, AllGather reconstructs the full parameters from all GPUs’ shards.

All-to-All: Everyone → Everyone (Different)

Each GPU sends a different piece to each other GPU:

Before:  GPU0=[a0,a1,a2,a3]  GPU1=[b0,b1,b2,b3]
After:   GPU0=[a0,b0]        GPU1=[a1,b1]
         GPU2=[a2,b2]        GPU3=[a3,b3]

GPU ii receives the ii-th piece from every GPU.

Use case: Expert parallelism (MoE). Tokens must be dispatched to the GPU holding their selected expert. Each GPU sends different tokens to different expert-GPUs.


3. Communication Volume Summary

For PP GPUs, each with NN bytes of data:

CollectivePer-GPU sendPer-GPU receiveTotal data moved
BroadcastNN (from root)NN (to each)N×(P−1)N \times (P-1)
ReduceNN (from each)NN (to root)N×(P−1)N \times (P-1)
AllReduce2N×P−1P2N \times \frac{P-1}{P}2N×P−1P2N \times \frac{P-1}{P}2N×(P−1)2N \times (P-1)
ReduceScatterN×P−1PN \times \frac{P-1}{P}N/PN/PN×(P−1)N \times (P-1)
AllGatherN/PN/PN×P−1PN \times \frac{P-1}{P}N×(P−1)N \times (P-1)
All-to-AllN×P−1PN \times \frac{P-1}{P}N×P−1PN \times \frac{P-1}{P}N×(P−1)N \times (P-1)

Key insight: AllReduce moves twice the data of ReduceScatter or AllGather individually — because it’s ReduceScatter + AllGather combined. But for large messages, the per-GPU volume scales as 2N(P−1)P≈2N\frac{2N(P-1)}{P} \approx 2N — nearly independent of GPU count. This is why distributed training scales.


4. Where Each Collective Appears in AI

Parallelism strategyPrimary collectiveWhen
Data Parallel (DDP)AllReduceGradient sync after backward
ZeRO Stage 1ReduceScatterGradient sharding
ZeRO Stage 3 / FSDPAllGather + ReduceScatterParameter gather (forward) + gradient scatter (backward)
Tensor ParallelAllReduceAfter each TP layer (column/row parallel)
Pipeline ParallelPoint-to-pointActivation transfer between stages
Expert Parallel (MoE)All-to-AllToken dispatch to/from experts
Context ParallelAllGather or RingKV sharing across sequence chunks

Understanding which collective each strategy uses tells you the communication cost — and where the bottleneck will be.


Self-Check

  • Name the 5 key collectives and draw the before/after data distribution for each
  • Explain why AllReduce = ReduceScatter + AllGather
  • Calculate per-GPU communication volume for AllReduce with P GPUs and N bytes
  • Explain why AllReduce volume is nearly independent of GPU count for large messages
  • Map each parallelism strategy to its primary collective operation
  • Explain why All-to-All is needed for MoE but not for dense models

References