- Key idea
- Prefill and decode, caching keys and values, the cache size formula, grouped-query attention, paged attention
- Real world
- Reading a novel with a notebook. After each chapter you jot down who is who and what happened. To read the next chapter you check your notes, instead of rereading the whole book from page one.
- In an LLM
- Llama 3 8B stores 131 kB of keys and values for every token (across all 32 layers). A 128k-token conversation needs 17 GB of cache, more than the 16 GB of weights.
Two phases
Generating a reply has two phases with very different shapes:
- . The whole prompt goes through the model at once. All of its tokens are processed in parallel, as big matrix multiplications, and the last position predicts the first new token.
- Decode. Every new token after that is produced one at a time: feed in the newest token, get the next one, repeat (the generation loop).
At every decode step, attention needs the newest token’s query and the keys and values of every earlier token, in every layer. Here is the important fact: because of the causal mask, an earlier token’s key and value never change when later tokens arrive. Token 3 cannot see token 50, so its key is the same whether the text is 10 tokens long or 1,000.
So there is no need to recompute them. Store each token’s keys and values the first time they are computed, and read them back afterwards. That store is the .
Watch the difference
Step through generation with and without a cache. Highlighted rows are the ones computed in that step; faded rows come from memory.
Without a cache, step recomputes all rows, so producing tokens costs about row computations per layer. With a cache it is one row per step: in total. Only the new token goes through the matrix multiplications with the weights; the cache supplies the rest.
You are reading a long mystery novel, one chapter a night. Without notes, each night you would have to reread the book from page one to remember who the butler is. With a notebook, each chapter costs you one chapter of reading plus a glance at your notes. The notebook grows by a page a chapter, so by the end it is thick: you have swapped rereading time for shelf space. That is exactly the trade the KV cache makes.
What the cache costs
Every token leaves one key vector and one value vector in each layer, for each key/value head. So the cache needs
The 2 counts keys and values. Multiply by the number of conversations the server holds at once.
Some numbers worth remembering, in 16-bit:
| Model | Layers | KV heads × head size | Per token | 8k tokens | 128k tokens |
|---|---|---|---|---|---|
| GPT-2 small | 12 | 12 × 64 | 36.9 kB | (max 1,024 tokens: 38 MB) | |
| Llama 3 8B | 32 | 8 × 128 | 131 kB | 1.07 GB | 17.2 GB |
| Llama 3 70B | 80 | 8 × 128 | 328 kB | 2.7 GB | 42.9 GB |
The weights of Llama 3 8B are 16 GB in 16-bit. One long conversation, or a few dozen short ones, needs as much memory again for the cache.
A chat service runs Llama 3 8B on one 80 GB GPU. The weights take 16 GB, leaving about 64 GB. At 131 kB per token, that holds about 490,000 tokens of cache: about 60 conversations of 8,000 tokens each, or 3 of 128,000. How many users one GPU can serve at once is decided by the cache, not by the model.
Making the cache smaller
The formula shows the levers:
- Fewer key/value heads. In (GQA), several query heads share one key/value head. Llama 3 8B has 32 query heads but only 8 key/value heads, so its cache is 4 times smaller than it would be with one per query head; Llama 3 70B shares each among 8. Taken to the extreme, multi-query attention keeps a single key/value head. See efficient attention.
- Fewer bytes per number. Storing the cache in 8 or 4 bits halves or quarters it, usually with little loss: see quantizing the KV cache.
- Fewer tokens. Sliding-window attention keeps only the last few thousand tokens in some layers; other methods compress or evict old entries.
Paged attention
A server does not know in advance how long each conversation will grow. Reserving room for the maximum length for everyone wastes most of the memory. (introduced by vLLM) stores the cache in small fixed-size blocks, say 16 tokens each, allocated as a conversation grows, like pages of virtual memory in an operating system. A table per conversation lists where its blocks are. Little memory is wasted, so many more conversations fit, and conversations that start with the same prompt can share its blocks.
Caching also works across requests: if many requests begin with the same long system prompt, its keys and values can be computed once and reused (prefix caching), so prefill only runs on the new part.
Why decode with a cache is exact
For the newest position in a layer, attention needs , and for . With the causal mask, and depend only on tokens , so they are identical at every later step. Reusing them gives exactly the same output as recomputing, up to floating-point rounding (different kernel shapes can change the order of additions).
Cost per decode step
With a cache, each decode step does about FLOPs for the weights (one token through every matrix), plus attention over the cache: against keys and a weighted sum of values, about FLOPs per layer. It also reads the whole cache from memory every step. See what a forward pass costs.
In code
# Hugging Face transformers keeps the cache for you:
out = model(input_ids=prompt_ids, use_cache=True) # prefill
past = out.past_key_values
next_id = out.logits[:, -1].argmax(-1, keepdim=True)
out = model(input_ids=next_id, past_key_values=past, use_cache=True) # one decode stepNumbers
Per token, 16-bit: GPT-2 small bytes; Llama 3 8B ; Llama 3 70B .
In papers
- Multi-query attention: Shazeer, 2019.
- Grouped-query attention: Ainslie et al., 2023.
- Paged attention and vLLM: Kwon et al., 2023.
- Llama 3 architecture details: Llama Team, 2024.