Quantcast
Viewing all articles
Browse latest Browse all 583

使用英特尔®GPU的性能调优达到153帧MobileNet-SSD目标检测

介绍

随着自动驾驶,智能视频监控,人脸检测和各种行人计数应用的兴起,快速、 准确的目标检测系统处于上升的需求。目标检测不仅需要确定图像中每个目标是什么,还需要把目标用方框标记出来。这使得目标检测比传统的图像分类更加复杂,计算量更大。

本文采用的MobileNet-SSD 模型来自 https://github.com/chuanqi305/MobileNet-SSD(MobileNet-SSD 也被选为谷歌对象检测 API),本文将展示如何在英特尔®GPU上优化MobileNet-SSD来获得总153 fps(6 路视频流,每路25fps)的性能。

英特尔® GPU 优化的clCaffe

本优化基于英特尔® clCaffe, GitHub 地址是 https://github.com/01org/caffe ,操作系统是最新的 Ubuntu 16.04 (内核版本是 4.7.10)。

在Skull NUC i7 (其GPU是Iris 580 Pro,GT4e架构72EU),如果直接运行视频分析demo,demo code 在/examples/video_analysis/video_analysis.cpp , 取batch为6的时候,FP16的性能只有50fps (浮点数是 32 位的称为 FP32,目前CPU只支持FP32,而 GPU 支持半精度浮点数的格式,这被称为 FP16,也就是16位的浮点数)。但理论值为 160 fps (理论值可以使用caffe time命令来获取,理论值只计算推理时间,不包括前处理时间) 。实际值和理论值之间存在着巨大的差距。相对于FP16,FP32的性能和理论值120fps差距很小,但是为了获得最大化性能, 本文讲解如何优化FP16,以获得在batch=6(也就是6路视频流)的时候接近160fps的总性能。

如何优化

多线程

总的任务可以分成3个线程。线程 A 将视频解码然后缩放图像到 300 * 300 并把图像转换成FP16的数组,最后拷贝到GPU的内存。线程 B 将进行推理。线程 C 在屏幕上绘制结果。更改为多线程后在没有显示的情况下(显示的优化将在3.4提及)FP32 可以得到 118 fps (理论值为 120 fps),但 FP16 只有 105 fps。因为MobileNet-SSD的FP16对比FP32并没有任何精度损失, FP16 可以在同精度下获得最佳性能。FP16 优化对我们是很关键的。不同于FP32 ,在CPU上做FP32转FP16是使用CPU软件模拟的,它会导致大量的Cache miss和并浪费太多的内存带宽。这样就会导致推理的速度受到很大影响。

在GPU上做FP16到 FP32转换

既然CPU 不支持 FP16,FP16的转换通过软件模拟性能低,而GPU是支持FP16的数据格式的,那么把FP32 到 FP16的转换放在 GPU 中应该可以得到比较好的结果。此GPU内核的伪码为,FP16 = (FP32 -Mean) * Scale (注意为了最大化性能,此GPU内核还做了一些从图形转浮点数组的前处理)。线程 A 将用软解去解码视频 (之所以使用软解解码,是因为开源的硬件解码libyami会占用一些 GPU 资源,导致低性能的推理,闭源的MediaSDK在本文中还没有验证过),然后调用 FP32 到 FP16 的kernel 代码在GPU内做FP32到FP16的转换,但是测试结果显示帧率反而更糟糕了,有时是甚至低于 80 fps。

导致慢的原因是GPU GT4e架构是有缓存的,当图像被一帧一帧的放到GPU内存中时,后面批量输入的数据会被从缓存中移除,这将导致很缓慢的内存读取速度。解决方法是在GPU做推理前才填充GPU内存,保证GPU在做FP32转FP16的时候是从GPU Cache读取的。做了此优化后,帧率在没有显示的时候达到了148 fps,带显示则是122fps。

让 Ubuntu 总是保持最高的 GPU 性能

理论值160 fps,在测试此理论数值的时候 x-window系统是关闭的,但是在此demo中需要有显示输出,在x-window开启的时候,发现系统开机几分钟后,理论值降低到150fps。最后发现当屏幕变暗后,也就是screen lock后的性能才会降低到 150 fps。根本原因目前还不太清楚,猜测是进入待机状态后,Ubuntu 会做一些限制 GPU 性能的节电命令。取消屏幕Dim和Lock,保持屏幕常亮后,帧率理论值能稳定在160fps。

显示优化

当添加了6路显示后,总体性能从158 fps 下降到 130 fps。第一步优化是从 6 窗口转变为 1 窗口,也就是把6个640*480的图像拼合成一个 1920 * 960 帧,并在一个窗口中显示。此优化后帧率上升到143 fps,但是和158fps的帧率还是有差距。第二步优化是切换到硬件加速的显示,在 Ubuntu 中,它被称为 XCB (就像 DirectDraw,使用GPU内的2D加速器,所以对OpenCL计算的影响很小)。这里要注意,不要使用 OpenGL刷新,因为 GPU 已经满载了,OpenGL加速的刷新 比XLib 软件刷新更为缓慢。此优化后的性能达到了我们的最终目标153 fps。

结论

除了上面的4步优化,还有一些小的优化,比如RGBtoYUV 或 YUVtoRGB使用 libyuv 来做转换,因为它支持 avx SIMD软件加速,而OpenCV 颜色空间转换性能较差。图像缩放可以使用OpenCV,它和libyuv的性能差距不大。这里还要注意,不要用 OpenCL 加速 OpenCV,因为GPU 已经满载用于推理 (如果你运行 intel_gpu_top,你可以发现 GPU已经满载了)。

做完上述所有这些优化后6路MobileNet-SSD目标检测总帧率为153 fps,模型是从开源网站上获取的,并没有做任何模型的优化。实际上因为 MobileNet 是"depthwise可分离的卷积",通常它可以比较方便的做卷积的剪枝,剪枝大约为20%,且没有任何精度损失。所以真正的帧率可以比 153 fps 更高 !

关于作者

李雨洺是英特尔软件与服务事业部的一名应用软件工程师,专注于图像处理领域。 主要负责与开发者一起合作,将英特尔平台的相关图像技术(例如图像编码,图像深度学习处理)应用到开发者的产品中,以实现图像处理相关的应用场景,并提高应用在英特尔®平台上的性能。


Viewing all articles
Browse latest Browse all 583

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>