Skip to content

Continuous Batching 调度策略

Continuous Batching(连续批处理)是 vLLM 实现高吞吐推理的关键调度策略,它打破了传统 Static Batching 的限制,使得新请求可以在任意迭代步加入批次,已完成请求可以立即释放资源。

Continuous Batching调度流程

Static Batching 的局限

传统 Static Batching 的工作方式:

  1. 收集一批请求直到批次满或超时
  2. 整批执行直到所有请求完成生成
  3. 短请求必须等待长请求,造成 GPU 空闲

假设批次中有 1 个需要 500 Token 的请求和 7 个需要 50 Token 的请求,Static Batching 需要等待最长的请求完成,GPU 利用率仅约 25%。

Continuous Batching 原理

Continuous Batching 在每个迭代步进行调度决策:

  • Prefill 阶段:新请求加入批次,计算其 Prompt 的 KV Cache
  • Decode 阶段:已有请求各生成一个 Token
  • 驱逐:已完成的请求立即从批次中移除
  • 补充:从等待队列中选取新请求填补空位
python
# Continuous Batching 调度伪代码
class ContinuousBatchScheduler:
    def __init__(self, max_num_seqs=256):
        self.max_num_seqs = max_num_seqs
        self.running = []   # 正在运行的请求
        self.waiting = []   # 等待队列

    def schedule(self, block_manager):
        # 1. 移除已完成的请求
        self.running = [r for r in self.running if not r.finished]

        # 2. 释放完成请求的 KV Cache
        for req in self.running:
            if req.finished:
                block_manager.free(req.id)

        # 3. 从等待队列补充新请求
        while len(self.running) < self.max_num_seqs and self.waiting:
            req = self.waiting[0]
            if block_manager.can_allocate(req):
                block_manager.allocate(req.id, req.num_tokens)
                self.running.append(req)
                self.waiting.pop(0)
            else:
                break  # 显存不足,停止补充

        return self.running

调度策略对比

策略空闲等待显存利用率实现复杂度
Static Batching
Dynamic Batching
Continuous Batching

调度优先级

vLLM 默认采用 FCFS(先来先服务)策略。对于需要 SLA 保证的场景,可以配置优先级调度,确保高优先级请求优先获得计算资源。

Preemption 机制

当显存不足以接纳新请求时,vLLM 支持 Preemption(抢占)策略:

  • Recomputation:抢占低优先级请求,释放其 KV Cache,后续重新计算
  • Swap:将低优先级请求的 KV Cache 换出到 CPU 内存
python
# 配置抢占策略
from vllm import LLM

llm = LLM(
    model="meta-llama/Llama-2-7b-hf",
    preemption_mode="recompute",  # 或 "swap"
)

性能影响

Continuous Batching 带来的性能提升:

  • 吞吐量:相比 Static Batching 提升 2-4x
  • 延迟:P99 延迟降低 30-50%
  • GPU 利用率:从 40-60% 提升至 80-95%

注意事项

Continuous Batching 在 Prefill 和 Decode 混合执行时,Prefill 的计算量远大于 Decode,可能导致 Decode 请求的延迟抖动。vLLM 通过 Chunked Prefill 机制缓解此问题。

相关资源

最近更新