文章目录

  • 简介
  • Why TensorRT
  • TensorRT部署流程
  • TensorRT 支持范围
  • TensorRT 模型导入流程
  • TensorRT 优化细节
  • TensorRT 部署方法
https://developer.nvidia.com/zh-cn/tensorrt

简介

一般的深度学习项目,训练时为了加快速度,会使用多GPU分布式训练。但在部署推理时,为了降低成本,往往使用单个GPU机器甚至嵌入式平台(比如 NVIDIA Jetson)进行部署,部署端也要有与训练时相同的深度学习环境,如caffe,TensorFlow等。

由于训练的网络模型可能会很大(比如,inception,resnet等),参数很多,而且部署端的机器性能存在差异,就会导致推理速度慢,延迟高。这对于那些高实时性的应用场合是致命的,比如自动驾驶要求实时目标检测,目标追踪等。

所以为了提高部署推理的速度,出现了很多轻量级神经网络,比如squeezenet,mobilenet,shufflenet等。基本做法都是基于现有的经典模型提出一种新的模型结构,然后用这些改造过的模型重新训练,再重新部署。

TensorRT 则是对训练好的模型进行优化。 tensorRT就只是 推理优化器。当你的网络训练完之后,可以将训练模型文件直接丢进tensorRT中,而不再需要依赖深度学习框架(Caffe,TensorFlow等),如下:

可以认为tensorRT是一个只有前向传播的深度学习框架,这个框架可以将 Caffe,TensorFlow的网络模型解析,然后与tensorRT中对应的层进行一一映射,把其他框架的模型统一全部转换到tensorRT中,然后在tensorRT中针对NVIDIA自家GPU实施优化策略,并进行部署加速。

目前TensorRT4.0以上,几乎可以支持所有常用的深度学习框架,对于caffe和TensorFlow来说,tensorRT可以直接解析他们的网络模型;对于caffe2,pytorch,mxnet,chainer,CNTK等框架则是首先要将模型转为 ONNX 的通用深度学习模型,然后对ONNX模型做解析。而tensorflow和MATLAB已经将TensorRT集成到框架中去了。

ONNX(Open Neural Network Exchange )是微软和Facebook携手开发的开放式神经网络交换工具,也就是说不管用什么框架训练,只要转换为ONNX模型,就可以放在其他框架上面去inference。这是一种统一的神经网络模型定义和保存方式,上面提到的除了tensorflow之外的其他框架官方应该都对onnx做了支持,而ONNX自己开发了对tensorflow的支持。从深度学习框架方面来说,这是各大厂商对抗谷歌tensorflow垄断地位的一种有效方式;从研究人员和开发者方面来说,这可以使开发者轻易地在不同机器学习工具之间进行转换,并为项目选择最好的组合方式,加快从研究到生产的速度。

上面图中还有一个 Netwok Definition API 这个是为了给那些使用自定义的深度学习框架训练模型的人提供的TensorRT接口。举个栗子:比如 YOLO 作者使用的darknet要转tensorrt估计得使用这个API,不过一般网上有很多使用其他框架训练的YOLO,这就可以使用对应的caffe/tensorflow/onnx API了。

ONNX / TensorFlow / Custom deep-learning frame模型的工作方式:

Why TensorRT

训练对于深度学习来说是为了获得一个性能优异的模型,其主要的关注点在于模型的准确度等指标。推理则不一样,其没有了训练中的反向迭代过程,是针对新的数据进行预测,而我们日常生活中使用的AI服务都是推理服务。相较于训练,推理的关注点不一样,从而也给现在有技术带来了新的挑战:

根据上图可知,推理更关注的是高吞吐率、低响应时间、低资源消耗以及简便的部署流程,而TensorRT就是用来解决推理所带来的挑战以及影响的部署级的解决方案。

TensorRT部署流程


TensorRT的部署分为两个部分:

优化训练好的模型并生成计算流图

使用TensorRT Runtime部署计算流图

