关键词:
前言
今天是程序员节,当然是以程序员的方式来度过节日。
很早就听说TensorRT可以加速模型推理,但一直没时间去进行实践,今天就来把这个陈年旧坑填补一下。
背景知识
在实践之前有必要了解一下相关知识。
TensorRT简介
TensorRT是可以在NVIDIA各种GPU硬件平台下运行的一个C++推理框架。我们利用Pytorch、TF或者其他框架训练好的模型,可以转化为TensorRT的格式,然后利用TensorRT推理引擎去运行我们这个模型,从而提升这个模型在英伟达GPU上运行的速度[1]。
TensorRT支持几乎所有主流深度学习框架,将python框架转换成C++的TensorRT,从而可以加速推理。
具体而言,TensorRT主要做了以下几点来加快推理速度[1]:
- 算子融合(层与张量融合):简单来说就是通过融合一些计算op或者去掉一些多余op来减少数据流通次数以及显存的频繁使用来提速
- 量化:量化即IN8量化或者FP16以及TF32等不同于常规FP32精度的使用,这些精度可以显著提升模型执行速度并且不会保持原先模型的精度
- 内核自动调整:根据不同的显卡构架、SM数量、内核频率等(例如1080TI和2080TI),选择不同的优化策略以及计算方式,寻找最合适当前构架的计算方式
- 动态张量显存:我们都知道,显存的开辟和释放是比较耗时的,通过调整一些策略可以减少模型中这些操作的次数,从而可以减少模型运行的时间
- 多流执行:使用CUDA中的stream技术,最大化实现并行操作
当然,TensorRT主要缺点是与特定GPU绑定[1],在不同型号上转换出来的模型不能通用(这一点笔者暂未去从实践证实)
TensorRT官方在其仓库提供了三个开源工具,之后有需要可以使用。
三个工具大致用途[1]:
- ONNX GraphSurgeon
可以修改我们导出的ONNX模型,增加或者剪掉某些节点,修改名字或者维度等等 - Polygraphy
各种小工具的集合,例如比较ONNX和trt模型的精度,观察trt模型每层的输出等等,主要用-来debug一些模型的信息 - PyTorch-Quantization
可以在Pytorch训练或者推理的时候加入模拟量化操作,从而提升量化模型的精度和速度,并且支持量化训练后的模型导出ONNX和TensorRT
ONNX简介
Open Neural Network Exchange(ONNX,开放神经网络交换)格式,是微软和Facebook提出用来表示深度学习模型的开放格式,定义了一组和环境,平台均无关的标准格式,可使模型在不同框架之间进行转移[2]。
假设模型在 TensorFlow 中,但想要在TensorRT中使用,或者模型在PyTorch中,想要在TFLite中使用,就可以利用 ONNX 作为中介,进行模型转换。
典型的几个线路[3]:
- Pytorch -> ONNX -> TensorRT
- Pytorch -> ONNX -> TVM
- TF -> onnx -> ncnn
- Pytorch -> ONNX -> tensorflow
ONNX结构是将每一个网络的每一层或者每一个算子当作节点Node,再由这些Node去构建一个Graph,最后将Graph和这个onnx模型的其他信息结合在一起,生成一个model。
可以通过在线网站https://netron.app/来查看ONNX模型结构。
实践上手
下面来进行实践上手。
实验环境
这是我的电脑环境:
- 操作系统:Windows10
- 显卡:RTX2060
- CUDA版本:11.6
- Pytorch版本:1.7.1
- Python版本:3.8
查看CUDA版本
TensortRT非常依赖CUDA版本,在安装之前,需要先查看本机安装好的CUDA版本,查看方式有多种,第一种方式可以通过NVIDIA 控制面板查看;第二种方式可以通过在控制台输入nvcc -V
进行查看。
安装TensorRT
首先需要到Nvidia官网去下载对应Cuda版本的TensorRT安装包。
我这里下载的是红框选中的这一个,这个版本支持CUDA11.0-11.7
下载好后,将压缩包进行解压缩,然后到Anaconda环境中,以此进入到以下几个文件夹,安装这几个whl文件
cd TensorRT-8.4.3.1\\python
pip install tensorrt-8.4.3.1-cp38-none-win_amd64.whl
cd TensorRT-8.4.3.1\\graphsurgeon
pip install graphsurgeon-0.4.6-py2.py3-none-any.whl
cd TensorRT-8.4.3.1\\onnx_graphsurgeon
pip install onnx_graphsurgeon-0.3.12-py2.py3-none-any.whl
cd TensorRT-8.4.3.1\\uff
pip install uff-0.6.9-py2.py3-none-any.whl
然后需要移动安装包里的一些文件:
- 将
TensorRT-8.4.3.1\\include
中头文件拷贝到C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.6\\include
- 将
TensorRT-8.4.3.1\\lib
中所有lib文件拷贝到C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.6\\lib\\x64
- 将
TensorRT-8.4.3.1\\lib
中所有dll文件拷贝到C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.6\\bin
注:这里的v11.6根据自己的Cuda版本号即可
之后,需要手动将C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.6\\bin
路径添加到用户Path环境变量中
添加完之后,重启电脑,让环境变量生效。
之后进行验证:
python
import tensorrt
print(tensorrt.__version__)
在import
时发生报错,
FileNotFoundError: Could not find: nvinfer.dll. Is it on your PATH?
此时只需要将缺少的文件找到,然后添加到上面的bin
目录下即可,我这里是在安装的torch中lib文件下找到的部分文件,缺什么移什么即可。
如无报错,再次验证,可以输出tensorrt版本:
下面运行安装包里面的一个sample.py文件,以确保tensorrt能够正常工作。
进入到下图所示的路径,运行sample.py
,如果正常输出,则代表tensorrt安装成功。
如果提示没装pycuda,还需要再安装一下
pip install pycuda
YOLOv5使用TensorRT加速
这部分内容看到不少博客都是用Cmake编译生成yolov5的VS工程,非常繁琐麻烦,主要是这些博文写作时间较早。
而在YOLOv5 6.0版本更新后,官方新增了一个export.py
文件,支持大部分框架模型的导出,包括TensorRT。
下面我所使用的是YOLOv5官方最新的6.2版本。
下面直接导出官方提供的yolov5s模型试试,终端输入:
python export.py --weights yolov5s.pt --data data/coco128.yaml --include engine --device 0 --half
注:这里的--half
表示半精度模型,使用半精度可以加快推理速度,但会损失一定精度,直接导出可以不加
初次导出,遇到如下报错
ONNX: export failure 0.4s: Exporting the operator silu to ONNX opset version 12 is not supported.
这个报错需要修改pytorch的激活函数,找到该函数位置:D:\\anaconda\\envs\\pytorch\\Lib\\sitepackages\\torch\\nn\\modules\\activation.py
(此处结合自己的anaconda实际安装位置来更改)
修改代码如下:
class SiLU(Module):
__constants__ = ['inplace']
inplace: bool
def __init__(self, inplace: bool = False):
super(SiLU, self).__init__()
self.inplace = inplace
def forward(self, input: Tensor) -> Tensor:
# ------------------------------------- #
# 把F.silu替换掉,修改后如下
return input * torch.sigmoid(input)
#原来的代码
return F.silu(input, inplace=self.inplace)
再次导出,不再报错。
值得注意的是,YOLOv5并不会直接导出TensorRT模型,而是会先导出ONNX模型,然后将ONNX模型转换成TensorRT模型,因此导出完成后,会在模型位置处生成yolov5s.onnx
和yolov5s.engine
,yolov5s.engine
就是可以用来直接推理的TensorRT模型。
经过实测,不添加半精度导出yolov5s模型花费时间99.5s,添加半精度之后,导出yolov5s模型花费时间404.2s。
实验结果
图片检测
首先是来检测一下图片的推理速度,首先修改detect.py,统计程序花费时间。
if __name__ == "__main__":
begin_time = time.time()
opt = parse_opt()
main(opt)
end_time = time.time()
print("程序花费时间秒".format(end_time-begin_time))
然后依次使用不同模型进行推理
python detect.py --weights yolov5s.pt
python detect.py --weights yolov5s.engine
python val.py --weights yolov5s.pt
python val.py --weights yolov5s.engine
这里数据源选择的是coco128中128张图片,整体实验结果如下表所示:
模型 | 推理花费时间(s) | AP50 |
---|---|---|
原始模型 | 8.39 | 71.4% |
TensorRT(全精度) | 5.45 | 71.1% |
TensorRT(半精度) | 4.83 | 70.8% |
从数据可以发现,使用TensorRT加速之后,模型推理速度提升了约35%,但是模型精度并没有下降太多。coco数据集128张图片,模型训练和检测都是用同一份数据,这可能会对AP产生一定影响,于是再换用Visdrone数据集在进行实验。
下面对Visdrone数据集进行实验,使用yolov5m模型,训练100个epoch.
使用VisDrone2019-DET-test-dev
中的1610张图片进行验证和检测:
验证命令:
python val.py --data data/VisDrone.yaml --weights runs/train/exp3/weights/best.engine --batch-size 4 --task test
使用VisDrone2019-DET-test-dev
中的
检测命令:
python detect.py --weights runs/train/exp3/half/best.engine --source D:/Desktop/Work/Dataset/VisDrone/VisDrone2019-DET-test-dev/images --data data/VisDrone.yaml
实验结果如下表所示:
模型 | 验证花费时间(s) | P | R | AP50 | 推理花费时间(s) |
---|---|---|---|---|---|
yolov5m | 101.28 | 43.1% | 34.9% | 32.0% | 157.51 |
onnx | 156.16 | 42.8% | 34.9% | 32.0% | 158.97 |
TensorRT(全精度) | 124.37 | 42.8% | 34.9% | 32.0% | 144.93 |
TensorRT(半精度) | 127.85 | 42.8% | 34.8% | 31.9% | 139.97 |
由表可见,使用TensorRT加速之后,推理速度提升约了10%,同时精度只掉了0.3%,AP50基本上变化不大。
下面选一张图片来直观对比一下,左侧图为原始模型推理图,右侧图为TensorRT(半精度) 推理图,两者大致上差异不大,各有各的漏检对象。
视频检测
视频检测用了王者荣耀数据集做一个实验,比较了常规检测,tensorrt和onnx推理速度和帧率。推理所花费的时间分别为:
- 常规推理 程序花费时间20.88s
- onnx推理 程序花费时间25.68s
- tensorrt推理 程序花费时间16.03s
视频帧率如下视频所示:
YOLOv5:使用TensorRT加速效果对比
综合比较来看,tensorrt的推理速度最快,并且帧率会比原本检测帧率提升约20%左右,而用onnx模型推理,速度和帧率反而会变慢,这一点我是存在一些疑问的,看到一些博客说onnx模型对比pytorch模型速度更快,但我的实验结果并非如此,个人猜测是pytorch对模型优化已经做得比较出色,onnx模型作为一个通用标准模型,为了翻译功能,损失了部分性能。
参考
[1]TensorRT详细入门指北:https://blog.csdn.net/IAMoldpan/article/details/117908232
[2]ONNX简介:https://blog.csdn.net/qq_29258377/article/details/122907981
[3]ONNX简明教程:https://blog.csdn.net/xjm850552586/article/details/114898679
用c++部署yolov5+deepsort+tensorrt实现目标跟踪(代码片段)
...列——基于yolov5和deepsort的多目标头部识别,跟踪,使用tensorrt和c++加速二、相关介绍2.1重要说明==该项目能部署在Jetson系列的产品,也能部署在X86服务器中。==2.2项目结构.├──assets│└──yolosort.gif├──build#编译的文件夹│... 查看详情
nvidiajetsonyolov5tensorrt部署和加速c++版(代码片段)
...推理跑模型后;发现模型速度不够快,于是使用tensorRT部署,加速模型,本文介绍C++版本的。NVIDIAJetsonYOLOv5应用与部署_一颗小树x的博客-CSDN博客版本介绍:yolov5v6.0、 查看详情
pyqt搭建yolov5目标检测界面(代码片段)
Pyqt搭建YOLOV5目标检测界面(超详细+源代码)实现效果如下所示,可以检测图片、视频以及摄像头实时检测。实现效果如下所示,可以检测图片、视频以及摄像头实时检测。具体细节实现可以参考上一篇博客... 查看详情
目标检测yolov5分离检测和识别(代码片段)
前言YOLO作为单阶段检测方法,可以直接端到端的输出目标对象位置和类别,而在一些大型无人机遥感等目标检测任务中,使用单阶段检测往往会产生类别预测错误的问题。正好,YOLOv5-6.2版本提供了一个图像分类... 查看详情
jetson系列——基于yolov5对火源或者烟雾的检测,使用tensorrtc++和int8加速(代码片段)
项目简介:代码地址:github地址:https://github.com/RichardoMrMu/yolov5-fire-smoke-detectgitee地址:https://gitee.com/mumuU1156/yolov5-fire-smoke-detect欢迎start或提出你的issue、改进建议。本项目使用yolov5实现自然状态中火源或者烟雾的检测& 查看详情
使用tensorrt对人脸检测网络mtcnn进行加速(代码片段)
...一张1080P的图片要700ms,太慢了。想法正好这几天在学习TensorRT相关知识,已经成功将人脸特征提取网络转成onnx格式,然后用TensorRT的Python接口部署好了,单张图片耗时从15ms减少到3ms,非常理想的结果!理所当然,想着把MTCNN部署... 查看详情
目标检测yolov5:模型构建解析(代码片段)
前言最近在看一些目标检测的最新论文和代码,大多数都是在YOLOv5的基础上进行魔改。改的最多的基本是原版本的网络结构,这篇博文就从源码角度来解析YOLOv5中,模型是如何构建出来的。本文使用的是YOLOv5-5.0版本... 查看详情
完整目标检测项目流程——从使用labelimg标注到使用yolov5训练测试(代码片段)
完整目标检测项目流程——从使用LabelImg标注到使用YOLOv5训练测试大家好呀,虽然前面已经有两篇,分别使用FasterRCNN和YOLOv3进行目标检测的项目了,但是!相信大家应该也和我一样觉得远远不够吧!而且前面... 查看详情
目标识别yolov5针对小目标检测的改进模型/添加帧率检测(代码片段)
...下采样。对于一些分辨率很高的遥感/无人机图片,小目标难以被训练识别。本篇博文就来尝试这篇博文YOLOV5模型和代码修改——针对小目标识别所提到的一种改进方案。我所使用的是YOLOv5-5.0版本,数据集采用VisDrone数据... 查看详情
深度学习目标检测:yolov5实现车辆检测(含车辆检测数据集+训练代码)(代码片段)
深度学习目标检测:YOLOv5实现车辆检测(含车辆检测数据集+训练代码) 目录YOLOv5实现车辆检测(含车辆检测数据集+训练代码)1.前言2.车辆检测数据集说明(1)车辆检测数据集(2)自定义数据集3.基于YOLOv5... 查看详情
深度学习目标检测:yolov5实现车辆检测(含车辆检测数据集+训练代码)(代码片段)
深度学习目标检测:YOLOv5实现车辆检测(含车辆检测数据集+训练代码) 目录YOLOv5实现车辆检测(含车辆检测数据集+训练代码)1.前言2.车辆检测数据集说明(1)车辆检测数据集(2)自定义数据集3.基于YOLOv5... 查看详情
yolov5目标检测(代码片段)
前言YOLOv5官方发布的代码中,检测网络共有四个版本,依次为YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x。其中YOLOv5s是“深度”和“特征图宽度”均最小的网络,另外三种可以认为是在其基础上,进行了加深、加宽。看一下YOLOv... 查看详情
目标检测yolov5:标签中文显示/自定义颜色(代码片段)
前言本篇主要用来实现将YOLOv5输出的标签转成中文,并且自定义标签颜色的需求。我所使用的是YOLOv5-5.0版本。源码逻辑分析在detect.py中,这两行代码设置标签名字和颜色。#Getnamesandcolorsnames=model.module.namesifhasattr(model,... 查看详情
目标检测yolov5跑xview数据集/小样本检测策略实验(代码片段)
前言在YOLOv5的6.1版本新出了xView.yaml数据配置文件,提供了遥感数据集xView的检测方法。此篇就使用YOLOv5来试跑xView数据集,并对一些小样本检测的策略进行消融实验。xView数据集下载:https://github.com/zstar1003/Dataset数据... 查看详情
手把手教你使用yolov5训练自己的目标检测模型-口罩检测-视频教程(代码片段)
手把手教你使用YOLOV5训练自己的目标检测模型大家好,这里是肆十二(dejahu),好几个月没有更新了,这两天看了一下关注量,突然多了1k多个朋友关注,想必都是大作业系列教程来的小伙伴。既然有... 查看详情
yolov7tensorrt模型加速部署实战(代码片段)
0.linux环境配置基于tensorrt+cudac++实现模型end2end的gpu加速,支持win10、linux,在2023年已经更新模型:YOLOv8,YOLOv7,YOLOv6,YOLOv5,YOLOv4,YOLOv3,YOLOX,YOLOR,pphumanseg,u2net,EfficientDet。Windows10教程正在制作,可以关注仓库:https://github.com/ 查看详情
手把手教你使用yolov5训练自己的目标检测模型-口罩检测-视频教程(代码片段)
手把手教你使用YOLOV5训练自己的目标检测模型大家好,这里是肆十二(dejahu),好几个月没有更新了,这两天看了一下关注量,突然多了1k多个朋友关注,想必都是大作业系列教程来的小伙伴。既然有... 查看详情
深度学习目标检测---使用yolov5训练自己的数据集模型(windows系统)(代码片段)
...看一些视频教程和一些前辈的博客,实现了深度学习目标检测--使用yolov5网络训练自己的数据集并实现了对目标的识别。这篇博客我也是参考别人的博客教程,复现了使用yolov5训练自己的数据集,我呢主要是想记录下... 查看详情