热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

tersorrt安装_pytorch/mxnet模型tensorrt部署

本文用于记录pytorchmxnet模型使用tersorrt的整个流程以及遇到的坑。tensorrt支持TensorFlow的uff和onnx以及自定义模型的推理加速,


本文用于记录pytorch/mxnet模型使用tersorrt的整个流程以及遇到的坑。


tensorrt支持TensorFlow的uff和onnx以及自定义模型的推理加速,对于pytorch有第三方接口torch2trt项目,但是这个需要定义好模型在加入,不能把模型和tensorrt分离


import torch


from torch2trt import torch2trt


from torchvision.models.alexnet import alexnet


# create some regular pytorch model...


model = alexnet(pretrained=True).eval().cuda()


# create example data


x = torch.ones((1, 3, 224, 224)).cuda()


# convert to TensorRT feeding sample data as input


model_trt = torch2trt(model, [x])


部署的时候还依赖pytorch环境,就没尝试。


mxnet官方是有接口直接转tensorrt的,


arg_params.update(aux_params)


all_params = dict([(k, v.as_in_context(mx.gpu(0))) for k, v in arg_params.items()])


executor = mx.contrib.tensorrt.tensorrt_bind(sym, ctx=mx.gpu(0), all_params=all_params,data=batch_shape, grad_req='null', force_rebind=True)


y_gen = executor.forward(is_train=False, data=input)


y_gen[0].wait_to_read()


这个也没有尝试,主要还是想部署时分离,只用tensorrt环境,不需要装深度学习全家桶


pytorch和mxnet转换为onnx的模型官方都有接口和文档,使用方法也很简单


#mxnet转onnx


sym = './resnet-50-symbol.json'


params = './resnet-50-0000.params'


input_shape = (1, 3, 224, 224)


onnx_file = './resnet-50.onnx'


converted_model_path = onnx_mxnet.export_model(sym, params, [input_shape], np.float32, onnx_file)


#pytorch转onnx


import torch


import torchvision


dummy_input = torch.randn(10, 3, 224, 224, device='cuda')


model = torchvision.models.alexnet(pretrained=True).cuda()


# Providing input and output names sets the display names for values


# within the model's graph. Setting these does not change the semantics


# of the graph; it is only for readability.


#


# The inputs to the network consist of the flat list of inputs (i.e.


# the values you would pass to the forward() method) followed by the


# flat list of parameters. You can partially specify names, i.e. provide


# a list here shorter than the number of inputs to the model, and we will


# only set that subset of names, starting from the beginning.


input_names = [ "actual_input_1" ] + [ "learned_%d" % i for i in range(16) ]


output_names = [ "output1" ]


torch.onnx.export(model, dummy_input, "alexnet.onnx", verbose=True, input_names=input_names, output_names=output_names)


转onnx问题记录


自定义层SegmentConsensus 不识别


对于自定义层,在pytorch转onnx需要自定义,onnx转trt是还需要自定义,对于这种层还是建议搞懂底层原理,用基础的操作来实现,这个层比较简单,使用了mean和index_select操作实现了


TracerWarning: There are 2 live references to the data region being modified when tracing in-place operator copy_ (possibly due to an assignment). This might cause the trace to be incorrect, because all other views that also reference this data will not reflect this change in the trace! On the other hand, if all other views use the same memory chunk, but are disjoint (e.g. are outputs of torch.split), this might still be safe


这个错误是说修改的数据有两个引用导致无法trace,错误的代码如下:


out[:, :-1, :fold] = x[:, 1:, :fold] # shift left


out[:, 1:, fold: 2 * fold] = x[:, :-1, fold: 2 * fold] # shift right


out[:, :, 2 * fold:] = x[:, :, 2 * fold:] # not shift


查了一些资料应该是说左边赋值是一个引用,切片又是一个引用,两个引用无法trace,那么把切片使用index_select替换


left_side = torch.cat((x[:, 1:, :fold], torch.zeros(1, 1, fold, h, w)), dim=1)


middle_side = torch.cat((torch.zeros(1, 1, fold, h, w), x[:, :n_segment - 1, fold: 2 * fold]), dim=1)


out = torch.cat((left_side, middle_side, x[:, :, 2 * fold:]), dim=2)


模型部分转换为onnx


保存的模型可能是pretrained的模型,实际使用中只需要用部分层,对于mxnet可以在sym文件中直接指定出口层,再转换即可