关于这个流程很自然我们会想到以下几个问题:

TensorRT支持什么框架训练出来的网络模型呢?

TensorRT支持什么网络结构呢?

TensorRT优化器做了哪些优化呢?

TensorRT优化好的计算流图可以运行在什么设备上呢?

个中因果,诸位看官,稍安勿躁,待本文娓娓道来。

TensorRT 支持范围


输入篇之网络框架:TensorRT3支持所有常见的深度学习框架包括Caffe、Chainer、CNTK、MXnet、PaddlePaddle、Pytorch、TensorFlow以及Theano。

输入篇之网络层:TensorRT3支持的网络层包括

Activation: ReLU, tanh and sigmoid
Concatenation : Link together multiple tensors across the channel dimension.
Convolution: 3D,2D
Deconvolution
Fully-connected: with or without bias
ElementWise: sum, product or max of two tensors
Pooling: max and average
Padding
Flatten
LRN: cross-channel only
SoftMax: cross-channel only
RNN: RNN, GRU, and LSTM
Scale: Affine transformation and/or exponentiation by constant values
Shuffle: Reshuffling of tensors , reshape or transpose data
Squeeze: Removes dimensions of size 1 from the shape of a tensor
Unary: Supported operations are exp, log, sqrt, recip, abs and neg
Plugin: integrate custom layer implementations that TensorRT does not natively support.

基本上比较经典的层比如,卷积,反卷积,全连接,RNN,softmax等,在tensorRT中都是有对应的实现方式的,tensorRT是可以直接解析的。

但是由于现在深度学习技术发展日新月异,各种不同结构的自定义层(比如:STN)层出不穷,所以tensorRT是不可能全部支持当前存在的所有层的。那对于这些自定义的层该怎么办?
tensorRT中有一个 Plugin 层,这个层提供了 API 可以由用户自己定义tensorRT不支持的层。 这就解决了适应不同用户的自定义层的需求。如下图:

输入篇之接口方式:TensorRT3支持模型导入方式包括C++ API、Python API、NvCaffeParser和NvUffParser

输出篇之支持系统平台:TensorRT3支持的平台包括Linux x86、Linux aarch64、Android aarch64和QNX aarch64。

输出篇之支持硬件平台:TensorRT3可以运行在每一个GPU平台,从数据中心的Tesla P4/V100到自动驾驶和嵌入式平台的DrivePX及TX1/TX2。

注意:这是TensorRT3,现在已经到TensorRT 7.1,应该支持更丰富,更强大

TensorRT 模型导入流程

如上图所示,模型的导入方法可以根据框架种类分成三种:Caffe、TensorFlow和其他

Caffe

  1. 使用C++/Python API导入模型:通过代码定义网络结构,并载入模型weights的方式导入;
  2. 使用NvCaffeParser导入模型:导入时输入网络结构prototxt文件及caffemodel文件即可。

TensorFlow

  1. 训练完成后,使用uff python接口将模型转成uff格式,之后使用NvUffParaser导入;

  2. 对于TensorFlow或者keras(TensorFlow后端)的,利用Freeze graph来生成.pb(protobuf)文件,之后使用convert-to-uff工具将.pb文件转化成uff格式,然后利用NvUffParaser导入。

其他框架

  • 使用C++/Python API导入模型:通过代码定义网络结构,载入模型weights的方式导入。以Pytorch为例,在完成训练后,通过stat_dict()函数获取模型的weights,从而在定义网络结构时将weights载入

注:weights文件是保存的C++ Map对象,该对象定义为:

std::map<std::string, Weights>

其中Weights类型是在NvInfer.h中定义,为存储weights的array。

TensorRT 优化细节

网络模型在导入至TensorRT后会进行一系列的优化,主要优化内容如下图所示。TensorRT优化方法,最主要的是前面两种:Layer & Tensor Fusion、Precision Calibration

Layer & Tensor Fusion(层间融合或张量融合)

