2010-08-05 6 views
0

나는 윈도우 잉 방법을 사용하여 FFT와 교차 상관을 비교하려고합니다.Matlab과 CUDA 상관 관계 비교 및 ​​2D 배열에서의 감소

내 MATLAB 코드는 다음과 같습니다

isize = 20; 
n = 7; 
for i = 1:n %%7x7 xcorr 
    for j = 1:n 
    xcout(i,j) = sum(sum(ffcorr1 .* ref(i:i+isize-1,j:j+isize-1))); %%ref is 676 element array and ffcorr1 is a 400 element array 
    end 
end 

유사한 CUDA 커널 : 나는

어떻게 든
int blocksize = 64; //multiple of 32 
int nblocks = (pix3+blocksize-1)/blocksize; //round to max pix3 = 400 
xc_corr <<< nblocks,blocksize >>> (ffcorr1, ref_d, pix3, isize, npix, xcout, xc_partial); 
cudaThreadSynchronize(); 

로 내 커널이 호출 한

__global__ void xc_corr(double* in_im, double* ref_im, int pix3, int isize, int n, double* out1, double* temp1, double* sum_temp1) 
{ 

    int p = blockIdx.x * blockDim.x + threadIdx.x; 
    int q = 0; 
    int i = 0; 
    int j = 0; 
    int summ = 0; 

    for(i = 0; i < n; ++i) 
    { 
     for(j = 0; j < n; ++j) 
     { 
      summ = 0; //force update 
      for(p = 0; p < pix1; ++p) 
      { 
       for(q = 0; q < pix1; ++q) 
       { 
        temp1[((i*n+j)*pix1*pix1)+p*pix1+q] = in_im[p*pix1+q] * ref_im[(p+i)*pix1+(q+j)];    
        sum_temp1[((i*n+j)*pix1*pix1)+p*pix1+q] += temp1[((i*n+j)*pix1*pix1)+p*pix1+q]; 
        out1[i*n+j] = sum_temp1[((i*n+j)*pix1*pix1)+p*pix1+q]; 
       } 
      }  
     } 
    } 

, 나는 DIFF에 대한 작업을 수행 할 때 출력 파일을 보면, CUDA 커널은 처음 400 개 요소 만 계산합니다.

이 커널을 작성하는 올바른 방법은 무엇입니까 ??

또한 커널에서 아래와 같이 i, j를 선언 할 때의 차이점은 무엇입니까 ??

int i = blockIdx.x * blockDim.y + threadIdx.x * threadIdx.y; 
int j = blockIdx.y * blockDim.x + threadIdx.x * threadIdx.y; 
+0

pix3이란 무엇입니까? 픽셀 길이? 또는 다른 것? – Xzhsh

+0

@Xzhsh pix3은 픽셀의 길이이며 팁에 대해 감사 드리며 400 (20x20) – vivekv80

답변

4
int blocksize = 64; //multiple of 32 
int nblocks = (pix3+blocksize-1)/blocksize; //round to max pix3 = 400 
xc_corr <<< nblocks,blocksize >>> (ffcorr1, ref_d, pix3, isize, npix, xcout, xc_partial); 

는 블록 당 64 개 개의 스레드를 개시 및 pix3 요소를 처리하는 데 필요한 것보다 1 이상일 수 threadblocks 것을 의미한다. pix3이 실제로 400이면 400 개의 요소를 처리합니다. 각 스레드는 64 개의 점을 처리하는 7 개의 스레드 블록을 시작하고 48 개는 아무 것도 수행하지 않기 때문입니다.

여기에 무슨 문제가 있는지 잘 모르겠습니다. 또한

, 그들은 (X, Y, Z) 값을 갖도록

int i = blockIdx.x * blockDim.y + threadIdx.x * threadIdx.y; 
int j = blockIdx.y * blockDim.x + threadIdx.x * threadIdx.y; 

블록 크기 및 nblocks 실제로, dim3 벡터로 변환된다. 만약 >> < < 64,7와 커널을 호출하면, 해당 각 커널 호출하므로

dim3 blocksize(64,1,1); 
dim3 nblocks(7,1,1); 
kernel<<blocksize,nblocks>>(); 

로 번역 할 것이다의 blockIdx는 대응하는 3 개 성분, 스레드 ID x, y, z를 갖는 당신이 속한 쓰레드의 3d 그리드로. 당신의 경우, x 구성 요소 만 있기 때문에, blockIdx.y와 threadIdx.y는 모두 상관없이 1이 될 것입니다. 근본적으로, 그들은 쓸모가 없습니다.

솔직히 사용자 설명서에서 CUDA의 기초를 다시 읽어야하는 것처럼 보입니다. 누락 된 것으로 보이는 기본 사항이 많기 때문입니다. 여기에서 설명하면 경제적이지 않다. since it's all written down in a nice documentation you can get here. CUDA로 더 빠른 FFT를 원한다면 CUDA 학습에 신경 쓰지 않는다면 Nvidia의 CUDA 영역에 다운로드하여 설치할 수있는 라이브러리가 많이 있습니다.

운 좋은 친구.

추신. 각 커널 다음에 cudaThreadSynchronize를 호출 할 필요가 없습니다.)

+0

입니다. 블록 당 단지 64 개의 스레드 만 인스턴스화한다는 것을 이해합니다. 나는 이것을 다시 쓸 수 있었다. dim3 threadsperblock (20,20); dim3 numblocks (pix3/threadsperblock.x, pix3/threadsperblock.y); 더 나은 방법이라면 CUDA Occupancy 계산기를 사용하여이를 확인하고 싶었지만 사용 된 레지스터의 수와 점유 정도를 잘 모릅니다. 내 질문은 커널, 제안/수정에 관한 것입니까? – vivekv80