04-TensorRT 的 trtexec 工具使用
什么是 trtexec?
- 一种无需开发自己的应用程序即可快速使用 TensorRT 的工具
trtexec 如何从 onnx 生成引擎?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#生成静态batchsize的engine
./trtexec \
--onnx= \ # 指定onnx模型文件
--explicitBatch \ # 在构建引擎时使用显式批大小(默认=隐式)显示批处理
--saveEngine= \ # 输出engine
--workspace= \ # 设置工作空间大小单位是MB(默认为16MB)
--fp16 #除了fp32之外,还启用fp16精度(默认=禁用)
#生成动态batchsize的engine
./trtexec \
--onnx= \ #指定onnx模型文件
--minShapes=input: \ #最小的batchsize x 通道数 x 输入尺寸x x 输入尺寸y
--optShapes=input: \ #最佳输入维度,跟maxShapes一样就好
--maxShapes=input: \ #最大输入维度
--workspace= \ #设置工作空间大小单位是MB(默认为16MB)
--saveEngine= \ #输出engine
--fp16 #除了fp32之外,还启用fp16精度(默认=禁用)
trtexec 如何从 uff 生成引擎?
1
2
3
4
5
6./trtexec \
--uff=squeezenet.uff \ #指定onnx模型文件
--uffInput=input,3,300,200 \ #指定uff输入
--output=probs/BiasAdd \ #指定uff输出
--batch=1 \ #设置批处理大小
--saveEngine=squeezenet.trt #输出engine
trtexec 如何从 Caffe 生成引擎?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#生成engine
./trtexec \
--deploy=/path/to/mnist.prototxt \ #指定网络模型文件,caffe独有的
--model=/path/to/mnist.caffemodel \ #指定权重文件
--output=prob \ #标记输出节点名称(可以多次指定)
--batch=16 \ #为隐式批处理引擎设置批处理大小
--saveEngine=mnist16.trt #输出engine
#生成engine启用INT8精度
./trtexec \
--deploy=GoogleNet_N2.prototxt \ #指定网络模型文件,caffe独有的
--output=prob \ #标记输出节点名称(可以多次指定)
--batch=1 \ #为隐式批处理引擎设置批处理大小,默认=1
--saveEngine=g1.trt \ #输出engine
--int8 \ #除了fp32之外,还启用int8精度(默认=禁用)
--buildOnly #跳过性能测量
trtexec 如何加速引擎生成过程?
- 可以通过设置 tacticSources 减少搜索空间达到,坏处就是模型的推理时间不一定是最少的
- TensorRT 的依赖项(cuDNN 和 CUBLAS)会占用大量设备内存,TensorRT 允许使用构建器配置控制这些库是否用于推理
- 请注意,某些层实现需要这些库,因此当它们被排除时,网络可能无法编译
1
trtexec --onnx=model.onnx --explicitBatch --tacticSources=-cublasLt,+cublas --workspace=2048 --fp16 --saveEngine=model1.trt
trtexec 测试网络的关键指标介绍?
- Throughput (吞吐量)
- 给定时期内的产出量。通常以推理 / 秒或样本 / 秒来衡量,每台服务器的吞吐量 对于数据中心的经济高效扩展至关重要
- 观察到的吞吐量是通过将查询数除以 Total Host Walltime 来计算的
- 如果这明显低于 GPU Compute Time 的倒数,则 GPU 可能由于主机端开销或数据传输而未得到充分利用
- Host Latency (本机推断耗时)
- H2D Latency、GPU Compute Time、D2H Latency 这 3 个时间的总和
- 这是单个推断请求的耗时
- End-to-End Host Latency (端到端的本机推断耗时)
- 从 H2D 被调用→同一次查询的 D2H 完成的持续时间,包括等待前一查询完成的等待时间
- 如果连续有多个请求排队,就会有请求延迟
- Enqueue Time (排队时间)
- 请求排入队列的本机耗时,包括调用 H2D/D2H CUDA APIs,运行主机端,启动 CUDA 内核
- 如果这比 GPU 计算时间长,则 GPU 可能未得到充分利用,并且吞吐量可能由主机端开销主导。使用 CUDA 图(与–useCudaGraph) 可能会减少排队时间
- H2D Latency (主机内存至设备 GPU device 的耗时)
- 单个请求的输入张量的主机到设备数据传输的延迟。添加–noDataTransfer 禁用 H2D/D2H 数据传输
- D2H Latency (设备 GPU device 至主机内存的耗时)
- 单个请求的输出张量的设备到主机数据传输的延迟。添加–noDataTransfer 禁用 H2D/D2H 数据传输
- GPU Compute Time (GPU 的计算时间)
- 请求时,执行 CUDA 内核的 GPU 延迟
- Total Host Walltime (本机总挂起时间)
- 从第一次查询(预热后)排队到最后一次查询完成时的 Host Walltime
- Total GPU Compute Time (GPU 计算总时间)
- 所有请求的 GPU 计算时间的总和。如果这比 Total Host Walltime 短得多,则 GPU 可能由于主机端开销或数据传输而未得到充分利用
- Efficiency
- 每单位功率提供的吞吐量 ,通常表示为性能 / 瓦特。效率是经济高效的数据中心扩展的另一个关键因素,因为服务器、服务器机架和整个数据中心必须在固定的功率预算内运行
- Memory usage
- 需要保留以在网络上进行推理的主机和设备内存取决于所使用的算法。这限制了可以在给定推理平台上运行的网络和网络组合。这对于需要多个网络且内存资源有限的系统尤其重要 —— 例如用于智能视频分析和多摄像头、多网络自动驾驶系统的级联多类检测网络
trtexec 如何测试网络性能
- 使用随机输入测试网络
1
./trtexec --loadEngine=mnist16.trt --batch=16
- 在具有静态输入形状的全维模式下运行 ONNX 模型
1
./trtexec --onnx=model.onnx
- 在给定的输入形状在全维模式下运行 ONNX 模型
1
2# 假设 ONNX 模型具有一个带有名称input和维度的动态输入[-1, 3, 244, 244]
./trtexec --onnx=model.onnx --shapes=input:32x3x244x244 - 使用一系列可能的输入形状对 ONNX 模型进行基准测试
1
2
3
4
5
6./trtexec \
--onnx=model.onnx \
--minShapes=input:1x3x244x244 \
--optShapes=input:16x3x244x244 \
--maxShapes=input:32x3x244x244 \
--shapes=input:5x3x244x244 - 在 DLA 上运行网络
1
2
3
4
5
6
7# 使用FP16 模式在 NVIDIA DLA(深度学习加速器)上运行 AlexNet 网络
./trtexec \
--deploy=data/AlexNet/AlexNet_N2.prototxt \ #指定网络模型文件,caffe独有的
--output=prob \ #标记输出节点名称(可以多次指定)
--useDLACore=1 \ #使用NVIDIA DLA(深度学习加速器)
--fp16 \ #除了fp32之外,还启用fp16精度(默认=禁用)
--allowGPUFallback #启用DLA时,允许GPU回退不支持的层(默认值=禁用)
trtexec 如何生成模型构建时的序列化缓存?
- 测量模型性能时,将测量顺序导出到 json 中
1
2
3
4
5
6./trtexec \
--deploy=data/AlexNet/AlexNet_N2.prototxt \
--output=prob \
--exportTimes=trace.json
# 使用命令python tracer.py trace.json以不同的形式打印输入、计算和输出的时间戳和持续时间
# 同理,配置文件也可打印并存储在json文件中,并使用profiler.py查看该文件
trtexec 使用例子
- 使用多流调整吞吐量
- 当实现的延迟完全在所需的阈值内时,我们可以增加吞吐量,即使以一些延迟为代价
- 保存的引擎在 batch 为 1,2 时,延迟阈值都在 2ms 内
1
2trtexec --deploy=GoogleNet_N2.prototxt --output=prob --batch=1 --saveEngine=g1.trt --int8 --buildOnly
trtexec --deploy=GoogleNet_N2.prototxt --output=prob --batch=2 --saveEngine=g2.trt --int8 --buildOnly - 尝试不同的 batch 与 stream 的组合,在延迟低于 2ms 的前提下,选择最大吞吐量组合
1
2
3
4
5
6
7
8
9trtexec --loadEngine=g1.trt --batch=1 --streams=2
trtexec --loadEngine=g1.trt --batch=1 --streams=3
trtexec --loadEngine=g1.trt --batch=1 --streams=4
trtexec --loadEngine=g2.trt --batch=2 --streams=2
```
- TensorRT为了最大化GPU利用率,将提前将一个batch入队,即
```bash
# 多流情况下,每个流遵循该模式
enqueue batch 0 -> enqueue batch 1 -> wait until batch 0 is done -> enqueue batch 2 -> wait until batch 1 is done -> enqueue batch 3 -> wait until batch 2 is done -> enqueue batch 4 -> ...