70B 大模型推理服务的容量规划与性能设计

很多 AI Infra 面试题彼此看似独立:计算 KV Cache、解释张量并行、分析 Decode 瓶颈、选择量化方案、设计压测指标、排查 OOM。放到真实部署里,它们其实是同一道综合题的不同步骤。

本文设定一个具体任务:使用 8 张 H100 80GB 部署一个 70B、GQA、BF16 的 Decoder-only 模型,并满足在线聊天业务的延迟目标。我们不会寻找唯一答案,而是展示一套可以复用的决策过程。

大模型推理服务容量规划闭环

图 1:容量规划不是一次显存除法,而是负载、资源、压测、归因和上线门禁构成的闭环。

这里的“容量”不是一个数字,而是一个约束向量:

Capacity=(显存,HBM 带宽,计算吞吐,互联,并发,SLO)Capacity=(\text{显存},\text{HBM 带宽},\text{计算吞吐},\text{互联},\text{并发},\text{SLO})

某个方案可能容纳更多请求,却因为 TPOT 超标而没有更高有效容量;另一个方案可能单请求延迟很低,却因 KV Cache 太小无法承受流量峰值。本文后续所有比较都以 Goodput 为最终尺度,而不是孤立的显存占用或 Tokens/s。

一、需求不能只写“部署 70B”

假设业务提供以下信息:

项目 假设值
模型 70B Decoder-only,80 层
隐藏维度 8192
Query/KV Heads 64 / 8
Head Dimension 128
权重精度 BF16
GPU 8 × H100 80GB,单机 NVLink
Prompt P50/P99 2K / 16K Token
平均输出 500 Token
TTFT SLO P95 小于 2 秒,示例目标
TPOT SLO P95 小于 60 ms,示例目标

这些 SLO 只是演示。真实项目应根据交互产品、离线任务或 Agent 工作流重新定义。

还需要补齐:

  • 到达率和峰值并发;
  • Prompt 长度的完整分布;
  • 系统 Prompt 是否大量重复;
  • 是否要求多模型或 Multi-LoRA;
  • 单机故障时是否允许降级;
  • 成本、功耗和可用区约束。

1.1 从到达率估算活跃请求数

容量规划经常直接假设“并发 64”,却没有解释这个数字来自哪里。稳定系统中可以先用 Little’s Law 建立近似:

Cλ×E[T]C\approx\lambda\times E[T]

λ\lambda 是每秒到达请求数,E[T]E[T] 是请求从进入到完成的平均驻留时间,CC 是系统中的平均活跃请求数。例如到达率 8 req/s、平均完成时间 6s,平均活跃请求约为 48。突发流量和长尾会让瞬时值更高,因此还需结合 P95/P99 和排队上限。

把并发与业务流量联系起来后,KV Cache 预算才不只是人为选择的压测参数。

二、第一步:权重能否装下

训练与推理显存状态模型

图 2:部署容量规划只使用右侧推理账本,但量化和并行选择仍要明确权重、KV 与运行时空间的边界。

70B BF16 权重的理论大小约为:

70×109×2 Bytes140 GB70\times10^9\times2\text{ Bytes}\approx140\text{ GB}

使用 TP=8 时,理想情况下每张卡约承担 17.5GB 权重。实际还会包含:

  • 未均匀切分或复制的参数;
  • CUDA Context;
  • NCCL Buffer;
  • Attention 和 GEMM Workspace;
  • CUDA Graph;
  • KV Cache;
  • 框架分配器保留空间。

因此,权重能装下不是瓶颈终点,而只是说明 TP=8 在容量上可行。

2.1 是否需要 INT8 或 INT4

如果 BF16 已经为 KV Cache 留出足够空间,量化不一定是第一步。Weight-only 量化可能减少 Decode 读取权重的带宽并提高单机容量,但要确认:

  • 目标 GPU 和推理框架是否有成熟 Kernel;
  • 模型精度是否满足业务要求;
  • Prefill 是否因反量化或 Kernel 形状变慢;
  • TP 下量化元数据如何切分;
  • 长上下文业务的主要瓶颈究竟是权重还是 KV Cache。

