ml-models / Language models / The KV cache advanced

The KV cache

When a language model writes one token at a time, almost everything it computed for the previous token is needed again for the next. The KV cache is the memory that keeps the reusable part, the attention keys and values of every earlier token, so each step does a little new work instead of redoing the whole prefix. It makes generation fast, and it is also what fills the GPU: this page shows how big it gets and the tricks that shrink it.

On this page
  1. Problem
  2. Intuition
  3. Mechanics
  4. What is cached, and why only K and V
  5. How big the cache is
  6. Multi-query and grouped-query attention
  7. Sharing the cache across layers, and storing it in 4 bits
  8. Paged attention
  9. Worked example
  10. Cached decoding gives the same answer
  11. Cache memory for 32 layers, 8,192 tokens
  12. Multiplying the savings
  13. Paged versus contiguous
  14. Implementation
  15. Tradeoffs
  16. Check yourself
  17. Connections
  18. Read first
  19. Read next
  20. References

Problem

A decoder-only model generates by running itself over and over, appending the chosen token each time (see decoding). Naively, step t runs the whole network on all t tokens, so writing n tokens costs about n²/2 token-positions of work. On the page's four-token example that is 10 key/value computations where only 4 were really new.

The waste is avoidable because of causality: the keys and values of token 3 depend only on tokens 1 to 3, so they never change when token 4 arrives. Keep them and the cost of a step no longer grows with the work already done. The price is memory, and for long conversations that price is large.

Intuition

Imagine taking notes in a meeting. To answer a question about what was said, you do not replay the recording from the start; you look at your notes. Each attention layer keeps two notes per past token: a key (what this token is about, used for matching) and a value (what it contributes if matched). A new token writes its own two notes, then reads all the notes to decide what to attend to. Nothing already written is edited.

Generation therefore has two phases. Prefill reads the whole prompt at once and fills the cache, with many tokens processed in parallel, which keeps the hardware busy. Decode then adds one token at a time, and each step must read the entire cache but does little arithmetic with it. That makes decode limited by memory bandwidth, not by compute.

Prefill fills the cache, decode appends to it On the left, a prompt of four tokens is processed in one pass and writes four key and value entries into the cache. On the right, decode steps each take one new token, append its key and value as a fifth and then sixth entry, and read all stored entries to compute attention for that one token. prefill: whole prompt, one pass t1t2t3t4 decode: one token per step t5 t6 cache: K and V rows per token, per layer KV KV KV KV KV KV solid = written in prefill; dashed = appended by decode steps each decode step reads every column, writes one

Prefill is compute-heavy and parallel over the prompt; decode is a sequential loop over the cache.

Mechanics

What is cached, and why only K and V

In each layer, token i produces a query qi, key ki and value vi (see attention). Its output is softmax(qi·K≤iT/√d) V≤i. For a new token only its own query is needed: past queries were used once, for the past tokens' outputs, and are never read again. Past keys and values are read by every later token, so they are the things to store. The causal mask is also free: the cache only contains earlier positions, so nothing needs masking at decode time. The cache has one slot per layer, per token, per K/V head: shape [layers, 2, B, Hkv, S, D] with S the length so far.

How big the cache is

Per token the cache holds 2 (K and V) × layers × Hkv × head width × bytes per value. For an 8B-class configuration with 32 layers, 32 query heads, 8 key/value heads, head width 128 and 2-byte values (fp16 or bf16) that is 131,072 bytes, 128 KiB, per token. An 8,192-token context costs 1 GiB for one sequence, and a batch of 32 such sequences costs 32 GiB, comparable to the weights of the model itself.

Multi-query and grouped-query attention

Cache size is proportional to the number of key/value heads, so share them. Multi-query attention (MQA) keeps all the query heads but a single K/V head. Grouped-query attention (GQA) is the middle: query heads are split into groups, each group sharing one K/V head. With 32 query heads and 8 K/V heads, every K/V head serves 4 queries. In PyTorch, F.scaled_dot_product_attention(..., enable_gqa=True) does this by repeating each key and value head to match the query heads (lines 6442-6444 of the reference code in its docstring), so the saving is in what you store, not in the attention arithmetic.

