Hello! Welcome back to our course on Generative Sequence Modeling.
Introduction
In our previous lesson, we demystified the autoregressive process, seeing how decoder-only models generate text one token at a time in a predict -> sample -> append loop. We concluded by highlighting a significant inefficiency: at every step, the model re-processes the entire sequence from the beginning. For a 100-token prompt and a 100-token generation, this involves an enormous amount of redundant computation.
This lesson tackles that problem head-on. Our learning outcome is to explain the KV cache mechanism and how it avoids redundant computation during autoregressive inference. The KV cache is not an approximation; it is a fundamental optimization that makes the fast, interactive experience of modern LLMs possible. By the end of this lesson, you will understand what the KV cache is, why it works, and how it transforms the computational complexity of text generation from quadratic to linear.
1. The Redundancy Problem in Autoregressive Generation
To understand the solution, we must first pinpoint the exact source of the waste. Recall that in the attention mechanism, each token's input embedding is projected into three vectors: a Query (Q), a Key (K), and a Value (V).
- Query: "What am I looking for?"
- Key: "What information do I contain?"
- Value: "What information I will provide if attended to?"
The critical insight is that for any given token in the input sequence, its Key and Value vectors are always the same. They are computed by multiplying the token's embedding by the fixed projection matrices and . No matter how many new tokens are generated afterwards, the Key and Value for "The" in "The cat sat on the mat" will never change.
However, in the naive generation loop, we recompute them at every single step.
To build a strong intuition for this problem, let's start with a conceptual overview.
Understanding and Coding the KV Cache in LLMs from Scratch
The following article, 'Understanding and Coding the KV Cache in LLMs from Scratch' by Sebastian Raschka, provides an excellent, easy-to-follow explanation of this redundancy.
Please read the first two sections: 'Overview' and 'What Is a KV Cache?'. Then, read the section 'How LLMs Generate Text (Without and With a KV Cache)'. Focus on the diagrams that illustrate how the Key and Value vectors for early tokens are wastefully recomputed.
As the article illustrates, the attention mechanism is constantly re-running the same calculations on the initial prompt tokens. Now, let's get a more formal look at where this happens in the attention formula.
KV Cache Explained: Efficient Attention for LLM Generation
This article, 'KV Cache Explained', provides a more technical breakdown of the same problem.
Please read the section titled 'The Redundancy Problem in Autoregressive Generation'. Pay close attention to the description of the 'Prefill phase' and the subsequent steps. The final part of the section, with the summation formula, quantifies exactly how this redundancy leads to quadratic scaling.
2. The KV Cache Solution: Compute Once, Reuse Often
The solution is as elegant as the problem is clear: if the Key and Value vectors for past tokens don't change, we should compute them once and store them. This is the essence of the KV cache.
The generation process is split into two phases:
- Prefill: The model processes the entire input prompt at once. It computes the K and V vectors for all prompt tokens and saves them in the cache.
- Decode: For each subsequent step, the model only needs to perform computations for the single new token. It computes the new token's Q, K, and V vectors. It then appends the new K and V to the cache. Finally, it uses the new token's Q vector to attend to all the K and V vectors stored in the cache (from the prompt and all previously generated tokens).
This creates an important asymmetry:
- Keys and Values are cached because they represent the static properties of tokens already in the sequence.
- Queries are not cached because a query is always "new" for the token being generated, asking how it should relate to all the history that came before it.
The following image provides a clear visual summary of this two-phase process.

To further solidify this, the following video provides a helpful analogy.
Let's watch a segment from the 'KV Cache Crash Course' video by AI Anytime, which explains why the cache is so important and uses a simple analogy to make the concept stick.
Watch from 18:19 to 21:02. Pay attention to the 'teacher taking attendance' analogy—it's a great way to think about why you wouldn't re-check information you already have.
3. Cache Structure and Mathematical Formulation
Since you appreciate the underlying math, let's formalize this. With a KV cache, the computation at each decode step t becomes much simpler. We only compute the projections for the single new token's embedding, :
We then append the new key () and value () vectors to our cache:
The attention output for the new token, , is then computed using the new query and the entire history stored in the cache:
This is not an approximation; it's an algebraically equivalent way to get the exact same result as the naive method, but with drastically fewer computations.
This cache must be maintained for each attention head and for each layer of the Transformer, as they all learn unique projection matrices.
For a deeper dive into the mathematical details and the cache's structure, the "KV Cache Explained" article is an excellent resource.
KV Cache Explained: Efficient Attention for LLM Generation
Let's return to the 'KV Cache Explained' article to see the formal details.
Please read the sections 'Mathematical Formulation' and 'Cache Structure'. These sections will show you precisely how the cache is updated and organized within the model's architecture, including the typical tensor shapes.
4. Implementation and Performance Impact
Seeing this in code makes the concept even more concrete. The implementation involves adding buffers to store the cache and a flag to switch between the initial prefill and the subsequent decode steps.
Understanding and Coding the KV Cache in LLMs from Scratch
Let's go back to Sebastian Raschka's article, which walks through a clear, from-scratch implementation.
Please read the sections 'Implementing a KV Cache from Scratch' and 'Using the Cache in Generation'. Trace the five implementation steps, noticing how the MultiHeadAttention class is modified to store and retrieve from the cache, and how the generate_text_simple_cached function handles the prefill and decode logic differently.
The core change is in the generation loop. Without a cache, you feed the entire sequence model(idx) at each step. With a cache, you do one prefill model(idx, use_cache=True), and then feed only the single next_idx in the decode loop: model(next_idx, use_cache=True).
This change from quadratic to linear complexity has a massive impact on inference speed. The Welch Labs video provides a striking example of the KV cache's memory footprint, which is the trade-off for this speed.
How DeepSeek Rewrote the Transformer [MLA]
This video on DeepSeek's MLA explains the computational shortcut of KV caching and quantifies its memory cost.
Watch from 07:31 to 10:45. The animation starting at 07:31 visually demonstrates how only the final row of the attention pattern needs to be computed. Then, the section from 09:58 calculates the memory cost for a real-world model (DeepSeek R1), highlighting the memory-for-compute trade-off.
As the video shows, while the computational savings are huge, the memory required to store the cache for long sequences can become a new bottleneck—a problem that advanced architectures like DeepSeek's MLA (which we will study later) are designed to solve.
Conclusion
In this lesson, we have explored the KV cache, a simple yet profoundly important optimization for LLM inference.
Key Takeaways:
- The Problem: Naive autoregressive generation is inefficient because it repeatedly recomputes Key and Value vectors for tokens that have not changed, leading to quadratic computational complexity.
- The Solution: The KV cache stores these Key and Value vectors after they are computed once. In subsequent steps, the model only computes projections for the new token and reuses the cached values.
- The Impact: This changes the computational complexity of generation from quadratic, , to linear, , with respect to the sequence length .
- The Trade-off: The speed-up comes at the cost of memory. The cache size grows linearly with the sequence length and can become substantial for large models and long contexts.
- Structure: The cache is maintained on a per-layer, per-head basis, as each of these components learns independent K and V projections.
Preview of the Next Lesson:
We have now completed our foundational module on Transformer architecture basics. We've seen how tokens become vectors, how attention creates context, and how autoregressive generation with the KV cache produces text efficiently.
Next, we will begin our deep dive into the Modern Transformer Components that define state-of-the-art models. Our first lesson in this new module will explore RMSNorm and the SwiGLU activation function, two key architectural tweaks that improve training stability and model performance, moving us closer to understanding the design of models like Qwen 2.5 and DeepSeek-V3.