Inference and the KV cache
Why generation is fast after the first token.
Create a free account Try part of it here
Why it matters
When a chatbot streams a reply, it writes one token at a time. (A token is a word or a piece of a word.) Each new token needs a pass through the whole model. Done the naive way, each pass also redoes the work for every earlier token, so the reply slows down as it grows. The KV cache is the fix that makes generation practical. It also explains everyday facts about AI APIs. The first token takes longest. Long conversations cost more. Output tokens cost more than input tokens. And cached prompts are cheaper and faster.
What you'll be able to do
- Describe the two phases of generation: prefill and decode
- Implement attention with a KV cache and confirm it matches full recomputation
- Calculate how much memory a KV cache needs, and how grouped-query attention shrinks it
- Explain time to first token, tokens per second, and why prompt caching is cheaper
What it covers
- Generation repeats a lot of work
- How fast the extra work grows
- Prefill, then decode
- The cache is big
- Worked example: a tiny model's cache
- Real models
- Prompt caching is a KV cache you keep
Generation repeats a lot of work
Recall the generation loop from the tiny-GPT lesson. The model reads the whole text so far. It scores every possible next token at the last position (these scores are the logits). You pick one token, add it to the end, and go round again.
Picture writing a letter where, before each new word, you reread the whole letter from the top. By the last line you've reread the opening hundreds of times. Yet the opening never changed. The plain loop works like that. Each step processes every earlier token again, although almost nothing about them has changed.
You met three things each token makes in the attention lessons:
- a query: what this token is looking for;
- a key: a label that other tokens' queries match against;
- a value: the information this token passes on when it's picked.
The causal mask means a token only looks at itself and the tokens before it. So a token's key and value depend only on that token and the ones before it. Adding a new token at the end can't change them.
That means you can work out each token's key and value once and keep them. The store is called the KV cache (K for keys, V for values). On each new step, the model computes the query, key and value for the new token only. Everything else comes from the cache.
The code below runs one attention head both ways. It also counts how many times a key and value get computed.
import math import torch import torch.nn as nn torch.manual_seed(0) d = 16 W_q, W_k, W_v = (nn.Linear(d, d, bias=False) for _ in range(3)) tokens = torch.randn(12, d) # embeddings of a 12-token sequence def attend(q, K, V): return torch.softmax(q @ K.T / math.sqrt(d), dim=-1) @ V with torch.no_grad(): # without a cache: every step recomputes keys and values for the whole prefix slow, kv_slow = [], 0 for t in range(1, len(tokens) + 1): prefix = tokens[:t] K, V = W_k(prefix), W_v(prefix) kv_slow += t slow.append(attend(W_q(prefix[-1]), K, V)) # with a cache: each token's key and value are computed once and kept K_cache, V_cache, fast, kv_fast = [], [], [], 0 for x in tokens: K_cache.append(W_k(x)) V_cache.append(W_v(x)) kv_fast += 1 fast.append(attend(W_q(x), torch.stack(K_cache), torch.stack(V_cache))) print("same outputs:", all(torch.allclose(a, b, atol=1e-6) for a, b in zip(slow, fast))) print(f"key/value computations for 12 tokens: {kv_slow} without a cache, {kv_fast} with one") for T in [1_000, 10_000, 100_000]: print(f"for {T:>7,} tokens: {T * (T + 1) // 2:>14,} vs {T:>7,}")
The two ways give the same outputs. The cache changes how much work the model does, not what it says. No mask is needed, either. At each step the new token's query sees only the cache, and the cache holds exactly the earlier tokens.
Now look at the counts. For 12 tokens, the loop without a cache computes 78 keys and values. The loop with a cache computes 12, one per token. For 100,000 tokens the gap is about 5 billion against 100,000.
A real model keeps a cache like this for every head in every layer. It also skips re-running the other parts of each layer (the MLPs) on old tokens. (torch here is the course's in-browser PyTorch subset.)
Show the answer
With causal attention, token 5's key depends only on tokens 1–5, which never change
In a decoder, later tokens can't influence earlier positions. So once a token's key and value are computed, they're final.
How fast the extra work grows
Without a cache, step 1 computes 1 key and value. Step 2 computes 2, step 3 computes 3, and so on. Write for the number of tokens. The total is all the whole numbers from 1 up to :
The dots mean "keep going in the same pattern". The right side is a shortcut for the same total.
In plain words: add up 1, 2, 3 and so on, up to the number of tokens. For a quick answer, multiply the number of tokens by one more than itself, then halve it.
Try it with 4 tokens. The long way: 1 + 2 + 3 + 4 = 10. The shortcut: 4 × 5 = 20, and half of 20 is 10. With a cache, 4 tokens need only 4 computations. For 12 tokens the shortcut gives 12 × 13 / 2 = 78, the number the code printed.
T = 4 print(sum(range(1, T + 1)), T * (T + 1) // 2)
Both ways print 10. When is large, the total is close to half of . So without a cache, the work grows with the square of the length. Double the text and the work roughly quadruples. With a cache, the work grows in a straight line. Double the text and the work doubles.
Go deeper Why the shortcut works
Write the sum forwards, then backwards underneath it:
1 + 2 + 3 + 4 4 + 3 + 2 + 1
Each column adds to 5, which is . There are 4 columns, which is . So both rows together come to 4 × 5 = 20. That counts every number twice, so halve it: 10. The same trick works for any .
T = 100 print(T * (T + 1) // 2)
Show the answer
5050
100 × 101 // 2 is 5050, which is how many computations 100 tokens cost without a cache. With one, just 100.
Without a cache, every step redoes every earlier token, so the work grows with the square of the length.
Show the answer
15
1 + 2 + 3 + 4 + 5 = 15, or 5 × 6 / 2 = 15. With a cache it would be 5, one per token.
Prefill, then decode
With a cache, generation runs in two separate phases. A restaurant kitchen is a good picture. First the cooks do all the chopping and prep in one go. Then they plate dishes one at a time.
- Prefill. The model reads the whole prompt in one pass and fills the cache. It handles all the prompt's tokens at the same time, in parallel. This is a big block of matrix math, the kind of work a GPU does efficiently. How long it takes is the time to first token (TTFT). A longer prompt means a longer wait.
- Decode. After that, the model makes one token per step. Each step does little arithmetic. But it must read all the model's weights, plus the whole cache, from the GPU's memory. So the limit isn't arithmetic. It's memory bandwidth: how many bytes per second the GPU can read from its memory. The speed you see is tokens per second.
This difference is one reason APIs charge more for output tokens than input tokens. Input tokens are processed in bulk during prefill. Each output token costs a full step of its own, one after another.
Show the answer
Before the first word appears, while the model prefills the report
The whole report must go through prefill before the first token. The summary is short, so only a few quick decode steps follow.
The cache is big
Now count what the cache holds. You know these words from earlier lessons:
- A model is a stack of layers, and each one has its own attention.
- Each layer's attention is split into several heads.
- Each head's key (or value) is a list of numbers. The length of that list is the head size.
- Each number takes up some bytes of memory. Models usually store 16-bit numbers, which take 2 bytes each.
Many models let several heads share one set of keys and values (more on that below). So the count uses KV heads: the heads that keep their own keys and values.
For every token, every layer stores one key and one value for each KV head. Multiply it all out:
The 2 at the front is there because each token stores two things: a key and a value.
In plain words: each key or value is a list of numbers. Count how many numbers one token adds across all layers and KV heads, and double it for keys and values. Then multiply by the number of tokens and by the bytes each number takes.
Worked example: a tiny model's cache
A tiny model has 2 layers, 1 KV head and a head size of 4. It stores 16-bit numbers, so 2 bytes each. How much cache do 3 tokens need?
layers, kv_heads, head_size, bytes_per_number = 2, 1, 4, 2 per_token = 2 * layers * kv_heads * head_size * bytes_per_number # 2: keys and values print("bytes per token:", per_token) print("bytes for 3 tokens:", per_token * 3)
Per token: 2 × 2 layers × 1 KV head × 4 numbers × 2 bytes = 32 bytes. Three tokens need 3 × 32 = 96 bytes. Every new token adds the same 32 bytes. So the cache grows in a straight line with the length of the conversation.
Real models
Real models are far bigger. The code below works out the cache for two Llama 3 models. It also tries a made-up version of the 70B model that gives every query head its own KV head.
The sizes print in KiB and GiB. A KiB is 1,024 bytes. A GiB is 1,024 × 1,024 × 1,024 bytes, a little over a billion. "128K tokens" means 128 × 1,024 = 131,072 tokens.
The last two lines ask two practical questions about the 8B model on one GPU with 80 GB of memory. How many conversations fit? And how fast can it decode?
def kv_cache_bytes(layers, kv_heads, head_dim, tokens, batch=1, bytes_per_value=2): return 2 * layers * kv_heads * head_dim * tokens * batch * bytes_per_value # 2: keys and values GiB = 1024 ** 3 models = [ ("Llama 3 8B", 32, 8, 128), ("Llama 3 70B", 80, 8, 128), ("70B with one KV head per query head", 80, 64, 128), ] for name, layers, kv_heads, head_dim in models: per_token = kv_cache_bytes(layers, kv_heads, head_dim, 1) full = kv_cache_bytes(layers, kv_heads, head_dim, 128 * 1024) print(f"{name:<36} {per_token / 1024:>6,.0f} KiB per token {full / GiB:>6,.0f} GiB at 128K tokens") weights = 8e9 * 2 # Llama 3 8B in 16-bit: 2 bytes per parameter free = 80e9 - weights # what's left on an 80 GB GPU per_conversation = kv_cache_bytes(32, 8, 128, 4_000) print(f"\nconversations of 4,000 tokens that fit beside the 8B model on one 80 GB GPU: {int(free // per_conversation)}") print(f"decode speed limit for one conversation at 3.35 TB/s: {3.35e12 / weights:.0f} tokens per second")
The 8B model adds 128 KiB per token, which comes to 16 GiB for a 128K-token conversation. The 70B model adds 320 KiB per token, or 40 GiB at 128K tokens. Three things stand out.
Sharing keys and values
Picture a study group of 8 people sharing one textbook instead of buying 8 copies. Llama 3 70B does the same with its heads. It has 64 query heads but only 8 KV heads. Each KV head is shared by a group of 8 query heads. This is called grouped-query attention (GQA).
Sharing cuts the cache 8 times, from 320 GiB to 40 GiB for a 128K-token conversation. Quality drops only a little. Multi-query attention goes all the way, with a single KV head shared by every query head.
Memory decides how many users a GPU can serve
The 8B model's weights take 16 GB: 8 billion numbers at 2 bytes each. That leaves 64 GB free on an 80 GB GPU. Each 4,000-token conversation needs about 0.52 GB of cache. So 122 conversations like that fit at once, as the code printed.
Everyone shares the weights, but every conversation needs its own cache. Servers run many conversations together in a batch. Each read of the weights then makes one token for all of them, like a bus that carries many passengers on one trip. Phase 6 covers this in more detail.
Decode speed is set by memory
Making one token means reading every weight once. That gives a speed limit:
The sign means "is at most".
In plain words: each new token needs one full read of the weights. Divide how fast the GPU reads by how much there is to read. That's the most tokens it can make in a second.
Try small numbers. A model has 10 GB of weights, and the GPU reads 100 GB per second. It can read the weights 100 ÷ 10 = 10 times a second, so it makes at most 10 tokens per second.
weight_bytes = 10e9 # 10 GB of weights bandwidth = 100e9 # the GPU reads 100 GB per second print(bandwidth / weight_bytes, "tokens per second at most")
Now the real case. An H100, a common data-center GPU, reads 3.35 TB per second (3.35 trillion bytes). Dividing by the 8B model's 16 GB gives about 209, as the code printed. So even this GPU tops out at around 200 tokens per second for a single 8B conversation. That's a simplified limit: it leaves out reading the cache, so real speeds are lower. Storing each weight in fewer bytes (quantization, Phase 6) raises the limit.
Go deeper Why decode waits on memory, not arithmetic
During prefill, each weight read from memory is used for every prompt token at once. The GPU's arithmetic units stay busy.
During decode, each weight read is used for one token only. That's one multiply and one add, then the GPU must fetch the next weight. The arithmetic units spend most of their time waiting for memory. Faster arithmetic barely helps. Faster memory, smaller weights or bigger batches do.
Batching helps for the same reason. One read of a weight now serves many conversations, so the arithmetic has more to do per byte read.
Show the answer
8 times smaller
Each KV head is shared by 32 ÷ 4 = 8 query heads. The cache stores 4 KV heads instead of 32, so it's 8 times smaller.
Prompt caching is a KV cache you keep
You met prompt caching in Phase 1. It's the same idea, carried across requests.
Many requests start with the same long text: a system prompt, a product catalog, a contract. That shared start is the prefix. The provider can keep the KV cache for the prefix. Next time, it skips the prefill for that part.
That's why cached input tokens are billed at a fraction of the normal price. It's also why the first token arrives sooner.
There's a strict rule, though. The cached part must be an exact, unchanged prefix. Remember that each key and value depends on its own token and every token before it. Change one early token, and every key and value after it changes too. Think of a tower of blocks: you can keep the bottom of the tower only if every block in it is exactly the same.
For marketers: put the long, stable material at the start of the prompt. That means brand guidelines, the catalog and examples. Put the part that changes per request, such as the customer's question, at the end. Then the stable prefix can be cached.
Show the answer
Style guide first, customer question last
Only an identical prefix can be reused. Anything that changes per request, like the question or a timestamp, must come after the stable part, or every key and value after it changes.
Practice what you just read
- 5 code examples you can edit and run
- a practice exercise that checks your code
- a 5-question quiz
- 5 review cards for spaced repetition
Try a quiz question
Why does a long prompt make the first token arrive later, while later tokens stream at a steady pace?