ZeRO Optimization › ZeRO Stage 3: Parameter Partitioning
Language AI HandbookAll chapters ZeRO Optimization › ZeRO Stage 3: Parameter PartitioningOne section · Sections in this chapter5 / 14 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
ZeRO Stage 3 completes the partitioning by distributing the parameters themselves across the GPUs. In Stages 1 and 2, each GPU still holds a full 16-bit replica of all parameters for the forward and backward passes. This bytes is the last significant replicated component. Stage 3 eliminates it, reducing every component of model state to per GPU.
On-Demand Parameter Fetching
The challenge with partitioning parameters is that the forward and backward passes need parameters for every layer. If GPU only permanently stores a shard, how does it execute the forward pass through layers whose parameters live on other GPUs?
Stage 3 exploits the sequential structure of the forward pass: a transformer processes layers one at a time, and at any given moment, only the parameters for the current layer are actively needed. Stage 3 uses this property to fetch parameters on demand:
- Each GPU permanently owns only of the total parameters, distributed across all layers.
- Before layer 's computation begins, all GPUs participate in an All-Gather to collect the complete parameter set for layer from whichever GPUs own those shards.
- The computation for layer proceeds normally, using the fully gathered parameters.
- Once layer 's contribution to the activations (forward) or gradients (backward) has been computed, the gathered parameters are discarded. The GPU reverts to holding only its permanent shard.
The backward pass mirrors this: backpropagation traverses layers in reverse, fetching each layer's parameters via All-Gather before computing gradients, then immediately discarding the fetched parameters. A Reduce-Scatter ships the local gradient contribution to the GPU that owns each parameter shard, which then performs the optimizer update.
This "just-in-time" parameter fetching means that at any moment, a GPU holds:
- Its permanently-owned parameter shard, which is of all parameters
- The parameters for the layer currently being computed, fetched transiently via All-Gather
- Its permanently-owned gradient shard and optimizer state shard
The transient parameter buffer for the current layer is bounded by the size of the largest single layer, which is typically much smaller than . For a transformer model, the largest layer (usually the MLP FFN) has roughly parameters. For a 7B model with , that is about parameters, or 0.13 GB at fp16, which is negligible compared to the savings.
Memory Per GPU Under Stage 3
When all components are partitioned, the per-GPU memory for model state becomes:
where is the total model state (fp16 params + fp16 grads + fp32 master + fp32 Adam moments). Every component scales with . This is a perfect linear reduction in per-GPU memory with the number of GPUs.
For a 7B model with 64 GPUs:
Stage 3 makes it theoretically possible to train arbitrarily large models given enough GPUs, since the memory per GPU decreases linearly with . Doubling the GPU count halves the per-GPU model state memory. This is a fundamentally different scaling property than Stages 1 and 2, where the parameter replica creates a floor that does not decrease with more GPUs.
The Communication Cost
Stage 3's memory efficiency comes at a communication price. The total communication volume relative to standard data parallelism is:
- Baseline (Standard DP): 1 All-Reduce equivalent, total volume bytes per step
- Stage 1: 1 All-Reduce equivalent, total volume bytes (Reduce-Scatter + All-Gather for gradients/parameters)
- Stage 2: 1 All-Reduce equivalent, total volume bytes (same operations, gradient memory freed earlier)
- Stage 3: 3 All-Reduce equivalents, total volume bytes per step
Stage 3's forward pass requires one All-Gather to fetch parameters layer by layer (total volume ). The backward pass requires a second All-Gather for parameters (another ) plus a Reduce-Scatter for gradients (). The full step therefore transfers bytes versus for the baseline. This 3x communication overhead is manageable on high-bandwidth interconnects such as NVLink (600 GB/s bidirectional on A100 nodes) or InfiniBand (200-400 Gb/s between nodes), but can become a significant bottleneck on slower networks.
The communication-compute overlap is critical to Stage 3's practical performance. Modern implementations prefetch the parameters for the next layer while computing the current layer, so the All-Gather for layer proceeds in parallel with the computation for layer . If the network is fast enough to transfer a layer's parameters before the GPU finishes computing with the previous layer, the communication overhead is effectively hidden. This prefetching only works for sequential architectures where the execution order is predictable at scheduling time.
def communication_volume(params_billions, stage, num_gpus):
"""
Estimated total communication volume per training step in gigabytes.
Stage 1 and 2 match standard DP all-reduce volume.
Stage 3 triples it due to forward/backward parameter gathers.
"""
params = params_billions * 1e9
bytes_per_param = 2 # fp16
if stage in (1, 2):
# Equivalent to one all-reduce: 2 * params * bytes_per_param
volume = 2 * params * bytes_per_param
else:
# Stage 3: forward gather + backward gather + backward reduce-scatter
volume = 3 * 2 * params * bytes_per_param
return volume / 1e9
stages = [1, 2, 3]
gpu_counts_comm = [8, 16, 32, 64]
params_7b = 7
comm_table = {
stage: {
nd: communication_volume(params_7b, stage, nd) for nd in gpu_counts_comm
}
for stage in stages
}Communication volume per step (GB) for 7B parameters Stage 8GPUs 16GPUs 32GPUs 64GPUs ------------------------------------------------ Stage 1 28.0G 28.0G 28.0G 28.0G Stage 2 28.0G 28.0G 28.0G 28.0G Stage 3 84.0G 84.0G 84.0G 84.0G
Notice that the communication volume for Stages 1 and 2 is independent of the number of GPUs in this model, because the total data transferred in a ring-based all-reduce scales as for large . Stage 3's volume is also constant across GPU counts here because all three phases each transfer bytes in total, regardless of how many GPUs share the work. The communication volume for Stage 3 matches standard data parallelism practitioners already accept, just tripled. This is why it requires fast interconnects to achieve good hardware utilization.