当前位置:首页 > 数码 > 实现推理速度提升-TensorRT的架构优化 (实现推理速度的方法)

实现推理速度提升-TensorRT的架构优化 (实现推理速度的方法)

admin4个月前 (05-08)数码9

简介

TensorRT是NVIDIA在2016年发布的一款SDK,专门用于在NVIDIA GPU上加速推理任务。它也被称为推理框架。

为什么选择TensorRT?

速度:TensorRT针对NVIDIA GPU进行优化,比直接使用PyTorch等框架快得多。 易用性:TensorRT提供了一个直观的API,让开发者可以轻松地部署和优化推理模型。 可扩展性:TensorRT支持各种NVIDIA GPU,从边缘设备到云端服务器。

TensorRT的优化技术

TensorRT之所以能够实现卓越的推理性能,得益于其独特的优化技术:

1. 全面搜索优化空间

与PyTorch等训练框架不同,TensorRT基于目标GPU进行推理性能优化。它会在一个巨大的搜索空间中搜索可能的优化方案,包括: 计算划分:将Tensor划分为块,并组织到网格中以优化数据流。 指令选择:选择合适的CUDA指令(如FFMA、FMMA、TensorCore)来执行计算。

2. 强制选择内核

由于GPU的性能可能会受到系统环境的影响,TensorRT提供了强制选择特定内核实现的功能。这样可以确保选择最优内核,从而获得最佳性能。

3. 优化数据流调度

TensorRT使用先进的技术优化Tensor数据在GPU内存中的调度,包括: 内存划分:将Tensor划分为块,并分配给适当的内存区域(本地、共享或全局)。 数据流管理:管理不同Tensor之间的依赖关系,以最大化数据流效率。

4. 预定义算子和层

TensorRT预定义了一系列用于神经网络计算的算子和层,这些算子和层经过优化以适应特定的GPU架构。

5. 实时性能分析

TensorRT提供了实时性能分析功能,允许开发者监控模型推理时的性能,并识别潜在的瓶颈。

TensorRT的优势

使用TensorRT进行推理优化具有以下优势: 更高的推理速度:TensorRT的优化技术能够显著提升推理模型的性能。 更低的延迟:通过优化数据流和减少内存访问,TensorRT可以降低推理延迟。 更节能:TensorRT通过减少GPU内存访问和计算开销,提高了推理的能效。

TensorRT的应用

TensorRT广泛应用于各种推理任务,包括: 图像分类 目标检测 语音识别 自然语言处理

TensorRT的API

TensorRT提供了丰富的API,允许开发者轻松地部署和优化推理模型。这些API包括: Python API:用于从Python代码中集成TensorRT。 C++ API:用于高级自定义和低级控制。 TensorRT推理引擎:执行推理任务。

结论

TensorRT是NVIDIA提供的强大推理优化器,可以显著提升在NVIDIA GPU上推理模型的性能。它通过全面的优化技术、强制内核选择和实时性能分析功能,帮助开发者部署和优化高性能推理应用程序。

用沐神的方法阅读PyTorch FX论文

作者丨BBuf

编辑丨极市平台

对于PyTorch来说确实是一个比较好的工作,因为它消除了一些动态图和静态图的Gap。比如在图改写方面, 让PyTorch想做一些其它静态图框架的算子融合优化非常容易。并且 让后训练量化和感知训练量化以及AMP等的实现难度大大降低,这得益于我们可以直接在Python层操作这个IR,所以我认为这是一个不错的工作。尤其是对使用PyTorch开发的算法工程师来说,现在可以基于这个特性大开脑洞了。 的卖点就是,它使用纯Python语言实现了一个可以捕获PyTorch程序的计算图并转化为一个IR的库,并且非常方便的在这个IR上做Pass,同时提供将变换后的IR Codegen合法的Python代码功能。我觉得算是达到了在Eager下写Pass就像做链表插入删除题目一样顺滑。

PyTorch FX论文的链接在:。

