Warum Opencv GPU-code langsamer ist als die CPU?
Ich bin mit opencv242 + VS2010 von einem notebook.
Ich habe versucht zu tun, einige einfache test der GPU-block in OpenCV, aber es zeigte die GPU ist 100-mal langsamer als die CPU-codes.
In diesem code, ich habe gerade drehen Sie das Farbbild in ein Graustufenbild, verwenden Sie die Funktion cvtColor
Hier ist mein code, PART1 ist ein CPU-code(test-cpu RGB2GRAY), PART2 ist Bild hochladen GPU, PART3 ist GPU RGB2GRAY, PART4 die CPU RGB2GRAY wieder.
Es gibt 3 Dinge, die macht mich so Fragen:
1 In meinem code, part1 ist 0.3 ms, während Teil4 (das ist genau das selbe mit part1) ist 40ms!!!
2 Den part2 das Bild hochladen zu GPU ist 6000ms!!!
3 Part3( GPU-codes) ist 11ms, es ist so langsam für dieses einfache Bild!
#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;
}
- Es ist nicht so, dass die GPU ist in der Regel "slow". Allerdings, Speicher-transfer zwischen host und device ist extrem langsam. GPU-Berechnung macht nur Sinn, wenn Sie verschieben kann, eine sehr große, hoch parallele Berechnung auf dem Gerät.
- Sollten auch überprüfen, answers.opencv.org/question/1670/...
- Dann übergeben Sie die nicht zugeordnet GpuMat Sie haben GPU-Speicher Zuweisung im inneren GPU-optimierten Funktionen. Um es zu vermeiden, sollten Sie preallocate Ihr Gedächtnis mit der richtigen Größe vor der Funktion usage.
Du musst angemeldet sein, um einen Kommentar abzugeben.
cvtColor nicht sehr viel Arbeit zu machen, Grau ist alle, die Sie haben, um durchschnittlich drei zahlen.
Den cvColor-code auf der CPU mit SSE2-Instruktionen verarbeiten können bis zu 8 Pixel auf einmal, und wenn du TBB, dass es alle Kerne/Hyper-Threads, die CPU läuft auf die 10-fache Taktrate der GPU und schließlich werden Sie nicht haben, um das kopieren von Daten auf die GPU und zurück.
Den meisten Antworten oben sind eigentlich falsch. Der Grund, warum es langsam ist um einen Faktor 20.000 ist natürlich nicht, weil der CPU-Taktgeschwindigkeit schneller ist " und "es hat für das kopieren in die GPU' (akzeptierte Antworten). Dies sind Faktoren, aber zu sagen, dass Sie auslassen, die Tatsache, dass Sie erheblich mehr Rechner-power für ein problem, das ist eklig parallel. Sagen 20.000 x Leistungsunterschied ist, da der letztere ist einfach so schlicht lächerlich. Der Autor hier wusste, dass etwas war falsch, dass ist nicht geradlinig. Lösung:
Ihr problem ist, dass CUDA braucht, um zu initialisieren! Es wird immer initialisiert, die für das erste Bild und dauert in der Regel zwischen 1-10 Sekunden, abhängig von der Ausrichtung von Jupiter und Mars. Nun versuchen Sie dies. Tun die Berechnung zweimal und dann mal die beiden. Sie werden wahrscheinlich sehen, in diesem Fall, dass die Geschwindigkeiten in der gleichen Reihenfolge magnutide, nicht 20.000 x, das ist lächerlich. Können Sie etwas über diese Initialisierung? NÖ, nicht dass ich wüsste. Es ist ein Haken.
edit: ich habe gerade wieder Lesen die post. Sie sagen, Sie arbeiten auf einem notebook. Diese haben oft schäbigen GPU 's und CPU' s mit einem fairen turbo.
versuchen mehr als einmal ausgeführt werden....
-----------Auszug aus http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ
Perfomance
Warum erste Funktionsaufruf ist langsam?
Ist, da der Initialisierungs-Overhead. Auf den ersten GPU-Funktion Aufruf der Cuda-Runtime-API initialisiert ist implizit. Auch einige GPU-code wird kompiliert (Just-In-Time-Kompilierung), die für Ihre Grafikkarte auf der ersten Benutzung. Also für die Leistung zu Messen, ist es notwendig zu tun, dummy-Funktion aufrufen und nur dann durchführen, tests.
Wenn es wichtig ist für eine Anwendung zum ausführen von GPU-code nur einmal, ist es möglich, eine Zusammenstellung cache ist persistent über mehrere Läufe. Bitte Lesen Sie nvcc-Dokumentation für details (CUDA_DEVCODE_CACHE environment-variable).
cvtColour ist eine kleine operation, und jede performance-boost erhalten Sie von der tut es auf der GPU ist wesentlich überwogen in der Erinnerung Transferzeiten zwischen host (CPU) und device (GPU). Die Minimierung der Latenz der Speicher-transfer ist eine zentrale Herausforderung jeder GPU-computing.
Welche GPU hast du?
Check-compute-Unterstützung, vielleicht ist es der Grund.
https://developer.nvidia.com/cuda-gpus
http://docs.opencv.org/modules/gpu/doc/introduction.html