TPAT : TensorRT Plugin Autogen Tool

Qian Qiu Tencent AI Lab
Meng Wang NVIDIA DevTech
作者信息未提供

目录

背景

ONNX

ONNX (Open Neural Network Exchange) 是一种开放的、用于机器学习模型的中间格式。
详情请见:https://github.com/onnx/onnx

ONNX生态系统
Page 3 展示了ONNX的生态系统,包括与PyTorch、Chainer、Caffe2、MXNet、Cognitive Toolkit、XGBoost、PaddlePaddle等各种框架的连接,以及在CPU、GPU、FPGA、ASIC等不同硬件上的部署。
更多信息可查阅:https://azure.microsoft.com/es-es/blog/onnx-runtime-for-inferencing-machine-learning-models-now-in-preview/

TensorRT

TensorRT 是最流行的GPU推理引擎,在将模型部署到TensorRT后可以显著加速。

TensorRT的问题:
* TensorRT无法完全覆盖所有的运算符。
* 当运算符不受支持或其性能不足时,需要手动编写插件。
* 编写插件需要GPU和CUDA编程知识和经验。

TensorRT优化流程
Page 4 展示了TensorRT的内部优化流程,包括层与张量融合、精度校准、内核自动生成、训练神经网络、动态张量内存和多流执行。

基于ONNX解析器的传统TensorRT工作流

传统TensorRT工作流
Page 5 描述了传统的TensorRT工作流:PyTorch/TensorFlow模型经过ONNX转换,然后由ONNX解析器处理。如果遇到不支持的运算符,需要手动编写插件(通常需要数天的工作量),之后通过trtexec工具部署到TensorRT。
* 编写插件是此工作流中最耗时的部分。
* 实现一个插件通常需要数天的工作量。

带有插件的TensorRT工作流

利用TensorRT ONNX解析器的回退(Fallback)机制:
* 实现TensorRT插件。
* 为插件构建一个独立的库。
* 预加载该库,ONNX解析器将自动尝试将不支持的层/操作作为插件导入(通过FallbackPluginImporter)。

优点与缺点:
* 优点:易于实现整个过程的自动化。
* 缺点:插件的定义必须与ONNX运算符保持一致,即名称、输入/输出。

TVM

TVM是一个编译器,它提供图级别和运算符级别的优化,以实现深度学习工作负载在不同硬件后端上的性能可移植性。
它提供了一个端到端的编译和优化堆栈,允许部署用高级框架指定的深度学习工作负载。

TVM工作流
Page 7 展示了TVM的工作流:从TF/PyTorch/ONNX等框架,通过Relay(高级IR)到TE(计算定义),再通过AutoTVM/AutoScheduler(自动调优模块)生成TE+Schedule(优化规范),最终生成TIR(低级IR)和机器码。
关键思想: 结合TensorRT和TVM工作流。
更多信息可查阅:https://tvm.apache.org/docs/tutorial/introduction.html#sphx-glr-tutorial-introduction-py

TPAT:TensorRT 插件自动生成工具

TPAT利用TVM的强大功能自动生成CUDA内核,然后自动填充TensorRT插件模板。

TPAT工作流
Page 9 描述了TPAT的工作流:PyTorch/TensorFlow模型经过ONNX转换,然后由ONNX解析器处理。TVM在此阶段介入,自动生成插件(耗时30-60分钟),之后通过trtexec工具部署到TensorRT。
使用TPAT的TensorRT工作流:
* 不再需要手动编写插件。
* TensorRT插件完全自动化生成。

TPAT亮点

TPAT架构

TPAT架构
Page 11 展示了TPAT的架构:
用户提供来自框架(如Tensorflow、PyTorch)的模型、运算符名称、ONNX模型和批次大小作为输入。这些输入进入TVM流程:ONNX模型转换为Relay,经过TE/TOPI、AutoScheduler和Best Schedule,最终到达TVM Runtime。TVM Runtime生成CUDA源代码。CUDA源代码用于填充插件模板,生成TensorRT插件。此插件通过trtexec工具加载到TensorRT引擎,最终实现TensorRT推理。

