Skip to content

连续批处理原理与优化

GPU 专为高并行计算设计,但 LLM 推理由于自回归特性,往往难以充分利用硬件算力。批处理通过跨请求复用已加载的模型参数,是提升吞吐量的关键手段。本文将介绍从静态批处理、动态批处理到连续批处理(Continuous Batching) 的演进,并分析其底层机制。

1. 批处理策略的演进

1.1 静态批处理

服务器等待固定数量的请求到达后,将它们作为一个批次统一处理。缺陷在于:

  • 首个请求必须等待最后一个请求到达才能启动。
  • 所有请求必须等待最慢的请求完成,造成 GPU 空闲。

1.2 动态批处理

设置时间窗口,处理该窗口内到达的所有请求;若批次提前达到规模上限则立即启动。虽然能平衡吞吐量与延迟,但批次中最长请求仍决定整体完成时间。

1.3 连续批处理

连续批处理允许批次中每个序列独立完成,并立即用新请求替换已完成序列。它采用迭代级调度(Iteration-level Scheduling),批次组成在每个解码迭代周期动态变化,从而最大化 GPU 占用率。

主流推理框架如 vLLM、SGLang、TensorRT-LLM、LMDeploy 与 Hugging Face TGI 均已支持该机制。

2. 注意力机制与 KV Cache

2.1 预填充阶段(Prefill)

模型首先处理完整输入 Prompt,计算每个 Token 的 Key 与 Value 并缓存。该阶段计算密集,复杂度为 O(n2d),其中 n 为 Prompt 长度,d 为模型维度。

2.2 解码阶段(Decode)

进入自回归循环后,每步只需计算新 Token 的 Query、Key、Value,并复用历史 KV Cache。复杂度从 O(n2) 降至 O(n),代价是 O(n) 的显存开销。

对于一个拥有 L 层、H 个头、头维度为 A 的模型,单个 Token 的 KV Cache 大小为:

CacheSizetoken=2×L×H×A×DtypeSize

例如 Llama-2-7B(L=32,H=32,A=128)在 FP16 下每个 Token 约需 16 KB。

2.3 分块预填充(Chunked Prefill)

当 Prompt 过长、单次前向传播无法容纳所有 Token 时,可将 Prefill 拆分为多个块,逐块计算并增量更新 KV Cache:

text
chunk 1: compute KV for tokens 1..m
chunk 2: prepend cached KV, compute KV for tokens m+1..2m
...

这使得模型能够灵活适应不同显存限制,而不会丢失上下文信息。

3. 连续批处理的核心思想

3.1 朴素批处理的缺陷

朴素批处理要求所有序列长度相同,短序列通常需要 Padding 到最长序列。一旦某个序列提前生成 <eos>,其占用的空间会继续浪费到批次结束。

此外,当用新请求替换已完成请求时,新请求需要 Prefill,而批次中其他请求正在 Decode。新请求的全部长度几乎都转化为 Padding Token,造成巨大计算浪费。填充成本随 Batch Size B 与 Prompt 长度 n 近似二次方增长。

3.2 参差批处理(Ragged Batching)

连续批处理的关键是彻底消除批次维度及其 Padding。方法是不再堆叠张量,而是将不同请求的 Token 序列拼接(Concatenate)成一个超长序列,并通过精心设计的注意力掩码保证:

  • 每个 Token 只能看到自身及之前的 Token(因果性)。
  • 不同请求的 Token 之间互不干扰(请求隔离)。

这种长度不均匀的拼接方式称为参差批处理,其核心优势在于彻底消除 Padding Token。

3.3 完整算法

连续批处理是参差批处理与动态调度的结合:

  1. 确定内存预算 m:每批次总 Token 数不超过该预算。
  2. 优先 Decode 序列:将所有处于 Decode 阶段(每个仅占 1 个 Token)的请求加入当前批次。
  3. 填充 Prefill 序列:利用分块预填充的灵活性,用 Prefill 请求填充剩余空间;若过长则拆分为合适大小的块。
  4. 动态替换:一旦某请求生成 <eos>,立即移除,并用新的等待请求(以其第一个 Prefill 块)替换。

通过在同一批次中高效混合 Prefill 与 Decode,并结合动态调度与无 Padding 的参差批处理,连续批处理显著提高了 LLM 服务系统的效率。

总结

连续批处理是现代高性能 LLM 服务系统的核心技术,它巧妙结合了三种机制:

  • KV Cache:避免在自回归生成中重复计算历史 Token。
  • 分块预填充:在显存受限时灵活、增量地处理可变长 Prompt。
  • 参差批处理与动态调度:消除 Padding 与批次边界,确保 GPU 始终处于高负载状态。

正是这些技术的结合,使得 ChatGPT 等服务能够高效、低延迟地同时处理成千上万并发用户。

参考

Maintained by Robin