← All posts

Model development

Post 8 of 26

GPU memory and compute: what training stores, computes and waits for

Posts in this series · 26

The scaling-laws post turned a training run into a number of FLOPs. This post turns that number into hardware: how much memory the run needs, how long it takes, and why a GPU that advertises nearly a thousand trillion operations per second often delivers far fewer. Everything in the rest of this track, data parallelism, sharding, model parallelism, efficient kernels, is an answer to one of the limits we meet here.

We use the NVIDIA H100 as the running example, with the figures CS336’s resource-accounting lecture uses: 989.5 trillion BF16 operations per second without sparsity, 3.35 TB/s of memory bandwidth and 80 GB of memory (CS336 lecture 2).

What training keeps in memory

Training memory has four parts:

  1. Weights, used in the forward and backward pass.
  2. Gradients, one per weight, produced by the backward pass.
  3. Optimizer state: for AdamW, the two moving averages mm and vv from the first post, one of each per weight.
  4. Activations: the intermediate values of the forward pass that the backward pass needs.

The first three scale with the number of parameters NN. In mixed-precision training, weights and gradients are usually kept in 16-bit BF16 (2 bytes each), and the optimizer moments in 32-bit FP32 (4 bytes each), because they accumulate many small updates. That makes 12 bytes per parameter, the count CS336 uses.

Many large-scale systems also keep an FP32 master copy of the weights, apply the update to it, and cast it down to BF16 for the next step. That adds 4 bytes, for 16 bytes per parameter, the count used in the ZeRO paper (ZeRO, §3.1). The reason for the master copy is that BF16 cannot hold small updates: it keeps only 8 significant bits, so near 1.0 the next representable number is 1.0078, and adding 0.001 to a BF16 weight of 1.0 leaves it at exactly 1.0. The small training run demonstrates this. Both conventions are in use; which one a framework follows is a configuration choice, and it changes the memory bill by a third.

At 16 bytes per parameter, a 7-billion-parameter model needs 112 GB for weights, gradients and optimizer state alone. It does not fit on one 80 GB GPU before a single activation is stored. That is the problem the sharding post solves.

Activations

Activations do not depend on the number of parameters but on how much text is in flight: batch size bb, sequence length ss, width hh and number of attention heads aa. Korthikanti et al. counted them for a GPT-style Transformer layer in 16-bit precision, without recomputation (Korthikanti et al., 2022, §4.1, Eq. 1):

activation bytes per layer=s b h(34+5 a sh).\text{activation bytes per layer} = s\,b\,h\left(34 + \frac{5\,a\,s}{h}\right).

With h=4,096h = 4{,}096, a=32a = 32, s=4,096s = 4{,}096 and b=1b = 1: the first term is 0.57 GB, the attention term 2.68 GB, together 3.25 GB per layer and about 104 GB for 32 layers, for a single sequence. The attention term grows with the square of the sequence length; at s=1,024s = 1{,}024 the whole layer needs only 0.31 GB. Modern blocks differ in the constants (no dropout, SwiGLU instead of GeLU), but not in this shape. Long sequences make the attention scores the dominant cost, which is why the efficient-execution post is largely about not storing them.

How long training takes

Training time is FLOPs divided by the FLOPs you actually achieve:

time=6NDGPUs×peak FLOP/s×MFU.\text{time} = \frac{6 N D}{\text{GPUs} \times \text{peak FLOP/s} \times \text{MFU}} .

Model FLOPs utilization (MFU) is the fraction of peak that goes into the model’s own arithmetic; communication, waiting for memory and recomputation all lower it. CS336’s lecture works a concrete case: a 70-billion-parameter model on 15 trillion tokens needs 6×7×1010×1.5×1013=6.3×10246 \times 7 \times 10^{10} \times 1.5 \times 10^{13} = 6.3 \times 10^{24} FLOPs. On 1,024 H100s at 50% MFU, that is about 144 days. The lecture calls an MFU of 50% or more “quite good”. Every percentage point is worth roughly a day and a half of this run.

Compute-bound or memory-bound

Why is MFU not close to 100%? A GPU must move data from memory before it can compute on it. Each operation has an arithmetic intensity: FLOPs performed per byte moved. The H100 can do 989.5×1012/3.35×1012≈989.5 \times 10^{12} / 3.35 \times 10^{12} \approx 295 FLOPs per byte at full speed. An operation with lower intensity than that waits for memory; one with higher intensity is limited by arithmetic.

Three examples in BF16, with n=1,024n = 1{,}024 (CS336 lecture 2):

Training spends most FLOPs in large matrix multiplications, so it can approach the compute limit. The elementwise operations around them (norms, activations, residual additions) are memory-bound, which is why fusing them into fewer kernels helps. Generating text one token at a time is mostly matrix-times-vector work, which is why inference is usually memory-bound; the inference post builds on this.

Everyday picture: a chef (the arithmetic units) and a single narrow pantry door (memory bandwidth). Making a big stew from a few bulk ingredients keeps the chef busy; plating hundreds of garnishes, each fetched separately, leaves the chef waiting at the door.

Try it: will it fit? You want to fine-tune the 1.24-billion-parameter model from the architecture post (16 layers, width 2,048, 32 heads) with AdamW on a single 24 GB GPU, at sequence length 1,024 and batch size 1. Does it fit?

Answer. State: 16×1.24≈19.816 \times 1.24 \approx 19.8 GB with FP32 master weights, or 12×1.24≈14.912 \times 1.24 \approx 14.9 GB without, leaving 4.2 or 9.1 GB. Activations with the GPT-style formula: 1,024×2,048×341{,}024 \times 2{,}048 \times 34 bytes plus 5×32×1,02425 \times 32 \times 1{,}024^2 bytes, about 239 MB per layer, 3.8 GB for 16 layers. So it fits tightly with master weights and comfortably without, before temporary buffers and the logits for a 128,000-token vocabulary (about 0.26 GB per sequence in BF16), which may tip the tight case over. Doubling the sequence length would more than double the activations and break the tight case; recomputation or a smaller batch would bring it back.

Diagnosing the two limits

What to remember

Sources

Further reading