3. 批处理基础与动态批处理

在推理服务中,批处理是把多个请求合并成一次前向计算的核心手段。GPU 的算力来自大规模并行,单条请求往往无法填满 SM 与显存带宽,于是把多条请求拼成一个 batch,让矩阵乘法的 M 维变大,单位时间内完成的 token 数就会显著上升。但批处理不是免费的午餐:它把不同请求的等待时间绑在一起,批越大,单条请求从进入到拿到首 token 的延迟通常越高。理解静态、动态、连续三种批处理方式,以及批大小如何同时影响吞吐和延迟,是做好推理服务调优的第一步。

三种批处理方式的概念

静态批处理是最朴素的形式:服务端先攒够固定数量的请求,或者等待一个固定时间窗口,然后把这批请求一次性送入模型,等整批全部生成完毕后再统一返回。它的优点是实现简单、GPU 利用率高、显存占用可预测;缺点是“木桶效应”明显——批内只要有一条请求生成很长,其他已经结束的请求也必须陪着等,尾延迟被最长的那条拖住。此外,如果请求到达稀疏,攒批阶段本身就会引入额外等待。

动态批处理在静态批处理基础上引入时间窗口:服务端不再死等固定条数,而是在一个很短的时间窗(例如 5~20 ms)内收集到达的请求,窗口一到就把当前攒到的请求组成一批。这样在低负载时不必空等,在高负载时又能自然形成较大批次。它缓解了静态批处理的攒批僵化问题,但批内请求仍然要“同进同出”,长序列依旧会拖累短序列。

连续批处理(continuous batching,也称 iteration-level batching)把调度粒度从“整批”降到“单步”。每一轮解码迭代时,调度器都可以把已经完成的请求移出批次,并把新到达的请求插入空出的位置。于是批次成员在每一步都可能变化,GPU 始终维持较高的占用率,短请求完成后立即释放,不必等待同批的长请求。这是当前主流推理框架(如 vLLM、TensorRT-LLM、TGI)默认采用的策略,也是高并发场景下吞吐与延迟平衡的关键。

三种批处理方式的调度对比 静态批处理 攒满固定条数 → 整批同进同出 请求A(长) 请求B 请求C B、C 已完成但必须等待 A 动态批处理 时间窗口攒批 → 整批同进同出 窗口 请求A(长) 请求B 请求C B、C 仍被 A 拖住 连续批处理 每步调度 → 完成即退出,新请求即时补位 A B C D 补位 E 补位 持续填充

批大小对吞吐和延迟的直接影响

批大小 B 对两个指标的作用方向相反。吞吐方面,增大 B 让每次前向的矩阵规模变大,权重读取和 kernel 启动开销被更多请求分摊,GPU 利用率上升,单位时间处理的 token 数增加。但收益会递减:当 B 超过某个点后,计算从“访存受限”转为“算力受限”,吞吐曲线趋于平坦,而显存占用(尤其是 KV Cache)继续线性增长,最终触发 OOM 或被迫降低并发。

延迟方面,单条请求的端到端延迟大致由三部分构成:排队等待、首 token 时间(TTFT)、逐 token 生成时间(TPOT)。批越大,排队和 TTFT 通常越长,因为请求要等更久才能凑成一批,且一次前向要处理更多序列。TPOT 的变化更微妙:在访存受限区间,增大批能摊薄权重读取,TPOT 甚至可能下降;但进入算力受限区间后,TPOT 随批增大而上升。

可以用一个简化的示例说明这种权衡。假设某模型在 B=1 时单步耗时 20 ms,其中权重读取占 15 ms、计算占 5 ms;当 B 增大到 8 时,权重读取仍约 15 ms,计算增至 40 ms,单步耗时约 55 ms。此时单请求 TPOT 从 20 ms 升到 55 ms,但整批每步产出 8 个 token,吞吐从 50 token/s 提升到约 145 token/s。这就是典型的“用延迟换吞吐”。实际数值取决于模型、硬件和序列长度,此处仅为说明趋势的假设示例。

调优时不要只盯一个指标。在线交互场景优先保证 TTFT 和 TPOT 的 P99;离线批处理场景可以牺牲延迟换吞吐,把批大小推到显存允许的上限。

典型推理服务中的批处理策略

生产环境通常采用分层策略。第一层是准入控制:限制最大并发请求数 max_num_seqs 和最大批 token 数 max_num_batched_tokens,防止单批过大导致显存溢出。第二层是调度策略:优先填充 prefill 请求还是 decode 请求,常见做法是把 prefill 和 decode 分开调度(chunked prefill),避免长 prompt 的 prefill 阻塞正在解码的请求。第三层是抢占与回收:当显存不足时,按优先级或到达时间抢占部分请求,将其 KV Cache 换出到 CPU 或直接丢弃重算。

一个可参考的配置思路是:先根据显存容量估算 KV Cache 能容纳的最大 token 数,再反推 max_num_seqs;把 max_num_batched_tokens 设为单次前向能高效处理的上限(例如 2048~8192,视模型而定);开启连续批处理并设置合理的调度窗口。上线后观察 TTFT、TPOT、吞吐和 GPU 利用率的 P50/P99,逐步调整批大小上限,直到延迟满足 SLA 且吞吐不再明显增长为止。

策略批大小特征吞吐延迟适用场景
静态批处理固定,攒满即发高且稳定尾延迟高离线批量推理
动态批处理窗口内浮动较高中等负载波动的一般服务
连续批处理每步动态变化最高低且可控高并发在线服务

需要强调的是,批处理策略没有绝对最优,只有与业务目标匹配。对话类应用对首 token 延迟敏感,应控制批大小并优先调度新请求的 prefill;文档摘要类应用可以接受较长等待,适合用大 batch 提升吞吐。把批大小、调度方式和 SLA 三者放在一起权衡,才是批处理调优的完整视角。