Reducing Activation Recomputation in Large Transformer Models
Cut activation memory 5× and recover over 90% of the time lost to recomputation.
Training a transformer stores every intermediate tensor the backward pass will need, and the usual fix when those tensors overflow the GPU is to discard them and recompute them later, at 30 to 40% of the training time. This paper shards the tensors that tensor parallelism copies onto every GPU and recomputes only the attention scores.
Explaining the paperReducing Activation Recomputation in Large Transformer ModelsFor GPT-3 split across 8 GPUs, one layer's stored activations for one sequence fall from 579 MB to 107 MB per GPU, and the 530B-parameter model trains 29.7% faster than it did with full recomputation.
When a large transformer does not fit on its GPUs, the weights are usually not what overflows. The overflow comes from the activations: the intermediate tensors of the forward pass that the backward pass needs to compute gradients. A matrix multiply needs to compute the gradient of , so has to stay in memory from the moment the forward pass computes it until the backward pass reaches that layer. Every layer of every microbatch in flight holds such tensors at once.
The standard remedy is activation recomputation, also called gradient checkpointing, covered in our gradient checkpointing explainer: keep only each layer's input, drop everything else, and rerun that layer's forward pass when the backward pass needs its internals. The memory drops to almost nothing, and a full extra forward pass is paid for every layer. In NVIDIA's training runs that costs 30 to 40% of the execution time.
This paper, from the team behind Megatron-LM, removes most of that cost with two techniques layered on Megatron's existing tensor parallelism. Sequence parallelism splits, along the sequence, the part of each layer that tensor parallelism leaves copied on every GPU. Selective activation recomputation recomputes only the attention-score tensors, which take up more memory than the rest of a GPT-3 layer and cost little to rebuild. Together they cut activation memory about 5× and recover over 90% of the time full recomputation used to cost. On a 530B-parameter model across 2240 A100 GPUs, MFU (the fraction of the GPUs' peak FLOP rate spent on the FLOPs the model itself needs for its forward and backward passes) rises from 42.1% to 54.2%, a 29% speedup.
The page follows the paper's derivation: count the bytes one layer stores, see which of them tensor parallelism divides and which it copies, split the copied ones along the sequence at the same communication volume, account for what pipeline parallelism adds, and then recompute only the tensors that are large in bytes and small in FLOPs.
Why activations, not weights, fill the GPU
The paper defines an activation as any tensor created in the forward pass that is needed for gradient computation. That excludes the parameters and the optimizer state and includes the dropout masks, since the backward pass must know which entries were zeroed. Weights and optimizer state are fixed once the model and optimizer are chosen. Each activation can either be stored or recomputed, so activations are the part of the memory a training system can trade against compute.
The paper's Figure 1 shows the split for its four test models, 22B to 1T parameters, each on an 80 GB A100. Without the new techniques the activations alone exceed the parameters and optimizer state for every model, by roughly three to four times at 530B and 1T, and the total is above 80 GB in all four cases. With both techniques, every model's total drops below 80 GB.
The other forms of parallelism do not remove the problem. Tensor parallelism (splitting each layer's matrix multiplies across GPUs) does shrink activations, but it communicates inside every layer and its matrix multiplies get smaller as it spreads, so in practice it stays inside one 8-GPU server linked by NVLink. Pipeline parallelism (splitting the layers into consecutive stages on different GPUs) looks as if it should divide activations by the number of stages, and a section below shows why it does not.
Counting one layer's activation bytes
One transformer layer is a layer norm, a self-attention block, a second layer norm and a two-layer MLP, with residual connections around each block. Write for the sequence length, for the microbatch size (the number of sequences processed together), for the hidden width and for the number of attention heads. The paper assumes 16-bit activations, 2 bytes per element, except dropout masks at 1 byte per element, and ignores small buffers such as a layer norm's per-token mean and variance. A tensor of shape then costs bytes.
Operation by operation, each part of the layer keeps what its own backward step reads:
- Each layer norm keeps its input, . Two layer norms: .
- Attention keeps the shared input of the Q, K and V projections (), both Q and K for the product (, since the gradient for Q needs K and the one for K needs Q), the softmax output (, one matrix per head), the softmax dropout mask (), the dropped-out probabilities and V for the product with the values (), the input of the output projection () and the dropout mask after attention (). Total: .
- The MLP keeps the inputs of its two linear layers ( and , the second one wide), the GeLU input () and a dropout mask (). Total: .
Adding the three gives . Factoring out gives the paper's per-layer formula:
The figure lists the fourteen tensors with their sizes for GPT-3 (, ) at one sequence. Click a row to see why the backward pass needs it, and drag the sequence length to watch the three amber score tensors outgrow the eleven teal ones. The two view buttons mark the tensors the next sections are about.
The two terms of Equation (1) grow differently. The part is linear in the sequence length. The part is quadratic in it, because each of the heads keeps an score matrix. Written inside the bracket as , it is compared directly with 34: the attention part is larger once , which for GPT-3 happens at .
At GPT-3's trained length of 2048, is exactly 80. With = 2048 × 1 × 12288 = 25,165,824 elements, the structural part is 34 × 25.2M = 856 MB, the attention part is 80 × 25.2M = 2.01 GB, and one layer holds 2.87 GB for a single sequence, 70% of it in the score tensors. GPT-3 has 96 layers, so storing everything for one sequence would take 275 GB.
What tensor parallelism leaves replicated
Megatron's tensor parallelism splits each layer across GPUs, the tensor-parallel group. In the MLP, the first weight matrix () is split by columns and the second, (), by rows. Each GPU then computes GeLU on its own columns without talking to the others, because GeLU acts on each element separately, and produces a partial sum of the MLP output. Attention is split the same way across heads. At the end of each block the partial sums are added with an all-reduce, the collective that sums a tensor across all GPUs and leaves the full sum on every one of them. The paper calls this operator (all-reduce in the forward pass, nothing in the backward), paired with at the start of the block (nothing forward, all-reduce backward).
Splitting the matrices also splits the activations inside the blocks: each GPU stores only its heads' score tensors and its slice of the MLP intermediates. What it does not split is anything at the block boundaries, where every GPU holds the full tensor. That gives the paper's Equation (2):
The 24 is the 34 minus the ten boundary units. Those ten are the two layer-norm inputs (), the inputs to the two blocks, meaning the shared QKV input and the input of the layer (), and the two dropout masks after attention and after the MLP (). Every one of the GPUs stores an identical copy of them.
For GPT-3 at the paper's , Equation (2) gives units of , or 579 MB per GPU per layer, down from 2.87 GB. The undivided 10 is now 43% of what remains, and it is the same size as the whole attention term. Doubling to 16 would only bring 23 down to 16.5, and it would push tensor parallelism across the slower links between servers.
Splitting the layer norm along the hidden dimension is possible, and some systems do it (Amazon SageMaker's model parallelism and GSPMD). Then every layer norm must compute each token's mean and variance across devices, an extra collective on an operation that is otherwise cheap.
How sequence parallelism works
Layer norm and dropout treat every token independently. Layer norm normalizes each token's -vector using only that vector; dropout zeroes elements one at a time. So the boundary region can be split along the sequence: rank keeps tokens to and runs layer norm and dropout on those alone. The layer then alternates between two layouts, split by sequence in the layer-norm and dropout regions and split by hidden dimension (as before) inside attention and the MLP, and it needs a conversion at each change.
Going into a block, the matrix multiply needs every token, so the shards are concatenated with an all-gather: each rank sends its shard to all others, and all end with the full tensor. The paper calls this . Coming out, each rank holds a full-length partial sum that must be added across ranks and then cut back into sequence shards. A reduce-scatter does both at once: rank ends with the sum of shard only. This is . For the MLP, the paper writes the whole block as Equation (3), with superscripts marking the split dimension:
The same block as code for one rank, with GPT-3's shapes at :
# MLP block with tensor + sequence parallelism, on rank i of t (Eq 3).
# GPT-3 shapes at t = 8: s = 2048, b = 1, h = 12288. Residual add omitted.
def mlp_block(x_i): # x_i: [s/t, b, h] = [256, 1, 12288]
y_i = layernorm(x_i) # only this sequence shard of Y is stored
y = all_gather(y_i) # g: [2048, 1, 12288], the full sequence
z_i = gelu(y @ A_cols[i]) # [2048, 1, 6144], this rank's 4h/t columns
w_i = z_i @ B_rows[i] # [2048, 1, 12288], a partial sum
v_i = reduce_scatter(w_i) # g-bar: sum over ranks, keep 256 rows
return dropout(v_i) # [256, 1, 12288]
# backward: all_gather's gradient is a reduce-scatter and vice versa,
# plus one extra all_gather(y_i) to rebuild Y for the weight gradient of AIn the backward pass each converter runs its mirror image. The gradient of an all-gather is a reduce-scatter, and the gradient of a reduce-scatter is an all-gather, so is all-gather forward and reduce-scatter backward, and the reverse.
The new collectives replace the old ones rather than adding to them. Per layer, forward plus backward, tensor parallelism used four all-reduces; tensor plus sequence parallelism uses four all-gathers and four reduce-scatters. A ring all-reduce, the standard bandwidth-optimal implementation, is itself a reduce-scatter followed by an all-gather. Sequence parallelism does the same two halves, with layer norm and dropout run between them on the sequence shards. Step through a ring all-reduce on four ranks in the figure: after the first three steps each rank owns one fully summed sequence chunk, which is exactly the layout produces, and the last three steps are the all-gather performs at the start of the next block.
Each rank sends bytes in each half, for , and the pair adds up to the of the all-reduce it replaces. The byte count stays the same, but the timing does not: the paper measures a reduce-scatter plus an all-gather as slightly slower than one all-reduce.
The layer-norm output needs extra care. The GeLU matrix multiply needs the full again in the backward pass, to compute the gradient of . Storing the gathered would put an undivided back into memory, so each rank stores only its shard and runs one more all-gather in the backward pass, overlapped with the computation of the input gradient so its latency is hidden. That all-gather is additional traffic beyond the swap above; the paper's “no communication overhead” refers to the swap.
With the boundary region sharded, every term carries a :
Equation (4) is Equation (1) divided by . For GPT-3 at it is units, 359 MB per GPU per layer instead of 579 MB. The forward pass also gets a little faster: on one 22B layer it drops from 7.7 ms to 7.2 ms, because layer norm and dropout now run on of the tokens on each GPU.
Why pipeline parallelism does not divide activations
Pipeline parallelism gives each of GPUs a consecutive group of layers and streams microbatches through them. To keep all stages busy, the 1F1B schedule (one forward, one backward) lets the first stage start microbatches before the backward pass of the first one returns to it. Until each backward pass finishes, that microbatch's activations stay stored. So the first stage holds microbatches of layers each, layers' worth, whatever is. The later stages hold fewer, but the first stage sets the memory requirement.
In the figure, the right-hand column counts the microbatches each stage is holding at the time cursor. Play the schedule, then change : stage 0 always peaks at , and the layers-held readout stays at 96.
The total activation memory on the first stage, with tensor and sequence parallelism, is therefore Equation (4) times :
Megatron's interleaved schedule, which gives each GPU smaller groups of layers to shrink the pipeline's idle time, multiplies this by . The paper also counts the embedding dropout, the final layer norm, the output layer and the fp32 logits; for the 22B model those add less than 0.01%.
Take GPT-3 as the paper runs it: , , , microbatch 1. The interleaving factor is , so the first stage stores about 124 layers' worth. At 579 MB per layer for tensor parallelism alone, that is 71.8 GB of activations. The parameters and optimizer state add about 44 GB per GPU (175B parameters over 64 GPUs is 2.7B each, at 16 bytes per parameter for mixed-precision Adam as counted in the ZeRO explainer), so the total is far past 80 GB. Sequence parallelism alone brings activations to 44.5 GB, and the total to 88.5 GB, still too much.
How selective activation recomputation works
When activations still do not fit, something has to be recomputed. The simplest option is to checkpoint some layers fully and store all activations of the others. It does not scale well: MT-NLG (Megatron-Turing NLG, the paper's 530B model) on 35 pipeline stages has only three layers per GPU, so the choice is between recomputing zero, one, two or three whole layers. The tensors inside a layer also differ widely in what they cost to rebuild.
The term comes from the operations after the Q, K and V projections widen the tensor to one score matrix per head: the product, the softmax, the softmax dropout and the product with V (the region the paper's Figure 3 outlines in red). These tensors are large, but few FLOPs are spent per element. In the paper's FLOP count, the forward pass of a layer spends in the weight matrix multiplies and in the two score products, a ratio of , 1 to 36 for GPT-3. The tensors are the opposite case: the GeLU input, for example, comes out of the matrix multiply, one of the most expensive operations in the layer.
Selective activation recomputation therefore stores everything in the 34 (including Q, K and V) and discards only the score tensors. In the backward pass it reruns , the softmax, the dropout (regenerating the same mask from the saved random-number state) and the product with V from the stored Q, K and V. Memory drops by a fraction of
which is for GPT-3 and for MT-NLG (, , ). The recomputation is one extra forward of the two score products, FLOPs each per layer. The paper puts the resulting ratio of hardware FLOPs (what the GPU executes) to model FLOPs (what the model needs) at approximately , an overhead of 2.7% for GPT-3 and 1.6% for MT-NLG.
The figure shows both bars. Switch between the two models, and drag the sequence length: the memory saving climbs toward 100% as the quadratic term takes over, and the FLOP overhead grows with as well, since the recomputed products are themselves quadratic in .
In code the change is one checkpoint around the attention core. Megatron-LM exposes it as --recompute-granularity selective, or the shorthand --recompute-activations.
# Selective activation recomputation: checkpoint only the attention core.
def attn_core(q, k, v): # q, k, v: [b, a, s, h/a], stored
p = softmax(q @ k.transpose(-1, -2)) # [b, a, s, s]: 2as^2b bytes
p = dropout(p) # mask as^2b, output 2as^2b
return p @ v # [b, a, s, h/a]
def layer(x): # x: [s, b, h]
y = layernorm(x)
q, k, v = qkv(y) # kept: part of the 34sbh
o = checkpoint(attn_core, q, k, v) # scores dropped, rebuilt in backward
x = x + dropout(proj(o))
return x + dropout(mlp(layernorm(x)))With sequence parallelism and selective recomputation together, the first stage stores
(multiplied by under interleaving). The attention term is gone, so activation memory is now linear in and does not depend on the number of heads. For GPT-3 that is units, 107 MB per layer and 13.3 GB for the 124 layers' worth the first stage holds. With 44 GB of parameters and optimizer state the total is about 57 GB, inside 80 GB with no layer fully recomputed. Selective recomputation without sequence parallelism would leave units, 40.6 GB of activations, and would not fit; the paper reports that none of its four models fit without both techniques together.
What the paper measured
All experiments use , , a vocabulary of 51,200 and no data parallelism, on 80 GB A100s. The four models are 22B (, , 8 GPUs), 175B GPT-3 (, , 64 GPUs), 530B MT-NLG (, , 280 GPUs) and 1T (, , 512 GPUs), with the interleaved schedule () for 175B and 530B.
Memory first, as a percentage of the tensor-parallel baseline of Equation (2). The paper reports that each technique alone cuts the requirement nearly in half (by the Table 2 formulas, to 62% and 57% for GPT-3), and that together they bring it under 20%, the 5× reduction of the title. Full recomputation reaches about 10%, so the combination uses roughly twice the memory of full recomputation. For GPT-3 the formulas give 23 units for the baseline, 4.25 for both techniques (18.5%, a 5.4× cut) and 2 for full recomputation (8.7%).
On one layer of the 22B model (Table 4), the forward plus backward pass takes 19.6 ms with no recomputation. Full recomputation raises it to 27.2 ms, 39% more; the expected cost of one extra forward is about 33%, and the rest comes from losing an optimization that overlaps the backward all-reduce with the weight gradient computation. Selective recomputation costs 20.9 ms (7%), and selective recomputation with sequence parallelism 20.3 ms (4%). On the larger models the per-layer overhead falls to 2% for 530B and 1T, against 36% for full recomputation.
End to end (Table 5), the full training iteration runs 29.0% to 32.1% faster than with full recomputation, taking about 76 to 77% of the time. For 530B the iteration drops from 49.05 s to 37.83 s. MFU rises with model size, to 56.3% for the 1T model. HFU, the same ratio computed with the recomputed FLOPs included, is 57.0%. Both are measured against the A100's 312 TFLOP/s dense 16-bit peak.
The abstract's 54.2% is a separate run: the 530B model with 8-way data parallelism on 2240 GPUs (280 × 8), where the gradient all-reduce between replicas raises the iteration time from 37.83 s to 39.15 s and MFU drops from Table 5's 56.0% to 54.2%. The paper did not overlap that all-reduce with the backward pass. The 42.1% it compares against is the same setup with full recomputation, and 54.2/42.1 is the 29% speedup.
Scope and later work
The evaluation runs without data parallelism apart from that one 2240-GPU data point, so batch sizes (4 to 512 sequences) are far below real training. Data-parallel memory techniques such as ZeRO and CPU offloading are described as complementary and are not compared. All memory numbers include an optimization from Appendix B that frees each pipeline stage's output tensor after its forward pass, since the next stage holds a copy. Appendix C tests storing all activations for as many microbatches as memory allows and recomputing only the rest, and finds that after the two main techniques it adds little.
The attention score tensors were also the target of FlashAttention, released later the same month. It computes attention in tiles, keeps only the output and the softmax normalization statistics, and recomputes the scores inside one fused kernel in the backward pass, which removes the term without a separate checkpoint. Sequence parallelism addresses the replicated , which FlashAttention does not touch, and it remains part of Megatron-LM.
Questions you might still have
If activations are the problem, why not recompute all of them?
The paper calls that full activation recomputation: store each layer's input and redo the whole forward pass during backpropagation. It cuts activations to 2sbh per layer but costs 30 to 40% of training time in NVIDIA's runs (39% on one 22B layer). This paper makes activations small enough that only the attention scores need recomputing, which costs 4% on that same layer.
Why can't tensor parallelism split the layer norms and dropouts too?
Those operations sit between the parallel blocks, on a tensor every rank holds in full after the all-reduce. Splitting them along the hidden dimension would make each layer norm compute its mean and variance across devices, which is extra communication on a cheap operation. They are independent along the sequence, so sequence parallelism splits them there instead.
Does sequence parallelism add communication?
Replacing each all-reduce with a reduce-scatter and an all-gather moves the same bytes, because a ring all-reduce is those two steps. There is one extra all-gather per MLP and attention block in the backward pass, to rebuild the layer-norm output for a weight gradient, and it is overlapped with computation. The paper measures the two collectives as a little slower than one all-reduce, but the forward pass still gets faster overall (7.7 to 7.2 ms on a 22B layer).
Why recompute the attention scores and not the MLP?
Selective recomputation picks tensors by how many bytes they take to store per FLOP needed to rebuild them. The score tensors are 5as²b bytes, larger than the rest of the layer for GPT-3 at s = 2048, and come from two small matrix multiplies. The MLP's 8sbh intermediates come from the h-to-4h matrix multiply, one of the most expensive operations in the layer.
Does FlashAttention make selective recomputation unnecessary?
It removes the same term by another route. FlashAttention, released later the same month, computes attention in tiles, never stores the s by s matrix, and keeps only the output and the softmax normalization statistics, recomputing the scores in the backward pass inside one fused kernel. With it, the stored activations are essentially the 34sbh part, as in Equation (6). The FlashAttention explainer covers the kernel.
How does this relate to ZeRO?
They target different memory. ZeRO partitions optimizer state, gradients and parameters across data-parallel ranks; this paper reduces activations inside a tensor-parallel group. The paper calls such techniques complementary and does not compare against them. The ZeRO explainer covers the other half of the memory.
Is this the same "sequence parallelism" as Li et al. (2021)?
No. Li et al. split the sequence through the entire network, including attention, and replicate the parameters and optimizer state on every device, which does not scale to models this size. Megatron's version splits along the sequence only in the layer-norm and dropout regions and leaves the weights split by tensor parallelism.
What is the difference between MFU and HFU?
Model FLOPs utilization counts only the FLOPs the model needs for one forward and backward pass; hardware FLOPs utilization also counts recomputed FLOPs. Both divide by the 312 TFLOP/s A100 peak. With recomputation HFU is always higher: 57.0% vs 56.3% for the 1T model, a gap of roughly 1 + s/6h.
Footnotes & further reading
- The paper: Korthikanti, Casper, Lym, McAfee, Andersch, Shoeybi, Catanzaro, Reducing Activation Recomputation in Large Transformer Models (NVIDIA, arXiv May 2022; MLSys 2023). The implementation ships in Megatron-LM; the sequence-parallel converters are in megatron/core/tensor_parallel/mappings.py.
- Tensor (intra-layer) parallelism, the column and row splits, and the f and g operators of the 2019 paper: Shoeybi et al., Megatron-LM: Training Multi-Billion Parameter Language Models Using Model Parallelism, explained in our Megatron-LM page.
- Activation recomputation is prior art: Chen, Xu, Zhang, Guestrin, Training Deep Nets with Sublinear Memory Cost (2016), building on Griewank & Walther. We cover it in the gradient checkpointing explainer.
- Pipeline schedules: Narayanan et al., Memory-Efficient Pipeline-Parallel DNN Training (1F1B), and Narayanan et al., Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM (the interleaved schedule).
- The earlier, different “sequence parallelism”: Li, Xue, Li, You, Sequence Parallelism: Long Sequence Training from System Perspective.
- The reduce-scatter plus all-gather decomposition of all-reduce: the NCCL collective operations guide and Patarasuk & Yuan, Bandwidth Optimal All-reduce Algorithms for Clusters of Workstations (2009).
- The MFU and HFU definitions: Chowdhery et al., PaLM: Scaling Language Modeling with Pathways. The models measured are GPT-3 (arXiv) and Megatron-Turing NLG 530B.
- Dao, Fu, Ermon, Rudra, Ré, FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness (2022). The optimizer-state memory that ZeRO partitions is in Rajbhandari et al., ZeRO, explained in our ZeRO page.
How could this explainer be improved? Found an error, or something unclear? I read every message.