Estoy usando opencv242 + VS2010 con una notebook.
Intenté hacer una prueba simple del bloque de la GPU en OpenCV, pero mostró que la GPU es 100 veces más lenta que los códigos de la CPU. En este código, sólo girar la imagen en color a escala de grises, utilice la función de cvtColor¿Por qué el código de Opencv GPU es más lento que la CPU?
Aquí está mi código, PARTE 1 es el código de la CPU (prueba de CPU RGB2GRAY), PART2 es de carga de imágenes a la GPU, PART3 es GPU RGB2GRAY, PART4 es CPU RGB2GRAY nuevamente. Hay 3 cosas que me preguntan:
1 En mi código, part1 es 0.3ms, mientras que part4 (que es exactamente lo mismo con part1) es 40ms !!!
2 ¡La part2 que sube la imagen a la GPU es 6000ms!
3 Parte 3 (códigos GPU) es 11ms, ¡es tan lento para esta imagen simple!
#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;
}
No es que la GPU sea generalmente "lenta". Sin embargo, la transferencia de memoria entre el host y el dispositivo es * extremadamente * lenta. El cálculo de la GPU solo tiene sentido si puede descargar un cálculo muy grande y altamente paralelo al dispositivo. –
También debería marcar http://answers.opencv.org/question/1670/huge-time-to-upload-data-to-gpu/#1676 – Sam
Luego pasa GpuMat no asignado, tiene asignación de memoria GPU dentro de GPU optimizado funciones. Para evitarlo, debe preasignar su memoria con el tamaño adecuado antes de usar la función. – geek