一篇就够:高性能推理引擎理论与实践(TensorRT)

丰富的线上&线下活动,深入探索云世界

做任务,得社区积分和周边

最真实的开发者用云体验

让每位学生受益于普惠算力

让创作激发创新

资深技术专家手把手带教

遇见技术追梦人

技术交流,直击现场

海量开发者使用工具、手册,免费下载

极速、全面、稳定、安全的开源镜像

开发手册、白皮书、案例集等实战精华

为开发者定制的Chrome浏览器插件

训练过程通过设定数据处理方式,并设计合适的网络模型结构以及损失函数和优化算法,在此基础上将数据集以小批量的方式(mini-batch)反复进行前向计算并计算损失,然后反向计算梯度利用特定的优化函数来更新模型,来使得损失函数达到最优的结果。训练过程最重要的就是梯度的计算和反向传播。

而推理就是在训练好的模型结构和参数基础上,做一次前向传播得到模型输出的过程。相对于训练而言,推理不涉及梯度和损失优化。推理的最终目标是将训练好的模型部署生产环境中。

虽然推理就是数据经过模型的一次前向计算,但是推理是面向不同的终端部署,一般推理需要满足:

所以推理框架一般包括模型优化和推理加速,以便于支持高性能的推理要求。

那么一个推理框架要做哪些事情呢?

首先,因为推理框架要支持现有流行的深度学习框架如TensorFlow和Pytorch等,而不同的深度学习框内在的不一致性,就要求推理框架需要有一种同一个表达形式,来统一外部的不一致性,这就需要推理框架外部模型解析和转换为内在形式的功能。

其次,为了追求性能的提升,需要能够对训练好的模型针对特定推理设备进行特定的优化,主要优化可以包括

我们下面依次来做下说明。

一般模型训练过程中都是采用FP32或者FP64高精度的方式进行存储模型参数,主要是因为梯度计算更新的可能是很小的一个小数。高精度使得模型更大,并且计算很耗时。而在推理不需要梯度更新,所以通常如果精度从FP32降低到FP16,模型就会变小很多,并且计算量也下降,而相对于模型的推理效果几乎不会有任何的变化,一般都会做FP16的精度裁剪。

而FP32如果转换到INT8,推理性能会提高很多,但是裁剪不是直接裁剪,参数变动很多,会影响模型的推理效果,需要做重新的训练,来尽可能保持模型的效果

我们先来了解下计算图的概念,计算图是由算子和张量构建成一个数据计算流向图,通常深度学习网络都可以看成一个计算图。而推理可以理解成数据从计算图起点到终点的过程。

算子编译优化其中一项优化就是计算图的优化。计算图优化的目标是对计算图进行等价的组合变换,使得减少算子的读写操作提供效率。

最简单的情况,就是算子融合。比如常见Conv+ReLu的两个算子,因为Conv需要做大量卷积计算,需要密集的计算单元支持,而Relu几乎不需要计算,如果Relu算子单独运算,则不仅需要一个计算单元支持其实不需要怎么计算的算子,同时又要对前端的数据进行一次读操作,很浪费资源和增加I/O操作;此时,可以将Conv和Relu合并融合成一个算子,可以节省I/O访问和带宽开销,也可以节省计算单元。

这种算子融合对于所有推理设备都是支持,是通用的硬件优化。有些是针对特定硬件优化,比如某些硬件的计算单元不支持过大算子输入,此时就需要对算子进行拆解。

计算图的优化可以总结为算子拆解、算子聚合、算子重建,以便达到在硬件设备上更好的性能。

算子编译优化的另一个优化就是数据排布优化。我们知道,在TensorFlow框架的输入格式NHWC,而pytorch是NCHW。这些格式是框架抽象出来的矩阵格式,实际在内存中的存储都是按照1维的形式存储。这就涉及物理存储和逻辑存储之间的映射关系,如何更好的布局数据能带来存储数据的访问是一个优化方向;另外在硬件层面,有些硬件在某种存储下有最佳的性能,通常可以根据硬件的读写特点进行优化。

我们推理的时候都需要借助额外的硬件设备来达到高速推理,如GPU,NPU等,此时就需要再CPU和这些硬件设备进行交互;以GPU为例,推理时需要将CPU中的数据copy到GPU显存中,然后进行模型推理,推理完成后的数据是在GPU显存中,此时又需要将GPU显存中的数据copy回cpu中。

这个过程就涉及到存储设备的申请、释放以及内存对齐等操作,而这部分也是比较耗时的。

因此内存优化的方向,通常是减少频繁的设备内存空间的申请和尽量做到内存的复用。