技术选型应该由 Benchmark 决定,而不是由“位宽更低”直接决定。

三、第二步:KV Cache 才是并发上限的关键

KV Cache 每 Token 大小为:

2LHkvdhb2LH_{kv}d_hb

代入 L=80L=80Hkv=8H_{kv}=8dh=128d_h=128、BF16 的 b=2b=2

2×80×8×128×2=327680 Bytes2\times80\times8\times128\times2=327680\text{ Bytes}

即整个模型每个 Token 约 320 KiB KV Cache。

如果 KV Head 能随 TP=8 均匀切分,每卡约承担八分之一,也就是约 40 KiB/Token。具体布局仍应以引擎和 Attention Backend 的实现为准。

3.1 平均负载和最坏负载不同

若 64 个并发请求平均已经缓存 2500 Token,总 KV Cache 约为:

64×2500×320 KiB48.8 GiB64\times2500\times320\text{ KiB}\approx48.8\text{ GiB}

分到 8 张卡约 6.1 GiB/卡,看起来很轻松。

但如果 64 个请求同时接近 16K Prompt,并继续输出 500 Token,总 KV Cache 会超过 300 GiB,单卡分片也可能超过 40 GiB。再考虑权重、Workspace 和运行时空间,容量压力会明显上升。

因此不能用 P50 Prompt 推导最大并发,也不能简单用 P99 长度假设所有请求同时达到最坏值。需要用真实分布做 Trace Replay 或概率模型。

四、第三步:确定并行方式

两节点多维并行拓扑示意

图 3:本文场景是单机 8 卡,TP 通信位于 NVLink 域;扩展到多机时,应避免把高频 TP Collective 直接放到慢速跨机链路。

单机 8 卡 NVLink 环境下,TP=8 是直观起点:

  • 权重均匀分片;
  • 层内通信留在高速 NVLink 域;
  • 不引入 Pipeline Bubble;
  • 一个模型副本可以使用全部 GPU。

但它也有代价:

  • 每个 Transformer 层都有 TP 通信;
  • 小 Batch 下通信和 Launch 占比可能较高;
  • 单个副本占用全部 GPU,故障域较大;
  • 扩容粒度是整套 8 卡实例。

如果量化后模型可以用 TP=4,可能在一台 8 卡机器上部署两个副本,以数据并行方式处理不同请求。此时总吞吐、尾延迟和故障隔离可能更好,但单请求可用 KV Cache、单副本最长上下文和量化精度需要重新评估。

所以要比较的不是“TP=4 还是 TP=8 哪个更先进”,而是:

1
2
3
一个 TP=8 大副本
vs
两个 TP=4 小副本

在真实请求分布下,哪个获得更高 Goodput。

五、第四步:配置 KV Cache 与调度器

5.1 gpu_memory_utilization

这个参数决定引擎可以为权重、KV Cache 和运行时使用多少显存。设得太低会限制并发,设得太高则可能在 CUDA Graph、临时 Workspace 或长请求下 OOM。

建议从保守值开始,用压测观察:

  • 实际可分配 KV Block 数;
  • 峰值显存;
  • 抢占次数;
  • OOM 和碎片情况。

5.2 max_model_len

如果业务 P99 只有 16K,却把最大序列长度配置为模型理论支持的 128K,可能让引擎为极少出现的请求保留过多规划空间或降低可接纳并发。

更合理的方式是按产品能力设置上限,并为超长请求设计独立队列、限流或专用实例。

5.3 Block Size

  • Block 过大:尾块浪费和细粒度调度能力下降;
  • Block 过小:块表、哈希和管理开销增加。

不要只测固定长度。不同 Prompt 分布对最佳 Block Size 的偏好可能不同。

六、第五步:哪些功能值得开启

6.1 Prefix Cache

如果大量请求共享系统 Prompt、Few-shot 示例或固定文档前缀,Prefix Cache 可以跳过重复 Prefill,明显降低 TTFT。

如果 Prompt 开头包含随机 ID、时间戳或用户特定内容,Token 前缀很早就分叉,命中率可能很低。此时缓存会占用显存,却没有带来足够收益。

