What the backward pass costs, in arithmetic and in memory
complexity▲▲△GFLOP to two decimals, GB to three, at 4 bytes per fp32 value.
STATEMENT
Account for both resources a backward pass consumes. Show that the arithmetic is a small multiple of the forward pass and that the memory is not, find the batch size at which stored activations overtake parameters, and quantify what checkpointing buys.
GIVEN
A stack of square affine layers of width , in fp32. Two working regimes: a batch of 32 rows, and a batch of 32 sequences of length 512, which presents rows to every layer.
FIND
Forward and backward FLOPs and their ratio; activation memory against parameter memory in both regimes; the batch at which the two are equal; and the memory and arithmetic under checkpointing.
STRATEGY
Count matrix products, since everything else is lower order. Forward, each layer does one. Backward, by (I.6.3) and (I.6.4), each layer does two — one to send the adjoint onward and one to form the weight gradient. For memory, count what the backward pass will read and cannot recompute for free.
SOLUTION
Step 1 — arithmetic. A product of a matrix with a matrix costs floating-point operations, counting a multiply and an add for each of the pairs. Forward:
Backward does two such products per layer, so , and the step costs :
| regime | forward | backward | total / forward |
|---|---|---|---|
| batch 32 | GFLOP | GFLOP | |
| batch | GFLOP | GFLOP |
The ratio is 3 in both regimes and would be 3 for any , and : it is a property of the graph, not of the size. This is the cheap gradient principle (I.6.T1) at work, and the constant here — three — sits comfortably inside the the theorem allows.
Step 2 — memory. The parameters are values, GB. The activations kept for the backward pass are by (I.6.7):
| regime | activations | parameters | ratio |
|---|---|---|---|
| batch 32 | GB | GB | |
| batch | GB | GB |
The same model, the same weights, the same arithmetic per row — and the memory picture inverts completely. At batch 32 the parameters dominate by thirty times; at batch 16 384 the activations dominate by sixteen.
Step 3 — the crossover. Setting gives
The layer count cancels, and so does everything else. Activations overtake parameters when the batch reaches the width, which for this model is 1024 rows — a number a single sequence of moderate length already exceeds. That is why the second regime is the normal one and the first is the exception.
Step 4 — checkpointing. Keep every -th activation and recompute the rest during the backward pass. With , : hold 7 segment boundaries, plus the 6 tensors of whichever segment is currently being recomputed, so 13 tensors instead of 48.
The price is recomputing each segment’s forward pass once, which adds one forward pass to a step that cost three:
A third more arithmetic for nearly four times less memory. On a device where memory is the binding constraint and arithmetic is not — which describes most training — that is not a close decision.
Answer
Arithmetic: backward is exactly twice forward, so a step costs a forward pass, independent of , and .
Memory: activations are and parameters , so they are equal when . At batch 32 activations are the parameters; at batch they are — GB against GB.
Checkpointing at 7 segments holds 13 tensors instead of 48: GB becomes GB, a reduction, for the arithmetic.
Check — sanity
The FLOP ratio is exactly 3 in both regimes. It has to be — it is a count of matrix products per layer, one forward and two back, and no dimension enters it. A measured ratio far from 3 on real hardware is a statement about memory bandwidth and kernel efficiency, not about the arithmetic.
The crossover has no free parameters. reduces to with cancelling, so the answer cannot depend on depth. A deeper model has more activations and more parameters, in the same proportion.
Checkpointed memory is near . against the 13 tensors counted, and matches the measured reduction. The of (I.6.7) is where boundary storage and segment storage balance; away from it, one term or the other grows.
Where this breaks
Every number here counts one thing each and ignores the rest of the bill. The gradient buffer is another copy of the parameters, and Adam adds two more, so the parameter side of the ledger is nearer GB than GB before any activation is stored — a point I.7 makes properly. Workspace for the matrix kernels, fragmentation and the framework’s own overhead are all real and none is counted.
The FLOP count is also not a time. It assumes every operation costs the same, which on a device with a hundred times more arithmetic throughput than memory bandwidth is badly wrong: the backward pass touches more memory per FLOP than the forward pass and is routinely slower than the its arithmetic suggests. The is a lower bound on the time ratio and an exact statement about the arithmetic, and confusing the two is how a training run comes in over its estimate.
Finally, checkpointing assumes recomputation is deterministic. A segment containing dropout, or any other sampling, recomputes a different forward pass unless the random state is stored and restored — and the gradient then belongs to neither the first forward pass nor the second.
Variation
Recompute the crossover for a model whose layers are not square: width in and out, as a transformer’s feed-forward block is. The parameter count gains a factor of 4 and the stored activation gains one too. Does the crossover move?