
CANN-ATB-Continuous-Batching-昇腾NPU推理服务吞吐量的核心引擎单请求推理时 NPU 利用率只有 5-10%。Continuous Batching 把多个请求的 decode 步骤拼在一起跑NPU 利用率拉到 60%。ATB 的 BatchScheduler 是实现这个策略的核心模块。Static Batching vs Continuous BatchingStatic Batching等所有请求生成完毕后再接收新一批请求。短请求要等长请求NPU 大量时间在空转。请求 A: 20 tokens ████████████████████ 请求 B: 5 tokens █████ 请求 C: 10 tokens ██████████ Static Batching 时间线 A: ████████████████████ B: █████............... ← 等A完成 C: ██████████.......... ← 等A完成 ↑ NPU 空转Continuous Batching某个请求生成完毕后立刻把新请求插入 batch。不等其他人。请求 A: ████████████████████ 请求 B: █████[D: ██████████] 请求 C: ██████████[E: ████] B 完成后 D 立刻插入C 完成后 E 插入 NPU 没有空转时间ATB 的 BatchScheduler 实现BatchScheduler 维护三个队列classBatchScheduler:def__init__(self,max_batch_size):self.waiting_queue[]# 等待 prefill 的请求self.running_batch[]# 正在 decode 的请求self.max_batch_sizemax_batch_sizedefstep(self):# 1. 检查完成的请求移出 batchcompleted[rforrinself.running_batchifr.finished]forrincompleted:self.running_batch.remove(r)free_slots1# 2. 从等待队列中补充新请求whilefree_slots0andself.waiting_queue:new_requestself.waiting_queue.pop(0)self.prefill(new_request)# 首 token 生成self.running_batch.append(new_request)free_slots-1# 3. 执行一步 decode所有 running_batch 的请求并行self.decode_step(self.running_batch)关键设计决策prefill 和 decode 是否可以混跑。CANN 8.0 的 ATB 不支持 prefill 和 decode 混跑——一个请求做 prefill 时其他 decode 请求要等。CANN 8.5 支持了混跑叫 chunked prefill新请求的 prefill 被切成小块跟 decode 交替执行。Chunked Prefillprefill 的计算量远大于 decodefull sequence vs 1 token。如果 prefill 和 decode 串行新请求的 prefill 会阻塞所有 decode 请求。Chunked Prefill 把 prefill 切成多个 chunk每个 chunk 跟 decode 交替执行时间线 [decode batch] [prefill chunk 1] [decode batch] [prefill chunk 2] [decode batch] ... 每个 decode batch 的等待时间 1 个 prefill chunk 的时间 而不是 完整 prefill 的时间chunk 大小默认 512 tokens。一个 4096 token 的 prefill 被切成 8 个 chunk每个 chunk 约 5ms。decode batch 每 5ms 被打断一次延迟抖动从 ~100ms 降到 ~5ms。优先级调度ATB 支持请求优先级。高优先级请求可以抢占低优先级请求的 batch slotfromatbimportLLM modelLLM(model_id,devicenpu:0,max_batch_size32)# 高优先级请求resultmodel.generate(紧急请求,priorityhigh)# 低优先级请求resultmodel.generate(普通请求,prioritylow)高优先级请求在等待队列里排前面。如果 batch 满了低优先级请求的 decode 步骤可以被暂停让高优先级请求先 prefill。性能数据Atlas 800I A2Llama2-7B32 并发请求配置吞吐 (tokens/s)P99 延迟 (ms)Static Batching2,800450Continuous Batching8,500180 Chunked Prefill9,20095Continuous Batching 吞吐提升 3 倍P99 延迟降 60%。加 Chunked Prefill 后 P99 延迟再降 47%。和 vLLM 的对比ATB 的 Continuous Batching 跟 vLLM 的实现思路一致但有一个差异vLLM 的 prefill 是完整执行的iteration-level schedulingATB 8.5 支持 chunked prefillchunk-level scheduling。chunked prefill 在高并发场景下延迟更稳——新请求不会因为长 prefill 阻塞所有 decode。vLLM 在 2024 年底的更新里也加了 chunked prefill 支持两者现在思路一致。Continuous Batching 是推理服务吞吐量的关键。不开它NPU 大部分时间在空转开了它吞吐能提升 3 倍。如果你的 ATB 推理服务并发低先确认 Continuous Batching 和 Chunked Prefill 有没有开启。仓库在这里https://atomgit.com/cann/ATB