开启前至少统计:

  • 可复用前缀长度;
  • 请求之间的 Token 级重复率;
  • 缓存命中率;
  • 命中后节省的 Prefill 时间;
  • 缓存块占用和淘汰频率。

6.2 Chunked Prefill

P99 Prompt 达到 16K 时,长 Prefill 很可能干扰正在 Decode 的短请求。Chunked Prefill 可以改善 TPOT 稳定性,但在相同调度预算下可能让长请求 TTFT 增加。

是否开启应由 SLO 决定:

  • 聊天业务重视输出流畅度,通常更愿意保护 TPOT;
  • 离线批处理只关心吞吐,未必需要同样的切块策略;
  • 超长上下文可以进入独立队列,避免污染普通请求。

6.3 CUDA Graph 与 torch.compile

Decode 中 Batch Shape 相对稳定时,CUDA Graph 可以减少 CPU Launch 开销。需要同时评估:

  • 捕获 Shape 覆盖范围;
  • Graph 额外占用的显存;
  • 冷启动时间;
  • 动态控制流和调试需求;
  • 捕获外算子是否形成新的同步点。

6.4 Speculative Decoding

投机解码使用 Draft 模型或 Self-Draft 结构提出多个候选,再由目标模型并行验证。收益依赖接受率:

  • Draft 太弱:候选经常被拒绝;
  • Draft 太大:草稿本身开销过高;
  • 目标模型 Batch 已经很大:验证收益可能被调度和内存压力抵消。

它更适合作为单独 Benchmark 变量,而不是默认开启。

七、第六步:是否需要 Prefill/Decode 解耦

混合部署时,Prefill 和 Decode 共享 GPU:

  • Prefill 偏 Compute Bound;
  • Decode 偏 Memory Bound;
  • 长 Prefill 会抬高 Decode TPOT;
  • 两类阶段的最优 Batch 和并行配置不同。

PD 解耦将它们放在不同 Worker,并通过网络传输 KV Cache。它带来新的成本:

  • KV 传输带宽和延迟;
  • Worker 比例规划;
  • 请求路由;
  • 故障恢复;
  • KV 一致性和生命周期管理。

只有当混部的相互干扰已经成为主要瓶颈,并且业务规模足以摊销复杂度时,PD 解耦才值得采用。单机 8 卡的第一版系统通常应先把混部调度做好。

八、第七步:设计一套可信 Benchmark

8.1 不要只测固定 Prompt

至少覆盖:

  • 短输入、短输出;
  • 长输入、短输出;
  • 短输入、长输出;
  • P99 长上下文;
  • 高 Prefix 重复率;
  • 无 Prefix 重复;
  • 稳态到达和突发流量。

8.2 指标分层

层级 指标
用户体验 TTFT、TPOT、E2E、P95/P99
系统吞吐 Request/s、Input/Output Tokens/s
SLO Goodput、超时率、拒绝率
GPU SM、HBM、显存、Kernel Gap
调度 Queue Time、Batch Size、抢占次数
Cache Prefix 命中率、KV Block 使用率

8.3 性能回归门禁

每次修改引擎版本、模型权重、CUDA、Attention Backend 或量化方式后,自动执行相同负载集。门禁不应只限制平均吞吐,还应限制:

  • P95/P99 TTFT 和 TPOT;
  • 峰值显存;
  • 错误率和 OOM;
  • 输出正确性或精度回归;
  • 长上下文稳定性。

九、常见故障如何定位

9.1 启动时 OOM

优先检查权重精度、TP 数量、最大序列长度、CUDA Graph 捕获和显存利用率,而不是直接降低 Batch。

9.2 运行一段时间后 OOM

重点检查 KV Cache 增长、长请求比例、缓存块占用、抢占策略和请求是否正确释放。

9.3 GPU 利用率低

可能原因包括:

  • 请求不足,Batch 太小;
  • CPU 调度或 Tokenization 跟不上;
  • Kernel Launch Gap;
  • TP 通信等待;
  • 大量小 Kernel;
  • 请求长度差异导致调度低效。

