CUDA并行化从属2D阵列

时间:2014-04-07 20:36:02

标签: c++ arrays cuda

我有以下表格的示例循环。请注意,我的psi[i][j]依赖于psi[i+1][j], psi[i-1][j], psi[i][j+1] and psi[i][j-1],我必须仅为内部矩阵计算psi。现在我尝试在CUDA中写这个,但结果与顺序不一样。

for(i=1;i<=leni-2;i++)
for(j=1;j<=lenj-2;j++){
    psi[i][j]=(omega[i][j]*(dx*dx)*(dy*dy)+(psi[i+1][j]+psi[i-1][j])*(dy*dy)+(psi[i][j+1]+psi[i][j-1])*(dx*dx) )/(2.0*(dx*dx)+2.0*(dy*dy));
}

这是我的CUDA格式。

//KERNEL
__global__ void ComputePsi(double *psi, double *omega, int imax, int jmax)
{
int x = blockIdx.x;
int y = blockIdx.y;
int i = (jmax*x) + y;
double beta = 1;
double dx=(double)30/(imax-1);
double dy=(double)1/(jmax-1);

if((i)%jmax!=0 && (i+1)%jmax!=0 &&  i>=jmax && i<imax*jmax-jmax){
    psi[i]=(omega[i]*(dx*dx)*(dy*dy)+(psi[i+jmax]+psi[i-jmax])*(dy*dy)+(psi[i+1]+psi[i-1])*(dx*dx) )/(2.0*(dx*dx)+2.0*(dy*dy));
}
}


//Code
cudaMalloc((void **) &dev_psi, leni*lenj*sizeof(double));
cudaMalloc((void **) &dev_omega, leni*lenj*sizeof(double));
cudaMemcpy(dev_psi, psi, leni*lenj*sizeof(double),cudaMemcpyHostToDevice);
cudaMemcpy(dev_omega, omega, leni*lenj*sizeof(double),cudaMemcpyHostToDevice);
dim3 grids(leni,lenj);
for(iterpsi=0;iterpsi<30;iterpsi++)         
    ComputePsi<<<grids,1>>>(dev_psi, dev_omega, leni, lenj);

psi[leni][lenj] and omega[leni][lenj]和双数组。

问题是顺序问题,CUDA代码给出了不同的结果。代码中是否需要进行任何修改?

2 个答案:

答案 0 :(得分:1)

您正在使用全局内存,而您正在更改psi条目,而其他线程可能需要旧值。只需将新迭代的值存储在单独的变量中。但请记住,每次迭代后都必须交换变量!! 更复杂的方法是使用共享内存和空间域分配到单独线程的解决方案。只需google获取解决热/扩散方程的CUDA教程,您就会明白这一点。

答案 1 :(得分:0)

for(i=1;i<=leni-2;i++)
  for(j=1;j<=lenj-2;j++){
    psi[i][j]= ( omega[i][j]*(dx*dx)*(dy*dy) + 
                 (psi[i+1][j]+psi[i-1][j]) * (dy*dy) + 
                 (psi[i][j+1]+psi[i][j-1]) * (dx*dx) 
               )/(2.0*(dx*dx)+2.0*(dy*dy));
}

我认为这个内核顺序不正确:psi[i][j]的值取决于此处操作的顺序 - 因此您将使用未更新的psi[i+1][j]psi[i][j+1],但psi[i-1][j]psi[i][j-1]已在此扫描中更新

确保使用CUDA时,结果会有所不同,其中操作顺序不同。

为了强制执行这样的排序,如果可能的话,你需要插入那么多可能对CUDA来说不值得的同步。这真的是你需要做的吗?