sym, arg_params, aux_params = mx.model.load_checkpoint(pretrained, epoch)


sym = get_output_sym(sym, 'fc1_output')


arg_params.update(aux_params)


onnx_mx.export_model(sym, arg_params, input_shape, onnx_file_path=onnx_file_path, verbose=True)


对于pytorch可以继承torch.nn.Module将模型传进来自己进行修改定制


class ExtractFeature(torch.nn.Module):


def __init__(self, cnn, frames=16):


super().__init__()


self.model = cnn


self.num_segments = frames


self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")


def forward(self, data):


# st = time.time()


# print('feature extracting start')


n = self.model


pool = torch.nn.MaxPool2d(3,2)


with torch.no_grad():


input= data.view((-1, 3) + data.size()[-2:]).to(self.device)


x=n.conv1(input)


x=n.bn1(x)


x=n.relu(x)


x=n.maxpool(x)


x=n.layer1(x)


x=n.layer2(x)


x=n.layer3(x)


x=n.layer4(x)


x=pool(x)


x=x.flatten(start_dim=1)


ndata=x


data=ndata.view((-1, self.num_segments) + ndata.size()[1:])


return data


模型调用不使用默认的forward


模型继承torch.nn.Module,该类有个__call__方法可以使类可以像函数一样被调用,在__call__中调用了apply方法最终调用到forward方法,如果模型使用中不使用forward方法,该怎么转onnx呢?如下这种


out = net.forward_features(x)


显式调用了forward_features方法,开始想通过继承方式,将forward_features函数直接返回父类的forward,其实可以直接修改方法的指向,像下面这样直接修改指向即可


OCR.forward = OCR.forward_ocr


Exporting the operator GatherElements to ONNX opset version 9 is not supported


opset9 不支持该op,可以将opset version调高,目前最高是12,越高支持的op越多,opset_version默认是9


torch.onnx.export(model, dummy_input, "alexnet.onnx", verbose=True, input_names=input_names, output_names=output_names,opset_version=11,)


dynamic input


动态输入包括batchsize, 以及可变h,w,使用dynamic_axes参数指定可变的维度


torch.onnx.export(OCR, dummy_input ,onnx_ocr_forword_ocr_path,


input_names=['input'],


output_names=['segm_pred', 'segm_pred2', 'rbox', 'rbox2', 'angle', 'angle2', 'x'],


opset_version=11,


dynamic_axes={"input": {0: 'batch',2:'h', 3:'w'}})


onnxruntime测试


模型转换完成后需要测试onnx的模型和原模型的输出是否一致,先用onnxruntime来跑模型,运行时报错can’t load culib 10.1,找不到cuda库,查看了代码和官方文档,明确指定只支持cuda10.1,不是对应的版本重新安装对应的版本即可



tensorrt问题记录


在tensorrt官网下载最新的tensorrt7.1版本,安装好后,配置环境变量,库里面都是so库,和一些c文件,无法import tensorrt,查看官网说明发现tensorrt 的Python接口是不支持Windows的,无法在Windows下用Python接口



[TensorRT] ERROR: …/rtSafe/cuda/caskConvolutionRunner.cpp (290) - Cask Error in checkCaskExecError: 7 (Cask Convolution execution)


[TensorRT] ERROR: FAILED_EXECUTION: std::exception


这个问题是因为创建的engine和执行不在一个线程中,使用了多线程,将创建和执行放在一个线程中


[TensorRT] ERROR: …/rtSafe/cuda/cudaConvolutionRunner.cpp (303) - Cudnn Error in execute: 7 (CUDNN_STATUS_MAPPING_ERROR)


[TensorRT] ERROR: FAILED_EXECUTION: std::exception


创建engine后不使用to(device)和cuda操作,pytorch和mxnet都需要将模型和数据cuda操作,需要删除


[TensorRT] WARNING: Explicit batch network detected and batch size specified, use execute without batch size instead.


[TensorRT] ERROR: Parameter check failed at: engine.cpp::resolveSlots::1024, condition: allInputDimensionsSpecified(routine)


动态batchsize tensorrt不能直接构建engine,需要设置profile构建


profile = builder.create_optimization_profile()


profile.set_shape(


ModelData.INPUT_NAME,


ModelData.MIN_INPUT_SHAPE,


ModelData.OPT_INPUT_SHAPE,


ModelData.MAX_INPUT_SHAPE)


