我正在使用笔记本电脑的opencv242 + VS2010 我试图对OpenCV中的GPU块进行一些简单测试,但它表明GPU比CPU代码慢100倍。 在这段代码中,我只是将彩色图像转换为灰度图像,使用 cvtColor
的功能这是我的代码,PART1是CPU代码(测试cpu RGB2GRAY),PART2是GPU上传图像,PART3是GPU RGB2GRAY,PART4是CPU RGB2GRAY。 有三件事让我如此疑惑:
1在我的代码中,part1是0.3ms,而part4(与part1完全相同)是40ms !!! 2将图像上传到GPU的第2部分为6000毫秒! 3 Part3(GPU代码)是11ms,对于这个简单的图像来说速度太慢了!
#include "StdAfx.h"
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/gpu/gpu.hpp"
#include "opencv2/gpu/gpumat.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <ctime>
#include <windows.h>
using namespace std;
using namespace cv;
using namespace cv::gpu;
int main()
{
LARGE_INTEGER freq;
LONGLONG QPart1,QPart6;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&freq);
dfFreq = (double)freq.QuadPart;
cout<<getCudaEnabledDeviceCount()<<endl;
Mat img_src = imread("d:\\CUDA\\train.png", 1);
// PART1 CPU code~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// From color image to grayscale image.
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
Mat img_gray;
cvtColor(img_src,img_gray,CV_BGR2GRAY);
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("CPU RGB2GRAY running time is %.2f ms\n\n",dfTim);
// PART2 GPU upload image~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GpuMat gimg_src;
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
gimg_src.upload(img_src);
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("Read image running time is %.2f ms\n\n",dfTim);
GpuMat dst1;
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
/*dst.upload(src_host);*/
dst1.upload(imread("d:\\CUDA\\train.png", 1));
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("Read image running time 2 is %.2f ms\n\n",dfTim);
// PART3~ GPU code~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// gpuimage From color image to grayscale image.
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
GpuMat gimg_gray;
gpu::cvtColor(gimg_src,gimg_gray,CV_BGR2GRAY);
QueryPerformanceCounter(&freq);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("GPU RGB2GRAY running time is %.2f ms\n\n",dfTim);
// PART4~CPU code(again)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// gpuimage From color image to grayscale image.
QueryPerformanceCounter(&freq);
QPart1 = freq.QuadPart;
Mat img_gray2;
cvtColor(img_src,img_gray2,CV_BGR2GRAY);
BOOL i_test=QueryPerformanceCounter(&freq);
printf("%d \n",i_test);
QPart6 = freq.QuadPart;
dfMinus = (double)(QPart6 - QPart1);
dfTim = 1000 * dfMinus / dfFreq;
printf("CPU RGB2GRAY running time is %.2f ms\n\n",dfTim);
cvWaitKey();
getchar();
return 0;
}
答案 0 :(得分:24)
cvtColor没有做太多的工作,灰色你只需要平均三个数字。
CPU上的cvColor代码使用SSE2指令一次处理多达8个像素,如果你有TBB它使用所有内核/超线程,CPU运行速度是GPU时钟速度的10倍,最后你不会必须将数据复制到GPU上并返回。
答案 1 :(得分:21)
上面的大多数答案实际上都是错误的。它之所以慢了20000倍,当然不是因为“CPU时钟速度更快”而且“它必须将其复制到GPU”(接受的答案)。这些都是因素,但是你说你省略了一个事实,即对于一个令人作呕的并行问题你有更多的计算能力。说20.000x的性能差异是因为后者只是如此荒谬可笑。作者在这里知道一些错误并不是直截了当的。解决方案:
你的问题是CUDA需要初始化!它将始终初始化第一张图像,通常需要1-10秒,具体取决于木星和火星的对齐方式。现在尝试一下。计算两次,然后计算两者。在这种情况下,您可能会看到速度与magnutide相同,而不是20.000x,这太荒谬了。你能对这个初始化做些什么吗?不,不是我所知道的。这是一个障碍。
编辑:我刚刚重新阅读了帖子。你说你在笔记本上运行。那些经常有破旧的GPU,而CPU则有一个公平的涡轮增压。
答案 2 :(得分:5)
尝试不止一次......
-----------来自http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ的摘录 性能比较
为什么第一次函数调用很慢?
这是因为初始化开销。在第一个GPU函数调用Cuda Runtime API被隐式初始化。在第一次使用时,还会为您的视频卡编译一些GPU代码(即时编译)。因此,对于性能测量,有必要进行虚函数调用,然后才进行时间测试。
如果应用程序仅运行一次GPU代码至关重要,则可以使用在多次运行中持久的编译缓存。有关详细信息,请阅读nvcc文档(CUDA_DEVCODE_CACHE环境变量)。
答案 3 :(得分:1)
cvtColour是一个小型操作,主机(CPU)和设备(GPU)之间的内存传输时间远远超过了在GPU上执行任何性能提升。最小化此内存传输的延迟是任何GPU计算的主要挑战。
答案 4 :(得分:0)
你有什么GPU?
检查计算兼容性,也许是原因。
https://developer.nvidia.com/cuda-gpus
这意味着对于具有CC 1.3和2.0二进制图像的设备 准备好了。对于所有较新的平台,1.3的PTX代码是JIT 到二进制图像。对于具有CC 1.1和1.2的设备,PTX for 1.1是 JIT'ed。对于具有CC 1.0的设备,没有可用的代码和 函数抛出异常。对于JIT编译的平台 首先执行,运行缓慢。