Learn: Model Parallelism

What you're learning

How to split the computation itself — not just the optimizer state — across GPUs, when a single device can no longer hold or feed a layer. By the end you should be able to (1) derive why Megatron’s column→row GEMM pairing needs only one all-reduce per block, (2) derive the pipeline bubble fraction from scratch, (3) explain sequence and context parallelism as sequence-dimension splits, (4) reason about the MoE all-to-all, and (5) lay out a full DP × TP × PP (× EP × CP) plan onto a real cluster topology.

This lesson assumes lessons 08–09: 08-data-parallelism-and-collectives (all-reduce, ring/tree collectives, NVLink vs InfiniBand) and 09-zero-and-fsdp (sharding optimizer state, gradients, params with ZeRO/FSDP). The crucial hand-off from lesson 09: ZeRO/FSDP shard state but every GPU still runs the same computation on its own data. Here we do the opposite — we split the computation.


1. Learning map

graph TD
    Z["Lesson 09:<br/>ZeRO/FSDP shard STATE<br/>(each GPU: same compute)"] --> M["Why model parallelism:<br/>split the COMPUTE itself"]
    C["Lesson 08:<br/>collectives — all-reduce,<br/>all-gather, reduce-scatter,<br/>all-to-all, NVLink vs IB"] --> M

    M --> TP["Tensor parallelism (TP)<br/>split each matmul<br/>Megatron col→row"]
    M --> PP["Pipeline parallelism (PP)<br/>split LAYERS into stages"]

    TP --> SP["Sequence parallelism (SP)<br/>split LN/dropout/residual<br/>along sequence"]
    TP --> EP["Expert parallelism (EP)<br/>MoE: split experts,<br/>all-to-all dispatch/combine"]

    PP --> BUB["Pipeline bubble<br/>GPipe → 1F1B →<br/>interleaved 1F1B"]

    M --> CP["Context parallelism (CP)<br/>Ring Attention:<br/>split sequence, overlap KV"]

    TP --> COMP["Composition:<br/>3D/4D/5D parallelism<br/>DP × TP × PP × EP × CP"]
    PP --> COMP
    SP --> COMP
    EP --> COMP
    CP --> COMP

    COMP --> TOPO["Map to topology:<br/>TP inside node (NVLink),<br/>PP/DP across nodes (IB)"]
    TOPO --> N["Lesson 11:<br/>putting it together at scale"]

    style M fill:#44a,color:#fff
    style COMP fill:#4a4,color:#fff
    style TOPO fill:#4a4,color:#fff

Figure 1 — Dependency graph. Everything branches from one decision: once state-sharding (lesson 09) is exhausted, you split the compute. The four axes (TP, PP, EP, CP) each attack a different bottleneck, and the final skill is composing them onto a heterogeneous interconnect.


2. Why model parallelism — when sharding state isn’t enough

Lesson 09 gave you a powerful lever: ZeRO-3 / FSDP shard parameters, gradients, and optimizer state across data-parallel ranks, so per-GPU state memory scales as . That solves the static memory problem. But three things it does not solve force us to split the computation:

1. A single layer’s activation working set can exceed one GPU. FSDP all-gathers a layer’s params, computes on the full local batch, then frees them. During that compute, the activations of that layer live entirely on one GPU. At large hidden size , long sequence , and micro-batch , the activation tensor — and the attention score matrix — can simply not fit, no matter how you shard the weights.1

2. You want to cut activation memory without shrinking the batch. Activation memory is what dominates at scale (lesson 06). Recomputation (checkpointing) trades it for FLOPs, but there’s a floor. Splitting the tensors across GPUs cuts activation memory proportionally — a lever orthogonal to ZeRO.

3. You want to keep per-GPU work high while growing the model. With pure data parallelism, making the model bigger means each GPU does more work and holds more state until it OOMs. Splitting layers/matmuls lets you grow model size by adding GPUs to the model dimension, keeping each GPU’s slice tractable.

The one distinction that organizes this whole lesson