TensorRT在获得网络计算流图后会针对计算流图进行优化,这部分优化不会改变图中最底层计算内容,而是会去重构计算图来获得更快更高效的执行方式,即计算不变优化计算方法。

如下图左侧是GoogLeNetInception模块的计算图。这个结构中有很多层,在部署模型推理时,这每一层的运算操作都是由GPU完成的,但实际上是GPU通过启动不同的CUDA(Compute unified device architecture)核心来完成计算的,CUDA核心计算张量的速度是很快的,但是往往大量的时间是浪费在CUDA核心的启动和对每一层输入/输出张量的读写操作上面,这造成了内存带宽的瓶颈和GPU资源的浪费。TensorRT通过对层间的横向或纵向合并(合并后的结构称为CBR,意指 convolution, bias, and ReLU layers are fused to form a single layer),使得层的数量大大减少。横向合并可以把卷积、偏置和激活层合并成一个CBR结构,只占用一个CUDA核心。纵向合并可以把结构相同,但是权值不同的层合并成一个更宽的层,也只占用一个CUDA核心。合并之后的计算图(图右侧)的层次更少了,占用的CUDA核心数也少了,因此整个模型结构会更小,更快,更高效。

深度学习框架在做推理时,会对每一层调用多个/次功能函数。而由于这样的操作都是在GPU上运行的,从而会带来多次的CUDA Kernel launch过程。相较于Kernel launch以及每层tensor data读取来说,kernel的计算是更快更轻量的,从而使得这个程序受限于显存带宽并损害了GPU利用率。

TensorRT通过以下三种方式来解决这个问题:

  1. Kernel纵向融合:通过融合相同顺序的操作来减少Kernel Launch的消耗以及避免层之间的显存读写操作。如上图所示,卷积、Bias和Relu层可以融合成一个Kernel,这里称之为CBR。
  2. Kernel横向融合:TensorRT会去挖掘输入数据且filter大小相同但weights不同的层,对于这些层不是使用三个不同的Kernel而是使用一个Kernel来提高效率,如上图中超宽的1x1 CBR所示。
  3. 消除concatenation层,通过预分配输出缓存以及跳跃式的写入方式来避免这次转换。

通过这样的优化,TensorRT可以获得更小、更快、更高效的计算流图,其拥有更少层网络结构以及更少Kernel Launch次数。下表列出了常见几个网络在TensorRT优化后的网络层数量,很明显的看到TensorRT可以有效的优化网络结构、减少网络层数从而带来性能的提升。

Weight &Activation Precision Calibration(数据精度校准)

大部分深度学习框架在训练神经网络时网络中的张量(Tensor)都是32位浮点数的精度(Full 32-bit precision,FP32),一旦网络训练完成,在部署推理的过程中由于不需要反向传播,完全可以适当降低数据精度,比如降为FP16或INT8的精度。更低的数据精度将会使得内存占用和延迟更低,模型体积更小。

如下表为不同精度的动态范围:

INT8只有256个不同的数值,使用INT8来表示 FP32精度的数值,肯定会丢失信息,造成性能下降不过TensorRT会提供完全自动化的校准(Calibration )过程,会以最好的匹配性能将FP32精度的数据降低为INT8精度,最小化性能损失。关于校准过程,后面会专门做一个探究。

FP16 & INT8 精度校准

大多数的网络都是使用FP32进行模型训练,因此模型最后的weights也是FP32格式。但是一旦完成训练,所有的网络参数就已经是最优,在推理过程中是无需进行反向迭代的,因此可以在推理中使用FP16或者INT8精度计算从而获得更小的模型,低的显存占用率和延迟以及更高的吞吐率

TensorRT可以采用FP32、FP16和INT8精度部署模型,只需要在uff_to_trt_engine函数中指定相应数据类型即可:

  • 对于FP32, 使用 trt.infer.DataType.FLOAT.
  • 对于FP16 指令 以及 Volta GPU内的Tensor Cores, 使用trt.infer.DataType.HALF
  • 对于INT8, 使用 trt.infer.DataType.INT8.

