04 · Scheduler:连续批处理的决策中心
Scheduler 每轮只回答一个问题
在资源有限的情况下,这一轮让哪些 Sequence 处理多少 token?
它同时受到三类约束:
max_num_seqs:一个批次最多容纳多少序列。max_num_batched_tokens:本轮最多处理多少 token。- KV Cache block 是否足够。
Prefill 阶段
Scheduler 先查看 waiting 队列。对队首请求:
- 询问 BlockManager 能否分配,并返回可命中的缓存 block 数。
- 计算仍需执行的 prompt token。
- 检查本轮 token 预算。
- 分配 block,并设置
num_scheduled_tokens。 - 把请求移到 running。
当一个超长 prompt 超过剩余预算时,nano-vLLM 允许第一个请求做 Chunked Prefill,即只处理一部分 prompt;但若本轮已经选了其他请求,就不会再塞入一个无法完整容纳的长请求,以保持逻辑简单。
Decode 阶段
没有可调度 Prefill 后,Scheduler 从 running 队列选择请求。Decode 中每个序列通常只需要处理最后一个 token,但可能需要新 block。如果空闲 block 不足,调度器会回退或抢占序列,释放其缓存,之后让它重新进入等待。
为什么要连续批处理
静态 batching 必须等待整批请求一起结束;连续批处理允许某个请求完成后立即腾出位置,引入新请求。这样 GPU 不必被最慢序列拖住。
公平性与吞吐的取舍
Prefill 优先能让新请求尽快进入系统,但超长 prompt 可能占用大量 token 预算;Decode 批次越大,总吞吐通常越高,但单个用户的每 token 延迟可能变差。生产系统会加入更复杂的优先级、预算和延迟目标,nano-vLLM 保留了最小但清晰的核心。
HTML INTERACTIVE LAB04 · Scheduler:连续批处理的决策中心
单独打开 ↗课后习题等待完成
为什么 `max_num_batched_tokens` 比“最大 batch size”更适合约束 Prefill?
动手任务
在互动实验中加入三个请求:8、24、60 token,把预算分别设为 32 和 64,记录每轮发生了完整 Prefill 还是 Chunked Prefill。
下一节:分页 KV Cache