Index Ai Academy
Phase 5 · Transformers · Scale & inference

Inference and the KV cache

Why generation is fast after the first token.

About 35 minutes · A free account opens the whole lesson

Create a free account Try part of it here

Already have an account? Sign in to open this lesson

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

  1. Generation repeats a lot of work
  2. How fast the extra work grows
  3. Prefill, then decode
  4. The cache is big
  5. Worked example: a tiny model's cache
  6. Real models
  7. 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,}")
It runs right here in your browser, with nothing to install.

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.)

Quick check
Why can a key computed for token 5 be reused unchanged when token 50 is generated?
  1. Keys are random and don't matter
  2. The model's weights change after each token
  3. With causal attention, token 5's key depends only on tokens 1–5, which never change
  4. Token 50 can't attend to token 5
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 TT for the number of tokens. The total is all the whole numbers from 1 up to TT:

1+2+3+⋯+T=T×(T+1)21 + 2 + 3 + \cdots + T = \frac{T \times (T + 1)}{2}

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 TT is large, the total is close to half of T×TT \times T. 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 T+1T + 1. There are 4 columns, which is TT. So both rows together come to 4 × 5 = 20. That counts every number twice, so halve it: 10. The same trick works for any TT.

Quick check
What does this print?
T = 100
print(T * (T + 1) // 2)
  1. 200
  2. 10000
  3. 100
  4. 5050
Show the answer

5050

100 × 101 // 2 is 5050, which is how many computations 100 tokens cost without a cache. With one, just 100.

Try it now

Without a cache, every step redoes every earlier token, so the work grows with the square of the length.

Quick check
A text has 5 tokens. How many key and value computations does the loop without a cache do in total?
  1. 15
  2. 5
  3. 25
  4. 10
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.

  1. 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.
  2. 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.

Quick check
You paste a 50-page report into a chatbot and ask for a one-line summary. Where does most of the waiting happen?
  1. Before the first word appears, while the model prefills the report
  2. Spread evenly, because the model reads one page per output word
  3. After the last word, while the model checks its answer
  4. Between the words of the summary
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:

bytes=2×layers×KV heads×head size×tokens×bytes per number\text{bytes} = 2 \times \text{layers} \times \text{KV heads} \times \text{head size} \times \text{tokens} \times \text{bytes per number}

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

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)
In the lesson you can change this and run it.

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:

tokens per second≤memory bandwidthbytes of weights\text{tokens per second} \le \frac{\text{memory bandwidth}}{\text{bytes of weights}}

The sign ≤\le 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.

Quick check
A model has 32 query heads and 4 KV heads. Compared with the same model giving every query head its own KV head, how big is its KV cache?
  1. 8 times smaller
  2. The same size, because only query heads are stored
  3. 32 times smaller
  4. 4 times smaller
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.

Quick check
You send 1,000 requests. Each has the same 5,000-token style guide plus one customer question. Which layout lets the provider reuse the cached style guide?
  1. Any order, because the same words appear in every request
  2. Style guide first, customer question last
  3. Customer question first, style guide last
  4. The exact time of the request first, then the style guide, then the question
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

Create a free account

Try a quiz question

Why does a long prompt make the first token arrive later, while later tokens stream at a steady pace?

  1. The whole prompt must be processed (prefill) before the first token; after that, each token is one cached decode step
  2. The model reads the prompt one word at a time, and it has to hold each word in memory until the reply is finished
  3. The API waits until the whole answer is ready, then sends the tokens out one by one at a pace that looks like typing
  4. Long prompts get routed to a slower model, and it takes a while to load that model before the first token can arrive

Answer it at the end of the lesson to see if you're right, and why.

Before this lesson