TensorRT 3:更快的TensorFlow推理和Volta支持
TensorRT 3: Faster TensorFlow Inference and Volta Support
英伟达TensorRT 是一个高性能的深度学习推理优化器和运行时,为深度学习应用程序提供低延迟、高吞吐量的推理。NVIDIA去年发布了TensorRT,其目标是加速产品部署的深度学习推理。
Figure 1. TensorRT optimizes trained neural network models to produce adeployment-ready runtime inference engine.
在这篇文章中,我们将介绍TensorRT 3,它比以前的版本提高了性能,并且包含了新的特性,使其更易于使用。TensorRT 3的主要亮点包括:
TensorFlow模型导入器:从TensorFlow训练的模型导入、优化和生成推理运行时引擎的方便API;
Python API:一个易于使用的Python接口,用于提高生产率;
Volta Tensor核心支持:与Tesla P100 GPU相比,在Tesla V100上提供高达3.7倍的更快推理性能。
让我们使用一个代码示例深入了解TensorRT工作流。我们将介绍如何将经过训练的模型导入TensorRT,优化它们并生成运行时推理引擎,这些引擎可以序列化到磁盘进行部署。最后,我们将看到如何加载序列化的运行时引擎并在生产应用程序中运行快速高效的推理。但首先,让我们回顾一下部署推理的一些挑战,看看为什么推理需要一个专用的解决方案。
Why Does Inference Need a Dedicated Solution?
作为数字产品和服务的消费者,我们每天都与一些人工智能服务进行交互,例如语音识别、语言翻译、图像识别和视频字幕生成等。在幕后,神经网络计算每个查询的结果。这个步骤通常被称为“推断”:新数据通过经过训练的神经网络来生成结果。在传统的机器学习文献中,它有时也被称为“预测”或“评分”。
这种神经网络通常运行在云中的web服务中,它同时接收来自数千或数百万用户的新请求,计算每个请求的推理计算,并将结果返回给用户。为了提供良好的用户体验,所有这些都必须在较小的延迟预算下实现,包括网络延迟、神经网络执行和基于生产环境的其他延迟。
类似地,如果AI应用程序运行在设备上,例如在执行实时避免碰撞的自主车辆中或在进行实时路径规划决策的无人机中,则延迟对于车辆安全而言变得至关重要。功率效率同样重要,因为这些车辆在充电或加油之间可能需要几天、几周或几个月。
今天,应用程序开发人员和领域专家使用GPU加速的深度学习框架,如Caffe、TensorFlow或PyTorch来训练深度神经网络来解决特定于应用程序的任务。这些框架通过探索网络设计、执行模型评估和诊断以及使用新数据重新训练模型,为他们提供了原型解决方案的灵活性。
一旦对模型进行了训练,开发人员通常会遵循以下部署方法之一。
使用诸如Caffe、TensorFlow或其他的训练框架进行生产推理。
直接使用GPU加速的cuDNN和cuBLAS库在内部构建自定义部署解决方案,以最小化框架开销。
使用训练框架或构建自定义部署解决方案以进行仅限CPU的推断。
这些部署选项通常无法满足关键的推断需求,例如数百万用户的可伸缩性、同时处理多个输入的能力,或者快速高效地交付结果的能力。
更正式地说,关键要求包括:
高吞吐量:部署的模型必须处理大量数据才能为大量用户服务。对可用资源的低效使用导致云或数据中心成本增加,以及与服务较少用户相关的机会成本。
低响应时间:移动设备上的语音识别和汽车碰撞检测系统等应用要求在严格的低延迟阈值下获得结果。无法在这些阈值下交付结果会对应用程序的用户体验产生负面影响,或者可能会危及汽车驾驶员的安全。
节能:对于部署在数据中心和低功耗嵌入式设备,节能至关重要。高功耗会增加成本,并可能使嵌入式部署解决方案变得棘手。
部署级解决方案:部署环境要求部署的软件以最小的依赖性实现可靠和轻量级。为模型构建、训练和原型设计的深度学习框架包括额外的包和依赖项,这些包和依赖项会带来不必要的开销。
如果你是人工智能应用程序的开发人员,你可能会涉及到一些或所有这些挑战与深入学习部署。NVIDIA TensorRT通过优化经过训练的神经网络来生成部署就绪的推理引擎,从而最大限度地提高GPU推理性能和功耗效率,从而解决了这些部署难题。TensorRT以最小的依赖性运行在每个GPU平台上,从数据中心GPU(如P4和V100)到自主驱动和嵌入式平台(如驱动器PX2和Jetson TX2)。
有关TensorRT和NVIDIA GPU如何提供高性能和高效的推理,从而显著节省数据中心的成本和边缘的功耗的更多信息,请参阅以下技术白皮书:NVIDIA AI推理技术概述。
Example: Deploying a TensorFlow model with TensorRT
虽然为了完整起见,本文涵盖了TensorRT的许多基础知识,但是您可以回顾前面的文章,使用NVIDIA TensorRT部署深层神经网络,了解更多细节。
TensorRT 3更快、更容易使用,并且引入了一些新特性,我们将在下面的代码示例中回顾这些特性。GitHub上提供了本例中的Jupyter(iPython)笔记本。
这个简单的例子演示了导入和优化一个经过训练的TensorFlow神经网络并将其部署为TensorRT运行时引擎所需的步骤。该示例包括两个不同的步骤:
Import and optimize trained models to generate inference engines导入和优化训练模型生成推理机
在部署之前,我们只执行此步骤一次。我们使用TensorRT解析一个经过训练的模型,并对目标部署GPU的批大小、精度和工作区内存等指定参数执行优化。这个步骤的输出是一个优化的推理执行引擎,我们将磁盘上的一个名为计划文件的文件序列化。
Deploy generated runtime inference engine for inference
这是部署步骤。我们加载并反序列化保存的计划文件以创建TensorRT引擎对象,并使用它在目标部署平台上对新数据运行推断。
Importing a trained model
有几个深度学习框架,每个框架都有自己的神经网络结构定义和训练的模型文件格式。对于CAFE和TunSoFrices用户,TunSRRT提供简单方便的Python和C++ API来导入模型进行优化。
Figure 2. TensorRT provides model importers for Caffe and TensorFlow. Other framework models can be imported using the Network Definition API.
然而,一些开源和商业框架,以及专有的内部开发工具,都有自己的网络定义格式。您可以使用TensorRT的网络定义API来指定网络描述(使用C++或Python API),并将其加载到TensorRT中以进行优化。图2显示了将经过训练的模型放入TensorRT的两种不同方法。
不管您选择什么方法,一旦导入了模型,TensorRT就会执行与图2中所示相同的一组模型优化。
我们将从导入必要的python包开始,并调用函数导入TensorFlow模型。这里我们假设您已经安装了TensorRT 3.0,并且有一个经过训练的TensorFlow模型,您已经使用TensorFlow freeze_graph 工具将其导出为冻结模型(.pb文件)。
这个例子使用了TensorRT3的Python API,但是你可以使用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代表通用框架格式,这是TensorRT的内部格式,用于在运行优化之前表示网络图。from_tensorflow_frozen_model()的第一个参数是冻结训练模型。在本例中,我们使用的是Keras VGG19模型。第二个参数是输出层名称。
上述步骤的输出是TensorFlow模型的UFF图表示,该模型可以被TensorRT解析。我们通过提供输入层的名称和维度(CHW格式)以及输出层的名称来配置下面的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")
A Note on TensorRT Supported Layers
如今,神经网络设计的许多创新都围绕着新颖的定制层的发明展开。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++定义,以便于使用高度优化的CUDA库,如CUDNN和CUBLAS。TensorRT将在进行推理时使用您提供的自定义层实现,如图3所示。
Figure 3. Custom layers can be integrated into the TensorRT runtime as plugins.
本例中VGG19网络中的所有层都由TensorRT支持,因此我们不演示编写插件的过程。有关代码示例和编写自定义层的详细信息,请参阅TensorRT文档。
TensorRT Optimizations
将模型导入TensorRT后,下一步称为构建阶段,在该阶段,您可以优化模型以执行运行时。TensorRT可以执行许多优化,如图1所示:
层与张量融合及未利用层的消除;
FP16和INT8精度降低校准;
目标特定自动调谐;
高效的内存重用
构建阶段需要在目标部署GPU平台上运行。例如,如果应用程序要在Jetson TX2上运行,则需要在Jetson TX2上执行生成,同样,如果推理服务将在带有Tesla V100 gpu的AWS P3实例上的云中运行,则生成阶段需要在带有Tesla V100的系统上运行。
这个步骤只执行一次,所以典型的应用程序只构建一个或多个引擎,然后将它们序列化以供以后使用。
TensorRT会在引擎盖下为您自动执行这些优化。您只需要指定要优化的UFF推理图、推理批大小、工作区GPU内存量(用于CUDA内核暂存空间)和目标推理精度,如下代码所示。
# 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_模型是从Tensorflow冻结图创建的,选项指定FP32推断,批大小为1和1MB的暂存空间。此步骤的输出是一个优化的运行时引擎,可以进行推理。
让我们仔细看看在优化步骤中引擎下面发生了什么。
Optimization 1: Layer & Tensor Fusion
TensorRT解析网络计算图并寻找执行图优化的机会。这些图优化不会改变图中的底层计算:相反,它们希望重新构造图以更快、更高效地执行操作。
为了便于说明,图4显示了神经网络图的一部分。专家读者可能会认为这是2014年赢得ImageNet大赛的谷歌架构的“初始”模块。
Figure 4. TensorRT’s vertical and horizontal layer fusion and layer elimination optimizations simplify the GoogLeNet Inception module graph, reducing computation and memory overhead.
当一个深度学习框架在推理过程中执行这个图时,它会对每个层进行多个函数调用。由于每个操作都是在GPU上执行的,这就意味着要启动多个CUDA内核。相对于内核启动开销和读写每个层的张量数据的成本,内核计算通常非常快。这会导致内存带宽瓶颈和可用GPU资源利用率不足。
TensorRT通过垂直融合内核来实现这一点,以便一起执行顺序操作。这种层融合减少了内核的启动,避免了在层之间写入和读取内存。在图4左侧的网络中,各种大小的卷积层、偏置层和ReLU层可以组合成一个称为CBR的内核,如图4右侧所示。一个简单的类比是,三次分别去超市买三样东西,而不是一次就买三样东西。
TensorRT还可以识别共享相同输入数据和过滤器大小但具有不同权重的层。TensorRT不使用三个独立的内核,而是将它们水平地合并成一个更宽的内核,如图4右侧的1×1CBR层所示。
TensorRT还可以通过预先分配输出缓冲区并以快速的方式写入它们来消除图4中的连接层(“concat”)。
总的来说,结果是一个更小、更快、更高效的图形,具有更少的层和内核启动,因此减少了推理延迟。表1显示了一些常见图像分类网络的TensorRT图优化结果。
ptimization 2: FP16 and INT8 Precision Calibration
大多数深度学习框架训练神经网络完全32位精度(FP32)。一旦模型得到充分训练,推理计算可以使用半精度FP16甚至INT8张量运算,因为推理不需要梯度反向传播。使用较低的精度会导致较小的模型大小、较低的内存利用率和延迟以及较高的吞吐量。
TensorRT可以在FP32、FP16和INT8中部署模型,并且在它们之间切换就像在uff_to_trt_engine函数中指定数据类型一样简单:
- For FP32, use trt.infer.DataType.FLOAT.
- For FP16 in and FP16 Tensor Cores on Volta GPUs, use trt.infer.DataType.HALF
- For INT8 inference, use trt.infer.DataType.INT8.
从表2中可以看出,INT8的动态范围明显小于全精度动态范围。INT8只能表示256个不同的值。为了将全精度信息量化为INT8,同时最小化精度损失,TensorRT必须执行一个称为校准的过程,以确定如何最好地将权重和激活表示为8位整数。
校准步骤要求您向TensorRT提供输入训练数据的代表性样本。不需要对模型进行额外的微调或重新培训,也不需要访问整个培训数据集。校准是将FP32转换为INT8的完全自动化和无参数方法。
在这个例子中,我们只演示了FP32和FP16的部署,请参阅TensorRT文档中的代码示例和有关如何执行校准步骤的更多详细信息。
Optimization 3: Kernel Auto-Tuning
在优化阶段,TensorRT还从数百个专门的内核中进行选择,其中许多是针对一系列参数和目标平台进行手动调整和优化的。例如,有几种不同的卷积算法。TensorRT将从内核库中选择实现,该库为目标GPU、输入数据大小、过滤器大小、tensor布局、批大小和其他参数提供最佳性能。
这可以确保部署的模型针对特定的部署平台以及正在部署的特定神经网络进行性能调整。
Optimization 4: Dynamic Tensor Memory
TensorRT还通过仅在每个tensor使用期间为其指定内存,从而减少内存占用并改进内存重用,避免了快速高效执行的内存分配开销。
TensorRT Optimization Performance Results
TensorRT所有优化的结果是,与在CPU或GPU上使用深度学习框架运行推理相比,模型运行更快、更有效。图5中的图表比较了CPU、Tesla V100 GPU和TensorFlow推理以及Tesla V100 GPU和TensorRT推理上ResNet-50网络的图像/秒推理性能。
使用TensorRT,与Tesla V100和CPU相比,您可以获得高达40倍的更快的推理性能。在Volta GPU上运行TensorFlow模型的TensorRT推理在7毫秒的实时延迟要求下可以快18倍。
Figure 5. TensorRT inference performance
compared to CPU-only inference and TensorFlow framework inference.
Serializing
Optimized TensorRT Engines
TensorRT优化阶段的输出是一个可以序列化到磁盘的运行时推理引擎。此序列化文件称为“计划”文件,其中包含运行时引擎用于执行网络的序列化数据。它被称为计划文件,因为它不仅包括权重,还包括内核执行网络的计划。它还包括应用程序可以查询的网络信息,以确定如何绑定输入和输出缓冲区。
使用TensorRT的write_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 Run-Time Inference
现在可以使用TensorRT部署应用程序了。为了快速概括,到目前为止,您已经将一个经过训练的TensorFlow模型导入到TensorRT中,并执行了许多优化以生成运行时引擎。您已经将此引擎序列化为引擎计划文件。您离线执行了所有这些步骤,并且仅在部署之前执行了一次。
下一步是将序列化模型加载到运行时环境中,并对新数据执行推断。为了演示这个步骤,我们将使用TensorRT Lite API。这是一个高度抽象的接口,处理许多标准任务,如创建记录器、从计划文件反序列化引擎以创建运行时,以及为引擎分配GPU内存。在推断过程中,它还自动管理与GPU之间的数据传输,因此您只需创建一个引擎并开始处理数据。对于更细粒度的控件,您可以始终使用标准API或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)
Conclusion
TensorRT解决了深度学习部署的三个关键挑战。
高吞吐量和低延迟:如图5所示,TensorRT执行层融合、精确校准和目标自动调整,以在7毫秒实时延迟下,在Volta GPU上提供高达40倍的推理速度,以及高达18倍的TensorFlow模型推理速度。这意味着,由于更好地利用了GPU资源,您可以轻松地扩展您的AI应用程序以服务更多用户。
功耗效率:通过针对特定目标的优化和动态内存管理,与深度学习框架推理相比,TensorRT提供了更高的功耗效率。低功耗设备运行时间更长,数据中心运行温度更低。
部署级解决方案:TensorRT是为部署而设计的。使用TensorRT,您可以部署一个轻量级运行时,而不需要框架依赖性和开销。使用Python和C++接口,TensorRT可以很容易地从研究人员和数据科学家培训模型、开发人员构建生产部署应用程序的每个人身上使用。
TensorRT 3现在可以免费下载给NVIDIA开发者程序的所有成员。请访问TensorRT主页了解更多信息并立即下载TensorRT!
TensorRT也可以作为NVIDIA GPU云上的容器在本地或AWS P3实例上使用。注册一个NGC帐户,可以免费访问TensorRT容器以及NVIDIA优化的深度学习框架容器进行培训。