firehose> #llmops

Prefill and Decode Phases

LLM inference is not one workload but two, with opposite bottlenecks. Prefill ingests the whole prompt at once — every token runs through every transformer layer to build the representation the model needs before it can emit a single output token. Because the entire prompt is available simultaneously, prefill is a big dense matrix multiply: it is compute-bound, and it is the lag you feel before the first token appears (time-to-first-token). Decode then emits one token at a time; each step is a small matrix multiply against a large cached context that must be read out of GPU memory. Arithmetic intensity collapses, and decode becomes memory-bound — the GPU spends most of each step waiting on VRAM reads rather than computing. This split is not an implementation detail of any engine; it falls out of the shape of autoregressive attention. It is also the reason every other serving optimization exists: KV Cache makes decode tractable, Paged Attention makes decode's memory usable, and Speculative Decoding spends the compute that decode leaves idle.

The practical consequence is that a serving stack running one phase at a time under-uses the hardware in both. A prefill running to completion starves active decode streams (visible as stuttering token output when a long prompt arrives); a batch of pure decode leaves compute units idle between memory reads. Chunked prefill is the direct answer: prioritize decode requests in the batch, then fill the remaining compute budget with chunks of pending prefill.

Claims


Linked from