详细解释
连续批处理(Continuous Batching,又称动态批处理、Orca Batching) 是大模型推理服务中把 GPU 利用率从 20% 至 30% 拉到 80% 至 95% 的核心调度算法。与早期静态批处理(Static Batching,必须等一整批的所有请求都生成完最后一个 Token 才能弹出、再塞下一批)完全不同,连续批处理会在每个解码步(Decode Step)结束后检查:哪些请求已经生成了 EOS 结束符可以立刻出队?队列里又有哪些新请求(或还在排队的 Prefill 请求)可以立刻塞进当前这批的空位?于是 GPU 在任何一个解码步都不会空转,整个推理过程如同一条永不间歇的流水线。
连续批处理最早由 UC Berkeley 在 2022 年的 Orca 论文 中系统化提出,随后成为 vLLM、SGLang、TensorRT-LLM、Text Generation Inference 等现代推理框架的默认调度模式。对于 7B 至 70B 级大模型,连续批处理单独一项优化即可在相同 P99 延迟下,将单 A100 的 TPS(每秒输出 Token 数)提升 2 至 4 倍,对应的 每百万 Token 成本 直接下降 50% 至 75%,是 LLM 在线推理的「成本一哥」优化手段。
唯元智创 的推理网关在接入 vLLM / SGLang 后端时默认开启 「连续批处理 + 分页注意力 + 前缀缓存」三位一体:连续批处理负责动态出队入队填 GPU 空隙,分页注意力负责把 KV Cache 切割成可按需换入换出的页避免显存碎片,前缀缓存 负责在 System Prompt、RAG 上下文重复出现时直接复用 Prefill 计算。三者叠加后,相同 GPU 集群下相比原生 TGI 静态批处理可支持的并发对话数再提升 1.5 至 2 倍,与 流式响应 结合后用户体感几乎不会出现「等很久才跳出第一字后又快速吐字」的怪现象。
四种推理批处理模式对比表
| 批处理模式 | 调度时机 | GPU 空闲时间占比 | 典型 70B 单 A100 输出 TPS | 适合场景 | 与流式响应兼容性 | 实现复杂度 |
|---|---|---|---|---|---|---|
| 静态批处理 Static Batching | 一批全部 EOS 后才切换 | 高(30% 至 60%) | 1,200 至 1,800 | 离线评测、纯离线批处理 | 差(用户等待整批结束) | 极低 |
| 客户端批处理 Client Batching | 由调用方按时间窗攒批 | 中高(20% 至 40%) | 1,800 至 2,500 | 简单 Embedding、轻量 Rerank | 中(调用方控制) | 低 |
| 连续批处理 Continuous Batching | 每个解码步动态进出 | 极低(5% 至 15%) | 3,500 至 5,000 | 在线实时对话、RAG 问答 | 极佳(逐 Token 出队) | 中高 |
| 连续批处理 + 投机解码(Speculative Decode) | 连续批 + 每步草稿验证 | 极低(3% 至 10%) | 6,000 至 9,000 | 低延迟高吞吐旗舰场景 | 极佳 | 高 |
| 唯元智创 默认组合(Continuous Batching + PagedAttention + Prefix Cache) | 连续批 + 页式 KV 管理 + 提示缓存 | 极低(3% 至 8%) | 4,500 至 6,500 | 通用在线推理 + RAG + 企业 SLA | 极佳 | 中(开箱即用) |
实战经验与避坑
- 连续批处理要生效,推理框架必须原生支持;在「外层自写请求队列攒批」不算数:很多团队想偷懒,在外层用 Python asyncio 队列按 500 毫秒或 20 条一组攒一批再扔给 TGI / vLLM,以为这就是「批处理」,但本质仍是静态批(TGI 内部如果不是连续批,还是必须等这批所有请求 EOS 后才清),吞吐提升通常不超过 50%,和真正的连续批(每解码步进出)相去甚远。正确做法:直接用 vLLM 0.2+、SGLang 0.1+、TensorRT-LLM 0.5+ 这些原生 Continuous Batching 的推理引擎,外层只做简单的并发上限控制即可。
- 连续批处理的「最大并发批大小 max_num_seqs」有黄金区间,不要设太高:很多人以为「连续批就是并发设越大越好」,于是把 vLLM 的
max_num_seqs从默认 256 直接拉到 2048,结果 P99 延迟从 3 秒飙升到 15 秒以上。原因是连续批本质是一种「公平共享调度」:当你塞 2000 条请求同时运行时,每条请求每个解码步只能分到 GPU 总算力的 1/2000,于是所有请求都变慢。黄金经验:7B 模型单 A100 推荐 max_num_seqs 256 至 512,70B 模型单 A100 推荐 64 至 128,并根据你的 P99 目标反推——如果延迟超标就下调并发,而不是盲目加大。 - 连续批处理必须配合分页注意力使用,否则显存碎片会吃掉 30% 至 50% 的显存收益:连续批的请求长短不一,入队出队频繁,如果 KV Cache 还是「一条请求一段连续显存」的老分配方式,出队请求留下的空洞无法被新请求的 KV 填满,显存利用率骤降。必须搭配 分页注意力 把 KV Cache 切成固定大小的 16KB 或 64KB 页,出队的页立即回收供新请求复用,整体 KV 显存利用率从 40% 左右提升到 85% 至 95%,相当于白嫖了 2 倍并发。
- 流式响应下要关注「首字延迟 TTFT」与「每两字间隔 IRR」两个长尾指标,不要只看 TPS:连续批在高并发下虽然 TPS 非常高,但如果调度器是纯贪心的(FIFO 按先来后到塞),会出现「新来的短请求 Prefill 长时间排不到,TTFT 5 秒以上」的现象。正确做法:给 Prefill 阶段设更高的调度优先级(vLLM
--preempt-mode swap+ SGLang 里的policy=fcfs配合 prefill priority),保证每个新请求到达后 100 毫秒内至少能执行一次 Prefill,这样 P99 TTFT 才能稳定控制在 500 毫秒以内。 - 长输出请求要做「抢占 + 换出 Preempt/Swap」,否则会被短请求反复挤兑永远跑不完:有些请求是写 3000 字报告、代码整文件生成,连续批里如果完全公平,长请求每 30 步才轮到一次解码,实际生成时间从 30 秒拖到 5 分钟。解决方案:用 vLLM/SGLang 自带的 Preempt 机制——当显存吃紧时,把「连续运行步数最多」的长请求的 KV 页临时写到 CPU 内存(Swap)或直接丢弃(Recompute),先腾显存给新来的 Prefill 跑,短请求送走后再把长请求的 KV 页换回显存继续。这样兼顾了短请求低延迟和长请求能最终跑完,长请求完成率从 60% 左右拉到 99% 以上。
- 上线前做「长短线混合压测」,不要只测 1:1 的短请求:连续批的优势只有在「长短混合、输入输出长度方差大」的真实场景才能体现。纯 1000 输入 + 100 输出的短请求,连续批和静态批差距可能不到 1.5 倍;但如果混合 30% 的长请求(输出 2000 Token 以上),连续批的吞吐优势会拉到 3 至 5 倍、P99 延迟反而更低。压测时务必按真实业务的输入输出分布做(比如 60% 对话 100 至 500 Token、25% RAG 检索 1K 至 4K、15% 代码生成或写作 2K 至 8K),才能测出真实的吞吐量和 SLA 安全水位。
常见问题
连续批处理和分页注意力是一回事吗?为什么很多人总一起提?
为什么我开了 vLLM 连续批处理,单卡 TPS 还是上不去?常见排查顺序是什么?
vllm:gpu_utilization 指标,如果 GPU 利用率长期低于 70%,说明「并发不够塞不满 GPU」,不是连续批的锅。第二步,检查 max_num_seqs 是否设得太小。很多人默认 128 甚至 64 去跑 7B 模型,GPU 永远填不满;7B 单 A100 先拉到 256,70B 拉到 64 做基线。第三步,看 KV 显存使用率。如果 KV 显存长期接近 100%,但 GPU 利用率 60%,说明「并发被显存卡死了」。这时优先开启分页注意力的 Swap/Preempt 到 CPU 内存,KV 可换入换出后并发能再涨 50% 至 100%;再不行就开 KV 缓存淘汰 的 Sliding Window 策略,主动把超长对话里最远的 KV 页丢掉腾显存。第四步,检查 Prefill 优先级是否太低。如果你的业务是大量短请求 + 少量长请求,但 vLLM 里 Decode 阶段优先级过高,新来的 Prefill 迟迟排不上,会出现「GPU 利用率不低但新用户 TTFT 极高、有效 TPS 低」的假象。把 vLLM 的 --prefill-chunk-size 适当调小(如 8192),保证短 Prefill 能更频繁地插入到 Decode 间隙。第五步,看请求是否被外层网关限流了。很多团队外层有个自作主张的令牌桶,按 100 QPS 封顶,后面的推理引擎再强也接不到请求。第六步,最后才怀疑是计算本身的瓶颈。如果 GPU 利用率稳定在 90% 以上、KV 显存还有富余、max_num_seqs 还没到上限但 TPS 就是上不去,说明确实到了计算瓶颈,这时才能上 FlashAttention、分页注意力的 Page Size 调优(2 Token 至 32 Token 扫一遍找最优)、量化(FP8/AWQ/GPTQ)、投机解码等优化手段。