Query heads and key/value heads in MHA, GQA and MQA Three panels with eight query heads each. In multi-head attention every query head has its own key/value head, eight in total. In grouped-query attention, groups of four query heads share one of two key/value heads. In multi-query attention all eight share a single key/value head. MHA: 8 K/V heads qqqqqqqq kv kv kv kv kv kv kv kv cache × 1 GQA: 2 K/V heads qqqqqqqq kv kv cache × 0.25 MQA: 1 K/V head qqqqqqqq kv cache × 0.125

Sharing the cache across layers, and storing it in 4 bits

The per-token size is a product, 2 × layers × Hkv × head width × bits, and GQA attacks only one factor. The others can shrink too. Cross-layer attention (CLA, Brandon et al. 2024) lets a group of adjacent layers share one set of keys and values: only the first layer in the group projects and caches K and V, and the others attend to them with their own queries. Sharing across pairs halves the cache again, on top of GQA. You Only Cache Once (YOCO, Sun et al. 2024) takes it to the limit: the bottom half of the network is a self-decoder with cheap local attention, and the middle layer's output is projected once into a single global K/V that every upper layer cross-attends to. The upper layers no longer need the prompt run through them to build their own caches, so prefill does roughly half the work as well.

DeepSeek-V4.1-Flash (2026) combines all three axes. Its report frames them as entry size (GQA, latent attention), sequence (keeping one compressed entry per m tokens) and layer (cache reuse). It splits its 40 layers into a causal encoder-decoder after YOCO: the 20 decoder layers project their global K/V from the hidden state at layer 20, so a prompt only passes through the encoder half to fill them. Inside each half, most layers reuse a neighbour's work: a Full layer computes its own compressed K/V, sparse-attention indexer keys and top-k selection, a Reindex layer keeps the K/V but picks its own top-k, and a Reuse layer takes both. Finally the main cache is stored in FP4: E2M1 values (sign, 2 exponent bits, 1 mantissa bit, so magnitudes 0 to 6) with one E4M3 scale shared by every 16 channels, 4.5 bits per value. The values are quantized after rotary embeddings and the model is trained for it with quantization-aware training; the small sliding-window cache stays in FP8. The report gives about 890 bytes of global K/V per token, a quarter of its predecessor's.

Which layers write a K/V cache: standard, cross-layer attention, and a causal encoder-decoder Three stacks of eight layers. In the standard stack every layer writes its own cache, eight caches. With cross-layer attention in pairs, the lower layer of each pair writes a cache that both layers read, four caches. In the encoder-decoder stack the lower layers keep small local caches and the middle layer's output is projected into one global cache that all four upper layers read. Standard: 8 caches layer 1 layer 2 layer 3 layer 4 layer 5 layer 6 layer 7 layer 8 CLA pairs: 4 caches layer 1 layer 2 layer 3 layer 4 layer 5 layer 6 layer 7 layer 8 Encoder-decoder: 1 global layer 1 layer 2 layer 3 layer 4 layer 5 layer 6 layer 7 layer 8 K/V K/V K/V K/V K/V K/V K/V K/V K/V K/V K/V K/V local local local global K/V solid: layer writes the cache · dashed: layer only reads a cache written below it

Paged attention

A serving system holds many sequences of different, unknown final lengths. Reserving one contiguous region of the maximum length for each wastes most of it, and the leftovers fragment memory. Paged attention (the idea behind vLLM) stores each sequence's cache in fixed-size blocks of tokens that need not be adjacent, with a per-sequence block table mapping positions to blocks, as an operating system pages virtual memory. A sequence wastes at most the unused tail of its last block, and blocks can be shared between sequences with a common prefix.

