吞吐量概念与度量:从“快不快”到“多不多”

在诊断 vLLM 性能问题时,我们首先要回答一个看似简单的问题:系统到底跑得多快? 然而在 LLM 推理场景中,“快”并不只有一个维度。用户感受到的“快”是首字延迟低、生成流畅;而运维和成本控制关心的“快”是单位时间内能处理多少请求、产出多少 token。吞吐量(Throughput)正是从“数量”维度刻画系统能力的核心指标。它不回答“单个请求多快”,而是回答“系统整体多能装、多能产”。

3.1 吞吐量的本质定义

吞吐量指系统在单位时间内成功处理的工作量。对于 vLLM 这类文本生成服务,工作量有两种天然计量单位:请求数(requests)和Token 数。因此,吞吐量不是一个单一数值,而是一组从不同视角观察的指标。理解它们的区别,是后续调优的前提。

关键认知:吞吐量是“系统级”指标,不是“单请求”指标。一个系统单请求延迟 50ms,但如果只能串行处理,每秒最多 20 个请求;另一个系统单请求延迟 200ms,但支持 64 路并发,每秒可处理 320 个请求。后者吞吐量远高于前者,这正是 vLLM 通过 PagedAttention 和 Continuous Batching 追求的目标——牺牲部分单请求延迟,换取数量级的吞吐提升。

3.2 核心度量指标详解

在实际工程中,我们通常用以下三个指标构成吞吐量度量的“铁三角”:

指标 定义 典型单位 关注点
Token 吞吐量 系统每秒生成的 token 总数(含输入+输出) tokens/s 算力利用效率、硬件饱和度
请求吞吐量 系统每秒完成的完整请求数 requests/s 业务处理能力、QPS 承载
并发吞吐量 在特定并发数下测得的吞吐量 tokens/s @ concurrency 系统在不同负载下的表现曲线

需要特别注意的是 tokens/s 与 requests/s 的换算陷阱。假设系统每秒产出 1000 个 token,如果每个请求平均输出 500 token,则每秒完成 2 个请求;但如果请求平均输出 50 token,则每秒可完成 20 个请求。两者差异巨大,但 token 吞吐量完全相同。因此,在汇报性能时必须同时标注两个指标,并说明平均输入/输出长度,否则数据毫无意义。

3.3 性能基准测试方法

度量吞吐量不能靠“感觉”,必须遵循可重复、可对比的基准测试流程。以下是 vLLM 场景下推荐的标准方法:

3.3.1 测试数据集构建

使用真实业务分布的数据集,或使用 ShareGPT、Alpaca 等公开数据集。关键是要控制输入长度分布和输出长度分布。vLLM 官方提供了 benchmark_serving.py 脚本,支持通过参数模拟不同请求模式:

# 使用 vLLM 内置压测脚本,模拟真实请求分布
python benchmark_serving.py \
    --backend vllm \
    --model meta-llama/Llama-3-8B-Instruct \
    --tokenizer meta-llama/Llama-3-8B-Instruct \
    --dataset-name sharegpt \
    --dataset-path ./ShareGPT_V3_unfiltered_cleaned_split.json \
    --num-prompts 500 \
    --request-rate 10 \
    --max-concurrency 32 \
    --output-len 512

其中 --num-prompts 控制总请求数,--request-rate 控制请求到达速率(设为无穷大表示全并发灌入),--max-concurrency 控制客户端最大并发连接数。

3.3.2 测试执行与数据采集

执行测试时,需要同时监控服务端日志和客户端统计。vLLM 的 benchmark 脚本会输出如下关键结果:

Successful requests: 500
Benchmark duration: 128.32s
Total input tokens: 152340
Total generated tokens: 245890
Request throughput: 3.90 requests/s
Output token throughput: 1916.34 tokens/s
Total token throughput: 3103.55 tokens/s
Mean TTFT: 45.2ms
Mean TPOT: 18.7ms

注意:Total token throughput 是输入+输出 token 的总和,而 Output token throughput 仅统计生成部分。在对比不同系统时,务必明确使用的是哪个口径。

3.3.3 并发扫描(Concurrency Sweep)

单点测试无法反映系统全貌。正确做法是进行并发扫描:从并发数 1 开始,按 1、2、4、8、16、32、64、128 逐步增加,记录每个并发点下的吞吐量。将结果绘制成曲线,可以清晰看到系统的“拐点”——即吞吐量不再随并发增加而提升的饱和点。这个拐点通常就是系统的最佳工作负载区间。

实操建议:在 GPU 显存允许范围内,vLLM 的吞吐量通常随并发数近似线性增长,直到达到算力或显存带宽瓶颈。如果曲线过早平坦甚至下降,说明可能存在调度开销过大、KV Cache 命中率下降或显存碎片化等问题,这正是后续章节要诊断的对象。