Kernel Auto-Tuning(内核自动调优)

TensorRT会针对大量的Kernel进行参数优化和调整。例如说,对于卷积计算有若干种算法,TensorRT会根据输入数据大小、filter大小、tensor分布、batch大小等等参数针对目标平台GPU进行选择和优化。

Dynamic Tensor Memory(动态张量储存)

TensorRT通过为每一个tensor在其使用期间设计分配显存来减少显存的占用增加显存的复用率,从而避免了显存的过度开销以获得更快和高效的推理性能。

Multi-Stream Execution

Scalable design to process multiple input streams in parallel,这个应该就是GPU底层的优化了。

Performance Results

上图为基于Resnet50网络,分别在CPU、V100+TensorFlow、V100+TensorRT上进行推理时的性能比较,纵轴为每秒处理的图片数量。相较于CPU和TensorFlow,TensorRT可以带来40倍和18倍的吞吐率的提升,而这部分的提升只需要在拥有GPU的前提下使用TensorRT即可免费获得。

TensorRT 部署方法

完成TensorRT优化后可以得到一个Runtime inference engine,这个文件可以被序列化保存至硬盘中,而这个保存的序列化文件我们称之为“Plan”(流图),之所以称之为流图,因此其不仅保存了计算时所需的网络weights也保存了Kernel执行的调度流程。TensorRT提供了write_engine_to_file()函数以来保存流图。

在获得了流图之后就可以使用TensorRT部署应用。为了进一步的简化部署流程,TensorRT提供了TensorRT Lite API,它是高度抽象的接口会自动处理大量的重复的通用任务例如创建一个Logger,反序列化流图并生成Runtime inference engine,处理输入的数据。以下代码提供了一个使用TensorRT Lite API的范例教程,只需使用API创建一个Runtime Engine即可完成前文提到的通用任务,之后将需要推理的数据载入并送入Engine即可进行推理。

from tensorrt.lite import Enginefrom tensorrt.infer import LogSeverityimport tensorrt# Create a runtime engine from plan file using TensorRT Lite API engine_single = Engine(PLAN="keras_vgg19_b1_FP32.engine",postprocessors={"dense_2/Softmax":analyze})images_trt, images_tf = load_and_preprocess_images()results = []for image in images_trt:result = engine_single.infer(image) # Single function for inferenceresults.append(result)

敲黑板!!!TensorRT3 Highlight:

TensorRT3带来的三个重大更新为:

  • TensorFlow Model Importer - 便捷的API用于导入TensorFLow训练的模型,优化并生成推理Engine。
  • Python API - Python API用于进一步提高开发效率。
  • Volta Tensor Core支持 - 带来相较于Tesla P100高达3.7倍的更快的推理性能。

参见

https://mp.weixin.qq.com/mp/homepage?__biz=MzI5ODk5NjQ3Mg==&hid=3&sn=53d89b8be0c605b5f48e8b27341659ab&scene=1&devicetype=android-29&version=28000951&lang=zh_CN&nettype=cmnet&ascene=59&session_us=gh_65d128e93a48&wx_header=1

https://arleyzhang.github.io/articles/7f4b25ce/

