丰富的线上&线下活动,深入探索云世界
做任务,得社区积分和周边
最真实的开发者用云体验
让每位学生受益于普惠算力
让创作激发创新
资深技术专家手把手带教
遇见技术追梦人
技术交流,直击现场
海量开发者使用工具、手册,免费下载
极速、全面、稳定、安全的开源镜像
开发手册、白皮书、案例集等实战精华
为开发者定制的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的魅力所在。