静态 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:

from atb import LLM, DynamicBatchingConfig

model = LLM(
    "meta-llama/Llama-2-7b-hf",
    device="npu:0",
    dynamic_batching=DynamicBatchingConfig(
        max_wait_ms=50,        # 最多等 50ms 凑 batch
        max_batch_size=32,     # 最大 batch 大小
        max_seq_len=4096,     # 最大序列长度
    )
)

# 并发发送多个请求(ATB 自动做动态 batching)
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor:
    futures = [executor.submit(model.generate, prompt)
                for prompt in prompts]
    results = [f.result() for f in futures]

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 秒凑大 batch
    max_batch_size=64,     # 离线可以开大 batch
    max_seq_len=8192,
)

动态 batching 是昇腾NPU推理服务的标配——把 batch 从 1 提到 16-32,吞吐提升 10-20×。关键参数 max_wait_ms 根据业务延迟要求调整。仓库在这里:

https://atomgit.com/cann/ATB

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