AI engineering and inferenceLoading progress…

Chunked prefill

Trace static and iteration-level schedules and explain chunked prefill, preemption and latency tradeoffs.

Chunked prefill

Chunked prefill splits a long prompt into pieces and mixes one piece into each iteration under a total token budget. With a budget of 256 tokens and 4 decoding requests, each iteration carries 252 prompt tokens, so the 2000-token prompt needs 8 iterations of about 29 ms each instead of one 204 ms stall. The scheduler also gets a decision point between chunks.

token budget per iteration256requests decoding4prompt tokens2000
it 1: 252
it 2: 252
it 3: 252
it 4: 252
it 5: 252
it 6: 252
it 7: 252
it 8: 236
chunk = 256 − 4 = 252 prompt tokens per iteration → 8 iterations (the last chunk may be smaller) longest iteration = 4 + 252 × 0.1 = 29.2 ms (whole prompt in one go: 204 ms)

Chunking gives the scheduler a decision point between chunks and keeps every decode iteration short. The whole earlier context still has to be processed; the prompt just finishes later.

Change the budget and the prompt length.

Predict first. Does splitting a prompt remove the need to process its earlier context?

Chapter context

Requests arrive at different times and finish after different output lengths. Scheduling decides which work enters each iteration and how waiting prompts compete with ongoing generation.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

In a simplified equal-cost decode schedule, utilization = active sequence-iterations / available sequence-iterations. This omits prefill costs and assumes uniform iteration time. A real scheduler needs measured compute, memory and latency constraints.

Worked example

Two slots serve requests A,B,C with output lengths 2,1,2. Static groups run A+B for two iterations, then C alone for two: 5 active slots out of 8 available. Continuous admission runs A+B, then A+C, then C: 5 active slots out of 6. Utilization rises from 62.5% to about 83.33% in this toy schedule; real token costs are not equal.

Reference code

The following example uses the Python standard library and does not call a remote service.

from math import isclose
static=[['A','B'],['A',None],['C',None],['C',None]]
continuous=[['A','B'],['A','C'],['C',None]]
util=lambda rows: sum(x is not None for row in rows for x in row)/(2*len(rows))
assert util(static) == .625
assert isclose(util(continuous),5/6)

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

Continuous batching does not guarantee a fixed improvement. Chunked prefill changes scheduling granularity, not the model's context dependencies. Include cache movement or recomputation costs when comparing preemption policies.