Pourquoi Opencv code GPU est plus lent que le CPU?
Je suis en utilisant opencv242 + VS2010 par un ordinateur portable.
J'ai essayé de faire un simple test du GPU bloc dans OpenCV, mais elle a montré que le GPU est 100 fois plus lent que le CPU codes.
Dans ce code, j'ai juste à tourner la couleur de l'image à niveaux de gris de l'image, utilisez la fonction de cvtColor
Voici mon code, PART1 est code de CPU(test cpu RGB2GRAY), PART2 est de télécharger l'image sur GPU, PART3 de la GPU RGB2GRAY, PART4 du CPU est RGB2GRAY de nouveau.
Il y a 3 choses qui me rend si vous vous demandez:
1 Dans mon code, part1 est de 0,3 ms, tandis que part4 (qui est exactement la même chose avec part1) est de 40ms!!!
2 La partie2 téléchargement de l'image sur GPU est 6000ms!!!
3 Part3( GPU codes) est de 11 ms, c'est si lent pour cette simple image!
#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;
}
- Ce n'est pas que le GPU est généralement "lent". Toutefois, la mémoire de transfert entre l'hôte et le périphérique est extrêmement lent. GPU calcul n'a de sens que si vous pouvez vous décharger d'une très grande, très calcul parallèle à l'appareil.
- Devriez également vérifier answers.opencv.org/question/1670/...
- Ensuite, vous passez pas alloué GpuMat vous avez de la mémoire graphique de répartition à l'intérieur de GPU-optimisé fonctions. Pour éviter cela, vous devez préallouer votre mémoire avec la bonne taille avant de l'utilisation de fonction.
Vous devez vous connecter pour publier un commentaire.
cvtColor n'est pas de faire beaucoup de travail, pour faire des gris tout ce que vous avez à l'est la moyenne de trois nombres.
La cvColor code de la CPU est à l'aide d'instructions SSE2 pour traiter jusqu'à 8 pixels à la fois et si vous avez TBB c'est à l'aide de tous les cœurs/hyperthreads, le PROCESSEUR fonctionne à 10x la vitesse d'horloge du GPU et enfin, vous n'avez pas de copie des données sur le GPU et le dos.
La plupart des réponses ci-dessus sont en fait mal. La raison pour laquelle il est lent par un facteur de 20.000 n'est évidemment pas à cause de l'utilisation du PROCESSEUR de clockspeed est plus rapide " et "il a copier sur le GPU' (réponses acceptées). Ces facteurs, mais en disant que vous omettez le fait que vous avez beaucoup plus de puissance de calcul pour un problème qui est épouvantablement parallèle. En disant: 20.000 x différence de performance est en raison de ce dernier est tellement ridicule plaine. L'auteur le savait que quelque chose allait mal, qui n'est pas simple. Solution:
Votre problème, c'est que CUDA doit initialiser! Il sera toujours initialiser pour la première image et prend généralement comprise entre 1 et 10 secondes, en fonction de l'alignement de Mars et de Jupiter. Maintenant, essayez ceci. Faire le calcul deux fois et puis le temps tous les deux. Vous aurez probablement voir dans ce cas que les vitesses sont dans le même ordre de magnutide, pas de 20.000 x, c'est ridicule. Pouvez-vous faire quelque chose à propos de cette initialisation? Non, pas que je sache. C'est un écueil.
edit: je viens de relire le post. Vous dites que vous êtes en cours d'exécution sur un ordinateur portable. Ceux qui ont souvent minable GPU et le CPU avec une juste turbo.
essayez d'exécuter plus d'une fois....
-----------extrait de http://opencv.willowgarage.com/wiki/OpenCV%20GPU%20FAQ
Perfomance
Pourquoi le premier appel de la fonction est lente?
C'est à cause de l'initialisation de frais généraux. Sur le premier GPU appel de fonction API Cuda Runtime est initialisé de façon implicite. Aussi certains GPU code est compilé (Juste Au Moment de la compilation) pour votre carte vidéo sur la première utilisation. Donc, pour la mesure de la performance, il est nécessaire de faire mannequin d'appel de fonction et seulement ensuite effectuer des tests de temps.
S'il est important pour une application à exécuter de code GPU qu'une seule fois, il est possible d'utiliser une compilation de cache qui est persistante sur plusieurs pistes. Veuillez lire nvcc la documentation pour plus de détails (CUDA_DEVCODE_CACHE variable d'environnement).
cvtColour est une petite opération, et toutes les performances que vous obtenez de le faire sur le GPU est largement compensé par la mémoire des temps de transfert entre l'hôte (CPU) et le dispositif (GPU). En minimisant la latence de ce transfert de mémoire est un défi majeur de toute GPU computing.
Ce GPU avez-vous?
Vérifier calculer la compatibilité, c'est peut-être la raison.
https://developer.nvidia.com/cuda-gpus
http://docs.opencv.org/modules/gpu/doc/introduction.html