使用TensorRT部署TensorFlow模型
- 导入优化的训练模型用于生成推理引擎
这一步仅仅执行一次,在部署前。我们用TensorRF解析一个训练好的模型为指定的目标GPU平台优化想batch size,precision和workspace memory。这一步输出一个优化的推理执行引擎,我们序列化它到磁盘中的plan文件

- 部署生成的运行推理引擎用于推理
这是部署的一步。我们载入和序列化保存的plan文件创建一个TensorRT引擎对象,使用它在目标平台上通过新数据运行推理。
导入一个训练好的模型
对Caffe和TensorFlow用户TensorRT提供简单方便的Python和C++ API导入模型优化。
```Import TensorRT Modules
import tensorrt as trt import uff from tensorrt.parsers import uffparser G_LOGGER = trt.infer.ConsoleLogger(trt.infer.LogSeverity.INFO)
Load your newly created Tensorflow frozen model and convert it to UFF
uff_model = uff.from_tensorflow_frozen_model("keras_vgg19_frozen_graph.pb", ["dense_2/Softmax"])
UFF(Universal Framework Format),用于在优化前表示网络图的TensorRT内部表示,`from_tensorflow_frozen_model()`的第一个参数是冻结的训练好的模型这里我们用的模型是[Keras VGG19 model](https://keras.io/applications/#vgg19),第二个参数是输出层的名字。
上面的步骤输出的是一个代表被TensorRT解析的TensorFlow模型的UFF表示。通过给定uff解析及输入的维度和名称和输出层的名字。
Create a UFF parser to parse the UFF file created from your TF Frozen model
parser = uffparser.create_uff_parser() parser.register_input("input_1", (3,224,224),0) parser.register_output("dense_2/Softmax")
TensorRT支持的层:
- Convolution
- LSTM and GRU
- Activation: ReLU, tanh, sigmoid
- Pooling: max and average
- Scaling
- Element wise operations
- LRN
- Fully-connected
- SoftMax
- Deconvolution

另外TensorRT也提供了对自定义层的支持的API,自定义的层使用C++写的,利用高度优化的cuDNN和cuBLAS的
CUDA库,这样就能使用TensorRT按照上面的步骤推理了。[TensorRT documentation](http://docs.nvidia.com/deeplearning/sdk/tensorrt-user-guide/index.html#plugin_sample)有关于自定义层推理的介绍。
# TensorRT优化
当你导入模型进入TensorRT后,下一步称为构建阶段,当你优化模型用于执行的时候TensorRT可以执行一些优化,具体说明如图1,:
- 层和tensor的融合,消除无用的层
- FP16和INT8减少精度校准
- 指定目标的自动调整
- 高校的存储使用
构建阶段需要在指定平台上,如果是在Jetson TX2上运行需要在Jetson TX2上构建,同样如果在Tesla V100GPU的aws上运行则需要在Tesla V100上构建。
这一步仅仅执行一次,因此通常构建多个平台为之后使用它们序列化他们。你需要指定推理batch size GPU存储空间优化UFF,目标推理精度,如下:
Build your TensorRT inference engine
This step performs (1) Tensor fusion (2) Reduced precision
(3) Target autotuning (4) Tensor memory management
engine = trt.utils.uff_to_trt_engine(G_LOGGER, uff_model, parser, 1, 1<<20, trt.infer.DataType.FLOAT)
这里的`uff_model`是从TensorFlow frozen图创建的图,这里指定FP32推理batch size为1
1MB的空间。输出是一个优化的用于推理的运行引擎。
## 优化层个Tensor融合
TensorRT解析网络计算图寻找机会执行图优化,图优化不改变底层计算,只是重构图让图更快更高效的执行。

上图是GoogleNet结构。深度学习框架在推理的时候执行图,每层调用多个函数。因为每个操作在GPU上执行
转化为多CUDA内核函数启动,这些函数运行很快但是每层读写tensor开销和内核启动开销,结果却导致存储带宽限制个GPU资源没有充分使用。TensorRT通过
通过融合内核一起执行序列操作,层融合减少了内核启动避免了层间的反复读写,图4显示了convolution,bias和ReLU层的的多变量结合成单个内核CBR。这好比
三次到到超市买三种商品变成了一次到超市买三种商品。
TensorRT也识别曾共享相同的输入数据和卷积核大小,但是权重不同,相比于分开他们TensorRT容和他们成一个更宽的卷积核。正如上面的$1\times1$CBR层。
上图4通过预分配输出buffer写他们到一个strided fashine消除层的连接。
总之通过生成一个更小的,更快的,更高效的,有更少内核的图,减少推理延时,表格1显示了TensorRT的图优化对图像分类网络的信息。
|网络|层|融合后的层数|
|:---:|:-----:|:-----:|
|VGG19|43|27|
|Inception V3|309|113|
|ResNet-152|670|159|
## 优化FP16和INT8的精度标尺
多数深度学习框架在FP32上训练网络,当模型训练好后,因为推理的时候不要求梯度反向计算,可以使用FP16或者INT8推理,使用更低的精度导致更小的模型,更低的内存占用和延时,更高的吞吐量。
Tensor可以步数FP32,FP16和INT8模型,通过指定`uff_to_trt_engine`函数指定数据类型:
- 对于FP32,使用`trt.infer.DataType.FLOAT`
- 对于FP16和Volta GPU的FP16 Tensor Core,使用`trt.infer.DataType.HALF`
- 对于INT8推理,使用`trt.infer.DataType.INT8`
你可以看表2,INT8的动态范围远小于整个精度的动态范围。INT8可以代表256个不同的值。为了量化完整精度信息到INT8最小化损失,TensorRT必须执行吊顶决定如何最好的用8bit表示权重和激活。
标尺要求你提供TensorRT一个输入训练数据的样本。没有额外的调整或者重新训练模型,你不需要访问整个训练数据集。标尺是一个自动和和parameter-free的FP32到INT8的转换方法
|精度|动态范围|
|:---:|:---:|
|FP32|$$-3.4x10^{38}-+3.4x10^{38}$$|
|FP16|$$-65504-+65504$$|
|INT8|$$-128-+127$$|
## 优化3:内核自动调整
在优化阶段TensorRT也从上百个特别的内核函数中选择,手动调整优化参数的范围和目标平台。例如有一些不同的算法卷积,TensorRT将从库函数中选择实现传递给好的运行给目标GPU,输入数据的大小,卷积核的大小,tensor的层,batch size和其他参数。为了确保部署的模型对指定平台的执行和将要部署的神经网络一
样。
## 优化4:动态Tensor Memory
TensorRT通过为每个tensor设计的memory减少footprint的memory提高menory重用,避免menory分配消耗快速高效的执行。
# TensorRT优化执行结果
TensorRT优化的一些结果比在CPU和GPU上运行更快更高效,在图5,比较了在CPU,Tesla V100和Teslav100 TensorRT优化在ResNet-50上推理执行images/sec。
对比Tesla V100和CPU,TensorRT你可以达到40x倍的推理,在Volta GPU上TensoFlow模型在7ms实时延时要求下达到了18x的提速。

# 序列化的TensorRT引擎
TensorRT优化阶段的输出是一个运行的推理引擎,可以被序列化到磁盘。序列文件称为`plan`文件,包含了序列数据和用于执行网络的运行引擎。称为plan文件因为不仅包含了权重,而且包含网络执行的内核调度。它也包含了一些应用能查看的网络信息为了界定如何绑定输入和输出buffer。使用TensorRT的`writer_engine+to_file()`函数执行序列化。
Serialize TensorRT engine to a file for when you are ready to deploy your model.
trt.utils.write_engine_to_file("keras_vgg19_b1_FP32.engine", engine.serialize())
# TensorRT运行时推理
你现在准备好通过TensorRT部署你的应用。为了快速处理,你需要导入训练好的TensorFlow模型到TensorRT,执行一些优化生成运行时引擎。你序列化引擎到一个plan文件。你执行玩所有的步骤,就差部署了。
下一步是载入序列化的模型到你的运行环境在新的数据上执行推理。为了展示这一步,我们将使用TensorFlow Lite API.这是一个高度首相的推理,处理一些标准的任务创建logger,从plan文件deserializing创建运行,分配GPU存储。在推理的时候,它也管理数据迁移,因此你仅仅创建一个引擎开始处理数据。更多dine-grained控制,你可以使用标准的C++ API。
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) ```
结论
TensorRT处理了三个关键的深度学习部署挑战
- 高吞吐低延时 通过层融合,精度标定,目标自动调比CPU整加速推理40x,比在7ms实时延时下TensorFlow模型在Volta GPU上有18x提升
- 电源效率 制定目标优化动态存储管理,TensorRT提高电源效率,低的电源效率运行更长数据中心更凉快
- 部署级解决 TensorRT为了部署而设计。介个TensorRT你部署一个清凉的运行不需要框架依赖和开销。结合Python和C++库TensorRT对于数据科学家和研究员训练模型,部署构建产品都很容易。