2016-04-08 59 views
0

GPU'daki Harris köşe tespiti üzerinde çalışıyorum. CPU performansımın alışılmadık davranışlarını gözlemliyorum.Kernel of GPU'yu çağırdıktan sonra CPU'nun performansı azaldı

Bu çağrıyı, ana işlevimi yorumlayarak çalıştırarak bu Main.cpp dosyasımdan sonra gelir (Bu işlev çeşitli GPU'yu çağırır) "Harris_Algo(a,d_a,d_g,dx_My,dy_My,dxdy_My,suppressed,corner_response,Res,Height,length,SIZE);" Bir sonraki kareyi okumak ve gri ölçeğe dönüştürmek için işlev çağrısı ("cap.read (Masrc)) ve cvtColor (Masrc, src, CV_BGR2GRAY)) 0,003 ortalama ve 0.004 sn kare başına alır.

Şaşırtıcı benim grafik işlemcisi çekirdek arama fonksiyonu "Harris_Algo" aynı işlemci fonksiyonu (cap.read (Masrc) ve cvtColor uncomment zaman (Masrc, src, CV_BGR2GRAY)), kare başına ortalama 0,009 ve 0,008 saniye sürüyor

Uygulamada zamanlama çok kritik olduğundan, bu varyasyon benim tarafımdan elde ettiğim avantajı öldürüyor. GPU. Bu iki işlev çağrısı GPU ile hiçbir ilgisi yok hala GPU işlevi (çekirdek) aradığımda daha fazla zaman alıyor.

Ne var ki, GPU işlevimin (Kernel) CPU üzerindeki ek yükü arttığını ve kullanımının arttığını ve performansın azaldığını düşünüyorum. Fakat bu çeşitlenme çok büyük. Bunu yapmak için başka herhangi bir uygun yöntem.

Herhangi bir yardım için teşekkür ederiz.

Jetson TK1 GPU kartını kullanıyorum.

main.cpp dosyası

#include <iostream> 
#include <time.h> 
#include <fstream> 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 

using namespace std; 
using namespace cv; 
void Cuda_Free(unsigned char *d_a,unsigned char *d_g,int *dx_My,int *dy_My,int *dxdy_My,int *suppressed,int *corner_response); 

void Harris_Algo(unsigned char *a,unsigned char *d_a,unsigned char *d_g,int *dx_My,int *dy_My,int *dxdy_My,int *suppressed,int *corner_response,int *Res, int Height,int length,int SIZE); 

void MemAlloc(unsigned char *&d_a,unsigned char *&d_g,int *&dx_My,int *&dy_My,int *&dxdy_My,int *&suppressed,int *&corner_response,int SIZE); 


    int main(int argc, char** argv) 
    { 
     cv::VideoCapture cap(argv[1]); 

     if (!cap.isOpened()) 
     { 
      std::cout << "!!! Failed to open file: " << argv[1] << std::endl; 
      return -1; 
     } 

     double time_spent; 
     clock_t begin3, end3,begin4; 
     bool start = false; 

     Mat src; 
     unsigned char *a,*d_a,*d_g; 
     int *dx_My,*Res; 
     int *dy_My; 
     int *dxdy_My; 
     int *suppressed; 
     int *corner_response; 
     int length; 
     int Height; 
     int SIZE; 
     Size S; 
     VideoWriter outputVideo; 

     Mat Masrc; 
     for(;;) 
     { 

      begin4 = clock(); 
      begin3 = clock(); 
      if (!cap.read(Masrc))    
       break; 
        end3 = clock(); 
      time_spent = (double)(end3 - begin3)/CLOCKS_PER_SEC; 
      cout<<"Read Frame    : "<<time_spent<<endl; 

      begin3 = clock(); 
      cvtColor(Masrc, src, CV_BGR2GRAY); 
         end3 = clock(); 
      time_spent = (double)(end3 - begin3)/CLOCKS_PER_SEC; 
      cout<<"Gray Convert    : "<<time_spent<<endl; 

      begin3 = clock(); 
      if(start == false) 
      { 
       length  = src.cols; 
       Height  = src.rows; 

       cout<<"Width"<<length<<endl; 
       cout<<"Height"<<Height<<endl; 
       SIZE = ((length)*(Height)); 

       Res = new int [SIZE]; 

       MemAlloc(d_a,d_g,dx_My,dy_My,dxdy_My,suppressed,corner_response,SIZE); 

       start = true; 

      } 

      a = src.data; 

      end3 = clock(); 
      time_spent = (double)(end3 - begin3)/CLOCKS_PER_SEC; 
      cout<<"Initial Processsing Time    : "<<time_spent<<endl; 

      Harris_Algo(a,d_a,d_g,dx_My,dy_My,dxdy_My,suppressed,corner_response,Res,Height,length,SIZE); 

      begin3 = clock(); 

      // imshow("Harris_OUT", Masrc); 
     // char key = cvWaitKey(1); 
     // if (key == 27) // ESC 
      //  break; 

      end3 = clock(); 
      time_spent = (double)(end3 - begin3)/CLOCKS_PER_SEC; 
      cout<<"Time After Displaying image on Output : "<<time_spent<<endl; 
      time_spent = (double)(end3 - begin4)/CLOCKS_PER_SEC; 
      cout<<"Overall Time of entire program exec : "<<time_spent<<endl; 
      cout<<"-----------------------------------------------------------------------------"<<endl; 

     } 

     Cuda_Free(d_a,d_g,dx_My,dy_My,dxdy_My,suppressed,corner_response); 
     delete Res; 
     cvWaitKey(0); 
    } 

Kernal.cu

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 
#include <iostream> 
#include <time.h> 
#include <fstream> 

using namespace std; 
__global__ void Harris_Mat(int *corner_response,int* dx_My,int* dy_My,int* dxdy_My,int rows, int cols,int Size) 
{ 

    /*...*/ 
} 

__global__ void Supress_Neighbour(int *input,int *output, int rows, int cols, int Size) 
{ 
    /* ... */ 
} 

__global__ void VectorGauss(unsigned char *D, unsigned char *M,int Length, int size_m) 
{ 
    float Val; 
    int i = blockIdx . x * blockDim . x + threadIdx . x; 
    if(i>0 & i<size_m) 
    { 
     if ((i%Length) ==(0) || (i%Length) == (Length-1)|| (i<Length) || (i>(size_m-Length))){ 
      M[i] = 0; 
     } 

     Val = ((D[i] +(D[Length+i]) + D[2*Length+i]) +(D[i]+ (D[Length+i])+ D[2*Length+i]) 
       +(D[i+1] + D[i+Length+1] + D[2*Length+i+])); 
    } 
} 

__global__ void VectorAdd(unsigned char *D,int* dx,int* dy,int* dxdy,int Length, int size_m) 
{ 

/* ... */ 
} 


__host__ void MemAlloc(unsigned char *&d_a,unsigned char *&d_g,int *&dx_My,int *&dy_My,int *&dxdy_My,int *&suppressed,int *&corner_response,int SIZE) 
{ 
    cudaMalloc (&d_a,SIZE*sizeof(unsigned char)); 
    cudaMalloc (&d_g,SIZE*sizeof(unsigned char)); 
    cudaMalloc (&dx_My,SIZE*sizeof(int)); 
    cudaMalloc (&dy_My,SIZE*sizeof(int)); 
    cudaMalloc (&dxdy_My,SIZE*sizeof(int)); 
    cudaMalloc (&suppressed,SIZE*sizeof(int)); 
    cudaMalloc (&corner_response,SIZE*sizeof(int)); 
} 

__host__ void Harris_Algo(unsigned char *a,unsigned char *d_a,unsigned char *d_g,int *dx_My,int *dy_My,int *dxdy_My,int *suppressed,int *corner_response,int *Res, int Height,int length,int SIZE) 
{ 
    double time_spent; 
    clock_t begin3, end3; 
    begin3 = clock(); 
    cudaMemcpy(d_a,a,SIZE*sizeof(unsigned char),cudaMemcpyHostToDevice); 


    VectorGauss<<< SIZE/512+1,512>>>(d_a,d_g,length,SIZE); 

    VectorAdd<<< SIZE/512+1,512>>>(d_g,dx_My,dy_My,dxdy_My,length,SIZE); 

    Harris_Mat<<< SIZE/512+1,512>>>(corner_response,dx_My,dy_My,dxdy_My,Height,length,SIZE); 

    Supress_Neighbour<<< SIZE/512+1,512>>>(corner_response, suppressed,Height, length, SIZE); 


    cudaMemcpy(Res,suppressed,SIZE*sizeof(int),cudaMemcpyDeviceToHost); 
    end3 = clock(); 
    time_spent = (double)(end3 - begin3)/CLOCKS_PER_SEC; 

    cout<<"Processsing Time of Algorithm   : "<<time_spent<<endl; 
} 

__host__ void Cuda_Free(unsigned char *d_a,unsigned char *d_g,int *dx_My,int *dy_My,int *dxdy_My,int *suppressed,int *corner_response) 
{ 
    cudaFree(d_a); 
    cudaFree(d_g); 
    cudaFree(dx_My); 
    cudaFree(dy_My); 
    cudaFree(dxdy_My); 
    cudaFree(corner_response); 
    cudaFree(suppressed); 

} 

derlemek için NVCC kullanımı ve aynı zamanda (NVCC ve g ++) hem de aynı sonuç kullanılır.

g++-4.8 -c Main.cpp 
nvcc -c Kernal.cu 
g++-4.8 -o Output Main.o Kernal.o -L/usr/local/cuda/lib -lcudart -lcuda `pkg-config opencv --cflags --libs` 
+0

CUDA bellek ayırmanızın ek yükü oluşturduğunu düşünüyorum. Hafızayı statik olarak sadece bir kez tanımladığınızdan ve sadece bir kez temizlediğinizden düşünüyorum. Neden her bir çerçeve için cudaMalloc ve cudaFree'yi denemiyorsunuz (bu fonksiyonun içinde Harris_Algo). –

+0

Evet, CUDA Bellek ayırma pahalıdır, bu nedenle tüm video karelerini işlemek için yalnızca bir kez yapıyorum. Her kare için yaparsam, o zaman yüküm kocaman olacak. Bunu denedim ama her kare için bellek ayırırsak genel süre daha fazla olacaktır. –

+1

Tüm zaman ölçüm yaklaşımınız yanlış. Lütfen saat() için man sayfasını okuyun. Yaptığınız şekilde saat-zaman kodunu kullanamazsınız.CPU saniye ve saniye aynı şey değil – talonmies

cevap

1

Ben GPU'ya ilgili sizin işlevini çağırarak zaman CPU üzerinde uzun süreleri sahip olduğunuz göre iki nedeni var kullanarak kodumu çalışan

:

  • Bu iki kopya itibaren bir aramaları CudaMemCpy ile VRAM'dan RAM ve VRAM'dan RAM'e geri dönüş. Bunun bir maliyeti var.
  • Çekirdeğiniz başladıktan sonra ikinci kopya çağrılır, GPU'nun hesaplamayı bitirmesini bekler, as cudaMemCpy is blocking/sync.

Bu hesaplamayı GPU'da yaparak bir performans geliştirmeniz olabilir, ancak bellek kopyaları daha pahalıya mal olursa, CPU tarafında her şeyi yaptıysanız daha az performansa sahip olursunuz.

+0

Evet, CudaMemCpy engelliyor ve maliyetli. Buradaki kaygım, "cap.read (Masrc) ve cvtColor (Masrc, src, CV_BGR2GRAY)" işlevlerinin her ikisi de CudaMemCpy dışındadır. Her bir karenin cihazına geri hafıza dahil olmak üzere tüm GPU hesaplamalarının tamamlanmasından sonra, yukarıdaki fonksiyonu çağırıyorum ve ölçülen süre sadece kodun tamamı için değil bireysel işlev içindir. CPU, CUDA çağrısı yapılmadığı zamana göre CUDA işlev çağrısı olduğunda yalnızca bu iki işlevi yürütmek için (yürütme süresinin tamamı değil) iki kattan fazla zaman alır. Not: CudaMemCpy zaman ölçümünde dikkate alınmaz. –

+0

Artık verdiğiniz kod, diğer kullanıcıların performans sorununuzu araştırması için çok eksik. Aynı sorunu yaratan tam bir kod sağlamalısınız, neden Minimal Tam Doğrulanabilir bir örnek olmasın? MCVE: http://stackoverflow.com/help/mcve – Taro