返回 文章 apply CMS 文章

NVIDIA AIPerf:大规模 LLM 推理基准测试实战指南

用 AIPerf 在 vLLM 上快速建立可复现的 LLM 推理性能基准测试循环。

LLM推理基准测试NVIDIA AIPerfvLLM
成长分 / 100 79 综合收获、行动、留存与影响

NVIDIA AIPerf:大规模 LLM 推理基准测试实战指南
为什么值得读了解 AIPerf 如何通过多进程架构解决传统基准测试工具的客户端瓶颈问题。

学习从零开始运行合成 ISL/OSL 基准测试和泊松流量模式的具体步骤。

关键洞察
  1. AIPerf 是 GenAI-Perf 的指定继任者,从头重写,与旧架构彻底决裂,支持大规模扩展。
  2. 多进程系统通过 ZMQ 协调,防止客户端成为瓶颈,实现更准确的服务器基准测试。
  3. 支持 15 种以上端点类型和公共数据集,如 ShareGPT 和 trace 回放格式。
转成行动

深入阅读

正文与原文对照

原文保真覆盖:全文原文字符:16183

你正在某个系统上部署一个模型。它启动了,提示词也能得到响应。接下来是真正棘手的问题:它够快吗?

你的第一反应可能是发几条 curl 命令、手写一个 asyncio 脚本,或者凭感觉再糊一个一次性的负载生成器。这些路子都有同样的问题:单进程性能受限、Python 的 GIL 限制了并发,或者测出来的数字是以你自己搭的参照为基准的。无论哪种,你得到的结果都无法完全信任,而且一旦需求变化,这些工具就得重写。

你需要的是这样一个负载客户端:它能把真实的服务器压满而自身不成为瓶颈,产出可以据以行动的结果,并且配置只需五分钟,而不是五小时。这就是 NVIDIA AIPerf。

AIPerf 有何不同

AIPerf 是 GenAI-Perf 指定的继任者,是一次从头开始的重写。这些设计选择反映了大规模运行 LLM 基准测试所积累的教训:

  • 与旧架构彻底决裂。AIPerf 不像 GenAI-Perf 那样运行在 Perf Analyzer 之上。这是一次干净的架构切割,也是 AIPerf 能够这样扩展的原因。如果你要迁移现有工作流,迁移指南涵盖了主要差异。
  • 客户端不该成为瓶颈。大多数基准测试工具(包括 GenAI-Perf)采用单进程架构,在真实的并发或请求速率下会受限于 GIL。AIPerf 是一个多进程系统:工作进程负责生成负载,独立的记录处理服务负责处理结果,一切通过 ZMQ 协调。这种结构避免了 AIPerf 自身成为客户端瓶颈,从而让服务器基准测试更加准确。
  • 覆盖你实际运行的工作负载。AIPerf 支持 15 种以上的端点类型:chat、responses、NIM rankings、图像生成等等,也支持 ShareGPT 等公开数据集,以及来自 Mooncake、Baseten、WEKA(AgentX)等的追踪回放格式。无论是跑一次快速的合成冒烟测试,还是回放捕获的生产流量,你都不需要换工具。
  • 真正由你掌控的负载形态。AIPerf 支持恒定、泊松和 gamma 到达模式(突发性可调),支持并发数和请求速率的渐进爬升,也支持合成分布,包括用于可变 ISL/OSL 的 vLLM/SGLang range-ratio。你控制的是负载的形态,而不只是总量。

你的第一次基准测试:在 vLLM 上使用合成 ISL/OSL

本文的演示使用通过 vLLM 部署的 Qwen3-0.6B。选择这个模型是有意为之:它小到可以在单块 GPU 上运行,也快到可以无需等待地反复迭代。重点并不是专门测试 Qwen3-0.6B,而是建立起测量的闭环。一旦有了这个闭环,换用别的模型或端点只需改一个参数。

启动服务器

拉取并启动 vLLM,同时启用推理解析器(reasoning parser):

docker pull vllm/vllm-openai:latest
docker run --gpus all -p 8000:8000 -e HF_TOKEN vllm/vllm-openai:latest \
  --model Qwen/Qwen3-0.6B \
  --reasoning-parser qwen3 \
  --host 0.0.0.0 --port 8000

安装 AIPerf

我们可以用 uv 安装一份全局副本:

uv tool install aiperf

或者安装到虚拟环境中:

uv venv venv
source venv/bin/activate
uv pip install aiperf

一个平台说明:在 aarch64 上,crick 依赖只以源码形式发布,需要 C 工具链(Debian/Ubuntu 上是 build-essential,RHEL 上是 Development Tools)。如果安装卡在这个包上,原因就在这里。

运行基准测试

服务器启动、AIPerf 安装完成后,我们就可以运行第一次性能剖析了:

aiperf profile \
  --model Qwen/Qwen3-0.6B \
  --endpoint-type chat \
  --streaming \
  --url localhost:8000 \
  --synthetic-input-tokens-mean 128 \
  --synthetic-input-tokens-stddev 0 \
  --output-tokens-mean 128 \
  --output-tokens-stddev 0 \
  --extra-inputs min_tokens:128 \
  --extra-inputs ignore_eos:true

