https://blog.tensorflowcn.cn/2018/04/speed-up-tensorflow-inference-on-gpus-tensorRT.html
https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg89ciEGdSKLRCQoeHv3mCqvnzV3GSh4pW9u3DJuHVC_a_Gb4wWEJgIEEE9mU6OIhLIhyphenhypheng49vzjjQ5QbPXjZPy5AcsAYEaQFLTtQRaQkJcT61CHGugg3QjogKIBYvVfzYnKtskD2_AZ-G8/s1600/fig1.png
作者:Siddharth Sharma - NVIDIA 技术产品营销经理;
Sami Kama - NVIDIA 深度学习开发技术专家;
Julie Bernauer - NVIDIA 追踪工程解决方案架构师;
Laurence Moroney - Google 开发者倡导者
概述
TensorFlow 仍然是当今最流行的深度学习框架,拥有全球数万用户。NVIDIA® TensorRT™ 是一个深度学习平台,它优化神经网络模型并加速在数据中心、嵌入式和汽车设备中运行的 GPU 加速平台上的推理。我们对 TensorFlow 与 TensorRT 的集成感到兴奋,这似乎是自然而然的,特别是 NVIDIA 提供了非常适合加速 TensorFlow 的平台。这使 TensorFlow 用户能够以极高的推理性能和使用 TensorRT 时几乎透明的工作流程来使用。
|
图 1. TensorRT 优化经过训练的神经网络模型,以生成可供部署的运行时推理引擎。 |
TensorRT 对神经网络图执行几个重要的转换和优化(图 2)。首先,消除具有未使用的输出的层,以避免不必要的计算。接下来,在可能的情况下,卷积、偏置和 ReLU 层融合形成单个层。另一个转换是水平层融合或层聚合,以及将聚合层划分为各自输出所需的划分。水平层融合通过将采用相同源张量并使用类似参数应用相同操作的层组合在一起来提高性能。请注意,这些图优化不会改变图中底层的计算:相反,它们旨在重构图以更快、更有效地执行操作。
|
图 2 (a):具有多个卷积和激活层的示例卷积神经网络。 (b) TensorRT 的垂直和水平层融合以及层消除优化简化了 GoogLeNet Inception 模块图,减少了计算量和内存开销。 |
如果您之前在 TensorFlow 模型中使用过 TensorRT,您就会知道应用 TensorRT 优化过去需要导出经过训练的 TensorFlow 图。您还需要手动导入某些不支持的 TensorFlow 层,然后在 TensorRT 中运行整个图。对于大多数情况,您不再需要这样做。在新的工作流程中,您可以使用简单的 API 从 TensorFlow 内部应用强大的 FP16 和 INT8 优化,使用 TensorRT。现有的 TensorFlow 程序只需要添加几行新代码即可应用这些优化。
对于 ResNet-50 基准的低延迟运行,TensorRT 将 TensorFlow 推理速度提高了 8 倍。这些性能改进只需要添加几行代码,并且适用于 TensorFlow 1.7 版本及更高版本。在本文中,我们将介绍新的工作流程和 API,以帮助您开始使用它。
将 TensorRT 优化应用于 TensorFlow 图
将 TensorRT 添加到 TensorFlow 推理工作流程中涉及一个额外的步骤,如图 3 所示。在此步骤(以绿色突出显示)中,TensorRT 从冻结的 TensorFlow 图构建一个优化的推理图。
|
图 3:在 TensorFlow 中使用 TensorRT 时的工作流程图 |
为此,TensorRT 获取冻结的 TensorFlow 图并解析它以选择可以优化的子图。然后,它对子图应用优化并将它们替换为原始 TensorFlow 图中的 TensorRT 节点,同时保持其余图不变。在推理期间,TensorFlow 执行整个图,调用 TensorRT 来运行 TensorRT 优化的节点。使用这种方法,开发人员可以继续使用灵活的 TensorFlow 功能集,并使用 TensorRT 的优化。
让我们看一个包含三个段 A、B 和 C 的图的示例。TensorRT 优化段 B,然后用单个节点替换它。在推理期间,TensorFlow 执行 A,调用 TensorRT 执行 B,然后 TensorFlow 执行 C。从用户的角度来看,您继续像以前一样在 TensorFlow 中工作。
TensorRT 在 TensorFlow 图中优化尽可能大的子图。子图中的计算量越大,从 TensorRT 获得的好处就越大。您希望大多数图被优化并用最少数量的 TensorRT 节点替换,以获得最佳性能。根据图中的操作,最终图可能包含多个 TensorRT 节点。使用 TensorFlow API,您可以指定子图中节点的最小数量,以便将其转换为 TensorRT 节点。任何节点数量少于指定设置数量的子图都不会转换为 TensorRT 引擎,即使它与 TensorRT 兼容。这对于包含由不兼容节点分隔的小型兼容子图的模型很有用,从而导致微小的 TensorRT 引擎。
让我们看一下如何更详细地实现工作流程。
使用新的 TensorFlow API
新的 TensorFlow API 使得只需添加几行新代码即可轻松实现 TensorRT 优化。首先,指定 TensorFlow 允许使用的可用 GPU 内存的比例,剩余的内存可用于 TensorRT 引擎。这可以通过
GPUOptions
函数的新
per_process_gpu_memory_fraction
参数来完成。此参数需要在 TensorFlow-TensorRT 进程首次启动时设置。例如,将
per_process_gpu_memory_fraction
设置为 0.67 将为 TensorFlow 分配 67% 的 GPU 内存,将剩余的三分之一分配给 TensorRT 引擎。
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction =
0 < memory_for_TensorFlow < 1)
下一步是让 TensorRT 分析 TensorFlow 图,应用优化并将子图替换为 TensorRT 节点。您可以使用新的
create_inference_graph 函数
将 TensorRT 优化应用于冻结的图。此函数使用冻结的 TensorFlow 图作为输入,然后返回一个具有 TensorRT 节点的优化图,如下面的代码片段所示
trt_graph = trt.create_inference_graph(
input_graph_def = frozen_graph_def,
outputs = output_node_name,
max_batch_size=batch_size,
max_workspace_size_bytes=workspace_size,
precision_mode=precision,
minimum_segment_size=3)
让我们看一下函数的参数
input_graph_def
:冻结的 TensorFlow 图
outputs
:输出节点名称的字符串列表,例如 [“
resnet_v1_50/predictions/Reshape_1
”]
max_batch_size
:整数,输入批次的大小,例如 16
max_workspace_size_bytes
:整数,可用于 TensorRT 的最大 GPU 内存大小
precision_mode
:字符串,允许的值“FP32”、“FP16”或“INT8”
minimum_segment_size
:整数(默认值为 3),控制要创建 TensorRT 引擎的子图中节点的最小数量
per_process_gpu_memory_fraction
和
max_workspace_size_bytes
参数应一起使用,将 TensorFlow 和 TensorRT 之间可用的 GPU 内存进行划分,以提供最佳的整体应用程序性能。为了最大限度地提高推理性能,您可能希望为 TensorRT 提供略多于其所需的内存,并将剩余内存分配给 TensorFlow。例如,如果您将
per_process_gpu_memory_fraction
参数设置为 (12–4) / 12 = 0.67,那么对于 12GB GPU,将
max_workspace_size_bytes 参数设置为 4000000000 将为 TensorRT 引擎分配大约 4GB。再次,找到最优的内存分配取决于应用程序,可能需要一些迭代。
使用 TensorBoard 可视化优化后的图
TensorBoard 使我们能够在 TensorBoard 中可视化 ResNet-50 节点图在应用 TensorRT 优化后的变化。图 4 显示 TensorRT 优化了几乎整个图,用名为“
my_trt_op0”的单个节点(以红色突出显示)替换它。根据模型中的层和操作,TensorRT 节点会由于优化而替换模型的部分内容。名为“conv1”的框实际上不是卷积层;它实际上是从 NHWC 到 NCHW 的转置操作。
|
图 4. (a) TensorBoard 中的 ResNet-50 图 (b) 应用 TensorRT 优化后,子图被 TensorRT 节点替换的 ResNet-50。 |
在 Volta GPU 上使用 Tensor Core
与 FP32 或 FP64 相比,使用半精度(也称为 FP16)算术会减少神经网络的内存使用量。FP16 使得能够部署更大的网络,同时比 FP32 或 FP64 占用更少的时间。NVIDIA 的 Volta 架构包含称为 Tensor Core 的硬件矩阵数学加速器。Tensor Core 提供一个 4x4x4 矩阵处理阵列,执行操作
D =
A * B + C,其中
A、B、
C 和
D 是 4×4 矩阵。图 5 显示了它是如何工作的。矩阵乘法输入
A 和
B 是 FP16 矩阵,而累加矩阵
C 和
D 可以是 FP16 或 FP32 矩阵。
|
图 5:Tensor Core 上的矩阵处理操作 |
在使用 FP16 数学进行推理时,TensorRT 会在检测到硬件 Tensor Core 时自动使用它们。Tensor Core 在 NVIDIA Tesla V100 上的峰值性能比双精度 (FP64) 快大约一个数量级,而吞吐量提高了比单精度 (FP32) 快 4 倍。只需将“FP16”用作
create_inference_graph
函数中
precision_mode
参数的值,即可启用半精度,如下所示。
getNetwork()
是一个辅助函数,它从 protobuf 文件读取冻结的网络,并返回网络的
tf.GraphDef()
。
trt_graph = trt.create_inference_graph(
getNetwork(network_file_name),
outputs,
max_batch_size=batch_size,
max_workspace_size_bytes=workspace_size,
precision_mode=”FP16")
图 6 显示 ResNet-50 在使用 NVIDIA Volta Tensor Core 的 TensorFlow-TensorRT 集成下,以 7 毫秒的延迟执行速度快 8 倍,而仅在同一硬件上运行 TensorFlow 则不然。
|
图 6:ResNet-50 推理吞吐量性能 |
使用 INT8 精度进行推理
使用 INT8 精度进行推理可以进一步提高计算速度,并对带宽的要求降低。减少的动态范围使得表示神经网络的权重和激活变得具有挑战性。
TensorRT 提供了将单精度(FP32)和半精度(FP16)训练的模型转换为 INT8 量化部署的能力,同时最大程度地减少精度损失。将模型转换为 INT8 部署需要在应用之前描述的 TensorRT 优化之前校准训练的 FP32 模型。工作流程更改为在创建 TensorRT 优化的推理图之前加入一个校准步骤,如图 7 所示。
|
图 7. 包含 INT8 推理的工作流程 |
首先使用
create_inference_graph
函数,将
precision_mode
参数设置为“
INT8”来校准模型。该函数的输出是一个准备校准的冻结 TensorFlow 图。
trt_graph = trt.create_inference_graph(
getNetwork(network_file_name),
outputs,
max_batch_size=batch_size,
max_workspace_size_bytes=workspace_size,
precision_mode=”INT8")
现在使用校准数据运行校准图。TensorRT 使用节点数据的分布来量化节点的权重。至关重要的是,您使用的数据要与生产中问题数据集的分布密切相关。建议在首次使用 INT8 校准的模型时检查推理过程中是否出现错误累积。
minimum_segment_size
参数可以帮助调整优化后的图以最大程度地减少量化误差。使用
minimum_segment_size,
可以更改优化后的 INT8 引擎中的最小节点数量,以更改最终优化后的图以微调结果精度。
在校准数据上执行图之后,使用
calib_graph_to_infer_graph
函数将 TensorRT 优化应用于校准图。此函数还会用针对 INT8 优化的 TensorRT 节点替换 TensorFlow 子图。该函数的输出是一个冻结的 TensorFlow 图,可以像往常一样用于推理。
trt_graph=trt.calib_graph_to_infer_graph(calibGraph)
只需这两个命令即可使用您的 TensorFlow 模型启用 INT8 精度推理。
如果您想查看此处显示的示例,请查看运行这些示例所需的代码,网址为:
https://developer.download.nvidia.com/devblogs/tftrt_sample.tar.xz
可用性
我们预计,将 TensorRT 与 TensorFlow 集成将使用 NVIDIA GPU 时实现最高性能,同时保持 TensorFlow 的易用性和灵活性。NVIDIA 继续与 Google TensorFlow 团队密切合作,以进一步增强这些集成功能。开发人员将自动从更新中受益,因为 TensorRT 支持更多网络,而无需更改现有代码。
有关如何立即开始的说明,请访问:
https://tensorflowcn.cn/install/install_linux
在不久的将来,我们预计标准的 pip 安装过程也能正常工作。敬请期待!
我们相信,在使用 GPU 时,将 TensorRT 与 TensorFlow 集成将为您带来巨大的好处。您可以在 TensorFlow 网站上找到更多信息,网址为:
https://tensorflowcn.cn/.
有关 TensorRT 的更多信息,请访问 NVIDIA 的 TensorRT 页面:
https://developer.nvidia.com/tensorrt.