AIAny. ← Back to AIAny

Lesson notes · One paper · a scheduler, not an architecture

GPipe

By the end of this page you'll be able to explain — with real numbers and a slider you can drag — how to train a model far too big for one chip: slice it into stages and feed it like an assembly line.

Subject Training giant models Date Nov 16, 2018 Source arXiv 1811.06965 Lab Google Brain Headline 6B-param Transformer · ~linear speedup

Yanping Huang · Youlong Cheng · Ankur Bapna · Orhan Firat · Mia Xu Chen · Dehao Chen · HyoukJoong Lee · Jiquan Ngiam · Quoc V. Le · Yonghui Wu · Zhifeng Chen — Google Brain.

The core idea

Don't redesign the network. Reschedule it — run the layers like an assembly line.

Most "train a giant model" papers propose a new, memory-frugal architecture (the shape of the network). GPipe's quiet bet is the opposite: scaling is mostly a systems problem, not a modeling one. So it leaves your model alone and treats any network that is a sequence of layers as something you can slice across several chips and run like a factory line — each chip owns one stage and hands its output to the next.

The catch with naive slicing is that the line runs one worker at a time: while stage 1 computes, stages 2–4 sit idle. GPipe's actual trick is to cut each mini-batch (one optimizer step's worth of data) into smaller micro-batches and stream them back-to-back, so all the stages overlap. An idle pipeline becomes a busy one — with the gradient math left exactly as if you trained on a single device.

Slicing a model across chips wastes most of them; streaming micro-batches through the slices is what turns the waste back into speed.

PART A

The problem

The model won't fit on one chip — and slicing it wastes the others.

Step 1 · The black box

A library that takes any layer-stack and a pile of chips, and trains a giant.

Here is the whole story in one picture. You hand GPipe two things: a model written as a sequence of layers, and several accelerators (the chips you train on — GPUs or TPUs). Out comes the same model, trained, but now far bigger than any single chip could hold. GPipe is not a network; it is a library that decides how to spread one across hardware. This picture — four chips in a row — is our running example for the whole page.

model = L layers (too big for 1 chip) GPipe slice · pipeline · sync 4 accelerators trained model same math, way bigger 6B params
Our running example: a four-stage pipeline. GPipe slices the layer-stack into stages (one per chip), pipelines micro-batches through them, then applies one synchronous update. You change nothing about the model itself.

The same library, unchanged, trained two very different giants. A 557M-parameter image classifier (AmoebaNet) reached 84.4% top-1 on ImageNet. And a single 6-billion-parameter, 128-layer Transformer (the sequence model behind modern language tools) trained on 103 languages at once, beating every specialized bilingual model. Two architectures, one scheduler.

6B
parameters in one 128-layer Transformer — across 103 languages.
84.4
% top-1 on ImageNet from a 557M-param AmoebaNet image classifier.
298×
bigger model fits on TPUv3 cores with GPipe vs. without (282M → 83.9B).
~linear
speedup as you add accelerators — the goal of the whole design.

From the abstract: “GPipe … allows scaling any network that can be expressed as a sequence of layers … resulting in almost linear speedup when a model is partitioned across multiple accelerators.”

Step 2 · Why one chip isn't enough

A bigger model needs more memory than any single chip has.

You've seen the black box: layers in, trained giant out. Before we open it, let's be clear on why you'd ever need more than one chip.

Training stores three things in a chip's memory: the parameters (the model's weights), the optimizer state (extra bookkeeping per weight), and — the quiet memory hog — the activations: every layer's output, kept around because the backward pass needs them to compute gradients. Make the model deeper or wider and all three grow. Past a point, the model simply does not fit in one chip's memory, and training stops before it starts.

One chip · model too big

1 chip · fixed RAM overflow

Parameters + optimizer state + activations exceed the chip. Won't run.

Many chips · split the stack

stage 1 stage 2 stage 3 stage 4 each chip holds a slice → it fits

Give each chip one slice of the layers. Now the whole model fits.

The plan — and the catch

Splitting the model by layers across chips is called model parallelism. It solves memory: each chip only stores its slice. But it creates a new problem you can already feel — the layers run in order, so while one chip computes, the rest wait. Step 3 measures exactly how much that wait costs.

Step 3 · The bubble

Naive model parallelism leaves three of four chips idle.

Step 2 put one slice of layers on each of four chips, so the model fits. Now actually run a training step through it and watch where the time goes.

Because the layers run in order, the forward pass climbs the stages one at a time: stage 1 computes, then hands its output to stage 2, then stage 3, then stage 4 — and the backward pass walks back down the same way. At every instant, only one chip is busy; the other three wait. The paper calls that idle time the bubble. With four chips you've paid for four, but you're getting the speed of barely one.

