首发于 8层会议室
TensorRT部署深度学习模型

TensorRT部署深度学习模型

1.背景

目前主流的深度学习框架(caffe,mxnet,tensorflow,pytorch等)进行模型推断的速度都并不优秀,在实际工程中用上述的框架进行模型部署往往是比较低效的。而通过Nvidia推出的tensorRT工具来部署主流框架上训练的模型能够极大的提高模型推断的速度,往往相比与原本的框架能够有至少1倍以上的速度提升,同时占用的设备内存也会更加的少。因此对是所有需要部署模型的同志来说,掌握用tensorRT来部署深度学习模型的方法是非常有用的。

2.相关技术

上面的图片取自TensorRT的官网,里面列出了tensorRT使用的一些技术。可以看到比较成熟的深度学习落地技术:模型量化、动态内存优化、层的融合等技术均已经在tensorRT中集成了,这也是它能够极大提高模型推断速度的原因。总体来说tensorRT将训练好的模型通过一系列的优化技术转化为了能够在特定平台(GPU)上以高性能运行的代码,也就是最后图中生成的Inference engine。目前也有一些其他的工具能够实现类似tensorRT的功能,例如 TVM, TensorComprehensions也能有效的提高模型在特定平台上的推断速度,但是由于目前企业主流使用的都是Nvidia生产的计算设备,在这些设备上nvidia推出的tensorRT性能相比其他工具会更有优势一些。而且tensorRT依赖的代码库仅仅包括C++和cuda,相对与其他工具要更为精简一些。

3. tensorflow模型tensorRT部署教程

实际工程部署中多采用c++进行部署,因此在本教程中也使用的是tensorRT的C++API,tensorRT版本为5.1.5。具体tensorRT安装可参考教程 [深度学习] TensorRT安装,以及官网的安装说明。

模型持久化

部署tensorflow模型的第一步是模型持久化,将模型结构和权重保存到一个.pb文件当中。

具体只需在模型定义和权重读取之后执行以上代码,调用tf.graph_util.convert_variables_to_constants函数将权重转为常量,其中outputs是需要作为输出的tensor的列表,最后用pb_graph.SerializeToString()将graph序列化并写入到pb文件当中,这样就生成了pb模型。

生成uff模型

有了pb模型,需要将其转换为tensorRT可用的uff模型,只需调用uff包自带的convert脚本即可

如转换成功会输出如下信息,包含图中总结点的个数以及推断出的输入输出节点的信息

tensorRT c++ API部署模型

使用tensorRT部署生成好的uff模型需要先讲uff中保存的模型权值以及网络结构导入进来,然后执行优化算法生成对应的inference engine。具体代码如下,首先需要定义一个IBuilder* builder,一个用来解析uff文件的parser以及builder创建的network,parser会将uff文件中的模型参数和网络结构解析出来存到network,解析前要预先告诉parser网络输入输出输出的节点。解析后builder就能根据network中定义的网络结构创建engine。在创建engine前会需要指定最大的batchsize大小,之后使用engine时输入的batchsize不能超过这个数值否则就会出错。推断时如果batchsize和设定最大值一样时效率最高。举个例子,如果设定最大batchsize为10,实际推理输入一个batch 10张图的时候平均每张推断时间是4ms的话,输入一个batch少于10张图的时候平均每张图推断时间会高于4ms。

生成engine之后就可以进行推断了,执行推断时需要有一个上下文执行上下文IExecutionContext* context,可以通过engine->createExecutionContext()获得。执行推断的核心代码是

其中buffer是一个void*数组对应的是模型输入输出tensor的设备地址,通过cudaMalloc开辟输入输出所需要的设备空间(显存)将对应指针存到buffer数组中,在执行execute操作前通过cudaMemcpy把输入数据(输入图像)拷贝到对应输入的设备空间,执行execute之后还是通过cudaMemcpy把输出的结果从设备上拷贝出来。

更为详细的例程可以参考TensorRT官方的samples中的 sampleUffMNIST代码

加速比情况

实际工程中我在Tesla M40上用tensorRT来加速过Resnet-50,Inception-resnet-v2,谷歌图像检索模型Delf(DEep Local Features),加速前后单张图推断用时比较如下图(单位ms)

4. Caffe模型tensorRT部署教程

