使用 OpenCL 的 GPU 比 CPU 慢。为什么?

问题描述 投票:0回答:2

环境:

  • 英特尔 i7-9750H
  • 英特尔超核芯显卡 630
  • Nvidia GTX1050(笔记本电脑)
  • Visual Studio 2019 / C++
  • OpenCV 4.4
  • OpenCL 3.0(英特尔)/1.2(英伟达)

我正在尝试使用 OpenCL 来加速我的代码。但结果显示 CPU 比 GPU 更快。 我怎样才能加快我的代码速度?

void GetHoughLines(cv::Mat dst) {
    cv::ocl::setUseOpenCL(true);

    int img_w = dst.size().width; // 5000
    int img_h = dst.size().height; // 4000

    cv::UMat tmp_dst = dst.getUMat(cv::ACCESS_READ);
    cv::UMat tmp_mat = cv::UMat(dst.size(), CV_8UC1, cv::Scalar(0));

    for (size_t i = 0; i < 1000; i++)
    {
        tmp_mat = tmp_mat.mul(tmp_dst);
    }
}

当我只使用CPU时,大约花费了3000ms。 当我使用 Intel UHD Graphics 630 时,需要 3500ms。 我也尝试过GTX1050,但花了大约3000ms。

请给我一些加快速度的想法。我应该让它至少1000毫秒。 我应该使用 AMP 还是 OpenMP?但据我所知,它们只能计算简单的运算,不适合 OpenCV 函数。

c++ opencv opencl
2个回答
3
投票

基本上,您的代码速度很慢,因为 OpenCV 使用 OpenCL 的方式效率低下。 与底层硬件无关。

为了使 OpenCL 代码(或任何与 GPU 相关的代码)高效,主机端代码正确利用 GPU 至关重要。举几个原则:

  • 通过异步对许多计算(内核)进行排队来使 GPU 饱和。
  • 避免不必要的同步。
  • 避免主机 CPU 和 GPU 设备之间不必要的内存复制。

即使您编写了最优化的 GPU 内核,但未能遵守这些基础知识,您也不太可能获得任何性能提升。

OpenCV 代码库是一个很好的例子,说明如何遵守这些原则。

对于您的示例,如果您重写代码以避免内存复制并显式使用设备内存,您可能会看到合理的性能:

auto frame1 = cv::UMat(size, format, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
auto frame2 = cv::UMat(size, format, cv::USAGE_ALLOCATE_DEVICE_MEMORY);
auto frame3 = cv::UMat(size, format, cv::USAGE_ALLOCATE_DEVICE_MEMORY);

for (size_t i = 0; i < 10; i++)
{
    cv::multiply(frame1, frame2, frame3);
}

但无论如何,我建议您学习使用 OpenCL API,而不使用 OpenCV。


0
投票

即使我从未使用过这个库,我也看到了问题所在,而且我更喜欢使用我的 OpenCl 代码。您会看到您的 cv::ocl lib。可以并行且非常高效地执行您的乘法代码。但即使是这种情况,您在传输缓冲区以执行此操作时也会遇到问题。当你使用 tmp_mat = tmp_mat.mul(tmp_dst); OpenCl 和 C++ 可能会假设您想在每次计算之后随时使用 tmp_table。在 for 循环中,它将数据从 cpu 传输到 GPU 并返回,这可能会严重滞后该过程。您必须使用图形社区中已知的方法作为进程的实例。因此,它在 GPU 中一次又一次地进行相同的计算,并在过程的开始和结束时传输缓冲区,这样您可以在 GPU 中实现比在 CPU 中平均快 30 倍的代码。我知道这一点是因为我的CPU太多了。请注意,为了在 Invidia 中运行 OpenCl 代码,您必须拥有使您的代码兼容 INVIDIA 的模块,即 cuda 代码。如果您没有这样做,您的 GPU 代码可能会在 Intel GPU 上运行,但它比更大的 INVIDIA GPU 慢!

© www.soinside.com 2019 - 2024. All rights reserved.