config.add_optimization_profile(profile)


engine = builder.build_engine(network,config)


[TensorRT]ERROR: …/rtSafe/safeRuntime.cpp (25) - Cuda Error in allocate: 2 (out of memory)


看起来像是显存爆了,nvidia-smi -l 打开显存实时占用发现显存还剩很多,调试运行后发现分配的buffer size未负数,当使用动态batchsize时候第一个维度变成了-1,分配的size是负数就失败了,将负数变成正数在*batchsize分配buffer


size = trt.volume(engine.get_binding_shape(binding)) * batch_size


if size <0:


size *&#61; -1


dtype &#61; trt.nptype(engine.get_binding_dtype(binding))


# Allocate host and device buffers


host_mem &#61; cuda.pagelocked_empty(size, dtype)


dynamic input&#xff0c;目标检测输入宽高不确定&#xff0c;和问题4中batchsize问题一样也需要在profile中设置H/W的最小值、典型值和最大值&#xff0c;还需要在allocate_buffers时传入w/h&#xff0c;如果不传入默认都是-1&#xff0c;算出来的size会很小&#xff0c;binding分别为输入和输出计算size并分配buffer&#xff0c;需要分别传入输入和输出的h_和w_


for binding in engine:


bind &#61; engine.get_binding_shape(binding)


vol &#61; trt.volume(bind)


# size &#61; trt.volume(engine.get_binding_shape(binding)) * engine.max_batch_size


if binding &#61;&#61; &#39;input&#39;:


size &#61; trt.volume(engine.get_binding_shape(binding)) * batch_size * h_ * w_


else:


size &#61; trt.volume(engine.get_binding_shape(binding)) * batch_size * math.ceil(h_ / 4) * math.ceil(w_ / 4)


if size <0:


size *&#61; -1


dtype &#61; trt.nptype(engine.get_binding_dtype(binding))


# Allocate host and device buffers


host_mem &#61; cuda.pagelocked_empty(size, dtype)


[TensorRT] ERROR: instance normalization doesn’t support dynamic input


instance normalization 不支持动态输入&#xff0c;又是在目标检测模型中使用的&#xff0c;无法规避&#xff0c;这个问题也可以归类为不支持的op,可以


在onnx自定义op然后在tensorrt定义plugin,也可以重写op&#xff0c;这里使用重写op实现&#xff0c;在torch/onnx/symbolic_opset9.py中将原有的instance_norm函数改写如下


&#64;parse_args(&#39;v&#39;, &#39;v&#39;, &#39;v&#39;, &#39;v&#39;, &#39;v&#39;, &#39;i&#39;, &#39;f&#39;, &#39;f&#39;, &#39;i&#39;)


def instance_norm(g, input, weight, bias, running_mean, running_var, use_input_stats, momentum, eps,


cudnn_enabled):


axes &#61; [-i for i in range(2, 0, -1)]


two_cst &#61; g.op("Constant", value_t&#61;torch.tensor(2.))


eps_cst &#61; g.op("Constant", value_t&#61;torch.tensor(eps))


mean &#61; g.op("ReduceMean", input, axes_i&#61;axes)


numerator &#61; sub(g, input, mean)


# variance &#61; e((x - e(x))^2), and (x - e(x)) is the numerator in the layer_norm formula


variance &#61; g.op("ReduceMean", pow(g, numerator, two_cst), axes_i&#61;axes)


denominator &#61; sqrt(g, add(g, variance, eps_cst))


inst_norm &#61; div(g, numerator, denominator)


if not (weight is None or weight.node().mustBeNone()):


inst_norm &#61; mul(g, inst_norm, weight)


if not (bias is None or bias.node().mustBeNone()):


inst_norm &#61; add(g, inst_norm, bias)


return inst_norm


instance_norm改写后报mul elementwise dimension mismatch [1,256,4,8]and [1,1,1,256]


乘法维度不匹配&#xff0c;mul是在计算完均值和方差后成γ参数时报错的&#xff0c;根据pytorch的broadcasting 机制&#xff0c;不同维度的数据会通过expand和repeat操作达到相同维度&#xff0c;但是expand是尾部对齐&#xff0c;变成四维后增加的维度都在前面&#xff0c;最后一个维度都不是1无法进行repeat操作&#xff0c;导致维度不匹配&#xff0c;那直接UNsqueeze两维出来将channel放在第二个维度再broadcasting 就可以维度相同了