ZeRO/FSDP shard state; model parallelism splits computation. Under ZeRO, every GPU eventually runs the same matmul (after gathering the weights). Under tensor parallelism, each GPU runs a different piece of the matmul and they combine results with a collective. This is why model parallelism adds communication inside the forward/backward of a single layer, whereas DP/ZeRO communication happens at gradient-sync / layer boundaries. The former is far more latency-sensitive — which is exactly why it must live on the fastest interconnect you have.

The four axes we’ll build:

AxisSplits…To reduce…Comms primitiveWhere it lives
TP (tensor)each matmul (hidden dim)param + activation mem, per-GPU FLOPsall-reduce (or RS+AG)inside a node (NVLink)
SP (sequence)LN/dropout/residual (seq dim)activation memall-gather / reduce-scatterfused with TP, inside node
PP (pipeline)layers into stagesparam mempoint-to-point send/recvacross nodes (IB)
EP (expert)MoE expertsexpert param memall-to-allnode / across nodes
CP (context)the sequence, for attentionactivation mem for long ring send/recv (P2P)across a ring of GPUs

3. Tensor parallelism — splitting the matmul itself

Tensor parallelism (TP), introduced by Megatron-LM (Shoeybi et al., 2019),2 is intra-layer model parallelism: it partitions the weight matrix of a single GEMM across GPUs so each holds a slice, computes a partial result, and the group combines them with one collective. The elegance is entirely in how you pair the two GEMMs of a block so that only one all-reduce is needed.

3.1 Two ways to split a GEMM

Consider with input and weight .

Column-parallel: split along its columns (output dim): . Each GPU holds and computes . No communication is needed to produce — each GPU independently owns a slice of the output columns. must be replicated on every GPU.

Row-parallel: split along its rows (input dim): , and split the input along columns to match: . Each GPU computes a partial sum , and the true output is the sum:

3.2 The column→row pairing (the key trick)

The MLP block is with the up-projection () and the down-projection (). Megatron makes column-parallel and row-parallel:

graph LR
    X["X (replicated)<br/>b·s × h"] --> A1["GPU0: A₁ (h × 4h/t)"]
    X --> A2["GPU1: A₂ (h × 4h/t)"]
    A1 --> G1["GeLU(XA₁)<br/>b·s × 4h/t"]
    A2 --> G2["GeLU(XA₂)<br/>b·s × 4h/t"]
    G1 --> B1["GPU0: B₁ (4h/t × h)"]
    G2 --> B2["GPU1: B₂ (4h/t × h)"]
    B1 --> S["all-reduce (g)<br/>Σ Bᵢ partials"]
    B2 --> S
    S --> Z["Z<br/>b·s × h"]

    style S fill:#a44,color:#fff

Figure 2 — Tensor-parallel MLP, . The up-proj is column-split so each GPU owns a slice of the 4h intermediate; GeLU is elementwise so it applies independently per slice — no comms. The down-proj is row-split, so each GPU produces a partial sum of the output, resolved by a single all-reduce. One collective for the whole two-GEMM block.

Why does this need only one all-reduce? Because the column-parallel first GEMM produces exactly the column-sharded layout that the row-parallel second GEMM consumes as input. The intermediate never needs to be gathered — it stays sharded and flows straight into . The nonlinearity is the reason the split must be this way round: GeLU is elementwise, so commutes with column-sharding. If you did row-parallel first, you’d need to all-reduce before the nonlinearity (to get the correct pre-activation), then again after the second GEMM — two collectives.2

Conjugate operators and

Megatron formalizes this as two conjugate operators. is identity in forward / all-reduce in backward; is all-reduce in forward / identity in backward. The MLP block is . In forward you all-reduce once (at ); in backward you all-reduce once (at ). Same for attention. Total: 2 all-reduces forward + 2 backward per transformer layer (one per block).23

3.3 Attention is parallel over heads

Multi-head attention is already embarrassingly parallel across heads — each head computes on its own -dim subspace and never interacts with other heads until the output projection. So Megatron assigns whole heads to GPUs: projections are column-parallel (each GPU produces for its heads), the per-head attention + softmax runs entirely locally (no comms — this is why FlashAttention composes cleanly with TP), and the output projection is row-parallel, closing with the single all-reduce.2 Constraint: num_attention_heads must be divisible by , and hidden_size divisible by .4

