连续批处理内部原理
静态批处理的效率问题 在传统LLM推理中,请求被分成固定大小的batch。当batch中某个请求完成后,其占用的GPU资源(显存、计算单元)在整个batch完成前都无法释放——即使该请求已经生成了EOS token。 这在大语言模型服务中造成了严重的资源浪费。用户请求的长度差异巨大——有的只需生成10个token,有的需要生成1000个token。静态批处理强迫"快请求等待慢请求",GPU计算能力被大量闲置。 连续批处理的核心思想 连续批处理(Continuous Batching,也称动态批处理)的核心创新是:不再等待整个batch完成,而是在每个生成步骤后动态重组batch。 当一个请求完成时,立即用新请求填充其位置,始终保持GPU满载。 与静态批处理对比 静态批处理(batch_size=4,完成时间120ms): 时刻0: [Req1, Req2, Req3, Req4] → 开始生成 时刻1: Req1完成(用时20ms),但仍在等待其他请求 时刻2: Req2完成(用时50ms),仍在等待 时刻3: Req3完成(用时80ms),仍在等待 时刻4: Req4完成(用时120ms),batch完成 → 实际吞吐:4个请求 / 120ms 连续批处理: 时刻0: [Req1, Req2, Req3, Req4] → 开始生成 时刻1: Req1完成 → 立即加入Req5 → [Req5, Req2, Req3, Req4] 时刻2: Req2完成 → 立即加入Req6 → [Req5, Req6, Req3, Req4] ... → 实际吞吐:~10个请求 / 120ms(约2.5倍提升!) vLLM中的连续批处理实现 请求状态机 每个请求在vLLM中经历以下状态: class RequestState(Enum): WAITING = 0 # 等待被调度 RUNNING = 1 # 正在生成 PREEMPTED = 2 # 被抢占(显存不足) FINISHED = 3 # 完成 class Request: def __init__(self, prompt, max_tokens): self.state = RequestState.WAITING self.prompt = prompt self.output_tokens = [] self.max_tokens = max_tokens self.current_step = 0 调度循环 vLLM的调度器在每一步动态决定哪些请求参与计算: ...