【问题标题】: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 代码可能并不完美。即使在单个“匹配”调用中,它也可能会进行复制等等。

标签: python opencv gpu template-matching


【解决方案1】:

回答您的问题:

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

【讨论】:

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