Training memory: model states, activations and checkpointing
Before this lesson: lesson 5 (bytes per number format, fp32 master weights), lesson 4 (FlashAttention never stores the score matrix), backpropagation, the transformer block, and Adam (two moment buffers per parameter). Time: about 70 minutes, plus the notebook.
Why this matters #
"Out of memory" is the first wall you hit when a model or a sequence grows. A 7B-parameter model trained with Adam needs 112 GB for its model states alone. That is more than one 80 GB H100 SXM (2022) holds, before a single activation is stored. Activations grow with the number of tokens in a micro-batch, and the attention part grows with .
Every parallelism choice in the next lessons is first a memory decision: data parallelism with ZeRO and FSDP shards the model states, and tensor and pipeline parallelism also split the activations. In ML for science the sequences are long. A global weather field on a 0.25° grid has million points. Even with patches this gives about 16,000 tokens per field, and then activations, not parameters, decide what fits.
1. Predict first #
2. The picture #
One linear layer #
Start with the simplest case: one linear layer . The input has rows (tokens) and columns; is . We train it with mixed-precision Adam.
- Model states belong to : the weights, their gradients and the optimizer states. With mixed-precision Adam this is 16 bytes per entry of , so bytes. The number of tokens does not appear.
- Activations belong to the data. The backward pass needs the weight gradient . So autograd keeps : bytes in bf16. It does not need to keep .
Small numbers. Take and tokens. Model states: MB. Activation: MB. Double the tokens and the activation doubles to 16.8 MB; the model states stay at 16.8 MB.
The rule: every operation keeps what its backward pass needs #
Each operation's backward formula decides what it keeps. Here are the operations of a transformer layer:
| operation | keeps | why the backward pass needs it |
|---|---|---|
| linear | its input | |
| GeLU | its input | , and needs |
| softmax | its output | with |
| dropout | its mask (1 byte per element) | the gradient passes only where the mask is 1 |
| LayerNorm | its input (and a mean and a variance per row) | the gradient depends on the normalised input |
| product of two activations, or | both factors | each factor's gradient needs the other factor |
| residual add | nothing | the gradient is copied to both branches |
Memory over one training step #
Now put these tensors on a time axis. The model states are allocated once and stay. During the forward pass, each layer adds its activations on top. At the end of the forward pass all layers' activations are in memory. The backward pass then goes through the layers in reverse order. Each layer uses its activations once and frees them. So memory rises during the forward pass, peaks when the backward pass starts, and falls during the backward pass.
Step through one training step. The grey band is the model states, the orange area is the stored activations of a 24-layer model (the 1.3B model of section 4). Press Play or drag the time slider. Notice that the peak is at the turn from forward to backward, and that the model states do not move. Switch on checkpointing to see the sawtooth that we explain in section 3.
So the peak is roughly: model states the activations of all layers the logits temporary buffers. Each term has its own fix. ZeRO and FSDP shard the model states (lesson 8). A smaller micro-batch, FlashAttention, recomputation and tensor or sequence parallelism shrink the activations.
You double the micro-batch (twice as many sequences per micro-batch). What happens to the model-state memory and to the activation memory?
Model states depend only on the number of parameters: 16 bytes each, whatever the batch. Activations are tensors of the data, one row per token, so twice the tokens means twice the activations. This is why a smaller micro-batch (with gradient accumulation) is a fix for activation memory, not for model-state memory.
3. Definitions and main results #
Notation (the same in the whole track): sequence length, micro-batch size in sequences, hidden size, attention heads, layers, vocabulary size, number of parameters. Memory is in bytes; 1 GB bytes.
Parameters: per layer #
A GPT-style layer has biases, two LayerNorms and an MLP with hidden width .
- Attention. are each with a bias of size : .
- MLP. The first matrix is with a bias of size ; the second is with a bias of size : .
- Two LayerNorms, each with a scale and a shift of size : .
Total: . The model adds the token embedding (often shared with the output layer), a final LayerNorm , and learned positions if there are any. For large , .
A Llama-style layer has no biases, uses RMSNorm (a scale only, each) and a SwiGLU MLP with three matrices of size . With the MLP has parameters, so the layer again has about . Grouped-query attention (GQA) with query heads per key/value head makes and of size . Llama 2 7B (, , , , untied embeddings) gives parameters: the "7B" of its name.
Count the parameters of one layer. Each bar is one weight matrix (or all biases and norms together), in units of . Switch between the GPT-style and the Llama-style layer, change the MLP width and the number of key/value heads, and compare the model total with . Notice that the embedding matters for small models: for the 1.3B preset, is only 92% of the total.
Model states: 16 bytes per parameter #
Mixed-precision Adam keeps five numbers per parameter (ZeRO paper, section 3.1). In the track notation the optimizer part is bytes per parameter.
| item | format | bytes per parameter |
|---|---|---|
| weights used in forward and backward | bf16 | 2 |
| gradients | bf16 | 2 |
| master weights | fp32 | 4 |
| Adam first moment | fp32 | 4 |
| Adam second moment | fp32 | 4 |
| total | 16 |
So the model states take bytes: 112 GB for 7B parameters. Lesson 5 explains why the master weights and the moments are fp32. Common variants:
- PyTorch autocast with fp32 parameters also gives 16 bytes (4 weights + 4 gradients + 8 Adam), plus short-lived bf16 copies of the weights.
- Megatron-LM with fp32 gradient buffers gives 18 bytes.
- Inference needs only the bf16 weights: 2 bytes per parameter.
A 13B-parameter model is trained with mixed-precision Adam on one GPU, without sharding. How much memory do its model states need?
GB: 2 (bf16 weights) + 2 (bf16 gradients) + 4 (fp32 master weights) + 4 + 4 (Adam moments). 26 GB is the bf16 weights only (inference), 52 GB is 4 bytes per parameter, and 156 GB counts only the 12 optimizer bytes and forgets the bf16 weights and gradients.
Activations: bytes per layer #
We use the pre-LN GPT layer of Korthikanti et al. (2022): LayerNorm, attention, dropout, residual add; LayerNorm, MLP, dropout, residual add. Inside attention, , and are split into heads. The scores of one head are an matrix.
Units. A tensor with one value per token and per hidden unit has elements; in bf16 it takes bytes. A dropout mask of the same shape takes bytes (1 byte per element). One score matrix per head and per sequence gives elements in total.
Theorem (activation memory of one transformer layer). Assume a pre-LN layer with a GeLU MLP, 16-bit activations, dropout after the softmax, after the attention projection and after the MLP, with 1-byte masks, and no FlashAttention. Then one layer keeps
Proof. List every tensor that the backward pass needs, in the order of the forward pass.
- LayerNorm 1 keeps its input, the layer input: .
- The QKV projection keeps its input, the LayerNorm output (one tensor for all three matrices): .
- keeps and : .
- The softmax keeps its output: score matrices of size per sequence, in bf16: .
- The dropout after the softmax keeps its mask: .
- The product with keeps both factors: the dropout output and .
- The output projection keeps its input ; the dropout after it keeps a mask . The attention block so far: .
- The MLP: the first linear () keeps its input ; GeLU keeps its input, which is wide: ; the second linear () keeps its input, the GeLU output: ; the dropout keeps a mask . Together .
- LayerNorm 2 keeps its input: . With LayerNorm 1 (step 1), the two norms give .
- Sum: , plus the core . Together .
Not counted: the mean and variance of each LayerNorm row (, very small) and the residual adds (they keep nothing).
| part | items | bytes |
|---|---|---|
| attention, linear in | LN1 input 2, QKV input 2, 2, 2, 2, projection input 2, mask 1 | |
| attention core, grows with | softmax output 2, dropout mask 1, dropout output 2 | |
| MLP and LN2 | LN2 input 2, fc1 input 2, GeLU input 8, fc2 input 8, mask 1 | |
| total |
Why the core grows with . Everything else has one row per token, so it grows like . The score matrices have one entry per pair of tokens, so they grow like . The ratio of the two parts is . It passes 1 when : for and , at tokens.
Walk through one layer. Press Next (or click an operation) to add the tensor it keeps. The running total in units of is orange; the magenta items are the attention core, counted in units of . The orange total reaches 34. Switch on FlashAttention: the magenta items disappear.
A layer has and , without FlashAttention. From which sequence length on does the attention core () take more memory than the rest of the layer ()?
The core is larger when , that is . At the common lengths of 2,048 to 8,192 tokens the core already dominates. 27 would come from forgetting the factor ; 4096 is the hidden size, not the answer.
What changes the count #
| setting | kept per layer | cost |
|---|---|---|
| baseline | — | |
| FlashAttention | none; usually faster | |
| selective recomputation | recompute the attention core: about 1% more FLOPs for GPT-3 | |
| full checkpointing | (the layer input) | one extra forward pass: about 33% more FLOPs |
| tensor parallelism, degree | all-reduces in every layer | |
| tensor + sequence parallelism | the same communication volume as tensor parallelism |
FlashAttention (lesson 4) never writes the matrices. It keeps the output and one fp32 log-sum-exp value per row and per head ( bytes, small), and rebuilds the scores in its backward pass. It also regenerates the dropout mask from the saved random-number state instead of storing it.
Selective activation recomputation (Korthikanti et al., section 5) keeps everything except the attention core, and recomputes the core from , and in the backward pass. It is the right part to recompute: it holds the most memory () but needs few FLOPs. Recomputing it costs the two matmuls and again, FLOPs per layer, plus elementwise work. A training step costs about FLOPs per layer, so the overhead is about . For GPT-3 (, , ) : the core is of the activations, and recomputing it costs about 0.9% more FLOPs.
Full activation checkpointing (also called gradient checkpointing or rematerialization) keeps only the input of each layer, . In the backward pass it reruns the layer's forward pass to rebuild the activations, then runs the layer's backward pass.
- Memory: for the layer inputs, plus the full activations of the one layer that is being rebuilt.
- Compute: one extra forward pass. A training step costs about FLOPs per token ( forward, backward); with checkpointing it costs , which is 33% more.
Checkpoint every layers. The yellow band is the stored segment inputs (the checkpoints; the band is thin because one checkpoint is only ); the magenta marks on the time axis are the recomputed forward passes. Move from 1 to 24 and watch the peak and the step time. Notice the sawtooth: each segment is rebuilt, then consumed by its backward pass.
Checkpoint every layers. Split the layers into segments of layers and keep only the input of each segment. In the backward pass, rebuild one segment at a time. Write for the bytes of one checkpoint and for the full activations of one layer. The peak is at the end of the first rebuild, when all checkpoints and one rebuilt segment are in memory:
The two terms pull in opposite directions. Setting the derivative to zero gives and .
- When a checkpoint costs as much as a layer's activations (), and the memory is layers instead of . This is the classic result of Chen et al. (2016) for general networks, for the price of one extra forward pass.
- In a transformer the layer input is small: against (with FlashAttention). Then , a small number: gives the lowest peak for , and for ( against ). So transformers checkpoint every layer or every few layers.
- The extra compute does not depend on : every layer is rerun once, so the cost is always one extra forward pass.
You must cut activation memory and you can recompute one part of each layer. Which part should you recompute?
Recompute what is large in memory and cheap in FLOPs. The core holds bytes, often more than half of the layer, and rebuilding it costs only two batched matmuls and elementwise work: about 1% more FLOPs for GPT-3. The MLP holds but costs 2/3 of the layer's FLOPs to rebuild. LayerNorms are cheap but hold only .
Tensor and sequence parallelism, pipeline and data parallelism
- Tensor parallelism with degree (lesson 9) splits , , , the projection input and both MLP intermediates (), and the attention core, over GPUs. The LayerNorm inputs (), the inputs of the QKV and first MLP linears () and the two dropout masks after the attention projection and the MLP () stay on every GPU. This gives .
- Sequence parallelism splits those along the sequence dimension . Then every term is divided by : . It replaces each all-reduce by a reduce-scatter and an all-gather, so the communication volume does not change.
- Pipeline parallelism with stages and the 1F1B schedule: the first stage holds micro-batches of layers, which is still layers' worth of activations (Korthikanti et al., section 4.2.3).
- Data parallelism and ZeRO do not change the activations. Every GPU still runs whole layers on its own micro-batch. ZeRO divides only the model states (lesson 8).
The logits #
The output layer turns hidden vectors into rows of scores, the logits. The loss is computed in fp32, so the logits take bytes (Korthikanti et al., section 4.3). For a large vocabulary this is large: with , and it is 3.3 GB. During the backward pass of the loss, the gradient of the logits has the same size for a short time.
Does it fit, and what is the cheapest fix? #
Keep 10–20% of the GPU memory free for temporary buffers, communication buffers and fragmentation (free memory split into pieces too small to use). The ZeRO paper (section 3.2) reports out-of-memory errors with more than 30% of memory still free in extreme cases.
Does it fit? The stacked bar is the memory of one GPU: weights (blue), gradients (yellow), optimizer states (violet), activations (orange) and logits (magenta). The solid line is the GPU's memory; the dashed line leaves 15% free. Start with the 1.3B preset without FlashAttention, then try the fixes in the list below. Notice which fixes change the orange part and which change nothing.
If it does not fit, estimate the time cost of each fix and take the cheapest one:
- FlashAttention (or selective recomputation): almost free.
- ZeRO-1 or ZeRO-2, if there is data parallelism: the same communication volume as plain data parallelism (lesson 8).
- A smaller micro-batch with gradient accumulation: free until the matmuls get too few tokens and become memory-bound (lesson 2).
- Full checkpointing (+33% FLOPs) or ZeRO-3 / FSDP (1.5× the communication of plain data parallelism): choose by whether the step is limited by compute or by communication.
- Tensor + sequence parallelism inside a node: divides model states and activations by , but adds communication in every layer; then pipeline parallelism across nodes.
- Offload to CPU memory: the last resort, because the CPU link is slow.
The 1.3B model of section 4 needs 116 GB on one 80 GB GPU: 21.0 GB model states, 91.8 GB activations (no FlashAttention) and 3.3 GB logits. Which single fix is the cheapest one that makes it fit?
FlashAttention removes the core: activations fall from 91.8 to 27.4 GB, and the total to 51.7 GB, at no extra cost. Full checkpointing also fits but costs 33% more FLOPs. Plain data parallelism does not help: every GPU keeps a full copy of the model states and its own activations. Offloading the optimizer saves only 15.7 GB (not enough) and is slow.
Answers to section 1. (1) 21 GB: 16 bytes per parameter, GB. 2.6 GB is the bf16 weights only. (2) It grows. The part depends only on the product , so it stays the same. The core doubles, because each token now attends to twice as many tokens. (3) At the start of the backward pass. At that moment all layers' activations (and the logits) are in memory; the backward pass then frees them layer by layer.
4. Worked example #
A 1.3B GPT-style model: , , , , , . Training in bf16 with mixed-precision Adam, rotary positions (no learned position table). One GPU with 80 GB.
Step 1: parameters.
- Per layer: .
- 24 layers: .
- Embedding (shared with the output layer): . Final LayerNorm: .
- Total: $\Psi = 1{,}311{,}528{,}960 \approx 1.31$B. Here is only 92% of : at this size the embedding matters.
Step 2: model states. GB.
Step 3: activations.
- , and .
- Per layer: GB.
- 24 layers: GB. The attention core is of it.
Step 4: logits. GB.
Step 5: total. GB. It does not fit on an 80 GB GPU.
Step 6: fix 1, FlashAttention. Activations GB. Total GB. It fits, with 28 GB free (35%).
Step 7: full checkpointing on top. Layer inputs GB, plus one rebuilt layer GB. Total GB, for 33% more FLOPs. It is not needed at , but it allows a larger micro-batch.
Step 8: the largest micro-batch. Keep 15% free, so the budget is GB, and GB is left after the model states. Activations and logits grow with . Per sequence ():
- FlashAttention only: GB, so .
- FlashAttention and full checkpointing: GB, so . Now the logits take more memory than the activations.
Step 9: what if we had 8 GPUs of 40 GB with data parallelism? Plain data parallelism still needs 51.7 GB per GPU: it does not fit. ZeRO-2 (lesson 8) keeps GB of model states per GPU, so GB. It fits, with only 4.4 GB (11%) free. Halving the micro-batch to (two accumulation steps, same global batch) gives GB.
5. In code #
The first block checks the worked example with the formulas of section 3. NumPy only.
import numpy as np
def params_gpt(L, h, V):
return L * (12 * h * h + 13 * h) + V * h + 2 * h # shared embedding, final LayerNorm
def act_per_layer(s, b, h, a, flash=False):
return s * b * h * 34 + (0 if flash else 5 * a * s * s * b)
L, h, a, V, s, b = 24, 2048, 16, 50257, 2048, 8
psi = params_gpt(L, h, V)
states, logits = 16 * psi, 4 * s * b * V
for flash in (False, True):
act = L * act_per_layer(s, b, h, a, flash)
print(f"flash={flash}: states {states/1e9:.1f} + act {act/1e9:.1f} + logits {logits/1e9:.1f}"
f" = {(states + act + logits)/1e9:.1f} GB")
print(psi, round(12 * L * h * h / psi, 3))
# flash=False: states 21.0 + act 91.8 + logits 3.3 = 116.1 GB
# flash=True: states 21.0 + act 27.4 + logits 3.3 = 51.7 GB
# 1311528960 0.921
The second block lets PyTorch report what autograd keeps. A saved-tensors hook sees every tensor that is saved for the backward pass; we add up their bytes (without the parameters) for one layer in bf16, on the CPU. You do not need to run it; it shows that the theorem matches a real framework.
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.checkpoint import checkpoint
s, b, h, a, p = 256, 2, 256, 4, 0.1 # sequence, micro-batch, hidden, heads, dropout
class GPTLayer(nn.Module): # pre-LN, 4h GeLU MLP, three dropouts
def __init__(self, flash=False):
super().__init__()
self.flash = flash
self.ln1, self.ln2 = nn.LayerNorm(h), nn.LayerNorm(h)
self.qkv, self.proj = nn.Linear(h, 3 * h), nn.Linear(h, h)
self.fc1, self.fc2 = nn.Linear(h, 4 * h), nn.Linear(4 * h, h)
def forward(self, x): # x: (s, b, h)
drop = lambda t: torch.native_dropout(t, p, True)[0] # 1-byte mask, as on a GPU
q, k, v = self.qkv(self.ln1(x)).split(h, dim=-1)
q, k, v = [t.reshape(s, b * a, h // a).transpose(0, 1) for t in (q, k, v)]
if self.flash: # fused attention: no s x s tensor is kept
o = F.scaled_dot_product_attention(q, k, v) # (attention dropout off here)
else:
o = drop(torch.softmax(q @ k.transpose(1, 2) / (h // a) ** 0.5, dim=-1)) @ v
x = x + drop(self.proj(o.transpose(0, 1).reshape(s, b, h)))
return x + drop(self.fc2(F.gelu(self.fc1(self.ln2(x)))))
def saved_bytes(layer, x, ckpt=False):
"""Bytes of the tensors autograd saves for backward (parameters not counted)."""
params = {w.untyped_storage().data_ptr() for w in layer.parameters()}
seen = {}
def pack(t):
st = t.untyped_storage()
if st.data_ptr() not in params:
seen[st.data_ptr()] = st.nbytes()
return t
with torch.autograd.graph.saved_tensors_hooks(pack, lambda t: t):
checkpoint(layer, x, use_reentrant=False) if ckpt else layer(x)
return sum(seen.values())
torch.manual_seed(0)
x = torch.randn(s, b, h, dtype=torch.bfloat16, requires_grad=True)
for flash, ckpt, predicted in [(False, False, 54), (True, False, 34), (False, True, 2)]:
layer = GPTLayer(flash).to(torch.bfloat16)
print(f"flash={flash}, checkpoint={ckpt}: {saved_bytes(layer, x, ckpt) / (s * b * h):.2f} sbh"
f" (predicted {predicted})")
print(sum(w.numel() for w in layer.parameters()), 12 * h * h + 13 * h)
# flash=False, checkpoint=False: 54.03 sbh (predicted 54)
# flash=True, checkpoint=False: 34.09 sbh (predicted 34)
# flash=False, checkpoint=True: 2.00 sbh (predicted 2)
# 789760 789760
Here , so the theorem predicts . The small extras
are the LayerNorm statistics and, with fused attention, the fp32 log-sum-exp per row.
torch.native_dropout keeps a 1-byte mask, like the fused GPU dropout; F.dropout on the CPU
keeps a mask in the activation's format and would add more.
6. Where it shows up #
- LLM training. Before a run, teams do this sum to choose the micro-batch, the recomputation
policy (
torch.utils.checkpoint, Megatron-LM's--recompute-granularity selectiveorfull) and the ZeRO or FSDP stage. After the run starts, they measure withtorch.cuda.max_memory_allocated()or a memory snapshot. - Long context. At , , , : , far above 34, so FlashAttention is required. Even is 4.6 GB per layer, 146 GB for 32 layers. This needs checkpointing or context parallelism (lesson 10).
- ML for science. Weather, climate and seismic models have long token sequences and large
activations but a moderate number of parameters. For them FlashAttention, checkpointing and
sequence sharding matter more than ZeRO. Physics-informed losses that call autograd with
create_graph=Truealso keep the graph of the first backward pass, so the activation memory grows further. - Fine-tuning. With LoRA the base weights are frozen: they need no gradients and no Adam states. The model states drop to about 2 bytes per frozen parameter, but the activations stay the same, so checkpointing is still common.
7. Common mistakes #
- 2 bytes per parameter for training. That is inference. Training with mixed-precision Adam needs 16.
- Expecting data parallelism or ZeRO to cut activation memory. They only divide model states.
- Using for another kind of layer. A Llama-style layer (no dropout, SwiGLU, RMSNorm) needs its own count, tensor by tensor.
- Forgetting the logits (, large for big vocabularies), the layer that is being rebuilt during checkpointing, and fragmentation.
- Thinking checkpointing is free. It costs about a third more FLOPs. It raises the hardware FLOPs utilization, not the model FLOPs utilization (lesson 13).
- Mixing GB () and GiB (). They differ by 7%. GPU tools often print GiB.
8. Check yourself #
- How many parameters does one GPT-style layer with have ( MLP, biases)?
Answer
. - At least how many 80 GB GPUs are needed just to hold the model states of a 70B model trained
with mixed-precision Adam, fully sharded?
Answer
TB, and GPUs. In practice you need more, for activations and buffers. - Which of the layer does tensor parallelism not split, and why?
Answer
The two LayerNorm inputs (), the inputs of the QKV and the first MLP linear (), and the two dropout masks after the attention projection and the MLP (). They lie outside the regions that tensor parallelism splits, so every GPU holds the full tensor. Sequence parallelism splits them along . - The same layer without any dropout: how many bytes per layer?
Answer
. The three masks go ( and ). The softmax output now feeds both the softmax backward and the product with , so it is stored once and the separate dropout output () goes too. - Why is selective recomputation almost as good as FlashAttention for memory, and why is it cheap?
Answer
Both remove the core and keep . Rebuilding the core needs only , , and few FLOPs: two batched matmuls () and elementwise work, against for the large linear layers over a training step. For GPT-3 this is about 1%. - You checkpoint a 24-layer transformer every layers, with FlashAttention. Using
and , what is the activation peak in units of , and is better?
Answer
. . So is much better: .
How many bytes per parameter does mixed-precision Adam need, and how do they split?
16: bf16 weights 2, bf16 gradients 2, fp32 master weights 4, fp32 Adam moments and 4 each.
How many parameters does a GPT-style transformer layer with a MLP and biases have?
: attention , MLP , two LayerNorms .
What is the activation memory of one transformer layer without FlashAttention (Korthikanti et al.)?
bytes, that is .
Why does the attention core of the activations grow with ?
The softmax output, its dropout mask and the dropout output have one entry per pair of tokens: matrices of size per sequence.
What does FlashAttention remove from the activation memory?
The attention core. It keeps the output and one log-sum-exp per row and rebuilds the scores in the backward pass, so about remain.
What does full activation checkpointing cost and save?
It keeps only each layer's input () and reruns the forward pass in backward: instead of FLOPs per token, about 33% more.
When during a training step is memory highest, and why?
At the start of the backward pass: all layers' activations are stored, and the backward pass then frees them layer by layer.
With checkpoints every layers, what is the peak and the best ?
, minimal at . With this is (Chen et al.); for transformers , so is 1 to 3.
How much memory do the logits of the loss take?
bytes, because the loss is computed in fp32. For , , : 3.3 GB.
9. Interview angle #
- "How much memory does it take to train a 7B model with Adam?" — 16 bytes per parameter: 112 GB of model states before activations. So you need ZeRO, FSDP or tensor parallelism even on 80 GB GPUs.
- "What does activation checkpointing cost?" — One extra forward pass, about 33% more FLOPs. It keeps per layer instead of or more.
- "Why does FlashAttention save memory, not only time?" — It never stores the matrices; it rebuilds them in the backward pass.
- "Out of memory at step 1, or after hours?" — At step 1: the estimate is wrong (logits, the
micro-batch, recomputation off). After hours: fragmentation, a longer batch than usual, or a
leak, such as keeping
losstensors with their graph in a Python list.
10. Practice #
The notebook for this lesson runs in Colab, with NumPy only. It has five exercises, each with a check cell and a folded solution:
params_per_layer(h, mlp_ratio, n_kv_ratio, style)and the model total, checked against GPT-2, the 1.3B model and Llama 2 7B and 70B.model_state_bytes(psi, K), and the GPU count for a few model sizes.activation_bytes(s, b, h, a, mode)for the baseline, FlashAttention, selective recomputation and full checkpointing, checked against a tensor-by-tensor list.- A memory-timeline simulator for one step with checkpoints every layers; find the that minimises the peak and compare it with .
cheapest_fix(...): try the fixes of section 3 in order and return the first one that fits.
11. Watch and read #
- Korthikanti et al. (2022), Reducing Activation Recomputation in Large Transformer Models: section 4.1 (the per-layer count), 4.2 (tensor, sequence and pipeline parallelism), 4.3 (logits), 5 (selective recomputation).
- Chen et al. (2016), Training Deep Nets with Sublinear Memory Cost: checkpointing with memory.
- Rajbhandari et al. (2019), ZeRO: Memory Optimizations Toward Training Trillion Parameter Models: section 3.1 (model states, 16 bytes per parameter), 3.2 (activations, buffers, fragmentation).
- Austin et al., How to Scale Your Model, All the Transformer Math You Need to Know: parameter and FLOP counts, and gradient checkpointing.
- EleutherAI, Transformer Math 101: memory and compute rules of thumb for training.
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.