【问题标题】:OpenCV GPU blurring is slowOpenCV GPU 模糊很慢
【发布时间】:2015-10-09 23:20:09
【问题描述】:

GPU:GeForce GTX 750

CPU:Intel i5-4440 3.10 GHz

这是我正在运行的简单 C++ 代码。

    #include <iostream>
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2\gpu\gpu.hpp"

    int main(int argc, char** argv) {
        cv::Mat img0 = cv::imread("IMG_0984.jpg", CV_LOAD_IMAGE_GRAYSCALE); // Size 3264 x 2448
        cv::Mat img0Blurred;

        cv::gpu::GpuMat gpuImg0(img0);
        cv::gpu::GpuMat gpuImage0Blurred;

        int64 tickCount;

        for (int i = 0; i < 5; i++)
        {
            tickCount = cv::getTickCount();
            cv::blur(img0, img0Blurred, cv::Size(7, 7));
            std::cout << "CPU Blur " << (cv::getTickCount() - tickCount) / cv::getTickFrequency() << std::endl;

            tickCount = cv::getTickCount();
            cv::gpu::blur(gpuImg0, gpuImage0Blurred, cv::Size(7, 7));
            std::cout << "GPU Blur " << (cv::getTickCount() - tickCount) / cv::getTickFrequency() << std::endl;

        }

        cv::gpu::DeviceInfo deviceInfo;
        std::cout << "Device Info: "<< deviceInfo.name() << std::endl;

        std::cin.get();

        return 0;
    }

因此,我通常会得到这样的结果:

CPU Blur: 0.01
GPU Blur: 1.7
CPU Blur: 0.009
GPU Blur: 0.012
CPU Blur: 0.009
GPU Blur: 0.013
CPU Blur: 0.01
GPU Blur: 0.012
CPU Blur: 0.009
GPU Blur: 0.013

Device Info: GeForce GTX 750

所以在 GPU 上的第一次操作需要时间。

但是,其余的 GPU 调用呢?

为什么 GPU 不为此提供任何加速。毕竟这是一张大图(3264 x 2448)。而且这个任务很适合并行化,不是吗?

是我的 CPU 这么好,还是我的 GPU 这么差? 或者这是组件之间的某种通信问题?

【问题讨论】:

  • 你在 IPP 中使用 opencv 吗?

标签: opencv cuda gpu


【解决方案1】:

您的第一次 gpu 测量与其他测量相差甚远,我也经历过同样的事情。对 opencv 内核的第一次调用(侵蚀/扩张/等...)比后面的其他调用要长。 在一个应用程序中,当我们初始化 GPU 内存时,我们首先调用了 cv::gpu::XX,以避免出现这种测量噪声。

我还看到 cv::gpu 在每次调用后使用 cudaDeviceSynchronize 而不使用 cv::gpu::Stream 参数。这可能会很长,并且会导致您测量噪声。 然后opencv可能会为一个临时缓冲区分配内存来存储你用来模糊图像的内核。

我在你的例子中没有看到 gpuImage0Blurred 的分配,你能确定你的目标图像在循环外正确分配,否则你也会测量这个矩阵的分配时间。

使用 nvvp 可以为您提供有关应用程序运行时实际发生的情况的线索,以删除不必要的操作。

编辑:

#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2\gpu\gpu.hpp"


int main(int argc, char** argv) {
    cv::Mat img0 = cv::imread("IMG_0984.jpg", CV_LOAD_IMAGE_GRAYSCALE); // Size 3264 x 2448
    cv::Mat img0Blurred;


    cv::gpu::GpuMat gpuImg0;
    cv::gpu::Stream stream;
    stream.enqueueUpload(img0, gpuImg0);
    stream.waitForCompletion();

    // allocates the matrix outside the loop
    cv::gpu::GpuMat gpuImage0Blurred( gpuImg0.size(), gpuImg0.type() );

    int64 tickCount;

    for (int i = 0; i < 5; i++)
    {
        tickCount = cv::getTickCount();
        cv::blur(img0, img0Blurred, cv::Size(7, 7));
        std::cout << "CPU Blur " << (cv::getTickCount() - tickCount) / cv::getTickFrequency() << std::endl;

        tickCount = cv::getTickCount();
        cv::gpu::blur(gpuImg0, gpuImage0Blurred, cv::Size(7, 7), cv::Point(-1, -1), stream);
        // ensure operations are finished  before measuring time spent doing operations
        stream.WaitCompletion();
        std::cout << "GPU Blur " << (cv::getTickCount() - tickCount) / cv::getTickFrequency() << std::endl;

    }

    std::cin.get();

    return 0;
}

是的,事实证明waitForCompletion 与众不同。 我得到的值与开始时相同:

CPU Blur: 0.01
GPU Blur: 1.7
CPU Blur: 0.009
GPU Blur: 0.012
CPU Blur: 0.009
GPU Blur: 0.013
CPU Blur: 0.01
GPU Blur: 0.012
CPU Blur: 0.009
GPU Blur: 0.013

【讨论】:

  • 这很酷,但现在我面临一个不同的问题。我只使用模糊作为一个简单的基准。我实际上想并行化特征检测。所以,这是我的下一个问题:stackoverflow.com/questions/31536735/…
  • 你仍然没有在循环之外分配你的输出矩阵,只是声明变量 cv::gpu::GpuMat gpuImage0Blurred(gpuImg0.size(), gpuImg0.type() );将在设备上进行分配,否则您第一次调用 blur 将分配此缓冲区
  • 我更新了编辑,在测量时间之前在流上添加了同步,因为您只会测量将订单添加到流中所花费的时间,而不是所花费的计算时间。
  • 我的计算时间使用gtx 770和一个cori7使用OpenCV 2.4 CPU模糊0.0467963 GPU模糊0.0125604 GPU模糊0.00665776 CPU模糊0.0124044 GPU模糊0.0126354 GPU模糊0.00666472 CPU模糊0.0132325 GPU模糊0.00665901你的 GPU 是限制因素,肯定是因为它的内存速度很差(根据 NVidia 规范为 80GB/秒),大约只有你的 RAM 输出的 2 倍。
  • 哇...谢谢。拥有完全独立的测量真的很有帮助。我试图从这一切中弄清楚。我一直在阅读 GPU 处理如何将此类操作的速度提高 10 倍或更多。所以当我第一次得到这些结果时,我以为我做错了什么。
猜你喜欢
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 2021-04-10
  • 2012-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多