Tensor and pipeline parallelism, and choosing a layout
Before this lesson: lesson 6 (model states and activation memory), lesson 7 (all-reduce cost: each GPU sends bytes), lesson 8 (data parallelism, ZeRO, and the overlap condition ); block matrix products (linear algebra 1); the transformer block (attention and MLP). Time: about 85 minutes, plus the notebook.
Why this matters #
ZeRO-3 can shard the model states of any model, but data parallelism has two limits (lesson 8). Each GPU still runs whole layers on its own micro-batch, so the activations are not divided. And each data-parallel rank needs about tokens to hide its communication, so at a fixed global batch you cannot add GPUs forever. Tensor parallelism (TP) and pipeline parallelism (PP) split the model itself.
Large LLM runs combine all three. Llama 3 405B was trained with TP = 8 inside each 8-GPU server, PP = 16 and DP = 128, on 16,384 H100 GPUs (Llama 3 paper, 2024, §3.3.2 and Table 4). Megatron-LM, NeMo, DeepSpeed and torchtitan implement these methods, and vLLM uses tensor parallelism to serve models that do not fit on one GPU. Choosing the degrees is a standard design and interview question; the answer is FLOPs, bytes and link bandwidths.
1. Predict first #
2. The picture #
Notation for this lesson. : TP degree (GPUs that share one layer). : number of pipeline stages (in lesson 7, was the number of ranks of a collective; here it is the number of stages). : DP degree. : micro-batches per step. : model chunks per GPU (interleaving). : sequences per micro-batch, : sequence length, : tokens per micro-batch. : hidden size, : attention heads, : layers. : FLOP/s one GPU achieves on the matmuls. : bandwidth per GPU and direction, bytes/s. , : time of the forward and backward pass of one micro-batch on one stage. Activations are bf16 ( bytes).
One matmul on two GPUs #
Take with of size and of size . There are two ways to split (block products, linear algebra 1):
- Column split : GPU computes , which is the -th block of columns of . Each GPU needs all of and sends nothing. The output is split by columns.
- Row split , with split by columns to match: GPU computes , a full-size partial sum, and . An all-reduce adds the two.
Chain the two splits. A column split produces an output split by columns, and a row split wants exactly that as its input. So "column split, then row split" needs no communication in the middle and one all-reduce at the end. An elementwise function such as GeLU can sit in the middle, because it acts on each column alone. This is the whole idea of Megatron tensor parallelism (Shoeybi et al. 2019).
Press Next step to see which block each GPU computes. All blue blocks are local work; the only communication is the aqua all-reduce at the end. Then switch to backward: the all-reduce moves to . Then try wrong split: splitting by rows puts a sum before the GeLU, which costs an extra magenta all-reduce on a 4× larger tensor. The side panel checks each claim on random matrices: the split result equals the unsplit one to about .
A pipeline is an assembly line #
Put layers 1–20 on GPU 0, layers 21–40 on GPU 1, and so on. If the whole batch flows through as one piece, only one GPU works at a time. Cut the batch into micro-batches; then the stages work at the same time on different micro-batches. But the line must fill at the start and drain at the end. The forward phase with stages and micro-batches (F0 is the forward pass of micro-batch 0, F1 that of micro-batch 1, and so on):
| time slot | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| stage 0 | F0 | F1 | F2 | F3 | · | · |
| stage 1 | · | F0 | F1 | F2 | F3 | · |
| stage 2 | · | · | F0 | F1 | F2 | F3 |
The forward phase takes slots, and each stage works in only 4 of them. The dots are the bubble: idle time. The backward phase is the mirror image.
The central figure of this lesson. Each row is a GPU (a stage); time runs to the right. Light blue boxes are forward passes, dark blue boxes backward passes (the number is the micro-batch; with interleaving, the subscript is the chunk), and the violet background is idle time. The orange bars on the right show the most micro-batches each stage keeps in memory at once. Switch GPipe → 1F1B: the step time and the bubble do not change, but the memory bars shrink. Then raise , and then try interleaved with . Press Play to watch the line fill and drain.
Why the two methods use different links. TP all-reduces activations twice per layer in the forward pass, and the next layer waits for the result. PP sends one activation tensor per micro-batch, point to point, to the next stage only. So TP needs the fastest links, and PP works well over the network.
A transformer layer (attention and MLP) uses Megatron tensor parallelism. How many all-reduces does it need in the forward and the backward pass together (no activation recomputation)?
Each of the two blocks (attention, MLP) is a column-parallel layer followed by a row-parallel layer. Each block needs one all-reduce in the forward pass (operator , after the row-parallel layer) and one in the backward pass (operator , for ). Two blocks give 2 + 2 = 4. The count does not depend on : one all-reduce involves all GPUs.
3. Definitions and main results #
The Megatron MLP split #
Proposition (Megatron MLP split). Let with , and . Split by columns and by rows into , in blocks of . Then the forward pass needs one all-reduce, the backward pass one all-reduce, and the weight gradients none.
Proof.
- Block product: . Write .
- GeLU acts on each element, so with . GPU computes alone.
- Column blocks of meet row blocks of : . GPU computes , and one all-reduce gives on every GPU. Megatron calls this operator : all-reduce in the forward pass, identity in the backward pass.
- Backward pass, with the loss and on every GPU: , , and . All of them use only local data.
- feeds all blocks, so : one all-reduce. This is operator : identity in the forward pass, all-reduce in the backward pass.
and are conjugate: each is the identity in one direction and an all-reduce in the other. The reason is the chain rule. When one tensor is copied to GPUs (forward, ), its gradient is the sum of the gradients (backward). When partial results are summed (forward, ), each of them receives the same gradient (backward).
Why not split by rows? Then GPU holds , a partial sum, and because GeLU is not linear. The sum must be complete before the GeLU: an extra all-reduce, on a tensor, 4× larger than .
Attention is split by heads. , and are column-parallel with heads per GPU (so must divide ; with grouped-query attention, the key/value heads are split too, or copied when there are fewer of them than ). Attention runs locally for each head, and is row-parallel. The same and appear. So per layer: 2 all-reduces in the forward pass and 2 in the backward pass, each on values. Activation recomputation repeats the forward ones. The embedding is split along the vocabulary, and the output logits are fused with the cross-entropy, so only numbers are communicated instead of , with the vocabulary size (Megatron-LM §3).
What TP divides. The weights, gradients and optimizer states of the blocks are divided by , and so are the activations inside the parallel regions. The LayerNorm and dropout regions stay replicated: the activation memory per layer is bytes (lesson 6). Sequence parallelism (lesson 10) shards those regions too.
The TP communication-to-compute ratio #
Proposition (TP ratio). Per layer and per forward pass, ignoring the FLOPs of the attention scores,
Proof.
- Matmul FLOPs per layer (2 FLOPs per multiply-add): QKV , output projection , MLP . Total , so per GPU and time .
- Two all-reduces of bytes each (bf16). A ring all-reduce of bytes sends bytes per GPU (lesson 7): bytes, time .
- Divide: .
What the formula says:
- cancels. More tokens per micro-batch do not help: compute and bytes both grow like .
- hurts. The compute per GPU falls as , but the bytes per GPU stay near .
- helps. Compute grows as , bytes only as . Wide models tolerate TP better.
- The backward pass has twice the FLOPs and the same two all-reduces: half the ratio. Megatron overlaps the backward all-reduce of with the weight-gradient matmul, which does not need it. The forward all-reduces sit on the critical path.
- Narayanan et al. (2021, §3.2) count elements per layer for forward plus backward. In bf16, the forward alone is bytes. Same expression, different quantity.
Numbers (H100 SXM, , TFLOP/s, the dense bf16 peak, as a worst case):
| NVLink, GB/s | InfiniBand, GB/s | |
|---|---|---|
| 8192 (70B class) | 0.63 | 5.6 |
| 4096 (7B class) | 1.25 | 11.3 |
Across nodes, TP spends 5–11× more time communicating than computing. Inside a node it is affordable for wide layers. For a 7B model, is already too much: use , or no TP.
Change , and the link. The solid aqua line is the ratio over NVLink, the dashed line over InfiniBand; above the magenta line (ratio 1) the all-reduces take longer than the matmuls. Notice that the InfiniBand line is 9× higher for every , and that forces the network on 8-GPU nodes. The bars in the panel are for tokens, but the ratio does not depend on .
A 7B-class model () uses across two nodes, so the all-reduces run over InfiniBand ( GB/s), with TFLOP/s. Is the forward ratio of communication to compute above or below 1?
The ratio is about 11: each layer waits eleven times longer for the network than it computes. Each GPU sends about bytes per all-reduce, not ; only the compute shrinks with . cancels in the ratio. This is why TP stays inside a node.
Pipeline schedules #
A stage holds consecutive layers. Per micro-batch, each stage boundary carries values forward (activations) and values backward (their gradients), point to point. All three schedules below flush at the end of the step: every micro-batch finishes its backward pass before the optimizer step, so the optimizer gets exactly the gradient of the whole batch.
- GPipe (Huang et al. 2019): all forward passes, then all backward passes.
- 1F1B (PipeDream-Flush, Narayanan et al. 2021; Megatron's default): stage (counted from 0) runs warm-up forward passes, then alternates one forward and one backward pass, then runs the remaining backward passes.
- Interleaved 1F1B (Narayanan et al. 2021): each GPU holds chunks of layers that are not adjacent (GPU 0 holds chunks ), so the pipeline has virtual stages. The schedule needs to be a multiple of .
Theorem (pipeline bubble). Assume equal stages, times and for the forward and backward pass of one micro-batch on one stage, one operation at a time per GPU, no communication time, and a flush at the end of every step.
- Any schedule with one contiguous stage per GPU takes at least . GPipe and 1F1B reach this bound. So their bubble is of the total time, which is of the ideal time (the form Narayanan et al. use).
- Stage stores the activations of micro-batches in GPipe, and of at most in 1F1B.
- With chunks per GPU and the interleaved schedule ( a multiple of ), the bubble time falls to , a fraction of the total. The point-to-point traffic grows about -fold.
Proof. Write and for the forward and backward pass of micro-batch on stage , both counted from 0.
- Lower bound. The last stage cannot start before micro-batch 0 has passed the other stages: not before . Its last operation is some , and after it still run: more. In between, the last stage does of work. So the step takes at least .
- GPipe reaches it. waits for and for . By induction on , it ends at , because both predecessors end at . The last forward pass ends at . The backward phase is the mirror image: more.
- 1F1B reaches it too. One checks by induction over the operations of each stage that ends at . For , this is . In words: once the last stage starts, it alternates F and B without waiting, because the stage before it delivers the next forward pass no later than the moment the last stage finishes a backward pass. (The simulator in the figure and in the notebook confirms the formula, also for and for .)
- Bubble. Each GPU works out of : an idle fraction .
- Memory. A micro-batch's activations stay on a stage from its forward to its backward pass. GPipe runs all forward passes first: in flight. In 1F1B, after warm-up forward passes each new forward pass is followed by a backward pass, so at most are in flight, whatever is.
- Interleaving (a sketch, not a full proof). A chunk's forward and backward pass take and . In this schedule the ramp-up and the ramp-down of step 1 cost chunk steps each, so the bubble time is ; a simulation of the schedule gives exactly this total. The total time is , and the fraction is . Each micro-batch now crosses stage boundaries instead of .
Consequences:
- More micro-batches, smaller bubble. With the bubble is below 20%, because . 1F1B keeps the memory bounded while grows; GPipe does not.
- 1F1B saves memory, not time. It has the same bubble as GPipe (point 1), but each stage keeps at most micro-batches instead of (point 2).
- The bubble is tied to the batch. With a global batch of sequences and DP degree , . More DP at a fixed global batch means fewer micro-batches and a larger bubble.
- Unequal stages. The slowest stage sets the pace. The embedding and the output layer (with a large vocabulary) make the first and the last stages heavier, so frameworks give them fewer layers.
A pipeline has stages and micro-batches, with . What fraction of the step time is each GPU idle with GPipe, and does 1F1B change it?
The bubble is of the total time for both schedules, whatever is ( is the same idle time measured against the ideal time). 1F1B only reorders the work so that stage keeps at most micro-batches. Interleaving () or more micro-batches reduce the bubble.
A run uses stages, a fixed global batch of 512 sequences and . You grow data parallelism from to to use more GPUs. What happens to the bubble fraction?
gives ; gives . At a fixed global batch, more replicas mean fewer micro-batches per replica, so the fill and drain phases weigh more. The growth is not proportional to .
Placing TP, PP and DP on a cluster #
Compare the communication per unit of compute of each method:
| Method | What moves | When | Comm / compute |
|---|---|---|---|
| TP | all-reduce of activations, 4 per layer | every layer, on the critical path | : 0.63 on NVLink, 5.6 on InfiniBand |
| PP | activations to the next stage | once per micro-batch and boundary | : 0.02 on InfiniBand |
| DP | gradients (DDP) or weights and gradients (ZeRO-3) | once per step (ZeRO-3: per micro-batch); overlapped | hidden if each DP rank has tokens |
The PP ratio. Per micro-batch, one GPU of a stage computes forward FLOPs. With TP inside the stage, all GPUs hold the same output tensor, so each sends only of it over its own network card, and the receivers all-gather the pieces over NVLink (the scatter/gather optimization, Narayanan et al. §4.1): bytes per GPU. The ratio is . The table uses , , , and TFLOP/s.
The three rules (Narayanan et al. 2021, takeaways 1 and 2; the Llama 3 order [TP, CP, PP, DP]):
- TP inside the NVLink domain: GPUs per node (8 on a DGX H100, 4 on a GH200 node with 4 GPUs), and smaller for narrow models.
- PP across nodes, with just large enough for the model to fit (including the micro-batches in flight of 1F1B), and .
- DP for the rest, outermost. It communicates least often and overlaps with compute, so it tolerates the slowest links.
The order [TP, CP, PP, DP] lists the dimensions from the fastest links to the slowest (CP is context parallelism, lesson 10): consecutive GPU ranks, which share a node, form the TP groups.
Plan a layout. Each box is a node of 8 GPUs; colour the GPUs by TP group, PP stage or DP replica (here the colours only tell groups apart). The bar shows the memory of one GPU of the first stage: weights, gradients, optimizer states and activations, against the 80 GB of an H100. Start from the worked example below (70B, 8 nodes, TP 8, PP 8), then try PP 4 with ZeRO-1, then TP 16, then the 7B model. Warnings appear in magenta. A back-of-the-envelope model: it ignores embeddings, logits and buffers, so keep 10–20% free.
A 70B model (, , ) trains on 8 nodes of 8 H100 80 GB, global batch 256 sequences of 4,096 tokens, , achieved TFLOP/s. Which layout is the best choice?
TP 8 × PP 8 fits (17.5 GB of model states + 34.9 GB of activations) with a 2.7% bubble and almost idle network links. ZeRO-3 fits too, but it gathers the weights over InfiniBand for every micro-batch of 4,096 tokens, below : communication-bound (ratio 1.7). TP 16 crosses nodes: ratio . Without TP, each GPU holds 10 layers × 8 micro-batches of full activations: about 140 GB with the model states.
Beyond 1F1B and 1D tensor parallelism
- Zero-bubble schedules (Qi et al., ICLR 2024) split the backward pass into the input-gradient part, which the previous stage waits for, and the weight-gradient part, which can wait. Scheduling the weight-gradient parts into the idle slots removes most of the bubble under synchronous training; the paper also reports schedules with no bubble at all.
- DualPipe (DeepSeek-V3 technical report, 2024) feeds micro-batches from both ends of the pipeline and overlaps computation with communication.
- 2D and 3D tensor parallelism (Optimus, Xu et al. 2021; Bian et al. 2021) split each weight matrix along two or three dimensions of a grid of GPUs, so that activations are also partitioned and the communication per GPU grows more slowly with the number of GPUs than in Megatron's 1D split.
Answers to section 1. (1) One: a column split for , a row split for , and one all-reduce at the end. (2) of the step time. 1F1B has the same bubble; it saves memory, not time.
4. Worked example #
(a) TP on one layer #
, one sequence of tokens (), , TFLOP/s.
- FLOPs per GPU and layer in the forward pass: . Time: ms.
- Bytes per GPU: bytes MB.
- Time on NVLink: ms, ratio . On InfiniBand: ms, ratio 5.6.
(b) A pipeline with , , , #
- GPipe: time units, against the ideal . Bubble: of the total ( of the ideal time). Every stage stores 12 micro-batches.
- 1F1B: also 45 units and 20%. Stage 0 stores 4 micro-batches, stage 3 only 1.
- Interleaved, (12 is a multiple of 4): units, bubble . Each micro-batch crosses boundaries in each direction instead of 3. GPU 0 stores a little more than in 1F1B: up to 15 chunk forward passes of stage each, the activations of 5 micro-batches.
Set the pipeline figure to , , to see these three schedules.
(c) A layout for a 70B model on 64 H100s #
Given. Model: parameters, , , . Cluster: 8 nodes × 8 H100 80 GB; NVLink 450 GB/s and InfiniBand 50 GB/s per GPU. Global batch: 256 sequences of 4,096 tokens; micro-batch . For whole-step estimates we use an achieved TFLOP/s.
- Model states: GB with mixed-precision Adam (lesson 6): the memory of 14 GPUs before any activation. So some model splitting is needed.
- TP = 8 inside each node. Ratio at TFLOP/s: on NVLink. Across nodes it would be 2.3.
- Activations per layer with TP = 8, FlashAttention and no sequence parallelism: bytes GB.
- Across the 8 nodes, compare PP = 8 with ZeRO-3 DP = 8 (TP = 8 in both):
| TP 8 × PP 8, 1F1B | TP 8 × ZeRO-3 DP 8 | |
|---|---|---|
| model states per GPU | GB | GB |
| activations per GPU | 10 layers × 8 micro-batches × 0.44 GB = 34.9 GB | 80 layers × 0.44 GB = 34.9 GB |
| network bytes per micro-batch | MB per boundary and direction: 0.17 ms | GB: 0.92 s |
| compute per micro-batch | ms | s |
| verdict | bubble ; network traffic negligible | communication-bound: 4,096 tokens |
- Decision. TP 8 × PP 8 needs about 52 GB per GPU plus buffers, and the network is almost idle. With GPipe instead of 1F1B, stage 0 would store all 256 micro-batches: about 1,117 GB. TP 8 × PP 4 × DP 2 (ZeRO-1) also works: bubble , 21.9 GB of model states, 56.8 GB in total, and a 4.4 GB gradient all-reduce per step that hides easily (DP ratio 0.01). Both are good choices; the second leaves less memory free but uses fewer pipeline stages. TP 8 × DP 8 with ZeRO-2 (no PP) would have no bubble, but it needs about 68 GB per GPU before logits and buffers: too tight.
5. In code #
The tensor-parallel MLP with NumPy, forward and backward written by hand. Each loop iteration is one "GPU"; we check which sums are needed.
import numpy as np
C = np.sqrt(2 / np.pi)
def gelu(x): # tanh form of GeLU
return 0.5 * x * (1 + np.tanh(C * (x + 0.044715 * x**3)))
def dgelu(x): # its derivative
u = np.tanh(C * (x + 0.044715 * x**3))
return 0.5 * (1 + u) + 0.5 * x * (1 - u**2) * C * (1 + 3 * 0.044715 * x**2)
rng = np.random.default_rng(0)
T, h, t = 4, 8, 2 # 4 tokens, width 8, two "GPUs"
X = rng.standard_normal((T, h)) # input
G = rng.standard_normal((T, h)) # upstream gradient dl/dZ
A = rng.standard_normal((h, 4 * h))
B = rng.standard_normal((4 * h, h))
U = X @ A # one GPU, full weights
Z = gelu(U) @ B
dX = ((G @ B.T) * dgelu(U)) @ A.T
Z_parts, dX_parts = [], []
A_cols, B_rows = np.split(A, t, axis=1), np.split(B, t, axis=0)
for Ai, Bi in zip(A_cols, B_rows): # GPU i: column block, row block
Ui = X @ Ai # local, no communication
Z_parts.append(gelu(Ui) @ Bi) # a full-size partial sum
dX_parts.append(((G @ Bi.T) * dgelu(Ui)) @ Ai.T) # a part of dl/dX
print(np.allclose(sum(Z_parts), Z)) # True: forward needs one sum (g)
print(np.allclose(dX_parts[0], dX)) # False: one GPU has only a part
print(np.allclose(sum(dX_parts), dX)) # True: backward needs one sum (f)
F = 989e12 # H100 dense bf16 peak, FLOP/s
for hh in (4096, 8192): # t = 8: (t-1)F/(3hW), NVLink and IB
print(hh, [round(7 * F / (3 * hh * W), 2) for W in (450e9, 50e9)])
# 4096 [1.25, 11.27]
# 8192 [0.63, 5.63]
A pipeline simulator: every stage runs its operations in order; an operation starts when the stage is free and its inputs are ready. It confirms the theorem for worked example (b).
def order(kind, p, m, s):
"""Operations of stage s in order: ("F", i) or ("B", i), i = micro-batch."""
if kind == "gpipe":
return [("F", i) for i in range(m)] + [("B", i) for i in range(m)]
w = min(p - s - 1, m) # 1F1B: warm-up forwards
ops = [("F", i) for i in range(w)]
for i in range(m - w):
ops += [("F", w + i), ("B", i)]
return ops + [("B", i) for i in range(m - w, m)]
def simulate(kind, p, m, tf, tb):
end, free, todo = {}, [0.0] * p, [order(kind, p, m, s) for s in range(p)]
in_flight, peak = [0] * p, [0] * p
while any(todo):
for s in range(p):
if not todo[s]:
continue
op, i = todo[s][0]
deps = [("F", s - 1, i)] if op == "F" and s > 0 else []
if op == "B":
deps = [("F", s, i)] + ([("B", s + 1, i)] if s < p - 1 else [])
if all(d in end for d in deps):
start = max([free[s]] + [end[d] for d in deps])
free[s] = end[(op, s, i)] = start + (tf if op == "F" else tb)
in_flight[s] += 1 if op == "F" else -1
peak[s] = max(peak[s], in_flight[s])
todo[s].pop(0)
return max(free), peak
for kind in ("gpipe", "1f1b"):
total, peak = simulate(kind, p=4, m=12, tf=1, tb=2)
print(kind, total, (total - 12 * 3) / total, peak)
# gpipe 45.0 0.2 [12, 12, 12, 12]
# 1f1b 45.0 0.2 [4, 3, 2, 1]
In PyTorch, torch.distributed.tensor.parallel provides ColwiseParallel and RowwiseParallel
for these splits, and torch.distributed.pipelining provides GPipe, 1F1B and interleaved schedules.
The notebook builds both from NumPy instead.
6. Where it shows up #
- LLM pretraining. Llama 3 405B: TP 8, PP 16, DP 128 on 16,384 H100s at about 400 TFLOP/s per GPU (41% of the bf16 peak), with the parallel dimensions ordered [TP, CP, PP, DP] from the fastest links to the slowest. Narayanan et al. (2021) ran a 1-trillion-parameter GPT model on 3,072 A100s with TP 8 and PP 64, at 502 petaFLOP/s in total.
- Newer pipeline schedules. Zero-bubble schedules and DualPipe (see the deeper box) fill the bubble with weight-gradient work or with a second stream of micro-batches.
- Inference. TP inside a node is the standard way to serve a model that does not fit on one GPU
(vLLM's
tensor_parallel_size). At decode time the all-reduced tensors are small, so latency, not bandwidth, sets their cost (lesson 12). - ML for science. ORBIT, a 113B-parameter vision transformer for Earth system prediction, combined tensor parallelism with sharded data parallelism on the Frontier supercomputer (Wang et al. 2024). On a GH200 node with 4 GPUs, . For models of a few billion parameters with very long token sequences (global weather grids, genomes), sequence and context parallelism (lesson 10) usually split the activations better than TP or PP.
7. Common mistakes #
- TP across nodes. Its per-layer all-reduces need NVLink-class bandwidth: the ratio is 5.6 on InfiniBand for .
- Splitting the first MLP weight by rows. It adds an all-reduce of a tensor before the GeLU.
- "TP communication shrinks with ." The bytes per GPU stay near , while the compute per GPU falls as .
- Head counts. must divide the number of attention heads; with GQA, the key/value heads must be split or copied.
- "1F1B has a smaller bubble than GPipe." It has the same bubble; 1F1B saves activation memory.
- Mixing the two bubble definitions. of the total time or of the ideal time: say which one you use.
- Forgetting . Adding DP ranks at a fixed global batch shrinks and grows the bubble.
8. Check yourself #
- , , TFLOP/s. What is the forward communication-to-compute ratio on
NVLink (450 GB/s) and on InfiniBand (50 GB/s)?
Answer
on NVLink and on InfiniBand. - In the Megatron MLP, why is the backward pass of the column-parallel layer an all-reduce, and
which gradients need no communication?
Answer
is used by every column block, so is a sum over GPUs (operator ). The weight gradients and use only local data, so they need no communication. - , , , . What is the bubble of GPipe, of 1F1B and of interleaving
with ? How many micro-batches does stage 0 store in GPipe and in 1F1B?
Answer
GPipe and 1F1B: (69 time units against 54). Interleaved: (61.5 units). Stage 0 stores 18 micro-batches in GPipe and 6 in 1F1B. - Why can no schedule with one contiguous stage per GPU and a flush beat ?
Answer
The last stage cannot start before , it does of work, and after its last backward pass backward passes on the other stages remain: . So the step takes at least . Interleaving escapes the bound because each GPU holds several stages. - Global batch 512 sequences, , . What is the bubble with and with
data-parallel replicas?
Answer
: , bubble . : , bubble . - In worked example (c), why does TP 8 × PP 8 with 1F1B store as many activations per GPU as TP 8
without PP?
Answer
Stage 0 holds up to micro-batches, each through layers: layers of one micro-batch, the same as one micro-batch through the whole model.
Why does "column split, then row split" need only one all-reduce in the forward pass?
The column split leaves the output split by columns, which is exactly the input a row split needs; elementwise GeLU in between is local. Only the row-parallel partial sums must be added.
What do Megatron's operators and do?
: identity in the forward pass, all-reduce in the backward pass (before the column-parallel layer). : all-reduce in the forward pass, identity in the backward pass (after the row-parallel layer).
How many TP all-reduces does one transformer layer need, and on what size?
2 in the forward and 2 in the backward pass, each on values ( tokens).
Write the TP communication-to-compute ratio per layer.
, with the achieved FLOP/s and the link bandwidth per GPU.
Compute the TP ratio for , , TFLOP/s on NVLink (450 GB/s).
.
What is the pipeline bubble of GPipe and 1F1B?
of the step time, which is of the ideal time .
How many micro-batches does stage keep in memory in 1F1B, and in GPipe?
At most in 1F1B (so at most ); all in GPipe.
What is the bubble of the interleaved schedule with chunks per GPU?
of the step time; the price is about times more point-to-point messages.
Why does tensor parallelism stay inside a node?
It all-reduces activations in every layer on the critical path; over InfiniBand the ratio is about 9× larger than over NVLink, far above 1.
In which order did Llama 3 place its parallel dimensions, and why?
[TP, CP, PP, DP], from the most frequent communication on the fastest links to the least frequent on the slowest.
9. Interview angle #
- "Implement column-parallel and row-parallel linear layers." — Column: replicated input, sharded output, before it. Row: sharded input, partial sums, (all-reduce) after it. Check against the unsplit layer in float64, forward and backward.
- "How many all-reduces does a TP transformer layer need?" — 2 in the forward pass and 2 in the backward pass, each on values.
- "GPipe, 1F1B or interleaved?" — GPipe and 1F1B have the same bubble, but 1F1B keeps instead of micro-batches in memory; interleaving divides the bubble time by at times the messages.
- "64 GPUs, 8 per node, a 70B model: choose TP, PP and DP." — TP = 8 in the node; the smallest PP that fits with 1F1B; DP for the rest; check and for DP. Justify TP in the node with : 0.63 on NVLink against 5.6 on InfiniBand for .
10. Practice #
The notebook for this lesson runs in Colab, with NumPy only. Four exercises, each with a check cell and a folded solution:
- The tensor-parallel MLP on 4 simulated GPUs: forward and backward with explicit all-reduces, checked against the unsplit MLP (outputs and all gradients).
- A pipeline schedule simulator for GPipe and 1F1B: check the step time and the in-flight counts.
- The interleaved schedule: simulate it and check the bubble for several .
layout_report(...): memory per GPU, bubble, TP and DP ratios for a layout; then search all layouts of 64 GPUs for a 70B model and find the best ones.
11. Watch and read #
- Shoeybi et al. (2019), Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism: §3, the MLP and attention splits, the and operators (Figures 3 and 4).
- Narayanan et al. (2021), Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM: §2.2 (GPipe, 1F1B and interleaved bubbles), §3 (takeaways on combining TP, PP and DP), §4.1 (scatter/gather).
- Huang et al. (2019), GPipe, and Narayanan et al. (2021), Memory-Efficient Pipeline-Parallel DNN Training (PipeDream-Flush, the 1F1B schedule).
- Llama Team (2024), The Llama 3 Herd of Models: §3.3.2 and Table 4, the 4D parallelism of the 405B run.
- Qi et al. (2024), Zero Bubble Pipeline Parallelism; DeepSeek-AI (2024), DeepSeek-V3 Technical Report (DualPipe); Xu et al. (2021), An Efficient 2D Method for Training Super-Large Deep Learning Models; Bian et al. (2021), Maximizing Parallelism in Distributed Training for Huge Neural Networks.
- Wang et al. (2024), ORBIT: Oak Ridge Base Foundation Model for Earth System Predictability.
- Hugging Face, The Ultra-Scale Playbook: the chapters on tensor and pipeline parallelism and "Finding the best training configuration"; and picotron, a small readable implementation.
- Austin et al., How to Scale Your Model, How to Parallelize a Transformer for Training: the same trade-offs in the language of TPU meshes.
- Stanford CS336 (2025), lectures 7 Parallelism 1 and 8 Parallelism 2 (on YouTube).
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.