这里有几个参数的作用比看上去要大:

--synthetic-input-tokens-stddev 0 和 --output-tokens-stddev 0 把工作负载固定为每个请求恰好 128 个输入 token 和 128 个输出 token。这复现了一种常用的静态基准测试,即请求长度和输出长度保持不变。

--extra-inputs min_tokens:128 和 --extra-inputs ignore_eos:true 让模型真正输出 128 个 token,而不是提前停止。没有它们,输出 token 数只是一个建议值:模型会在自然结束时停下,这可能远短于你的目标 OSL。吞吐量数字会低于应有水平,而且在多次运行之间无法复现。

如果想测量 TTFT 和 ITL,--streaming 是必需的。没有流式输出,服务器会先把完整响应攒好再发送,也就没有首 token 或解码 token 事件可供测量。

你将看到什么

AIPerf 实时 TUI 仪表盘在运行基准测试时的动画截图。仪表盘分为三个面板,上方三分之二被分成左右两部分,左侧是实时进度,右侧是按百分位数分解的各项统计数据。屏幕下方三分之一显示 AIPerf 后端执行基准测试时的滚动日志。
图 1. AIPerf 实时仪表盘用户界面的动画示例。实时仪表盘显示运行进度、各项指标及其分布,以及来自 AIPerf 后端的滚动事件日志

下一节我们会讲解如何解读这些数字。现在先注意下方图 2 中输出的形态:按百分位数分解的延迟、以每秒 token 数计的吞吐量,以及请求级别的统计数据,全都集中在一处。这就是你之后拿来对比一切的基线。

AIPerf 基准测试运行结束时终端中显示的统计摘要截图。截图自上而下显示三张表:有效指标、活跃指标和摘要指标。每张表都分解出平均值、最小值、最大值、p99、p90、p50 和标准差,各占一列。在输出末尾,AIPerf 报告了用于重复该基准测试的命令行、基准测试耗时、最终摘要及服务器指标采集结果(CSV 和 JSON 两种格式)的路径,以及运行日志文件的路径。
图 2. AIPerf 运行结束时输出指标的截图示例,其中包含多种指标的有效统计、活跃统计和摘要统计,并附有便于快速查看的百分位数分解、复现命令行和输出位置

解读数字:AIPerf 呈现了什么

运行完成后,AIPerf 会在控制台打印一张指标表,并把完整结果写入 CSV 和 JSON。下面说明你看到的都是什么。

四大核心指标:

  • TTFT(Time to First Token,首 token 时间)——从发出请求到收到第一个 token 所用的时间。这是交互式场景下最主要的延迟信号。
  • ITL(Inter-Token Latency,token 间延迟)——生成过程中相邻 token 之间的时间间隔。即使 TTFT 看起来正常,ITL 偏高也意味着解码阶段吃力。
  • 请求延迟(Request Latency)——完整响应的端到端时间。它把预填充和解码的开销合成了一个数字。
  • 输出 token 吞吐量(Output Token Throughput)——所有并发请求每秒生成的 token 数。这是做容量规划时最主要的吞吐量信号。

关于这些指标以及 AIPerf 报告的其他所有指标的完整定义,请参阅指标参考。

获得完整全貌。以上每项指标都会按百分位数(p25、p50、p75、p90、p95、p99)分解报告,同时给出最小值、最大值、平均值和标准差。这些分解很重要,因为它们能暴露长尾分布:一台服务器的平均 TTFT 很健康、p99 却有离群值,从汇总数据看一切正常,在生产环境中却会出问题。

不止这四大指标。在 DCGM 或 pynvml 可用的情况下,AIPerf 还会把 GPU 功耗、利用率和显存占用拉进同一次运行的输出中。要把延迟尖峰和显存压力事件关联起来,不需要再单独做一次性能剖析,遥测数据已经在那里了。

进一步:配置流量模式

现在我们已经通过静态基准测试初步入门,可以开始探索更动态的场景。上一节给出的是极其固定的流量模式,而真实的推理流量并不遵循静态模式。要测试一个不那么死板的场景,我们可以利用 AIPerf 的一些合成工作负载参数,为请求引入变化。

aiperf profile \
  --model Qwen/Qwen3-0.6B \
  --endpoint-type chat \
  --streaming \
  --url localhost:8000 \
  --request-rate 10 \
  --arrival-pattern poisson \
  --synthetic-input-tokens-mean 512 \
  --synthetic-input-tokens-stddev 128 \
  --output-tokens-mean 128 \
  --output-tokens-stddev 32 \
  --random-seed 42 \
  --request-count 200

与上面的静态基准测试相比,有几处变化。

--arrival-pattern poisson 配合 --request-rate 10 表示请求平均每秒到达 10 个,到达间隔服从指数分布。服务器现在经历的是突发和空档,而不是单一的用户流,这才是真实流量下排队的实际样子。

