Skip to content
The Generation Loop

01.01 · Concept · Free

Forward Pass vs Generation

Distinguish training forward passes from autoregressive generation and explain why inference is a fundamentally different workload.

This video is hosted by Klay so it plays even when YouTube blocks embedding.

Curated for this lesson

The Generation Loop

Forward Pass vs Generation

Best explanation of Forward Pass vs Generation from Stanford Online.

Autoregressive inference is a sequential serving workload, not just a forward pass without backpropagation. Training evaluates many known token positions together under teacher forcing. Generation must prefill a prompt, repeatedly produce one next-token distribution, sample or select from it, update cache state, and schedule many uneven requests.

What this lesson answers

  • why is LLM inference not just forward pass
  • how does autoregressive generation differ from training
  • what are prefill and decode in LLM serving

Notes

A training forward pass computes logits for many known target tokens in parallel, while autoregressive generation repeatedly runs the model to sample exactly one next token per sequence and feeds it back into the input. Training: , compute , logits , loss in one parallel pass. Generation loop: initialize prompt , then for : , , , append token. With KV cache, step becomes instead of recomputing the whole prefix.

Example: let , prompt length , vocab , generate tokens. Training forward on two length-4 examples computes logits shape , i.e. predictions for 8 token positions in one call, then teacher-forces against known labels. Generation prefill computes prompt logits once for shape and stores KV cache for 4 positions. Decode step 1 runs only the last token per sequence, produces logits shape , samples e.g. ; step 2 consumes , samples ; step 3 consumes , samples . The workload changed from one large parallel matrix-heavy pass to many latency-sensitive sequential decode iterations.

1. Parallelism: training parallelizes over tokens; decoding parallelizes mostly over batch because time dimension is sequential: cannot be known before sampling . 2. Cost split: generation has prefill cost attention over the prompt and decode cost with KV cache, growing one token at a time; without KV cache decode would be recomputation. 3. Memory: training stores activations for backprop, roughly proportional to layers ; inference stores KV cache, roughly . 4. Batching: training batches are static rectangular tensors; generation batches are dynamic because requests have different prompt lengths, output lengths, stop conditions, and sampling parameters. 5. Objective: training computes loss under teacher forcing; generation performs search or sampling using greedy, top-, top-, temperature, beam search, penalties, and stop tokens.

This distinction is explicit in serving systems. In vLLM, prefill/decode scheduling is handled around `vllm/engine/llm_engine.py` and `vllm/core/scheduler.py`, with paged KV cache managed by block allocators such as `vllm/core/block_manager.py`; model execution separates prompt/prefill and decode metadata in worker/model-runner paths such as `vllm/worker/model_runner.py`. HuggingFace TGI implements the continuous generation loop in Rust around `router/src/infer.rs` and batching/scheduling in `router/src/batcher.rs`, while model backends consume prefill/decode batches and return next-token logits through server code under `server/text_generation_server/`. TensorRT-LLM exposes the same split via its inflight batching executor, with generation logic in `cpp/tensorrt_llm/batch_manager/` and Python runtime examples using `tensorrt_llm.runtime.GenerationSession`.

The practical consequence is that inference is not “training without backward.” For a 32-layer model with , , FP16 KV, one sequence of length uses GB of KV cache, before weights and workspace. If 100 users each decode one token at a time, the server must schedule 100 tiny dependent steps, not one static tensor batch. This is why production engines optimize KV cache paging, continuous batching, prefix caching, speculative decoding, and fast sampling rather than only raw forward throughput.

Common questions

Why can training process tokens in parallel but generation cannot?
During training, the target sequence is already known, so the model can compute predictions for many positions at once and compare them with shifted labels. During generation, each new token depends on the token just produced, so the time dimension becomes sequential even when multiple requests are batched together.
What does the KV cache change during generation?
The KV cache avoids rerunning attention over the entire previous text at every decode step. After the prompt is processed, stored key and value tensors let each new step attend to earlier context while computing mainly for the latest token. This saves compute but makes memory management central to serving.
Why is batching harder for LLM inference than training?
Training batches are usually fixed rectangular tensors with the same operation applied across the batch. Inference batches contain live requests with different prompt lengths, generation lengths, sampling settings, stop conditions, and cache sizes. Serving systems therefore need continuous scheduling rather than a single static batch plan.