3.4 Communication cost — and why TP stays inside a node

Each all-reduce is over an activation tensor of elements. A ring all-reduce (lesson 08) moves times the tensor size in bytes per GPU (reduce-scatter + all-gather). Per transformer layer, with 2 all-reduces forward + 2 backward, in bf16 (2 bytes/elem):

The critical property: this volume is independent of for large (the factor ) and — worse — it is exposed on the critical path of every layer, with no useful compute to hide behind it (the all-reduce sits between two dependent GEMMs). This is the entire reason TP must run over the highest-bandwidth, lowest-latency link available:

TP does not scale across nodes

On a DGX/HGX H100 node, all-reduce runs over NVLink/NVSwitch (~900 GB/s bidirectional per GPU);5 across nodes you fall to InfiniBand (~400 Gb/s = 50 GB/s per direction) — roughly an order of magnitude slower, and higher latency. Because TP’s all-reduces are on the per-layer critical path, crossing the node boundary tanks throughput. Rule of thumb: keep (one node’s NVLink domain). This limit is echoed across the field — NVIDIA’s own guidance is “max TP within the node, up to TP=8.”43


4. Sequence parallelism — cut activation memory in the non-TP regions

TP shards the matmul activations, but look at what it doesn’t touch: the LayerNorm, dropout, and residual add around each block. In vanilla Megatron TP these operate on the full activation, replicated identically on all TP ranks — pure redundancy that dominates activation memory at scale.1

Sequence parallelism (SP) (Korthikanti et al., 2022) splits these regions along the sequence dimension: rank owns tokens . LayerNorm and dropout are per-token operations, so they parallelize trivially over the sequence — no communication within them. Activation memory for these regions drops by .1

The beautiful part is how SP splices into TP at the block boundaries. The TP block wants its input replicated (sharded over hidden); the SP region has it sharded over sequence. Converting between the two:

  • Entering the TP block (the operator): sequence-sharded → hidden-replicated is an all-gather (forward) / reduce-scatter (backward).
  • Leaving the TP block (the operator, previously an all-reduce): hidden-partial → sequence-sharded is a reduce-scatter (forward) / all-gather (backward).

SP is "free" — same comms volume as plain TP

A ring all-reduce is a reduce-scatter followed by an all-gather. SP replaces the single all-reduce () with a reduce-scatter, and replaces the identity () with an all-gather. Total communication volume is identical to TP-only — you’ve just re-associated the same bytes so that between the reduce-scatter and the next all-gather each GPU holds only of the activation. You get the activation-memory reduction on the LN/dropout regions at zero extra bandwidth.1 This is why modern Megatron enables SP whenever TP > 1.4


5. Pipeline parallelism — splitting layers into stages

TP splits within a layer and is bandwidth-hungry; pipeline parallelism (PP) splits across layers — assign layers to stage 0, the next chunk to stage 1, etc. Communication is only the activation at stage boundaries, sent GPU→GPU with cheap point-to-point send/recv (no collective) — so PP tolerates the slower inter-node IB link. The cost is a new enemy: the pipeline bubble.

5.1 The bubble

Naively, stage can’t start until stage finishes forwarding the whole batch, so only one GPU works at a time — slowdown. The fix is micro-batching (GPipe, Huang et al., 2018):6 split the global batch into micro-batches and stream them through, so stages overlap. But the pipe still has to fill (stages idle while microbatch 1 propagates) and drain (stages idle at the end). That idle time is the bubble.

graph TD
    subgraph GPipe["GPipe: all forwards, then all backwards (high activation mem)"]
        direction LR
        g["fill: p-1 idle → m fwd → m bwd → drain: p-1 idle<br/>each stage stores activations for ALL m microbatches → O(m) memory"]
    end
    subgraph F1["1F1B: interleave 1 fwd / 1 bwd in steady state (same bubble, less memory)"]
        direction LR
        f["after warmup, each stage alternates F,B,F,B...<br/>a microbatch's activations freed right after its backward → O(p) memory"]
    end
    GPipe --> F1

