05. 批处理与调度
本篇导读
前两篇解决了工作台容量和便笺复用。现在资料助手同时接待许多同事,本篇观察如何一起算、如何及时补位、如何避免长输入挡住正在回答的人。用排班和时间线建立 batch、连续批处理、分块 prefill 的直觉,最后再看队列与公平性。
一起处理,摊薄公共成本
如果每位同事都单独触发一次前向,模型权重可能被反复读取。把多个请求放到一轮计算,部分权重读取可以共同承担,这叫批处理。像同一轮准备好材料后处理多份工作,公共准备成本得到摊薄。
代价是每轮工作可能更大,等待凑批也会增加时延。整体每秒产出更多,不保证小林这一条答复更早结束。
短请求结束后,能否让新人补位
把简化 batch 想成两个工作位。A 只需 2 轮,B 需要 6 轮。如果整批结束才换人,A 空出的位子会等 B;连续批处理允许在轮次边界把 C 补进来。
观察批处理的空位全部请求在第 0 轮到达;每步成本相同
整批结束后补入
轮次12345678910111213A · 2B · 6C · 3D · 2E · 4
完成需 13 轮 · 序列槽位利用率 65%
每轮补入新请求
轮次12345678910111213A · 2B · 6C · 3D · 2E · 4
完成需 10 轮 · 序列槽位利用率 85%
灰色虚线为尚未推进的工作。两种方法都完成 17 个输出 token;总轮数差别来自空位能否及时补入。
这不是 GPU 利用率或性能预测:没有计算 prefill、KV 限制、不同 batch 的耗时及抢占。真实连续批处理在迭代边界重组执行集合。
拖到最后一轮,对照两条时间线:两种方案都完成 17 个输出 token,连续方案更早补进未开始的工作。灰色格子里的空等,正是这里要观察的现象。
类比有边界:实际引擎每轮重组的是张量和请求集合,不是永远固定的座位。不同 batch 的单轮耗时也会改变,演示中的轮数差不等于真实 GPU 加速倍数。
一份很长的输入,为什么让别人停顿
小林的回答已经开始,小周突然上传长手册。如果小周的 prefill 一次占用设备很久,小林的下一步 decode 就要等。把长手册拆成几块、在轮次之间交错推进,可以减少这种连续占用。
上方图示的下半部分对比的就是整段 prefill与分块 prefill。分块像分批接收一项大工作,让短的续写任务穿插进去;它没有减少手册字数,也没有自动压缩上下文。
代价可能是小周自己的首 token 更晚,以及更多调度开销。块太大,干扰还在;块太小,计算可能不够高效。正确验证方式是混合长短请求,同时看 TTFT 与生成间隔。
连接数、活跃人数和本轮工作量
| 类比 | 推理中的对象 | 它决定什么 |
|---|---|---|
| 大厅里有多少人 | API 请求和连接 | 系统接入与排队的总人数 |
| 这一轮正在处理几人 | 活跃序列 | 同时推进多少条序列 |
| 这一轮处理多少页 | Token 预算 | Prefill 与 decode 共用多少计算位置 |
接住 100 个连接,不等于 GPU 同时处理 100 条序列。一条长 prefill 就可能用掉大量 token 预算,而普通 decode 通常每条推进一个新 token。语音里的声学或说话人 embedding batch 还可能属于另一套队列。
深入:排队、回压、抢占与取消
把队列调大只会容纳更多等待,不会增加 GPU 算力。Admission control 在接入时约束长度与容量,回压让上游减速或得到明确拒绝。显存压力可能引起抢占、重算或按实现卸载恢复;频繁抢占会损害有效吞吐。
取消要传到引擎:等待中的请求可以移除,已运行请求需要在安全位置终止。底层仍使用的缓冲不能提前复用。实际语音链路的不同队列见动态批处理与推理调度。
深入:命中率、吞吐和公平性为什么不能只优化一个?
缓存友好请求省 prefill,但永远优先它们会让冷请求饥饿;最热实例也可能有最长队列。路由应综合可省计算、等待和传输。在线服务还要看同时满足质量、成功率和延迟目标的 goodput,不能只追求最高平均 tokens/s。
本篇回顾
- Batch 摊薄公共成本;连续批处理让结束的位置尽早被新工作利用。
- 分块 prefill 缩短长输入的连续占用,代价要同时从长短请求观察。
- 接入人数、活跃序列和 token 预算不同;队列变大不会增加计算能力。
至此已经理解一套服务如何安排多人。下一篇把镜头推进到每轮计算本身:能否让材料更小、搬运更少、提交更省? 进入量化、算子与编译。
