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

GPU with OpenCL is slower than CPU. Why?

环境:

我正在尝试使用 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 函数。

基本上,您的代码很慢,因为 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。