现代 AI 推理的“调度艺术”:从静态批处理到连续批处理 (Continuous Batching)
在 LLM(大语言模型)的生产环境中,推理成本的高低并不直接取决于模型参数量,而取决于一个核心指标:吞吐量 (Throughput)。

现代 AI 推理的“调度艺术”:从静态批处理到连续批处理 (Continuous Batching)
在 LLM(大语言模型)的生产环境中,推理成本的高低并不直接取决于模型参数量,而取决于一个核心指标:吞吐量 (Throughput)。
如果你在开发一个 AI 服务,你会发现最简单的推理方式是“静态批处理 (Static Batching)”:将 4 个用户的请求打包在一起,等所有请求都生成完毕后,一次性返回。但这种方式在实际应用中存在一个致命缺陷——“木桶效应”。
静态批处理的痛点:等待最慢的那个 Token
LLM 生成文本是自回归的,每个请求生成的 Token 数量不可预测。假设一个 Batch 中有三个请求:
- 请求 A:生成 10 个 Token 就结束了。
- 请求 B:生成 50 个 Token 才结束。
- 请求 C:生成 500 个 Token 才结束。
在静态批处理中,即使请求 A 和 B 早早完成了,GPU 资源也必须被占用直到请求 C 完成。这意味着 GPU 在处理 A 和 B 的位置上出现了大量的“空转”气泡(Bubbles),极大地浪费了计算资源。
连续批处理 (Continuous Batching) 的炼金术
为了解决这个问题,现代推理框架(如 vLLM, TensorRT-LLM)引入了 连续批处理 (Continuous Batching)。其核心逻辑是将调度粒度从“请求级”细化到“Token 级”。
在连续批处理中,推理引擎不再等待整个 Batch 完成,而是在每一个迭代步 (Iteration) 结束后立即检查状态:
1. 即时释放:如果请求 A 在第 10 步生成了 <|endoftext|>,它会立即被移出 Batch 并返回给用户。
2. 即时填充:一旦 A 离开,调度器立即从等待队列中拉入一个新的请求 D 进入该槽位。
3. 动态对齐:GPU 在每一步计算时,只对当前活跃的请求进行矩阵运算。
这种机制将 GPU 的利用率推向极致,使得系统能够以极高的并发量维持低延迟响应。
从内存管理看 PagedAttention
连续批处理虽然解决了计算调度问题,但带来了新的挑战:内存碎片化。由于每个请求的长度不一且动态变化,传统的连续内存分配会导致严重的内部碎片(Internal Fragmentation)。
这就是为什么 vLLM 推出了 PagedAttention。它借鉴了操作系统虚拟内存的分页机制:
- 将 KV Cache 分割成固定大小的“页 (Blocks)”。
- 使用一个映射表记录物理页与逻辑序列的对应关系。
- 当需要增加 Token 时,动态申请一个新的物理页,而不需要在内存中移动之前的所有数据。
实战启示:如何选择推理策略?
对于开发者而言,理解这些底层机制有助于优化部署方案:
- 追求极致吞吐量 $\rightarrow$ Continuous Batching + PagedAttention:适用于高并发的 Chatbot 服务。
- 追求极低首字延迟 $\rightarrow$ Speculative Decoding (投机采样):用一个小模型预预测 Token,大模型并行验证,进一步压低延迟。
- 显存受限 $\rightarrow$ 量化 (Quantization) + KV Cache 压缩:通过 FP8 或 INT4 量化减少 KV Cache 的体积,从而在同一块显卡上容纳更多并发请求。
AI 推理的演进路径非常清晰:从单纯追求算力 $\rightarrow$ 到优化内存带宽 $\rightarrow$ 再到精细化的调度管理。在这个过程中,“减少浪费”比“增加算力”往往能带来更显著的性能飞跃。
留言区
欢迎分享你的想法!
加载留言中…