swin transformer v2转tensorrt踩坑与总结

工程部署swin transformer v2的编译过程踩的坑……实验结果ok的时候真是无语泪先流了……记录一下。

部署过程主要是pytorch模型➡onnx模型➡trt engine,每个过程我都进行了结果排查,确认两者间的转换没有出现很明显的掉点。虽然有点费事,但是最好还是做下确认。

网络部分修改

这部分根据同事分享的blog做了修改,但是该blog转换的是swin v1的模型。因此对这部分结合自己的修改做一下总结。blog

  1. 依照blog转onnx模型,do_constant_foldding=True的时候会报错:All input tensors must be on the same device;但是设置do_constant_foldding=False后,可以转onnx,但是转换engine后也会报错While parsing node number 340 [Slice -> "backbone/layers.0/downsample/Slice_output_0"]。因此开始查issue,回答是可以还是得进行常量折叠。因此继续回到转onnx的问题。
  2. 转onnx的问题主要是在于All input tensors must be on the same device这个报错,将verbose设置为True后,查看打印的日志,发现确实有些long和constant在cpu上,但是这个似乎不太影响……后面开始查网络结构中定义的一些层,发现这些层的weights确实在cpu上,因此进行修改,把有weights的部分都移到cuda上(以官方代码为例code):
//class WindowAttention, line 98-99
relative_coords_h = torch.arange(-(self.window_size[0] - 1), self.window_size[0], dtype=torch.float32).cuda()
relative_coords_w = torch.arange(-(self.window_size[1] - 1), self.window_size[1], dtype=torch.float32).cuda()
//line 128-131
self.qkv = nn.Linear(dim, dim * 3, bias=False).cuda()
if qkv_bias:
    self.q_bias = nn.Parameter(torch.zeros(dim)).cuda()
    self.v_bias = nn.Parameter(torch.zeros(dim)).cuda()
//line 135-138
self.attn_drop = nn.Dropout(attn_drop).cuda()
self.proj = nn.Linear(dim, dim).cuda()
self.proj_drop = nn.Dropout(proj_drop).cuda()
self.softmax = nn.Softmax(dim=-1).cuda()
//class WindowAttention,forward,line148-149
if self.q_bias is not None:
    qkv_bias = torch.cat((self.q_bias.detach(), torch.zeros_like(self.v_bias, requires_grad=False), self.v_bias.detach())) //requires_grad must be false
//class SwinTransformerBlock,line241
self.norm2 = norm_layer(dim)
//class PatchMerging,line340-341
self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False).cuda()
self.norm = norm_layer(2 * dim).cuda()
//class BasicLayer,line 422
self.downsample = downsample(input_resolution, dim=dim, norm_layer=norm_layer).cuda()
//class PatchEmbed,line 479-483
self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size).cuda()
if norm_layer is not None:
    self.norm = norm_layer(embed_dim).cuda()
//class SwinTransformerV2,line 582
self.norm = norm_layer(self.num_features).cuda()
  1. 经过blog和转移weights,折叠常量进行转onnx的问题基本解决了。但是转tensorrt 8.6.1版本还是会报错,主要报的是reshape问题,在reshape节点上转换的维度不匹配。排查下可以正常转换的节点,正常节点一定是某个维度的值为-1(自动推断),如下所示:
    在这里插入图片描述
    因此,还是得回到网络结构,查看哪个维度需要改为(-1)进行推理,这个需要继续结合第一部的blog和报错节点进行排查,后续进行总结。
  2. 在可成功转换为engine后,我用修改后的网络结构进行了一遍推理,精度没有掉,证明上述修改只是使网络适应trt转换,不会出现网络结构大变动,影响推理结果。我在转onnx后也写了推理脚本对比相似度,确认模型转换没有问题。

onnx转engine推理问题

首先说明我的环境:

cuda 12.2
cuda toolkit 12.2
ubuntu 22.04
tensorrt 8.6.1

转onnx中opset版本为17,用新版本会缩小engine与pth模型的推理结果差异。在转换的过程中主要出现了两个问题:

  1. max_batch_size问题,转换engine后进行推理,一直报错[07/09/2024-09:13:17] [E] [TRT] 3: [executionContext.cpp::validateInputBindings::2082] Error Code 3: API Usage Error (Parameter check failed at: runtime/api/executionContext.cpp::validateInputBindings::2082, condition: profileMaxDims[d.i] >= dimensions[d.i]. Supplied binding dimension [8,3,256,256] for bindings[0] exceed min ~ max range at index 0, maximum dimension in profile is 1, minimum dimension in profile is 1, but supplied dimension is 8.
    查了很多issue,都没有解决,主要是工程代码中是明确设置为min\opt\max维度的,转R50模型都没有出现这种报错。后面解决方法是转onnx模型时关闭动态维度,在脚本设置中将min\opt\max都设置为8,便没有报错了。
  2. 推理速度慢,这个是版本问题,决定升或降级试试。
    240716update:
  3. 关于动态维度问题,对多个tensorr版本删了又卸,不知道为什么,在没有关闭动态维度的情况下又好了……被我归为设备问题。
  4. 推理速度慢纯纯是设备问题。由于初始调试用的是远程服务器,可能是连接过程中出现的问题,推理一张小图速度能为30ms,转到部署设备上就成不到3ms了。

总结

工程部署中真是会遇到超多奇怪问题,一定要及时总结和归纳,多翻issue,多学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值