2021寒武纪TensorFlow融合模式用户手册_第1页
2021寒武纪TensorFlow融合模式用户手册_第2页
2021寒武纪TensorFlow融合模式用户手册_第3页
2021寒武纪TensorFlow融合模式用户手册_第4页
2021寒武纪TensorFlow融合模式用户手册_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

版本2021年05月06 插图目 表格目 离线模式(AheadOf INT量 修改BUILD文 tensordump功能以及误差计算工 融合段tensordump功 MLU内存越界检 使用FP16精 使用frozen 增大batch 开启FirstConv优 设置首层Conv2D的补齐方 使用SessionConfig的配置参 Python接 C++接 设置 设置 Python接口使 C++接口使 插图目录TensorFlow融合模式图编译器示意 插图目录ResNet50v1原始计算图(融合前 ResNet50v1融合计算图(融合后 表格目录 表格目录 支持的 11((或保证本文件所且寒武纪不承担因应用或使用任何产品或服务而产生的任何责任。寒武纪不应对因下列原因产生的任何12客户产品设计。本指南列出的性能测试和等级要使用特定芯片或计算机系统或组件来测量。经该等测试,本指南所示结果反映了寒武纪产品的大概性能。系统硬件或软件设计或配置的任何不同会影响实际性能。如上所述,寒武纪不代表、担保或保证本指南所述产品将适用于任何特定用途。寒武纪不代表或担保测试每种产品以期避免应用程序或产品的默认情况。客户产品设计的脆弱性会影响寒武纪产品的质量和可靠性并导致超出本指南范围的额外或不同的情况和/或要求。 ©2021222.1:寒武纪TensorFlowV20210506更新时间:20210201–33CambrionensorFlw内建了基于CNML(CambrionNeuaeMachinearnin,寒武纪机器学习库的融合模式CambrionensorFlwMUusionOCNML进行深度优化,消除不必要的中间结果,生成更高效率、更具硬件亲和性的MUernel。以下以ResNet50v.可以发现,整个ResNet50v1网络被融合为一个MLUFusionOP 目前CambriconTensorFlowNative(逐层)模式。如果想使用融合模式需要将环境变量MLU_STATIC_NODE_FUSION设置为true。exportexport融合模式可分为在线模式(JustInTime)和离线模式(AheadOfTime在线模式(JustIn在线模式下,用户无需对自己的网络进行修改适配,CambriconTensorFlowCNML支持的算子划分进融合段。通常情况下,用户无需关心CNML计算库支持哪些TensorFlow算子。CNML不支持的算子,依会在CPU上运行。离线模式(AheadOf融合模式还有一种特殊的运行模式:离线模式。用户可以通过CambrionensorFlw提供的离线模型生成工具,将ensorFlw计算图转化为寒武纪离线模型。生成的离线模型可以脱离ensorFlw框架,使用CN(CambrionNeuaeRuntime由于离线模式不依赖TensorFlow,所以计算图中不能包含CNML如果计算图中包含CNML对于CNML计算库支持的TensorFlow算子,参见支持算子列表在主机端使用离线模型生成工具将TensorFlow在部署端,用户可以脱离TensorFlow,使用CNRT44使用CambriconTensorFlow融合模式时只需正常安装CambriconTensorFlow,不需要额外安装依赖编译CambriconTensorFlow加载TensorFlow##-*-coding:UTF-8-importtensorflowastfimportosinput_data=np.random.rand(2,1234)配置Sessionconfig,确保可以进入TensorFlowconfigconfig=tf.ConfigProto()config.graph_options.rewrite_options.min_graph_nodes=-1融合模式依赖TensorFlowTensorFlow44Sessionconfig=tf.ConfigProto()config.graph_options.rewrite_options.min_graph_nodes=-1withtf.Session(config=config)assess:withwithtf.Session(config=config)as#input=tf.placeholder(dtype=tf.float32,shape=(2,1234))weight=tf.constant(weight_data,dtype=tf.float32)matmul=tf.matmul(input,weight)#mlu_result=sess.run(["MatMul:0"],#CPUcpu_result=np.matmul(input_data,#打印MLU和CPU计算结果print("mlu_result:",mlu_result)print("cpu_result:",֒→0addedforsegment0consistingof1nodes('mlu_result:',[array([[314.6094,309.8875],[305.2355,305.2257]],dtype=float32)])('cpu_result:',array([[314.55574484,309.93644877],[305.27366373,305.3328487]]))支持以INT8和INT16模式进行计算。例如,Conv2D、MatMul。一般情况下,INT8的性能比INT16的性能更优。如果INT8INT8INT式的详细使用,参见INT。支持以float32(FP32)float16(FP16)Relu、MaxPool。一般情况下,float16开启float16keyMLUFusionOp在第二次迭代时,如果MLUFusionOpINT量化算子要使用INT模式进行计算需要先进行量化,CambriconTensorFlow提供了两种量化模式,在2在线量化方式时,量化算子默认使用INT8通过设置环境变量的方式进行离线量化,使用起来相对比较简单,且理论上可以支持TensorFlow通过量化工具进行离线量化,使用起来相对比较复杂,且只支持pb量化阶段。主要是计算量化算子的量化参数scale#量化位宽,8filter_channel_quant:true#可选参数:分通道量化,根据需求设置true/false,默认为igeqnm#量化模式,目前支持naive模式和igeqnm模式,当naive###node_name/input:input_scale bit_width、quant_mode、filter_channel_quant和convfirst_param的值需要在量化前设定,其中优化时配置,关于FirstConvFirstConv优化。scale_map入的,并且是以追加的方式写入,也就是说如果量化前scale_mapMLU_QUANT_PARAMMLU_RUNNING_MODE:用于指定是量化阶段还是运行阶段。0为量化阶段,1为运行阶段,默认值为1。加载TensorFlowimportimporttensorflowastfimportoswithopen(quant_param_file,'w')asf:f.write('bit_width:8\n')f.write('quant_mode:naive\n')osos.environ['MLU_QUANT_PARAM']=屏蔽所有MLU设备。离线量化必须在CPU上进行。osos.environ['MLU_VISIBLE_DEVICES']=osos.environ['MLU_RUNNING_MODE']=input_data=np.random.rand(2,1234)配置Sessionconfig,确保可以进入TensorFlowconfigconfig=tf.ConfigProto()config.graph_options.rewrite_options.min_graph_nodes=-1withwithtf.Session(config=config)asinput=tf.placeholder(dtype=tf.float32,shape=(2,1234))weight=tf.constant(weight_data,dtype=tf.float32)matmul=tf.matmul(input,weight)result=sess.run(["MatMul:0"],打开network_quant_param.txt文件,查看scale_map中是否有值,如下所示:如果scale_map–量化阶段依赖TensorFlow的图优化机制,但是TensorFlow44Sessionconfig。configconfig=tf.ConfigProto()config.graph_options.rewrite_options.min_graph_nodes=-1withtf.Session(config=config)assess:–如果使用的是Keras件是在SessionKeras内部的Sessionfromfromtensorflow.python.kerasimportbackendsession=backend.get_session()–Sessionwith语法自动管理SessionSessionclose加载TensorFlowimportimporttensorflowastfimportososos.environ['MLU_QUANT_PARAM']=MLU_RUNNING_MODE默认值为1osos.environ['MLU_RUNNING_MODE']=input_data=np.random.rand(2,1234)配置Sessionconfig,确保可以进入TensorFlowconfigconfig=tf.ConfigProto()config.graph_options.rewrite_options.min_graph_nodes=-1withwithtf.Session(config=config)asinput=tf.placeholder(dtype=tf.float32,shape=(2,1234))weight=tf.constant(weight_data,dtype=tf.float32)matmul=tf.matmul(input,weight)mlu_result=sess.run(["MatMul:0"],cpu_result=np.matmul(input_data,weight_data)print("mlu_result:",mlu_result)print("cpu_result:",cpu_result)[305.23404,305.2287]],dtype=float32)])('cpu_result:',array([[314.55574484,309.93644877],[305.27366373,305.3328487]]))我们提供了量化工具fppb_to_intpb来量化模型,工具位于TensorFlow根目录下tensorflow/cambricon_examples/tools/fppb_to_intpb/中。下面以ResNet50v1pythonpythonfppb_to_intpb.py其中,resnet50_v1_naive_int8.inidata_path= ;batch_size= ;每次运行的num_runs= ;batch_size=֒→runs=10data_path20= ;meanfile=./mean.txt ;h*w行每std= ;color_mode= ;rgb、bgr、crop=224,224 ;224*224大calibration=default_preprocess_cali ;校准数据读取及前处理的方式,可以根据需求进行自定义,[preprocess]和[data]中定义的参数均为calibration的输入original_models_path=path/to/resnet50_v1/resnet50_v1.pb;输入pbsave_model_path= ;输出input_tensor_names=input:0 ;Tensor的名称,可以是多个,以逗output_tensor_names=resnet_v1_50/predictions/Softmax:0 ;输出Tensor的名称,可以是多个,以逗 quantization_type=int_op_listConv2D,MatMul,LRN,Conv2DBackpropInputuse_convfirst=True;int8;要量化的layerthreshold_search。naive为基础模式,threshold_searchactivation_quantization_alg=;输入量化模式,可选naive;是否使用FirstConvthreshold_search。naive为基础模式,threshold_searchweight_quantization_alg=;权值量化模式,可选naivedevice_mode=clean clean、mluorigin。建议使用channel_quantization=fuse_filter_scales_to_bn=;;当channel_quantization为True关于如果color_mode是grey(即灰度图模式,则meantheshold_sach阈值搜索模式用于处理存在异常值的待量化数据集,该模式能够过滤部分异常值,是对于不存在异常值,数据分布紧凑的情况,比如网络权值的量化,不建议使用theshold_sach阈值搜索模式。关于mlu:将输出pb的所有节点的device设置为MLUclean:将输出pbdeviceorigin:使用输入pb(在int_op_list。mean与meanfile当前处理需要减去的均值为h*w*3(h,w分别为输入图片的高度和宽度)时,可使用meanfile。meanfile文件按h*wr/g/bmeanvaluemeanfilemeanfile_default_preprocess_cali关于calibration来定义前处理。meanfile下面以ResNet50v1ResNet50graph在ini文件中添加calibration的名称及其需要的参数。ini文件中的[data]和[preprocess]两个section下可以自定义calibrationResNet50batch_size、preprocessed_h和preprocessed_wimage_list,也可以指定为数据集的路径,只要在preprocess_cali类里面能根据data_path;data_pathbatch_size=num_runs= ;num_runspreprocessed_w=224 calibration= ;calibrationsave_model_path=./pbs/resnet50_v1/resnet50_v1_int8.pbinput_tensor_names=input:0quantization_type=use_convfirst=Falseactivation_quantization_alg=naiveweight_quantization_alg=naivechannel_quantization=Falsedevice_mode=上面提到的da_th为./image_list_imagenet,在这个例子中imae_lit_imaent内容如下:(下页继续据的方式能和这里定义的data_path添加resnet50_v1_preprocess_cali在tensorflow/cambricon_examples/tools/fppb_to_intpb/calibrate_data.py文件中添加为esNt50v1网络提供校准数据的类esnt50_v1_pepoess_alinit方法和nt方法的参数列表必须是init(sel,aams)和nt(self),ini文件中[da]和[pepoess]下定义的参数都会通过init的aams参数传入到这个类中,nt方法的返回值必须是网络的eed_di(Session.run的eed_di。比如为esNt50v1添加了下列代码:importdefread_image_batch(file_list,batch_size,ifbatch_size>raiseValueError("batch_sizemustbelessequalthanfile_listsize.")batch_data=[]start=iters*ifstart<end=start+batch_sizeif(start+batch_size)<len(file_list)elseforpathinfile_list[start:end]:print("Warning:batch_size*num_runs>file_listforpathinfile_list[-batch_size:]:returnbatch_datadefwithopen(input_image_list,"r")asimages_path=[line.strip()forlinein

returnclassdefinit(self,"""Getallnecessaryparametersfromself.iter=-self.file_list=read_file(params['data_path'])self.batch_size=int(params['batch_size'])self.out_h=int(params['preprocessed_h'])self.out_w=int(params['preprocessed_w'])self.input_tensor_names= #params[preprocess]和[data]下的参数,还会加入[model]下的def"""Readnextbatchinputsandpreprocessthem.Returnaself.iter+=batch_data=read_image_batch(self.file_list,self.batch_size,self.iter)batch_data=[self.resnet50_v1_preprocess(image)forimageinbatch_data]batch_data=np.asarray(batch_data)iflen(batch_data.shape)=="ifbatch_sizeisgreaterthan1.")return{self.input_tensor_names[0]:defresnet50_v1_preprocess(self,resize_side_min=ifresize_side_min<min(self.out_h,raiseValueError("resnet50_v1_preprocessresize_side_minmustbegreaterequal"{}vs.{}".format(resize_side_min,min(self.out_h,self.out_w)))image_h=image.shape[0]image_w=#scale=resize_side_min/min(image_h,image_w)resize_h=int(round(image_h*scale))resize_w=int(round(image_w*resized_image=cv2.resize(image.astype(np.float32),(resize_w, #offset_h=(resize_h-self.out_h)/2offset_w=(resize_w-self.out_w)/2croped_image=resized_image[offset_h:offset_h+self.out_h,last_image=croped_image-[mean_r,mean_g,returnresnet50_v1_preprocess_caliinitparams读取和前处理相关的参数以供nextparamsini[preprocess][data]的是paramsnext函数主要是进行输入数据的读取和前处理。需要注意的是如果网络的前处理包含在graph是一个字典,形式和session.run的feed_dictpreprocess_caliinit函数和next最后在tensorflow/cambricon_examples/tools/fppb_to_intpb/calibrate_data.py文件的get_calibrate_data函数的calibrate_data_mapdefdefget_calibrate_data(params,name="default_preprocess_cali"):print("calibrate_data:",name)calibrate_data_map={"no_preprocess_cali":no_preprocess_cali,"default_preprocess_cali":[preprocess]下面定义的名称,valuereturn"resnet50_v1_preprocess_cali":resnet50_v1_preprocess_cali,#keyini目前calibrate_data.py文件提供一些前处理的demo以供参考。关于FirstConvFirstConvTrue。关于FirstConv息,参见FirstConv。55CambriconTensorFlowC++支持的数[05][05][04][05][44][44]5.1–C++支持的数[05][05][05][04][44][05][05][05][05][05][05]C++支持的数[05][04][04][05][05][44][33][44][44]C++支持的数[11][05][05][05][05][05][05][05][25][34][22][05][05][05]5.1–C++支持的数[05][44][0,[44][44][05][44][44][05][05][44][05][05]C++支持的数[05][05][04][05][0,[05][44][44][0,[05][05][05][05]5.1–C++支持的数[0,[05][05][04][05][05][0,[0,[05][05][04][05][05]C++支持的数[05][44][44][05][05][05][04][05][05][05][05][05][05]C++支持的数[05][05][05][04][05]66本章以添加自定义激活算子Relu20为例,说明如何在CambriconTensorFlow注册OP在tensorflow/core/user_ops/mlu_special_ops.cc文件中,类比其他已有的自定义算子利用REGISTER_OP的宏注册Relu20.Input("features:.Output("activations:.Attr("T:{half,在REGISTER_OP根据算子的实际情况,可以先检查已封装的形状推断函数是否满足条件(在tensorflow/core/framework/common_shape_fns.h中,比如本例中Relu20指定的UnchangedShape)。如果不满足条件,需要自定义形状推断函数(形状推断的相关函数可以在tensorflow/core/framework/shape_inference.h找到,也可以参考其他自定义形状推断函数。以上就完成了Relu20注册OpKernelOpernel即注册的OpOpernel(M、CP。在tensorflow/core/kernels/mlu_kernels文件夹下,创建新文件relu20_op.cc。在该文件中利用REGISTER_KERNEL_BUILDER宏进行注册。使用该宏时,保证Name中的字符串和步骤1中REGITER_OP中的算子名称相同。通过调用TF_CALL_MLU_FLOAT_TYPES向REGISTER_MLUhalffloat(这里,#define#define #undef添加自定义算子时,除了注册MLUKernel,最好同时注册CPUKernel。如果缺乏CPU以下为注册CPUKernel在tensorflow/compiler/tf2mlu/convert/convert_nodes.cc的op_types_map(以op_name为key,data_typevalue)中加入新添加的算子及允许进入融合段的数据类型。constconstOpTypesMapop_types_map={"Abs",{{"T",{DT_FLOAT,//{"Relu20",{{"T",{DT_FLOAT,{"Relu20",{}}, 注册融合用的OpKernel(OpConverterstaticvoidRegisterValidatableOpConverters(std::unordered_mapstaticvoidRegisterValidatableOpConverters(std::unordered_map<string,OpConverter>*registration){(*registration)["ArgMax"]=//(*registration)["Relu20"]=之后添加对应Op的convert(具体实现,见后面的步骤:MLURelu20Layerlayer;在fp16 gtl::FlatSet<string>WhiteList()中加入staticstaticgtl::FlatSet<string>WhiteList()//autolist=gtl::FlatSet<string>//return在tensorflow/compiler/tf2mlu/convert/nodes文件夹下,创建新文件relu20.h现一个MLURelu20Layer类:////Copyright[2020]#define#includenamespacetensorflow{namespacemlu_fusion{namespaceconvert{classMLURule20LayerexplicitMLURelu20Layer(OpConverterContext*ctx)voidconvert(OpConverterContext*ctx)//添加必要的参数检查(可选if(!ctx->ValidateInputsAreSameShape(ctx))//ctxconstTensor&input=ctx-//添加必要的零元素检查(可选CONVERT_REQUIRES_NON_ZERO_ELEMENT(ctx,//添加输出//common_inc.hCONVERT_REQUIRES_OK(ctx,}//namespace}//namespace}//namespace#endif//之后需要在tensorflow/compiler/tf2mlu/convert/nodes/layers.h中加入新创建的头文件 relu20.h 在tensorflow/compiler/tf2mlu/convert/nodes/common_inc.h中有一个公共接口StatusStatusRelu20(OpConverterContext*ctx)returnCommonFusionImpl会默认使用OpConverterContext中的inputtensortensorflow/compiler/tf2mlu/convert/nodes/add_stride.h3.添加MLURelu20首先在tensorflow/stream_executor/mlu/mlu_api/ops/mlu_ops.h中声明之后在tensorflow/stream_executor/mlu/mlu_api/ops/中创建新文件relu20.cc,用于实现classMLURelu20的CreateMLUOp方法:#include#include"tensorflow/stream_executor/mlu/mlu_api/lib_ops/mlu_lib_ops.h"#include"tensorflow/stream_executor/mlu/mlu_api/ops/mlu_ops.h"#include"tensorflow/stream_executor/mlu/mlu_api/tf_mlu_intf.h"namespacemludoubleRelu20(doublex)return(x<0)?0:((x<20)?x:std::vector<cnmlTensor*>&outputs,void*param){TF_PARAMS_CHECK(inputs.size()>0,"Missinginput");TF_PARAMS_CHECK(outputs.size()>0,"Missingoutput");cnmlBaseOp*customized_active_op_ptr=nullptr;cnmlTensor*input=inputs.at(0);MLULOG(3)<<"Create<<",inputshape:"<<<<",outputshape:"<<double(*active_func_ptr)(double)=Relu20;reinterpret_cast<void*>(active_func_ptr),input,return}//namespace}//namespace}//namespace其中,lib::CreateCustomizedActiveOp实现在tensorflow/stream_executor/mlu/mlu_api/lib_ops/mlu_lib_ops.cc中,只是对底层接口的简单封装,根据实际需求添加即可。.修改BUILD4.添加OpKernel由于本章是介绍如何添加融合自定义算子,默认用户只有运行融合模式的需求。对于原生的OpKernel,只需添加一个空的实现即可。更多内容,参见《寒武纪TensorFlowclassMLURelu20Op:publicOpKernelexplicitMLURelu20Op(OpKernelConstruction*context):OpKernel(context){LOG(FATAL)<<"Relu20:noimplemented.";voidCompute(OpKernelContext*ctx)overrideclassCPURelu20Op:publicOpKernelexplicitCPURelu20Op(OpKernelConstruction*context):OpKernel(context)voidCompute(OpKernelContext*ctx)override{constTensor&input=ctx->input(0);Tensor*output=nullptr;OP_REQUIRES_OK(ctx,ctx->allocate_output(0,input.shape(),此处的CPURelu20Op这个Kerneloutput_shape修改BUILD在添加新算子过程中,只需要修改BUILDtensorflow/core/kernels/mlu_kernels/BUILD该文件主要完成以下内容:他targetmlu_core_kernelsrelu20_op作为新的依赖项,从而能够编译进整个TensorFlow在生成mlu_core_kernels目标函数的deps域中,添加一行":relu20_op"name=srcs=["relu20_op.cc"],deps=[#Publicsupportdeps=[...//在PythonAPI和C++API中分别通过调用Relu20和gen_user_ops.relu20importimportimportnumpyasnpimporttensorflowastffromtensorflow.python.opsimportconfig=tf.ConfigProto(log_device_placement=False)config.mlu_options.core_num=1config.graph_options.rewrite_options.constant_folding=2config.graph_options.rewrite_options.arithmetic_optimization=config.graph_options.rewrite_options.remapping=2sess=tf.Session(config=config)(下页继续deftest(x_shape,x_val=np.random.randint(-10,30,x=tf.placeholder(dtype=tf.float32,withres_mlu=gen_user_ops.relu20(x,mlu=sess.run(res_mlu,defmain():(16,(16,4,6,fori,shapeintest(shape,ifname=="main77tensordump使用tensordump功能将网络中各节点输出tensordump到指定文件夹,后使用误差计算工具输出将以下内容写入配置文件fusion_dump_config.iniexportTF_MLU_FUSION_DUMP_TENSOR=trueexport#.TENSORDUMP运行结束后,融合段的中间tensordumpPath所指定的文件夹中。dump出来的例如:2_resnet50.conv_1.conv2d_output_0_mlufusion_5其中,execution_times:该tensor被第几次dump(这个节点被第几次运行。此例中为2node_name:节点名称。此例中为resnet50.conv_1.conv2d。原本名称应为“/output_port:此文件是这个node0execution_order_in_fusion:此tensordump5如果开启了tensordump功能,每次运行前,必须清空fusion_dump_dir融合模式会有WarmUp的过程。如果运行网络的程序中存在使用假数据WarmUp预编译的代码,会导致dump使用tensordump因此,在使用tensordump功能进行精度调试时,需移除使用假数据WarmUp的代码。关于该工具的更多内容,参见《寒武纪TensorFlow在MLU上以融合模式运行并dumptensor将以下内容写入配置文件fusion_dump_config.iniexportTF_MLU_FUSION_DUMP_TENSOR=trueexport //在MLU上以nativedumptensorunsetunsetexportexport //cdcd(下页继续.MLU打开output_wrong.txt文件找到第一个误差大于阈值的节点。打开output_abnormal.txt文件找到第一个出现异常的节点。MLU中。内存越界的bug(出现的时机和出错的现象都是随机的,很难定位。别插入header和footer,在deallocate时拷回到host端检查之前插入的header和master打开MLU内存越界检查之后,程序会进入同步模式。计算图运行模式和默认不同,运行速度会变慢,有遇到日志中有[cnrtError]、mluunfinished这些关键字时,执行exportTF_MLU_DEBUG_MEMORY_OVERSTEP=true打开内存越界检查。如果出现coredump并且日志中有Footermaskhasbeenoverwritten或者Headermaskhasbeenoverwritten类似内容,说明存在20212021-01-1810:50:48.701641:[cnrtError][186985][Card:0]Erroroccurredin2021-01-1810:50:48.701678:[cnrtError][186985][Card:0]Returnvalueis230,֒→CHECKfailed.Function:MLUCnrtMemcpyAsync@line:221returnedcode632046:Unknownerror.֒→errordetected,forceterminating...Aborted(coredumped)若log[cnrtError],设置exportTF_MLU_DEBUG_MEMORY_OVERSTEP=true20212021-01-1811:15:05.364044:E֒→cc:141][230845]i=0mask=0xcdcdcdcdcdcdcdcd2021-01-1811:15:05.364053:E֒→cc:141][230845]i=1mask=0xcdcdcdcdcdcdcdcd2021-01-1811:15:05.364059:E֒→cc:229][230845]Footermaskhasbeenoverwritten,ptr=2021-01-1811:15:05.364067:E֒→cc:235][230845]wasallocated2021-01-1811:15:05.364238:I֒→cc:101][230845]call可以看出,新生成的logFootermaskhasbeenoverwritten遇到精度问题(比如,在CPU上运行结果正确,在MLU运行误差较大)一般需要先定位出哪个节点异常导致的,这就需要使用tensordump功能和误差计算工具。如果定位到的异常节点的算子是ConvMatMul为了进一步确认问题,可编写单算子测试,使用上一个节点dump出的output试CPU与MLU的结果。总之,无论是什么类型的精度异常,都可以优先通过dump功能找出异常节点,后处理该节点对应的以YOLOv4tensordump功能和误差计算工具定位精度问题节点。在执行以下步骤前,确保已安装CambriconTensorFlowcdcd$TENSORFLOW_BENCHMARK_HOME/benchmarks/cn_benchmarks/YOLO/Keras-./run_evaluate.sh111执行成功后,会在当前目录下生成量化参数文件yolov4_quant_param_int16.txt本例中,将import/conv2d_27/convolution/input1331.080.1YOLOv4predictsessionrun:一次编译,另一次真正执行。如果不注释掉会dump两次tensor,浪费时间。vivi$TENSORFLOW_BENCHMARK_HOME/models/third_party/Keras-注释掉predict3defpredict(self,#if(self.cur_iter==-self.cur_iter+=start=self.input_ph:dumpCPU上的运算结果作为真值。mkdirmkdirexportexportexport./run_evaluate.sh111dumpMLU上的运算结果用于比对。mkdirmkdirexportexportexportexportexport(下页继续export./run_evaluate.sh111对比结果:使用误差计算工具对比CPU和MLUlnln-s$TENSORFLOW_HOME/tensorflow/cambricon_examples/tools/debug_tool/֒→dumps_mlu--output_wrong.txt、output_all.txt````output_wrong.txt文件,第一个节点就是异常节点,节点import.conv2d_27.convolution即为模拟异常步骤中修改的节点。truth_value_file:import.conv2d_27.convolution_output_0_740test_value_file:1_import.conv2d_27.convolution_output_0_mlufusion_86tensor_name:import/conv2d_27/convolution:0iteration:error_rate:is_same_size:truth_value_file:import.batch_normalization_27.FusedBatchNorm_1_output_0_741iteration:error_rate:is_same_size:有时可能无法设置一个合适的threshold恰好过滤出异常节点,可以通过查看output_all.txt文件点的error_rateerror_rate的节点由于可能会受到异常节点的影响,其error_rate本例中可以看出import.conv2d_27.convolutiontruth_value_file:import.mish_25_output_0_738test_value_file:1_import.mish_25_output_0_mlufusion_84tensor_name:import/mish_25:0iteration:error_rate:mse:is_same_size:truth_value_file:import.add_6.add_output_0_739test_value_file:1_import.add_6.add_output_0_mlufusion_85tensor_name:import/add_6/add:0iteration:error_rate:mse:is_same_size:truth_value_file:import.conv2d_27.convolution_output_0_740test_value_file:1_import.conv2d_27.convolution_output_0_mlufusion_86tensor_name:import/conv2d_27/convolution:0iteration:error_rate:mse:is_same_size:88在使用CambriconTensorFlow运行网络之前先进行离线量化。相比在线量化,离线量化的性能更好。关于离线量化的更多内容,参见离线量化。使用FP16运行网络时设置环境变量TF_MLU_FP16_OPTIMIZATION_LEVEL1以开启FP16模式。在FP16足网络精度的情况下,相比于FP32,FP161、4、16。使用Pythonconfigconfig=tf.ConfigProto()withtf.Session(config=config)assess:result=sess.run(...)使用CC++SessionOptionsSessionOptionsoptions;std::unique_ptr<Session>session(NewSession(options));.使用FROZEN使用frozen融合模式理论上支持TensorFlowfrozengraph格式的模型,建议先转换为frozengraph,后再运行融合模式。以下介绍如何将SavedModel和ckpt转换为frozengraph将SavedModel转换成frozenwithwithtf.Session()assess:frozen_graph=tf.graph_util.convert_variables_to_constants(output_node_names=['logits','classes'])将ckptfrozenwithwithtf.Session()as#Firstcreatea`Saver`object(forsavingandrebuilding#model)andimportyour`MetaGraphDef`protocolbufferintoit:saver=tf.train.import_meta_graph("/path/to/your/model.ckpt.meta")#Thenrestoreyourtrainingdatafromcheckpointfiles:saver.restore(sess,"/path/to/your/model.ckpt")#Finally,freezethefrozen_graph=tf.graph_util.convert_variables_to_constants(output_node_names=['logits','classes'])增大batch当batchsizebatchsizebatchsize1416minimum_sgment_si被替换成MUusionO1替换为MUusionO。如果在调试中遇到某个融合段有功能问题(比如出现crash)或者性能问题时,可将最小分段数设置为exportexportFirstConv优化是底层CNML库针对网络的首层Conv2DConv2DFirstConv输入的CCNMLFirstConvConv2DC13。inputimagemeanstd其中,input表示网络首层Conv2Dimagemean和std细介绍,参见离线模式简介。.FIRSTCONV使用环境变量量化时,如果要使用FirstConv优化,需要在量化阶段配置量化参数文件时,增加convfirst_param#Conv2D###meanfilestd和color_mode,还需要将use_convfirst的值设为True。如下所示:mean=123.68,116.78,;每行依次为mean_r、mean_g、mean_b,以逗号隔开,与meanmeanfile=;h*wstd=color_mode=;rgb、bgr、;use_convfirst=Conv2D当使用FirstConv优化时,如果将首层Conv2D的输入的C4,可以进一步提升首层Conv2D算子的性能。但是,由于补齐操作会额外引入其他开销,影响整体性能,因此默如果是离线部署,而且CPU算力足够,可以在生成离线模型时执行补齐操作并且放到CPU上运行,这样可以获得更优的全局性能。关于离线模式的详细介绍,参见离线模式简介。CambriconTensorFlow提供环境变量TF_MLU_ADD_STRIDE来控制是否执行补齐操作以及补齐操作运行成离线模型时设置相应的值即可,例如,执行exportTF_MLU_ADD_STRIDE=1。99TensorFlow框架基于CNML(CambriconNeuwareMachineLearning,寒武纪机器学习库)在线构建融合模型,并将编译过程中生成的MLU指令、数据等写入到文件,该文件称为离线模型。离线模型包含模型版本、MLU指令、权值数据、输入输出数据规模、参数信息等。用户通过CNRT(CambriconNeuwareRuntimeLibrary,寒武纪运行时库)API加载离线模型并驱动MLU完成计算的运行模式称为离线模式可免去编译过程所产生的开销,减少了运行依赖,也避免了对TensorFlow框架和CNML等的不是所有在TensorFlow关于如何查看网络是否为单段的更多信息,参见FAQTensorFlowpb_to_cambricon和使用SessionConfigpb_to_cambricon为单独使用的工具,仅依赖独立编译的二进制文件;SessionConfig使用时需依赖TensorFlowdemo。pb_to_cambricon工具除MLUCPUMLU270或者MLU220SessionConfigMLU离线模型生成工具pb_to_cambricon为C++cdcd若当前目录下生成pb_to_cambricon.host如果仅想使用离线功能,无需整体编译TensorFlow,编译build_host.sh即可 --------‑‑gap:需要转换成离线模型的pb文件。使用离线工具前,要确保pb在线模式可以单段运行成功,如旧量化模式下的MU量化模型作为输入,亦或在新量化模式下设置好在线运行环境变量和量化文件,将与其对应的原生pb模型作为输入。‑‑mlu_core_version:目标支持的MLU卡。目前支持MLU270、MLU220、1M70、1M20‑‑oe_nuMUMU270oe_num可设置为1416MU220oe_num可设置为1、4;对于1M70和1M20,oe_num仅可设置为1。不同核数对应的离线文件不同。用“,”分隔。目前支持的keys支持的option_keys。 input_nodes指定模型的Session::Run指定Session::Run信息数字n表示输入节点的个数,“xxxx名称dim_size(0)dim_size(n‑Shapedim_size(0)模型输入的batch_size注:模4指定Session::Runn以ResNet50v1和SSD(下页继续9.2:支持的对于保存离线模型的参数,要在创建SessionConfigPythonC++赖的环境为安装CambriconTensorFlow的环境。有关安装CambriconTensorFlow《寒武纪TensorFlowoffline_model_name:指定离线模型的名称。string类型,默认为offline_model configconfig=**config.mlu_options.save_offline_model=withtf.Session(graph=graph,config=config)asC++SessionOptionsSessionOptionsoptions;**session_config.mutable_mlu_options()-std::unique_ptr<tensorflow::Session>session(tensorflow::NewSession(options));session->Run(...在TensorFlow中,提供基于ImageNetcd/tensorflow_srcsourceenv.shcdcd/tensorflow_srcsourceenv.shcdcd./classify_offlinecd./classify_offline--offline_model=${offline_model}--images_file=${file_list_

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论