本文转载于:子棐之GPGPU 的 TensorRT系列入门篇 学习一下加深印象

Why TensorRT

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

需求

现有框架的局限性

影响

高吞吐率 无法处理大量和高速的数据 增加了单次推理的开销
低响应时间 应用无法提供实时的结果 损害了用户体验(语音识别、个性化推荐和实时目标检测)
高效的功耗以及显存消耗控制 非最优效能 增加了推理的开销甚至无法进行推理部署
部署级别的解决方案 非专用于部署使用 框架复杂度和配置增加了部署难度以及生产率

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

TensorRT的部署流程

TensorRT的部署分为两个部分:

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

  2. 使用TensorRT Runtime部署计算流图

那么我们很自然的就会想到下面几个问题?

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

  2. TensorRT支持什么网络结构呢?

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

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

TensorRT的神通

输入篇之网络框架:TensorRT3支持所有常见的深度学习框架包括Caffe、Tensorflow、Pytorch、MXnet、PaddlePaddle、Theano等

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

Convolution

LSTM and GRU

Activation: ReLU, tanh, sigmoid

Pooling: max and average

Scaling

ElementWise

LRN

Fully-connected

SoftMax

Deconvolution

Concatenation

Flatten

Padding

Plugin

RNN: RNN, GRU, LSTM

Scale

Shuffle

Softmax

Squeeze

Unary

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

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

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

TensorRT模型导入流程

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

caffe

  1. 使用C++/Python API导入模型:通过代码定义网络结构,并载入模型weights的方式导入;

  2. 使用NvCaffeParser导入模型:导入时输入网络结构prototxt文件及caffemodel文件即可

Tensorflow

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

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

其他框架

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

TensorRT优化细节

网络模型在导入至TensorRT后会进行一系列的优化,主要优化内容如下图所示

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

以下图为例:

深度学习框架在做推理时,会对每一层调用多个/次功能函数。而由于这样的操作都是在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可以有效的优化网络结构、减少网络层数从而带来性能的提升。

Network Layers Layers after fusion
VGG19 43 27
Inception V3 309 113
ResNet-152 670 159

FP16 & INT 8精度校准

大多数的网络都是使用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在其使用期间设计分配显存来减少显存的占用,增加显存的复用率,从而避免了显存的过度开销以获得更快和更高效的推理性能。

优化结果如图所示

上图为基于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 Engine
from tensorrt.infer import LogSeverity
import 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 inference
    results.append(result)

TensorRT3带来的三个重大更新:

  1. TensorFlow Model Importer - 便捷的API用于导入TensorFLow训练的模型,优化并生成推理Engine。

  2. Python API - Python API用于进一步提高开发效率。

  3. Volta Tensor Core支持 - 带来相较于Tesla P100高达3.7倍的更快的推理性能。