--synthetic-input-tokens-stddev 128 在 512 个 token 的均值附近引入了方差,产生长短混合的提示词。服务器在预填充阶段必须处理长度不一的提示词,而不是完全相同的提示词。

--output-tokens-stddev 32 在输出侧增加了方差。请注意,这条命令中已经没有 min_tokens 和 ignore_eos。在静态基准测试中,这些参数把输出固定为恰好 128 个 token,以保持基线干净;我们现在有意放开这一约束,让输出分布可以变化。

--random-seed 42 让泊松时序和合成长度的抽样可以复现。重新运行这条命令会产生相同的请求序列。

--streaming 是必需的。没有流式输出,服务器会先把完整响应攒好再发送,也就没有首 token 或解码 token 事件可供测量。

从这次运行的 LLM 指标来看,各项分布明显比静态基线更宽,这在意料之中:更多请求同时争抢 GPU,而且每个请求的预填充长度各不相同。

对图 2 中摘要表的放大截图。它显示了首 token 时间、请求延迟、token 间延迟等汇总指标。每项指标都分解为平均值、最小值、最大值、p99、p90、p50 和标准差等独立的列。
图 3. 泊松到达模式运行的摘要统计截图示例。由于采用了新的流量模式,统计分布与 512/128 静态场景相比差异显著

从下方图 4 的图表可以看到,泊松命令行产生的请求速率以每秒 10 个为中心,但并不完全吻合。与保证固定每秒 10 个请求的恒定模式相比,这种到达模式模拟了请求到达时间上的抖动。

一幅折线图,将一条虚线形式的屋顶线与一条蓝线作对比,横轴是自发送第一个请求以来的时间(秒),纵轴是已派发请求的累计数量。如果请求的是恒定速率(没有任何抖动),虚线的斜率就是我们要求的每秒 10 个请求;与之对应的蓝线斜率相近,但由于泊松模式引入了抖动,显得更加参差不齐。
图 4. 自第一个请求派发起的报告延迟,与恒定的每秒 10 个请求模式作对比,显示出派发时间围绕指定请求速率的波动

从下方图 5 可以看到,请求长度围绕 512 个 token 的均值产生变化,输入序列长度范围为 154 到 818 个 token。

一幅直方图,显示在要求平均输入长度为 512 个 token、标准差为 128 个 token 时输入序列长度的分布。可以看到,直方图以 514 为中心,呈钟形曲线,两侧大致对称,最小值为 154 个 token,最大值为 818 个 token。
图 5. 直方图显示输入(请求)长度的分布,以要求的平均 512 个 token 为中心

对比两次运行的 TTFT,可以看到泊松运行的离散程度要大得多。更多请求同时争抢 GPU,预填充长度各不相同,预填充和解码操作也相互重叠。单并发的情形是一种理想化场景:每次只运行一个请求,能得到尽可能低的 TTFT,但代价是吞吐量。

一幅直方图,显示两种首 token 时间分布:蓝色的是作为参照的单用户(并发数为 1)直方图,绿色的是请求速率为每秒 10 个的直方图。横轴是首 token 时间,纵轴是出现特定首 token 时间的请求所占百分比。可以看到,单用户场景的首 token 延迟低得多,中心峰值很高,分布也紧凑得多(标准差更小)。相比之下,绿色直方图平坦得多,首 token 延迟分布也更分散,体现了服务器竞争更激烈时对用户初始响应的影响。
图 6. 直方图对比了单个活跃用户与泊松到达模式的 AIPerf 运行在首 token 时间分布上的差异

从上方图 6 可以看到,单用户运行的 TTFT 波动小于泊松实验中变化大得多的工作负载。

还有更多可以探索

本文的演示涵盖了基础内容,但 AIPerf 也是为更复杂的场景而构建的。

同一个工具可以处理多节点 Kubernetes 部署、KV 缓存复用的预热机制、生产流量的追踪回放、前缀合成、自定义数据集,以及跨并发级别的扫描配置。

如果你在大规模运行分布式推理,请参阅 NVIDIA Dynamo 1.0 如何支撑生产规模的多节点推理。

AIPerf 仓库中的教程是最快的入门途径。AIPerf 仓库和文档是了解新功能和参与贡献的权威参考。

致谢

AIPerf 是 NVIDIA 与外部贡献者共同努力的成果。感谢以下各位:AWS 的 Loki Ravi、Dan Ferguson 和 Sheng Moua,感谢他们持续的合作、跨公司验证,以及推动以 AIPerf 作为标准的努力;Coreweave 的 Aaron Batilo,感谢他贡献了 Weights & Biases 导出器、接受长度(acceptance-length)投机解码数据集,并加固了并发下扫描与额度派发(credit-dispatch)的可靠性;Baseten 的 Shounak Ray,感谢他提供对 Baseten 追踪回放的忠实支持;Baseten 的 Michael Feil,感谢他实现了更快的追踪加载和会话亲和性(session affinity)请求头。Pinterest 的 Cristian Lopez,感谢他在 DAG 基准测试方法上的紧密合作。我们还要感谢 Ben Hamm 在 AIPerf 的设计、规划和实现过程中给予的产品指导。