下面我就以沐神的论文阅读顺序来分享一下阅读体验,帮助大家搞清楚PyTorch FX这个特性到底是什么,以及它可以在PyTorch中发挥什么作用。

摘要部分简单指明了像PyTorch这种基于动态图执行模式的深度学习框架虽然提升了用户的易用性。但是在一些真实场景中,用户可能是需要捕获和变换程序结构(也可以直接理解为神经网络的结构)来进行性能优化,可视化,分析和硬件调优等。为了解决这个痛点,PyTorch设计了 这个模块来做PyTorch程序的捕获和变换,这个模块是纯Python开发的。

这一节主要是讲了一下 的卖点,就是说动态图虽然易用性很强,但是图结构不能被提前感知和变换,但通过这篇论文的 模块,这件事就成啦!

早期的图模式或者叫define-and-run 的静态图框架有Caffe,TensorFlow等,它们设计了一个表示图的IR,用户通过调用这些框架提供的API来构建IR。然后我们可以在这个IR上做程序微分,将IR切分到设备上实现并行,量化,性能优化等等。但这些事情一般都要求开发者在领域特定的语言上去做,比如以OneFlow的静态图模式为例,要做图切分,量化,性能优化等都需要基于C++去开发,并且调试也会相对比较难(要借助pdb,gdb等等专业工具)。

现在的eager模式或者叫define-by-run 的动态图框架有PyTorch,TensorFlow Eager模式等,它们可以随心所欲的让用户基于脚本语言编程并且可以解决大多数的训练(基于自动微分)和预测任务。但是有一些变换比如 「量化和算子融合」 是不能直接做的,而这一点在静态图模式下则很简单。为了消除这种Gap,动态图框架需要一种从用户的程序捕获图结构的方法来使能这些变换。

在捕获和变换程序时,eager和graph模式的深度学习框架都必须在「捕获程序结构」 、「程序特化」 和 「保存程序的IR的设计」 方面做出选择。这些选择的组合决定了可在框架中表示的 「程序空间」 、「编写变换的难易程度」以及「生成的变换程序的性能」 。「一般来说,支持程序的高性能运行需要更复杂的捕获框架和IR,从而使转换更难编写」 。每一段相关工作我就不详细过了,只描述每一段工作的核心是在说什么,相关细节大家可以查看原始论文。

这一节提到了PyTorch的 ,MxNet Gluon,TensorFlow的 等程序捕获方法,并指出这些方法只能处理Python的一些子集。然后,TorchScript通过在AST上分析可以处理控制流和更多的Python语法。然后还提了一下Julia和Swift For TensorFlow中将捕获程序结构的接口集成到了非Python的宿主语言中,要使用的话需要用户放弃Python生态系统。

对于a+b 这个Python语句来说,这个表达式对 a 和 b 的类型没有限制。但当深度学习框架捕获程序时一般会对这两个变量进行特化,以便它们只对特定类型或者张量有效。在深度学习框架中处理的大多数程序都是特化类型的程序,特化程度越高,能够处理的输入就越少。例如 在执行trace的时候只能处理某些拥有合法输入shape的输入。接下来还讨论了LazyTensor和Jax的 jit 来说明为了更好的处理特化程序中捕获的失败,它们做了哪些努力。

深度学习框架都有自己的IR设计,Caffe和TensorFlow使用Protocol Buffers格式。而PyTorch和MxNet使用C++数据结构来表示IR并额外绑定到Python。这些IR设计在runtime阶段表现都会比较好并且可以统一被序列化。但从另外一个角度来说,这些IR表示相比于纯Python语言的表示都需要更高的学习成本。接下来,这一节讨论了控制流和状态的问题,用来表明要处理这些问题需要设计较为复杂的IR以及要基于这个IR做较为复杂的分析才行。

基于上面几点,论文提出了 的基本设计原则:

