Naive attention has a quadratic memory bill that capped GPT-3 at 2K tokens. Then in 2022 Tri Dao's FlashAttention paper found a way to never write the N×N matrix to slow GPU memory — and quietly, every frontier lab swapped it in. Claude Sonnet 4.6 at 200K context, Gemini 1.5 Pro at 2M tokens, Llama 3.3 at 128K — none of it works without the tricks in this lesson.
Learning Objectives
After this lesson, you will be able to:
Explain why naive attention is O(N²) in both compute and memory and how FlashAttention's IO-aware tiling avoids ever writing the full N×N attention matrix to GPU HBM
Tell Multi-Head, Multi-Query, and Grouped-Query Attention apart by what they share — and pick the right one based on inference latency, memory budget, and quality targets
Use a KV cache to skip recomputing keys and values during autoregressive generation, and recognize when paged attention (vLLM) is the right next step for serving
Diagnose a long-context bottleneck (memory? throughput? latency?) and reach for the right tool — FlashAttention, sliding window, attention sinks, or linear attention — instead of just buying more H100s
Don't worry if "FlashAttention" sounds like a paper you have to skim — the core insight is one sentence: never write the full attention matrix to slow memory. Once you see the picture, every optimization in this lesson is a variation on that theme.
The attention output is mathematically the same whether you compute it block-by-block or all at once. FlashAttention exploits this by tiling the computation across blocks of Q, K, V that fit in SRAM. The catch is making the softmax work block-by-block — softmax requires the row max and row sum across the entire row, but you only have a block at a time.
The trick: maintain running statistics (running max m_i, running sum ℓ_i) and rescale outputs as new blocks arrive. This is the online softmax algorithm (Milakov & Gimelshein 2018), wrapped around tiled matmul.
FlashAttention-2 (2023) rebalanced work between thread blocks for better GPU utilization on long sequences, hitting ~1.7x over FlashAttention-1. FlashAttention-3 (2024) added FP8 / asynchronous Tensor Cores for H100s, hitting ~2x over FA-2 on top of that. By 2026, every serious training and inference stack — PyTorch's scaled_dot_product_attention, HuggingFace, vLLM, TensorRT — defaults to a FlashAttention variant.
The KV cache (covered next) stores keys and values from prior tokens for fast autoregressive generation. For a model with H heads, the KV cache is proportional to H. Cut the number of K and V projections, and you cut KV-cache memory linearly.
Multi-Head Attention (MHA). Every head has its own Q, K, V. Best quality, biggest cache.
Multi-Query Attention (MQA). H query heads, 1 shared K head, 1 shared V head. Cache is H times smaller. Quality drop on training-from-scratch is real but small; on retrofitting, it can be severe.
Grouped-Query Attention (GQA). H query heads, G key/value groups (G < H). Cache is H/G times smaller. With G = H/8, you keep almost all of MHA's quality and most of MQA's savings.
You serve a 70B Llama at 100k context to thousands of concurrent users. Which combination?
GQA is the quality/memory sweet spot Llama 2/3 chose. FlashAttention is non-negotiable for the prefill phase at 100k context — naive attention would OOM instantly. Paged KV cache (vLLM-style) is what lets you batch unrelated requests together by sharing GPU memory blocks dynamically. MHA loses the memory war at this scale; full MQA gives up too much quality. Buying H100s helps but doesn't scale.
Autoregressive generation is "predict next token, append, repeat." Every step the model runs attention over the entire prefix plus the new token. Without a cache, each step does N forward passes — O(N²) total work per generated token. With a KV cache, only the new token's K and V are computed; everything prior is reused.
Without cache: O(N²) compute per generated token. With cache: O(N) compute per token plus O(N) memory growth.
pythonplayground.py · Pyodide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Tests · Verify the windowed output differs from full attention but produces stable outputs (no NaN), and that receptive field grows linearly with depth.
Naive KV-cache management allocates one contiguous block per request. Result: severe fragmentation when requests have varying lengths — a 90% wasted GPU memory budget on real serving traffic.
vLLM's PagedAttention treats the KV cache like an OS treats RAM. Memory is split into fixed-size blocks (typically 16 tokens). Each request keeps a block table mapping logical positions to physical blocks. Free blocks return to a pool. Adjacent requests can share blocks (e.g., shared prefixes for parallel sampling) via copy-on-write.
Block table: logicali⟼physicalj(j may not be contiguous)
For very long sequences (1M+ tokens), even FlashAttention's O(N²) compute is impractical. Several approximations dominate:
Sliding-window attention (Mistral). Each token attends only to the last W tokens; receptive field grows with depth.
Attention sinks (StreamingLLM, Xiao 2023). The first few tokens accumulate all the attention from later positions; preserve them and you can stream indefinitely without quality collapse.
Linear attention (Performer, Linformer, Longformer). Kernel approximations that bring attention to O(N) at the cost of some accuracy.
State Space Models (Mamba, RWKV). Covered in the Mamba lesson; RNN-like recurrence with parallel training.
Sliding-window and attention-sink tricks were the 2023 answer. The 2025 wave is a generation more sophisticated: instead of one fixed sparsity pattern, modern long-context models route each query through several attention pathways at once and let the model learn which pathway matters where. Four designs dominate the frontier.
NSA (Native Sparse Attention, DeepSeek 2025) ships in DeepSeek-V3 and is the most influential of the new wave. NSA runs three parallel attention pathways for every query: a compression branch that attends to coarse block summaries (one key/value per 64-token block, giving a low-resolution view of the entire context), a selection branch where a small router scores blocks and the query attends only to the top-k highest-scoring blocks at full resolution, and a sliding-window branch that always attends to the most-recent W tokens for local fidelity. The three branches' outputs are fused with learned gates. The whole pattern is trained end-to-end and stays hardware-friendly because each branch is itself a dense, kernel-friendly matmul.
MoBA (Mixture of Block Attention, Moonshot 2025) powers Kimi K1.5's million-token context. MoBA chunks the KV-cache into blocks, scores each block against the query through a lightweight gating network, and lets the query attend only to its top-k blocks. Unlike NSA's hand-designed three pathways, MoBA's routing is fully learned and looks closer to a Mixture-of-Experts router operating over context blocks rather than over MLP experts. The gating is differentiable enough to train from scratch, which is what distinguishes MoBA from earlier retrieval-style "select-then-attend" approaches.
Hybrid local + global stacks in Gemma 2 and Llama 4 alternate layer types: roughly every fourth layer uses dense global attention while the rest use sliding-window-only attention. The intuition is that you do not need every layer to see every token — a few global layers per stack are enough to mix long-range information, and the rest can stay cheap. This is a tiny architectural change that buys most of the cost benefit of sparse attention without changing the kernel.
Mamba2-Hybrid in Jamba 1.5 (AI21) goes further by mixing layer types: some layers are state-space (Mamba) blocks with O(N) recurrence, others are full attention, and a sprinkle of MoE FFN layers sits between them. The attention layers handle the few global lookups; the SSM layers carry the long-distance state cheaply. Jamba 1.5 Mini fits 256K context on a single 80 GB GPU because most of its layers no longer pay the O(N²) bill.
Quick check
You are choosing a long-context attention strategy for a 1M-token coding assistant that runs on a single H100. Which trade-off correctly maps each technique to its strongest use case?
Attention's wall is memory bandwidth, not FLOPs. Naive attention writes O(N²) bytes to HBM. FlashAttention's IO-aware tiling drops HBM traffic to O(N), giving 5-10x wall-clock speedup with no quality change.
GQA is the modern default. Between Multi-Head (full quality, full cache) and Multi-Query (smallest cache, quality risk), Grouped-Query Attention is the sweet spot every frontier 70B+ model has chosen since Llama 2.
The KV cache is what makes inference cheap. Without it, generating each token costs O(N²) compute; with it, O(N). It also dominates inference memory, which is why GQA matters so much.
PagedAttention is the OS analogy that 24x'd serving. Chunking the KV cache into fixed blocks and tracking them with a block table eliminates fragmentation and enables prefix sharing.
Long context (>32k) requires a stack, not a single trick. FlashAttention + GQA + sliding window + attention sinks together; or switch to alternative architectures (Mamba, hybrid).
Attention's quadratic wall is the central engineering challenge of the LLM era. Next we look at the inference-side optimizations — quantization, speculative decoding, and the serving stacks that turn a 70B model into a 200ms-per-token API.