vLLM Continuous Batching 和KVCache


vLLM 的 Continuous Batching(连续批处理) 是其相较于传统 LLM Serving 框架(如 HuggingFace TGI、早期 Triton 推理方案)最核心、也是最有工程价值的优化点之一。下面从问题背景 → 核心思想 → 关键实现机制 → 性能收益 → 与传统 batching 的对比几个层次,系统性说明其优化原理。


一、背景问题:为什么“传统 batching”在 LLM 推理中失效

1. Prefill 与 Decode 阶段差异巨大

LLM 推理天然分为两段:

阶段 特点
Prefill 输入长、一次性计算、算力密集
Decode 每步只生成 1 token,但需要频繁迭代

传统 batching 假设:

所有请求 同步开始、同步结束

但现实是:

  • 用户 prompt 长度不同
  • 输出 token 数不同
  • 有的请求已经进入 decode,有的还在 prefill

批次中最慢的请求拖累所有请求


2. Padding 浪费极其严重

传统 batching 需要对齐:

  • 输入长度
  • KV Cache 长度

结果:

  • 短请求被 padding 到最长请求
  • GPU 做了大量无效计算

二、vLLM 的核心思想:把“批”变成“流”

一句话总结:

Continuous Batching = 请求级动态调度 + Token 级执行对齐

不是“等一批请求齐了再算”,而是:

  • GPU 每一步 decode 都在干活
  • 请求可以 随时加入 / 随时退出
  • 不再存在固定 batch 生命周期

三、Continuous Batching 的工作机制(关键原理)

1. Token-Level 执行对齐(最关键)

在 decode 阶段:

  • 每个请求 每一步只需要 1 个 token
  • vLLM 将不同请求的 下一 token 生成 拼成一个 batch

例如:

请求 当前状态
Req A decode step 12
Req B decode step 5
Req C decode step 20

vLLM 做的是:

Step t:
[A 的第13个 token]
[B 的第6个 token]
[C 的第21个 token]
→ 合并成一个 GPU batch

这意味着:

  • 不要求请求“同一时间开始”
  • 只要求“同一时间生成下一个 token”

2. 动态 Batch Size(随时变化)

传统:

batch_size = 固定

vLLM:

batch_size(t) = 当前所有 active 请求数
  • 新请求 → 立即加入 batch
  • 完成请求 → 立即移出 batch

GPU 利用率始终维持在高位。


3. Prefill / Decode 混合调度

vLLM 并不会强行区分:

  • “现在只能 prefill”
  • “现在只能 decode”

而是:

  • Prefill 请求作为 一次性大算子
  • Decode 请求作为 持续小算子
  • 通过调度器交错执行

调度目标:

  • 避免 decode starvation
  • 避免 prefill 阻塞整体吞吐

4. PagedAttention(为 Continuous Batching 服务)

Continuous Batching 能成立,PagedAttention 是前提条件

传统 KV Cache:

  • 每个请求一块连续显存
  • 长度变化 → 内存碎片 / 重分配

PagedAttention:

  • KV Cache 切成固定大小的 block(页)
  • 类似虚拟内存页表

好处:

  • 请求加入 / 退出时 不搬内存
  • 不同长度请求共存
  • 支撑高频 batch 变化

Continuous Batching 解决算力利用率问题
PagedAttention 解决显存管理问题

两者是强耦合设计。


四、与传统 Batching 的本质对比

维度 传统 Static Batching vLLM Continuous Batching
Batch 生命周期 请求级 Token 级
请求加入时机 批次开始前 任意时刻
Batch Size 固定 动态
Padding 严重 基本无
GPU 利用率 波动大 稳定高
尾延迟(P99) 显著降低

五、性能收益从哪里来(量化直觉)

典型收益来源:

  1. Decode 阶段 GPU 不再空转
  2. Prefill 不再阻塞 Decode
  3. KV Cache 不重排、不复制
  4. 更高并发下仍可稳定吞吐

实际线上常见效果:

  • 吞吐 ↑ 2–4 倍
  • P99 延迟 ↓ 30%–70%
    (具体与 prompt 长度分布强相关)

六、为什么 Triton / 传统 Serving 很难做到?

核心障碍:

  1. 静态 batch 假设写死在推理图中
  2. KV Cache 以连续内存组织
  3. 调度粒度在 request 而非 token

vLLM 是:

  • 推理引擎
  • 调度器
  • 显存管理器
    三位一体设计

这也是为什么:

Triton + HF Model ≠ vLLM


七、一句话总结(面试/评审级)

vLLM Continuous Batching 的本质是:
以 token 为最小调度单位,在 PagedAttention 的支撑下,实现请求级动态加入/退出,从而在高度异构的 LLM 推理负载下维持 GPU 的持续满载。

如果你愿意,我可以进一步:

  • 拆解 vLLM Scheduler 的内部队列设计
  • 画一个 prefill/decode 混合调度时间线
  • 对比 Continuous Batching 与 Speculative Decoding 的协同关系
posted @ 2026-01-15 19:28  向着朝阳  阅读(0)  评论(0)    收藏  举报