chip 1 chip 2 chip 3 chip 4 F1 F2 F3 F4 B4 B3 B2 B1 bubble = idle time (≈ 75% of the chips, always) time → (forward, then backward)
Naive model parallelism on one mini-batch (Figure 2b). The lit blocks form a single diagonal staircase: forward F1→F4, then backward B4→B1. Everything off that diagonal is bubble — paid-for chips doing nothing.
The whole problem in one number

With K = 4 stages and one batch flowing straight through, only 1 of 4 chips works at any moment — about 75% of your hardware is idle. Buy 8 chips instead of 4 and it gets worse, not better. Part B fixes this without touching the model — just by changing how the data flows through the same four stages.

“The naive model parallelism strategy … leads to severe under-utilization due to the sequential dependency of the network.” Forward = F, backward = B; one mini-batch shown end to end.

PART B

The mechanism

Stream micro-batches · count the bubble · recompute to fit · keep gradients exact

Step 4 · Split the batch — fill the pipe

Cut one batch into many micro-batches and stream them back-to-back.

Step 3 left us with three idle chips out of four. The fix changes nothing in the model — only how the data enters. Here is the single most important idea on this page, and there's a slider to feel it.

One optimizer step processes a mini-batch of, say, 128 examples. Naively, all 128 march through stage 1 together, then stage 2, then 3, then 4 — one big slug, one busy chip at a time. GPipe instead cuts the mini-batch into M micro-batches (here M = 8 chunks of 16) and feeds them in one after another. As soon as micro-batch 1 leaves stage 1, micro-batch 2 enters it — so stage 1 starts on chunk 2 while stage 2 works on chunk 1. The stages overlap, and the pipe fills up.

Drag M = number of micro-batches — watch the bubble shrink and utilization rise

4
57%
chip utilization
M / (M + K − 1)
43%
bubble (idle)
(K − 1) / (M + K − 1)
2.3×
vs. one chip
K × utilization
0% busyfilling up…100% busy
chip 1 chip 2 chip 3 chip 4 time → forward fills, backward drains
One mini-batch, K = 4 stages, M micro-batches (Figure 2c). Each block is one micro-batch on one stage. The bubble is the empty triangle at the start (filling) and end (draining); raising M shrinks it relative to the busy middle.

M = 4 → bubble ≈ 43%. Still a big triangle of idle time at each end.

Push M to 16 (four times the K = 4 stages) and the bubble collapses to about 16% — the busy diagonal dominates. Pull M back to 1 and pipelining vanishes: you're back to Step 3's single working chip. The paper's rule of thumb: the bubble is negligible once M ≥ 4 × K.

Now the formula arrives as a receipt for the slider, not as new magic. With K stages and M micro-batches, the fraction of time a chip sits in the bubble is:

K = stages (here 4) · M = micro-batches · for K = 4: M = 1 → 3/4 = 75% · M = 8 → 3/11 ≈ 27% · M = 16 → 3/19 ≈ 16%

Why this works

The bubble's size (K − 1) is fixed by how many stages you have — the cost of filling and draining the pipe once. But you amortize it over all M micro-batches. Pour more micro-batches through the same pipe and the one-time fill/drain shrinks toward zero as a fraction — so the speedup approaches the ideal of K× from K chips.

The micro-batch sizes here are a toy illustration (128 split into M chunks); the bubble formula and the M ≥ 4×K rule are the paper's. Stages are assumed evenly balanced — Step 8 revisits what happens when they're not.

Step 5 · Does the real hardware agree?

With enough micro-batches, speedup is almost linear in chips.

The slider in Step 4 was the theory. Here are the paper's measured numbers on real TPUs — and they track the formula closely.

The authors timed a Transformer split across K chips, sweeping the number of micro-batches M. Read each cell as “how many times faster than a single chip.” The pattern is exactly what Step 4 predicts: at M = 1 there is effectively no pipeline (about 1×, no matter how many chips), but once M is comfortably larger than K, throughput rises almost in step with the chip count.

Normalized training throughput vs. one chip, Transformer on TPUs (Table 2). Bold cells are the regime M ≥ 4×K, where the bubble is negligible.
micro-batchesK = 2 chipsK = 4 chipsK = 8 chips
M = 11.0×1.07×1.3×
M = 41.7×3.2×4.8×
M = 321.8×3.4×6.3×

Look down the M = 1 row: adding chips barely helps — that's the Step 3 bubble, the optimizer working one chip at a time. Now look at M = 32: eight chips give a 6.3× speedup, close to the ideal 8×. The gap from perfect is the leftover fill/drain bubble plus a little communication between stages.