Figure 3 — GPipe vs 1F1B. Both have the identical bubble fraction; the difference is when backward passes happen, which sets peak activation memory. See the space-time diagram below.

Here is the space-time schedule that makes the bubble concrete (rows = GPUs/stages, columns = time; F = forward of microbatch , B = backward). , :

GPipe schedule (p=4 stages, m=4 microbatches) — bubble shaded S0S1S2S3 F1 F2 F3 F4 bubble B4 B3 B2 B1 bubble F1 F2 F3 F4 B4 B3 B2 B1 bubble Idle at fill (top drains last) + idle at drain (bottom fills last) = (p−1) fwd + (p−1) bwd of idle per stage. Bubble fraction = (p−1)/(m+p−1). Here (4−1)/(4+4−1) = 3/7 ≈ 43%. 1F1B (same p,m): identical bubble, but each stage runs B as early as possible → peak activations held drop from O(m) (GPipe) to O(p) (1F1B).

Figure 4 — GPipe space-time diagram, . Green = forward, orange = backward, hatched red = bubble. The bubble is the steps of fill plus of drain that every stage cannot avoid.

5.2 Deriving the bubble fraction

Let , be the per-microbatch forward/backward time on one stage. Total useful work along the critical path (steady state, once the pipe is full) is microbatches each costing :

The bubble is the fill + drain: the last stage waits forward-steps to receive microbatch 1, and the first stage waits backward-steps at the end:

For this is . The ratio is what matters, not absolute size: and both give 30–32%.3 To make the bubble small you push up — but is capped by memory (GPipe holds activations for all ) and by the global batch size.

5.3 1F1B and interleaved 1F1B

PipeDream 1F1B (Narayanan et al., 2018/2021)7 keeps the same bubble fraction as GPipe but slashes memory: after a warmup of forwards, each stage settles into one-forward-one-backward in steady state, so a microbatch’s activations are freed as soon as its backward completes. Peak activation memory drops from (GPipe) to — this is what made deep pipelines feasible at all.3

Common misconception: "1F1B reduces the bubble"

It does not. GPipe and standard 1F1B have the identical bubble . 1F1B is purely a memory optimization (reorder backwards earlier → free activations sooner). The thing that actually reduces the bubble is interleaving.3

Interleaved 1F1B (Megatron)3 gives each device non-contiguous chunks of layers (“virtual pipeline stages”) instead of one contiguous block. Each chunk is the size, so the fill/drain cost per chunk shrinks and the bubble drops by a factor of :

The price: more point-to-point communication (each microbatch now crosses stage boundaries times as often). Megatron makes this affordable with a scatter/gather optimization that does the extra tensor-reassembly over fast intra-node NVLink.3 So interleaving pays off when your interconnect has headroom, and stops paying when comms becomes the bottleneck. Constraint: must be a multiple of for the interleaved schedule.3

The 2024+ frontier: zero-bubble

Zero-Bubble Pipeline Parallelism (Qi et al., 2024) splits the backward pass into B (input-gradient) and W (weight-gradient) sub-passes; since W has no downstream dependency it can be slotted into the bubble, driving it toward zero under a synchronous schedule.8 [recent]


6. Context parallelism — Ring Attention for long sequences

TP/SP/PP all leave one thing on a single GPU: the attention over the full sequence for a given set of heads. At million-token context, the KV cache and the attention working set blow up regardless of how you shard weights. Context parallelism (CP) partitions the sequence itself across GPUs, so each holds only query/key/value tokens.

The problem: attention is not token-local — query block must attend to all key/value blocks, which live on other GPUs. Ring Attention (Liu, Zaharia, Abbeel, 2023)9 solves this by arranging the CP GPUs in a ring: each GPU computes attention of its local queries against its local KV block, then passes its KV block to the next GPU in the ring while simultaneously computing on the KV block it just received. Over steps every query has seen every KV block. Because attention is computed blockwise with online softmax (FlashAttention, lesson 06), partial results accumulate correctly without ever materializing the full score matrix.9

The key win: communication is fully hidden