TPAT步骤

给定一个包含需要TensorRT插件的节点的ONNX模型:
1. 从ONNX到TVM Relay。
2. 从TVM到CUDA源代码。
3. 从TVM运行时到CUDA内核参数。
4. 自动填充TensorRT插件模板。
5. 修改ONNX图。
使用构建的插件将修改后的ONNX模型转换为TensorRT。

步骤1:从ONNX到TVM Relay

ONNX到TVM Relay的转换
Page 13 展示了一个示例图,其中input0经过MatMulCastOneHot等操作。其中MatMulCast等节点可以转换为Relay IR并生成CUDA源代码。特别指出OneHot节点需要TVM的自动调优。

步骤1:从ONNX到TVM Relay(解决方案)

解决方案: 将指定的ONNX节点提取为一个小的ONNX模型,然后将其转换为TVM。
ONNX graphsurgeon是一个很好的工具,可以隔离子模型并使此步骤自动化。

ONNX节点提取和转换
Page 14 进一步阐述了解决方案,通过ONNX graphsurgeon工具将需要自动调优的OneHot节点从主图中分离出来,形成一个独立的子模型,然后将该子模型转换为Relay IR并生成CUDA源代码。

步骤2:从TVM到CUDA源代码

TVM自动生成CUDA内核源代码。

从TVM到CUDA源代码
Page 15 再次展示了TVM的工作流,强调了从Relay(高级IR)经过一系列优化和调度后,最终生成机器码(其中包含了CUDA源代码)。

步骤3:从TVM运行时到CUDA核函数参数

TPAT: 从TVM运行时到CUDA核函数参数
TPAT: 从TVM运行时到CUDA核函数参数

复杂案例:一个ONNX节点 -> 多个CUDA核函数

TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数
TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数
EID 0 1 2 3 4 5
Size 131072 4 131072 4 4 3355432
Pointer inputs[0] workspace workspace +4 workspace +131076 workspace +131080 outputs[0]
Meaning input_0 depth intermediate variable on_value off_value output_0
TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数
TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数
EID_2 EID_0 EID_1
Host function workspace + 4 inputs[0] workspace
Device function T_where placeholder placeholder1
Meaning intermediate variable input_0 depth
TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数
TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数
EID_5 EID_2 EID_3 EID_4
Host function outputs[0] workspace+4 workspace+131076 workspace+131080
Device function T_one_hot placeholder placeholder1 placeholder2
Meaning output_0 intermediate variable on_value off_value
TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数
TPAT: 复杂案例:一个ONNX节点 -> 多个CUDA核函数

步骤4:自动填充TensorRT插件模板

from jinja2 import Template
template = Template('Hello {{ name }}!')
outputText = template.render(name='John')
print(outputText)
# Hello John!
TPAT: 第4步:自动填充TensorRT插件模板
TPAT: 第4步:自动填充TensorRT插件模板
TPAT: 第4步:自动填充TensorRT插件模板
TPAT: 第4步:自动填充TensorRT插件模板

步骤5:修改ONNX图

TPAT: 第5步:修改ONNX图
TPAT: 第5步:修改ONNX图

复杂案例:多个ONNX节点需要插件

TPAT: 复杂案例:多个ONNX节点需要插件
TPAT: 复杂案例:多个ONNX节点需要插件
TPAT: 复杂案例:多个ONNX节点需要插件
TPAT: 复杂案例:多个ONNX节点需要插件

子图自动生成

LayerNormalization子图自动生成

TPAT: LayerNormalization子图自动生成
TPAT: LayerNormalization子图自动生成

TPAT 示例

一个完整的 one_hot 操作到TensorRT引擎的TPAT流程示例,如下图所示(包含op name: one_hotbatch size: 256 的ONNX模型,经过Cast, OneHot, Reshape等操作)。

TPAT: 示例流程
TPAT: 示例流程

TPAT模块的工作流程如下:

  1. ONNX模型输入。
  2. 通过Relay and Autoscheduler进行优化。
  3. 生成CUDA Kernel
  4. 填充Plugin Template
  5. 生成TensorRT Plugin
  6. 最终由Trtexec tool生成TensorRT engine

