7 routes42 sections324 units

Unit 5.2 · about 5 h

319 / 324

Building a KV cache

A cache that shares layers, mixes sequences or misplaces positions returns fluent garbage with matching shapes. Ownership, layout and offsets are what make it correct.

  • implement

You can now

  • Implement per-layer KV allocation, append and single-token cached decode with absolute position offsets for the tiny transformer.
  • Explain MHA, MQA and GQA head mappings and the repeat_interleave rule for shared KV heads.
  • Explain KV tensor shapes and why each layer owns its cache for its own sequence.

Covers

  • Per-layer KV ownership and sequence identity
  • KV tensor shapes, layout, capacity and append state
  • Position offsets and RoPE consistency under cached decode
  • MHA, MQA and GQA KV head mapping

Study, in this order

3 steps

  1. Raschka `gpt_with_kv_cache.py`: per-layer cache with positions
    LLMs from Scratch companion - KV cache and GQA

    MultiHeadAttention (cache_k and cache_v buffers, use_cache append by torch.cat on dim 1, ptr_current_pos mask slice, reset_cache), GPTModel (current_pos with pos_ids arange, ModuleList loop, reset_kv_cache) and generate_text_simple_cached (full-prompt prefill then single-token loop)

  2. Raschka `ch04/04_gqa`: GQA head mapping and memory
    LLMs from Scratch companion - KV cache and GQA

    GroupedQueryAttention (num_kv_groups with group_size, \(K\) and \(V\) cache on dim 2, repeat_interleave mapping with the repeat versus repeat_interleave comment, q_positions versus k_positions mask) plus the README bytes formula with n_kv_heads and the 4096/32/32/32768 example

  3. Modern LLM Notebook 21 Sections 2 and 4: shapes and head sharing
    Modern LLM Notebook - KV cache and inference acceleration

    Section 2 shape evolution ([batch, num_heads, cached_seq_len, d_k] from [1,4,1,8] to [1,4,5,8]) and Section 4 MHA/MQA/GQA (32 \(Q\) heads with 32, 8 and 1 KV heads at 8K, the 8 \(Q\) with 2 KV repeat_interleave demo, savings ratio 32/8 = 4x)

    Depth · Skip Sections 5 to 8 and 10 (quantization, GGUF, PagedAttention, FlashAttention, batching) until their own units.

Focus on

  • Each layer owns its \(K\) and \(V\) tensors and each batch row owns its positions. Sharing a cache across layers or sequences mixes unrelated spaces.
  • Append grows the sequence dim by the new chunk only. Prefill appends the whole prompt at once, decode appends one token per step.
  • Positions are absolute. pos_ids and the mask pointer advance by the chunk length, so decode step \(k\) uses position current_pos plus \(k\).
  • GQA stores fewer KV heads and expands them with repeat_interleave. With 8 \(Q\) heads and 2 KV heads, heads 0 to 3 share KV head 0.

Reproduce closed-book

Write the cache-owning attention forward from scratch: buffers, append, pointer-based mask slice, absolute pos_ids, reset, and the GQA repeat_interleave mapping for 8 \(Q\) heads with 2 KV heads.

Traps

  • Forgetting reset_kv_cache between independent generations. Stale \(K\), \(V\) and pointers leak the old sequence into the new one.
  • Using repeat instead of repeat_interleave for grouped heads. Tiling maps the wrong KV head to each query group while shapes still match.
  • Restarting positions at 0 on every decode step. Absolute embeddings repeat and RoPE rotations reuse early angles, so logits diverge from the full prefix.

Practice

Raschka `ch04/03_kv-cache` tests: cached equivalence

test_gpt_model_equivalence_cached and test_gpt_model_equivalence_not_cached (30 new tokens from Hello, I am across base, cached and optimized models with torch.equal)

Run against the reference files, then re-run against your own per-layer cache in your own repository.

Self-test

  1. After a 4-token prefill, the first decode step feeds 1 token. What are the \(Q\) and \(K\) lengths and which mask row applies?

  2. With 32 \(Q\) heads and 8 KV heads, which \(Q\) heads share KV head 0, and why repeat_interleave?

  3. Why must decode pos_ids use current_pos, and what breaks for RoPE if they restart at 0?

  4. Two layers share one cache object to save memory. What fails?

Completion criterion

Stop when

Your own cache passes both equivalence tests with torch.equal and you can state the cache shape after each step.

Mark passed, then open 5.3 Only mark this when you can do it without notes.

Leads to

Comes after

Resources for this unit

  • LLMs from Scratch companion - KV cache and GQA
    Sebastian Raschkaprimaryimplementation
    Use ch04/03_kv-cache and ch04/04_gqa with the chapter model code. Add explicit per-layer ownership, position offsets, variable lengths, EOS compaction and MHA-versus-GQA cache arithmetic to the runnable comparison.
  • Modern LLM Notebook - KV cache and inference acceleration
    Walking Labsrequiredimplementation
    Use the KV-cache portions of English notebooks 11-mla-kv-cache and 21-inference-acceleration. Skip MLA and advanced acceleration as core work. Recalculate cache sizes and verify timing after warmup and explicit synchronization.

Also in this section

  • Stanford CS336 - Lecture 10 Inference
    Stanford Universityrequiredtheory
    Use the Spring 2026 inference lecture to connect KV arithmetic, phase behavior and batching vocabulary. Keep kernels, distributed serving and expensive performance experiments for the later tracks.
  • How to Scale Your Model - inference chapter
    JAX MLdepththeory
    After cache equivalence and phase measurement pass, read the inference chapter for arithmetic intensity, parallelism and production-scale reasoning. Treat it as the handoff to inference and performance tracks, not required foundation work.
  • AI Performance Engineering - inference-engine bridge
    Waferdepthreference
    Use Sections 4 and 5 only after this gate to choose the next inference, KV-cache, scheduling, quantization or distributed-serving resource. Do not treat its GPU and kernel material as unfinished LLM Foundations work.
  • No Magic - micro KV or paged-cache simulation
    No Magicoptionalpractice
    Use one small CPU simulation such as microkv.py or micropaged.py only to visualize state ownership. Do not present Python timing as GPU or serving-performance evidence.

Quick find

Search Michi

Type to search every route, section, unit, topic and resource.

Enter opens the first result Esc closes

Reference

Keyboard shortcuts

n
Continue to the first unit not passed
j / k
Next / previous unit
1 2 3
Toggle learned, practised, passed
/
Open search
?
Show this help
Esc
Close open panels