Agentic AI · L-Att
Prerequisite: the recap Probability.
I · From Text to Vectors
II · Attention
III · What a Token Costs
IV · Buying the Cost Back
A language model is a Transformer: a stack of identical layers that maps a sequence of tokens to a probability distribution over the next token. The Transformer Stack presents the complete architecture; Part I states what enters the stack, Part II how attention combines the positions of a sequence, Part III what one token costs in memory and in time, and Part IV how that cost is reduced:
The network computing $P(W_t\mid W_{1:t-1})$ (→ L-Intro) is a Transformer (Vaswani et al., 2017). For a language model it is a single causally masked stack: tokens flow from bottom to top through $L$ identical layers, and the top produces a distribution over the next token.
| Component | Mixes information across positions? |
|---|---|
| Multi-head self-attention | yes — the only component that does |
| Feed-forward MLP | no — every position is processed independently |
| Residual connections + layer normalization | no — they make a deep stack trainable |
Removing the causal mask gives a bidirectional stack — the same blocks, every position now
attending to every other, trained to fill in masked tokens instead of predicting the next one. That
is what a text-embedding model is: nomic-embed-text is a 137 M-parameter model of this shape
(Nussbaum et al., 2025), and it is the model behind the vector arithmetic of → L-Embed.
Interactive visualisations:
Because these LLM designations are technical misnomers compared to classic information theory and machine learning architectures, we avoid using these terms in the lectures to prevent confusion.
The question this part answers: what does the model actually receive?
Neither characters nor words. A model reads a sequence of token identifiers, replaces each by a learned vector, and has no notion of order until one is added explicitly. Two decisions are therefore settled before any attention is computed — how text is cut into tokens, and how a position is encoded — and both are visible in what an agent pays and in how far its context reaches.
The unit of text a model reads is a design decision with two failure modes.
Word-level — one identifier per word.
certain, uncertain and uncertainty occupy three unrelated
rows, so what is learned about one is unavailable to the others.Character-level — one identifier per character, or per byte.
un-, certain, -ty — must be composed from characters by the model
itself, which spends depth and parameters on what the word-level scheme supplied ready-made.Subword schemes take the middle — Tokenization (BPE), below.
Text is cut into tokens — subword units — by a learned scheme, most commonly Byte-Pair
Encoding (Sennrich et al., 2016; Gage, 1994). Tokens are not words, e.g. "tokenization" becomes "token" + "ization".
Begin with a base vocabulary of single characters, or of bytes; then repeatedly merge the most frequent adjacent pair of symbols into a new token, for a fixed number of merges.
Frequent sequences (ing, tion, whole common words) collapse into single tokens, while rare words remain split into pieces.
At inference the learned merges are applied greedily.
For details read chapter 2.4 Subword Tokenization: Byte-Pair Encoding of Jurafsky, Daniel, and James H. Martin. Speech and Language Processing. 3rd ed.
| Granularity | Vocabulary size | Sequence length | Unknown words |
|---|---|---|---|
| character / byte | tiny | very long | none |
| subword (BPE) | fixed, ≈ 30k–200k | moderate | none — every string is representable |
| word | very large | short | yes — out of vocabulary |
The middle row is the compromise the field settled on, and two of its consequences are paid for directly by an agent:
Each token identifier indexes a learned embedding vector. Attention is permutation-invariant — it computes a set of pairwise similarities and nothing in it refers to an index — so without position "dog bites man" and "man bites dog" would produce identical outputs. Order has to be injected.
| Scheme | Mechanism | Property |
|---|---|---|
| Sinusoidal (Vaswani et al., 2017) | add a fixed vector $\mathbf p_t$ of $\sin/\cos$ values at geometric frequencies | absolute; no parameters |
| Learned table | add a trained vector per position | absolute; defined only up to the trained length |
| Rotary — RoPE (Su et al., 2021) | rotate each query and key by an angle proportional to its position | the score $\mathbf q_i\cdot\mathbf k_j$ depends only on the relative offset $i-j$ |
RoPE is the standard in current models (Llama, Qwen) because the relative form generalises better to lengths not seen during training.
Context extension follows from that mechanism. The rotation angles are derived from a base
frequency, so a model trained at one length can be served at a longer one by rescaling the
base — at inference, without finetuning. nomic-embed-text is trained at 2048 tokens and served at
8192 in exactly this way (Nussbaum et al., 2025).
The core distinction: A recurrent neural network (RNN) carries information across the sequence length in a temporal hidden state $\mathbf h_t$ of fixed size, updated step by step. Standard softmax self-attention maintains no such sequence-level temporal state. Instead, every position computes attention directly over all previous token representations, and generation retains the raw Keys and Values themselves rather than a compressed temporal summary.
(Note: "Hidden state" here refers to a sequence-level recurrent memory state across time, not to be confused with the intermediate layer activations / hidden representations inside the model's MLPs.)
Sidenote: The lack of a fixed-size temporal state stems specifically from the softmax kernel in attention. If attention similarity were computed as an inner product of finite feature maps without softmax, it could be rewritten as a linear recurrence with a constant-sized state (Katharopoulos et al., 2020).
Relying on full softmax attention rather than a recurrent memory state provides parallel training and a single-hop path ($O(1)$ distance) between any two positions. However, it incurs three fundamental costs:
The first two are priced in the next part. The third is a theorem, and it closes this one.
Each position forms its new representation as a weighted average of the values of all positions, and the weights are computed from the content itself (Jurafsky & Martin, 2026, §7.1).
Let $X \in \mathbb{R}^{n \times d}$ be the input of one attention layer: $n$ positions, model dimension $d$, and row $\mathbf x_i \in \mathbb{R}^{d}$ the vector at position $i$ — in the first layer, the token embedding with its position injected as above. The sequence is the one written $W_{1:T}$ in the chain-rule notation; its length is counted here as $n$, since $T$ already names the sampling temperature and $T_{\max}$ the context window.
Three learned projections. One attention head holds
$$W^Q, W^K \in \mathbb{R}^{d \times d_k}, \quad W^V \in \mathbb{R}^{d \times d_v}, \qquad Q = X W^Q, \quad K = X W^K \ \in \mathbb{R}^{n \times d_k}, \qquad V = X W^V \in \mathbb{R}^{n \times d_v},$$
one matrix product projecting all $n$ positions at once. Queries and keys share the width $d_k$ because they are compared by a dot product; the value width $d_v$ is free in principle and is taken equal in practice, $d_k = d_v = d/h$ for $h$ heads — the $d_{\text{head}}$ of the KV-cache count. (The value matrix $V$ is not the vocabulary $V$ of the sampling notation; the collision is standard and the context disambiguates.)
Row by row, $\mathbf q_i = \mathbf x_i W^Q$, $\mathbf k_j = \mathbf x_j W^K$ and $\mathbf v_j = \mathbf x_j W^V$:
| Vector | Formed at | What it carries |
|---|---|---|
| Query $\mathbf q_i$ | position $i$ | the property position $i$ requires of the other positions |
| Key $\mathbf k_j$ | position $j$ | the property position $j$ advertises |
| Value $\mathbf v_j$ | position $j$ | the content position $j$ contributes when it is selected |
The computation, for the whole sequence in one expression (Vaswani et al., 2017, §3.2.1):
$$\operatorname{attn}(Q,K,V) \;=\; \underbrace{\operatorname{softmax}\!\Big(\frac{QK^\top}{\sqrt{d_k}}\Big)}_{A \;\in\; \mathbb{R}^{n \times n}} V .$$
Per pair of positions $(i,j)$ it performs four steps:
$$\mathbf z_i \;=\; \sum_{j=1}^{n} a_{ij}\,\mathbf v_j \;\in\; \mathbb{R}^{d_v}.$$
| Device | What it does | What follows from it |
|---|---|---|
| Multi-head | run $h$ heads in parallel on subspaces of width $d_{\text{head}} = d/h$, concatenate their outputs and project back to width $d$ | one head averages the values under one relation; $h$ heads admit $h$ of them, at the arithmetic cost of a single head of width $d$ |
| Causal mask | before the softmax, set the score of every pair with $j > i$ to $-\infty$, so that $a_{ij} = 0$ and position $i$ reads from positions $1,\dots,i$ alone | the representation at a position does not change when later tokens are appended — the premise of the KV-cache |
| Stacking | $L$ identical layers, each a multi-head attention block and a feed-forward MLP, both with a residual connection and layer normalization | later layers compose the relations the earlier ones found, and attention remains the only component that mixes positions |
Written out, with $m = 1,\dots,h$ indexing the heads:
$$\operatorname{MHA}(X) \;=\; \big[\operatorname{head}_1 \;\cdots\; \operatorname{head}_h\big]\,W^O, \qquad \operatorname{head}_m \;=\; \operatorname{attn}\!\big(X W^Q_m,\; X W^K_m,\; X W^V_m\big),$$
where $W^Q_m, W^K_m \in \mathbb{R}^{d \times d_k}$ and $W^V_m \in \mathbb{R}^{d \times d_v}$ are the head's own projections, $d_k = d_v = d_{\text{head}}$, and $W^O \in \mathbb{R}^{h\,d_{\text{head}} \times d}$ maps the concatenation back to the model dimension. Because $h\,d_{\text{head}} = d$, the concatenation is already of width $d$ and the stack's layers can be composed.
import numpy as np
def softmax(z, axis=-1):
z = z - z.max(axis=axis, keepdims=True); e = np.exp(z)
return e / e.sum(axis=axis, keepdims=True)
n, d = 4, 8 # 4 tokens, head dim 8
rng = np.random.default_rng(0)
Q, K, V = rng.normal(size=(n,d)), rng.normal(size=(n,d)), rng.normal(size=(n,d))
scores = Q @ K.T / np.sqrt(d)
mask = np.triu(np.ones((n,n)), 1) * -1e9 # causal mask (upper triangle -> -inf)
A = softmax(scores + mask) # attention weights (rows sum to 1)
out = A @ V
print("attention weights (causal):\n", np.round(A, 2))
Depth is fixed. One forward pass runs the same $L$ layers whatever the input, so the number of sequential steps available before a token must be emitted is a constant of the architecture and not a function of the problem. That is precisely what makes the pass parallelisable — and it carries a provable price.
Merrill & Sabharwal (2023) prove an upper bound on one pass of a transformer whose arithmetic precision is logarithmic in the input length: the whole pass can be simulated by a Boolean circuit whose depth does not grow with the input at all — the circuit class TC⁰. Under the assumptions standard in circuit complexity — none of the separations involved is proved — problems an ordinary sequential program solves easily are therefore beyond a single pass at any width: simulating a finite automaton, deciding whether one node of a directed graph reaches another, solving a system of linear equalities. Width does not repair this; the obstruction is depth per token, not parameter count. The authors name the phenomenon the parallelism tradeoff — any architecture as parallelisable as the transformer obeys limits of this kind.
The escape is more tokens, not more layers. Each generated token is a further forward pass, conditioned on everything written so far, so a chain of thought — intermediate tokens emitted before the answer — turns the context into a tape, and the reachable class grows with the number of intermediate steps: logarithmically many buy little, linearly many suffice to simulate automata, polynomially many give exactly P, the problems decidable in polynomial time (Merrill & Sabharwal, 2024; constructively for arithmetic, Feng et al., 2023). This is the reason a task is decomposed into steps at all (→ L-Decomp).
The question this part answers: what is paid, in memory and in time, for one token of context and one token of output?
Three quantities are countable in advance, and an agent engineer needs all three:
The first two grow with the context length and bound how long a session may become; the third does not depend on the context at all, and it is the one that decides how fast the agent answers.
The cache replaces the recomputation of the whole prefix by an append. One pass produces one token, so at step $t$ a single position is new: the positions $1,\dots,t-1$ are fixed, and the positions after $t$ do not exist yet. Forming the full sequence matrices at every step would therefore repeat work already done.
The input of step $t$ is one vector $\mathbf x_t \in \mathbb{R}^{1 \times d}$, the representation of the token produced at the previous step:
The key and value of the new position are appended to the matrices retained in GPU memory; those of the earlier positions are read from the cache rather than projected again:
$$K_{1:t} = \begin{bmatrix} K_{1:t-1} \\ \mathbf k_t \end{bmatrix} \in \mathbb{R}^{t \times d_k}, \qquad V_{1:t} = \begin{bmatrix} V_{1:t-1} \\ \mathbf v_t \end{bmatrix} \in \mathbb{R}^{t \times d_v}$$
The single query row attends to every retained position $1,\dots,t$:
$$\mathbf a_t = \operatorname{softmax}\!\Big(\frac{\mathbf q_t K_{1:t}^\top}{\sqrt{d_k}}\Big) \in \mathbb{R}^{1 \times t}, \qquad \mathbf z_t = \mathbf a_t V_{1:t} \in \mathbb{R}^{1 \times d_v}$$
No mask appears here: the positions a causal mask would remove are exactly those that have not been generated yet.
What the append saves. Without a cache, every step would project and attend over the entire prefix again — $\Theta(t\,d^2 + t^2 d)$ arithmetic at step $t$ and layer, hence $\Theta(n^2 d^2 + n^3 d)$ over a generation of $n$ tokens. With it, a step projects one position and forms $t$ scores: $\Theta(d^2 + t\,d)$, hence $\Theta(n\,d^2 + n^2 d)$ for the generation — the count the summary carries. The cache trades one factor of $n$ in arithmetic for memory, and that memory is countable exactly.
The query heads and the key/value heads are counted separately. Multi-head attention merely ties them together, and $n_{\text{kv}}$ is what the untying leaves behind in the formula.
| Scheme | $n_{\text{kv}}$ | KV-cache, against multi-head |
|---|---|---|
| Multi-head attention (MHA) | $h$ | baseline |
| Multi-query attention (MQA) — Shazeer (2019) | $1$ | $h$ times smaller |
| Grouped-query attention (GQA-$G$) — Ainslie et al. (2023) | $G$, one per group of $h/G$ query heads | $h/G$ times smaller |
Grouped-query attention is the general case: $n_{\text{kv}} = 1$ is multi-query and $n_{\text{kv}} = h$ is multi-head, so the choice is a dial rather than a switch. The name GQA-$G$ counts the groups, and a group holds exactly one key head and one value head, so $G$ and $n_{\text{kv}}$ are two names for one number; the formula's name is used here.
Eight query heads, and the key/value heads they read. The cache holds one key and one value per key/value head and per layer, so it is the lower row of each column — not the number of query heads — that $n_{\text{kv}}$ counts.
Every query head keeps its own projection $W^Q_m$ in all three schemes; what is shared is $W^K$ and $W^V$, and with them the rows written into the cache. The middle column is drawn at the ratio of the deployed shape — four query heads per key/value head, as in a model with 32 query heads over 8 key/value heads.
What is bought is bytes, not arithmetic — and bytes are what a generation step waits for. The FLOP count of a forward pass is unchanged, and so is the training speed; what falls is the quantity of memory held and reloaded per step. Generation is bounded by that traffic rather than by the arithmetic (Prefill vs. Decode, below), which is why a measurement in seconds improves although no operation was removed.
The price in quality is small, and smaller than that of the obvious alternatives. Multi-query costs 0.2 BLEU — the standard $n$-gram overlap score for translation — on the WMT14 English–German translation task, at a parameter count held equal; every simpler way of shrinking $K$ and $V$, fewer heads or narrower keys and values, costs two to five times as much (Shazeer, 2019).
Grouped-query attention is measured on T5-XXL, a model of 64 query heads. At $n_{\text{kv}} = 8$ one key/value head serves each group of eight query heads, so the cache is eight times smaller; the converted model stays within 0.1 average points of the multi-head checkpoint it came from and generates 5.4 times faster (Ainslie et al., 2023, Table 1).
Eight was chosen there as the middle ground of the group-count ablation, and open-weight models have kept the number, not the ratio: a model of 32 query heads is built with 8 key/value heads, four query heads to a group. That is the $n_{\text{kv}} = 8$ of the footprint calculation above.
Two units and three memories carry the arithmetic of this part.
The FLOP. A floating-point operation is one multiplication or one addition on floating-point numbers. The plural FLOPs counts operations — a quantity of work — whereas FLOP/s is a rate, the operations a processor completes per second.
The three memories. An accelerator stores data at three levels that differ by roughly two orders of magnitude in both capacity and bandwidth. The figures are those measured for an NVIDIA A100 by Dao et al., 2022, §2.1:
| Level | What it is | Capacity | Bandwidth |
|---|---|---|---|
| SRAM — static RAM | on-chip memory: registers, caches, and the shared memory of a streaming multiprocessor | $\approx 20$ MB | $\approx 19$ TB/s |
| HBM — High Bandwidth Memory | the stacked DRAM on the accelerator package, which holds the weights and the KV-cache | 40–80 GB | 1.5–2.0 TB/s |
| Host DRAM | main memory of the machine, reached over the PCIe bus | $> 1$ TB | $\approx 12.8$ GB/s |
VRAM is the generic name for the memory on a graphics card, HBM the technology by which current accelerators provide it, and SRAM the on-chip memory no model fits into.
Attention is bounded by memory traffic before it is bounded by arithmetic. A forward pass over a sequence of $n$ tokens forms, per head and per layer, the score matrix $S = QK^\top/\sqrt{d_k} \in \mathbb{R}^{n \times n}$ and from it the attention weights $A = \operatorname{softmax}(S)$ written above. A direct implementation writes both matrices to HBM and reads them again, which costs twice:
FlashAttention (Dao et al., 2022) removes that traffic without approximating the result, by three devices:
What remains in HBM is the input and the output alone, $O(n)$ instead of $O(n^2)$, and the result is exact: identical to the one the direct implementation computes, not an approximation of it.
What this does not change is the arithmetic. The number of comparisons is still $n^2$ per head and per layer; what the tiled kernel removes is the cost of moving them. Lowering the exponent itself requires a different attention mechanism (Beyond $O(n^2)$, below).
Because attention evaluates every token against every other token, processing a context of $n$ tokens requires $O(n^2)$ total compute operations (FLOPs), while the cached keys and values require $O(n)$ memory storage per layer. Both bound the usable context window.
The same layer runs in two shapes. Training sees the whole sequence at once; generation sees one new position at a time.
| Aspect | Training pass (whole sequence) | Generation step (with KV-cache) |
|---|---|---|
| Queries | the full matrix $Q \in \mathbb{R}^{n \times d_k}$ | one row, $\mathbf q_t \in \mathbb{R}^{1 \times d_k}$ |
| Keys and values | the full matrices $K \in \mathbb{R}^{n \times d_k}$, $V \in \mathbb{R}^{n \times d_v}$, projected from $X$ | the cache $K_{1:t}, V_{1:t}$, extended by one row per step |
| Causal mask | required — the scores of all pairs with $j > i$ are set to $-\infty$ | not required — positions after $t$ do not exist yet |
| Attention weights | the full matrix $A \in \mathbb{R}^{n \times n}$, lower triangular after the mask | one row, $\mathbf a_t \in \mathbb{R}^{1 \times t}$ |
| Attention arithmetic | $\Theta(n^2 d)$ for the whole sequence, in one parallel pass | $\Theta(t\,d)$ for the step, and the steps are strictly sequential |
The two compute the same function. With the same weights, the step returns exactly row $t$ of the training pass; what differs is which rows are formed, and when. That is why a model is trained on complete sequences and served one token at a time.
$$ \text{size} \approx 2 \cdot L \cdot n_{\text{kv}} \cdot d_{\text{head}} \cdot n \cdot b \ \text{bytes} $$
$2$ = keys + values; $L$ layers; $n_{\text{kv}}$ = the number of key/value heads, which need not equal the number of query heads $h$; $d_{\text{head}}$ their width; $n$ tokens of context; $b$ bytes per number. This is why long context is expensive.
def kv_cache_bytes(L, n_kv, d_head, n_tokens, bytes_per=2): # fp16 -> 2 bytes
return 2 * L * n_kv * d_head * n_tokens * bytes_per
# 32 layers; 8 key/value heads of width 128 -- the grouped-query shape below.
gb = kv_cache_bytes(L=32, n_kv=8, d_head=128, n_tokens=8192) / 1e9
print(f"KV-cache for 8k tokens ≈ {gb:.2f} GB")
Every token appends one key and one value per layer and per key/value head, so the cache is linear in the length of the context — and so is the work of one generation step: the score row $\mathbf q_t K_{1:t}^\top$ has one entry per retained position, and every one of them is formed anew at every step.
| What grows with the context | Why | What it amounts to |
|---|---|---|
| The bytes held | one key and one value per token, layer and key/value head | a 70 B model of the shape of Llama-3-70B — 80 layers, 8 key/value heads of width 128, fp16 — holds 1.3 GB of cache at 4 000 tokens and 42 GB at 128 000, per request and beside the 140 GB of weights. It is therefore the cache, not the model, that decides how many sessions a card serves at once |
| The bytes read, and the scores computed | step $t$ forms $t$ similarity scores per head and per layer, and reads the whole cache to form them | 10 scores at step 10, 10 000 at step 10 000: the cost of a token is not a constant of the model but is proportional to the context already accumulated |
Summed over a generation of $n$ tokens, $\sum_{t=1}^{n} t = \tfrac{n(n+1)}{2}$ — the quadratic cost of attention, seen from the generation side: a context that is re-read at every step. The first of the two costs is the one that can be reduced by construction, and the count of key/value heads is where it is done (MQA, GQA).
The compute half of that bound can be counted exactly. Write $L$ for the number of layers, $d$ for the model dimension, and $n$ for the context length. For the standard Transformer shape — attention output width $d$, feed-forward width $4d$, a ratio fixed by convention since the original architecture (Vaswani et al., 2017, §3.3) rather than derived — the non-embedding parameter count is (Kaplan et al., 2020, §2.1):
$$N \approx 12\,L\,d^{2}$$
where $N$ is the total non-embedding parameter count of the Transformer model ($12\,d^2$ per layer):
Two-thirds of $N$ is therefore feed-forward — $8\,d^2$ against attention's $4\,d^2$ per layer — and that is the part of the model in which knowledge from the training corpus is stored (Geva et al., 2021).
The forward-pass cost per token generated at sequence position $n$ is:
$$C_{\text{forward}} \approx \underbrace{2N}_{\text{weight matrix ops}} \;+\; \underbrace{2\,L\,n\,d}_{\text{attention dot products}} \quad\text{FLOPs per token,}$$
the factor $2$ throughout accounting for one multiplication and one addition per parameter/activation:
The second term is the only one carrying $n$. While linear per generated token at position $n$, summing this term across a full sequence of length $n$ yields $L n^2 d$ FLOPs—creating the quadratic wall when processing long contexts.
To find where attention FLOPs match weight matrix FLOPs per token, equate the two terms:
$$2N \;=\; 2\,L\,n\,d \qquad\implies\qquad 24\,L\,d^{2} \;=\; 2\,L\,n\,d \qquad\implies\qquad n \;=\; 12\,d$$
| Model Dimension ($d$) | Weight vs. Attention Crossover ($n = 12d$) |
|---|---|
| 2,048 | $\approx 24,576$ tokens |
| 4,096 | $\approx 49,152$ tokens |
| 8,192 | $\approx 98,304$ tokens |
The context-dependent attention cost is a small fraction of total compute only while $n \ll 12d$, and dominates beyond it. These crossover points lie well within modern context windows (e.g., 32k–128k+ tokens).
Because a backward pass costs roughly twice a forward pass ($C_{\text{backward}} \approx 2 \cdot C_{\text{forward}}$), the standard estimate quoted for training compute per token is:
$$C_{\text{train}} \approx 6N \quad\text{FLOPs per token}$$
This estimate must be carried with its condition attached: $6N$ accounts solely for weight matrix multiplications and ignores attention FLOPs. It holds accurately in the regime $n \ll 12d$ (understating cost by less than 10%, with error shrinking as model size $d$ increases; see Hoffmann et al., 2022, App. F). For long-context training where $n \gtrsim 12d$, the full $6N + 6Lnd$ formulation must be used.
Serving an inference request consists of two distinct phases with opposing resource bottlenecks:
| Phase | What happens | Parallel over tokens? | Bottleneck | Operational Intensity |
|---|---|---|---|---|
| Prefill (Prompt Processing) | Processes the full input prompt simultaneously; populates the initial KV-cache. | Yes — matrix-matrix ops over all $n$ prompt tokens in parallel. | Compute (FLOPs) | High ($O(n)$ ops per weight loaded) |
| Decode (Token Generation) | Generates tokens sequentially one-by-one; appends new key/value vectors to the KV-cache. | No — strictly sequential due to autoregressive dependency ($x_{t+1}$ depends on $x_t$). | Memory Bandwidth (HBM $\to$ SRAM) | Low ($O(1)$ ops per weight loaded) |
The bottleneck split stems from the ratio of arithmetic operations performed relative to bytes loaded from VRAM:
On modern GPU architectures—where peak compute capacity (TFLOPs) is roughly two orders of magnitude higher than memory throughput (TB/s)—decoding time is spent waiting for weights to transfer from memory, not on arithmetic (Shazeer, 2019).
While the weight-projection matrices in the prefill phase are compute-bound, standard attention introduces a severe memory bottleneck by constantly writing and reading intermediate $O(n^2)$ score matrices back and forth from slow GPU main memory (HBM). This causes high-speed Tensor Cores to sit idle, waiting on memory transfers.
FlashAttention solves this by tiling the computation into fast on-chip SRAM, keeping the $O(n^2)$ intermediate matrices entirely inside the processor. Though it does not reduce the actual arithmetic FLOP count, eliminating these HBM stalls delivers major gains:
In short, FlashAttention is a huge gain because it transforms a memory-thrashing operation back into a purely compute-bound task, unlocking the GPU's full hardware capacity.
PagedAttention is the decode-phase counterpart of FlashAttention. FlashAttention reduces the memory traffic of one attention computation; PagedAttention reduces the memory capacity that the KV-caches of many requests occupy (Kwon et al., 2023). The two act at different steps. During decoding, a server processes many requests as one batch, and the batch size is bounded by the number of KV-caches that fit into GPU memory. Earlier serving systems stored each request's cache as one contiguous tensor sized for the maximum possible sequence length, so the space reserved for tokens not yet generated — or never generated — was occupied but unused; the effective use of cache memory was measured as low as 20.4 %.
PagedAttention applies the paging of an operating system to the cache. The cache of a sequence is divided into blocks of a fixed number of tokens, which may lie anywhere in memory, and a per-request block table maps each logical block to a physical one, as a page table maps pages to frames. A block is allocated only when the sequence reaches it, so at most one partly filled block per request remains unused. Attention is computed block by block through the table, which makes the attention kernel 20–26 % slower; the larger batch that the recovered memory admits repays this, with 2–4× the throughput of FasterTransformer and Orca at the same latency. Because blocks are addressed through the table, several requests can refer to the same physical block, with reference counting and copy-on-write when one of them writes to it. This is the mechanism behind the prompt caching of the KV-cache slide, and it saves 37.6–66.3 % of the cache blocks in beam search, whose candidates share their history.
vLLM. PagedAttention is the basis of vLLM, the widely used open-source serving engine that the same authors built around it (vllm.ai).
For a batch size of 1, the theoretical maximum generation speed is bounded by memory bandwidth:
$$ \text{Generation Throughput} [\text{tokens}/\text{s}] \;\lesssim\; \frac{\text{GPU Memory Bandwidth } [\text{Bytes}/\text{s}]}{\text{Model Parameter Footprint } [\text{Bytes}/\text{token}]} $$
The two units are what make the bound a rate of tokens. A generation step reads every weight exactly once, so the parameter footprint measured in bytes is also the number of bytes that must cross the memory bus per generated token; dividing bytes per second by bytes per token leaves tokens per second.
(Note: This represents an optimistic upper bound because it excludes KV-cache memory traffic—which grows linearly with context length $n$—as well as kernel launch overheads and intermediate tensor activations.)
Including the KV-cache, the true bandwidth-bound formula for a single token step is:
$$\text{Generation Throughput} [\text{tokens}/\text{s}] \;\lesssim\; \frac{\text{GPU Memory Bandwidth } [\text{Bytes}/\text{s}]}{\big(\text{Model Weight Footprint} \;+\; \text{KV-Cache Footprint at Context Length } n\big) [\text{Bytes}/\text{token}]} $$
Three practices follow from that one inequality, and each of them changes a different part of it:
| Practice | What it changes in the bound | What it costs |
|---|---|---|
| Quantization | Fewer bytes per weight — halving them roughly doubles the throughput ceiling | Slight loss in model accuracy |
| Mixture of Experts (MoE) | Only a fraction of parameters is activated per token, reducing total weight data transferred per step (e.g., Qwen3.5-35B-A3B activates ~3B of 35B parameters) | Higher VRAM footprint relative to active parameter compute capacity |
| Batching | Streams the weights once through the GPU memory bus to generate tokens for multiple requests simultaneously | Increased latency (wait time) for individual requests |
| Key/Value-Head Sharing | Reduces bytes of KV-cache transferred per step — addressing the hidden term omitted by the simple bound that scales linearly with context length $n$ | Minor impact on generation quality |
The third row (Batching) is the fundamental reason why a hosted API is inexpensive per token while a single laptop is not: a laptop running a single-user request (Batch Size = 1) must pay the full memory-bandwidth cost of reading the entire model weight footprint for every single token generated. A hosted API provider reads those same weights once from VRAM but amortizes that hardware cost across 64 or 128 concurrent user requests in a single memory pass.
Meanwhile, the fourth row (KV-Head Sharing) enables this economic scale. By drastically shrinking the memory required for each user's KV-cache, it frees up the VRAM capacity necessary to hold those large batches of concurrent users in memory at the same time.
The question this part answers: if decoding is bounded by bandwidth, how is more than one token obtained from a single read of the weights?
The bound $\text{tokens/s} \lesssim \text{bandwidth} / \text{model bytes}$ has two sides, and the practices of the previous part reduce only the denominator. This part raises the numerator: a pass that verifies several candidate tokens emits more than one of them for the same traffic. Two sources of candidates are developed — a second, cheaper model, and extra output heads trained into the model itself — and the first thing to establish about both is that the text they produce is unchanged.
If a decode pass is paid for in (memory) bandwidth, then scoring one token and scoring several cost almost the same — "the latency of parallel scoring of short continuations … is comparable to that of sampling a single token from the larger target model" (Chen et al., 2023). So let something cheap propose the next few tokens and let the expensive model check them all in one pass (Leviathan et al., 2023).
| Symbol | Name | Role |
|---|---|---|
| $M_p$, distribution $p$ | target model | the model we actually want to sample from |
| $M_q$, distribution $q$ | draft model | much faster, and weaker |
| $\gamma$ | drafting horizon | how many tokens $M_q$ proposes before $M_p$ verifies |
One round.
A round emits between 1 and $\gamma+1$ tokens — never zero, because a rejection is corrected rather than discarded.
The property that makes the scheme usable. It is a modified rejection sampling, and the tokens it emits are distributed exactly as $p$ — the output is what the target model would have produced on its own, "within hardware numerics". Speculative decoding is therefore not a trade of quality for speed, which is worth separating from two things that are:
| Technique | Adopted for | Effect on the output distribution |
|---|---|---|
| temperature, top-$p$ | shaping the output — they buy no time | changes the distribution that is sampled from, by design |
| quantization | fewer bytes per weight, and hence bandwidth | approximates the model, at a cost in accuracy |
| speculative decoding | wall-clock time alone | identical distribution |
Of the three, only quantization and speculative decoding are accelerations. A sampling rule stands beside them because it is the other place in the decode loop where the emitted distribution is decided: temperature and top-$p$ depart from $p$ deliberately, quantization departs from it as a side effect of storing the weights in fewer bits, and speculative decoding does not depart from it at all.
The draft need not be a separate model: a model trained to predict several tokens ahead can propose for itself — multi-token prediction, treated below.
The switch is in the runtime, not in the model. Each engine names the two settings — where the
draft comes from, and $\gamma$ — its own way: llama.cpp takes the draft module as a second model
file (-md) and the horizon as --spec-draft-n-max, tuned by raising it until the token rate stops
rising (Gille, 2026); Ollama binds the draft into the model definition (DRAFT in the Modelfile) and
exposes the horizon as the per-request option draft_num_predict (Ollama, 2026). Both require a
checkpoint that carries the extra prediction heads.
Why $\kappa$ cannot be chosen small. Summing the envelope condition over the vocabulary gives $1 = \sum_x p(x) \le \kappa \sum_x q(x) = \kappa$, so $\kappa \ge 1$ for any pair of distributions, and $\kappa = 1$ forces $p = q$ — the case in which no proposal was needed. The tightest legal choice is $\kappa = \max_x p(x)/q(x)$, the single point at which the proposal under-weights the target most; one such token raises $\kappa$, and the acceptance probability $1/\kappa$ then falls for every draw because of it.
Neither property survives contact with decoding, and the modification repairs both:
| Classical | Obstacle in decoding | Modification |
|---|---|---|
| envelope $p \le \kappa q$ | $\kappa$ must bound $p(x)/q(x)$ over the whole vocabulary at every position, and $1/\kappa$ collapses as $\kappa$ grows | drop the envelope, $\kappa = 1$: accept with $\min\!\big(1,\ p(x)/q(x)\big)$ |
| discard a rejected draw | evaluating $p$ is the expensive target pass, so a discarded draw is a round that cost everything and returned nothing | repair instead of retry: draw from the residual $(p-q)_+ = \max(0,\,p-q)$ — exactly the mass the accept step could not deliver |
The repair is available only because the vocabulary is finite and both distributions arrive as explicit softmax rows, so the residual can be formed and normalised in $O(|V|)$.
The classical loop draws one proposal at a time; verification draws none. In the box above, each attempt needs a fresh evaluation of $p$ at a fresh $x$, which is why it is a loop over evaluations of the target. In decoding, the $\gamma$ drafted tokens are already fixed before the target is consulted, so one forward pass of $M_p$ over $\text{prefix} + [x_1, \dots, x_\gamma]$ produces every row the round needs at once — the causal mask makes row $i$ depend only on what precedes position $i$, exactly as in a training pass over a known sequence:
$$p_1(x),\ \dots,\ p_{\gamma+1}(x) \;\leftarrow\; M_p(\text{prefix}),\ \dots,\ M_p\big(\text{prefix} + [x_1, \dots, x_\gamma]\big).$$
Only the draft is sequential: $M_q$ is run $\gamma$ times, once per proposed token. The accept/reject walk that follows touches no model at all — it is arithmetic over $\gamma$ pairs of rows already in memory, and its $\gamma+1$-st row $p_{\gamma+1}$ is the target's prediction for the position after the last draft, which is where the free extra token comes from.
$$ \begin{array}{l} \textbf{Verify-And-Emit}(x_{1:\gamma},\ q_{1:\gamma},\ p_{1:\gamma+1}) \\ \hline \textbf{Input: } \text{drafted tokens } x_i \sim q_i \text{, the draft rows } q_i \text{, the target rows } p_i \text{ from one pass} \\ \textbf{Output: } \text{between } 1 \text{ and } \gamma+1 \text{ tokens, distributed as } p \\ \hline 1: \quad n \leftarrow \gamma \qquad \text{// how many drafted tokens are kept} \\ 2: \quad \textbf{for } i = 1 \textbf{ to } \gamma \\ 3: \quad \qquad r \sim U[0,1] \\ 4: \quad \qquad \textbf{if } r > p_i(x_i) / q_i(x_i) \ \textbf{ then } n \leftarrow i - 1; \ \textbf{break} \\ 5: \quad \textbf{if } n < \gamma \ \textbf{ then } t \sim \operatorname{norm}\big((p_{n+1} - q_{n+1})_+\big) \qquad \text{// the rejected position, repaired} \\ 6: \quad \textbf{else } t \sim p_{\gamma+1} \qquad \text{// nothing rejected: one token for free} \\ 7: \quad \textbf{return } x_1, \dots, x_n,\ t \\ \hline \end{array} $$
Reading the paper's one-line form. Lines 1–4 are written by Leviathan et al. (2023) as a single expression,
$$n \leftarrow \min\Big(\big\{\, i-1 \ \big| \ 1 \le i \le \gamma,\ r_i > \tfrac{p_i(x_i)}{q_i(x_i)} \,\big\} \cup \{\gamma\}\Big),$$
which says: the first rejected position, minus one — and $\gamma$ if nothing was rejected. The set collects the positions that fail the test; $\min$ takes the earliest of them, because a rejection invalidates every draft after it; the appended $\{\gamma\}$ is the default that makes the minimum defined when the set is empty. Drawing all $\gamma$ uniform variates $r_i$ in advance, as the expression does, changes nothing — the ones past the first rejection are discarded.
With $\kappa = 1$ the accept step alone no longer produces $p$; the residual draw is what restores it. Let $x \sim q$ be the drafted token.
What acceptance delivers. The round emits $x$ by acceptance with probability
$$q(x)\cdot\min\!\Big(1,\ \frac{p(x)}{q(x)}\Big) \;=\; \min\big(p(x),\,q(x)\big),$$
so the accept step delivers the pointwise minimum of the two distributions and never more. Its total mass $\alpha = \sum_x \min\big(p(x), q(x)\big)$ is the overlap of draft and target, below $1$ whenever $q \neq p$ — so some probability is always left undelivered.
What is missing. Token $x$ falls short of its target probability by
$$p(x) - \min\big(p(x),\,q(x)\big) \;=\; \max\big(0,\ p(x) - q(x)\big) \;=\; (p-q)_+(x),$$
and these deficits sum to $1 - \alpha$, which is exactly the probability of a rejection. Drawing from the normalised residual $p'(x) = (p-q)_+(x) / (1-\alpha)$ therefore returns to each token precisely the mass the accept step could not deliver:
$$\underbrace{\min\big(p(x),q(x)\big)}_{\text{emitted by acceptance}} \;+\; \underbrace{(1-\alpha)\,p'(x)}_{\text{emitted by resampling}} \;=\; \min\big(p(x),q(x)\big) + (p-q)_+(x) \;=\; p(x).$$
The emitted token is distributed exactly as $p$ for any proposal $q$ (Chen et al., 2023, Thm. 1). A poor draft model costs acceptance rate — $\alpha$ is small and rounds are short — but never correctness; and where the classical scheme discards a rejected draw, the round still emits one token for the target pass it has already paid for.
$\alpha$ is the share of the target distribution the draft already covers. At one position the accept test passes with probability
$$\alpha \;=\; \sum_x q(x)\cdot\min\!\Big(1,\ \frac{p(x)}{q(x)}\Big) \;=\; \sum_x \min\big(p(x),\,q(x)\big),$$
which is the overlap the accept step delivers, computed above. Two readings of the same number:
Within a round, $\alpha$ is taken to be the same at every position and independent across positions (Leviathan et al., 2023). It is measured for a given model pair and task, not predicted from model sizes.
Step 1 — how far the accepted prefix reaches. Write $n$ for the number of drafted tokens a round accepts, $0 \le n \le \gamma$. The walk stops at the first rejection, so reaching $n \ge i$ requires the first $i$ drafts all to have been accepted:
$$P(n \ge i) \;=\; \alpha^{i}, \qquad i = 0, 1, \dots, \gamma.$$
Equivalently $P(n = k) = \alpha^{k}(1-\alpha)$ for $k < \gamma$, and $P(n = \gamma) = \alpha^{\gamma}$: a geometric count of consecutive successes, capped at $\gamma$ because no more than $\gamma$ tokens were drafted.
Step 2 — the emitted count. A round emits the $n$ accepted drafts plus exactly one further token — the repaired residual draw if there was a rejection, the free draw from $p_{\gamma+1}$ if there was not — so $N = n+1$, between $1$ and $\gamma+1$. Rather than summing over outcomes, count how far the round reaches:
The expectation adds over the indicators of these events — the tail-sum identity for a variable on the non-negative integers — and the sum is a finite geometric series:
$$\mathbb{E}[N] \;=\; \sum_{i=0}^{\gamma} P(N > i) \;=\; \sum_{i=0}^{\gamma} P(n \ge i) \;=\; \sum_{i=0}^{\gamma} \alpha^{i} \;=\; 1 + \alpha + \alpha^{2} + \dots + \alpha^{\gamma} \;=\; \frac{1-\alpha^{\gamma+1}}{1-\alpha}.$$
Two ends check the expression: at $\gamma = 0$ it is $1$ — nothing is drafted and the round is an ordinary decoding step — and as $\alpha \to 1$ it approaches $\gamma+1$, every draft accepted plus the free token.
$c$ prices one draft run in units of one target run — the time for a single run of $M_q$ divided by the time for a single run of $M_p$ (Leviathan et al., 2023, Def. 3.7). Since both are bandwidth-bound at batch size one, the ratio is in that limit the ratio of the bytes each pass moves, the draft's weights against the target's: a $1$ B draft beside a $70$ B target is of the order of $c \approx 0.015$, with the fixed overheads of a step — sampling, dispatch, the host round trip — raising it. A draft that is not smaller, or that is served over a network, has no small $c$ and nothing to offer.
$c$ is thus a property of the pair and of the runtime; $\alpha$ is a property of the pair and the
task. The third quantity, the drafting horizon $\gamma$, is the only one the operator sets — the
number of tokens drafted before a verification pass, exposed as --spec-draft-n-max and
draft_num_predict.
Step 3 — what a round costs, measured in units of one target pass, since that is what ordinary decoding spends per token. The round runs the draft model $\gamma$ times, at $c$ each, and the target model once — one pass scores all $\gamma+1$ positions, so it counts as one and not as $\gamma+1$, which is the parallel-scoring premise the whole scheme rests on:
$$\text{cost per round} \;=\; \gamma c + 1.$$
Step 4 — divide. Ordinary decoding emits one token per target pass, that is one token per unit of cost. The expected walltime improvement is therefore the ratio of the two rates, tokens per unit cost against tokens per unit cost (Leviathan et al., 2023, Thm. 3.8):
$$ \boxed{\ \frac{\mathbb{E}[N]}{\gamma c + 1} \;=\; \frac{1-\alpha^{\gamma+1}}{(1-\alpha)\,(\gamma c + 1)}\ } $$
Being a ratio of rates it is dimensionless: it states by what factor the same hardware produces tokens, and assumes nothing about how fast that hardware is.
The numerator saturates in $\gamma$ — a further drafted token helps only while it is still likely to be accepted, the gain decaying like $\alpha^{\gamma}$ — while the denominator grows linearly, because $c$ is paid for every drafted token, accepted or not. Hence an interior optimum $\gamma^{*}$, and hence a horizon that is tuned per model rather than set once.
How $\gamma^{*}$ is found. Not by differentiating the factor: the stationarity condition is transcendental in $\gamma$, and $\alpha$ is in any case not known in advance — it is a property of the model pair and of the task, measured rather than predicted, and it drifts with the prompt. The horizon is therefore set by measurement on the workload that will be served: raise $\gamma$ one step at a time and keep the last value before the measured token rate stops rising (Gille, 2026). Observed optima are small and model-specific — between $2$ and $7$ across the four local models of that test — and precision is not needed, because the factor is flat near its maximum.
| Limit | The factor becomes | Reading |
|---|---|---|
| $\alpha \to 1$ (perfect draft) | $\dfrac{\gamma+1}{\gamma c+1}$ | grows with $\gamma$, bounded by $1/c$ |
| $\alpha \to 0$ (useless draft) | $\dfrac{1}{\gamma c+1} < 1$ | a bad draft model makes decoding slower |
The condition for any gain at all (Cor. 3.9): if $\alpha > c$, some $\gamma$ yields a speedup, of at least $\frac{1+\alpha}{1+c}$. The draft must agree with the target more often than it costs — nothing else is required of it, neither accuracy nor good training. At $c \approx 0.05$ the bar is very low; at $c \approx 0.5$ it is a genuine constraint.
What is spent to buy the time. Every rejected draft is arithmetic discarded, so the operation count rises; the weights and KV-cache, however, are read once per round instead of once per token. Speculative decoding spends arithmetic to buy bandwidth — which is why it belongs to decode and has nothing to offer prefill, which is compute-bound and already parallel over tokens.
# Speculative decoding: expected speedup, and the optimal number of drafted tokens.
# Leviathan et al. (2023), Thm. 3.8: (1 - a**(g+1)) / ((1 - a) * (g*c + 1))
def expected_tokens(alpha, gamma):
if alpha == 1.0:
return gamma + 1
return (1 - alpha ** (gamma + 1)) / (1 - alpha)
def speedup(alpha, gamma, c):
return expected_tokens(alpha, gamma) / (gamma * c + 1)
c = 0.05 # draft model costs 5% of a target pass
print(f"cost coefficient c = {c}\n")
print("gamma |" + "".join(f" a={a:<5.2f}" for a in (0.9, 0.8, 0.6, 0.3)))
for gamma in range(1, 11):
row = "".join(f" {speedup(a, gamma, c):6.2f} " for a in (0.9, 0.8, 0.6, 0.3))
print(f"{gamma:5d} |{row}")
print("\noptimal gamma per acceptance rate:")
for a in (0.9, 0.8, 0.6, 0.3):
best = max(range(1, 51), key=lambda g: speedup(a, g, c))
print(f" alpha={a:.2f} -> gamma*={best:2d} (speedup {speedup(a, best, c):.2f}x)")
# A useless draft model is worse than no speculation at all:
print(f"\nalpha=0.05, gamma=8 -> {speedup(0.05, 8, c):.2f}x (below 1.0 = slower)")
In standard speculative decoding, draft tokens originate from a second, smaller model. An alternative approach uses a single model equipped with multiple internal look-ahead heads to predict several tokens in a single step. To accomplish this, the model must be trained to predict multiple tokens from the start, allowing its own auxiliary heads to propose draft candidates. This requires a fundamental shift in the loss function, not merely a change in the decoding procedure (Gloeckle et al., 2024).
Writing $w_{1:t}$ for the context, and $n$ — the paper's letter — for the number of future tokens predicted at each position:
| Objective | Predicted at position $t$ | |
|---|---|---|
| baseline | $L_1 = -\sum_t \log P_\theta(w_{t+1} \mid w_{1:t})$ | the next token |
| generalisation | $L_n = -\sum_t \log P_\theta(w_{t+1:t+n} \mid w_{1:t})$ | the next $n$ tokens at once |
What makes $L_n$ tractable. Route everything through a shared latent $z_{1:t} = f_s(w_{1:t})$ — the output of the transformer trunk $f_s$ — and let the $n$ heads be conditionally independent given $z_{1:t}$:
$$L_n = -\sum_t \sum_{i=1}^{n} \log P_\theta(w_{t+i}\mid z_{1:t})\cdot P_\theta(z_{1:t}\mid w_{1:t}), \qquad P_\theta(w_{t+i}\mid w_{1:t}) = \operatorname{softmax}\big(f_u(f_{h_i}(f_s(w_{1:t})))\big).$$
Why a look-ahead loss should make a model better, and not merely faster, is argued twice in the paper, both times avowedly speculatively: once from the variance of a position's value, once from the mutual information between neighbouring tokens.
A choice point is a position whose alternatives differ widely in value —
$\sigma_\pi(w_{1:t}) = \sqrt{\operatorname{Var}_{w_{t+1}\sim\pi}\big[v_\pi(w_{1:t+1})\big]}$, where
$v_\pi(w_{1:t})$ is the value of a prefix, the expected return of the sequence completed from it
under the model's own policy $\pi$ (the value of an MDP, → L-ToT). In code, return True against
return False is such a position — one token fixes what the function means — while the name of
the variable it is assigned to is inconsequential, every alternative continuing equally well; in a
derivation, the sign chosen in a step is a choice point, the letter chosen for an index is not.
Where the up-weighting comes from. Every token is the target of exactly $n$ loss terms, head $i$ predicting it from position $t = m-i$, so the count alone does not separate the two kinds. What separates them is what a token drags with it: an inconsequential token decides nothing that follows, while a choice point decides the continuation, so a prediction of any token after it is a prediction about it as well. Counting the terms that reach a choice point at position $m$ or past it: from $t = m-1$ all $n$ heads do, from $t = m-2$ the last $n-1$, and so on to $t = m-n$, where only head $n$ does —
$$n + (n-1) + \dots + 1 \;=\; \frac{n(n+1)}{2} \quad\text{against the}\quad n \quad\text{of an inconsequential token,}$$
an up-weighting by $\tfrac{n+1}{2}$. Nothing labels which positions these are.
The size of those terms points the same way. A choice point is by its definition the harder thing to foresee several positions in advance, so the look-ahead heads $2, \dots, n$ assign the realised token a low probability and their cross-entropy — the loss $L_n$ sums exactly these terms, $-\log P_\theta$ of the token that was realised — is large there. With a softmax output the gradient at the logits is $\hat{p} - e_{w}$, the predicted distribution minus the one-hot vector of the realised token $w$, and its magnitude grows as the probability assigned to $w$ falls. The extra heads therefore contribute most of their gradient at exactly the positions where the continuation is decided — a weighting that no annotation produced and no hyper-parameter controls.
The second argument establishes the same conclusion from information theory (Gloeckle et al., 2024). $W_{t+1}$ is the next token and $W_{t+2}$ the second-next; every entropy below is conditional on the context $w_{1:t}$ that the heads share, and that conditioning is suppressed to keep the identity readable.
What a head is charged with. Write $H(W) = -\sum_w P(w)\log P(w)$ for the entropy of a random variable: the average information its value carries, and therefore the uncertainty that remains about it even for someone who knows the true distribution. A head's expected cross-entropy is smallest exactly when the head's distribution is the true one, and that smallest value is $H(W)$ — training removes the model's error, never the entropy of what is predicted.
In standard teacher-forced training, the single model head predicts $W_{t+1}$ given $w_{1:t}$, and then predicts $W_{t+2}$ given $w_{1:t+1}$ (where $W_{t+1}$ is fed as a teacher-forced input token).
The total target loss for generating two consecutive steps autoregressively is the joint entropy $H(W_{t+1}, W_{t+2})$. By the chain rule of entropy:
$$H(W_{t+1}, W_{t+2}) = H(W_{t+1}) + H(W_{t+2} \mid W_{t+1})$$
Using the definition of mutual information $I(A;B) = H(A) - H(A \mid B)$ — the uncertainty about $A$ that knowing $B$ removes — we rewrite $H(W_{t+1})$ as $H(W_{t+1} \mid W_{t+2}) + I(W_{t+1}; W_{t+2})$. Substituting this back into the joint entropy gives:
$$H(W_{t+1}, W_{t+2}) = H(W_{t+1}\mid W_{t+2}) \;+\; \mathbf{1\,I(W_{t+1};W_{t+2})} \;+\; H(W_{t+2}\mid W_{t+1}).$$
Because teacher forcing places the realised $w_{t+1}$ in the context at step $t+1$, the model need not have encoded $I(W_{t+1};W_{t+2})$ in its state $z_{1:t}$ to predict $W_{t+2}$: that mutual information is paid for only once.
A two-head multi-token model predicts $W_{t+1}$ and $W_{t+2}$ simultaneously from the one trunk state $z_{1:t}$, the heads being conditionally independent given it. Head 2 therefore never conditions on the realised $w_{t+1}$: the smallest loss it can reach is $H(W_{t+2})$ and not $H(W_{t+2} \mid W_{t+1})$, so the two heads together are charged the sum $H(W_{t+1}) + H(W_{t+2})$.
The identity. The rearranged definition $H(A) = H(A \mid B) + I(A;B)$, applied once in each direction and added, gives:
$$H(W_{t+1}) + H(W_{t+2}) \;=\; H(W_{t+1}\mid W_{t+2}) \;+\; \mathbf{2\,I(W_{t+1};W_{t+2})} \;+\; H(W_{t+2}\mid W_{t+1}).$$
| Term | What it holds | Example |
|---|---|---|
| $I(W_{t+1};W_{t+2})$ | the part of the next token that constrains what follows | an opening parenthesis; the keyword that fixes the shape of a block |
| $H(W_{t+1}\mid W_{t+2})$ | what varies in the next token without bearing on the one after | a synonym, a stylistic choice |
| $H(W_{t+2}\mid W_{t+1})$ | what is new at the second position and cannot be read off the first | the next argument of a call |
The two objectives differ in exactly one coefficient:
| standard autoregressive loss | two-head multi-token loss | |
|---|---|---|
| target loss | $H(W_{t+1}, W_{t+2})$ | $H(W_{t+1}) + H(W_{t+2})$ |
| expansion | $H(W_{t+1}\mid W_{t+2}) + \mathbf{1\,I} + H(W_{t+2}\mid W_{t+1})$ | $H(W_{t+1}\mid W_{t+2}) + \mathbf{2\,I} + H(W_{t+2}\mid W_{t+1})$ |
| coefficient on $I(W_{t+1};W_{t+2})$ | $\mathbf{1}$ | $\mathbf{2}$ |
The shared part enters the sum from both sides and so carries the coefficient $\mathbf{2}$, while each conditional entropy keeps the coefficient $1$: a look-ahead loss therefore weighs a token by what its successors depend on, and leaves what nothing depends on at the weight it had — the same conclusion the choice-point count gives, by a different argument.
The gap this narrows. Training is teacher-forced: every position is predicted from the true prefix, so the loss asks only for the next token given a history that never contains the model's own mistakes. Generation has no such prefix — an error at one position stands in the context of every position after it, which is the exposure bias between the two regimes. Charging the model for what a token implies, and not only for the token, narrows that gap from the training side.
Heads $2,\dots,n$ are trained look-ahead predictors, so the model drafts for itself: heads $2..n$ propose and head $1$ verifies — blockwise parallel decoding (Stern et al., 2018), speculative decoding "without the need for an additional draft model". The cost coefficient collapses, and the improvement reduces to the tokens-per-round factor alone,
$$\frac{1-\alpha^{\gamma+1}}{(1-\alpha)(\gamma c + 1)} \;\xrightarrow[\;c\to 0\;]{}\; \frac{1-\alpha^{\gamma+1}}{1-\alpha} \;\le\; \frac{1}{1-\alpha},$$
with $\gamma \le n-1$: the drafting horizon is fixed by the architecture rather than chosen at run time. Measured on a 7 B model with greedy self-speculative decoding (Gloeckle et al., 2024):
| Model | heads used | speedup | tokens per forward pass |
|---|---|---|---|
| $n=4$, code | 2 / 3 / 4 | 1.85× / 2.54× / 3.05× | 1.94 / 2.78 / 3.50 |
| $n=8$, byte-level | 8 | 6.39× | 7.04 |
The heads must be pre-trained this way; attaching them to a finished next-token model gives markedly weaker acceptance.
Where the cost went. A draft model is paid for at inference — a second set of weights in VRAM, and the $\alpha$-versus-$c$ bet. Multi-token prediction is paid for at pre-training, and then decodes fast with no draft model at all: the same bottleneck, with the cost moved to a place where it is paid once.
The quadratic term is the matrix of scores, not the model. Attention compares each position with every position at or before it, so one layer forms $O(n^2)$ comparisons over a sequence of length $n$: summed over the sequence, the attention term of the forward-pass cost is $L\,n^{2}d$ FLOPs, and the cache that spares a generation step those recomputations grows linearly in $n$ at every layer. Nothing else in the model behaves this way — a projection and a feed-forward layer cost the same at position $1$ as at position $100{,}000$.
So there are two levers, and each has a price. Either restrict what a position may compare itself with, and lose the scores that were not computed; or stop keeping the prefix as a growing set of vectors, carry a state of fixed size instead, and lose whatever did not fit into it. Every family below pulls one of the two.
| Cost | Where it was derived | Families, and what each of them gives up |
|---|---|---|
| Quadratic compute, linear cache | the $2\,L\,n\,d$ attention term, and the crossing at $n = 12d$ | sparse and local attention — a position attends to a window or a fixed pattern rather than to all predecessors; linear (kernelised) attention (Katharopoulos et al., 2020) and its delta-rule variants (DeltaNet) — the same product regrouped so that a fixed-size state replaces the cache, at the cost of the softmax; state-space models (Mamba — Gu & Dao, 2023) — a recurrence whose state is selected by the input; hybrids that keep a few full-attention layers among many cheap ones |
| Bandwidth-bound generation | one pass over all weights per token | MoE (mixture of experts) — route a token through a fraction of the parameters; quantization — fewer bytes per weight; speculative decoding / MTP — more tokens per pass; KV-cache compression — MQA and GQA, and MLA (multi-head latent attention), which stores keys and values in a lower-dimensional latent |
| Positional decay at long range | the rotation angles of RoPE | base scaling — slow the rotations, so the angles the model was trained on cover a longer context; ALiBi (attention with linear biases) — no positional vector at all, a distance penalty added to the scores instead |
The first column is the lecture's three findings, in the order they were derived; the third is where the field went with each. (A fast-moving area — treat the named models as examples to verify, not as a list to learn.)
lecture-Att-exercises.ipynb: softmax-attention & a KV-cache VRAM calculation by hand; the
modified rejection-sampling rule traced over a four-token vocabulary until the emitted
distribution comes out as $p$; and the speculative-decoding speedup
$\frac{1-\alpha^{\gamma+1}}{(1-\alpha)(\gamma c+1)}$ — find $\gamma^{*}$ for a given $\alpha, c$.
lecture-Att-lab.ipynb: explore a BPE tokenizer, implement scaled dot-product attention in
NumPy, measure prompt-caching latency in Ollama, and separate prefill from decode: time a long
prompt with a short answer vs. a short prompt with a long answer, and compare the measured tokens/s
against the bandwidth bound.
| Part | What to retain |
|---|---|
| I · From Text to Vectors | text is cut into subword tokens, and cost and context are counted in them. Attention is permutation-invariant, so order is injected — by addition (sinusoidal, learned) or by rotation (RoPE), whose relative form also permits context extension at inference. |
| II · Attention | self-attention, $\operatorname{softmax}(QK^\top/\sqrt{d_k})V$, is the only component that mixes positions. Having no hidden state buys parallel training and a single-hop path between any two positions, paid for with $O(n^2 d + n d^2)$ compute per layer and a KV-cache that grows with the context. Depth per token is fixed, which places one pass inside TC⁰; the escape is more tokens, not more layers. |
| III · What a Token Costs | $N \approx 12Ld^2$ and $C_{\text{forward}} \approx 2N + 2Lnd$ per token, so attention overtakes the weights at $n = 12d$ — also the condition under which the usual $C \approx 6N$ training estimate holds. Prefill is compute-bound, decode is memory-bandwidth-bound: $\text{tokens/s} \lesssim \text{bandwidth}/\text{model bytes}$, the single fact behind quantization, MoE and batching. |
| IV · Buying the Cost Back | speculative decoding — a cheap draft proposes $\gamma$ tokens, the target verifies them in one pass, and modified rejection sampling keeps the output distribution exactly $p$; the speedup $\frac{1-\alpha^{\gamma+1}}{(1-\alpha)(\gamma c+1)}$ has an interior optimum, and $\alpha > c$ is the condition for any gain. Multi-token prediction trains several look-ahead heads on a shared trunk against shifted targets; the heads then draft for the model itself at $c \approx 0$, moving the cost of fast decoding from inference to pre-training. |
Three numbers to carry out of this lecture. A KV-cache of $2\,L\,n_{\text{kv}}\,d_{\text{head}}\,n\,b$ bytes; a decode ceiling of bandwidth divided by model size; and $n = 12d$, the context length at which attention stops being a footnote.
The context window is the agent's working memory. How it is filled from a corpus far larger than itself is the subject of retrieval (→ L-RAG).
Peer-reviewed papers
Preprints & other non-peer-reviewed papers
Textbooks & monographs
Blogs, documentation & other web sources
llama.cpp on consumer GPUs (single runs, not a controlled benchmark; use for the mechanism and the ordering dense > MoE, not for exact factors).DRAFT Modelfile directive binding a draft model to a model definition, and draft_num_predict as the per-request drafting horizon.