下图展示了TPAT的工作流程示例,特别是如何将ONNX模型中的操作转换为优化的TensorRT插件,并包含了生成的CUDA内核代码片段,以及一个tvm_one_hot_enqueue函数的C++代码片段,说明了TPAT如何自动生成用于TensorRT插件的底层CUDA实现。

TPAT示例
TPAT示例

结果

与手写插件比较

该幻灯片展示了TPAT与手写插件在不同操作上的性能比较结果。实验设备为Nvidia Tesla T4。

结果:与手写插件比较
结果:与手写插件比较

主要结果如下:
* GatherNd 操作:对于 shape=(1, 128, 128, 224),手写插件耗时 180.0 ms,TPAT 耗时 127.0 ms,提升 1.4x。
* GatherNd 操作:对于 shape=(1, 158, 128, 128),手写插件耗时 21.1 ms,TPAT 耗时 17.5 ms,提升 1.2x。
* ScatterND-update 操作:对于 data=(32, 128, 128, 256),手写插件耗时 0.36 ms (ScatterND-kernel),TPAT 耗时 0.18 ms (ScatterND-kernel),提升 2.0x。
* ScatterND-Add 操作:对于 data=(32, 128, 128, 256),手写插件耗时 2.37 ms,TPAT 耗时 2.13 ms,提升 1.1x。
* OneHot 操作:对于 depth=16384,手写插件耗时 9.3 us,TPAT 耗时 11.6 us,性能比为 0.8x(即TPAT略慢)。

优化 TensorRT 算子

该幻灯片展示了TPAT对现有TensorRT算子的优化结果,对比了TensorRT 7.2.2.3与TPAT的性能。实验设备为Nvidia Tesla T4。

结果:优化 TensorRT 算子
结果:优化 TensorRT 算子

主要结果如下:
* Resize 操作:对于 NCHW(32, 32, 32, 44, 50) -> (32, 32, 176, 200),TensorRT 7.2.2.3 耗时 1.450 ms,TPAT 耗时 1.079 ms,提升 1.38x。
* Resize 操作:对于 NCHW(32, 64, 11, 12) -> (32, 64, 176, 200),TensorRT 7.2.2.3 耗时 2.759 ms,TPAT 耗时 2.171 ms,提升 1.27x。
* Reduce_max 操作:对于 input_shape=(256, 82, 128)output_shape=(256, 128),TensorRT 7.2.2.3 耗时 0.167 ms,TPAT 耗时 0.036 ms,提升 4.63x。

支持的算子

该幻灯片总结了TPAT支持的算子数量:
* TPAT 共支持 137 个算子。
* 其中有 17 个算子由 TPAT 支持,但 TensorRT 不支持。

下表列出了这些由 TPAT 支持但 TensorRT 不支持的算子:

结果:支持的算子
结果:支持的算子

表格中列出的算子包括:
* BitShift
* Compress
* ConcatFromSequence
* Einsum
* Hardmax
* IsInf
* MaxRoIPool
* MaxUnpool
* Mod
* NegativeLogLikelihoodLoss
* OneHot
* RandomNormal
* Reciprocal
* RoiAlign
* Shrink
* SoftmaxCrossEntropyLoss
* Xor

总结

本幻灯片对TPAT进行了总结,并展望了未来计划:
* TPAT(TensorRT Plugin Autogen Tool)消除了为不支持或效率低下的算子手动编写TensorRT插件的困扰。
* 它利用TVM的力量自动生成CUDA内核,并且是完全自动化的。
* 它基于TensorRT和TVM的ONNX工作流。
* TPAT即将开源。欢迎使用并提供反馈!

未来计划:
* 针对TensorRT的激进子图优化 (Radical Subgraph optimization for TensorRT)
* 动态形状支持 (Dynamic shape support)
* 半精度和INT8支持 (Half precision and INT8 support)

招聘信息

我们正在招聘!腾讯AI Lab深度学习编译器团队
联系方式:[email protected]