我在两台不同的电脑上运行以下代码,第一台电脑有一块 Nvidia GPU Quadro FX 880M,第二台电脑有一块 Quadro FX 1000M(编译环境为 VS2010、opencv242,64 位;opencv 是从源代码编译的)。
我运行的代码如下:
int n = 1000; //number of iterations
int t = CV_TM_CCORR_NORMED; //correlation type
//reset GPU, print device info
cv::gpu::printCudaDeviceInfo(cv::gpu::getDevice());
cv::gpu::resetDevice();
//read big image
cv::Mat imgA = cv::imread("img.bmp" ,CV_LOAD_IMAGE_GRAYSCALE);
//read small, template image
cv::Mat imgB = cv::imread("tmplt.bmp",CV_LOAD_IMAGE_GRAYSCALE);
//upload images to GPU
cv::gpu::GpuMat imgA_GPU,imgB_GPU;
imgA_GPU.upload(imgA);
imgB_GPU.upload(imgB);
cv::gpu::GpuMat imgC_GPU; //correlation results, computer in GPU
cv::Mat imgC_CPU; //correlation results, computer in CPU
//matchTemplate in GPU, print average time(mSec)
size_t t1 = clock();
for(int i = 0;i!=n;++i)
cv::gpu::matchTemplate(imgA_GPU , imgB_GPU, imgC_GPU , t);
std::cout << "GPU: " <<
(double(clock())-t1)/CLOCKS_PER_SEC*1000.0/n <<std::endl;
//matchTemplate in CPU, print average time(mSec)
size_t t2 = clock();
for(int i = 0;i!=n;++i)
cv:: matchTemplate(imgA , imgB , imgC_CPU , t);
std::cout << "CPU: " <<
(double(clock())-t2)/CLOCKS_PER_SEC*1000.0/n <<std::endl;
//download GPU image to host
cv::Mat imgC_GPUhost;
imgC_GPU.download(imgC_GPUhost);
//convert images to 8U
imgC_CPU.convertTo(imgC_CPU,CV_8U,255);
imgC_GPUhost.convertTo(imgC_GPUhost,CV_8U,255);
//!!!!!! imgC_GPUhost should be equal to imgC_CPU
cv::Mat diff;
cv::absdiff(imgC_CPU,imgC_GPUhost,diff);
//expected: RESULTS DIFF: 0
std::cout << "RESULTS DIFF: " << cv::sum(diff).val[0] << std::endl;
cv::imwrite("cor2.bmp",imgC_CPU);
cv::imwrite("cor.bmp",imgC_GPUhost);
char s;
std::cin >> s;
有两个主要的问题困扰着我:
- 在Quadro FX 880M上,此功能不起作用:GPU输出图像(imgC_GPU)全部为零 - 无论输入类型(8U或32F)或相关方法(ccor,ccoef等)如何。另一方面,在Quadro FX 1000M中,CPU和GPU之间得到了一致的结果。这是怎么回事?我需要做什么来使其在Quadro FX 880M上工作?
- 在模板匹配中,输出图像中的每个像素都可以独立于其他像素计算 - 因此并行化很容易,并且GPU实现非常适合。即使查看平均时间(如代码中所示),GPU性能比CPU慢3倍,这是怎么可能的?在两台电脑上进行验证,没有其他后台进程运行。