比较Matlab与CUDA相关和2D阵列的减少

时间:2010-08-05 23:18:40

标签: matlab cuda multidimensional-array correlation reduction

我试图比较使用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 个答案:

答案 0 :(得分: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元素所需的数量。如果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;

blocksize和nblocks实际上被转换为dim3向量,因此它们具有(x,y,z)值。如果您使用&lt;&lt;&lt; 64,7&gt;&gt;调用内核,则会将其翻译为

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,那么您可以在Nvidia的CUDA区域下载并安装许多库,如果您不关心学习CUDA,它将为您完成。

祝你好运。

PS。你不需要在每个内核之后调用cudaThreadSynchronize;)