本文用于记录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 *= -1

dtype = trt.nptype(engine.get_binding_dtype(binding))

# Allocate host and device buffers

host_mem = cuda.pagelocked_empty(size, dtype)

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

for binding in engine:

bind = engine.get_binding_shape(binding)

vol = trt.volume(bind)

# size = trt.volume(engine.get_binding_shape(binding)) * engine.max_batch_size

if binding == 'input':

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

else:

size = trt.volume(engine.get_binding_shape(binding)) * batch_size * math.ceil(h_ / 4) * math.ceil(w_ / 4)

if size < 0:

size *= -1

dtype = trt.nptype(engine.get_binding_dtype(binding))

# Allocate host and device buffers

host_mem = cuda.pagelocked_empty(size, dtype)

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

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

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

@parse_args('v', 'v', 'v', 'v', 'v', 'i', 'f', 'f', 'i')

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

cudnn_enabled):

axes = [-i for i in range(2, 0, -1)]

two_cst = g.op("Constant", value_t=torch.tensor(2.))

eps_cst = g.op("Constant", value_t=torch.tensor(eps))

mean = g.op("ReduceMean", input, axes_i=axes)

numerator = sub(g, input, mean)

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

variance = g.op("ReduceMean", pow(g, numerator, two_cst), axes_i=axes)

denominator = sqrt(g, add(g, variance, eps_cst))

inst_norm = div(g, numerator, denominator)

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

inst_norm = mul(g, inst_norm, weight)

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

inst_norm = add(g, inst_norm, bias)

return inst_norm

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

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

@parse_args('v', 'v', 'v', 'v', 'v', 'i', 'f', 'f', 'i')

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

cudnn_enabled):

axes = [-i for i in range(2, 0, -1)]

two_cst = g.op("Constant", value_t=torch.tensor(2.))

eps_cst = g.op("Constant", value_t=torch.tensor(eps))

mean = g.op("ReduceMean", input, axes_i=axes)

numerator = sub(g, input, mean)

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

variance = g.op("ReduceMean", pow(g, numerator, two_cst), axes_i=axes)

denominator = sqrt(g, add(g, variance, eps_cst))

inst_norm = div(g, numerator, denominator)

weight = g.op("Unsqueeze", weight, axes_i=[-1])

weight = g.op("Unsqueeze", weight, axes_i=[-1])

bias = g.op("Unsqueeze", bias, axes_i=[-1])

bias = g.op("Unsqueeze", bias, axes_i=[-1])

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

inst_norm = mul(g, inst_norm, weight)

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

inst_norm = add(g, inst_norm, bias)

return inst_norm

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

tersorrt安装_pytorch/mxnet模型tensorrt部署相关推荐

  1. 实践教程 | TensorRT部署深度学习模型

    作者 | ltpyuanshuai@知乎 来源 | https://zhuanlan.zhihu.com/p/84125533 编辑 | 极市平台 本文仅作学术分享,版权归原作者所有,如有侵权请联系删 ...

  2. TensorRT部署深度学习模型

    1.背景 目前主流的深度学习框架(caffe,mxnet,tensorflow,pytorch等)进行模型推断的速度都并不优秀,在实际工程中用上述的框架进行模型部署往往是比较低效的.而通过Nvidia ...

  3. 收藏 | TensorRT部署深度学习模型

    点上方计算机视觉联盟获取更多干货 仅作学术分享,不代表本公众号立场,侵权联系删除 转载于:作者 | ltpyuanshuai@知乎 来源 | https://zhuanlan.zhihu.com/p/ ...

  4. keras保存模型_onnx+tensorrt部署keras模型

    由于项目需要,最近捣鼓了一波如何让用tensorrt部署训练好的模型来达到更快的推理速度,期间花费了大量的时间在知乎和各种网页上去搜索别人的方案,但始终没有找到我想要的条理相对清晰的记录贴(也许只是我 ...

  5. tensorRT 部署 YOLOV5模型详解

    tensorRT 部署 YOLOV5模型详解 第一步: 下载tensorRT库 https://developer.nvidia.com/nvidia-tensorrt-8x-download 欢迎使 ...

  6. win10下 yolov8 tensorrt模型加速部署【实战】

    Windows10下yolov8 tensorrt模型加速部署[实战] TensorRT-Alpha基于tensorrt+cuda c++实现模型end2end的gpu加速,支持win10.linux ...

  7. 图像分类实战:mobilenetv2从训练到TensorRT部署(pytorch)

    文章目录 摘要 mobilenetv2简介 线性瓶颈 倒残差 ONNX TensorRT 项目结构 训练 数据增强Cutout和Mixup 导入包 设置全局参数 图像预处理与增强 读取数据 设置模型 ...

  8. 谈谈机器学习模型的部署

    随着机器学习的广泛应用,如何高效的把训练好的机器学习的模型部署到生产环境,正在被越来越多的工具所支持.我们今天就来看一看不同的工具是如何解决这个问题的. 上图的过程是一个数据科学项目所要经历的典型的过 ...

  9. MxNet 模型转Tensorflow pb模型

    用mmdnn实现模型转换 参考链接:https://www.twblogs.net/a/5ca4cadbbd9eee5b1a0713af 安装mmdnn pip install mmdnn 准备好mx ...

  10. 400 fps!CenterFace+TensorRT部署人脸和关键点检测

    本文转载自知乎,为CenterFace原作者手把手教程,欢迎参考. https://zhuanlan.zhihu.com/p/106774468 近来,很多人在使用tensorrt部署centerfa ...

最新文章

  1. 能做pc网页吗_梦幻西游网页版:如今还能抽金伙伴吗?玩家亲自验证,感觉还行...
  2. 提高PHP运行速度的小技巧
  3. saltstack之(十二)配置管理mount
  4. Java 使用ZeroMQ 2.2 进行通信编程
  5. python将字符串中的数字相加求和的实现
  6. lua脚本简单编辑及常用指令
  7. java获取web.xml 参数_解析web.xml中在Servlet中获取context-param和init-param内的参数
  8. leetcode474. 一和零(动态规划)
  9. OpenJudge NOI 1.7 32:行程长度编码
  10. imagick php手册,windows7下安装php的imagick和imagemagick扩展教程
  11. 系分 - 企业信息化战略与实施
  12. 回溯算法符号三角形java_算法设计与分析——符号三角形问题(回溯法)
  13. web端--斗图Tenor api 接入
  14. skynet:cluster
  15. 基于Phyton爬虫索引设计与实现答辩PPT模板
  16. Android 调用手机相册、摄像头拍照及剪裁照片
  17. 阿里云推出区域经济大脑 | 苹果发布机器学习框架Turi Create | 工业超市震坤行完成2亿元B+轮融资
  18. 设置用户ID位是什么意思
  19. 【nacos】springboot @Value @NacosValue 使用时可能无效
  20. ARM汇编指令—CPSR访问指令(mrsmsr)

热门文章

  1. 文件系统错误故障排除
  2. 12款常用的Web服务器软件整理(windows+Linux)
  3. IE编程1(.net)——读取IE窗口信息
  4. js根据url下载文件并重命名,兼容ie11(其他版本未测试)
  5. Android7.0调用系统相机拍照、读取系统相册照片+CropImageView剪裁照片
  6. Acrel-2000T无线测温产品方案介绍(安科瑞-须静燕)
  7. java中使用jxls导出excel,excel单元格换行,多sheet页导出
  8. 三十岁那年,我的梦想是年薪十万
  9. C语言常见缩写和英文
  10. Java实现 LeetCode 108 将有序数组转换为二叉搜索树