Crucially, this holds even without fast interconnects. Because GPipe only passes a stage's output activations across the boundary — not weights or gradients — communication is light. On plain P100 GPUs with no NVLink, going from 2 to 8 chips still gave 3.3× for a Transformer and 2.7× for AmoebaNet.

The honest caveat

AmoebaNet scales sub-linearly because its layers aren't evenly balanced — some stages do far more work, so the slowest stage sets the pace and the others wait. The Transformer's near-identical layers split cleanly, which is why it scales so well. Balanced stages matter; Step 8 returns to this.

Table 2 / Table 3. “There is an almost linear speedup with the number of accelerators … when M ≫ K.” Throughput is normalized to the single-chip (no-pipeline) baseline.

Step 6 · Re-materialization

Don't store every activation — recompute them in the backward pass.

Pipelining solved speed. But each stage still has to remember its activations for the backward pass — and that memory is what makes a stage fat. GPipe's second trick attacks exactly this.

Recall from Step 2: the backward pass needs each layer's stored output (its activation) to compute gradients, so normally a stage keeps all of them. Re-materialization (also called gradient checkpointing) makes a deal with time: a stage stores only the activation at its boundary (its input), throws the rest away, and when the backward pass arrives it recomputes the stage's forward pass to regenerate them on the spot. You spend a little extra compute to buy a lot of memory.

Store everything

keep all 8 activations memory: full ✗

Every layer's output sits in memory until backward. Big, but no recompute.

Store the boundary, recompute the rest

keep 1 · recompute 7 memory: small ✓ · recompute

Only the input is saved (solid). The dashed ones are rebuilt on demand in backward.

How much does this buy? Compare what one chip must hold. The wasteful way scales with every layer's activation; re-materialization plus pipelining scales only with one micro-batch through a fraction of the layers:

N = mini-batch size · L = total layers · K = stages · M = micro-batches · L/K = layers per stage · N/M = micro-batch size

1 chip · plain
282M params
1 chip · +recompute
2.7× bigger
128 chips · GPipe
83.9B params
The two levers, together

Re-materialization alone lets a single chip hold a 2.7× bigger model. Combine it with pipelining across 128 chips and the Transformer goes from 282M to 83.9B parameters — a roughly 298× jump. Splitting buys you more chips; recomputing makes each chip hold far more.

Memory numbers from Table 1 (TPUv3, 16 GB cores). Re-materialization = gradient checkpointing. The extra cost is one recomputed forward pass per stage, often hidden because it can be scheduled before the gradients arrive.

Step 7 · Exact, synchronous gradients

Scaling changes the speed — not the math you're optimizing.

You've made it fast (Step 4–5) and made it fit (Step 6). One worry remains: did all this slicing and streaming quietly change what the model learns?

No — and that is a deliberate design choice. Other parallel schemes go asynchronous: different micro-batches update the weights at different times, using slightly stale parameters, which subtly changes the optimization. GPipe refuses that. All M micro-batches in a mini-batch run on the same weights; their gradients are accumulated (summed) and applied as one update at the end of the mini-batch.

M micro-batch grads g₁ … g₈ Σ accumulate one update new W next step
Gradients from all M micro-batches are summed, then applied once. The result is bit-for-bit the same update as feeding the whole mini-batch to one giant chip — pipelining is invisible to the optimizer.
Why this matters

Because the update is identical regardless of how many chips you use, a researcher can prototype on one device and scale to dozens without re-tuning anything or worrying that results won't reproduce. The one subtlety: layers with batch-wide statistics like BatchNorm must use per-micro-batch stats during training and accumulate mini-batch stats for evaluation.

“Gradient updates using GPipe are consistent regardless of the number of partitions.” Synchronous = one update per mini-batch; exact = the same number a single device would compute.

Step 8 · Putting it together

Slice, stream, recompute — three knobs that trade time for memory.

You've met the three moving parts. Before the results, see them as one recipe and one set of dials a practitioner actually turns.

Training a giant becomes a planning problem with three controls. Pick K (how many stages / chips) to make the model fit in memory. Pick M (how many micro-batches) large enough — about 4×K — to make the bubble negligible. Turn on re-materialization so each stage can hold more layers. The partition itself is chosen to balance the per-stage cost so no chip is the bottleneck.

The three knobs and what each one buys. Turn them together to fit a model that no single chip could hold and still train it fast.
KnobWhat it doesWhat it buys
K · stagesSlice the layer-stack across K chipsThe model fits in memory
M · micro-batchesStream M chunks through the stagesThe bubble shrinks → speed
re-materializeRecompute activations in backwardEach chip holds far more

