本文介绍 SOLOV2-TensorRT加速一:加速计划
SOLOV2-TensorRT加速一:加速计划
本文由林大佬原创,转载请注明出处,我们有来自腾讯、阿里等一线AI算法工程师组成微信交流群, 如果你想交流欢迎添加微信: jintianandmerry 拉群, 添加请备注 "交流群"
我之前写过一篇关于SOLOV2的文章,不过没有任何关于部署的内容.最近由于笔者想部署一个实例分割算法,目标是精度OK,其次速度可以加速到Realtime, 我尝试了一些two stage的方案,结果都是坑太深,于是只能放弃.最后还是打算部署SOLOV2, 原因主要是两个:
- SOLOV2模型简单,为数不多的一个精度(mAP 38)和速度比较均衡的模型;
- SOLOV2是真正的single stage, 它不需要先生成框,再去做mask的回归,这一点和CenterMask, CondInst等方法是不同的,虽然都宣称是singe stage.
当然这只是可行性,其实SOLOV2的坑也很深,比如最不好搞的就是动态卷积,以及matrix nms.相信对深度学习部署比较熟悉的朋友知道,对于动态卷积目前在TensorRT内部是不支持的,换句话说,你需要通过一种特别的方式去处理它.另外就是matrix nms, 这部分你可以用cuda kernel 去做,也可以封装到模型里面,因为它和其他的nms不同,对于矩阵操作依赖太大,如果你写后处理,可能会就此歇菜.但是不管怎么样,我们已经踏平了所有的艰难险阻,也算是给大家做一个前车之鉴.最终加速后的效果如下:
上面所展示的效果大概是我们调节过得SOLOv2 coco mAP 35.5模型的效果,速度在Python下是56ms, tensorRT下是23ms, 加速了一倍.整体加速情况如下:
model | latency | mAP | 评价 | input |
---|---|---|---|---|
python | 55ms | 35.5 | 还可以 | 732x704 |
TensorRT(C++) | 23ms (GTX1080Ti, FP32) | 35.5 | 快到脱发 | 732x704 |
简单来说, 我们实现了一个精度很高,速度快到逆天的实例分割模型!! 并且可以纯C++推理!!
采坑记录
上面给大家展示了SOLOV2加速之后的逆天速度,接下来也顺便分享一下整个过程中的遇到的问题.可以说是喜马拉雅有多高,坑就有多深.
1. 动态卷积不支持
首先是动态卷积不支持,很多人可能没有遇到过,因为你根本遇不到啊,即便是我这么一个老谋深算的人,之前甚至部署过PanopticFCN, 也在这上面摘了一个跟头.
如果有同学是研究实例分割的,你会发现PanopticFCN用到的动态卷积,和SOLOV2不太一样,但是本质上是一个东西,只不过SOLOV2把问题暴露出来了.
那么到底哪里不一样呢,又为什么本质上一样呢?不卖关子了,你如果只考虑1x1大小的动态卷积,同时步长和扩边都是1,那么这个卷积其实就退化成了一个普通的矩阵乘,请注意这里是 matmul
不是*
. 所以这二者本质上就是同一个东西,PanopticFCN的作者是这么写的:
torch.matmul(a, b)
实际上就是用一个矩阵乘替代了这里的动态卷积.所以你应该知道动态卷积这个应该如何解决吧?
2. matrix nms
这部分其实也可以用kernel去写,但是我偷懒没有去搞,而是直接揉进了onnx, 我测试了这部分的速度,实际上耗时并不是很大.可以说跟你用plugin去写,差别应该不太大.
我说起来可能很简单,但是这里面揉进onnx, 其实经历了许多不为人知的东西... 这部分我不展开来讲,感兴趣的同学自己去试一下便知道了.
3. Gridmask如何用onnx去trace
经过这个超级复杂模型的尝试,我越来越明白一个统一的图表示有多么的必要,同时在模型里面部署框架对于逻辑图的支持的重要性和必要性,单纯的数据驱动的静态图很难满足我们日益增长的模型复杂度的需求了.而这里面,最直接的体现就是SOLOV2里面对于Gridmask的处理.
这部分我试过用SOLOV2的mmdet的实现去导出,发现那种写法实在是很难处理,而切换到detectron2的版本,反而可以更好的去支持,只需要修改一下对于linspce的写法即可.从而让ONNX可以自己去寻找对应的算子去实现.
4. 输出mask的处理
我们都知道,SOLOV2里面有两个output number 变动的过程,一旦输出变动了,也就意味这你的模型极有可能不能free, 换句话说,你需要一张有检测结果的图,去生成一个检测结果的输出,再导出,但是如果这里free了,你再换一张图就不行了.
这个问题其实SOLOV2也有,一个变动地方在于feature encoding出来之后,和kernel乘机的结果,另一部分是两次threshold的判定,以及最后的matrix nms过滤.经过这么几次筛选之后,出来的数目就是不确定的.
但是也不是没有解决办法,目前的解决办法是通过固定输出来实现,这样做的代价是输出的tensor会比较大.这也引入了下一个问题;
5. 简单粗暴的后处理导致e2e耗时很大
很多人在做教程或者做博客的时候,只会写前向推理时间,而对于前处理和后处理部分的时间是不提及的,有些人是只跑一个网络推理部分看一下时间就完事儿了,就觉得加速完了,其实并没有,这里面还有很多细节.举个例子,很少有人知道opencv resize这个步骤的耗时可能是你的网络的两倍,你可能不信,但是大可以自己试一下,当图片尺寸比较大的时候,确实可能如此.
另外就是简单粗暴的后处理,比如SOLOV2的输出有一个特点,就是输出尺寸很大,因为它的mask是相对于原图的.这带来的结果就是它的张量所占用的空间是很大的.很多人跑完前向就不管了,但是你去把输出拷贝到CPU再可视化的时间,可能是你的网络前向时间的两倍.
所以这里简单粗暴的后处理是不可行的,最后我们根据fix的输出,筛选出我们需要的输出,还需要进一步的做一些工作.我们的解决方法是自己写kernel来处理.
SOLOV2的应用案例分享
其实这个只是我们的一个初步结果,初步来看它的速度已经达到了可以部署的要求,精度也很高.这里我们进一步分享一些使用SOLOV2的案例.
个人认为SOLOV2这个模型比较适合的应用场景包括:
- 需要实例分割的场景,比如面板,俯视图检测,不规则形状物体的检测等;
- 适合实时的场景,比如你想做工业缺陷检测,但是传统的检测算法没法用,此时SOLOV2可以帮忙,而落地和商业化我们已经有了这么一个TensorRT的解决方案,方便部署
1. 芯片检测与识别
###
2. 易拉罐垃圾检测
3. 行人检测与计数
总体来讲,还是可以在工业界发挥SOLOV2的用武之地,尽管它有着一些自身的缺点,但是相信在不断的优化下,这个模型还是可以比肩其他检测模型的,至少在一些需要实例分割的场合,其他的检测方法就不一定能做到,即使可以做到,也不一定能有这么快的速度.
总结
本篇大概给大家分享了部署过程中遇到的一些问题,也分享了一些加速的结果,也进一步跟大家分享了一些使用案例.如果你对SOLOV2比较感兴趣,同时也有这样的需求:
- 您有自己的数据集符合使用场景,可以加入我们的知识星球,联系星主获取相应训练代码和加速代码;
- 如果你需要其他模型的TensorRT, 也可以联系我们,对于一些有趣的有用的算法,我们可以部署到工业上.
最后下一篇将会给大家进一步介绍SOLOV2 TensorRT加速的技术细节,以及如何做后处理等.
更多
如果你想学习人工智能,对前沿的AI技术比较感兴趣,可以加入我们的知识星球,获取第一时间资讯,前沿学术动态,业界新闻等等!你的支持将会鼓励我们更频繁的创作,我们也会帮助你开启更深入的深度学习之旅!
往期文章
zhuanlan.zhihu.com/p/165009477
zhuanlan.zhihu.com/p/149398749