viv*_*v80 -1 matlab cuda reduction multidimensional-array correlation
我正在尝试使用 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
Run Code Online (Sandbox Code Playgroud)
类似的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];
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我在内核中将其称为
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();
Run Code Online (Sandbox Code Playgroud)
不知何故,当我对输出文件进行比较时,我看到 CUDA 内核只计算前 400 个元素。
编写这个内核的正确方法是什么?
另外,在我的内核中如下声明 i,j 有什么区别?
int i = blockIdx.x * blockDim.y + threadIdx.x * threadIdx.y;
int j = blockIdx.y * blockDim.x + threadIdx.x * threadIdx.y;
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
意味着您要为每个块启动 64 个线程,并且线程块的数量比处理 pix3 元素所需的多 1 个。如果 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;
Run Code Online (Sandbox Code Playgroud)
blocksize 和 nblocks 实际上转换为 dim3 向量,因此它们具有 (x,y,z) 值。如果您使用 <<64,7>> 调用内核,它将被转换为
dim3 blocksize(64,1,1);
dim3 nblocks(7,1,1);
kernel<<blocksize,nblocks>>();
Run Code Online (Sandbox Code Playgroud)
所以对于每个内核调用,blockIdx 有 3 个组件,线程 id x、y 和 z,对应于您所在线程的 3d 网格。在您的情况下,因为您只有一个 x 组件,blockIdx.y 和 threadIdx .y 无论如何都将是 1。所以本质上,它们是无用的。
老实说,您似乎应该从用户手册中重新阅读 CUDA 的基础知识,因为您似乎缺少很多基础知识。在这里解释它并不经济,因为它都写在一个很好的文档中,你可以在这里找到。如果您只想使用 cuda 进行更快的 FFT,您可以在 Nvidia 的 CUDA 区域下载并安装许多库,如果您不关心学习 CUDA,它们将为您完成。
祝你好运。
附注。您不需要在每个内核之后调用 cudaThreadSynchronize ;)