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.

  1. 01 Work
  2. 02 Parallelism
  3. 03 Memory
  4. 04 Tiling
  5. 05 Precision
  6. 06 Inference
next tokentoken32 identical layersone layer, one tokenQKV10%Attn13%Output7%MLP70%Othermatrix multiplication: 99.8%forward: 2Nbackward: 4N32 layers × 504 MFLOP + 1.1 GFLOP= 17.2 GFLOP per token ≈ 2 × 8B params6 × 70B params × 15T tokens= 6.3 × 10²⁴ FLOP

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.

CPU8 fast workersGPUthousands of slow workerseach cell is one dot product, independent of every other cell256 / 256 cellsdone in 4 ticks, then idletick 32

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.

cacheCPUa few clever workersGPUmany simple workersmemory on both sidesarithmeticOne block of the GPU1 of 132a small, fast shared shelfinstructions32 workersmatrix unitscratch spacemultiply, add32 workers, one instruction

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.

doing arithmetic989 trillion operations per secondfetching numbers1.68 trillion numbers per second590 operations for every number fetchedsizespeedin your handsRegisters34 MB300 TB/son the counterShared memory30 MB33 TB/sin the pantryL2 cache50 MB10 TB/sat the warehouseHBM80 GB3.35 TB/scloser is smaller and faster

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.

1101001,00010,0001 T10 T100 T1,000 Toperations per byte fetchedspeedwaiting for databusy computingridge 295ReLUone word at a timebig matrix productn = 51258% of peak

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 AA meets a whole column of BB.

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.

ABCthe counter×reuse every number 4 timestrips to the warehousenaive1,024tiled, T = 4256one output reads 16 numbers4× fewer reads

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 AA and one block of BB 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 AA to the right, the next block of BB 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.

signscaleprecisionstored asFP3232 bits010000000100100100001111110110113.141593error 0.0000028%67BF1616 bits01000000010010013.140625error 0.031%989FP1616 bits01000010010010003.140625error 0.031%989FP88 bits010001013.25error 3.5%1,979FP44 bits01013error 4.5%Blackwell
value

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.

GPU memoryweights 16 GBKV cache 0 GB for 1 × 8,192 tokenstime to write the next wordfetch the model4.8 msfetch the memory of the text0.000 msdo the arithmetic0.016 ms209tokens per second0.3%of the arithmetic in use

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.

1 GPU505 years16,384 GPUseach square is 32 GPUs11 days6 × 70B × 15T = 6.3 × 10²⁴ FLOP6.3 × 10²⁴ ÷ (989 T × 0.4) = 505 GPU-years4.4 M GPU-hours ÷ 16,384 GPUs = 11.2 daysestimate 4.4 M GPU-hours, published 7.0 M
Putting it together

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.

Field guide

Numbers to know

Most questions about AI hardware can be answered with a handful of ratios. Here are the ones from this essay.

C≈2NC \approx 2N
FLOPs to process one token
16 GFLOP for 8B
C≈6NDC \approx 6ND
FLOPs to train on D tokens
forward + backward
PpeakP_{\text{peak}}
H100 dense BF16 tensor core rate
989 TFLOP/s
BmemB_{\text{mem}}
H100 HBM bandwidth
3.35 TB/s
Ppeak/BmemP_{\text{peak}} / B_{\text{mem}}
the ridge: FLOPs needed per byte
295 FLOP/B
I=n/3I = n / 3
intensity of an n × n × n BF16 matmul
compute-bound above 886
I≈bI \approx b
intensity of decoding at batch size b
memory-bound below the ridge
2N/Bmem2N / B_{\text{mem}}
lower bound on time per decoded token
4.8 ms for 8B
2Lhkvdhead⋅22 L h_{kv} d_{\text{head}} \cdot 2
KV cache bytes per token in BF16
128 KB for 8B
2n3/T2n^3 / T
reads of a matmul tiled with T × T tiles
T times fewer
MFU\text{MFU}
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.

← Back to blog