AI engineering and inferenceLoading progress…

Continuous batching

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

Continuous (iteration-level) batching

Instead of fixing the batch until it empties, the scheduler looks at the end of every iteration: finished requests leave, and waiting ones are admitted into the free slots immediately. The same work then finishes in fewer iterations. In the example (lengths 2, 1, 2 with two slots) the schedule becomes A+B, A+C, C: 3 iterations and 5/6 = 83.33% utilisation, against 4 iterations and 62.5%.

slots2request A tokens2request B tokens1request C tokens2request D tokens4request E tokens1
static
it 1it 2it 3it 4it 5it 6it 7
slot 1AACCE
slot 2BDDDD
continuous (admit at every iteration)
it 1it 2it 3it 4it 5it 6
slot 1AACDDD
slot 2BCDE
iterationsutilisationA doneB doneC doneD doneE done
static771.4%21467
continuous683.3%21364

The default has five requests, so the first three (2, 1, 2 tokens, two slots) are the chapter's example: 62.5% becomes 83.33%. Continuous admission needs a scheduler that decides every iteration and a cache that can hold new sequences at any time. Real token costs are not equal, so this is a toy.

Compare the two schedules on the same requests.

Predict first. Can admission change after every token iteration?

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.