Сравнение корреляции и сокращения Matlab против CUDA на двумерном массиве - PullRequest
0 голосов
/ 06 августа 2010

Я пытаюсь сравнить кросс-корреляцию с использованием FFT и метода оконного вычисления.

Мой код 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:

__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];
                }
            }       
        }
    }

Я назвал это в своем ядре как

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();

Каким-то образом, когда я выполняю 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;

1 Ответ

4 голосов
/ 06 августа 2010
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 потока на блок, а количество потоковых блоков на 1 больше, чем необходимо для обработки элементов pix3.Если pix3 действительно 400, то вы обрабатываете 400 элементов, потому что вы запускаете 7 потоковых блоков, каждый из которых выполняет 64 пункта, а 48 из них ничего не делает.

Я не слишком уверен, в чем здесь проблема.

Кроме того,

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

blockize и nblocks фактически преобразуются в векторы dim3, так что они имеют значение (x, y, z).Если вы вызываете ядро ​​с << 64,7 >>, оно будет переведено в

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

, поэтому для каждого вызова ядра blockIdx имеет 3 компонента, идентификатор потока x, y и z, соответствующий трехмерной сетке потоков, в которой вы находитесь. В вашем случае, поскольку у вас есть только компонент x, blockIdx.y и threadIdx.y будут равны 1, несмотря ни на что.По сути, они бесполезны.

Честно говоря, вам кажется, что вы должны перечитать основы CUDA из руководства пользователя, потому что есть много основ, которые, по-видимому, вам не хватает.Объяснение этого здесь не будет экономичным , поскольку все это записано в хорошей документации, которую вы можете получить здесь .И если вы просто хотите иметь более быстрое БПФ с cuda, есть ряд библиотек, которые вы можете просто загрузить и установить в зоне Nvidia CUDA, которые сделают это для вас, если вы не хотите изучать CUDA.

Желаем удачи, приятель.

PS.вам не нужно вызывать cudaThreadSynchronize после каждого ядра;)

...