The one real-world wrinkle is balance. The bubble formula assumes every stage takes the same time; if one stage is much heavier, the rest wait on it and the speedup sags (exactly AmoebaNet's sub-linear scaling in Step 5). GPipe's partitioner tries to even out the per-stage cost, but a better partition can always help — which is precisely what later systems improved.

This is the whole library in one paragraph: a partitioner (choose K and the cut points), a pipelining scheduler (choose M), and re-materialization — all behind an API where you just declare your model as a sequence of layers.

PART C

The payoff

Did it work — and can you now explain it?

Step 9 · The results

One library trained giants on two completely different tasks.

You've built the whole idea: slice (Step 2–3), stream micro-batches (Step 4–5), recompute (Step 6), keep gradients exact (Step 7). Final question — what did it actually let the authors train?

Report card · Transformer speedup on TPUs (× vs. one chip, M = 32)

K = 8 chips · M = 32

6.3×

K = 4 chips · M = 32

3.4×

K = 2 chips · M = 32

1.8×

K = 8 chips · M = 1 (no pipeline)

1.3×

speedup vs. one chip · higher is better

6B parameters in a single 128-layer Transformer, trained on 103 languages — beating every bilingual baseline.
84.4% top-1 on ImageNet from a 557M-parameter AmoebaNet, divided across just 4 chips.
298× bigger models fit on TPUv3 cores with GPipe (282M → 83.9B); 25× bigger on 8 GB GPUs.
3.3× on plain GPUs (2→8 chips, no NVLink) — efficient even without fast interconnects.

Read the report card top-down and the whole lesson is there: with M = 32 micro-batches the bubble is tiny, so speedup tracks the chip count (6.3× from 8 chips). Drop to M = 1 and the same 8 chips give barely 1.3× — pipelining is the difference. The image model and the language model were trained by the same code; only the layer list changed.

Numbers from the paper's abstract, Tables 1–3. The AmoebaNet image result (557M params, 84.4%) used 4 partitions; the multilingual Transformer used 128.

Step 10 · Now you can explain it

Five questions — answer each out loud before opening it.

If all five come easily, you've genuinely got this paper — you could walk a colleague through how a model too big for one chip gets trained.

Why isn't one chip enough for a giant model?

A chip must hold the parameters, optimizer state, and — the big one — every layer's activation for the backward pass. Past some size that exceeds the chip's memory, so you split the layers across several chips (model parallelism) just to make it fit.

What is the "bubble," and why does it appear?

Layers run in order, so with naive slicing only one stage is busy at a time while the rest wait. That idle time is the bubble. With K = 4 stages and one batch, about 3 of 4 chips sit idle — you bought four, you get one.

How does micro-batch splitting shrink the bubble?

Cut the mini-batch into M micro-batches and stream them; while stage 2 works on chunk 1, stage 1 starts chunk 2, so the stages overlap. The bubble = (K−1)/(M+K−1), so raising M shrinks it — negligible once M ≥ 4×K. You saw it on the slider: M = 16, K = 4 → ~16%.

What does re-materialization save, and at what cost?

A stage stores only its boundary activation and recomputes the rest during the backward pass, dropping peak memory from O(N×L) toward O(N + (L/K)(N/M)). The cost is one extra forward pass per stage — cheap memory for a little compute. Alone it fits a 2.7× bigger model.

Does pipelining change what the model learns?

No. All M micro-batches use the same weights; their gradients are summed and applied as one synchronous update — bit-for-bit identical to single-device training. You can scale across chips without re-tuning or worrying about reproducibility.

What happened next — pipeline parallelism became one of the three standard ways to split a model across hardware (alongside data and tensor parallelism). Re-materialization (gradient checkpointing) is now a one-line option in every major framework. Today's largest models are trained with descendants of exactly these ideas.

“GPipe … utilizes a novel batch-splitting pipelining algorithm, resulting in almost linear speedup when a model is partitioned across multiple accelerators.” — the abstract, Huang et al., 2018
The profound impact

This is how today's largest models are physically trained.

GPipe's bet — that scaling is a systems problem you solve with a scheduler, not a new architecture — became the default. Pipeline parallelism is now one of the standard ways to spread a model across hardware, and re-materialization ships in every major framework.

2019 → present · the toolbox

Megatron-LM · DeepSpeed

The systems that train frontier models combine pipeline parallelism with tensor and ZeRO-style sharding. GPipe is the pipeline branch's clean starting point — its bubble and the M ≥ 4×K rule still apply.

successors · less bubble

PipeDream & beyond

Later schedulers (PipeDream, interleaved 1F1B) shrink the bubble further by reordering forward and backward micro-batches — refining, not replacing, the batch-splitting idea you just learned.

everywhere · one line

Gradient checkpointing

Re-materialization is now a one-flag option in PyTorch, JAX and TensorFlow. Trading recompute for memory to fit a bigger model is routine — you've just seen where it came from.

Don't redesign the network — reschedule it. That one move is now baked into how giant models get trained.