ComponentShape/ParamsMeaningSource
Key cache (per layer) [B, Hkv, S, 128] Keys of all tokens so far; grows by one row per decode step. sdpa reference code (key argument)
Value cache (per layer) [B, Hkv, S, 128] Values of all tokens so far. sdpa reference code (value argument)
Query at decode [B, Hq, 1, 128] L = 1 against S cached keys; is_causal=True would align the mask to the upper-left, so omit it and pass no mask. functional.py
enable_gqa=True Hq divisible by Hkv Repeats K and V heads to match the query heads. lines 6442-6444
nn.MultiheadAttention kdim, vdim, no cache argument Recomputes keys and values from its inputs every call; the module has no cache of its own, so a cache must be kept outside it. activation.py
Block table (paged) [sequences, max_blocks] ints Maps a sequence's block number to a physical block. Not part of PyTorch; defined by the serving engine. Kwon et al., 2023 (see references)

Worked example

Cached decoding gives the same answer

Take the four-token example from the attention page. Decode it step by step: at step t, append key and value t to the cache, and attend query t to the cache. The outputs are [1.0, 0.0], [0.3302, 0.6698], [0.2321, 0.9546], [0.3719, 0.3719], and they differ from full causal attention over all four tokens by at most 0e+00, i.e. zero. The work differs: the cache computes 4 key/value pairs in total, the recompute version 10. At length n these are n and n(n+1)/2.

Cache memory for 32 layers, 8,192 tokens

VariantK/V headsBytes per token8,192 tokens (GiB)Batch of 32 (GiB)
MHA32524,2884128
GQA8131,072132
MQA116,3840.124

Why decode is memory-bound: each step reads the cache once, 2·S·Hkv·D·b bytes per layer, and does about 4·S·Hq·D floating-point operations on it (a multiply-add for each of the scores and the weighted sum). The ratio, in FLOPs per byte, is 2·Hq/(Hkv·b), independent of S: 1 for MHA with 2-byte values, 4 for this GQA and 32 for MQA. A modern GPU can do on the order of hundreds of FLOPs per byte it reads, so all three are far below that and the memory system is the limit; sharing K/V heads both shrinks the cache and raises the ratio.

Multiplying the savings

Start from the same 32-layer configuration and apply one factor at a time:

StepK/V headsLayers per cacheBits per valueBytes per token× smaller than MHA
Multi-head attention, 16-bit32116524,2881.0
Grouped-query attention8116131,0724.0
Share each K/V across 2 layers821665,5368.0
Store values in FP882832,76816.0
FP4 values, one 8-bit scale per 16824.518,43228.4

The scales are why FP4 costs 4.5 bits, not 4: every 16 values carry one 8-bit scale. Quantizing one block of 16 values whose largest magnitude is 1.95: the scale is 1.95/6 rounded to E4M3, 0.3125, and each value divided by it snaps to the nearest of ±0, 0.5, 1, 1.5, 2, 3, 4 or 6. The codes are 0.5, -3.0, 1.5, 6.0, 0.0, 2.0, -4.0, 1.0, 3.0, -1.5, 0.0, 4.0, -0.5, 2.0, -3.0, 1.0. Multiplied back, the largest error is 0.15 and the mean 0.054; the block takes 72 bits instead of 256 in bf16. The scale's own range caps what a block can hold at 448 × 6 = 2,688, and the coarse grid is why the model is trained with quantization in the loop rather than quantized afterwards.

Paged versus contiguous

Four sequences have 37, 120, 5, 64 tokens so far, 226 in all. Reserving 128 slots each takes 512 slots and wastes 286 (56%). With blocks of 16 tokens the sequences take 3, 8, 1, 4 blocks, 256 slots in all, wasting 30 (12%).

Implementation

import torch
import torch.nn.functional as F

