Pipeline Parallelism › Pipeline Schedules

Michael BrenndoerferJanuary 20, 202613 min read
Language AI HandbookAll chapters
Part 31 of 67Training Infrastructure
Chapter 224Pipeline Parallelism › Pipeline Schedules
Reading section 5 of 10 · Pipeline Schedules · 13 minSection 5 of 10 · 13 min

Book contents

Section 5 of 10 · 13 min read

Pipeline Parallelism › Pipeline SchedulesOne section · Sections in this chapter5 / 10 ↓
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

The order in which forward and backward passes are scheduled across stages and micro-batches is called the pipeline schedule. Different schedules make different tradeoffs between bubble fraction, activation memory, and implementation complexity. The two most important schedules in practice are GPipe and 1F1B, with the interleaved 1F1B schedule providing a further refinement.

The schedule determines how busy each device is, how much memory it requires, and how long the pipeline takes to produce a gradient update. These tradeoffs are non-trivial: a schedule that minimizes the bubble fraction might require enormous activation memory, making it impractical for large models. A schedule that minimizes memory might introduce communication complexity that reduces efficiency. Understanding the specific tradeoffs of each schedule is essential for selecting the right one for a given training configuration, cluster topology, and model architecture.

GPipe: Flush-Based Schedule

GPipe (Google's Pipeline for Machine Learning) was one of the earliest systematic frameworks for pipeline parallelism in deep learning. The paper, published by researchers at Google Brain in 2019, demonstrated that models with billions of parameters could be trained reliably using pipeline parallelism with gradient checkpointing. Its schedule is conceptually straightforward: all MM micro-batches complete their forward passes before any backward passes begin. This "flush" design is easy to reason about, simple to implement, and was used to train some of the earliest large language models.

The full GPipe schedule for DD stages and MM micro-batches proceeds as follows. In the forward phase, micro-batches B1B_1 through BMB_M are injected sequentially into the pipeline. Stage 1 processes B1B_1, then B2B_2, then B3B_3, and so on, passing activations downstream as each micro-batch completes. By the time stage DD has processed BMB_M, all activations for all micro-batches are sitting in GPU memory across all stages. Only then does the backward phase begin. Stage DD computes gradients for BMB_M, then BM−1B_{M-1}, and so on in reverse order. Gradients flow backward through the pipeline until all micro-batches have completed their backward passes and all parameter gradients have been accumulated.

The bubble fraction for GPipe is:

bubble fractionGPipe=D−1M+D−1\text{bubble fraction}_{\text{GPipe}} = \frac{D - 1}{M + D - 1}

where:

  • DD: number of pipeline stages
  • MM: number of micro-batches

Note that this formula uses D−1D-1 in the numerator rather than 2(D−1)2(D-1). This is because in the GPipe flush-based schedule, the startup bubble and the drain bubble are shared: the same pipeline states that are idle during the forward-phase ramp-up become idle again during the backward-phase drain, but the two phases are not counted separately in the same way as a fully interleaved schedule. The effective bubble fraction formula is (D−1)/(M+D−1)(D-1)/(M+D-1), which is equivalent to the general formula when you account for the specific timing of the flush.

For D=4D = 4 and M=8M = 8, this gives (4−1)/(8+4−1)=3/11≈0.27(4-1)/(8+4-1) = 3/11 \approx 0.27. For D=4D = 4 and M=32M = 32, it gives 3/35≈0.0863/35 \approx 0.086. As MM grows large, the bubble fraction approaches zero.

The critical weakness of GPipe is its peak activation memory. Because all MM micro-batch activations across all DD stages must be stored simultaneously (they are all needed for the eventual backward phase), the total activation memory scales as:

activation memoryGPipe=M×D×Alayer\text{activation memory}_{\text{GPipe}} = M \times D \times A_{\text{layer}}

where:

  • MM: number of micro-batches
  • DD: number of pipeline stages
  • AlayerA_{\text{layer}}: activation memory per layer per micro-batch

For large MM and DD, this can easily exceed available GPU memory. Consider a GPT-3-scale model with D=8D = 8 stages and M=32M = 32 micro-batches. Each activation tensor has shape (Bμ,T,H)=(4,2048,12288)(B_{\mu}, T, H) = (4, 2048, 12288) in bfloat16, which is about 201 MB. The total activation memory is 32×8×201 MB≈51 GB32 \times 8 \times 201 \text{ MB} \approx 51 \text{ GB}, which on top of the parameter and optimizer state memory would exceed any single GPU.

GPipe addresses this through gradient checkpointing (also called activation recomputation). Instead of storing all intermediate activations during the forward pass, only certain checkpoint activations are kept. When the backward pass needs an intermediate activation that was not stored, the forward pass is rerun from the nearest checkpoint to recompute it. This reduces activation memory dramatically at the cost of additional computation.

Gradient Checkpointing

Gradient checkpointing is a technique that trades compute for memory. Instead of storing all intermediate activations during the forward pass, only a subset of checkpoint activations is saved. When the backward pass needs a discarded activation, it recomputes the forward pass from the nearest checkpoint. This reduces activation memory at the cost of approximately one additional forward pass per backward pass, roughly doubling the compute cost for the forward-pass portion of training.

In GPipe, gradient checkpointing is applied at the stage granularity: each stage stores only its input activation (the tensor it received from the previous stage) and recomputes all intermediate activations within the stage during the backward pass. With this approach, the activation memory per stage is just Astage-inputA_{\text{stage-input}} regardless of how many layers are in the stage or how many micro-batches are in flight. The recomputation cost is roughly one additional forward pass for every backward pass, which adds about 30-33% to total compute time (since the backward pass typically costs about twice as much as the forward pass, and you are adding one more forward pass).

The simplicity of GPipe made it the natural first implementation choice, and it demonstrated that pipeline parallelism was practical at scale. The activation memory limitations, combined with the compute overhead of gradient checkpointing, motivated the development of more memory-efficient schedules.

1F1B: One Forward, One Backward

The 1F1B (One Forward, One Backward) schedule, introduced by the Megatron-LM project at NVIDIA, addresses the memory problem of GPipe by interleaving forward and backward passes rather than separating them into two distinct phases. The core idea is that a device should begin its backward pass as soon as it has accumulated enough in-flight forward passes to make the backward pass possible, rather than waiting for all MM micro-batches to complete their forward phases first.

In the steady-state of a 1F1B schedule, each device alternates between one forward-pass micro-batch and one backward-pass micro-batch. At any point in time, each device is always working on one computation, and the peak number of activations stored in memory is bounded by the number of stages DD rather than the number of micro-batches MM.

The 1F1B schedule proceeds in three distinct phases.

The warmup phase fills the pipeline: stage 1 processes micro-batches B1B_1 through BDB_D in the forward direction, and stage DD performs its first backward pass after receiving BDB_D from all prior stages. This warmup phase is where the pipeline bubble accumulates, since early stages are busy on their forward passes while late stages are still waiting for activations to arrive. The warmup phase lasts for D−1D - 1 time steps of startup latency.

The steady-state phase then alternates forward and backward passes, maintaining full pipeline utilization. Every stage is either processing a forward pass or a backward pass at every time step. In the steady state, stage kk forwards micro-batch Bk+DB_{k+D} while simultaneously backward-passing micro-batch BkB_k. The stage is never idle during the steady state, as there is always either a new forward micro-batch arriving or a backward gradient ready to process.

The drain phase at the end completes the remaining backward passes as the pipeline empties. After the last forward pass (BMB_M reaching stage DD), no new forward passes enter, and the pipeline drains as gradients flow backward through each stage. The drain phase mirrors the startup bubble in duration: it also occupies D−1D - 1 time steps.

The bubble fraction for 1F1B is identical to GPipe:

bubble fraction1F1B=D−1M+D−1\text{bubble fraction}_{\text{1F1B}} = \frac{D - 1}{M + D - 1}

The advantage of 1F1B is not a smaller bubble but a much smaller peak activation memory. Because each stage begins processing backward passes before accumulating many pending forward-pass activations, the maximum number of in-flight activations at any stage is bounded by DD:

activation memory1F1B=D×Alayer\text{activation memory}_{\text{1F1B}} = D \times A_{\text{layer}}

where:

  • DD: number of pipeline stages
  • AlayerA_{\text{layer}}: activation memory per layer per micro-batch

Comparing to GPipe's M×D×AlayerM \times D \times A_{\text{layer}}, the 1F1B schedule saves a factor of MM in activation memory. For a typical training run with M=32M = 32 and D=8D = 8, 1F1B uses 32 times less activation memory than naive GPipe without checkpointing. This allows 1F1B to handle significantly larger MM without running out of memory, which in turn enables smaller micro-batches (for better tensor core utilization) while still achieving a low bubble fraction.

The reason for the memory difference becomes clear when you examine the schedule visually. In GPipe, by the time the backward phase begins, every stage has already processed all MM micro-batches in the forward direction and is holding all of their activations in memory simultaneously. In 1F1B, a stage begins its backward pass much sooner. Stage DD begins its first backward pass after receiving only its DD-th micro-batch's activations, not after receiving all MM micro-batches. As each backward pass completes at stage DD, the corresponding forward activations can be freed. The memory at any stage is therefore bounded by the maximum number of micro-batches simultaneously "in flight" at that stage, which is DD, not MM.

This is the key algorithmic insight of 1F1B: by scheduling backward passes early, you free activation memory early, keeping the peak memory footprint proportional to pipeline depth rather than to the number of micro-batches. For practical training runs where MM can be tens or hundreds of micro-batches, this memory savings is what makes 1F1B the default schedule for large model training.

The Interleaved 1F1B Schedule

The interleaved schedule is a further refinement of 1F1B introduced by Megatron-LM to reduce the bubble fraction at the cost of increased communication. Standard 1F1B assigns a contiguous block of L/DL/D layers to each device. The interleaved schedule instead assigns VV smaller, non-contiguous blocks of L/(D×V)L/(D \times V) layers each to every device. A single device might hold layers 1-4 and layers 33-36, with another device holding layers 5-8 and 37-40, and so on.

This arrangement means that each micro-batch traverses the pipeline VV times instead of once, because it must visit each device multiple times, once per model chunk assigned to that device. Each traversal is called a pipeline pass. The bubble fraction for the interleaved schedule improves by a factor of VV compared to standard 1F1B:

bubble fractioninterleaved=1V⋅D−1M+D−1\text{bubble fraction}_{\text{interleaved}} = \frac{1}{V} \cdot \frac{D - 1}{M + D - 1}

where:

  • VV: number of model chunks per device (also called virtual pipeline stages)
  • DD: number of devices
  • MM: number of micro-batches

With V=2V = 2, the interleaved schedule halves the bubble fraction. With V=4V = 4, it reduces the bubble to a quarter. The intuition is that by splitting the model into more, smaller chunks, the pipeline fills up faster relative to the total amount of work. The startup ramp covers the same number of time steps, but those time steps represent a smaller fraction of the total work because each "pass" through the pipeline covers only 1/V1/V of the model's layers. The effective depth of each pipeline pass is shorter, so the bubble overhead is smaller relative to the useful computation.

The tradeoff is that each device now sends and receives activation tensors VV times per micro-batch instead of once, so inter-device communication volume increases by a factor of VV. For V=2V = 2, the device sends activations at four different points in the forward pass (instead of two: once when passing from chunk 1 to the next device's chunk 2, once again when passing from chunk 3 to the next device's chunk 4, and similarly in the backward pass). Whether this tradeoff is favorable depends critically on the ratio of communication bandwidth to compute throughput. On systems with fast interconnects, such as NVLink between GPUs within the same node, the extra communication overhead may be small relative to the bubble reduction gains. On systems with slower interconnects, such as InfiniBand between nodes, the added communication can become a bottleneck that negates the bubble benefits.

The interleaved schedule also imposes a constraint that the number of micro-batches MM must be at least D×VD \times V for full pipeline efficiency, and clean scheduling requires MM to be a multiple of DD. In large-scale training runs where MM is already large, these constraints are not binding. In smaller experiments or when memory constraints limit MM, the constraint can be inconvenient.

Out[4]:
Visualization
Line plot comparing GPipe and 1F1B bubble fractions, showing identical overlapping curves that decrease with M.
Bubble fraction comparison between GPipe and standard 1F1B for D=4 pipeline stages across varying micro-batch counts. Both schedules share identical bubble fractions (D-1)/(M+D-1), confirming that 1F1B's primary advantage is memory efficiency rather than reduced bubble time.
Bar chart showing bubble fraction decreasing as virtual stages V increases from 1 to 8.
Bubble fraction for the interleaved 1F1B schedule at D=4, M=16, as a function of virtual stages V. Each doubling of V halves the bubble fraction, with diminishing absolute gains as V grows and communication overhead becomes a larger concern.

Comparing the Three Schedules

The three schedules form a clear progression in terms of capabilities and implementation complexity. Standard GPipe establishes the baseline: full forward phase followed by full backward phase, simple to implement, large activation memory. Standard 1F1B matches GPipe's bubble fraction but dramatically reduces activation memory by interleaving. Interleaved 1F1B goes further, reducing the bubble fraction at the cost of more communication.

Choosing between them in practice comes down to the constraints of the specific hardware setup. For a cluster with fast NVLink interconnects where communication cost is low, interleaved 1F1B with V=2V = 2 or V=4V = 4 is often the best choice, as the bubble reduction improves hardware utilization without a significant communication penalty. For clusters with slower interconnects where communication is a bottleneck, standard 1F1B may be preferable. GPipe is primarily used today when simplicity is the priority, such as for initial prototyping or for smaller models where activation memory is not a binding constraint.