TensorRT | 入门篇相关推荐

  1. 女友问粉丝过万如何庆祝,我发万字长文《保姆级大数据入门篇》感恩粉丝们支持,学姐|学妹|学弟|小白看了就懂

    2021大数据领域优质创作博客,带你从入门到精通,该博客每天更新,逐渐完善大数据各个知识体系的文章,帮助大家更高效学习. 有对大数据感兴趣的可以关注微信公众号:三帮大数据 目录 粉丝破万了 新星计划申 ...

  2. Farseer.net轻量级ORM开源框架 V1.x 入门篇:新版本说明

    导航 目   录:Farseer.net轻量级ORM开源框架 目录 上一篇:没有了 下一篇:Farseer.net轻量级ORM开源框架 V1.x 入门篇:数据库配置 前言 V1.x版本终于到来了.本次 ...

  3. SQL注入漏洞全接触--入门篇

    随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进 ...

  4. Symbian开发系列 - 入门篇

    要开始我的Symbian开发之旅了, 先收集一些相关资料,如Symbian概述, 开发平台搭建, 参考书籍与网络资源. [基础] 什么是Symbian 学习Symbian的基本概念  Symbian操 ...

  5. 《Ansible权威指南 》一 第一篇 Part 1 基础入门篇

    本节书摘来自华章出版社<Ansible权威指南 >一书中的第1章,第1.1节,李松涛 魏 巍 甘 捷 著更多章节内容可以访问云栖社区"华章计算机"公众号查看. 第一篇 ...

  6. 【SSRS】入门篇(二) -- 建立数据源

    原文:[SSRS]入门篇(二) -- 建立数据源 通过 [SSRS]入门篇(一) -- 创建SSRS项目 这篇,我们建立了一个SSRS项目: 接下来,我们以 AdventureWorks2012 示例 ...

  7. Python从入门到精通 - 入门篇 (下)

    上一讲回顾:Python从入门到精通 - 入门篇 (上) 接着上篇继续后面两个章节,函数和解析式. 4 函数 Python 里函数太重要了 (说的好像在别的语言中函数不重要似的).函数的通用好处就不用 ...

  8. Python从入门到精通 - 入门篇 (上)

    转载自微信公众号:王的机器 0 引言 微信公众号终于可以插代码了,Python 可以走一波了.首先我承认不是硬核搞 IT 的,太高级的玩法也玩不来,讲讲下面基本的还可以,之后带点机器学习.金融工程和量 ...

  9. matplotlib中文文档_python绘图库——Matplotlib及Seaborn使用(入门篇1)

    在数据分析过程中,数据及模型可视化是无可避免的,同时这也是展示我们数据分析成果的最佳方式.因此,熟悉掌握绘图库的使用,对精进我们的数据分析技能起着不可替代的作用. 今天,我们就来了解一下python强 ...

最新文章

  1. localStorage、sessionStorage、Cookie的区别及用法
  2. mysql数据库唯一性_mysql表的字段怎么设置唯一性
  3. android 获取最近应用和全部应用_Android 黑科技之卸载系统应用
  4. 这周开发工作时间及内容、思考和阅读的内容
  5. MFC制作打地鼠小游戏
  6. spring IOC基本配置(xml配置和注解配置)
  7. 数据库工作笔记005---You have an error in your SQL syntax; check the manual that corresponds to y
  8. problem making ssl connection
  9. 四行代码创建复杂(无限级)树
  10. 不学无数——JAVA中NIO再深入
  11. Ubuntu下Chrome打不开解决办法
  12. html 实现页面加载进度,网页加载进度条实现方案
  13. 操作 神通数据库_国产神通数据库操作备忘(Linux)
  14. android中图片压缩上传方法之Luban库
  15. windows安装scala
  16. moment时区转换
  17. 华东师范大学计算机考研有多难,「华东师范大学考研详解」报录比70:1的专业,热度高到“爆炸”!...
  18. C++ 应用程序无法正常启动0xc000007b
  19. 根据url批量下载图片
  20. 苏建林DGCNN模型代码详解

热门文章

  1. mysql neq什么意思_【知识科普】标准中的Eqv、Idt和Neq分别代表什么?
  2. 获取新浪开放平台的Access token
  3. 学Python更多是为了摸鱼,大多数人都这么做
  4. 中文转拼音 中文转罗马声调
  5. 《打地鼠》游戏简单制作
  6. 电子计算机怎么按不了数字,计算器失灵按不出数字
  7. VB.NET学习笔记:使用Random类生成随机数(不重复、数字、字母)
  8. Segment Routing入门
  9. 小程序 设置小程序打开聊天中的素材
  10. 会计中阿拉伯数字变数字繁体大写