相比与tensorflow模型caffe模型的转换更加简单,不需要有tensorflow模型转uff模型这类的操作,tensorRT能够直接解析prototxt和caffemodel文件获取模型的网络结构和权重。具体解析流程和上文描述的一致,不同的是caffe模型的parser不需要预先指定输入层,这是因为prototxt已经进行了输入层的定义,parser能够自动解析出输入,另外caffeparser解析网络后返回一个IBlobNameToTensor *blobNameToTensor记录了网络中tensor和pototxt中名字的对应关系,在解析之后就需要通过这个对应关系,按照输出tensor的名字列表outputs依次找到对应的tensor并通过network->markOutput函数将其标记为输出,之后就可以生成engine了。

生成engine后执行的方式和上一节描述的一致,详细的例程可以参考 SampleMNIST

加速比情况

实际工程中我在Tesla M40上用tensorRT加速过caffe的VGG19,SSD速度变为1.6倍,ResNet50,MobileNetV2加速前后单张图推断用时比较如下图(单位ms)

5.为tensorRT添加自定义层

tensorRT目前只支持一些非常常见的操作,有很多操作它并不支持比如上采样Upsample操作,这时候就需要我们自行将其编写为tensorRT的插件层,从而使得这些不能支持的操作能在tensorRT中使用。以定义Upsample层为例,我们首先要定义一个继承自tensorRT插件基类的Upsample类

然后要实现该类的一些必要方法,首先是2个构造函数,一个是传参数构建,另一个是从序列化后的比特流构建。

一些定义层输出信息的方法

根据输入的形状个数以及采用的数据类型检查合法性以及配置层参数的方法

层的序列化方法

层的运算方法

在enqueue中我们调用编写好的cuda kenerl来进行Upsample的计算

完成了Upsample类的定义,我们就可以直接在网络中添加我们编写的插件了,通过如下语句我们就定义一个上采样2倍的上采样层。addPluginExt的第一个输入是ITensor**类别,这是为了支持多输出的情况,第二个参数就是输入个数,第三个参数就是需要创建的插件类对象。

6.为CaffeParser添加自定义层支持

对于我们自定义的层如果写到了caffe prototxt中,在部署模型时调用caffeparser来解析就会报错。

还是以Upsample为例,如果在prototxt中有下面这段来添加了一个upsample的层

这时再调用

就会出现错误

之前我们已经编写了Upsample的插件,怎么让tensorRT的caffe parser识别出prototxt中的upsample层自动构建我们自己编写的插件呢?这时我们就需要定义一个插件工程类继承基类nvinfer1::IPluginFactory, nvcaffeparser1::IPluginFactoryExt。

其中必须要的实现的方法有判断一个层是否是plugin的方法,输入的参数就是prototxt中layer的name,通过name来判断一个层是否注册为插件

根据名字创建插件的方法,有两中方式一个是由权重构建,另一个是由序列化后的比特流创建,对应了插件的两种构造函数,Upsample没有权重,对于其他有权重的插件就能够用传入的weights初始化层。mplugin是一个vector用来存储所有创建的插件层。

最后需要定义一个destroy方法来释放所有创建的插件层。

对于prototxt存在多个多种插件的情况,可以在isPlugin,createPlugin方法中添加新的条件分支,根据层的名字创建对应的插件层。

实现了PluginFactory之后在调用caffeparser的时候需要设置使用它,在调用parser->parser之前加入如下代码

就可以设置parser按照pluginFactory里面定义的规则来创建插件层,这样之前出现的不能解析Upsample层的错误就不会再出现了。

官方添加插件层的样例 samplePlugin可以作为参考

7.心得体会(踩坑记录)

1. 转tensorflow模型时,生成pb模型、转换uff模型以及调用uffparser时register Input,output,这三个过程中输入输出节点的名字一定要注意保持一致,否则最终在parser进行解析时会出现错误,找不到输入输出节点。

2.除了本文中列举的pluginExt,tensorRT中插件基类还有IPlugin,IPluginV2,继承这些基类所需要实现的类方法有细微区别,具体情况可自行查看tensorRT安装文件夹下的include/NvInfer.h文件。同时添加自己写的层到网络时的函数有addPlugin,addPluginExt,addPluginV2这几种和IPlugin,IPluginExt,IPluginV2一一对应,不能够混用,否则有些默认调用的类方法不会调用的,比如用addPlugin添加的PluginExt层是不会调用configureWithFormat方法的,因为IPlugin类没有该方法。同样的在还有caffeparser的setPluginFactory和setPluginFactoryExt也是不能混用的。