一般的,可以根据张量生命周期来申请空间:

在计算图中,存在某些算子是串行依赖,而某些算子是不依赖性;这些相互独立的子计算图,就可以进行并行计算,提高推理速度,这就是计算图的调度。

在第二部分我们讲解了推理引擎的一般工作流程和优化思路,这一部分我们想介绍一个具体的推理引擎框架:TensorRT。

TensorRT是NVIDIA出品的针对深度学习的高性能推理SDK。目前,TensorRT只支持NVIDIA自家的设备的推理服务,如服务器GPUTeslav100、NVIDIAGeForce系列以及支持边缘的NVIDIAJetson等。

TensorRT通过将现有深度学习框架如TensorFlow、mxnet、pytorch、caffe2以及theano等训练好的模型进行转换和优化,并生成TensorRT的运行时(RuntimeEngine),利用TensorRT提供的推理接口(支持不同前端语言如c++/python等),部署不同的NVIDIAGPU设备上,提供高性能人工智能的服务。

在性能方面,TensorRT在自家的设备上提供了优越的性能

如果你采用的是NVIDIA的设备,TensorRT是一个理想的部署解决方案。

对于前面第2节介绍的推理引擎要做的主要工作项,TensorRT做了哪些优化呢?

对于TensorRT而言,主要优化如下(大家可以第2部分的理论做一个对照,理论结合实践):

以上面Inception模块的计算图为例子,左边是未优化原始的结构图,右边是经过TensorRT优化过的计算图。优化的目标是减少GPU核数的使用,以便于减少GPU核计算需要的数据读写,提高GPU核数的计算效率

经过优化,使得整个模型层数更少,占用更少GPU核,运行效率更快。

了解了TensorRT是什么和如何做优化,我们实际操作下TensorRT,先来看看TensorRT的安装。

TensorRT是针对NVIDIAGPU的推理引擎,所以需要CUDA和cudnn的支持,需要注意版本的对应关系;以TensorRT7.1.3.4为例,需要至少CUDA10.2和cudnn8.x。

本质上TensorRT的安装包就是动态库文件(CUDA和cudnn也是如此),需要注意的是TensorRT提供的模型转换工具。

下载可参考

rpm-icuda-repo-rhel7-10-2-local-10.2.89-440.33.01-1.0-1.x86_64.rpmtar-zxvfcudnn-10.2-linux-x64-v8.0.1.13.tgz#tar-xzvfTensorRT-${version}.Linux.${arch}-gnu.${cuda}.${cudnn}.tar.gztar-xzvfTensorRT-7.1.3.4.CentOS-7.6.x86_64-gnu.cuda-10.2.cudnn8.0.tar.gzTensorRT也提供了python版本(底层还是c的动态库)

在安装TensorRT之后,如何使用TensorRT呢?我们先来了解下TensorRT的工作流程。

总体流程可以拆分成两块:

由于不同的深度学习框架的实现逻辑不同,TensorRT在转换模型时采用不同适配方法。以当前最流行深度学习框架TensorFlow和Pytorch为例。

由于pytorch采用动态的计算图,也就是没有图的概念,需要借助ONNX生成静态图。

pth转换为onnx