The KV send/recv for step is launched while the blockwise attention for step computes. As long as (compute per block) ≥ (time to ship one KV block), the ring communication is completely overlapped with compute — Ring Attention adds no wall-clock overhead versus single-device, up to longer sequences.9 This is the same overlap philosophy as FSDP prefetch (lesson 09), applied to the sequence dimension.

Causal masking breaks the load balance

With a causal mask, later query blocks attend to more KV blocks than earlier ones, so a naive ring leaves some GPUs idle. Striped Attention (Brandon et al., 2023) permutes tokens so each GPU gets a balanced mix of early/late positions, restoring even load.10 Production CP implementations (Megatron-Core, Transformer Engine) use this kind of balancing. [recent]

CP composes with SP (both split the sequence) and is the standard axis for long-context training today.4


7. Expert parallelism — the MoE all-to-all

Mixture-of-Experts (MoE) replaces a dense FFN with expert FFNs and a router that sends each token to its top- experts (typically or ; DeepSeek-V3 uses fine-grained routing with many small experts).11 The whole point is conditional compute: parameters grow with but per-token FLOPs stay ~constant. But now the experts — which hold most of the parameters — are too big to replicate. Expert parallelism (EP) places different experts on different GPUs.

This creates a communication pattern unlike anything above. A token arrives on the GPU that holds its sequence position, but must be computed by the GPU holding its chosen expert — an arbitrary all-to-all shuffle:

graph LR
    subgraph before["tokens by position"]
        T0["GPU0<br/>tok a,b,c,d"]
        T1["GPU1<br/>tok e,f,g,h"]
    end
    R["router: top-k<br/>expert assignment"]
    subgraph after["tokens by expert (after dispatch)"]
        E0["GPU0: Expert 0<br/>gets a,e,..."]
        E1["GPU1: Expert 1<br/>gets c,g,..."]
    end
    T0 --> R
    T1 --> R
    R -->|"all-to-all<br/>DISPATCH"| E0
    R -->|"all-to-all<br/>DISPATCH"| E1
    E0 -->|"all-to-all<br/>COMBINE"| out["tokens back<br/>to original position"]
    E1 -->|"all-to-all<br/>COMBINE"| out

Figure 5 — MoE expert parallelism. Two all-to-all collectives per MoE layer: dispatch (route tokens to the GPU holding their expert) and combine (send expert outputs back to the token’s home position).

7.1 Why the all-to-all is the hard part

Unlike all-reduce, whose volume is independent of the parallelism degree, all-to-all volume is proportional to token count × hidden dim, and as EP grows it pushes traffic cross-node where bandwidth is scarce.12 For fine-grained MoEs the pain compounds: many experts ⇒ more dispatch/combine ops per layer (DeepSeek-V3 has ~58 MoE layers, each with two all-to-alls), large EP spanning nodes ⇒ inter-node latency dominates, and small experts ⇒ low arithmetic intensity, leaving little compute to hide the comms behind. Megatron’s report notes comms can exceed 50% of training time in DeepSeek-V3-scale MoE without optimization.12

Mitigations in current practice (2025–26): DeepEP (DeepSeek’s NVSHMEM-based dispatch/combine kernels) and NVIDIA’s HybridEP overlap all-to-all with expert GEMMs and hit near-hardware-limit bandwidth; overlapping the shared-expert MLP with the dispatch is standard; and “1F1B A2A overlap” hides EP comms inside the pipeline schedule.12

7.2 Load balancing

The router can collapse onto a few popular experts, starving the rest and creating stragglers (the all-to-all waits for the slowest expert). Two levers:12

  • Auxiliary load-balancing loss — penalize uneven expert assignment (Shazeer et al., 2017);13 DeepSeek-V3 notably moves to an auxiliary-loss-free bias-adjustment scheme to avoid the aux-loss quality tax.11
  • Capacity factor + token dropping — cap tokens per expert; overflow tokens are dropped (skip the expert), bounding the worst-case imbalance.

EP is orthogonal to TP/DP — it's a different axis

Experts are replicated across the DP dimension and split across the EP dimension. You can (and do) combine EP with TP inside each expert. Megatron exposes expert-model-parallel-size and expert-tensor-parallel-size separately from the dense TP/DP; a common tuning move is to shift the split from EP toward expert-TP to rebalance load across ranks.12


