3、trtexec基础用法:命令行基本结构、常用参数概览、如何运行一个简单的benchmark测试

trtexec是TensorRT官方提供的命令行性能测试工具,它封装了引擎构建、序列化、反序列化、推理执行和性能统计的全流程。对于工程师而言,trtexec的价值在于它提供了一个标准化、可复现的基准测试环境——你不需要编写任何C++或Python代码,仅通过命令行参数即可完成从ONNX模型到TensorRT引擎、再到性能指标采集的完整链路。本章将围绕trtexec的命令行结构、核心参数和典型benchmark执行流程展开,帮助你快速建立对TensorRT性能评估的基本操作框架。

trtexec 基础用法链路图 输入模型 ONNX / UFF / Caffe --onnx=model.onnx 构建参数 --fp16 / --int8 --minShapes / --optShapes TensorRT引擎 .engine / .plan --saveEngine=model.engine 推理参数 --loadEngine --shapes=input:1x3x224x224 性能测试执行 --warmup=500 --duration=10 --iterations=100 --avgRuns=10 --streams=2 性能指标输出 Latency: min / max / mean / p50 / p90 / p95 / p99 Throughput: fps / QPS GPU利用率 / 显存占用 / 功耗 迭代调优

上图展示了trtexec从输入模型到性能指标输出的完整链路。整个流程可以概括为四个阶段:输入解析(指定模型文件)、引擎构建(配置精度和动态shape)、推理执行(设置warmup和测试时长)、指标采集(延迟和吞吐量统计)。理解这条链路是掌握trtexec所有高级用法的前提。

3.1 命令行基本结构

trtexec的命令行结构遵循"工具名 + 参数 + 参数值"的通用模式。其基本语法为:

trtexec [参数1] [参数2] ... [参数N]

参数之间使用空格分隔,每个参数以--开头,后跟参数名和可选的参数值。参数值可以是字符串、整数、浮点数或布尔值。对于布尔参数,直接写参数名即表示启用该功能,例如--fp16表示启用FP16精度。

从功能维度划分,trtexec的参数可以分为以下五大类:

参数类别 典型参数 功能说明
模型输入 --onnx, --deploy, --uff 指定输入模型文件路径和格式
引擎构建 --fp16, --int8, --minShapes, --optShapes, --maxShapes 控制引擎的精度、动态shape范围和优化策略
推理执行 --loadEngine, --shapes, --warmup, --duration, --iterations 配置推理时的输入shape、预热时间和测试时长
性能统计 --avgRuns, --percentile, --streams 设置统计窗口、百分位和并发流数量
输出控制 --saveEngine, --verbose, --dumpProfile 控制引擎保存、日志详细程度和性能分析输出
经验提醒:trtexec的参数数量超过100个,但日常benchmark测试中常用的核心参数不超过20个。建议先掌握本章列出的基础参数,再根据实际需求查阅官方文档扩展。

3.2 常用参数详解

下面按照使用频率和重要性,对trtexec的核心参数进行逐一说明。

3.2.1 模型输入参数

--onnx是最常用的模型输入参数,用于指定ONNX格式的模型文件。例如:

trtexec --onnx=resnet50.onnx

对于TensorRT 8.x及更早版本,还支持--deploy(Caffe prototxt)和--uff(UFF格式)参数。但在TensorRT 9.x和10.x中,ONNX已成为主流输入格式,Caffe和UFF支持已被移除或弱化。

3.2.2 引擎构建参数

引擎构建参数决定了TensorRT如何优化模型。最核心的是精度控制参数:

  • --fp16:启用FP16精度推理,通常可带来1.5~3倍的加速,但精度可能略有下降。
  • --int8:启用INT8量化推理,需要提供校准数据(配合--calib参数),加速比可达3~5倍。
  • --best:自动选择最优精度组合(等价于同时启用FP16和INT8)。

对于动态shape模型,需要指定shape范围:

trtexec --onnx=model.onnx --minShapes=input:1x3x224x224 --optShapes=input:8x3x224x224 --maxShapes=input:16x3x224x224

其中--minShapes定义最小输入维度,--optShapes定义最优输入维度(引擎优化目标),--maxShapes定义最大输入维度。这三个参数必须同时指定,且格式为输入名:维度,多个输入用逗号分隔。

3.2.3 推理执行参数

当引擎构建完成后,trtexec会立即执行推理测试。以下参数控制测试过程:

  • --loadEngine:加载已保存的引擎文件,跳过构建阶段。
  • --shapes:指定实际推理时的输入shape,必须落在min和max范围内。
  • --warmup:预热时间(毫秒),默认500ms。预热让GPU达到稳定工作状态,避免冷启动影响指标。
  • --duration:测试持续时间(秒),默认3秒。建议至少10秒以获得稳定统计。
  • --iterations:测试迭代次数,与--duration二选一。指定后trtexec会运行固定次数后停止。

3.2.4 性能统计参数

