Most AI programs today, from a photo app that spots faces to a chatbot, are . Inside, it’s a giant pile of numbers. Answering one question means multiplying and adding those numbers billions of times.
So an AI chip needs two kinds of speed. It needs fast math. It also needs to fetch numbers from its memory fast, because the math can’t start until the numbers arrive. A chip can run short of either one.
AI jobs are the same. Some keep the chef busy, and some leave the chef waiting. This chapter shows which is which, using a simple chart called a roofline.
A is a sequence of layers, and almost every layer comes down to one operation: . Even , the layer that made today’s language models possible, is mostly two matrix multiplications.2 So an AI chip is, first of all, a machine for multiplying matrices.
Doing the arithmetic is only half of the job. The numbers have to be fetched from memory first, and a chip can do arithmetic far faster than it can fetch. Whether a given job is limited by arithmetic or by fetching depends on one ratio: how many operations it does for each byte it moves. That ratio is called , and the turns it into a picture of how fast the job can possibly run on a given chip.1
This chapter builds the vocabulary the AI chapters of this guide use:
- How to count the work in a matrix multiplication and in attention.
- How to count the bytes, and so the arithmetic intensity.
- The roofline: peak compute, memory bandwidth, and the ridge point where they meet.
- Why training, and the two phases of running a language model (reading the prompt and writing the reply), land in very different places on that chart.
You know a runs mostly on matrix multiplication. To reason about hardware for it, you need two counts for every operation: the FLOPs it performs and the bytes it must move to and from off-chip memory. Their ratio, the , placed on a next to the chip’s peak compute and bandwidth, bounds the performance any implementation can reach.1
This chapter derives those counts for the operations that matter and applies them:
- intensity as a function of , , and bytes per value, and why it is set by the smallest dimension.
- Attention’s quadratic FLOPs and traffic, fused and unfused.
- Why is compute-bound and is memory-bound, and how batch size and the move decode on the chart.
- Training’s FLOPs per token and 16 bytes per parameter of state, against inference’s and latency limits.
- Where the roofline bound is loose: ceilings, latency, quantization effects and multiple memory levels.
The AI chapters that follow assume this vocabulary. Number formats change the bytes per value (Number formats); GPUs, systolic arrays and spatial meshes are different ways to raise on-chip reuse; and The memory wall follows decode’s bandwidth problem down to HBM.
Pick a workload. The chip has 400 TFLOP/s of math and 2 TB/s of memory bandwidth.
A neural network is built in layers. Each layer takes in a list of numbers, say, describing a word or a patch of a photo. It turns that list into a new list.
To make each new number, the layer multiplies every input by a number it learned, called a . Then it adds up all the results. Do that for a whole stack of inputs at once and you get a : one grid of numbers times another.
The amount of math is huge. One well-known image model does about 4 billion multiplications just to look at one photo.10 The good news is that it’s the same simple step, over and over. So a chip can pack thousands of tiny multipliers side by side.
A matrix is a grid of numbers. Multiplying an matrix by a matrix gives an matrix . Each entry of is a dot product: pairs of numbers multiplied together and summed. So the whole product takes multiplications and as many additions.19 The combined step “multiply, then add to a running total” is a , and it counts as two .
Why does a neural network reduce to this? Take the basic building block, a fully connected layer:
- It has inputs and outputs, and one weight for every input-output pair: a weight matrix.
- One input vector times that matrix gives one output vector: MACs.
- Stack inputs ( images, or words of a sentence) as rows of a matrix, and the whole layer becomes one by matrix multiplication.9
The other common layers follow. A , the workhorse of image networks, slides small filters across an image; libraries rearrange the image patches into a matrix so the whole layer becomes a single matrix multiplication.8 The layers of a , the design behind language models, are matrix multiplications too, as the next section shows.2
The numbers get large quickly. ResNet-50, a standard image model, needs about 3.9 billion MACs and 25.5 million weights to classify one image.9 A language model needs about 2 FLOPs per weight for every (word piece) it processes, so a 7-billion-parameter model does about 14 billion FLOPs per token.3
Libraries call a general matrix multiplication a GEMM, and this guide uses that name too.
For with , , the work is MACs, or FLOPs.19 The layers map onto it as follows:
- Fully connected / linear: , = input features, = output features. With one input vector () it degenerates to a matrix-vector product (GEMV).9
- Convolution: lowered (im2col) to a filter matrix times a data matrix, where is input channels, the filter, output channels and the batch times output pixels. The price is duplicating each input up to times, which lowers intensity unless the lowering is done on the fly.8
- Transformer block: the , , and output projections ( weights per layer) and the two MLP matrices (), giving parameters with ; plus the activation-by-activation products and inside attention.3
Kaplan et al.’s count gives a forward pass of about FLOPs per token; the second term is attention over the context, and it is small while .3 For a 6.7B model with width 4,096 and 32 layers16, that crossover is at a context of about 49,000 tokens, so at ordinary lengths the weight GEMMs dominate the FLOPs.
That FLOP share is not the time share. In BERT training on GPUs, tensor contractions were 99.80% of the FLOPs but 61.0% of the runtime; normalization (0.17% of FLOPs) took 25.5% and elementwise operations (0.03%) took 13.5%.7 The reason is bytes, not FLOPs, and that is what the rest of the chapter is about.
M × N × K = 3 × 5 × 6 = 90 MACs, or 180 FLOPs. Tap an output to see its dot product.
Chatbots use a step called . In “The cat sat on the mat because it was tired,” attention is how the model works out that “it” means the cat.
It compares every word with every other word and scores how closely they’re linked. That comparing is more grid multiplication.2
Here’s the catch. Double the text, and there are four times as many pairs of words to compare. Long documents get expensive fast.
To save work, a chatbot keeps notes on every word it has already read, called the . The notes save math. But the chip has to read through them again for every new word it writes.
A represents each token as a vector of numbers (4,096 of them in a 7-billion-parameter model16). An attention layer lets every token gather information from the others in three steps:2
- Project. Multiply each token’s vector by three weight matrices to get a query (what this token is looking for), a key (what it offers) and a value (what it passes on). These are ordinary matrix multiplications.
- Score. Multiply every query by every key: a matrix multiplication of the queries () by the transposed keys (), where is the number of tokens and the vector length. The result is an table of scores. A function called softmax turns each row into weights that add up to 1.
- Mix. Multiply that table of weights by the values (): each token’s output is a weighted mix of every token’s value.
Real models run several of these in parallel (multi-head attention), each on a slice of the vector, and follow every attention layer with a feed-forward layer of two more matrix multiplications.2
Steps 2 and 3 cost work proportional to , so doubling the text length quadruples them.2 Standard implementations also write the table out to memory and read it back, which makes the bytes grow as too.5
When a model writes text, each new token needs its own query but attends to the keys and values of all the tokens before it. Recomputing those every time would be wasteful, so they are stored: the . It saves arithmetic but has to be read in full for every new token, and it grows with both the length of the text and the number of users being served.4
Per head, with sequence length and head dimension : ; ; row-wise; .2 Across heads with :
- Projections: weights per layer (, , , output), 2 FLOPs per weight per token. GEMMs with = tokens.
- and : FLOPs each, so per layer without masking; a causal mask lets a kernel skip about half. Both operands are activations, so there is no weight reuse to amortize, and the inner dimension of is .
- Softmax, scaling, masking: a few operations per score, but over scores; memory-bound reductions and elementwise ops.5
The textbook kernel sequence writes and to HBM, giving HBM accesses per head. FlashAttention tiles , and through on-chip SRAM and recomputes the softmax normalization incrementally, so the matrices never leave the chip; it reports up to 7.6× faster attention on GPT-2.5 In roofline terms, fusion moves attention from the slope to the flat roof without changing its FLOPs (the Try it sim has a toggle for this).
During decode, a step processes one new query per sequence against cached keys and values per layer. The FLOPs are per layer per token, but the KV cache must be streamed in for every step. Shazeer’s analysis puts the ratio of memory traffic to arithmetic for incremental multi-head attention at , with the context and the batch, and says both terms must be made small; a larger batch shrinks only the second.12 Multi-query attention (one shared K/V head) and grouped-query attention (a few) shrink the first.1213
8 tokens give an 8 × 8 table of 64 scores. Halve S and it is 16: the work grows as S².
Here’s the key question for any AI job: how much math does it do for each number it fetches? Chip designers call this the .
Grid multiplication scores high. In a big grid multiply, each number fetched gets used in a thousand multiplications. The chef gets lots of chopping out of each delivery.
Simple steps score low. Some steps do one tiny thing to each number, like turning negative numbers into zero. One delivery, one chop, then wait.
A chip with super-fast math but slow memory races through the first kind of job. It crawls through the second. That’s why designers work as hard on memory as on math.
is the number of operations a job does divided by the number of bytes it moves to or from off-chip memory, in FLOPs per byte.1 Bytes depend on the number format: a 16-bit number is 2 bytes, an 8-bit one is 1 (see Number formats). Two examples, both in 16-bit:
| Job | Operations | Bytes moved | Intensity |
|---|---|---|---|
| Multiply two 1,000 × 1,000 matrices | MACs = FLOPs | read and , write : | about 333 FLOP/B |
| Replace negatives with zero (ReLU) in numbers | operations | read and write numbers: | 0.25 FLOP/B |
That is a factor of more than a thousand between two jobs that look equally simple on paper. NVIDIA’s performance guide lists the same ReLU figure of 0.25, and puts layer normalization below 10.18
Why is matrix multiplication so favorable? Because the work grows faster than the data. Multiply two matrices and the work grows as while the data grows as , so each number is reused about times. Double and the intensity doubles.19 A matrix multiplication with one very thin side does not get that benefit: if one input is a single vector, each weight is used just once, and the intensity falls to about 1 FLOP per byte.19 NVIDIA’s example is a layer with 1,024 inputs and 4,096 outputs: 315 FLOP/B when 512 inputs are processed together, 1 FLOP/B for a single input.18
The bytes that count are the ones crossing between the chip and its main memory, not the ones moving inside the chip. A chip with more on-chip memory, used well, can keep data on the chip longer and so raise a job’s intensity.1 That matters for energy too: fetching a value from off-chip costs roughly 200 times the energy of fetching it from a tiny register next to the multiplier.9
Define intensity , with the FLOPs and the bytes moved between the chip and the memory level you are analyzing, normally off-chip DRAM or HBM. Williams et al. call this operational intensity and count traffic after it has been filtered by the caches, so that cache and tiling optimizations show up as a higher .1
For a GEMM with bytes per value and each operand read once and the result written once:19
- Square, : . At , an GEMM gives 2,731 FLOP/B; NVIDIA’s guide reports 2,730.19
- Skinny: if , the term dominates the bytes and . NVIDIA’s example gives 124.1 FLOP/B.19 Intensity is set by the smallest dimension.
- GEMV (): , about 1 FLOP/B at 16 bits. Always memory-bound on any accelerator.19
For a weight GEMM, the dimension that sets intensity is usually the number of tokens processed together: batch × sequence length. That one fact explains most of the chapter: large-batch training and prefill have thousands of tokens per GEMM; decode has one per sequence.
The formula assumes ideal reuse. Real kernels reach it only if a tile of the output and the matching panels of the inputs fit on chip (derivation in Under the hood). Lowering a convolution through im2col, or writing intermediates between unfused kernels, adds traffic and lowers the intensity actually achieved.85 Operations with no reuse, such as and reductions, sit at or below 1 FLOP/B, which is why they took 39% of BERT’s training time for 0.2% of its FLOPs.7
64³ multiply: 524,288 FLOPs for 24,576 bytes, 21.3 FLOP/B. Work grows as n³, data as n², so intensity grows with n.
Now draw both limits on one chart. It shows how fast a job can run for each amount of math per number fetched.
The chip’s math speed makes a flat ceiling. Nothing can go faster than that. The memory limit makes a sloping line, because a job that does little math per number can only go as fast as numbers arrive. Together they look like the roof of a house, so the chart is called a .1
The bend in the roof is the tipping point. Jobs to its left are waiting on memory. Jobs to its right are limited by math.
The , introduced by Samuel Williams, Andrew Waterman and David Patterson at Berkeley in 2008, puts a chip’s two limits on one log-log chart.1
- Horizontal axis: arithmetic intensity, in FLOPs per byte.
- Vertical axis: attainable performance, in FLOP/s.
- The flat roof: the chip’s peak compute. Nothing goes faster.
- The slanted roof: times intensity. A job moving data at the full memory speed can only do as many FLOPs per second as its intensity allows.
The bound is a single line:
1 The two lines meet at the , at an intensity of peak ÷ bandwidth. A job to the left of it is ; to the right, .1
A worked example with a made-up chip: 400 TFLOP/s of peak compute ( FLOPs per second) and 2 TB/s of bandwidth. Its ridge point is FLOP/B.
- The 1,000 × 1,000 matrix multiply (333 FLOP/B) is right of the ridge: it can reach the full 400 TFLOP/s.
- The ReLU (0.25 FLOP/B) can reach only : about a thousandth of the chip’s math is in use.
The chart is drawn once per chip and reused for every job. It also tells you what to fix: for a memory-bound job, more math hardware is useless; raise its intensity or the bandwidth instead.1 The same chart describes the first Google TPU, whose authors used it to show that four of their six production applications were limited by memory bandwidth.6
With peak compute (FLOP/s) and bandwidth (byte/s), the roofline bound for a kernel of intensity is1
On log-log axes the bandwidth term is a line of slope 1 and the compute term a horizontal line, meeting at the .1 Williams et al. treat as a measure of how hard a machine is to program to peak: when the AMD Opteron X4 quadrupled the X2’s peak compute on the same memory system, the ridge moved from 1.0 to 4.4 FLOP/B, and kernels below 1 FLOP/B gained nothing from the upgrade.1 AI accelerators sit two orders of magnitude further right (see By the numbers).
Three refinements make it a working tool rather than a slogan:
- Ceilings. Lines below the roof for missing optimizations: unbalanced multiply/add mix, no SIMD, no prefetching, poor memory affinity. A kernel cannot break through a ceiling without the matching optimization.1 On an accelerator, a vector unit is a lower compute ceiling than the matrix unit; the AMD MI300X, for example, lists 163.4 TFLOPS of vector FP32 next to 1,307.4 TFLOPS of dense FP16 matrix math.21
- One roof per memory level. Nothing requires DRAM: with L2 or on-chip SRAM bandwidth on the slope and intensity counted against that level’s traffic, the ridge moves left.1
- Measured, not datasheet, bandwidth. The paper measures sustainable bandwidth with microbenchmarks rather than using pin bandwidth.1
The first TPU paper adapted the model to inference by counting integer operations per byte of weights read, since weights didn’t fit on chip. Its ridge sat at 1,350 operations per weight byte; the MLPs and LSTMs (at intensities of 64 to 200, equal to their batch sizes) were memory-bound and the CNNs compute-bound.6 The paper’s Table 1 shows intensity tracking batch size directly, the same lever this chapter returns to for decode.
Peak compute, 400 TFLOP/s: a horizontal line. Nothing runs faster.
An AI model has two lives. is how it learns. It’s shown huge piles of examples in big bundles, and it adjusts its numbers after each bundle. Big models train for weeks on thousands of chips.16 Big bundles keep the math busy.
is using the finished model, like when you ask a chatbot something. First it reads your whole question at once. That’s like a big bundle, so it’s quick.
Then it writes the reply one word at a time, since each word depends on the one before. For every word, the chip reads through all of the model’s numbers but does only a little math with each. That’s the chef waiting on the pantry.4
The fix is to serve many people at once. Read the numbers once, and use them to write the next word for 64 conversations. This trick is called .
runs data forward through the model, measures the error, then runs backward to work out how to change each weight. The backward pass costs about twice the forward pass, so training takes about 6 FLOPs per parameter per token, against 2 for running the model.3 It also needs much more memory: with a common recipe, every parameter carries 16 bytes of state (the weights, their gradients and the optimizer’s bookkeeping), so a 1.5-billion-parameter model needs at least 24 GB before counting anything else.11 Training processes millions of tokens per step (LLaMA used batches of 4 million tokens16), so its matrix multiplications are large and mostly compute-bound.
is running the trained model. It is forward-only, but usually has a response-time limit because someone is waiting.6 For a language model it has two phases with opposite characters:4
- processes all the prompt’s tokens at once, in one pass. A 2,000-token prompt makes every weight matrix multiplication 2,000 rows tall, so intensity is high and the step is compute-bound. It also fills the KV cache.
- then generates the reply one token at a time, each step depending on the token before. Each step reads every weight from memory to produce one token per sequence: 2 FLOPs per 2-byte weight, about 1 FLOP/B. It is deeply memory-bound.
A per-layer analysis of the open Llama-2-7B model makes it concrete: with a 2,048-token prompt, its prefill projections run at about 1,024 operations per byte and are compute-bound, while every decode layer sits near 1 operation per byte and is memory-bound.15
is the main lever on decode. Serve 64 conversations together and each weight, fetched once, does 64 tokens’ worth of work, so intensity rises about 64-fold. But each sequence brings its own KV cache, which cannot be shared, so beyond some batch size the KV cache dominates the traffic.4 Bigger batches also make each user wait longer for each token.4
Put numbers on it with the made-up chip (400 TFLOP/s, 2 TB/s) and a 6.4-billion-parameter model in 16-bit, whose weights fill 12.9 GB. One decode step at batch 1 must read all 12.9 GB: 6.4 ms at 2 TB/s. Its 12.9 billion FLOPs would take the math units only 32 µs. The math units are busy 0.5% of the time, and one user gets at most about 150 tokens per second. You can check this in the simulation below.
Training. per token: forward, about backward (gradients with respect to both activations and weights).3 GPT-3 175B at 300 billion tokens is FLOPs by exactly this count.17 Weight GEMMs have = tokens per device per step, typically thousands, so they sit far right on the roofline; the attention core and the normalization and elementwise ops are where time leaks.7 The binding constraint is often capacity: mixed-precision Adam needs bytes for parameters, gradients and optimizer states,11 plus saved activations, which is what pushes training across many devices (see the parallelism chapter in Systems).
Inference. Forward only, FLOPs per token,4 under a latency target. Pope et al. split it into4
- : one forward pass over tokens in parallel. Weight GEMMs have , so prefill is compute-bound at any realistic prompt length; they report 76% model FLOPs utilization (MFU) for large-batch prefill on PaLM 540B.4 It sets time to first token.
- : sequential passes with . Per step, the chip streams all weights plus every sequence’s KV cache. At small batch and short context the weights dominate; at large batch or long context the KV cache does. For a 500B+ model with multi-head attention at batch 512 and context 2,048, the KV cache is 3 TB, three times the weights, reloaded for every token while the compute sits mostly idle.4
For a decoder with parameters, layers, width , context , batch and bytes per value (multi-head attention, activations ignored):
At , : about 1 FLOP/B at 16 bits. As grows, the weight term is amortized and approaches ; with that is . For and at 16 bits the ceiling is 25 FLOP/B no matter the batch, an order of magnitude below a typical ridge point. Shazeer’s is the same statement.12 This is why decode is attacked on the bytes side: fewer KV heads (MQA, GQA),1213 fewer bits per weight and cache entry, and more bandwidth (The memory wall).
Decode at batch 1: all 12.9 GB of weights are read to make one token, about 6.4 ms at 2 TB/s. The math is busy 0.5% of the time.
Below is a roofline for a made-up AI chip. Each numbered dot is an AI job. Pick a job to see if it’s waiting on memory or limited by math. The bottom of the chart shows how much math a job does for each byte it fetches from memory; a byte is a tiny bit of memory, about enough for one letter of text.
Make the math faster with a slider. Which jobs speed up, and which don’t move? Now try faster memory instead. Compare “Next word, 1 user” with “Next word, 64 users.”
The chart plots six workloads on the roofline of a hypothetical chip (400 TFLOP/s, 2 TB/s by default). Each workload’s intensity is computed from its shape, assuming 16-bit numbers. Things to try:
- Find the ridge point. Which workloads are left of it?
- Raise peak compute to 3,000 TFLOP/s. Which workloads speed up? Which stay exactly where they were?
- Compare decode at batch 1 and batch 64. How much does batching raise the intensity, and is batch 64 enough to reach the ridge?
- Raise the bandwidth to 5 TB/s. Does the small GEMM change sides?
The Expert view adds the FLOP and byte counts, compute and memory time, a bytes-per-value switch, and controls for each workload’s shape: , , for the GEMMs; prompt length and fused versus unfused for attention prefill; batch and context for decode. The decode model is a 6.4B-parameter decoder (32 layers, width 4,096, multi-head attention) and includes KV-cache reads. Try:
- Shrink one GEMM dimension and confirm that intensity tracks the smallest of , , .
- Turn off fusion for prefill and see how far attention falls once the matrices go to memory.
- Push decode batch to 512 at 1,024 and then 8,192 tokens of context. Where does intensity level off, and why?
- Switch to 8-bit. What moves, and what would you expect to happen to peak compute on a real chip?
The model is the bound, not a prediction: every point sits on the roof because it assumes ideal reuse and perfect overlap of memory and compute. The same peak is used at every precision, which real chips don’t do.
- BERT training: share of FLOPs in matrix math
- 99.8%
- …and share of run time
- 61%
- Llama-2-7B decode intensity, batch 1
- ≈ 1 op/byte
- GPT-3 175B training compute
- 3.14 × 10²³ FLOPs
- 99.8% and 61%. When researchers trained a well-known language model, nearly all its math was grid multiplication. Yet that took only about 60% of the time. The tiny bit of other math took the other 40%, because it was stuck waiting on memory.
- About 1. When a popular chatbot model writes for one person, it does about one math step for each byte it fetches. Today’s AI chips need hundreds per byte to keep busy. So the math sits mostly idle.
- 314 followed by 21 zeros. That’s how many math steps it took to train GPT-3. One chip doing a thousand trillion steps a second would need about ten years. That’s why training uses thousands of chips at once.
Prefill versus decode, layer by layer
Yuan et al.’s roofline analysis of Llama-2-7B, with a 2,048-token sequence at batch 1, on a GPU roofline of 155 trillion operations per second and 768 GB/s (operations counted as 2 per MAC):15
| Layer | Phase | Ops/byte | Bound |
|---|---|---|---|
| , , , output projections | Prefill | 1,024 | compute |
| MLP projections | Prefill | 1,215 | compute |
| and products | Prefill | 114 | memory |
| Softmax | Prefill | 1.25 | memory |
| Residual add | Prefill | 0.25 | memory |
| Every projection and MLP layer | Decode | 1 | memory |
| and products | Decode | 0.99 | memory |
Read across: the same model, on the same chip, runs at roughly 1,000 operations per byte while reading the prompt and about 1 while writing the reply. The attention products in prefill fall below the ridge in this analysis because it counts the score matrix as going to memory; a fused kernel keeps it on chip.5
Two details: the attention products in prefill land at 114 because this analysis materializes the matrix; with a fused kernel they would sit near . And the decode figure of 1 is the limit for GEMV at 16 bits; nothing about the layer shapes can lift it without batching.1519
Ridge points of real chips
Delivered, not peak
Published runs show how far below the roof real workloads sit, and how much the phase matters. On PaLM 540B, Pope et al. report 76% of peak FLOPs (model FLOPs utilization) for large-batch prefill, and 29 milliseconds per token for low-batch decode with 8-bit weights.4 LLaMA-65B trained at about 380 tokens per second per GPU on 2,048 GPUs, about 21 days for 1.4 trillion tokens;16 at 6 FLOPs per parameter per token that is about 150 TFLOP/s of useful work per GPU.
Every way of keeping the math busy has a cost.
Serving many people at once keeps the chip busy. But each person waits a little longer for each word.
Using smaller numbers, with fewer digits, means less to fetch. But the answers can get a little less accurate.
Building a chip with even more math only helps jobs that were already limited by math. Jobs waiting on memory don’t speed up at all. That’s the trap: a bigger number on the box that doesn’t make real jobs any faster.
Raising intensity and what it costs
- Batching raises decode intensity roughly in proportion to batch size, but each request waits for the batch, and each sequence’s KV cache takes memory capacity. Pope et al. describe exactly this trade: smaller batches give lower latency and worse utilization, so a higher cost per token.4
- keeps intermediate results on the chip instead of writing them to memory between steps. It is the main fix for memory-bound chains of simple operations, and FlashAttention applies it to attention.5 It needs custom code for each fused pattern.
- Fewer bits per value cut the bytes and raise intensity directly: 8-bit weights halve decode’s memory traffic. The cost is accuracy, covered in Number formats.
- More on-chip memory allows bigger tiles and more reuse, but costs chip area. And it only helps until a job’s data is read just once; past that point, a bigger cache changes nothing.1
Where the roofline misleads
- It is a ceiling, not a forecast. Real code sits below it, sometimes far below, when it lacks parallelism or the right instructions.1
- Small jobs are limited by latency, a third limit the roofline doesn’t draw: there isn’t enough work to fill the chip, whatever the intensity.18 The first TPU paper found that the response-time limits of inference left a contemporary GPU badly underused.6
- Peak numbers are rarely reached. Matrix sizes that don’t divide evenly into the hardware’s tiles waste some work, an effect NVIDIA calls tile and wave quantization.19
For chip designers the lesson cuts both ways. Adding math without adding bandwidth moves the ridge point right and leaves more workloads stranded on the slope; adding bandwidth costs power, package area and money. The AI chapters that follow are largely about the different bets chips make on that balance, and Comparing chips covers how to judge them.
Design pressures from the workload
- Training and inference want different chips. Training is dominated by large GEMMs (compute) and by capacity for 16 bytes of state per parameter plus activations;11 decode is dominated by bandwidth and KV-cache capacity at a latency target.4 A design tuned for one is mis-provisioned for the other, which is why products and system configurations split along that line.
- The ridge keeps moving right. Compute has outpaced memory bandwidth, so more operations end up memory-bound.5 The first TPU’s authors estimated that giving it the GPU’s GDDR5 memory would have moved its ridge from 1,350 to 250 and raised the weighted mean speedup on their workload to 3.9×, more than a faster clock would.6
- Batch versus latency. Decode intensity rises with batch only until the KV cache dominates, and every step of batch adds per-token latency. MQA and GQA trade a little model quality for smaller caches;13 speculative decoding verifies several draft tokens per large-model pass, reporting 2–3× faster decoding with identical outputs on T5-XXL.14
- Fusion versus training state. Fusion helps less in training, because intermediates must be saved for the backward pass; FlashAttention instead recomputes attention on chip in the backward pass, spending FLOPs to save bytes.5
Failure modes of the analysis
- Counting FLOPs and ignoring bytes. BERT’s 0.2% of FLOPs in normalization and elementwise ops took 39% of its time.7
- Using the wrong roof. If a working set fits in an on-chip level, the DRAM roofline is the wrong bound; use that level’s bandwidth.1
- Assuming ideal reuse. The GEMM formula assumes each operand crosses the memory boundary once; tile sizes limited by on-chip capacity, im2col duplication or unfused intermediates all add traffic.8
- Ignoring latency and quantization. Small GEMMs underfill the machine; tile and wave quantization waste work at awkward sizes.19
- Mixing up peak precisions. Ridge points computed from a sparse or 8-bit peak and a 16-bit workload are off by 2× or more.
Batch 1, 16-bit: 6.7 ms per token for each user, 149 tokens/s in total, math busy 0.5%, 13.4 GB of weights and KV cache.
This part goes deeper, into the math, models and algorithms behind the chapter. It’s written for the Expert level.
The counting rules behind every number in this chapter, with their assumptions, and the model the simulation uses.
1. FLOPs of a GEMM
is multiplies and adds per output, so about FLOPs for each of outputs: .19 Counting a MAC as 2 FLOPs is the convention in Kaplan et al. and Pope et al.; vendor peaks follow it.34 Some papers count multiply-adds as one “FLOP” (ResNet-50’s “3.8 billion FLOPs” are multiply-adds), so check before comparing.10
2. GEMM traffic and the tiling argument
The compulsory traffic, each operand read once and the result written once, is , giving the intensity formula above.19 Whether a kernel reaches it depends on on-chip capacity. A standard blocked schedule, step by step:
- Keep a tile of in on-chip storage (registers or SRAM) for its whole computation.
- For each step along , load a column slice of and a row slice of : values, bytes.
- Those feed MACs, FLOPs, into the resident tile.
- So the intensity of the inner loop is , ignoring the one-time write of .
Intensity grows linearly with tile size, and tile area grows with on-chip capacity. To clear a ridge of 200 FLOP/B at , must be at least 400, a tile of accumulators (640 KB at 32-bit accumulation) plus staging buffers. This is why accelerators devote so much area to SRAM next to the multipliers, and why GPUs, systolic arrays and spatial meshes can all be read as different ways to hold a big tile close to the math (GPUs, Systolic arrays, Dataflow). It is also why the roofline paper’s operational intensity is measured after the caches: a better tiling is a higher , not a different roof.1
T = 128: each K step loads 2T = 256 values (512 B) and does T² = 16,384 MACs. Press “Load next slice”.
3. Attention, fused and unfused
For one layer with tokens, width and bytes per value:
- FLOPs of and : , or about with causal masking skipped.2
- Fused traffic (read , , ; write ): . Intensity with masking: , 1,024 FLOP/B for at 16 bits.
- Unfused, add a write and a read of and of for each head: about more. For , , , that is 4.3 GB against 134 MB, and intensity drops to about 31 FLOP/B.
Dao et al. prove FlashAttention needs HBM accesses with on-chip memory , against for the standard algorithm, and that no exact algorithm does asymptotically better over all .5
4. Decode intensity with a KV cache
- Weights: with the standard .3 For , : .
- FLOPs per decode step: , weights plus attention over cached positions.3
- KV cache per sequence: values. At 16 bits that is 512 KiB per token for this model, 537 MB for 1,024 tokens.
- Bytes per step: . With , : . With : . As : .
Grouped-query attention with key-value heads instead of divides the KV term by , raising the ceiling accordingly; multi-query attention is .1213 Pope et al. reach the same conclusion from the other side: weight loading dominates memory time at small batch and short context, KV loading at large batch and long context.4
5. Training compute
Backward through a linear layer computes the gradient with respect to its input (one GEMM the size of the forward) and with respect to its weights (another), so and the total is per token, ignoring attention’s context term.3 Check: , against the GPT-3’s authors report.17 Memory per parameter for mixed-precision Adam: 2 (16-bit weights) + 2 (16-bit gradients) + 12 (32-bit master weights, momentum and variance) = 16 bytes.11
6. What the bound assumes
- Perfect overlap. assumes memory and compute run concurrently. With no overlap, , at most 2× the bound, with the worst case at the ridge point.
- Enough concurrency. Sustaining bandwidth takes many outstanding requests, by Little’s law; the roofline paper’s “no prefetching” ceilings are what happens without them.1
- One bottleneck at a time. In a multi-level hierarchy, each level gets its own roof, and the binding one is the lowest at that level’s intensity.1
7. The simulation’s model
Each workload computes and from its shape with the formulas above ( unless switched), then plots against . Defaults: big GEMM (), small GEMM (85), causal fused attention prefill at for one layer of the 6.4B model (1,024), decode at batch 1 and 64 with 1,024 tokens of context (1.0 and 18), and a ReLU over 16 M values (0.25). It ignores activation traffic in decode, softmax and normalization FLOPs, tile and wave quantization, latency, and the fact that real chips change peak compute with precision.
Q1A chip has a peak of 400 TFLOP/s and 2 TB/s of memory bandwidth. What is its ridge point?
Q2Multiplying two 1,000 × 1,000 matrices takes about 2 billion FLOPs and moves about 6 MB (three matrices of 16-bit numbers). On the chip above, is it compute-bound or memory-bound?
Q3Why is generating text one token at a time for a single user memory-bound?
Q4In BERT training, matrix multiplications were 99.8% of the FLOPs. What share of the run time did they take?
Sources
Show Hide 22 sources
- Roofline: An Insightful Visual Performance Model for Floating-Point Programs and Multicore ArchitecturesOperational intensity as operations per byte of DRAM traffic; attainable = min(peak compute, bandwidth × intensity) on log-log axes; the ridge point; ceilings; ridge moving from 1.0 to 4.4 between two Opteron generations; fallacies, including per-level rooflines and Little’s law.
- Attention Is All You NeedScaled dot-product attention softmax(QKᵀ/√d_k)V, computed with optimized matrix multiplication; multi-head attention; the position-wise feed-forward network; self-attention cost O(n²·d) per layer.
- Scaling Laws for Neural Language ModelsParameter count N ≈ 12·n_layer·d_model²; forward pass ≈ 2N + 2·n_layer·n_ctx·d_model operations per token; backward pass about twice the forward, so training ≈ 6N FLOPs per token.
- Efficiently Scaling Transformer InferencePrefill vs decode; 2N matmul FLOPs per token; weights and KV cache loaded from HBM once per forward pass; KV cache of 3 TB at batch 512 and context 2048 for a 500B+ model; small batches lower latency but worsen utilization; 76% MFU in prefill; 29 ms per token decode on PaLM 540B.
- FlashAttention: Fast and Memory-Efficient Exact Attention with IO-AwarenessCompute-bound vs memory-bound operations; elementwise and reduction ops are memory-bound; kernel fusion; standard attention writes the N×N matrix to HBM (Θ(Nd + N²) accesses); tiling keeps it on chip; up to 7.6× faster attention on GPT-2.
- In-Datacenter Performance Analysis of a Tensor Processing UnitMLPs, LSTMs and CNNs were 95% of the inference workload; batching amortizes weight fetches; inference is latency-bound; roofline with ridge point at 1,350 operations per weight byte; four of six apps memory-bandwidth limited; 92 TOPS peak, 34 GB/s.
- Data Movement Is All You Need: A Case Study on Optimizing TransformersIn BERT training, tensor contractions are 99.80% of FLOPs but 61.0% of runtime; normalization 0.17% / 25.5%; elementwise 0.03% / 13.5%.
- cuDNN: Efficient Primitives for Deep LearningLowering a convolution to one matrix multiply (K × CRS filter matrix times CRS × NPQ data matrix); input duplicated up to RS times; matrix multiply has a high ratio of FLOPs per byte that grows with size.
- Efficient Processing of Deep Neural Networks: A Tutorial and SurveyFC and CONV layers mapped to matrix multiplication (Toeplitz form); ResNet-50 has 25.5M weights and 3.9G MACs per image; a DRAM access costs about 200× the energy of a MAC-level register access.
- Deep Residual Learning for Image RecognitionThe 50-layer ResNet has 3.8 billion FLOPs (counted as multiply-adds).
- ZeRO: Memory Optimizations Toward Training Trillion Parameter ModelsMixed-precision Adam training needs 2Ψ + 2Ψ + 12Ψ = 16Ψ bytes for parameters, gradients and optimizer states; at least 24 GB for a 1.5B-parameter model.
- Fast Transformer Decoding: One Write-Head is All You NeedIncremental decoding is limited by memory bandwidth for reloading keys and values; memory-to-arithmetic ratio Θ(n/d + 1/b); multi-query attention shares one K/V head.
- GQA: Training Generalized Multi-Query Transformer Models from Multi-Head CheckpointsMulti-query attention speeds up decoder inference but can cost quality; grouped-query attention uses an intermediate number of key-value heads.
- Fast Inference from Transformers via Speculative DecodingDecoding K tokens takes K serial runs; a small model drafts tokens that the large model checks in parallel; 2–3× speedup on T5-XXL with identical outputs.
- LLM Inference Unveiled: Survey and Roofline Model InsightsPrefill and decode stages; per-layer roofline analysis of Llama-2-7B (sequence 2048, batch 1) on an A6000-class roofline: prefill projections at 1,024 ops/byte and compute-bound, every decode layer near 1 op/byte and memory-bound.
- LLaMA: Open and Efficient Foundation Language ModelsThe 6.7B model has width 4,096, 32 heads and 32 layers; the 65B model trained at about 380 tokens/s/GPU on 2,048 A100-80GB GPUs, about 21 days for 1.4T tokens.
- Language Models are Few-Shot LearnersGPT-3 175B: 96 layers, width 12,288; 3.14×10²³ training FLOPs for 300B tokens, counted as 6 FLOPs per parameter per token.
- GPU Performance Background User’s GuidePerformance limited by memory bandwidth, math bandwidth or latency; ops:byte ratio; V100 at 125 FP16 tensor TFLOPS and about 900 GB/s; example intensities: linear layer batch 512 = 315, batch 1 = 1, ReLU = 0.25, layer norm under 10 FLOPS/B.
- Matrix Multiplication Background User’s GuideA GEMM takes 2·M·N·K FLOPs; intensity M·N·K/(M·K + N·K + M·N) at 2 bytes per value; 8192×128×8192 gives 124.1 and 8192³ gives 2,730 FLOPS/B; matrix-vector products are always memory-limited; tile and wave quantization.
- TPU v4: An Optically Reconfigurable Supercomputer for Machine Learning with Hardware Support for EmbeddingsTable 4: TPU v4 peak 275 TFLOPS (bf16 or int8), 32 GiB HBM2 at 1,200 GB/s; TPU v3 123 TFLOPS, 900 GB/s.
- AMD CDNA 3 Architecture White PaperMI300X: 1,307.4 TFLOPS peak dense FP16/BF16 matrix, 163.4 TFLOPS vector FP32, 192 GB HBM3 at 5.3 TB/s peak.
- TPU v6ePer chip: 918 TFLOPs peak bf16, 1,836 TOPs int8, 32 GB HBM at 1,638 GBps; one TensorCore with two matrix-multiply units.