这一节主要对一些相关工作进行了展开,以此来突出 的核心卖点,就是说我虽然不能像TorchScript这样的IR处理一些比较难的Case(比如动态控制流),但是我在神经网络这个领域里做得够用就可以了。最关键的是我的实现很简单,是纯Python的库,这样用户写变换就会很简单,学习成本会很小并且易用。(简单不代表不强大!

以简单为基本原则, 通过符号跟踪来捕获程序,并通过一个简单的6个指令的IR来表示它们,并基于这个IR重新生成Python代码来运行它。为了避免JIT特化中的重捕获的复杂性, 没有对程序本身进行特化,而是依靠变换来决定在捕获期间需要实现哪些特化。用户也可以配置符号跟踪的过程来实现自定义捕获需求。

Figure1给我们展示了使用_trace 捕获程序的例子,输入可以是一个 或者函数,并且捕获之后的结构被存在一个Graph对象里面。该 Graph 对象和 GraphModule 中的模块参数相结合, GraphModule 是的子类,其forward方法运行捕获的Graph 。我们可以打印此图的 Nodes 以查看捕获的 IR。 placeholder 节点表示输入,单个 output 节点表示 Graph 的结果。 call_function节点直接引用了它将调用的 Python 函数。 call_method节点直接调用其第一个参数的方法。 Graph被重组为 Python 代码( )以供调用。

Figure2展示了使用 进行变换的示例。变换是找到一个激活的所有实例并将它们替换为另一个。在这里,我们使用它来将 gelu替换relu 。

的符号跟踪机制使用一个Proxy数据结构来记录给定一个输入之后经过了哪些Op。Proxy是一个duck-typed类型的Python类记录了在它之上的的属性访问和调用方法,是程序中真实Op的上层抽象。duck-typed可以看一下这里的介绍:。PyTorch的算子以及Python子集的某些函数都会被这个Proxy包装一次,然后在符号跟踪传入的是一个 时,会对这个 中的子 也进行Proxy包装,当然还包含输入数据。这样程序中的输入和其它Op都是duck-typed类型的Proxy对象,我们就可以执行这个程序了,也就是符号跟踪的过程。符号跟踪的过程通过一个 Tracer 类进行配置,它的方法可以被重写以控制哪些值被作为Proxy对象保留,哪些值被unpack。(Proxy记录下来的Op可以进行unpack,unpack之后可以拿到真实的Tensor, Parameter和运算符等等)。通过Proxy和Tracer类的配合, 就可以完成PyTorch程序的符号跟踪,需要注意的是这里的符号跟踪的意思就是运行一遍这个被代理之后的 的forward。

的中间表示(IR)由一个Python数据结构 Graph 来做的。这个 Graph 实际上是一个包含一系列 Node 的线性表。节点有一个字符串操作码 opcode ,描述节点代表什么类型的操作(操作码的语义可以在附录 A.1 中找到)。节点有一个关联的目标,它是调用节点( call_module 、 call_function和call_method )的调用目标。最后,节点有args和kwargs ,在trace期间它们一起表示 Python 调用约定中的目标参数(每个opcode对应的args和kwargs的语义可以在附录 A.2 中找到)。节点之间的数据依赖关系表示为args和kwargs中对其他节点的引用。

将程序的状态存储在GraphModule类中。 GraphModule是转换程序的容器,暴露转换后生成的代码,并提供类似的参数管理APIs。 GraphModule可以在任何可以使用普通的的地方使用,以提供转换后的代码和PyTorch 生态系统的其余部分之间的互操作性。

变换pipline的最后阶段是代码生成。 并不是退出 Python 生态系统并进入定制的运行时,而是从变换后的 IR 生成有效的 Python 源代码。然后将此变换后的代码加载到 Python 中,生成一个可调用的 Python 对象,并作为 forward 方法安装在GraphModule实例上。使用代码生成允许将变换的结果安装在模型中并用于进一步的变换。例如,在图3中,我们拿到trace原始程序的结果并将其安装为新模块中的激活函数。

到这里PyTorch FX特性就精读完了,但查看FX的论文可以发现还有一节叫作Design Decisions,分别介绍了Symbolic Tracing,Configurable Program Capture,AoT Capture without Specialization,Python-based IR and Transforms等等FX实现中依赖的一些想法和 决策,以及它们的好处等。我理解这一节就是Introduction的加强版,所以就不继续讲解这一小节了,如果你担心会错过什么细节知识可以阅读论文原文。

的一个目标就是简化深度学习模型产生的IR,下面的Figure5以ResNet50为例展示了TorchScript IR和 的差别,相比于TorchScript IR, 确实简单并且可读性更强。

实现推理速度提升

我们知道后量化以及量化感知训练可以提示程序推理时的性能,下面的Figure6就展示了基于 实现的后量化(使用FBGEMM量化算子)应用在DeepRecommender模型之后,在Intel Xeon Gold 6138 CPU @2.00GHz上的性能表现。基于 实现的后量化模型推理速度相比float类型的模型要高3.3倍。并且基于 实现量化操作相比基于TorchScript IR要简单很多。

还可以做Op融合,Figure7展示了基于 做了Conv+BN融合后应用在ResNet50上,在n NVIDIA Tesla V100-SXM2 16GB with CUDA version 11.0 和 Intel Xeon Gold 6138 CPU @ 2.00GHz的性能表现,可以看到在GPU上减少了约6%的latency,在CPU上减少了约40%的latency(多线程)和约18%的latency(单线程)。

除此之外 还可以应用在FLOPs计算,内存带宽使用分析,工作负载的数据值大小估计等,用来分析程序运行时的内存和速度。 还可以用在形状推断,以及模型对应的DAG可视化作图等等。

最后, 在runtime阶段还支持通过ASIC加速(即将 中的算子lowering到对应的ASIC上),下面的Figure8展示了基于 推理ResNet50和LearningToPaint并将算子lowering到TensorRT之后的加速情况:

对于PyTorch来说确实是一个比较好的工作,因为它消除了一些动态图和静态图的Gap。比如在图改写方面, 让PyTorch想做一些其它静态图框架的算子融合优化非常容易。并且 让后训练量化和感知训练量化以及AMP等的实现难度大大降低,这得益于我们可以直接在Python层操作这个IR,所以我认为这是一个不错的工作。尤其是对使用PyTorch开发的算法工程师来说,现在可以基于这个特性大开脑洞了。我之前围绕FX也做了一个QAT的工作,感兴趣可以阅读:基于OneFlow实现量化感知训练:最后总结一下, 的卖点就是,它使用纯Python语言实现了一个可以捕获PyTorch程序的计算图并转化为一个IR的库,并且非常方便的在这个IR上做Pass,同时提供将变换后的IR Codegen合法的Python代码功能。我觉得算是达到了在Eager下写Pass就像做链表插入删除题目一样顺滑。

沐神的论文阅读方法,感觉确实比较科学,文章末尾再赞一次。

tensorRT如何实现神经网络推理加速?

TensorRT是NVIDIA的一个深度学习推理优化器和运行时库,能够实现神经网络推理的加速。 其优化过程主要包括以下几个步骤:1. **网络前向计算优化**:TensorRT使用一种称为“网络层融合”的技术来优化前向计算。 它将相邻的卷积层和池化层合并,以减少不必要的内存访问和数据重排。 此外,TensorRT还使用GPU上的特殊指令(例如CUDA)来并行化这些操作,从而提高计算速度。 2. **后向计算优化**:对于神经网络的反向传播,TensorRT通过使用与前向计算类似的技术来优化计算。 它将相邻的卷积层和池化层进行融合,减少了反向传播中的计算量和内存访问。 此外,TensorRT还使用梯度聚合技术来进一步优化反向传播的计算。 3. **数据布局优化**:TensorRT还可以优化数据布局,以进一步提高内存访问效率。 它使用一种称为“数据布局优化”的技术,根据网络的结构和数据流模式来确定最佳的数据布局方式。 这可以减少不必要的内存访问和数据重排,从而提高推理速度。 4. **模型剪枝**:对于一些不需要精确推理的模型,例如在图像超分辨率或者语义分割等任务中,可以使用模型剪枝技术来减少模型的复杂性。 TensorRT支持使用不同的剪枝策略,例如全局或局部剪枝,来减少模型的参数和计算量,从而提高推理速度。 通过以上优化技术,TensorRT可以显著提高神经网络推理的速度,特别是在GPU环境下。 这使得TensorRT成为深度学习应用中常用的推理加速工具。

免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。

标签: 架构

“实现推理速度提升-TensorRT的架构优化 (实现推理速度的方法)” 的相关文章

从零开始打造新系统架构的完整指南 (从零开始打造不朽仙域免费)

从零开始打造新系统架构的完整指南 (从零开始打造不朽仙域免费)

架构设计是一个多维度的过程,包括工程架构、业务架构和部署架构等。一个好的系统架构标准应该具备可扩展性、可维护性、可靠性、安全性、高性能等特点。本文主要围绕工程架构设计展开探讨。 二、价值为先...

实时的跨微服务数据访问-可信-微服务架构中的数据一致性-保障可靠 (跨服聊天微信例子)

实时的跨微服务数据访问-可信-微服务架构中的数据一致性-保障可靠 (跨服聊天微信例子)

引言 在微服务架构中,多个服务共同协作以执行原子操作。数据一致性是跨越多个服务执行分布式事务时面临的一项挑战。如果涉及分布式事务流程的某个参与者出现故障,可能会导致数据不一致,例如未下订单却向客...

你自称懂架构-架构设计的真谛!-来这里看看 (架构怎么理解)

你自称懂架构-架构设计的真谛!-来这里看看 (架构怎么理解)

1. 引言 抢红包已经成为春节期间不可或缺的娱乐活动,自2015年微信推出红包功能以来,每年参与抢红包的用户数和红包发放量都呈爆发式增长。微信红包系统的背后蕴含着怎样的技术架构和设计理念,一...

掌控复杂性-创造灵活可扩展的系统-六边形架构 (复杂事物掌控力)

掌控复杂性-创造灵活可扩展的系统-六边形架构 (复杂事物掌控力)

六边形架构是一种架构模式,将外部系统与核心应用程序分隔开来。它的思想很简单:从一个六边形开始,然后应用端口和适配器。 六边形架构的六个边 六边形有六个边,但六边形的形状本身并没有特别含...

六种最关键的架构模式 (六种最关键的职业)

六种最关键的架构模式 (六种最关键的职业)

架构模式:六种常见且关键的模式 引言 在软件开发中,架构模式是一种经过验证的解决方案,可以帮助解决常见的开发问题。这些模式提供了重用性的设计方案,允许开发人员创建可维护、可扩展和易于测试的应用程序...

从单体到分布式-全面解析-一文搞懂微服务架构演进 (单体可分为)

从单体到分布式-全面解析-一文搞懂微服务架构演进 (单体可分为)

简介 微服务架构是一种软件开发方法,将应用程序拆分为较小的、独立的服务,这些服务可以单独部署和维护。该架构旨在提高灵活性、可扩展性和可靠性。 微服务组件 服务:独立部署和维...

最佳实践和挑战-平台工程团队的架构和设计注意事项 (最佳实践的定义)

最佳实践和挑战-平台工程团队的架构和设计注意事项 (最佳实践的定义)

什么是平台工程? 平台工程是一种构建、维护和管理服务和工具的实践,这些服务和工具可供组织中的其他团队使用。平台工程团队创建标准化、可重用的组件,以便其他团队可以专注于构建应用程序和产品,而...

对代码的编写有很好的指导作用-聊聊六边形架构 (代码的编写过程)

对代码的编写有很好的指导作用-聊聊六边形架构 (代码的编写过程)

为了编写出漂亮代码,学习设计模式是一个好方法。但是,只读这些书籍还不够,还需要理解它们背后的思想,即面向对象的原则。 六边形架构是一种软件架构模式,遵循这些原则,可以实现高内聚、低耦合和可测...