3.运行程序出现cuda failure一般情况下是由于将内存数据拷贝到磁盘时出现了非法内存访问,注意检查buffer开辟的空间大小和拷贝过去数据的大小是否一致.

4. 有一些操作在tensorRT中不支持但是可以通过一些支持的操作进行组合替代,比如 sign(x)可替换为x/(abs(x)+1e-12) ,这样可以省去一些编写自定义层的时间。

5. tensorflow中的flatten操作默认时keepdims=False的,但是在转化uff文时会默认按照keepdims=True转换,因此在tensorflow中对flatten后的向量进行transpose、expanddims等等操作,在转换到uff后用tensorRT解析时容易出现错误,比如“Order size is not matching the number dimensions of TensorRT” 。最好设置tensorflow的reduce,flatten操作的keepdims=True,保持层的输出始终为4维形式,能够有效避免转到tensorRT时出现各种奇怪的错误。

6.tensorRT中的slice层存在一定问题,我用network->addSlice给网络添加slice层后,在执行buildengine这一步时就会出错nvinfer1::builder::checkSanity(const nvinfer1::builder::Graph&): Assertion `tensors.size() == g.tensors.size()' failed.,构建网络时最好避开使用slice层,或者自己实现自定层来执行slice操作。

7. tensorRT 的github中有着部分的开源代码以及丰富的示例代码,多多学习能够帮助更快的掌握tensorRT的使用

8.参考资料

Nvidia TensorRT Samples

tensorrt-developer-guide

TensorRT API Docs

TensorRT Github

天下网TXWEB乌海网站改版报价辽阳市网站搭建遵义市网站搭建公司潍坊seo按天扣费多少钱长春seo优化多少钱温州seo按天扣费哪家专业渭南seo按天扣费推荐松原seo排名公司本溪市网站定制太原建网站哪家专业商洛市建站哪家专业玉林市网站改版多少钱泉州市网站设计推荐枣庄优化公司承德seo价格商丘做网站哪家好安庆市做网站哪家好海口网站制作价格新余品牌网站设计价格蚌埠市网站搭建价格南通市模板网站建设价格邢台seo按天计费推荐邵阳网站建设哪家好邢台网站建设哪家好坪地企业网站改版哪家好莱芜市网站推广哪家好梅州企业网站改版价格泸州市网站制作多少钱镇江建站报价梅州网页设计哪家好香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声卫健委通报少年有偿捐血浆16次猝死汪小菲曝离婚始末何赛飞追着代拍打雅江山火三名扑火人员牺牲系谣言男子被猫抓伤后确诊“猫抓病”周杰伦一审败诉网易中国拥有亿元资产的家庭达13.3万户315晚会后胖东来又人满为患了高校汽车撞人致3死16伤 司机系学生张家界的山上“长”满了韩国人?张立群任西安交通大学校长手机成瘾是影响睡眠质量重要因素网友洛杉矶偶遇贾玲“重生之我在北大当嫡校长”单亲妈妈陷入热恋 14岁儿子报警倪萍分享减重40斤方法杨倩无缘巴黎奥运考生莫言也上北大硕士复试名单了许家印被限制高消费奥巴马现身唐宁街 黑色着装引猜测专访95后高颜值猪保姆男孩8年未见母亲被告知被遗忘七年后宇文玥被薅头发捞上岸郑州一火锅店爆改成麻辣烫店西双版纳热带植物园回应蜉蝣大爆发沉迷短剧的人就像掉进了杀猪盘当地回应沈阳致3死车祸车主疑毒驾开除党籍5年后 原水城县长再被查凯特王妃现身!外出购物视频曝光初中生遭15人围殴自卫刺伤3人判无罪事业单位女子向同事水杯投不明物质男子被流浪猫绊倒 投喂者赔24万外国人感慨凌晨的中国很安全路边卖淀粉肠阿姨主动出示声明书胖东来员工每周单休无小长假王树国卸任西安交大校长 师生送别小米汽车超级工厂正式揭幕黑马情侣提车了妈妈回应孩子在校撞护栏坠楼校方回应护栏损坏小学生课间坠楼房客欠租失踪 房东直发愁专家建议不必谈骨泥色变老人退休金被冒领16年 金额超20万西藏招商引资投资者子女可当地高考特朗普无法缴纳4.54亿美元罚金浙江一高校内汽车冲撞行人 多人受伤

天下网TXWEB XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化