前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TensorRT模型加速部署方案解析(视频/案例讲解)

TensorRT模型加速部署方案解析(视频/案例讲解)

作者头像
机器学习AI算法工程
发布2021-10-27 11:18:13
3.2K0
发布2021-10-27 11:18:13
举报
向AI转型的程序员都关注了这个号👇👇👇

机器学习AI算法工程 公众号:datayx

1、介绍tensorRT,和本课程、以及涉及的框架

2、介绍tensorRT驾驭的几种方案,以及推荐框架

3、正确导出onnx并在c++中使用

4、动态batch和动态宽高的实现方案

5、实现一个插件

6、关于封装

7、yolov5案例

8、retinaface案例

9、高性能低耦合

10、便捷性

tensorRT,nvidia发布的dnn推理引擎,是针对nvidia系列硬件进行优化加速,实现最大程度的利用GPU资源,提升推理性能

tensorRT是业内nvidia系列产品部署落地时的最佳选择

这个课程主要围绕着https://github.com/shouxieai/tensorRT_cpp提供的方案开展讨论,使得能够使用、部署起来

该教程,讲驾驭tensorRT,实现从模型导出,到c++/python推理加速,再到高性能、低耦合、有效、便捷的工程落地方案

以最终可用、好用为出发点

需要的知识点:

1、对深度学习的认识,CV相关知识,PyTorch

2、ONNX的认识,Netron工具的简单使用

3、C++和python能力

4、一定程度的cuda能力,了解tensorRT

课程内容:

1、如何正确的导出onnx

2、如何在c++中使用起来

3、动态batch,和动态宽高的处理方式

4、实现一个自定义插件

5、c++中推理实现高性能低耦合的方法

项目代码,视频讲解,PPT 获取方式:

关注微信公众号 datayx 然后回复 trt 即可获取。

驾驭TensorRT的方案介绍

TensorRT提供基于C++接口的构建模型方案

TensorRT-8.0.1.6/samples/sampleMNISTAPI/sampleMNISTAPI.cpp

以C++接口为主,进而提供了python的接口

TensorRT-8.0.1.6/samples/python/engine_refit_mnist/sample.py

基于tensorRT的发布,又有人在之上做了工作

repo1,https://github.com/wang-xinyu/tensorrtx

为每个模型写硬代码

repo2,https://github.com/NVIDIA-AI-IOT/torch2trt

为每个算子写Converter,反射Module.forward捕获输入输出和图结构

repo3(推荐方案),https://github.com/shouxieai/tensorRT_cpp

基于ONNX路线,提供C++、Python接口,深度定制ONNXParser,低耦合封装,实现常用模型YoloX、YoloV5、RetinaFace、Arcface、SCRFD、DeepSORT

算子由官方维护,模型直接导出

  • C++接口,YoloX三行代码
  • Python接口

如何正确的导出onnx

1.对于任何用到shape、size返回值的参数时,例如:tensor.view(tensor.size(0),-1)这类操作,避免直接使用tensor.size的返回值,而是加上int转换,tensor.view(int(tensor.size(0)), -1)

2.对于nn.Upsample或nn.functional.interpolate函数,使用scale_factor指定倍率,而不是使用size参数指定大小

3.对于reshape、view操作时,-1的指定请放到batch维度。其他维度可以计算出来即可。batch维度禁止指定为大于-1的明确数字

4.torch.onnx.export指定dynamic_axes参数,并且只指定batch维度。我们只需要动态batch,相对动态的宽高有其他方案

5.使用opset_version=11,不要低于11

6.避免使用inplace操作,例如y[…,0:2] = y[…, 0:2] * 2 - 0.5

7.掌握了这些,就可以保证后面各种情况的顺利了●

这些做法的必要性体现在,简化过程的复杂度,去掉gather、shape类的节点,很多时候,部分不这么改看似也是可以但是需求复杂后,依旧存在各类问题。按照说的这么修改,基本总能成。

实现一个自定义插件

流程简介:

导出环节:

1.对需要插件的layer,写一个类A,继承自torch.autograd.Function2.对这个类A增加symbolic的静态方法,其中返回g.op(),名称给Plugin,name_s为插件名称,info可以带上string类型信息3.对这个类A增加forward的静态方法,使得其可以被pytorch正常推理,此时的forward内的任何操作不会被跟踪并记录到onnx中。通常直接返回个对等大小和数量的tensor即可,不一定要完全实现功能4.实现一个OP的类,继承自nn.Module,在OP.forward中调用A.apply5.正常使用OP集成到模型中即可●

