
🧠 记忆锚点:静态批次等最慢请求;连续批处理按迭代进出队,用调度和分页 KV 保持 GPU 忙碌。
💡 答案要点
批处理 = 同时处理多个请求,提升 GPU 利用率
为什么批处理能加速?
单请求推理(batch=1):
GPU 利用率:5-10%
吞吐量:50 tokens/s
问题:大量算力浪费
批处理推理(batch=32):
GPU 利用率:40-60%
吞吐量:800 tokens/s
加速:16x传统批处理的问题:
请求1:100 tokens 输入 → 生成 50 tokens
请求2:200 tokens 输入 → 生成 150 tokens
请求3:150 tokens 输入 → 生成 80 tokens
传统批处理(Static Batching):
1. 等待凑够 3 个请求
2. 一起处理
3. 所有请求都完成才返回
问题:
请求1 生成完 50 tokens 后,要等请求2 生成完 150 tokens
→ 请求1 等待 100 tokens 的时间(浪费)
→ 延迟增加 3-5 倍Continuous Batching(持续批处理):
核心思想: 动态加入/移除请求,不等待全部完成
┌─────────────────────────────────────────────────────────┐
│ Continuous Batching │
└─────────────────────────────────────────────────────────┘
时间轴:
t0: [请求1, 请求2, 请求3] 开始生成
t1: [请求1, 请求2, 请求3] 生成 token1
t2: [请求1, 请求2, 请求3] 生成 token2
...
t50: [请求1] 完成 → 移除
[请求2, 请求3, 请求4] ← 加入新请求
t51: [请求2, 请求3, 请求4] 生成下一个 token
...算法:
python
class ContinuousBatcher:
def __init__(self):
self.running_requests = []
self.pending_requests = queue.Queue()
def step(self):
# 1. 移除完成的请求
self.running_requests = [
req for req in self.running_requests
if not req.is_finished()
]
# 2. 加入新请求(填满 batch)
while len(self.running_requests) < max_batch_size:
if self.pending_requests.empty():
break
req = self.pending_requests.get()
self.running_requests.append(req)
# 3. 批量生成下一个 token
batch_inputs = [req.get_input() for req in self.running_requests]
batch_outputs = model.generate(batch_inputs)
# 4. 更新每个请求的状态
for req, output in zip(self.running_requests, batch_outputs):
req.append_token(output)性能对比:
| 指标 | Static Batching | Continuous Batching |
|---|---|---|
| 吞吐量 | 100 req/s | 240 req/s |
| 平均延迟 | 2.5s | 0.8s |
| P99 延迟 | 8s | 2s |
| GPU 利用率 | 30% | 70% |
实现框架:
- vLLM(最流行)
- TensorRT-LLM
- Text Generation Inference(TGI)
面试话术:
"Continuous Batching 是 vLLM 的核心优化。传统批处理像公交车,等所有人上车才走。Continuous Batching 像地铁,到站就上下,不等人。吞吐量提升 2-3 倍,延迟降低 3-5 倍。"
📚 参考:Orca: A Distributed Serving System(Continuous Batching 起源,OSDI'22)