OpenCV GPU 模糊很慢
OpenCV GPU blurring is slow
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那么差?
或者这是组件之间的某种通信问题?
您的第一个 gpu 测量值与其他测量值相差甚远,我也遇到过同样的情况。对 opencv 内核 (erode/dilate/etc...) 的第一次调用比随后的其他调用要长。
在一个应用程序中,当我们初始化 GPU 内存时,我们首先调用了 cv::gpu::XX 以便没有这种测量噪声。
我还看到 cv::gpu 在每次没有 cv::gpu::Stream 参数的调用后使用 cudaDeviceSynchronize。这可能会很长,并导致您进行嘈杂的测量。
然后opencv大概会分配内存给一个临时buffer来存放你用来模糊图像的kernel。
我在你的示例中没有看到 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
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那么差? 或者这是组件之间的某种通信问题?
您的第一个 gpu 测量值与其他测量值相差甚远,我也遇到过同样的情况。对 opencv 内核 (erode/dilate/etc...) 的第一次调用比随后的其他调用要长。 在一个应用程序中,当我们初始化 GPU 内存时,我们首先调用了 cv::gpu::XX 以便没有这种测量噪声。
我还看到 cv::gpu 在每次没有 cv::gpu::Stream 参数的调用后使用 cudaDeviceSynchronize。这可能会很长,并导致您进行嘈杂的测量。 然后opencv大概会分配内存给一个临时buffer来存放你用来模糊图像的kernel。
我在你的示例中没有看到 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