10.3 — KV cache implementation details
Goal: Derive the KV-cache memory cost $2 \cdot n_\text{layers} \cdot n_\text{heads} \cdot d_\text{head} \cdot n_\text{ctx} \cdot \text{batch}$ exactly; walk through prefill vs decode phases; show how GQA/MLA reduce the cache; understand the operational consequences (batch size, context length, throughput-vs-latency).
1. Why this session exists
Cap 6.14 introduced the KV cache as the reason autoregressive decode is feasible at all: by caching keys and values for past tokens, each new-token forward is in context length rather than .
That gave us the concept. This session does the engineering: exact memory formula, prefill vs. decode separation, what GQA/MLA buy in the cache, and how the cache constrains the batch-size / context-length / throughput Pareto frontier.
By the end you should be able to look at a deployment and answer: given an A100-80GB or H100, what is the largest (batch × context) I can serve, and what does the inference loop look like step-by-step?
2. The exact KV-cache formula
At every Transformer layer, self-attention produces per-head keys and values from the input via linear projections .
For autoregressive decode, the keys and values for positions never change as advances — they depend only on the (now-fixed) earlier tokens. We cache them.
The cache at maximum context has:
- 2 tensors (K and V),
- copies (one per Transformer block),
- heads per layer,
- dimensions per head,
- positions,
- sequences in the batch,
- bytes per element (2 for fp16/bf16, 1 for int8, 0.5 for int4).
Multiplying:
2.1 Concrete numbers
Llama-2 70B has , , , fp16 (). For one sequence at :
Per sequence. At batch 8 and , the KV cache alone consumes GB — exceeding the 80 GB of an A100.
This is the principal bottleneck of LLM serving in 2025–2026: the KV cache, not the model weights, dominates GPU memory at production batch sizes and context lengths.
2.2 Per-token cache footprint
A useful summary statistic is bytes per token:
For Llama-2 70B fp16: MB/token. For Llama-3 70B (with GQA, ): MB/token. For DeepSeek-V2 (with MLA): MB/token. The factor of between dense MHA and MLA is precisely the reason MLA exists.
3. Prefill vs. decode
Inference has two distinct phases.
Prefill. The model processes the prompt of length in one forward pass. The KV cache is populated for positions . This is compute-bound: matrix-multiply work per layer.
Decode. Each subsequent step processes one new token, using the cached K/V for all earlier positions. The new token's K/V is appended to the cache. This is memory-bound: most of the time is spent moving the cache through the GPU memory hierarchy to perform attention against it.
3.1 The compute / memory profile
A useful operational reference (the numbers below are for an A100, fp16):
| Phase | Work per token | Bottleneck | Tokens/sec achievable | |---|---|---|---| | Prefill | FLOPs/token, parallel across | Compute (TFLOP/s) | – at single-batch, much higher batched | | Decode | FLOPs/token, sequential | Memory bandwidth (HBM) | – for a B model |
Decode is two orders of magnitude slower than prefill per token, because every step pays the cost of moving the entire weight matrix and the (growing) cache through the GPU bandwidth wall.
3.2 Time-to-first-token (TTFT) vs. inter-token latency (ITL)
- TTFT is the prefill time: time from receiving the prompt to emitting token . Scales with .
- ITL is the decode time per token: time between successive emitted tokens. Roughly constant in until KV-cache attention becomes dominant.
Modern serving stacks (vLLM, TGI, TensorRT-LLM) report both metrics. A "fast" model is one with low TTFT (prefill is fast) and low ITL (decode is fast).
4. KV cache shrinkage: GQA, MQA, MLA recap
Cap 8.3 and Cap 8.5 introduced cache-shrinkage techniques. The recap, in the units of this session:
4.1 Multi-Query Attention (MQA)
Single K/V projection shared across all query heads:
Factor of smaller than MHA. Loses some quality on long-context tasks.
4.2 Grouped-Query Attention (GQA)
KV groups, each shared across query heads:
Llama-2 70B → Llama-3 70B reduced from (MHA) to . The cache shrank by at the cost of perplexity points.
4.3 Multi-head Latent Attention (MLA)
Cache a latent per token, with , and reconstruct K and V on the fly via low-rank up-projections. DeepSeek-V2: vs. nominal . Per-token cache shrinks by more than GQA.
(Note: only one tensor, not two — MLA stores a single latent and reconstructs K and V separately at compute time.)
4.4 KV-cache quantisation
Independently of architecture, the cache itself can be stored in lower precision. KV-cache fp16 → int8 halves the memory, at a small (sub-perplexity-point) quality cost. int4 KV cache is increasingly common in 2025–2026. The math:
A common production stack: Llama-3 70B with GQA- and int8 KV cache — KB/token, allowing batches of + at on a single H100-80GB.
5. The decode-loop, step-by-step
A concrete walk-through of one decode step at position .
- Embed the new token. . One row lookup; no cache.
- For each layer :
- Apply pre-norm.
- Compute new projections only: , , . (Heads reshaped from to .)
- Append to the layer's KV cache. New cache shape: per beam/sequence.
- Attention: query is one row ; keys/values are the entire cache. Output: . This is the only place the cache is read.
- Residual add, FFN, residual add.
- Final LayerNorm + unembed. . Logits over .
- Sampling. Apply temperature/top-/top- (Cap 10.2). Sample .
The expensive steps are #2's attention reads (memory-bandwidth bound) and the weight-matrix multiplications of the projections and FFN (memory-bandwidth bound at batch 1, compute-bound at large batch).
5.1 Per-step compute and memory traffic
For one decode step, batch , context :
- Weight matrices read once: bytes from HBM. Independent of and .
- KV cache read once: bytes from HBM. Scales linearly in and .
- New K/V written once: bytes. Negligible.
- FLOPs: for the matmul, for the attention reduction.
The arithmetic intensity — FLOPs ÷ bytes — determines whether the step is compute-bound or memory-bound:
At , intensity — far below the GPU's roofline ratio (typically – FLOPs/byte for fp16 on H100). The step is memory-bound: most of the wall-clock is moving the weight matrices through HBM, not actually multiplying.
At , intensity — above the roofline. The step becomes compute-bound; the weight bytes are amortised across sequences.
This is why batching matters: a batch of sequences pays the weight-read cost once per token-step, divided over outputs. Below batch ~ you are wasting GPU compute; above batch ~ you saturate it.
6. Long-context tax
At long contexts, the KV cache attention read dominates even the weight read.
The crossover happens at
For Llama-3 70B (GQA-, , fp16 weights, fp16 KV): the crossover is around . With batch , that's — so for context lengths , the KV cache attention is the dominant cost.
Long-context architectures (6.13, 7.13) need an attention compute strategy that is sub-quadratic in for the cache read. FlashAttention (10.5) is the standard answer for exact attention; sliding-window, sparse, and SSM hybrids (8.7–8.8) are the architectural alternatives.
7. Cache management policies
Beyond per-step mechanics, cache lifetime matters. Three policies in production:
- Per-request cache. Allocate on prompt arrival; free when the response completes. Simplest; suffers from memory fragmentation when concurrent requests have variable length.
- PagedAttention (Kwon et al., vLLM, 2023; 10.8). The cache is allocated in fixed-size blocks (e.g., 16 tokens), like virtual-memory pages. Different sequences share a block table; non-contiguous physical blocks can be logically contiguous for the model. Eliminates fragmentation; allows fine-grained eviction.
- Prefix caching. When many requests share a common prefix (system prompt, few-shot examples), cache the prefix's K/V once and let multiple requests share it. Latency win on prefill; memory win on cache reuse. Standard in production chat-LLM serving as of 2025.
Prefix caching is conceptually a first-class optimisation now — the per-request system prompt for an aligned chat model often runs to 1–5 K tokens, and caching its K/V across the user-facing batch of requests saves all of the prefill compute on those tokens, request after request.
8. Putting it together: an end-to-end serving stack
A modern (2026) LLM serving stack — call it Llama-3 70B + GQA- + int8 KV cache on H100-80GB — looks like:
- Weights occupy GB (fp16) or GB (int8 / GPTQ; see 10.6). Quantised weights free up tens of GBs for the KV cache.
- KV cache budget: GB after weights + activations. At KB/token (GQA-, int8 KV), the total cache supports tokens. Split across batch and context: at or at .
- Prefill batched across sequences; FlashAttention reduces SRAM/HBM traffic.
- Decode runs in continuous-batching mode: sequences enter and leave the batch as they arrive / finish. PagedAttention manages the cache.
- Prefix caching reuses system-prompt K/V across requests.
- Sampling: , top-, top-.
- Speculative decoding (10.4) wraps the decode step for an additional – throughput on conversational workloads.
This is roughly the architecture under any of the major commercial inference endpoints in 2026.
9. What we keep going forward
Three things.
- The KV-cache formula. bytes. The KV cache is the dominant memory consumer at production batch and context sizes.
- Prefill vs. decode. Prefill is compute-bound and parallel across prompt tokens. Decode is memory-bound at small batch (weight reads dominate) or attention-bound at large context (cache reads dominate). Batching amortises the weight read; sub-quadratic attention (FlashAttention or hybrids) addresses the cache read.
- Cache shrinkage stacks. GQA cuts by ; MLA cuts another via latent compression; KV-cache quantisation (int8/int4) cuts by –. Modern stacks combine all three.
Cap 10.4 next: speculative decoding. With the KV cache understood, we can ask the next question — can we use a cheap draft model to propose tokens, verify them in parallel with the target model, and get – wall-clock speedup with zero quality loss?
(a) State the KV-cache bytes formula. Compute the cache size for Llama-2 70B (, , , MHA, fp16) at batch 4, context 8192. Compare to an 80 GB GPU.
(b) Distinguish prefill from decode. Why is decode memory-bandwidth bound at batch 1? What does increasing batch buy you on each phase?
(c) State the per-token cache-bytes formula. Compute it for Llama-3 70B (GQA-) fp16 and again with int8 KV cache.
(d) Define arithmetic intensity for a decode step. Derive the rough form. Explain why is roughly where decode transitions from memory-bound to compute-bound.
(e) Sketch the order of operations of one decode step at position , naming where in the loop the KV cache is read and where it is written.
(f) Prefix caching: explain what is cached, what is shared across requests, and which phase (prefill / decode) it accelerates.