KV Cache
Without caching, generating token 100 requires recomputing attention for all 99 previous tokens. KV cache stores each layer's K and V matrices, appending only the new token's K/V each step. Critical for production inference speed.
Instead of re-reading an entire book from page 1 every time you want to write the next sentence, you keep bookmarks (cache) at each page you've already read and only read the new page.
Visual Workflows
Start here — study each diagram, then use + / − to zoom if needed.
Scroll inside the frame · use + / − to zoom
Key Takeaways
- 1.KV cache stores previously computed Key and Value tensors during autoregressive generation — avoiding redundant recomputation and making inference O(n) per token instead of O(n²). During decode: for each new token, compute Q, K, V for that token only.
- 2.Append new K, V to cached K, V from all previous tokens. Attention: Q_new @ [K_cache; K_new]ᵀ → softmax → weighted sum of [V_cache; V_new].
- 3.Memory cost: 2 × num_layers × num_heads × seq_len × d_k × bytes_per_element. For Llama-70B at 4096 context: ~10GB just for KV cache.
- 4.Optimizations: Multi-Query Attention (MQA), Grouped-Query Attention (GQA) reduce KV heads, PagedAttention (vLLM) manages cache like virtual memory.
Real Example
Scenario
Generating 100 tokens without cache: 1+2+3+...+100 = 5050 attention computations. With KV cache: 100 (one per new token). ~50× speedup for long sequences.
What you would do
In Transformer & ML Foundations, apply KV Cache to this scenario: Generating 100 tokens without cache: 1+2+3+. Identify the inputs, run the technique, validate the output, and note one thing you would monitor in production.
Practice Task
Open the Code Walkthrough below and run it locally. Change one parameter related to KV Cache (e.g. model, temperature, top_k, or tool name), observe the difference in output, and write 2–3 sentences explaining what changed.
Code Walkthrough
Highlighted lines show where KV Cache happens in the code.
1import torch # import dependencies2
3# Simplified KV cache concept4class KVCache: # define a data structure or component5 def __init__(self): # define a reusable function6 self.keys = []7 self.values = []8
9 def update(self, k, v): # define a reusable function10 self.keys.append(k)11 self.values.append(v)12 return torch.cat(self.keys, dim=2), torch.cat(self.values, dim=2) # return the result13
14cache = KVCache() # key line for KV Cache15# Prefill: process prompt tokens, populate cache16# Decode: for each new token17for step in range(5):18 q = torch.randn(1, 8, 1, 64) # query for new token only19 k = torch.randn(1, 8, 1, 64) # key for new token only20 v = torch.randn(1, 8, 1, 64) # value for new token only21 all_k, all_v = cache.update(k, v) # key line for KV Cache22 # attention: q @ all_k.T -> softmax -> @ all_vCheat Sheet
Quick recap
quick ref- •Cache K,V per layer per token
- •Prefill: batch all prompt tokens
- •Decode: one token at a time
- •GQA: shared KV heads
- •PagedAttention: vLLM
- •Memory ∝ seq_len × layers × heads
Common Mistakes
- ✕Not using KV cache in production — inference is unusably slow
- ✕Underestimating KV cache memory for long contexts
- ✕Confusing KV cache with model weight caching
- ✕Forgetting cache invalidation when context changes mid-conversation