TensorRT入门的更多相关文章

  1. Attention Mechanism in Computer Vision

    ​  前言 本文系统全面地介绍了Attention机制的不同类别,介绍了每个类别的原理.优缺点. 欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结.最新技术跟踪.经典论文解读.CV招聘信息. 概 ...

  2. CV技术指南免费版知识星球

    ​ 最近公众号的交流群满了,我们决定搞一个免费的知识星球,让大家在里面交流.以往都是我们写原创,大家阅读,读者之间没什么交流.与此同时,在CV技术指南交流群里,大部分问题都得到了很好地解决,但从来没有 ...

  3. YOLO系列梳理(三)YOLOv5

    ​  前言 YOLOv5 是在 YOLOv4 出来之后没多久就横空出世了.今天笔者介绍一下 YOLOv5 的相关知识.目前 YOLOv5 发布了新的版本,6.0版本.在这里,YOLOv5 也在5.0基 ...

  4. EdgeFormer: 向视觉 Transformer 学习,构建一个比 MobileViT 更好更快的卷积网络

    ​  前言 本文主要探究了轻量模型的设计.通过使用 Vision Transformer 的优势来改进卷积网络,从而获得更好的性能. 欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结.最新技术跟 ...

  5. NMS技术总结(NMS原理、多类别NMS、NMS的缺陷、NMS的改进思路、各种NMS方法)

    ​  前言  本文介绍了NMS的应用场合.基本原理.多类别NMS方法和实践代码.NMS的缺陷和改进思路.介绍了改进NMS的几种常用方法.提供了其它不常用的方法的链接. 本文很早以前发过,有个读者评论说 ...

  6. 从零搭建Pytorch模型教程(四)编写训练过程--参数解析

    ​  前言 训练过程主要是指编写train.py文件,其中包括参数的解析.训练日志的配置.设置随机数种子.classdataset的初始化.网络的初始化.学习率的设置.损失函数的设置.优化方式的设置. ...

  7. 基于TensorRT优化的Machine Translation

    基于TensorRT优化的Machine Translation 机器翻译系统用于将文本从一种语言翻译成另一种语言.递归神经网络(RNN)是机器翻译中最流行的深度学习解决方案之一. TensorRT机 ...

  8. Recommenders with TensorRT

    Recommenders with TensorRT 推荐系统用于向社交网络.媒体内容消费和电子商务平台的用户提供产品或媒体推荐.基于MLP的神经协作滤波器(NCF)推荐器使用一组完全连接或矩阵乘法层 ...

  9. NVIDIA TensorRT高性能深度学习推理

    NVIDIA TensorRT高性能深度学习推理 NVIDIA TensorRT 是用于高性能深度学习推理的 SDK.此 SDK 包含深度学习推理优化器和运行时环境,可为深度学习推理应用提供低延迟和高 ...

随机推荐

  1. 7L-双线链表实现

    链表是基本的数据结构,尤其双向链表在应用中最为常见,LinkedList 就实现了双向链表.今天我们一起手写一个双向链表. 文中涉及的代码可访问 GitHub:https://github.com/U ...

  2. "四号标题"组件:<h4> —— 快应用组件库H-UI

     <import name="h4" src="../Common/ui/h-ui/text/c_h4"></import> < ...

  3. idea打包报错Cleaning up unclosed ZipFile for archive D:\m2\commons-beanutils\commons-beanutils\1.9.2\...

    关于idea的打包报错:Cleaning up unclosed ZipFile for archive D:\m2\commons-beanutils\commons-beanutils\1.9.2 ...

  4. 通过GSM模块发送经纬度求救信息。

    本博客作为实验笔记,仅供学习交流.(转载请注明出处) 本实验通过GSM模块:SIM900a,实现向特定手机发送sos求救信号,并且利用GPS模块:微科VK2828U7G5LF,将经纬度信息同时发送到手 ...

  5. HTTPS工作流程

    HTTPS工作流程 RSA算法 RSA的密钥分成两个部分: PublicKey 加密数据 验证签名 不能解密 任何人都可以获得 Private Key 数据签名(摘要算法) 解密 加密(不用此功能) ...

  6. Camunda 流程引擎的一种 Adapter 层实现

    上一篇说明了选择 Camunda 的理由.这一篇说明如何实现适配层. 当前还没有专门写一篇对 Camunda 各个功能的详细介绍.如果要获得比较直观的感受,可以下载 Modeler 或者使用在线版的 ...

  7. 新时代前端必备神器 Snapjs之弹动效果

    有人说不会 SVG 的前端开发者不叫开发者,而叫爱好者.前端不光是 Angularjs 了,这时候再不学 SVG 就晚了!(如果你只会 jQuery 就当我没说...)这里我就给大家分享一个前几天在别 ...

  8. matlab计算LZ复杂度

    我这个计算得14通道,每个通道截取3000个数据得复杂度,最后将计算得出得数据存储到本地txt文档中 function LZC(data) % 计算一维信号的复杂度 % data时间序列 % lzc: ...

  9. [转]sql二次注入

    01 二次注入原理 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入.防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据 ...

  10. PHP代码审计理解(三)---EMLOG某插件文件写入

    此漏洞存在于emlog下的某个插件---友言社会化评论1.3. 我们可以看到, uyan.php 文件在判断权限之前就可以接收uid参数.并且uid未被安全过滤即写入到了$uyan_code中. 我们 ...