环境:
我正在尝试使用 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 内核,但未能遵守这些基础知识,您也不太可能获得任何性能提升。
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。
即使我从未使用过这个库,我也看到了问题所在,而且我更喜欢使用我的 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 慢!