3.4 案例:一次完整的吞吐量基准测试

假设我们在一台 8×A100 80GB 的服务器上部署了 Llama-3-70B-Instruct 模型,使用 vLLM 0.6.0 版本,张量并行度为 8。我们希望通过基准测试回答:系统最大能支撑多少 QPS?每 token 成本是多少?

测试步骤如下:

  1. 准备数据集:从生产日志中随机抽取 2000 条真实请求,统计得到平均输入长度 850 token,平均输出长度 420 token。
  2. 预热:先发送 50 个请求预热 CUDA 内核和显存分配器,避免冷启动影响。
  3. 并发扫描:分别在并发 1、4、8、16、32、64、128、256 下各运行 3 分钟,取稳定段数据。
  4. 记录结果:得到如下关键数据:
并发数 请求吞吐 (req/s) 输出吞吐 (tokens/s) 平均 TTFT (ms) 平均 TPOT (ms)
10.833618042
168.2344421048
6422.5945035065
12828.11180262089
25627.8116761150142

从数据可以看到:并发从 128 增加到 256 时,吞吐量不再上升反而微降,且 TTFT 和 TPOT 显著恶化。这说明系统的最佳并发点约为 128,此时吞吐量约 28 req/s,输出 token 吞吐约 11800 tokens/s。超过该点后,排队延迟和调度开销开始主导,系统进入过载区。

常见误区:不要只报“最大吞吐量”而不报对应延迟。上表中并发 256 时吞吐量仍有 27.8 req/s,但 TTFT 已从 620ms 恶化到 1150ms。对于在线交互场景,超过 1 秒的 TTFT 是不可接受的。因此,有效吞吐量必须结合延迟约束(如 TTFT < 500ms)来定义,否则指标会误导容量规划。

3.5 吞吐量度量的常见误区与复盘

在长期性能调优实践中,以下误区反复出现,值得专门复盘:

  • 误区一:只测 requests/s,忽略 token 长度分布。 两个系统都报 10 req/s,但一个平均输出 2000 token,另一个平均输出 100 token,实际算力消耗相差 20 倍。正确做法是同时报告 req/s 和 output tokens/s,并附带平均输入/输出长度。
  • 误区二:用单条 prompt 反复压测。 如果所有请求都是同一个短 prompt,KV Cache 的局部性会虚高吞吐量。真实场景中请求长度高度可变,必须使用多样化的数据集。
  • 误区三:忽略预热和稳态。 刚启动时 CUDA 图捕获、显存分配尚未稳定,前几十个请求的数据不可信。应丢弃前 10% 的预热数据,只统计稳态段。
  • 误区四:把吞吐量当作唯一指标。 吞吐量提升往往伴随延迟上升。在调优时,应设定一个延迟 SLO(如 TTFT < 800ms,TPOT < 100ms),然后在该约束下最大化吞吐量,而不是无约束地追求吞吐。

吞吐量度量是性能工程的“仪表盘”。没有准确的度量,后续的 PagedAttention 调优、Continuous Batching 参数调整、KV Cache 量化等操作都将失去方向。掌握本节的概念与基准方法后,下一节我们将深入 vLLM 的调度引擎,剖析吞吐量瓶颈产生的底层机制。

吞吐量度量体系与基准测试流程 核心度量指标 Token 吞吐量 单位: tokens/s 衡量算力利用效率 输入+输出 token 总和 请求吞吐量 单位: requests/s 衡量业务处理能力 QPS / RPS 承载 并发吞吐量 单位: tokens/s @ C 不同并发下的表现曲线 寻找系统饱和拐点 基准测试方法流程 1 构建测试数据集 真实分布 / ShareGPT / Alpaca 控制输入输出长度分布 2 执行并发扫描 并发数: 1 → 2 → 4 → ... → 256 每点运行 3 分钟取稳态 3 采集多维度指标 req/s + tokens/s + TTFT + TPOT 同时记录 GPU 利用率 4 分析拐点与最佳并发 吞吐量饱和点 = 最佳工作区间 结合延迟 SLO 确定有效吞吐 输出与决策 基准测试报告 请求吞吐: 28.1 req/s 输出吞吐: 11802 tokens/s TTFT: 620ms @ C=128 TPOT: 89ms @ C=128 常见误区警示 ✗ 只报 req/s 不报 token 长度 ✗ 忽略预热与稳态 有效吞吐量 = 满足延迟 SLO 下的最大吞吐 核心公式:有效吞吐量 = 满足延迟约束(TTFT < SLO₁, TPOT < SLO₂)下的最大请求/Token 处理速率 度量是调优的基础 —— 没有准确的吞吐量基线,后续所有优化都无从对比验证