参数解释
--onnx # 指定ONNX model
# build option
# eg: input0:1x3x256x256,input1:1x3x128x128
--minShapes # 模型输入的最小shape, 可动态
--optShapes # 模型输入的推荐hape, 可动态
--maxShapes # 模型输入的最大shape, 可动态
--inputIOFormats=spec # 以什么样的格式获取值, 默认fp32
--outputIOFormats=spec # 以什么样的格式输出值, 默认fp32
# build options
--memPoolSize=poolspec # 分配的最大的内存容量
# eg: --memPoolSize=workspace:1024.5,dlaSRAM:256 单位M
--profillingVerbosity=mode # 打印消息的详细程度
# eg: --mode ::=layer_names_only|detailed|none(default=layer_names_only)
# 只打印ops name, 详细(会打印ops参数), none(不打印)
--fp16 # 默认default 是否对模型执行fp16加速
--int8 # 默认default 是否对模型执行int8量化
--calib=<file> # 当执行int8量化时用来标定参数的文件, 如果给的是带QDQ节点的model, 则不用给。如果给的不是QDQ model且没给定calib文件,默认会把dynamic range设置为4, 这时model量化会产生很大误差
--best # 默认disabled, 是否开启全精度方案来达到最优性能FP32+FP16+INT8 使用三种方案同时运行, 然后选最快的
--saveEngine=<file> # 保存序列化的engine
--loadEngine=<file> # 加载engine进行反序列化, infer时用到
# === Build Options ===
--tacticSources=tactics # 默认所有库都允许使用
# 某些平台使用某些库可能会报错, 且各种lib有各自缺点
# 通过 加上(+), 去掉(-) 指定什么包能用, 什么包不能用: +lib -lib
# eg: --taticSources=-CUDNN,+CUBLAS
# ==== inference Options ==== 推理的时候指定
--shapes=spec # 给推理设置输入tenosr形状(支持动态)
# eg: --shapes=input0:1x3x256x256,input1:1x3x128x128
--loadInputs=spec # 从文件中加载输入, tensor文件
# eg: --loadInputs=input0:input0.binary,input1:input1.binary
--iterations=N # 推理至少 运行几次 (默认10次)
--warmUp=N # 默认200ms, 设置多少毫秒用来热启动, 可以缩减误差
--duration=N # 默认3s, 运行inference所消耗的最少时间
--sleepTime=N # 默认0s, inference从开始到计算延迟多少s
--idleTime=N # 默认0s, 两次infer间隔多少s
--streams=N # 默认1, 使用多个流来运行推理, 多线程下可能会得到加速
--separateProfileRun # 默认False, 是否在infer时将profiler和benchmark分开, 做benchmark时设置为True
--buildOnly # 默认False, 是否只做编译不做执行
# =====Reporting Options=======
--verbose # 默认false, 将日志级别设置为详细
--dumpOutput # 默认false, 打印最后一次推理的输出
--dumpProfile # 默认false, 打印 每一层的配置信息
--dumpLayerInfo # 默认false, 打印每一层的层信息
--exportOutput=<file> # 默认false, 导出最后一层的输出到json文件中
--exportProfile=<file> # 默认false, 导出每一层的配置到json文件中
--exportLayerInfo=<file> # 默认false, 导出每一层的信息到json文件中
# eg: --exportLayerInfo=layer.json --profilingVerbosity=detailed
# ========System Options==========
--device=N # 默认0, 指定cuda device
--useDLACore=N # 默认None, 指定DLA core, 可以在Jetson设备上指定
--allowGPUFallback # 默认disabled, 当DLA被指定时, 允许GPU返回不受支持的层
--plugins # 加载插件库(.so)
# eg: --plugins=xxx.so --plugins=aaa.so --plugins=www.so
模型的编译和运行压测
1.写一个静态的onnx
1.基本的模型导出和编译
import torch
import torch.nn as nn
import torch.onnx as onnx
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super().__init__()
# x -> 1x1x3x3 conv(x) -> 1x3x3x3
self.conv = nn.Conv2d(1, 3, kernel_size=3, padding=1, stride=1)
self.fc = nn.Linear(in_features=27, out_features=2)
def forward(self, x):
x = self.conv(x)
x = F.relu(x)
x = x.view(-1, 27)
x = self.fc(x)
return x
if __name__ == "__main__":
torch.manual_seed(7)
dummy = torch.randn(1, 1, 3, 3)
model = Model().eval()
with torch.no_grad():
y = model(dummy)
print(f"y = {y}")
onnx.export(
model, dummy, "static.onnx",
opset_version=14,
input_names=['x'],
output_names=['y'],
verbose=True
)
2.让模型持续运行,并进行压测
模型的导出和加载
# 模型的转换和优化阶段,目的是将模型转换为TensorRT可以高效执行的格式
# 包含模型的优化、编译、推理、保存,并将模型转换为TensorRT可以高效执行的格式保存
trtexec --onnx=static.onnx --saveEngine=static.engine
# trtexec --onnx=static.onnx --saveEngine=static.engine --allowGPUFallback --useCudaGraph --useSpinWait
# 模型的加载和推理阶段,通过加载优化好的引擎文件来实现快速的模型推理
# 加载已经转换和优化好的TensorRT引擎文件,直接进行推理计算,无需再次进行模型转换和优化。
trtexec --loadEngine=static.engine
吞吐量和平均延迟是大多数应用场景下最重要的性能指标,它们直接反映了模型处理能力和响应速度。GPU计算时间、排队时间和设备到主机延迟也是在特定场景下需要重点关注的指标,尤其是在计算密集和数据密集型的应用中。
trtexec的输出结果提供了模型性能的综合概述。下面是一些关键指标的分析:
- Throughput: 模型的吞吐量为35188.9查询每秒(qps),这表示模型每秒能够处理的查询数。高吞吐量意味着模型能够快速处理大量数据。
- Latency: 延迟指标显示了处理单个查询所需的时间。最小延迟是0.0144043毫秒,最大延迟是0.0686035毫秒,平均延迟是0.0180023毫秒。中位数延迟是0.0170898毫秒,而90%、95%和99%的百分位数延迟分别是0.0213318毫秒、0.0220947毫秒和0.0266113毫秒。这些低延迟值表明模型响应非常迅速。
- Enqueue Time: 排队时间指的是将任务提交到GPU执行的时间。最小值是0.0065918毫秒,最大值是0.0490723毫秒。平均值是0.0111992毫秒,这意味着任务进入GPU执行队列的速度非常快。
- H2D Latency (Host to Device): 从主机(CPU)传输数据到设备(GPU)的延迟。这个延迟很低,平均值仅为0.00419833毫秒,表明数据从CPU到GPU的传输非常高效。
- GPU Compute Time: GPU计算时间是执行任务实际花费在GPU上的时间。平均计算时间为0.00979553毫秒,这表明GPU能够快速完成计算任务。
- D2H Latency (Device to Host): 从设备(GPU)传输数据回主机(CPU)的延迟。平均值是0.0040085毫秒,再次证明了数据传输的高效性。
- Total Host Walltime: 总主机时间是3.00006秒,这是执行测试所需的总时间。
- Total GPU Compute Time: 总GPU计算时间是1.0341秒,表示所有任务在GPU上的累积计算时间。
警告分析:
- 第一个警告指出吞吐量可能受到排队时间的限制,建议使用–useCudaGraph选项来提高吞吐量。
- 第二个警告指出GPU计算时间不稳定,可能需要锁定GPU的时钟频率或使用–useSpinWait来改善性能稳定性。
模型的压力测试
trtexec --loadEngine=static.engine --duration=1000
# 可以使用下面两个命令之一查看显卡内存占用率
watch -n 0.1 nvidia-smi
nvitop
2.写一个动态的onnx
1.基本的模型导出
batch_size 在 ONNX 中会经常设置为动态的, 然后在使用 tensorRT 推理时可以动态指定
import torch
import torch.nn as nn
import torch.onnx as onnx
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super().__init__()
# x -> 1x1x3x3 conv(x) -> 1x3x3x3
self.conv = nn.Conv2d(1, 3, kernel_size=3, padding=1, stride=1)
self.fc = nn.Linear(in_features=27, out_features=2)
def forward(self, x):
x = self.conv(x)
x = F.relu(x)
x = x.view(-1, 27)
x = self.fc(x)
return x
if __name__ == "__main__":
torch.manual_seed(7)
dummy = torch.randn(1, 1, 3, 3)
model = Model().eval()
with torch.no_grad():
y = model(dummy)
print(f"y = {y}")
onnx.export(
model, dummy, "dynamic.onnx",
opset_version=14,
input_names=['x'],
output_names=['y'],
verbose=True,
dynamic_axes={'x': {0: 'batch_size'}, 'y': {0: 'batch_size'}},
)
2.编译模型,设置动态shape参数
trtexec --onnx=dynamic.onnx --minShapes=x:1x1x3x3 --optShapes=x:50x1x3x3 --maxShapes=x:100x1x3x3 --saveEngine=dynamic.engine
trtexec --loadEngine=dynamic.engine --shapes=x:50x1x3x3
下面看不同batch_size, trt engine的推理时间
batch_size = 16 时, throughout = 35247 qps, meida latency = 0.0158691 ms
batch_size = 64时, througphout = 32613.9 qps,media latency = 0.017334 ms
随着batch_size的增大,系统吞吐量会下降,平均延迟有所增大