Walk through what actually happens during the prefill phase of an LLM forward pass.
Prefill is the one-shot parallel forward pass that processes the whole prompt at once, builds the KV cache, and produces the first output token.
Picture someone settling down to read a long book and then answer a question about it. They first read the entire book end to end, taking notes on each chapter so they can flip back without re-reading. That note-taking pass is prefill. Once the notes are ready, answering follow-up questions is fast because they consult the notes instead of re-reading the book. For an LLM, the notes are the KV cache, the book is the prompt, and the first sentence of the answer is the first thing they say after finishing the read. Prefill is one big concentrated reading session; decoding the answer afterward is many small consultations of the notes.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
LLM inference has two phases that share almost nothing in common. Prefill is one big parallel pass over the input prompt. Decode is a sequential loop that emits output tokens one at a time. The same neural network runs in both phases, but the matrix shapes, the GPU utilization, the bottleneck, and the optimizations are completely different. Anyone designing an inference system needs to think about these two workloads separately, because techniques that help one often do nothing for the other.
This deep dive walks through what physically happens during prefill, why its arithmetic intensity puts it on the compute-bound side of the roofline plot, how it populates the KV cache so that decode does not have to recompute everything from scratch, and what production optimizations like chunked prefill and prompt caching actually do under the hood. By the end, you should be able to look at any inference benchmark and reason about how much of the time is prefill cost versus decode cost.
What happens inside prefill, layer by layer
Prefill takes the entire input prompt and runs it through the model in a single parallel forward pass. Concretely:
-
Tokenize and embed. The prompt is tokenized into a sequence of
Ttoken IDs and converted into an initial[T, d_model]activation tensor via the embedding layer. -
Per-layer transformer block. At each layer, the activation goes through layer norm, then a self-attention sub-block, then a feed-forward sub-block. Inside attention, the activation is projected to Q, K, and V via three linear projections, each producing a
[T, d_model]tensor (or[T, n_heads * d_head]after reshaping). -
Attention computation. Scaled dot-product attention is computed as
softmax(QK^T / sqrt(d_k)) V. TheQK^Tmatrix has shape[T, T], which is the part that scales quadratically with prompt length and motivates FlashAttention. A causal mask is applied so positionican only attend to positions<= i. -
KV cache write. The K and V tensors computed at each layer are written to the KV cache, indexed by layer, head, and position. The cache is laid out in HBM such that the decode loop can later read it sequentially.
-
Feed-forward and residual. After attention, the activation passes through the feed-forward block (typically two linear layers with a SwiGLU or GELU nonlinearity in between), and residual connections plus layer norm wrap each sub-block.
-
Output head. After the last transformer layer, a final layer norm and the output projection map the activation at position
T-1(the last prompt token) to a logits vector over the vocabulary. The first output token is sampled from these logits.
At the end of prefill, two things have happened. The KV cache is fully populated for the entire prompt across every layer, and the first output token has been emitted. The decode loop can now start from a warm cache.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
| Aspect | Prefill | Decode |
|---|---|---|
| Compute pattern | Parallel over prompt length T | Sequential, one token per step |
| Arithmetic intensity | High (hundreds of FLOPs/byte) | Low (~1 FLOP/byte) |
| Bottleneck | Compute-bound (tensor cores) | Bandwidth-bound (HBM) |
| KV cache role | Writes the entire cache at once | Appends one K/V pair per step |
| Latency contribution | Dominates TTFT | Dominates total generation time |
Real products, models, and research that use this idea.
- Anthropic and OpenAI both expose prompt caching, which skips the prefill compute for repeated prefixes; this would be impossible if prefill state were not a clean, reusable object.
- FlashAttention v2 and v3 (used in vLLM, SGLang, TensorRT-LLM) optimize the attention computation that dominates long-prompt prefill.
What an interviewer would ask next. Try answering before peeking at the approach.
QWhy is prefill compute-bound while decode is bandwidth-bound on the same hardware?
Arithmetic intensity. Prefill's batch dimension is the prompt length, so each weight is reused thousands of times per matmul. Decode's batch dimension is 1, so each weight is read for a single multiply. The roofline plot puts prefill far right (compute) and decode far left (bandwidth).
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Treating prefill and decode as 'the same forward pass'. They have different shapes, different bottlenecks (compute-bound vs bandwidth-bound), and different optimization techniques.
60 second bullets to scan on the way to the call.
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.