8. Composing everything — 3D/4D/5D parallelism

No single axis suffices at frontier scale. The full configuration is a product:

Each axis attacks a different bottleneck, and — crucially — each has a different communication profile, which dictates where on the hardware topology it must live:

graph TD
    subgraph node0["Node 0 (8× H100, NVLink/NVSwitch ~900 GB/s)"]
        g0["GPU0"] --- g1["GPU1"] --- g2["GPU2"] --- g3["GPU3"]
        g4["GPU4"] --- g5["GPU5"] --- g6["GPU6"] --- g7["GPU7"]
    end
    subgraph node1["Node 1 (8× H100, NVLink)"]
        h0["GPU0..7"]
    end
    node0 -. "InfiniBand ~50 GB/s/dir<br/>(PP send/recv, DP all-reduce)" .- node1

    TPlab["TP=8 + SP: inside a node<br/>(all-reduce every layer, needs NVLink)"] -.-> node0
    PPlab["PP: across nodes<br/>(P2P at stage boundary, IB-tolerant)"] -.-> node1
    DPlab["DP/ZeRO: outermost<br/>(grad all-reduce once/step, IB-tolerant)"] -.-> node1

Figure 6 — Topology mapping. TP’s per-layer all-reduces demand NVLink, so TP is confined to one node (≤8). PP’s boundary P2P and DP’s once-per-step gradient sync tolerate the ~10× slower InfiniBand, so they span nodes.

The mapping heuristics (established practice):34

  1. TP within a node, TP ≤ 8. Its all-reduces are on the per-layer critical path; keep them on NVLink. Enable SP alongside it for free activation savings.
  2. PP across nodes. Only boundary activations cross the link, via cheap P2P; IB is fine. Size so that per-stage params fit, and pick (microbatches) large enough that is tolerable; interleave if NVLink allows.
  3. DP / ZeRO outermost. Gradient all-reduce (or reduce-scatter+all-gather for FSDP) happens once per optimizer step and overlaps with backward — most latency-tolerant, so it spans the most nodes.
  4. EP sized to fit experts; keep intra-node when possible because all-to-all is bandwidth-heavy. CP for long context, as a ring (often intra-node or over fast links).
  5. The ordering (which axis is “innermost” in the GPU rank layout) is chosen so the chattiest collective lands on the fastest link. Megatron’s rank ordering is essentially TP-innermost, then CP/EP, then PP, then DP-outermost.

How to actually reason about a config

Work memory-first, then comms. (a) Compute per-GPU memory need (params/DP-or-ZeRO shard + optimizer + peak activations). (b) If params don’t fit → add PP (cheap comms) until they do. (c) If a layer’s activations don’t fit, or you want to cut activation memory / raise per-GPU FLOPs → add TP (≤8, NVLink) + SP. (d) MoE experts too big → EP. (e) Sequence too long → CP. (f) Fill remaining GPUs with DP for throughput, sizing microbatches to shrink the bubble. Always check: does each axis’s collective fit on the link you’ve placed it on?


9. Practice problems


10. Practice & resources

Hands-on (do these, don’t just read):

  1. Write a two-GPU tensor-parallel MLP from scratch. Implement ColumnParallelLinear and RowParallelLinear with torch.distributed (all_reduce, all_gather) on 2 GPUs (or 2 processes with Gloo/NCCL). Verify the output equals the single-GPU MLP bit-for-bit (up to fp error). Then insert a GeLU and confirm why you can’t swap column/row order. This is the single most clarifying exercise for TP.
  2. Run Megatron-LM / Megatron-Core. Clone NVIDIA/Megatron-LM, train a small GPT with --tensor-model-parallel-size, --pipeline-model-parallel-size, --sequence-parallel, and --num-layers-per-virtual-pipeline-stage (interleaving). Watch throughput and memory change as you vary TP/PP/. Read megatron/core/pipeline_parallel/schedules.py to see 1F1B and interleaving in code.14
  3. Instrument the bubble. With PP on, profile with Nsight Systems and see the fill/drain idle in the timeline. Vary and confirm the bubble fraction matches .
  4. Compute a parallelism plan. Pick a target (e.g. train Llama-3-70B, or DeepSeek-V3-scale MoE) on a stated cluster (e.g. 256× H100, 8/node, NVLink + 400G IB). Write out DP×TP×PP(×EP×CP), justify each axis by memory-then-comms, and place each on the topology. Sanity-check against a published config.