这些参数影响性能指标的采集和输出方式:

  • --avgRuns:计算平均延迟时使用的迭代次数,默认10次。
  • --percentile:输出指定百分位的延迟,可多次指定,如--percentile=90 --percentile=95 --percentile=99。
  • --streams:并发CUDA流数量,模拟多路并发推理场景,默认1。

3.3 运行一个简单的Benchmark测试

下面通过一个完整的案例,演示如何使用trtexec对ResNet-50模型进行基准测试。

3.3.1 案例背景与目标

假设我们有一个resnet50.onnx模型,需要在NVIDIA A10 GPU上评估其FP16推理性能。目标包括:获取端到端延迟(p50/p95/p99)、吞吐量(FPS),并保存优化后的引擎文件供后续部署使用。

3.3.2 初始命令与现象

首先运行最简单的命令,观察默认行为:

trtexec --onnx=resnet50.onnx --fp16

输出中会显示引擎构建日志、推理配置和性能统计。关键输出片段如下:

[06/15/2024-10:23:45] [I] === Performance summary ===
[06/15/2024-10:23:45] [I] Throughput: 1254.63 qps
[06/15/2024-10:23:45] [I] Latency: min = 0.782 ms, max = 1.245 ms, mean = 0.796 ms
[06/15/2024-10:23:45] [I] Latency: p50 = 0.793 ms, p90 = 0.812 ms, p95 = 0.825 ms, p99 = 0.891 ms

默认测试时长仅3秒,且未保存引擎文件。对于正式benchmark,我们需要更长的测试时间和更完整的指标。

3.3.3 优化后的Benchmark命令

根据上述需求,我们构造如下完整命令:

trtexec --onnx=resnet50.onnx \
        --fp16 \
        --saveEngine=resnet50_fp16.engine \
        --warmup=1000 \
        --duration=10 \
        --avgRuns=50 \
        --percentile=90 --percentile=95 --percentile=99 \
        --streams=1

参数说明:

  • --saveEngine:将构建的引擎保存为resnet50_fp16.engine,后续可直接加载。
  • --warmup=1000:预热1秒,确保GPU达到稳定状态。
  • --duration=10:测试持续10秒,获得更稳定的统计结果。
  • --avgRuns=50:每次统计使用50次迭代,减少随机波动。
  • --percentile:额外输出p90、p95、p99延迟。

3.3.4 结果分析与复盘

运行后,我们获得了更详细的性能报告:

指标 默认测试(3秒) 优化测试(10秒) 差异分析
Throughput (qps) 1254.63 1248.21 基本一致,说明GPU已稳定
p50 Latency (ms) 0.793 0.789 略有改善,统计更精确
p99 Latency (ms) 0.891 0.934 长尾延迟更明显,10秒测试暴露了极端情况
GPU显存占用 未显示 ~1.2 GB 可通过--verbose查看详细内存信息

从结果可以看出,延长测试时间后p99延迟从0.891ms上升到0.934ms,这说明短时测试可能低估了长尾延迟。对于实时性要求高的场景,建议使用至少10秒的测试时长,并重点关注p99甚至p99.9指标。

风险提示:在benchmark过程中,GPU会处于高负载状态。如果GPU同时被其他任务占用,测试结果会失真。建议在测试前使用nvidia-smi确认GPU空闲,并在测试期间避免运行其他GPU任务。

3.4 常见误区与最佳实践

在使用trtexec进行benchmark时,工程师常犯以下错误:

3.4.1 误区一:忽略预热时间

GPU在冷启动时频率较低,直接测试会导致延迟偏高。默认的500ms预热可能不够,特别是对于大型模型。建议设置--warmup=1000或更长。

3.4.2 误区二:测试时长过短

3秒的默认测试时长只能覆盖约3000~4000次迭代,对于延迟分布较宽的模型,统计结果不够稳定。建议至少10秒,对于需要精确评估长尾延迟的场景,可延长至30秒。

3.4.3 误区三:忽略动态shape配置

对于动态shape模型,如果未正确设置--minShapes、--optShapes和--maxShapes,trtexec会使用默认值(通常是1x3x224x224),导致实际推理时shape不匹配或性能非最优。

3.4.4 误区四:混淆"构建时间"和"推理时间"

trtexec输出的时间包含引擎构建时间和推理时间。如果模型较大,构建可能耗时数分钟。要单独测量推理性能,应使用--loadEngine加载已构建的引擎。

最佳实践清单:
  1. 先使用--saveEngine保存引擎,后续测试用--loadEngine加载,避免重复构建。
  2. 设置--warmup=1000和--duration=10作为基准配置。
  3. 同时输出--percentile=90 --percentile=95 --percentile=99,全面评估延迟分布。
  4. 使用--streams=2或--streams=4模拟并发推理场景,评估服务端吞吐能力。
  5. 记录GPU型号、驱动版本、TensorRT版本和CUDA版本,确保结果可复现。

通过本章的学习,你已经掌握了trtexec的基本用法。下一阶段,我们将深入探讨如何解读trtexec输出的详细性能指标,包括GPU利用率、显存带宽、功耗等硬件层面的数据,这些信息对于定位性能瓶颈至关重要。