class CachedAttention(torch.nn.Module):
    def __init__(self, d, q_heads, kv_heads):
        super().__init__()
        self.hq, self.hkv, self.dh = q_heads, kv_heads, d // q_heads
        self.q = torch.nn.Linear(d, q_heads * self.dh, bias=False)
        self.k = torch.nn.Linear(d, kv_heads * self.dh, bias=False)
        self.v = torch.nn.Linear(d, kv_heads * self.dh, bias=False)
        self.o = torch.nn.Linear(d, d, bias=False)

    def forward(self, x, cache=None):          # x: [B, T, d]; T = prompt length, then 1
        B, T, _ = x.shape
        q = self.q(x).view(B, T, self.hq, self.dh).transpose(1, 2)
        k = self.k(x).view(B, T, self.hkv, self.dh).transpose(1, 2)
        v = self.v(x).view(B, T, self.hkv, self.dh).transpose(1, 2)
        if cache is not None:                  # append, never rewrite
            k = torch.cat([cache[0], k], dim=2)
            v = torch.cat([cache[1], v], dim=2)
        out = F.scaled_dot_product_attention(
            q, k, v, is_causal=(cache is None),   # prefill: causal; decode: T == 1
            enable_gqa=self.hq != self.hkv,
        )
        out = out.transpose(1, 2).reshape(B, T, -1)
        return self.o(out), (k, v)

Prefill calls it with the whole prompt and no cache, then each decode step passes the previous (k, v) back with one new token. torch.cat copies the whole cache every step; real systems preallocate a buffer and write into it (or use blocks, as above). Rotary positions, if the model uses them, are applied to q and k before k is cached, so the cache holds already-rotated keys. A decode step with T = 1 needs no mask, because the cache holds only earlier positions.

Tradeoffs

  • Speed versus memory. The cache turns quadratic recompute into linear work but its size is linear in context and batch, and often decides how many requests fit on a GPU.
  • MQA and GQA shrink the cache by Hq/Hkv at some loss in quality that grows as the K/V heads shrink; GQA is the usual compromise. A model must be trained with the choice (or converted and fine-tuned), since the projections differ.
  • Precision. Storing the cache in 8-bit or lower cuts memory again, trading accuracy; see quantization. At 4 bits the per-block scales are essential and the model generally has to be trained for it.
  • Sharing across layers (CLA, YOCO-style encoder-decoders) divides the cache by the sharing factor and, for YOCO, roughly halves prefill, but the layers that read a shared cache lose their own view of the prefix, which costs quality, and the architecture must be chosen before pre-training.
  • Paging improves utilisation and allows prefix sharing, at the cost of a more complex attention kernel that follows the block table.
  • Pitfalls. Passing is_causal=True with a one-token query and a longer key sequence aligns the mask to the wrong corner (the attention page covers the two alignments). Off-by-one position ids when resuming from a cache silently corrupt outputs. And a cache is tied to the exact prefix: change an earlier token and every later entry is stale.

Check yourself

Why cache keys and values but not queries?

A token's query is used once, to compute its own output. Later tokens attend to earlier keys and values, not earlier queries.

The per-token cache is 2 × layers × Hkv × D × bytes. Which factor does GQA change?

Hkv, from 32 to 8 here, a 4× saving.

Why is decode memory-bound but prefill is not?

Prefill reuses each loaded weight and cache entry across many tokens at once; decode reads the whole cache to process a single token.

Connections

Read first

Read next

References

  • Shazeer. Fast Transformer Decoding: One Write-Head is All You Need (multi-query attention). 2019 (arXiv 1911.02150).
  • Ainslie et al. GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. EMNLP, 2023 (arXiv 2305.13245).
  • Kwon et al. Efficient Memory Management for Large Language Model Serving with PagedAttention. SOSP, 2023 (arXiv 2309.06180).
  • Brandon, Mishra, Nrusimha, Panda and Ragan-Kelley. Reducing Transformer Key-Value Cache Size with Cross-Layer Attention. NeurIPS, 2024 (arXiv 2405.12981).
  • Sun, Dong, Zhu, Huang, Wang, Ma, Zhang, Wang and Wei. You Only Cache Once: Decoder-Decoder Architectures for Language Models. NeurIPS, 2024 (arXiv 2405.05254).
  • DeepSeek-AI. DeepSeek-V4.1-Flash: Pushing the Limits of KV Cache Compression. 2026 (technical report).
  • Vaswani et al. Attention Is All You Need. NeurIPS, 2017 (arXiv 1706.03762).
  • PyTorch v2.15.0: scaled_dot_product_attention, MultiheadAttention.