What an Inference Engine Actually Does
A request through the engine
After the first token, repeat 4 → 5 → 4 until stopping. The highlight introduces the stages; its timing does not model runtime duration.
A model's forward pass maps tokens to logits. Serving it adds a different problem: many requests arrive at different times, use different amounts of memory, and expect a response while other requests are still running.
An inference engine coordinates that work. It loads weights, schedules model execution, manages cached attention state, and returns generated tokens. A server adds the surrounding API and operational controls. Some projects package both together.
Follow one request
A request first passes through validation and tokenization. Chat messages need the checkpoint's chat template; raw text and a list of message objects are not interchangeable model inputs. The tokenizer must match the weights.
The request then waits for admission. The scheduler decides whether it can run within the current sequence, token, and memory budgets. A full cache does not imply one universal response: an engine may queue work, preempt a request for later recomputation, offload state, or reject a request according to its configuration.
Request data flow and supporting state
- HTTP request → formatting and tokenization → request queue
The server validates inputs and creates token IDs and generation settings.
- Scheduler → batch construction → model kernels
The scheduler selects prefill chunks and decode work. The cache manager allocates blocks and supplies their tables; the model loader supplies weights.
- Logits → constraints and sampling → output token
The token goes to detokenization and the response stream. If generation continues, its ID returns to the scheduler for the next model pass.
Weights, KV cache, and workspaces. Model kernels read weights and cache entries and append newly computed keys and values.
Stop, cancellation, or failure ends scheduling for that request. Release its cache references; reusable prefix blocks may remain cached.
Prefill processes the prompt through the model and creates its KV entries. Prompt positions can be computed in parallel within a layer under the attention mask; the layers still execute in dependency order. The final prompt position supplies logits for the first generated token.
The sampler selects that token. For a streaming request, the server can detokenize and emit it immediately. On the next model pass, the selected token becomes input, its K and V are appended, and its logits produce the next selection. A token's KV entry is created when the model processes it, not merely when the sampler chooses it.
This repeats until a stop condition, length limit, cancellation, or error. Request-owned blocks can be released; reusable prefix blocks may remain cached under the engine's eviction policy. Streaming and detokenization happen throughout generation, rather than once after the complete decode loop.
Computed toy schedule: exclusive prefill, batched decode
Assume 8 ms per prompt token and 80 ms per decode iteration. Ready prefills run before the next decode iteration. Arrivals during an iteration wait until it finishes.
| Request | Arrives | Prefill | First token | TTFT | Last token | Emitted |
|---|---|---|---|---|---|---|
| A | 0 ms | 0–112 | 112 ms | 112 ms | 912 ms | 8/8 |
| B | 150 ms | 192–368 | 368 ms | 218 ms | 1312 ms | 12/12 |
| C | 420 ms | 448–512 | 512 ms | 92 ms | 912 ms | 6/6 |
The first token is sampled at prefill completion. Later prefills interrupt ongoing decoding in this toy policy, making some token gaps longer than 80 ms. Sampling and transport overhead are omitted.
What the scheduler coordinates
With a static batch, membership stays fixed until its work finishes. A short request can leave an empty lane while another continues. Continuous batching allows completed requests to leave and new work to enter between iterations, subject to the scheduler's budgets.
Constructed schedule: two decode slots, six queued requests
Request lengths A–F: 2, 6, 3, 5, 2, 4 steps. Every step is assumed to take the same time; prefill is omitted.
| Step | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Slot 1 | A | A | — | — | — | — | C | C | C | — | — | E | E | — | — |
| Slot 2 | B | B | B | B | B | B | D | D | D | D | D | F | F | F | F |
22 occupied slots / 30 available slots = 73.3% slot occupancy. Completion: 15 steps.
Slot occupancy is not measured GPU utilization. Actual step time changes with batch size and context length.
A high slot-occupancy percentage is useful, but it is not the same as tensor-core utilization or memory-bandwidth utilization. A busy GPU can still spend much of its time moving data. Actual throughput depends on the kernels, batch sizes, sequence lengths, and communication as well as admission.
A long prefill can also delay ongoing decode work. Chunked prefill and continuous batching let an engine distribute prompt work across iterations. Priority policies choose which work gets those iterations. These are separate decisions, and their effects need workload-specific measurement.
The cache is part of the capacity plan
For a uniform full-attention decoder, cache bytes per stored token across the whole model are
The factor two counts keys and values. Use the number of KV heads, not query heads. The formula assumes equal dimensions in every layer; hybrid attention and compressed-cache architectures need their own accounting.
For 80 layers, eight KV heads, dimension 128, and BF16 cache elements, that is 327,680 bytes per token, or 320 KiB. A 32,768-token request needs about 10.74 decimal GB of KV data before page rounding and metadata.
- 8B
- 4.29 GB
- 70B
- 10.74 GB
- 405B
- 16.91 GB
Dimensions from Llama 3, Table 3: 32/80/126 layers, 8 KV heads, head dimension 128. Cache bytes = 2 × layers × 8 × 128 × context × 2. This is aggregate cache storage before sharding; weights and runtime memory are additional.
Weights, runtime workspace, graph allocations, and safety headroom occupy memory too. Adding GPU capacities gives an optimistic aggregate bound only when sharding and placement make that memory usable. Replicated KV heads or weights can reduce it. The memory-management post works through this budget.
Where engines make different choices
Select a stage to inspect the decisions it contains.
Kernels determine how matrix operations and attention use the device. Paged KV allocation determines how growing sequences occupy memory. Quantization changes storage formats and arithmetic paths. Parallelism distributes work and adds communication.
- Execution
- Eager operations, compilation, CUDA graphs, and specialized kernels can coexist in one runtime.
- Memory
- KV layout, prefix sharing, quantized weights, and device placement must fit the workload.
- Scheduling
- Admission, token budgets, chunked prefill, and priorities determine which work runs next.
- Deployment
- Model support, hardware support, maintenance, and APIs constrain the shortlist.
Offline generation and online serving
The vLLM offline API takes a finite collection of prompts and returns generated results. It can schedule that batch internally; this example does not stream results or listen for new network requests.
from vllm import LLM, SamplingParams
# Requires a compatible installation, suitable hardware, and model access.
llm = LLM(model="meta-llama/Llama-3.1-8B-Instruct")
conversations = [
[{"role": "user", "content": "Explain why the sky looks blue."}],
[{"role": "user", "content": "Name three common sorting algorithms."}],
]
results = llm.chat(conversations, SamplingParams(temperature=0, max_tokens=80))
for result in results:
print(result.outputs[0].text)For an online service, start the server instead, in a separate process with enough resources for its model:
The offline API and online-serving guide document these entry points.
Next: kernel fusion, where avoiding an intermediate memory round trip can matter as much as reducing arithmetic.
Additional reading
- Yu et al., Orca: iteration-level scheduling for generative models.
- Kwon et al., PagedAttention: block allocation and sharing for KV state.
- vLLM scheduler configuration: current admission, token-budget, and scheduling options.