Schedule Every Step
让 batch 在每一步变化
用 waiting、running 和 token 预算理解 continuous batching。
调度单位变成一步之后,请求可以独立离开,也可以在空位出现时加入。
01不再等待最慢的成员
静态 batch 中,短请求结束后留下空位,却不能立刻补入新请求。continuous batching 在每一轮重新选择工作,完成的请求退出,等待的请求在资源允许时进入。请求仍保留自己的 KV 和进度,改变的是本轮执行集合;这使请求生命周期与一次前向的 batch 成员关系分离。
s06_continuous_batch.py
# Framework pseudocode; phase selection is simplified.
for round in engine_rounds:
reclaim_finished_requests()
budget = max_query_tokens
selected = []
for request in eligible_requests(waiting, running):
cost = planned_query_tokens(request)
if cost <= budget and cache_can_fit(request):
reserve_planned_state(request)
selected.append(request)
budget -= cost
ready_outputs = execute_scheduled_round(selected)
apply_ready_updates(ready_outputs)
# Some sampling/post-processing may still be in flight.
# Inspect upstream NORMAL-mode prefill/decode coordination.02预算不能只数请求个数
一条长 prompt 的 prefill 和一条单 token decode 对计算与内存的需求不同。调度器既要限制序列数量,也要计算本步 query token 总量,并确认缓存能分配。chunked prefill 把长输入切成多步处理,避免一次占满全部预算。公平性、首次响应和吞吐之间需要明确策略,不能只靠队列顺序碰运气。
03读清 DeepInfer 的步型约束
上游 C++ Scheduler 在 NORMAL 模式下决定本轮做 prefill 还是 decode,并让 DP 组通过投票保持步型一致。它并不等同于任意混合两种 token 的通用片段。ALL 与 ANY 尝试点兼顾无效陪跑和等待上限;理解这些分支前,先追踪 waiting、running、缓存分配和完成回收的变化。
TRY IT YOURSELF
动手想一想
让长 prompt、短 prompt 和正在 decode 的请求同时到达。在固定 token 预算下安排五轮执行,写明每轮不能加入某条请求的具体原因。
把这个机制,加入你的工具箱。