importonnximporttorchdefexport_onnx(onnx_model_path,model,cuda,height,width,dummy_input=None):model.eval()ifdummy_inputisNone:dummy_input=torch.randn(1,3,height,width).float()dummy_input.requires_grad=Trueprint("dummy_inputshape:",dummy_input.shape,dummy_input.requires_grad)ifcuda:dummy_input=dummy_input.cuda()torch.onnx.export(model,#modelbeingrundummy_input,#modelinput(oratupleformultipleinputs)onnx_model_path,#wheretosavethemodel(canbeafileorfile-likeobject)export_params=True,#storethetrainedparameterweightsinsidethemodelfileopset_version=10,#theONNXversiontoexportthemodeltodo_constant_folding=True,#whethertoexecuteconstantfoldingforoptimizationverbose=True,input_names=['input'],#themodel'sinputnamesoutput_names=['output'],#themodel'soutputnames)从上可知,onnx通过pytorch模型完成一次模型输入和输出的过程来遍历整个网络的方式来构建完成的计算图的中间表示。

这里需要注意三个重要的参数:

onnx转换为planengine模型

这里给出的通过TensorRT的python接口来完成onnx到planengine模型的转换。

importtensorrtastrtdefbuild_engine(onnx_path):EXPLICIT_BATCH=1<<(int)(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)withtrt.Builder(TRT_LOGGER)asbuilder,builder.create_network(EXPLICIT_BATCH)asnetwork,trt.OnnxParser(network,TRT_LOGGER)asparser:builder.max_batch_size=128builder.max_workspace_size=1<<15builder.fp16_mode=Truebuilder.strict_type_constraints=Truewithopen(onnx_path,'rb')asmodel:parser.parse(model.read())#Buildandreturnanengine.returnbuilder.build_cuda_engine(network)从上面的转换过程可知,TensortRT的转换涉及到几个关键的概念:builder、network、parser

从总体上看,TensorRT的转换模型是,将onnx的模型结构(以及参数)转换到TensorRT的network中,同时设置模型推理和优化的参数(如精度裁剪等)。用一张图来总结下上述过程:

保存engine和读取engine

TensorFlow或者Keras(后台为TensorFlow)采用的是静态的计算图,本身就有图的完整结构,一般模型训练过程会保留ckpt格式,有很多冗余的信息,需要转换为pb格式。针对TensorFlow,TensorRT提供了两种转换方式,一种是pb直接转换,这种方式加速效果有限所以不推荐;另一种是转换uff格式,加速效果明显。

采用TensorRT提供的uff模块的from_tensorflow_frozen_model()将pb格式模型转换成uff格式模型

importuffdefpb_to_uff(pb_path,uff_path,output_names):uff_model=uff.from_tensorflow_frozen_model(pb_path,output_names,output_filename=uff_path)3.6模型推理通过TensorRT的模型转换后,外部训练好的模型都被TensorRT统一成TensorRT可识别的engine文件(并优化过)。在推理时,只要通过TensorRT的推理SDK就可以完成推理。

具体的推理过程如下:

importcommonimportnumpyasnpimportcv2importtensorrtastrtdefinference_test(engine_path,img_file):#processinputinput_image=cv2.imread(img_file)input_image=input_image[...,::-1]/255.0input_image=np.expand_dims(input_image,axis=0)input_image=input_image.transpose((0,3,1,2))#NCHWforpytorchinput_image=input_image.reshape(1,-1)#.ravel()#inferbatch_size=1TRT_LOGGER=trt.Logger(trt.Logger.INFO)withopen(engine_path,"rb")asf,trt.Runtime(TRT_LOGGER)asruntime:engine=runtime.deserialize_cuda_engine(f.read())#AllocatebuffersandcreateaCUDAstreaminputs,outputs,bindings,stream=common.allocate_buffers(engine,batch_size)#Contextsareusedtoperforminference.withengine.create_execution_context()ascontext:np.copyto(inputs[0].host,input_image)[output]=common.do_inference(context,bindings=bindings,inputs=inputs,outputs=outputs,stream=stream,batch_size=batch_size)3.7TensorRT进阶和缺点前面较全面了介绍了TensorRT的特点(优点)和工作流程;希望能感受到TensorRT的魅力所在。

THE END
1.目前主流的人工智能学习框架有哪些在人工智能的学习和开发中,选择合适的框架是关键。这些框架提供了核心工具和功能,帮助开发者构建和优化机器学习模型,提高效率,降低复杂度。目前主流的人工智能学习框架各有侧重,有些适合初学者快速上手,有些则针对专业研究者和工程师设计。接下来,我们详细介绍几个主流框架的特点和使用场景。 https://blog.csdn.net/Xhz181888/article/details/144437120
2.学不懂js可以直接学vue吗前端问答javascript 是 web 前端开发中不可或缺的一门语言,vue.js 是当前流行的前端框架之一。很多初学者在面对学习 vue.js 时,经常会听到这样的建议:「不懂 javascript,可以直接学 vue.js 吗?」。这个问题不是非黑即白的,需要分情况来看。 看你是否有 JavaScript 基础 https://www.php.cn/faq/512954.html
3.湖南统计信息网关于现代经济学的概念,我们把最近半个世纪以来发展起来的、在当今世界上被认可为主流的经济学称为现代经济学。现代经济学代表了一种研究经济行为和现象的分析方法或框架。 一、现代经济学的分析框架 作为理论分析框架,它由三个主要部分组成:视角(perspective)、参照系(reference)或基准点(benchmark)和分析工具(analyticahttp://tjj.hunan.gov.cn/bsfw/tjkp/tjjz/201507/t20150717_3824466.html
4.关于机器学习,这可能是目前最全面最无痛的入门路径和资源!李杰克尝试过Tensorflow、Mxnet和Keras三种框架,以使用Tensorflow为主,其他框架暂时没怎么接触。 今天重点要跟大家说的Tensorflow这个框架,Tensorflow背靠Google大树,是目前最火的框架,如果你想做一名AI工程师,那学Tensorflow一定是最好的选择,类似于一招鲜吃天下的意思。 https://www.36kr.com/p/5109465.html
5.学校安全先进个人事迹材料(通用17篇)二、层层签订安全工作责任书,构建安全教育框架 学校始终坚决贯彻执行县局下发的有关学校安全工作的文件精神及学校安全工作的各项规定,学校的各班级均制定了安全工作职责,班主任每学期都要作出本班切实可行的班级安全教育工作计划和总结,切实将安全工作作为第一要务来抓,学校也将此项工作的考核作为衡量教师工作绩效的重要https://www.ruiwen.com/xianjinshijicailiao/6159100.html
6.RPC框架:从原理到选型,一文带你搞懂RPC腾讯云开发者社区Thrift:thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++,Java,Python, PHP, Ruby, Erlang,Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。 https://cloud.tencent.com/developer/article/2021745
7.中世纪史学家格里:历史才是对“欧洲认同”最具威胁的事物联系与隔离:更广阔的框架 除此之外,研究中世纪早期的学者还受到跨区域、去中心化历史研究的影响,也就是,越来越多的西欧制度、社会和文化发展如今被纳入一个更宽广的欧亚历史的框架内来理解。这也就是后殖民历史学家如查克拉博蒂(Dipesh Chakrabarty)所说的“把欧洲地方化”(Provincializing Europe)的一部分。不过,查克https://www.thepaper.cn/newsDetail_forward_1478495
8.“宿舍文化圈”:大学室友对你的一生影响有多大?将宿舍作为本文的一个分析框架,可以跳出传统社会学在青年社会流动领域研究中集中于家庭背景、教育等结构性因素影响的讨论框架,构建一个新的研究载体。 宿舍在一定程度上打破了社会阶层在青年社会互动和交往中的聚合作用,将来自不同家庭和背景的同学联系在一起,在大学生活的几年中,青年可以在有限的范围内突破社会阶层的https://www.cqcb.com/manxinwen/manxinwen/2020-05-04/2374527_pc.html
9.PyTorch中文教程Python 优先的深度学习框架 PyTorch 手册说明 PyTorch 是一个 Torch7 团队开源的 Python 优先的深度学习框架,提供两个高级功能: 强大的 GPU 加速 Tensor 计算(类似 numpy) 构建基于 tape 的自动升级系统上的深度神经网络 你可以重用你喜欢的 python 包,如 numpy、scipy 和 Cython ,在需要时扩展 PyTorch。 https://www.w3cschool.cn/pytorch/
10.新技术·新成果——2021年度北京波谱年会之技术报告资讯中心报告题目: 配位聚合物框架结构材料中核磁的应用 万重庆教授简要介绍了固态核磁在配合物结构鉴定中的应用,包括在配位环境/结构、框架结构、相变及结构动力学方面的应用研究。并结合其课题组在这方面的研究进展,为固态核磁在配位聚合物材料的结构组成鉴定的实际应用提供范例。 https://www.instrument.com.cn/news/20130425/580258.shtml
11.3D点云数据开发的深度学习框架点云三维模型3D点云数据开发的深度学习框架 点云 三维模型 RGB-D 点云 何为点云? 点云的获取 点云的内容 点云的属性 点云目前的主要存储格式包括:pts、LAS、PCD、.xyz 和. pcap 等 相应基础算法库对不同格式的支持 三维点云有多种表示方法 相比于图像数据,点云不直接包含空间结构,因此点云的深度模型必须解决三个主要https://blog.51cto.com/u_12227/8777599
12.不学前端也可以做UI?机器学习UI框架Streamlit简介—入门配置不用学前端编程,你就能用 Python 简单高效写出漂亮的交互式 Web 应用,将你的数据分析成果立即展示给团队和客户 ——少数派 Streamlit 介绍 Streamlit是一个针对数据科学家设计的开源WEB框架,它可以使数据工程师能够围绕其数据,机器学习模型等几乎所有内容快速构建高度交互的Web应用程序。而且使用Streamlit开发自己的APP,只https://www.jianshu.com/p/46744bf46dd2
13.字节跳动破局联邦学习:开源Fedlearner框架,广告投放增效209%纵向与横向两种训练模式可以归约于一个框架,既一对 worker 各自执行一个神经网络,并通信中间结果和梯度。为了支持这种模式,Fedlearner 实现了一个基于 gRPC 的通信协议,并以算子的形式集成到 TensorFlow 中: bridge=bfl.bridge.Bridge(50051, 'localhost:50052')bridge.wait_for_remote_startup()g=tf.Graph()withhttps://maimai.cn/article/detail?fid=1550604028&efid=zqj9rqK7Yf_Us-lu-0Wnmg