先用 Nsight Systems 区分 GPU 空闲和 GPU 内部低效,再决定是否进入 Nsight Compute。

9.4 吞吐很高但用户仍觉得慢

平均 Tokens/s 可能掩盖排队和尾延迟。检查 P99 TTFT、TPOT 和 Goodput,并按 Prompt 长度和并发分桶。

9.5 NCCL Hang

检查所有 Rank 是否按相同顺序进入集合通信、进程是否异常退出、网卡与拓扑是否正确,然后使用 NCCL_DEBUG=INFOnccl-tests 分离代码与基础设施问题。

十、方案决策链与基线配置

一个完整方案不应该只报参数,而应呈现决策链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
业务负载和 SLO

模型权重与 KV 显存账本

TP/副本数/量化选择

KV Block 与调度配置

Prefix、Chunked Prefill、CUDA Graph

真实分布压测

Goodput 与成本比较

上线后的监控和回归门禁

对于本文场景,一个合理的第一版基线是:

  • 使用 BF16、TP=8 建立正确性和性能基线;
  • 使用 PagedAttention 和 Continuous Batching;
  • 将最大上下文限制在业务真实需要范围;
  • 对 16K 长 Prompt 开启或评估 Chunked Prefill;
  • Prefix Cache 由实际前缀命中率决定;
  • 用真实请求分布寻找 Token Budget 和并发上限;
  • 再与量化后 TP=4、双副本方案比较 Goodput;
  • 只有混部干扰无法满足 SLO 时,再评估 PD 解耦。

十一、技术 Q&A

Q1:TP=8 后,70B BF16 权重是否严格变成每卡 17.5GB?

17.5GB 只是参数均匀分片的理论值。Embedding、LM Head、Norm、小参数和量化元数据不一定都按同一方式分片;某些实现还会复制参数,或为集合通信准备连续 Buffer。容量规划应先根据引擎的实际分片规则计算下界,再用模型启动后的逐卡显存数据核对分片不均衡和额外状态。

Q2:为什么不能用 P50 Prompt 长度推导最大并发?

KV Cache 随每个活跃请求的实际缓存长度增长。按 P50 规划会在多个长请求同时出现时低估显存;假设所有请求都是 P99 又可能严重过度配置。更合理的方法是回放真实长度与到达 Trace,或按长度分桶建立概率模型,并为极端长请求设置独立队列、并发上限和 Token 配额。

Q3:Weight-only 量化为什么更可能加速 Decode?

Decode 的 Token 维很小,常受每轮读取大体量权重的 HBM 带宽限制。INT8/INT4 减少权重 Bytes,在具备高效融合反量化 Kernel 时可提高算术强度。Prefill 的大 GEMM 更接近 Compute Bound,其收益取决于低精度 Tensor Core、反量化开销和具体 Shape,因此加速比通常不会简单等于权重压缩比。

Q4:何时应引入 Chunked Prefill 或 PD 解耦,压测结果又如何转化为限流配置?

长 Prefill 阻塞 Decode、导致 TPOT 抖动时,可先用 Chunked Prefill 把计算切片;它会以潜在的 TTFT 增长换取更平滑的 Decode。当混部干扰经过统一调度仍无法满足 SLO,且流量规模足以支撑独立 Worker 池时,才值得用 PD 解耦换取阶段级隔离。压测时应找到满足 TTFT/TPOT SLO 的最高稳定到达率,以单副本 Goodput 乘以安全系数和可用副本数得到服务容量,再按 Prompt 长度或估算 Token 工作量实施 Admission Control;当排队时间、KV Block 水位或 P99 越过拐点时,应排队、拒绝或路由到长上下文池,而不是等到 OOM。

十二、系列导航

上一篇:Softmax 数值稳定性与 IO-Aware Attention

回到开篇:大模型训练与推理的显存模型

十三、参考资料

推理系统

量化与并行

  • SmoothQuant:W8A8 激活平滑量化。
  • AWQ:Activation-aware Weight Quantization。
  • GPTQ:训练后权重量化。
  • Megatron-LM:张量并行。

Benchmark 与指标