4、吞吐量指标:吞吐量定义、衡量指标与性能基准测试方法
4.1 吞吐量的核心定义:从“能跑”到“跑得多快”
在多GPU推理场景中,吞吐量(Throughput)是衡量系统在单位时间内能够处理多少推理请求或生成多少Token的核心指标。它直接反映了集群的“生产力”,决定了在固定算力投入下,业务能够支撑多大的用户并发或离线任务规模。与单卡场景不同,多GPU系统的吞吐量不仅取决于单卡的计算速度,还高度依赖张量并行(Tensor Parallelism)、数据并行(Data Parallelism)以及通信总线(如NVLink、PCIe)的协同效率。
理解吞吐量需要区分两个层面:系统吞吐量与有效吞吐量。系统吞吐量指集群在满载状态下单位时间完成的推理总量;有效吞吐量则剔除了因排队、抢占或无效重算造成的浪费,只统计客户端实际收到完整响应的工作量。在调优实践中,我们更关注有效吞吐量,因为它直接关联用户体验和业务成本。
4.2 衡量指标:tokens/s 与 requests/s 的双重视角
多GPU吞吐量通常用两个互补的指标来衡量,它们分别从“生成效率”和“服务能力”两个维度刻画系统性能。
4.2.1 tokens/s(每秒生成Token数)
这是最细粒度的指标,表示系统每秒生成的Token总数。在多GPU场景下,通常以聚合tokens/s(所有GPU卡生成Token之和)作为衡量标准。该指标直接反映模型的计算吞吐能力,受以下因素影响:
- Batch Size(批大小):增大Batch可提高GPU利用率,但过大会增加显存压力和调度延迟。
- 并行策略:张量并行会引入通信开销,数据并行则需考虑负载均衡。
- 显存带宽:权重和KV Cache的读取速度是瓶颈之一。
4.2.2 requests/s(每秒请求数)
这是面向业务层的指标,表示系统每秒能完成的完整请求数量。它受请求复杂度(输入长度、输出长度)和并发度影响。在vLLM中,由于采用Continuous Batching(连续批处理),requests/s与tokens/s并非简单的线性关系——短请求(如“你好”)的requests/s会很高,但tokens/s可能很低;长请求(如生成2000字文章)则相反。
| 指标 | 关注维度 | 典型场景 | 调优侧重点 |
|---|---|---|---|
| tokens/s | 算力利用率 | 离线批量生成、模型评测 | 增大Batch、优化显存布局 |
| requests/s | 服务吞吐能力 | 在线API服务、交互式应用 | 控制队列深度、减少排队 |
4.3 性能基准测试方法:从脚本到多卡压测
要准确测量多GPU吞吐量,需要一套严谨的基准测试流程。以下是推荐的方法路径:
4.3.1 基准测试核心流程
- 固定模型与精度:明确模型(如Llama-3-8B)、精度(FP16/BF16/INT8)和并行配置(TP=4, DP=2)。
- 准备代表性数据集:使用与真实业务分布接近的输入长度(如ShareGPT数据集),避免使用过短或过长的极端样本。
- 预热(Warm-up):先运行若干批请求,让CUDA上下文、显存分配和KV Cache达到稳定状态。
- 持续压测:以固定并发数(如32、64、128)发送请求,持续运行5-10分钟,记录稳定后的数据。
- 记录关键指标:同时采集聚合tokens/s、requests/s、P99延迟、GPU利用率(通过nvidia-smi或dcgm)。
4.3.2 使用vLLM内置Benchmark工具
vLLM提供了官方压测脚本 benchmark_serving.py,支持模拟真实请求模式。以下是一个典型的多GPU压测命令:
# 启动vLLM服务(4卡TP)
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Llama-3-8B-Instruct \
--tensor-parallel-size 4 \
--max-num-seqs 256 \
--port 8000
# 在另一终端运行压测
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 2000 \
--request-rate 20 \
--max-concurrency 64 \
--port 8000 \
--save-result
输出结果会包含类似以下的关键行:
Successful requests: 2000
Benchmark duration: 312.5s
Total input tokens: 1,250,000
Total generated tokens: 2,800,000
Request throughput (req/s): 6.4
Output token throughput (tokens/s): 8960.0
Mean latency: 4.8s
P99 latency: 9.2s
4.3.3 多GPU场景的专属测试要点
- 通信瓶颈探测:对比TP=1与TP=4时的tokens/s,若TP=4的加速比低于3.2倍,需检查NVLink拓扑或通信算子效率。
- 显存均衡性:通过
nvidia-smi dmon -s m观察各卡显存占用,若某卡显存明显偏高,说明KV Cache分配不均。 - 扩展性测试:分别测试2卡、4卡、8卡下的吞吐量,绘制扩展曲线,判断是否存在拐点。
nvidia-smi 的“Volatile GPU-Util”和“Encoder/Decoder”利用率。若GPU-Util接近100%但tokens/s增长停滞,说明已到计算上限;若GPU-Util低于70%,则需检查是否因Batch过小或通信等待导致。
4.4 案例:4卡A100的吞吐量基准测试复盘
某团队在4×A100-80GB(NVLink全互联)上部署Llama-3-8B,目标是支撑200路并发对话。他们进行了如下测试:
测试配置:TP=4,max-num-seqs=128,使用ShareGPT数据集,请求速率从10逐步提升至50。
测试结果:
| 请求速率(req/s) | 聚合tokens/s | P99延迟(s) | GPU平均利用率 | 是否过载 |
|---|---|---|---|---|
| 10 | 7,200 | 3.1 | 82% | 否 |
| 20 | 8,900 | 5.8 | 95% | 否 |
| 30 | 9,100 | 12.4 | 98% | 是(排队严重) |
分析:当请求速率达到30 req/s时,虽然tokens/s仅微增,但P99延迟从5.8s飙升至12.4s,说明系统已进入过载区。此时有效吞吐量(以P99延迟<10s为SLO)反而下降。最终团队将请求速率限制在22 req/s,并调整max-num-seqs至192,使P99稳定在6.2s,聚合tokens/s达到9,300。
4.5 误区与复盘:吞吐量测试中的常见陷阱
- 误区一:忽略预热直接压测。未预热时,显存分配和CUDA kernel加载会导致前几十个请求延迟偏高,拉低整体吞吐数据。应至少预热100个请求。
- 误区二:使用固定短输入测试。若测试数据全是“你好”这类短输入,tokens/s会虚高,但无法反映真实长文本生成场景。应使用混合长度的数据集。
- 误区三:只测单并发。单并发下的tokens/s反映的是“单请求最优延迟”,而非系统吞吐能力。必须使用多并发压测。
- 误区四:忽略通信开销。在多GPU下,若TP=2的tokens/s反而低于TP=1,说明通信同步开销已超过并行收益。此时应检查是否启用了
--enforce-eager或通信库版本问题。
wandb 或简单的CSV文件记录每次实验的tokens/s、requests/s、P99延迟和GPU利用率,便于横向对比。
上图展示了多GPU吞吐量基准测试的完整闭环:从负载生成、vLLM引擎调度、GPU集群执行到指标采集与判定。在实际调优中,应反复执行该循环,每次只改变一个变量(如Batch Size、TP大小或请求速率),以定位吞吐量瓶颈。