1.2 指标先行:吞吐、延迟与显存天花板


1.2 指标先行:吞吐、延迟与显存天花板

本节摘要:「吞吐」「首 token 延迟」「每 token 间隔」这些词在讨论里经常被混用,导致优化目标错位。本节给出四个核心指标的严格定义与相互制约关系,并引出"显存天花板"——并发上限由 KV Cache 显存决定。这是全册的度量衡:第 8 章的压测与监控全部建立在本节的概念上。

「KV Cache 把显存吃光了」——你会在 vLLM 的日志里反复见到这个词组。它同时压着本节的两个主题:延迟和并发上限都与显存中的这部分状态直接挂钩。上一节我们把成本拆到了 prefill 与 decode 两段,本节把"慢"和"扛不住"翻译成可以度量、可以写进验收标准的指标语言。没有这套语言,后续所有优化都无从谈起——你甚至说不清一个改动到底是让服务变好了还是变差了。

四个核心指标:先定义再讨论

吞吐(Throughput):整个服务每秒产出的 token 总数。注意它是"总量"——八条请求同时生成时,吞吐是八条加在一起。服务方的成本优化看它,因为它直接决定一张卡单位时间能赚多少 token。

单请求延迟(Latency):一条请求从发出到收完全部输出的时间。用户对"我这一个请求等多久"的体感看它。吞吐和延迟经常背道而驰:把批凑得越大吞吐越高,但批里每条请求的单步耗时被拉长,延迟变差。

TTFT(Time To First Token,首 token 延迟):从请求到达到第一个 token 吐出的间隔。交互式产品的体感关键——用户可以接受打字机式的流式输出,但对"点了发送之后屏幕干瞪着"零容忍。TTFT 主要由排队时间与 prefill 耗时构成。

TBT / TPOT(Time Between Tokens,每 token 间隔):流式输出阶段相邻 token 的平均间隔,决定"打字机"的滚动速度。它主要由 decode 单步耗时决定,批越大它越差。

指标 谁在关心 由什么决定 被什么伤害
吞吐 服务方/成本 批大小 × decode 效率 显存不足限制并发、批凑不起来
单请求延迟 用户(总体感) TTFT + 输出长度 × TBT 排队、大批稀释
TTFT 交互产品 排队时间 + prefill 耗时 请求堆积、长输入
TBT 交互产品 decode 单步耗时 批过大、序列过长

这张表里最重要的一行关系是:批大小同时正向影响吞吐、负向影响 TBT。推理服务调优的核心矛盾,就是把批开到多大而不把体验指标打穿——第 8 章的调优闭环本质上是在这个跷跷板上找平衡点。

显存天花板:并发上限从哪来

服务能同时运行多少条请求,不取决于 CPU 有多快,而取决于显存里装得下多少条请求的 KV Cache。模型权重是固定开销(8B 模型 FP16 约 16 GB,70B 模型约 140 GB),剩下的显存才是给 KV Cache 的活动空间。粗略地说:

最大并发数 ≈(总显存 − 权重 − 激活与缓冲)÷(单请求 KV Cache 字节数)

单请求 KV Cache 有一个全册反复使用的公式,请记住它:

KV Cache 显存 = 2 × 层数 × KV 头数 × head_dim × 精度字节数 × 序列长度 × 批内请求数 其中"2"对应 Key 与 Value 两份张量。 以 Llama-3-8B(32 层、32 头、head_dim 128、FP16 即 2 字节)为例, 单条请求每 1024 个 token 的 KV Cache: 2 × 32 × 32 × 128 × 2 × 1024 ≈ 0.5 GB 一张 80 GB 的卡,权重占约 16 GB,若给 KV Cache 留 50 GB, 理论并发 ≈ 50 ÷ 0.5 ≈ 100 条(按每条 1024 token 上下文计)。

用一小段脚本把这笔账算清楚,后续调参时可以直接改系数复用:

def kv_cache_gb(layers, kv_heads, head_dim, seq_len, batch, bytes_per=2): """估算 KV Cache 显存占用(GB)。bytes_per: FP16=2, FP8/BF8 类=1""" total_bytes = 2 * layers * kv_heads * head_dim * bytes_per * seq_len * batch return total_bytes / 1024 ** 3 # Llama-3-8B:32 层、32 头、head_dim 128,上下文 4096,并发 32 条 print(kv_cache_gb(32, 32, 128, seq_len=4096, batch=32)) # ≈ 64.0 GB # 同模型换 GQA 后 KV 头数为 8: print(kv_cache_gb(32, 8, 128, seq_len=4096, batch=32)) # ≈ 16.0 GB

留意第二组数字:同一个模型若用了分组查询注意力(GQA,KV 头数远少于注意力头数),KV Cache 直接缩到原先的几倍之一。这就是为什么新模型纷纷采用 GQA/MQA——架构设计本身就在为显存天花板松绑。

但这里有一个刺眼的事实:按上面的算法,传统推理框架的真实并发往往远够不到理论值。原因不是公式错了,而是分母里的显存没有被充分利用——传统框架按"最长可能序列"给每条请求整块预留空间,大量显存被从未用到的预留量锁死。这笔糊涂账,正是第 2 章的主角。

两个指标,两套口径

讨论优化效果时要先声明口径,否则数字没有意义:

单请求口径:固定输入输出长度,测单发的 TTFT 与 TBT。它反映模型与硬件的物理下限,几乎不随推理框架变化——换 vLLM 不会让单条请求的 decode 突然快一倍,因为权重搬运量没变。

服务口径:按真实流量的输入输出长度分布发压,测整体吞吐与分位延迟(P50/P99)。框架优化的收益几乎全部体现在这个口径上:并发能力上去了,同等硬件单位时间产出的 token 翻数倍,是"把闲置资源用起来"的结果。

关键直觉:vLLM 类系统的优化,本质不是把单步算得更快,而是让更多请求共享同一段搬运时间、把同一块显存伺候更多条请求。理解了这一点,你就能预判哪些优化有效:任何"提高共享度"的手段(批处理、前缀共享、多 LoRA 共享权重)都有大收益;任何"只加快单步"的手段收益则受带宽物理上限约束。

一个容易踩的坑:拿单发数据预测线上容量

曾有个团队用"单发 TBT 20 毫秒"推算"每卡每秒 50 token、一百张卡扛五千万日请求",上线即被打穿。问题出在两处:一是真实流量长度分布远比测试用例恶劣,长尾请求占掉数倍显存;二是没算排队——并发上限受显存天花板约束,流量一超,TTFT 不是线性劣化而是雪崩式劣化。容量规划必须用服务口径压测到拐点,第 8.3 节会给出完整方法。

本节要点回顾

  • 四个指标各司其职:吞吐看成本、延迟看总体感、TTFT 看响应、TBT 看流式体验;写验收标准时必须点名道姓。
  • 批大小是吞吐与 TBT 的跷跷板,推理服务调优的核心就是找平衡点。
  • KV Cache 公式是全册的算术基石:两乘层数、头数、head_dim、字节数、序列长度与批大小;GQA 能让它缩到几倍之一。
  • 显存天花板决定并发上限,理论并发与实际并发的差距正是后续章节要追回的浪费。
  • 单请求口径与服务口径必须分开谈,容量规划只能信服务口径的压测数据。

下一节我们把问题清单收拢,对照看看 vLLM 给每个问题准备的哪把钥匙——先把全景图立起来,再逐章深入。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U