Why AI Runs on GPUs
Matrix multiplication, memory, and the hardware behind language models, built one lane at a time
Sjoerd Vink
In 2012, a neural network trained on two gaming graphics cards won the ImageNet competition by a wide margin. Since then, nearly every leap in AI has run on GPUs, and the chips have become one of the most sought-after products on Earth.
This essay explains why. It follows the arithmetic of a language model down to the silicon: what the work is, why it splits across thousands of lanes, why memory is the real bottleneck, and the tricks that get around it.
Choose your depth. You can switch at any time.
01 Work
A language model runs once for every word it writes.
When a chatbot answers you, it does not plan the whole reply. It picks one word, adds it to the text, and starts over. Each pick sends the text through the entire model, bottom to top.
The model is a tall stack of identical layers. A small open model like Llama 3 8B has 32 of them.
Zoom into one layer and follow one token through it. Most of the work happens in a few large steps.
First the token is turned into a question, a label and an answer to share with the words before it. Then it looks back at those words. Then it passes through a large block, the MLP, that does most of the thinking.
Every one of those large steps is the same operation: multiplying two grids of numbers, a matrix multiplication.
Matrix multiplication is 99.8% of the arithmetic.
Everything else, like normalizing numbers or picking the most relevant words, is a rounding error. Make matrix multiplication fast and you have made the model fast.
Add up all 32 layers and the final step that scores every word in the vocabulary, and one token costs about 17 billion operations.
There is a neat shortcut: about two operations for every number in the model. Each weight is used once per word, to multiply and then to add.
Training multiplies this twice over: by the number of tokens the model reads, and by three, because learning also has to run the model backwards.
A 70B model trained on 15T tokens needs about 6 followed by 24 zeros operations. Counting one per second, it would take more than ten million times the age of the universe.
The question is not whether a computer can do this. It is how many matrix multiplications it can do per second.
02 Parallelism
Every cell of a matrix product can be computed on its own.
Think of filling in a giant multiplication table. Each square needs one row and one column, and nothing from any other square. A thousand people could each take one square and never need to talk to each other.
A CPU has a handful of cores. Each is very fast and very clever, but it still fills the grid a few cells at a time.
CPUs are built to finish one complicated task as quickly as possible: running your browser, your spreadsheet, your operating system. Most of the chip goes to being clever, not to doing arithmetic.
A GPU has thousands of simple lanes. Each one is slower than a CPU core, but they all start at once, and the grid is done before the CPU is an eighth of the way through.
A CPU minimizes latency. A GPU maximizes throughput.
02 Parallelism/ The chip
The difference is visible in the silicon.
Picture the chips from above. On a CPU, the parts that actually do arithmetic are small islands. The rest is there to keep a few workers busy and well informed.
A GPU flips the ratio. The chip is tiled with copies of the same block, and most of every block is arithmetic.
Next to the chip sit stacks of memory, packed as close as possible, because thousands of workers get hungry fast.
Inside one block are four groups of 32 lanes, a small scratch space for each, and a special unit that multiplies whole small matrices at once.
The 32 lanes of a group do not act independently. They receive one instruction and execute it together, each on its own data.
It is like a drill team: one call, thirty-two people moving at once. That is perfect for a grid of identical dot products, and a poor fit for work where everyone needs to do something different.
A GPU has arithmetic to spare. The hard part, it turns out, is getting numbers to it fast enough.
03 Memory
Arithmetic is cheap. Moving numbers is expensive.
Imagine a chef who can chop hundreds of vegetables in the time it takes a courier to bring one more. The chef will spend most of the day waiting. That is a GPU reading from its main memory.
So GPUs keep several layers of memory, each closer to the lanes and smaller than the last.
In the kitchen: a few ingredients in your hands, a tray on the counter, a pantry down the hall, and a warehouse across town that holds everything.
The closer the memory, the faster it is. Registers and shared memory move data ten to a hundred times faster than HBM, and answer in a few cycles instead of hundreds.
The whole game is to fetch each number from far away once, and use it many times up close.
03 Memory/ The roofline
One plot tells you what limits a computation.
Count how many operations a computation does for each byte it reads or writes. Few, and it waits for memory. Many, and it is limited only by the arithmetic.
A ReLU reads a number, compares it with zero and writes it back. One operation for every four bytes moved.
The GPU spends nearly all its time waiting. Steps like this are a tiny part of the math in a model, but they can still eat a surprising share of the time.
Matrix multiplication is different, because every number is used many times. Each entry of meets a whole column of .
Try it. Small products fall on the slope, large ones climb onto the roof.
A GPU is only fast when each byte is reused many times.
Operations that cannot reuse data can still be combined. Do three elementwise steps in one pass, while the numbers are close by, and the intensity triples.
04 Tiling
Load each number once, use it many times.
Computed naively, every output cell fetches its own row and column from main memory. Neighboring cells fetch the same numbers again and again.
It is a chef who drives to the warehouse for every single dish, even when the next dish needs exactly the same ingredients.
Instead, a group of threads copies one block of and one block of into fast memory on the chip. Every number in those blocks now serves 4 outputs instead of one.
Then it slides along: the next block of to the right, the next block of below, adding to the same outputs each time.
Do this for every output tile and the trips to main memory drop from 1,024 to 256: 4 times fewer. Bigger tiles save more.
Tiling turns a memory-bound computation into a compute-bound one.
At the very bottom, the product of two small tiles is exactly what the GPU's matrix units were built for.
The counter comes with a machine that combines whole trays at once. Hand it two trays and it hands back a finished one.
05 Precision
Fewer bits, more math.
A computer stores a decimal number like scientific notation: a sign, a power that sets the scale, and a few digits of detail. The classic format uses 32 bits for all three.
Neural networks do not need seven digits. BF16 keeps all of the scale and drops most of the detail. π becomes 3.140625.
The numbers get a little blurry, and the network does not mind. In exchange, each number takes half the space and the GPU can multiply many more of them per second.
FP16 splits its 16 bits differently: more detail, less scale. Pick 70,000 and it overflows, because nothing above 65,504 fits.
Keep going. FP8 has 8 bits and FP4 only 4. π becomes 3.25, then 3, and 0.0001 vanishes to zero.
That sounds hopeless, but there is a trick: store a shared scale for each small group of numbers, then each number only needs to say where it sits within its group.
Every halving of the bits roughly doubles how many multiplications a tensor core can do per second, and halves how many bytes have to move.
Lower precision speeds up both ceilings of the roofline at once.
06 Inference
Writing text is limited by memory, not math.
Reading your prompt is easy for a GPU: every word goes through the model at once, which makes big, efficient matrix products. Writing the answer is harder, because it happens one token at a time.
For each new word, the GPU has to read the entire model from memory, all 16 gigabytes, and do only a couple of operations with each number.
Reading the weights takes 4.8 milliseconds. The arithmetic takes a sliver of that. One user gets about 209 tokens per second, and the math units sit idle 99.7% of the time.
The fix is to serve many people at once. The weights are read once per step no matter how many sequences use them, so a batch of 32 gets nearly 32 times the throughput for free.
Batching is how one GPU serves thousands of users.
There is a catch. To avoid redoing work, each conversation keeps the keys and values of every token so far. This KV cache grows with every token, and it lives in the same memory as the weights.
With long conversations, the memory fills up after a few dozen users, and fetching their saved context takes longer than fetching the model itself.
Training a large model, on the back of an envelope.
Take a 70B model trained on 15T tokens, roughly the scale of Llama 3.1 70B. Chapter one gives the total work.
Real training runs keep about 40% of the tensor cores busy. The rest is lost to memory-bound operations, communication and waiting. At that rate one GPU would need 505 years.
So the work is split across 16,384 GPUs, and 505 years becomes 11 days.
Meta reported about 7.0 million H100-hours for Llama 3.1 70B. Our envelope says 4.4 million. Hardware failures, restarts and lower utilization in practice likely make up the difference.
A FLOP count, a peak rate and a utilization get you within a factor of two of a real training run.
Numbers to know
Most questions about AI hardware can be answered with a handful of ratios. Here are the ones from this essay.
- FLOPs to process one token
- 16 GFLOP for 8B
- FLOPs to train on D tokens
- forward + backward
- H100 dense BF16 tensor core rate
- 989 TFLOP/s
- H100 HBM bandwidth
- 3.35 TB/s
- the ridge: FLOPs needed per byte
- 295 FLOP/B
- intensity of an n × n × n BF16 matmul
- compute-bound above 886
- intensity of decoding at batch size b
- memory-bound below the ridge
- lower bound on time per decoded token
- 4.8 ms for 8B
- KV cache bytes per token in BF16
- 128 KB for 8B
- reads of a matmul tiled with T × T tiles
- T times fewer
- share of peak FLOPs a training run achieves
- often 35 to 50%
A language model is matrix multiplication. Matrix multiplication splits into thousands of independent dot products, and a GPU has thousands of lanes to run them. The rest is about feeding those lanes: tiles that reuse every byte, fewer bits per number, and batches that share every read.
To see what all that arithmetic computes, read Inside the Transformer or The Math Behind AI.