Reading (paper → docs → code):

  • TP: Megatron-LM, arXiv:1909.080532 — read Section 3 (the MLP + attention parallelism).
  • SP + selective recompute: Korthikanti et al., arXiv:2205.051981.
  • PP schedules: GPipe arXiv:1811.069656; PipeDream/1F1B arXiv:1806.033777; interleaved 1F1B + the analysis in the Megatron scaling paper arXiv:2104.044733; zero-bubble arXiv:2401.102418.
  • CP: Ring Attention arXiv:2310.018899; Striped Attention arXiv:2311.0943110.
  • EP / MoE: the original sparsely-gated MoE arXiv:1701.0653813; DeepSeek-V3 arXiv:2412.1943711; Megatron-Core MoE technical report + docs12.
  • Docs: the NVIDIA Megatron-Bridge / Megatron-Core parallelism guides are the best current (2025–26) practical reference for how these compose and are configured.4

11. What’s next

Three threads, in order:

  1. 11-sota-large-scale-training — putting all of this together at frontier scale: how a real training run (Llama-3, DeepSeek-V3) picks its DP×TP×PP×EP×CP config, overlaps everything, handles fault tolerance and MFU, and squeezes the last 10% out of the interconnect. This lesson is the toolbox; lesson 11 is the finished machine.
  2. Back to 09-zero-and-fsdp — re-read with the state-vs-compute distinction sharp. ZeRO-3 and TP are complementary: ZeRO shards the state you replicate across DP; TP shards the compute within a node. Frontier stacks run both at once (the “ZeRO + 3D parallelism” combination).
  3. Concept stubs to write: tensor-parallelism, pipeline-parallelism, sequence-parallelism, expert-parallelism, context-parallelism, 3d-parallelism.

Part of the gpu-systems-for-llms curriculum. Builds on 08-data-parallelism-and-collectives and 09-zero-and-fsdp; sets up 11-sota-large-scale-training. Filed: 2026-09-02


References