&#64;parse_args(&#39;v&#39;, &#39;v&#39;, &#39;v&#39;, &#39;v&#39;, &#39;v&#39;, &#39;i&#39;, &#39;f&#39;, &#39;f&#39;, &#39;i&#39;)


def instance_norm(g, input, weight, bias, running_mean, running_var, use_input_stats, momentum, eps,


cudnn_enabled):


axes &#61; [-i for i in range(2, 0, -1)]


two_cst &#61; g.op("Constant", value_t&#61;torch.tensor(2.))


eps_cst &#61; g.op("Constant", value_t&#61;torch.tensor(eps))


mean &#61; g.op("ReduceMean", input, axes_i&#61;axes)


numerator &#61; sub(g, input, mean)


# variance &#61; e((x - e(x))^2), and (x - e(x)) is the numerator in the layer_norm formula


variance &#61; g.op("ReduceMean", pow(g, numerator, two_cst), axes_i&#61;axes)


denominator &#61; sqrt(g, add(g, variance, eps_cst))


inst_norm &#61; div(g, numerator, denominator)


weight &#61; g.op("Unsqueeze", weight, axes_i&#61;[-1])


weight &#61; g.op("Unsqueeze", weight, axes_i&#61;[-1])


bias &#61; g.op("Unsqueeze", bias, axes_i&#61;[-1])


bias &#61; g.op("Unsqueeze", bias, axes_i&#61;[-1])


if not (weight is None or weight.node().mustBeNone()):


inst_norm &#61; mul(g, inst_norm, weight)


if not (bias is None or bias.node().mustBeNone()):


inst_norm &#61; add(g, inst_norm, bias)


return inst_norm


原文链接:https://blog.csdn.net/u011605951/article/details/108441935




推荐阅读
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • WPF之Binding初探
      初学wpf,经常被Binding搞晕,以下记录写Binding的基础。首先,盗用张图。这图形象的说明了Binding的机理。对于Binding,意思是数据绑定,基本用法是:1、 ... [详细]
  • java布尔字段用is前缀_POJO类中布尔类型的变量都不要加is前缀详解
    前言对应阿里巴巴开发手册第一章的命名风格的第八条。【强制】POJO类中布尔类型的变量都不要加is前缀,否则部分框架解析会引起序列化错误。反例:定义为基本 ... [详细]
  • 代码如下:#coding:utf-8importstring,os,sysimportnumpyasnpimportmatplotlib.py ... [详细]
  • 对于我当前的需求,我需要绘制一些我从mongodb中获取的数据的图表,并且我正在使用reactPo ... [详细]
  • 我正在尝试使用 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 本文介绍了游标的使用方法,并以一个水果供应商数据库为例进行了说明。首先创建了一个名为fruits的表,包含了水果的id、供应商id、名称和价格等字段。然后使用游标查询了水果的名称和价格,并将结果输出。最后对游标进行了关闭操作。通过本文可以了解到游标在数据库操作中的应用。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • KVC:Key-valuecodingisamechanismforindirectlyaccessinganobject’sattributesandrelations ... [详细]
  • 3.5.2Calc的公式语法:使用Calc计算一个公式可用是任何能够被Emacs的calc包所识别的代数表达式.注意,在Calc中,的操作符优先级要比*低,因此ab*c会被解释为a ... [详细]
  • pytorch Dropout过拟合的操作
    这篇文章主要介绍了pytorchDropout过拟合的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完 ... [详细]
  • 集合set集合是可变的容器集合内的数据对象都是唯一的(不能重复多次的)集合是无序的存储结构,集合中的数据没有先后关系集合内的元素必须是不可 ... [详细]
author-avatar
lenpre2017
林频仪器(http://www.linpin.com/)主营产品:盐雾试验箱、高低温试验箱、恒温恒湿试验箱,林频仪器是中国环境试验设备行业中唯一的股份制高新技术企业,是中国领先的环境试验设备制造商和可靠性环境试验解决方案综合服务商,拥有中国最大的环境试验设备生产基地,客户遍布全球40多个国家和地区。林频仪器现已发展成为环境试验设备领域的龙头企业。 ■ 凭借创新的产品、高效的供应链和强大的战略执行力,林频仪器锐意为全球用户打造优质、安全、环保的产品及专业高效的服务。 ■ 林频仪器产品系列包括:温
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有