编译/推理环节:

1.在src/tensorRT/onnxplugin/plugins中写cu和hpp文件,参照Hswish2.实现类继承自TRTPlugin,

a. new_config用于返回自定义config类并进行配置

b. getOutputDimensions返回layer处理后的tensor大小

c. enqueue实现具体推理工作

关于封装

Tenosr封装

  1. CPU/GPU内存自动分配释放,内存复用
  2. CPU/GPU之间自动内存复制
  3. 计算维度的偏移量

Builder封装

  1. 模型编译接口
  2. Int8 Calibrator数据处理
  3. 插件处理,自定义插件支持
  4. 特殊处理,reshape钩子
  5. 定制onnx的输入节点shape

Infer封装

1.抽象input和output关系,避免手动去操作binding

降低tensorRT使用门槛、和集成难度,避免重复代码,关注业务逻辑,而非复杂的细节。因此做了封装

1、Tensor类,实现张量的内存管理、维度管理、偏移量计算、cpu/gpu相互自动拷贝。避免手动管理内存、计算偏移量

2、Infer类,实现tensorRT引擎的推理管理,自动关联引擎的输入、输出,或者名称映射,管理上下文,插件

3、Builder,实现onnx到引擎转换的封装,int8封装,少数几行代码实现需求

4、plugin,封装插件的细节、序列化、反序列化、creator、tensor和weight等,只需要关注具体推理部分,避免面临大量复杂情况

YoloV5案例

https://github.com/ultralytics/YOLOv5

Retinaface案例

https://github.com/biubug6/Pytorch_Retinaface

高性能的注意点:

单模型推理时的性能问题:

1、尽量使得GPU高密集度运行,避免出现CPU、GPU相互交换运行

2、尽可能使tensorRT运行多个batch 数据。与第一点相合

3、预处理尽量cuda化,例如图像需要做normalize、reisze、warpaffine、bgr2rgb等,在这里,采用cuda核实现warpaffine+normalize等操作,集中在一起性能好

4、后处理尽量cuda化,例如decode、nms等。在这里用cuda核实现了decode和nms

5、善于使用cudaStream,将操作加入流中,采用异步操作避免等待

6、内存复用

系统级别的性能问题:

1、如何实现尽可能让单模型使用多batch,此时future、promise就是很好的工具

2、时序图要尽可能优化,分析并绘制出来,不必的等待应该消除,同样是promise、future带来的好处

3、尤其是图像读取和模型推理最常用的场景下,可以分析时序图,缓存一帧的结果,即可实现帧率的大幅提升

传统的队列方式,收集结果困难

例如:

1、image需要先给到yolo检测框得到box

2、image和box交给pose抠图识别关键点keys

3、keys、box绘制到image,并显示出来

如果串行时序图,效率低。如果队列,收集结果困难

推荐使用promise和future,未来给到结果

参照tensorRT/src/application/app_yolo/yolo.cpp的commit部分

低耦合:

隔离业务逻辑和tensorRT推理过程,分开调试,逻辑调试逻辑,推理调试推理,不应该耦合起来。对于高性能的处理,也应该在推理中实现,对使用者透明。最好的解决方案,即封装

参照tensorRT/src/application/app_yolo/yolo.cpp的commit部分

便捷性上讲,例如anchor base的模型,通常会需要计算anchor,需要储存xxx.onnx和xxx.anchor.txt,一起做编译推理。这样做常需要两个文件同时存在。其次,解码为框过程还比较繁琐

推荐的做法,例如yolov5做的,在导出onnx时,将输出与anchor做完操作后合并为一个(torch.cat)。此时模型与anchor信息融为一体,并且输出的结果就已经是计算好的box,只需要做nms即可完成解码。操作方便简单

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-10-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习AI算法工程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像识别
腾讯云图像识别基于深度学习等人工智能技术,提供车辆,物体及场景等检测和识别服务, 已上线产品子功能包含车辆识别,商品识别,宠物识别,文件封识别等,更多功能接口敬请期待。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档