为什么OpenCV用GPU/cuda跑得比用CPU慢

51
发表时间:2023-06-14 15:38

1、首先对于任何一个CUDA程序,在调用它的第一个CUDA API时后都要花费秒级的时间去初始化运行环境,后续还要分配显存,传输数据,启动内核,每一样都有延迟。

这样如果你一个任务CPU运算都仅要几十毫秒,相比而言必须带上这些延迟的GPU程序就会显得非常慢。


2、其次,一个运算量很小的程序,你的CUDA内核不可能启动太多的线程,没有足够的线程来屏蔽算法执行时从显存加载数据到GPU SM中的时延,这就没有发挥GPU的真正功能。


3、数据从内存传递到显存和cudaMalloc耗时很长,NVIDIA提供的nsight中的profile可以看每一个部分的耗时。基本上OpenCV的算法都归纳为三个部分:

upload(gpu::Mat), processCodeBlock, download(gpu::Mat)。你看看是不是80%以上的时间都花在第一个和最后一个上,问题就迎刃而解了。

因为gpu在计算上虽然比cpu快,但实际上在使用gpu的时候有一步非常耗时,那就是将内存与显存中的数据进行互相拷贝,同时这也是使用gpu运算时逃不掉的一步。


4、GPU擅长的是大规模并行计算,比起cpu只是以巨额核心数取得优势的,单核速度其实被cpu碾压。如果数据规模小的话GPU并不能用上太多核,所以比cpu慢。

减少数据在CPU和GPU之间的传递次数;运算量非常小的部分不要用GPU,数据量非常大、循环次数非常多的时候才使用GPU。


//执行这些简单算子,CPU比GPU更快


cvtColor,GaussianBlur,Canny


//执行这些耗时算子,GPU比CPU更快


HoughCircles,HoughLines,matchTemplate


5、如果问题规模较小,逻辑控制较为复杂,并行性很小优先使用CPU处理该问题,如果包含较大规模的数据处理,则考虑使用GPU进行处理。


CPU上线程是重量级实体,可以开启1~32个线程,且上下文切换较为缓慢,GPU上线程是高度轻量级的,可以开几百甚至上千个线程。


CUDA通过两种API来对设备GPU设备进行控制,包括驱动API和运行API,其中驱动API较难编程,但是设备控制能力和利用率高。两者只能选择其中一种,不能混合使用。


一个CUDA程序包含了两个部分代码,在CPU上运行的主机代码和在GPU上运行的设备代码。


6、总结一句,GPU的并行处理的确很快,但数据传入GPU和传出的开销实在太大,往往影响了代码的整体效率,运算量非常小的计算不要用GPU。





微信公众号:
蓝松文档:
地址:浙江省杭州市余杭区仓前街道龙园路88号3号楼A1318室(创鑫时代广场)