为啥 OpenCV GPU CUDA 模板匹配比 CPU 慢很多?

Posted

技术标签:

【中文标题】为啥 OpenCV GPU CUDA 模板匹配比 CPU 慢很多?【英文标题】:Why is OpenCV GPU CUDA template matching so much slower than CPU?为什么 OpenCV GPU CUDA 模板匹配比 CPU 慢很多? 【发布时间】:2022-01-19 02:40:12 【问题描述】:

我已经编译了最新的可用 OpenCV 4.5.4 版本,以与最新的 CUDA 11.5 一起使用,并在配备 GeForce RTX 2070 Super 显卡(7.5 拱门)的 Windows 10 机器上运行启用了快速数学。我正在使用 Python 3.8.5。

运行时结果:

CPU 性能优于 GPU(匹配 300x300 源图像中的 70x70 针图像) 最大的 GPU 瓶颈是需要在模板匹配之前将文件上传到 GPU CPU 大约需要 0.005 秒,而 GPU 大约需要 0.42 秒 这两种方法最终都找到了 100% 匹配

使用的图片:

源图片

针图

使用 CPU 的 Python 代码:

import cv2
import time

start_time = time.time()
src = cv2.imread("cat.png", cv2.IMREAD_GRAYSCALE)
needle = cv2.imread("needle.png", 0)

result = cv2.matchTemplate(src, needle, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
print("CPU --- %s seconds ---" % (time.time() - start_time))

使用 GPU 的 Python 代码:

import cv2
import time

start_time = time.time()
src = cv2.imread("cat.png", cv2.IMREAD_GRAYSCALE)
needle = cv2.imread("needle.png", 0)

gsrc = cv2.cuda_GpuMat()
gtmpl = cv2.cuda_GpuMat()
gresult = cv2.cuda_GpuMat()

upload_time = time.time()
gsrc.upload(src)
gtmpl.upload(needle)
print("GPU Upload time --- %s seconds ---" % (time.time() - upload_time))

match_time = time.time()
matcher = cv2.cuda.createTemplateMatching(cv2.CV_8UC1, cv2.TM_CCOEFF_NORMED)
gresult = matcher.match(gsrc, gtmpl)
print("GPU Match time --- %s seconds ---" % (time.time() - match_time))

result_time = time.time()
resultg = gresult.download()
min_valg, max_valg, min_locg, max_locg = cv2.minMaxLoc(resultg)
print("GPU Result time --- %s seconds ---" % (time.time() - result_time))
print("GPU --- %s seconds ---" % (time.time() - start_time))

即使我不考虑将文件上传到 GPU 所花费的时间,仅匹配时间就需要 CPU 上整个过程的 10 倍以上。我的 CUDA 安装正确,我已经运行了其他测试,其中 GPU 的性能远远优于 CPU,但到目前为止,模板匹配的结果确实令人失望。

为什么 GPU 性能这么差?

【问题讨论】:

CPU 和 GPU 可能使用不同的模板匹配方法。我知道 CPU 使用 DFT 和其他优化,并且对 CPU 的速度进行了非常优化。我不知道GPU使用什么方法。 GPU 有延迟。这是 GPU 编程中众所周知的事实。 从时间测量中排除匹配器的初始化,如果可能的话,在没有时间测量的情况下运行一次匹配,然后使用 tine measurent 确保没有更多的即时编译活动(这可能发生第一次通话)。如果可能:测量大量运行的总时间。 谢谢@Micka 我已经这样做了。我只循环匹配线超过 100 次,没有进一步初始化并取平均值,CPU 最终还是快了 10 倍。 您提供的代码混合了cv2.cuda.createTemplateMatchingmatcher.match。将时间移出 个。 -- OpenCV 代码可能并不完美。即使在单个“匹配”调用中,它也可能会进行复制等等。 【参考方案1】:

回答您的问题:

    您说其他任务更适合 GPU。我阅读了 Python CUDA 文档。它表明你是对的。有些任务更适合 CPU,有些任务更适合 CPU。无需进入注册表和我必须学会告诉你的东西,我可以说你写的东西在参考文档方面是有意义的。 我看不到这里的实际时间。此外,这个瓶颈似乎是意料之中的:CPU 在主板上,焊接在主板上,与内存有更好的连接。 GPU 是一张卡,带有一个扩展插头,它具有主板没有的限制。此外,它并不是一个真正麻烦的瓶颈,因为它并不拥挤。 2.1 其他人写道,我对计算机设计的假设是“无稽之谈”。我不敢苟同。这个微小的数据集可以指出卡和板之间的速度差异。数据来源于卡片,然后进入董事会的注册表。这么小的一组很容易让差异变得明显。 我所阅读的有关架构和 CUDA 文档的内容表明您的结果没有异常。 CUDA 模块可能更适合用于大型数据集。提供的优势是 GPU 和 CPU 可以同时工作,而不是相互竞争。

【讨论】:

抱歉,这只是废话。 (1) 是一个空短语 (2) 与物理连接或“焊接”完全无关 (3) 不,这里的问题是缺少 流水线。众所周知,GPU 的使用涉及各种设置任务的延迟。大型数据集只是更好地隐藏了编程缺陷。也可以有效地运行小型数据集,只是不要期望设置成本会消失。 我不同意,但很想知道您认为瓶颈是流水线,并且它是一个瓶颈。我在这里没有看到编程缺陷:这个小数据集不是 Python CUDA 模块旨在处理的。更好地完成设计工作并没有隐藏缺陷。 看完这篇文章后,我礼貌地同意Rackwitz先生的观点,半秒不能用硬件来解释,但不要收回我写的任何“废话”。

以上是关于为啥 OpenCV GPU CUDA 模板匹配比 CPU 慢很多?的主要内容,如果未能解决你的问题,请参考以下文章

为啥tensorflow训练用GPU比CPU更慢了

CUDA(GPU) 作为 OpenCV 后端

[CUDA OpenCV]GPU加速的计算机视觉学习资源下载

NVIDIA GPU / CUDA 中使用 OpenCV 深度神经网络模块

nvcc 致命:安装 cuda 9.1+caffe+openCV 3.4.0 时不支持 gpu 架构“compute_20”

opencv4.2+opencv_contrib编译gpu加速带cuda和CUDnn(二)