3. 动态批处理概念
3.1 动态批处理定义
动态批处理(Dynamic Batching)是 TensorRT-LLM 推理服务中用于提升 GPU 吞吐量的核心调度机制。其基本思想是:不等待单个请求完整执行完毕,而是在每个解码步骤(decode step)结束时,将当前处于"可执行状态"的多个请求动态组合成一个批次,送入 GPU 执行一次前向传播。每个请求在批次中的位置、批次的大小、甚至批次内请求的组成,都会随着解码进度实时变化。
与传统的"请求级批处理"不同,动态批处理在token 级(迭代级)进行调度。一个请求完成生成后,其占用的显存槽位立即被新到达的请求接管,GPU 无需等待整个批次的所有序列都结束。下图展示了动态批处理的核心调度循环:
上图中,请求 A、C、E 正在 GPU 上并行解码,请求 B、D 在队列中等待。当请求 E 在下一迭代完成生成后,其槽位会被立即分配给请求 B,整个过程对用户完全透明。
3.2 与静态批处理的区别
静态批处理(Static Batching)是动态批处理出现之前的主流方案,也是许多初学者容易混淆的概念。两者的本质区别在于批次的粒度和槽位释放的时机。下表从多个维度进行了对比:
| 对比维度 | 静态批处理 | 动态批处理 |
|---|---|---|
| 批次组成时机 | 请求到达时一次性组批,批次固定 | 每个解码迭代动态组批 |
| 最短执行单元 | 整个请求(完整生成序列) | 单个解码步骤(一次前向传播) |
| 槽位释放 | 批次内所有请求完成后统一释放 | 单个请求完成后立即释放并复用 |
| GPU 空闲率 | 高(批次尾部效应严重) | 低(持续保持高利用率) |
| 对长尾请求的容忍度 | 差,一个超长请求拖慢整个批次 | 好,长请求独立推进不影响他人 |
| 调度开销 | 低(仅组批一次) | 较高(每步需检查状态) |
| 典型适用场景 | 离线批量推理、长度均匀的任务 | 在线流式服务、长度高度不均 |
用一个具体案例来说明:假设静态批次中有 4 个请求,生成长度分别为 10、50、100、200 tokens。当最短的请求(10 tokens)完成时,它必须继续占用 GPU 资源等待其他 3 个请求完成,因为整个批次共享一次前向传播。这导致 GPU 计算量中约 30%~50% 是无效的 padding 计算。而动态批处理中,10-token 的请求完成后立即退出,其槽位马上被新请求填充,GPU 始终在处理"有效"的 token。
3.3 核心优势
动态批处理带来的收益在真实负载下非常显著,主要体现在以下四个方面:
- 吞吐量提升 2~5 倍:GPU 的算力被持续利用,消除了批次尾部的等待空洞。在 TensorRT-LLM 的官方 benchmark 中,动态批处理相比静态批处理在混合长度负载下吞吐提升可达 3.2 倍。
- 降低平均延迟:新请求无需等待当前批次完全结束,只要有一个空闲槽位即可开始推理。在负载 50% 时,平均排队延迟可降低 60% 以上。
- 天然适配流式输出:动态批处理与 token 流式生成(streaming)完美契合——每个请求的 token 是逐步产生的,调度器可以在每个 token 之间插入其他请求的计算。
- 资源利用率与服务质量解耦:通过控制最大批次大小(max_batch_size),可以在吞吐和延迟之间灵活权衡,而不影响已运行请求的稳定性。
实际收益参考(TensorRT-LLM 在 A100 上的测试数据):
负载类型: 在线流式, 输入长度 50~800 tokens, 输出长度 20~200 tokens
静态批处理: 吞吐 850 tokens/s, 平均延迟 420 ms, GPU 利用率 61%
动态批处理: 吞吐 2,340 tokens/s, 平均延迟 180 ms, GPU 利用率 89%
提升幅度: 吞吐 ×2.75, 延迟 ↓57%, 利用率 ↑28 个百分点
3.4 挑战与代价
动态批处理并非银弹,它在工程实现上引入了新的复杂性,需要在实际部署中仔细权衡:
- KV Cache 内存碎片化:每个请求占用的 KV Cache 大小随生成长度动态增长。频繁的槽位释放与分配会导致显存碎片,TensorRT-LLM 通过 paged KV cache(类似虚拟内存的分页机制)来缓解,但需要额外配置 page 大小和最大 token 数。
- 调度器开销:每个解码迭代都需要执行一次调度决策——检查完成状态、回收槽位、从队列取新请求、更新注意力掩码。当 batch size 很大(如 256)时,调度本身可能消耗 5%~10% 的 GPU 时间。
- 长请求饥饿风险:如果持续有新请求到达,调度器可能倾向于填充新请求而让长请求"插队",导致个别请求迟迟无法完成。需要设置合理的最大等待时间或优先级策略。
- 不确定性增加:由于批次组成动态变化,单次请求的完成时间波动比静态批处理更大,对延迟敏感型业务需要配合超时和重试机制。
3.5 常见误区与复盘
在实际使用 TensorRT-LLM 动态批处理时,开发者常陷入以下认知误区,这里逐一澄清:
误区 1:动态批处理 = 增大 batch size
动态批处理的核心是"动态重组",而非单纯增大批次。即使 batch size 保持 8 不变,动态调度也能通过及时替换已完成请求来提升效率。盲目增大 max_batch_size 会导致显存溢出或延迟恶化。
误区 2:动态批处理会自动解决所有并发问题
动态批处理只负责 GPU 端的调度,不涉及请求分发、负载均衡或超时管理。如果上游服务没有合理的并发控制,大量请求堆积在队列中,动态批处理反而会加剧排队延迟。
误区 3:所有模型都适合动态批处理
动态批处理对解码阶段收益最大。对于纯预填充(prefill)任务(如分类、embedding),请求长度固定且计算密集,静态批处理反而更高效。TensorRT-LLM 允许对 prefill 和 decode 阶段分别配置不同的批处理策略。
复盘建议:在部署动态批处理时,建议先通过 trtllm-bench 工具分别测量静态和动态模式下的吞吐-延迟曲线,找到适合自身负载的切换点。同时监控 KV Cache 利用率(而非仅看显存总量),当利用率低于 60% 时,优先检查是否存在槽位碎片或调度器配置过小的问题。