推理服务容量规划:从 QPS 到 GPU 实例数
说明:本篇为综述/无第一手实验数据,采用公开实践与容量工程路线。
实验目标
"线上 QPS 100 需要多少张卡"是推理服务上线前最常被问的问题,答案却常被拍脑袋。本篇目标:建立推理容量规划的完整方法——从业务 QPS 建模(峰值/波动)→ 单实例吞吐基准(12 章 benchmark 篇的延续)→ 延迟预算与并发约束 → 实例数与冗余公式 → 压测验收。读完能对"这个服务要几卡、预留多少余量、什么时候扩容"给出带计算依据的答案。
代码逐段拆解
第一段:QPS 建模与实例数估算
python
def capacity_plan(target_qps, peak_ratio, instance_throughput,
p99_budget_s, kv_overhead=0.1):
"""估算所需 GPU 实例数(含冗余与波动余量)"""
peak_qps = target_qps * peak_ratio # 峰值建模(如 3×均值)
# 单实例可用吞吐:受延迟预算约束(P99 预算内能稳定承受的并发)
usable = instance_throughput * (1 - kv_overhead)
instances = peak_qps / usable
# 冗余:N+1 起步,关键服务 2N
return {
'peak_qps': peak_qps,
'instances_min': int(instances) + 1, # N+1
'instances_critical': int(instances) * 2, # 2N
}
# 例:均值 100 QPS、峰值 3×、单卡 40 QPS(P99 预算内)、KV 开销 10%
print(capacity_plan(100, 3.0, 40))
# → peak 300 QPS / 单卡有效 36 QPS / 需要 ~9 卡(N+1)/ 18 卡(2N)要点:
- 峰值建模决定一切:容量按均值算必然爆——线上推理峰值/均值比常在 2-5×(时段效应、活动效应)。先按业务特性定
peak_ratio,再算容量。 - 单实例吞吐必须"在延迟预算内":vLLM 等框架的吞吐会随并发上升,但 P99 延迟也上升;容量规划用的吞吐是"P99 预算内的最大稳定吞吐",不是最大吞吐——这是 12 章 benchmark 篇的"预算内吞吐"口径的落地。
- KV 开销是安全系数:长上下文请求、前缀复用率低时 KV Cache 占显存(12 章 KV 篇),单实例有效并发下降——
kv_overhead就是给它留的余量。
第二段:扩容水位与压测验收
bash
# 扩容触发水位(监控表达式,呼应 06 章弹性篇)
# 当 GPU 利用率(DCGM SM)持续 > 70% 且 P99 > 预算 80% → 扩容
# 当利用率 < 40% 且持续 30 分钟 → 缩容
# 压测验收(12 章 benchmark 篇方法)
python -m vllm.entrypoints.benchmark.benchmark_serving \
--model your-model --num-prompts 10000 \
--request-rate 40 --max-concurrency 512 \
--percentile-metrics ttft,itl,tpot要点:
- 双信号扩容水位:利用率(GPU 侧)与 P99(用户侧)双指标——只盯利用率会漏掉"延迟已超但利用率不高"的队列堆积;只盯 P99 会反应滞后。
- 压测要带并发上限与请求分布:
max-concurrency模拟真实并发,--request-rate模拟到达节奏(12 章讲过的到达建模);压测结论是"这个配置在 XX QPS 下 P99 多少",而不是"最大吞吐多少"。 - 验收口径:容量规划是否正确,用"压测 P99 曲线"验证——在规划的 QPS 点压测,P99 必须低于预算;超了就加实例或调优,别等上线炸。
原理讲解
推理容量 vs 训练算力:不同的规划逻辑
| 维度 | 训练算力规划(10 章) | 推理容量规划(本篇) |
|---|---|---|
| 目标 | 单位时间训练量(卡时) | 单位时间请求量(QPS) |
| 约束 | 算力+显存+时间窗 | 延迟(P99)+并发+峰值 |
| 弹性 | 作业级(排队) | 实例级(秒-分级) |
| 余量逻辑 | 按峰值批次 | N+1/2N 冗余 + 波动余量 |
核心差异:训练能排队(慢点没关系),推理不能(超延迟即事故)——所以推理容量必须"峰值 × 冗余",训练算力可以"均值 × 利用率修正"。
单实例吞吐的三个决定因素
- 硬件:HBM 带宽(01 章:token 吞吐 ≈ 带宽/权重)、算力。
- 框架与量化:vLLM 连续批处理、KV 量化、权重精度(12 章 KV 篇的账本)。
- 请求特征:输入/输出长度比、前缀复用率、batch 形状——同硬件不同负载,单卡吞吐可差 5-10 倍,所以容量规划必须用"自己的负载"基准,不能抄别人的数字。
水位设计
低水位(缩容阈值):SM < 40% 持续 30min → 缩 1 实例
高水位(扩容阈值):SM > 70% 且 P99 > 80% 预算 → 扩 1 实例
安全水位(缓冲):预留 20% 实例余量应对突发(活动/故障转移)关键认知:扩容是"预防性"的——GPU 冷启动 5-15 分钟(06 章),等 P99 超了再扩已经来不及;水位要提前于延迟恶化,靠"利用率趋势"而不是"延迟现状"。
实验结果
(估算口径,非实测;示例服务)
| 输入 | 估算 | 结论 |
|---|---|---|
| 均值 100 QPS、峰值 3×、单卡 40 QPS | 9 卡(N+1)/ 18 卡(2N) | 关键业务按 2N |
| 长上下文占比 30% | 有效吞吐再降 20%-30% | 实例数上浮,或 KV 量化 |
| 前缀复用率高(RAG 场景) | 吞吐提升 2-3× | 优先做 prefix caching |
工程启示
- 峰值建模 + 延迟预算 + 冗余,三件套缺一不可:均值算容量、无延迟预算、无冗余,三者任何一个缺失都会在线上炸。
- 用自己负载的基准,不抄别家数字:请求特征对单卡吞吐影响 5-10 倍,容量规划基准必须来自自己的压测(12 章方法)。
- 水位看趋势,扩容要提前:利用率趋势 + P99 双信号,冷启动时间决定提前量。
- 与成本联动:2N 冗余是"成本翻倍"的决策——用竞价实例补冗余(06 章)可以降低成本而不牺牲关键路径稳定性。
下一篇预告:推理容量规划把"要几卡"算清楚了;下一步回到 AI×Science 主阵地——"科学基础模型:从数据到训练的工程全景"。