signed

QiShunwang

“诚信为本、客户至上”

[模型压缩/加速]-tensorrt使用简介,tensorrt为什么这么快?为什么可以实现对模型的加速?

2021/5/14 21:00:22   来源:

资源

惯例先放资源
1.官方的tensorrt文档
2.tensorrt官方主页
3.tensorrt支持的操作


1.为什么需要模型加速

模型加速越来越成为深度学习工程中的刚需了,最近的CVPR和ICLR会议中,模型的压缩和剪枝是受到的关注越来越多。

毕竟所有的算法想要产生经济效益一定要考虑落地的情况,可能我们看很多论文提出的方法或者说github公布的代码大多关注精度及python环境下的FPS,但在实际的工程用在考虑精度的同时,速度也是十分重要的,且更多的公司越来越青睐python 训练,C++重写推理并利用tensorrt库进行加速。

拿自动驾驶举例来说,如果使用一个经典的深度学习模型,单帧图像的推理速度很容易就跑到200ms的延时,那么这意味着,在实际驾驶过程中,你的车一秒钟只能看到5张图像,这限制了我们对环境的感知情况,这是很危险的一件事。

再比如来说,同样功能的app,一个每次打开需要响应500ms的,和一个每次打开只需要响应100ms的,用户用脚投票也会淘汰掉500ms的app。

所以,对于实时响应比较高的任务,模型的加速时很有必要的一件事情了。


2.什么是tensorrt

可以把TensorRT看做一个“深度学习框架”,不同于常用的TensorFlow、PyTorch和Caffe等深度学习框架,TensorRT的目的不是如何训练我们的深度学习模型,而是考虑如何将那些使用其他框架训练好的模型进行高效快速的Inference。

官方的这张图可以很明确的说明TensorRT的作用:用于模型训练完之后的部署阶段,以进行高效低延时的Inference:

在这里插入图片描述
在工程实践中,一般还是用python + tensorflow/pytorch 等工具对数据预处理与进行训练,训练完成后得到权重文件,利用c++ 与 tensorrt重写模型推理部分,生成特定的tensorrt推理引擎,通常想对于python的推理速度会快大约5-20倍左右。

需要注意的是,tensorrt不支持cpu的加速,如果需要cpu部署加速可以尝试libtorch(torch官方的加速工具)


3.tensorrt为什么可以对模型加速?

这里会有疑问:直接使用TensorFlow和PyTorch等模型进行部署不可以吗?
这当然是可以的,只是TensorRT是一个专用的Inference工具,使用它进行部署会使模型运行更高效。

先从一张图来总览一下相关优化方法:
在这里插入图片描述

3.1,Layer & Tensor fusion

有时制约计算速度的并不仅仅是计算量,而是网络对于内存的读写花费太大,TensorRT中将多个层的操作合并为同一个层,这样就可以一定程度的减少kernel launches和内存读写。例如conv和relu等操作一次做完。另外,对于多分支合并的情况,TensorRT完全可以实现直接接到需要的地方,不用专门做concat的操作,所以这一层也可以取消掉。

在这里插入图片描述
如上图左边为InceptionBlock,通过以下步骤优化得到上图右边的计算图:首先合并conv、bias、relu为一个CBR;接下来合并三个相连的1×1的CBR为一个大的1×1的CBR;最后取消concat层,直接连接到下一层的nextinput。另外还可以做并发(Concurrency),不同并的分支是相互独立的路径,本质上是不相关的,可以在GPU上通过并发来做,来达到的优化的目标。

3.2,Precision Calibration

训练时由于梯度等对于计算精度要求较高,但是inference阶段可以利用精度较低的数据类型加速运算,降低模型的大小。

3.3,Kernel Auto-tuning

在GPU上跑的函数叫Kernel,TensorRT是存在Kernel的调用的。TensorRT针对不同的超参数有一些Kernel层面的优化,比如会根据卷积核的大小、输入大小等超参数确定使用哪种算法进行卷积运算。

3.4,Dynamic Tensor Memory

TensorRT经过优化减少内存开销,提高内存的reuse。

3.5,Multi-stream Execution

对于同一输入的多个分支可以进行并行运算,还可以根据不同batchsize优化。


总结一下

TensorRT对一个模型主要进行了以下几点优化:

  • 去除输出没有被使用的层
  • 去除那些相当于没用的操作
  • 将卷积、偏置和ReLU操作融合在一起
  • 聚合那些相似的操作
  • 融合残差层
    (以上这些操作中有些并不清楚具体实现原理,后面在使用到时再具体学习)

除了上述对模型整体的优化外,在TensorRT中还可以直接设置权值的精度,如可以进行INT8FP16精度的运算,默认是FP32精度。当然,低精度带来速度提升的同时,必然会带来准确度的损失,在模型部署时可根据需要来权衡。


4.如何将python+其他框架的模型导入tensorrt

通过其他框架训练好的模型,如何导入到TensorRT中使用?
TensorRT支持TensorFlow、PyTorch,MXNet和Caffe等主流框架模型的导入,支持方式是通过一些通用的模型交换格式作为中间媒介。

TensorRT中有三个Parser用于模型的导入:

  • Caffe Parser: 支持Caffe框架模型的导入
  • UFF Parser:通用框架格式(UFF)是描述DNN的执行图的数据格式
  • ONNX Parser:通用模型交换格式(ONNX)是一种开放式的文件格式,用于存储训练好的模型

作者自己一般使用pytorch,一般都是将.pt/.pth文件转换成.onnx或者.wts格式文件,然后导入至tensorrt

需要清楚的是,各种框架间模型的转换,需要的仅仅是模型的定义及权值
通过将模型保存为以上三个Parser(trt解析器)可以解析的格式,则基本上就可以将模型导入到TensorRT中。


5.模型如何在TensorRT执行推理

事实上,一个模型从导入到执行,会经过下面三个阶段:

  • Network Definition: 这一阶段在TensorRT中定义网络模型,可以使用TensorRT提供的Parser导入已有模型进行定义,也可以使用TensorRT中提供的网络层来编程定义(这一步应该也需要准备好相关的权值)
  • Builder:前面提到过,TensorRT会对模型进行优化,这一步就是配置各项优化参数,并能生成可执行Inference的Engine
  • Engine:Engine可理解为一个Builder的实例,是我们导入的模型经过Builder的配置所生成的一个优化过的Inference执行器,所有的Inference可直接调用Engine来执行

通过上面的分析可以有这样的理解:一个导入的模型可根据不同的Builder配置来生成不同的Engine来执行Inference。

一个模型从导入到生成Engine是需要花费一些时间的,因此TensorRT提供了Engine的序列化和反序列化操作,一旦我们确定了一个Engine,可以对其进行序列化操作,下次执行Inference时直接反序列化该Engine即可。


6.注意事项

  • 1.想要获得更快的推理速度建议使用trt的C++接口(官方也提供了python接口)
  • 2.每个engine都是根据当前的GPU和CUDA及trt版本来的,所以换个环境可能不能用了,因此Builder生成Engine前,要注意环境配置。
  • 3.TensorRT可结合DALI(加速数据读取)和DLA(加速某些层的运算)一起使用来更快的加速处理
  • 4.对于TensorRT中不支持的层,需要自己编写相应的文件,TensorRT提供了相关支持

7.参考

1.trt官方文档
2.《一》TensorRT之基本概念
3.tensorrt轻松部署高性能dnn推理_深度学习模型inference优化之tensorrt(TRT)