CANN-昇腾NPU-动态batching-怎么把多个请求合并成一个batch
静态 batching 要求所有请求长度相同、batch 大小固定。动态 batching 把多个不同长度的请求拼成一个 batch,NPU 并行处理。在昇腾NPU上,动态 batching 是提升吞吐的关键——batch=1 的 GEMM 利用率只有 7%,batch=32 能到 65%。
动态 Batching 的原理
时刻 T1:收到请求 A(prompt_len=128) 时刻 T2:收到请求 B(prompt_len=256) 时刻 T3:收到请求 C(prompt_len=64) 静态 batching:等 batch 满 32 个才处理,A 等了 200ms 动态 batching:每 50ms 把当前所有 pending 请求拼成一个 batch 处理动态 batching 的权衡:等待时间 vs batch 大小。等待越久,batch 越大,NPU 利用率越高,但首 token 延迟越高。
ATB 的动态 Batching
ATB 的 LLM 接口内置动态 batching:
fromatbimportLLM,DynamicBatchingConfig model=LLM("meta-llama/Llama-2-7b-hf",device="npu:0",dynamic_batching=DynamicBatchingConfig(max_wait_ms=50,# 最多等 50ms 凑 batchmax_batch_size=32,# 最大 batch 大小max_seq_len=4096,# 最大序列长度))# 并发发送多个请求(ATB 自动做动态 batching)importconcurrent.futureswithconcurrent.futures.ThreadPoolExecutor(max_workers=32)asexecutor:futures=[executor.submit(model.generate,prompt)forpromptinprompts]results=[f.result()forfinfutures]Padding 策略
不同长度的请求拼成 batch 需要 Padding 到相同长度。两种策略:
策略 1:Padding 到最大长度
# 请求 A: 128 tokens → padding 到 256# 请求 B: 256 tokens → 不用 padding# Batch 大小: [256, 256]缺点:短请求浪费计算(Padding token 也过了 Attention)策略 2:分桶(Bucket)
# 预设几个桶:128, 256, 512, 1024, 4096# 请求 A (128) → 放入 128 桶# 请求 B (256) → 放入 256 桶# 不同桶的请求不混批优点:减少 Padding 浪费 缺点:桶内请求少时 batch 大小受限ATB 默认用分桶策略。max_batch_size是每个桶的最大 batch 大小。
动态 Batching 的吞吐提升
Llama2-7B,Atlas 800I A2,32 并发请求:
| Batching 策略 | 吞吐 (tokens/s) | 首 token 延迟 (ms) |
|---|---|---|
| 静态 batch=1 | 150 | 35 |
| 静态 batch=8 | 980 | 35(等 batch 满) |
| 动态 batching (max_wait=10ms) | 2,100 | 45 |
| 动态 batching (max_wait=50ms) | 2,800 | 85 |
| 动态 batching (max_wait=200ms) | 3,200 | 235 |
max_wait_ms是核心参数:小 → 延迟低但吞吐低;大 → 延迟高但吞吐高。
在线服务一般取 50-100ms。离线批量推理可以取 500-1000ms(不关心延迟,只要吞吐)。
跟 KV Cache 的配合
动态 batching 要求 KV Cache 能容纳不同 batch 大小的请求。Paged KV Cache 正好解决这个问题——不需要预分配固定 batch 大小的 KV Cache。
model=LLM("meta-llama/Llama-2-7b-hf",device="npu:0",kv_cache_dtype="fp16",paged_kv_cache=True,# 必须开启dynamic_batching=DynamicBatchingConfig(max_wait_ms=50),)如果不开启 Paged KV Cache,动态 batching 的 KV Cache 显存浪费 30-50%(因为要按最大 batch 预分配)。
实际部署配置
在线对话服务(QPS=50,延迟敏感):
config=DynamicBatchingConfig(max_wait_ms=50,# 平衡延迟和吞吐max_batch_size=16,# 在线服务 batch 不用太大max_seq_len=4096,)离线批量推理(不关心延迟):
config=DynamicBatchingConfig(max_wait_ms=2000,# 等 2 秒凑大 batchmax_batch_size=64,# 离线可以开大 batchmax_seq_len=8192,)动态 batching 是昇腾NPU推理服务的标配——把 batch 从 1 提到 16-32,吞吐提升 10-20×。关键参数max_wait_ms根据业务延迟要求调整。仓库在这里:
https://atomgit.com/cann/ATB
