在进行YOLOX的libtorch部署的时候,发现官方提供的代码里面解码的那一部分运行时间太长了,需要大概3秒钟,这个是远远不能达到应用需求的,但是作为一个土生土长的算法工程师,除了python以外,对其他的编程语言了解并不多,所以干脆就在python里面进行模型的解码,期望是模型输出的结果就是四个坐标点、分类以及置信度,但是在写完后处理之后,发现打包出来的torchscript在C++中不能forward(模型load是正常的),forward会导致程序异常退出,具体报错如下:
进程已结束,退出代码为 -1073740791 (0xC0000409)
这个是异常退出了,网上关于这个错误的帖子很多,但是都不是关于C++的,所以并没有解决我的问题。
搞了半天发现这个不是C++的问题,是打包出来的torchscript模型本身有问题,下面是我的解决方案:
首先是为什么会出这么一个错误,出错行代码如下:
index = torch.where(iou < 0.3)
_boxes = b_boxes[index]
这个是在做NMS的时候根据iou的值选择出需要保留的框的索引,然后根据索引将框取出来,这行代码在pytorch里面一点问题都没有,是可以顺利运行出结果的,但是打包成torchscript的时候就出问题了,因为torchscript只是python和pytorch的一个子类,并不是所有的python *** 作和pytorch *** 作都支持。
最坑的是它在打包的时候不会告诉你这个 *** 作在torchscript里面是不支持的,这个问题对于初学者来说是非常不友好的,因为它不给我报错,所以我不知道这个问题应该如何去解决,如果想知道到底哪一行代码出错,就需要一行一行的注释,一行一行的去找,这样太慢了,有时候甚至找不出来。
下面提供一种可能有效的思路,可以找到哪一行代码出了问题:
这个也很简单,就是在打包好之后通过pytorch进行解码再进行推理,如果推理过程出错的话python这边就会告诉你哪个地方出错了。
代码如下:
model_save = Mymodel(model) # 这里我将解码过程写成了一个类
saved_model = torch.jit.script(model_save) # 打包
saved_model.save(r'E:\YOLOX-main\tools\temporary.pt') # 保存
mm = torch.jit.load(r'E:\YOLOX-main\tools\temporary.pt') # 使用pytorch加载模型
out = mm.forward(dummy_input) # 在python中进行推理
根据上面的那个写法,它在推理过程中报错:
RuntimeError: The following operation failed in the TorchScript interpreter.
Traceback of TorchScript, serialized code (most recent call last):
File "code/__torch__.py", line 103, in forward
_62 = torch.lt(iou, 0.29999999999999999) # 这个地方对应原来的代码应该是0.3,精度误差不用管
index = torch.where(_62)
_63 = annotate(List[Optional[Tensor]], [torch.tensor(index, dtype=4)])
~~~~~~~~~~~~ <--- HERE
_boxes1 = torch.index(b_boxes, _63)
_44, _boxes0, r_boxes0 = torch.gt(torch.numel(_boxes1), 1), _boxes1, r_boxes1
Traceback of TorchScript, original code (most recent call last):
RuntimeError: Input must be of ints, floats, or bools, got Tensor
上面这个就是它的编译出的torchscript代码报错的地方,编译之后的代码稍微有一点变化,不过还是能看得懂的,对应你自己写的代码找一下在哪个位置,应该很容易能找得到的。
然后看报错信息,它画波浪线的地方就是出错的地方,报错:输入必须是int、float或者bools类型,但是输入了tensor类型,所以这个地方可以知道在torchscript里面不能这样索引。
改为:
index = torch.where(iou < 0.3)
_boxes = torch.index_select(b_boxes, 0, index[0])
再次运行就没有这个问题了,将模型放到C++里面使用libtorch调用也可以正常的运行了。
这样根据你自己的报错信息就可以快速地找到具体哪个地方有问题了,根据它的报错信息进行修改就行。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)