Footnotes

  1. Korthikanti et al., “Reducing Activation Recomputation in Large Transformer Models,” arXiv:2205.05198 (2022). https://arxiv.org/abs/2205.05198 — sequence parallelism: split LayerNorm/dropout/residual along the sequence dim, interleave with TP via all-gather () / reduce-scatter (); same total comms volume as plain-TP all-reduce, with activation-memory reduction on the non-TP regions. Also selective activation recomputation. [established] ↩ ↩2 ↩3 ↩4 ↩5

  2. Shoeybi et al., “Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism,” arXiv:1909.08053 (2019). https://arxiv.org/abs/1909.08053 — introduces tensor (intra-layer) parallelism: column-parallel then row-parallel GEMM pairing for the MLP (so a single all-reduce per block), head-split multi-head attention, and the conjugate operators /. [established] ↩ ↩2 ↩3 ↩4 ↩5

  3. Narayanan et al., “Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM,” arXiv:2104.04473 / SC’21 (2021). https://arxiv.org/abs/2104.04473 — 3D parallelism (DP×TP×PP), the pipeline bubble fraction , interleaved 1F1B reducing the bubble by at P2P cost, and the “TP within a node, PP across nodes” topology guidance. [established] ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10

  4. NVIDIA, “Parallelisms Guide” (Megatron-Bridge / Megatron-Core), https://docs.nvidia.com/nemo/megatron-bridge/latest/parallelisms.html and the Megatron-Core parallelism guide. Current (2025–26) practical guidance: enable sequence parallelism whenever TP>1; keep TP within a node up to TP=8 (NVLink), PP across nodes (IB); use context parallelism for long-context training; TP requires hidden-size and num-attention-heads divisible by the TP degree. [recent] ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  5. NVIDIA H100 / DGX H100 specs: fourth-gen NVLink ~900 GB/s bidirectional per GPU via NVSwitch; typical node-to-node fabric is 8× 400 Gb/s InfiniBand (NDR). NVIDIA H100 datasheet, https://resources.nvidia.com/en-us-data-center-overview/hpc-datasheet-sc23-h100 and DGX H100 datasheet. [established] ↩

  6. Huang et al., “GPipe: Efficient Training of Giant Neural Networks using Pipeline Parallelism,” arXiv:1811.06965 (2018). https://arxiv.org/abs/1811.06965 — micro-batching to fill the pipeline; all-forwards-then-all-backwards schedule ( activation memory). [established] ↩ ↩2

  7. Narayanan et al., “PipeDream: Generalized Pipeline Parallelism for DNN Training,” arXiv:1806.03377 / SOSP’19 (2018). https://arxiv.org/abs/1806.03377 — the 1F1B schedule; reordering backward earlier drops peak activation memory from to at the same bubble fraction as GPipe. [established] ↩ ↩2

  8. Qi et al., “Zero Bubble Pipeline Parallelism,” arXiv:2401.10241 / ICLR 2024. https://arxiv.org/abs/2401.10241 — splits backward into input-grad (B) and weight-grad (W); W has no downstream dependency and fills the bubble, approaching zero bubble under a synchronous schedule. [recent] ↩ ↩2

  9. Liu, Zaharia, Abbeel, “Ring Attention with Blockwise Transformers for Near-Infinite Context,” arXiv:2310.01889 (2023). https://arxiv.org/abs/2310.01889 — context parallelism: distribute the sequence across a ring of devices; each passes its KV block to the next while computing blockwise attention (online softmax), fully overlapping KV communication with compute; enables longer context with no added overhead. [established] ↩ ↩2 ↩3 ↩4

  10. Brandon et al., “Striped Attention: Faster Ring Attention for Causal Transformers,” arXiv:2311.09431 (2023). https://arxiv.org/abs/2311.09431 — permutes tokens so each ring GPU gets a balanced early/late position mix, fixing the load imbalance Ring Attention suffers under causal masking. [recent] ↩ ↩2

  11. DeepSeek-AI, “DeepSeek-V3 Technical Report,” arXiv:2412.19437 (2024). https://arxiv.org/abs/2412.19437 — fine-grained MoE with many small experts + shared experts, and an auxiliary-loss-free load-balancing strategy (bias adjustment) to avoid the aux-loss quality tax; a canonical large-scale EP training system. [recent] ↩ ↩2 ↩3

  12. “Scalable Training of Mixture-of-Experts Models with Megatron Core” (technical report, 2026, arXiv:2603.07685, https://arxiv.org/abs/2603.07685) and the Megatron-Core MoE docs (https://docs.nvidia.com/megatron-core/developer-guide/latest/user-guide/features/moe.html). Four-stage MoE forward (route → dispatch → compute → combine); all-to-all volume scales with tokens×hidden and pushes cross-node at large EP; comms can exceed 50% of DeepSeek-V3-scale training time without overlap; DeepEP/HybridEP kernels, shared-expert overlap, 1F1B A2A overlap; load balancing via aux loss, capacity-factor token dropping, and shifting EP↔expert-TP. See also NVIDIA, “Optimizing Communication for Mixture-of-Experts Training with Hybrid Expert Parallel” (https://developer.nvidia.com/blog/optimizing-communication-for-mixture-of-experts-training-with-hybrid-expert-parallel/). [recent] ↩ ↩2 ↩3 ↩4 ↩5 ↩6

  13. Shazeer et al., “Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer,” arXiv:1701.06538 (2017). https://arxiv.org/abs/1701.06538 — top-k routing with an auxiliary load-balancing loss; the foundation of modern MoE. [established] ↩ ↩2

  14. NVIDIA/Megatron-LM, megatron/core/pipeline_parallel/schedules.py. https://github.com/NVIDIA/Megatron-LM — reference implementation of GPipe, 1F1B, and interleaved 1F1B schedules; tensor_parallel/ holds ColumnParallelLinear / RowParallelLinear. ↩