优化CUDA FDTD Fortran

时间:2012-03-04 11:12:13

标签: cuda fortran

我正在尝试使用CUDA Fortran优化此FDTD代码。我有三个带有输入,输出和恒星的三维立方体矩阵。

attributes (global) subroutine kernel_h(k,num_cells_x,num_cells_y,num_cells_z,Hx,Hy,Hz,Ex,Ey,Ez,Cbdx,Cbdy,Cbdz)
    implicit none
    integer :: idx,idy
    integer,value :: k,num_cells_x,num_cells_y,num_cells_z
    real(kind=8), intent(in), dimension(1:num_cells_x,1:num_cells_y,1:num_cells_z) :: Ex, Ey, Ez
    real(kind=8), intent(inout), dimension(1:num_cells_x,1:num_cells_y,1:num_cells_z) :: Hx, Hy, Hz
    real(kind=8), intent(in), constant, dimension(1:num_cells_x,1:num_cells_y,1:num_cells_z) :: Cbdx,Cbdy,Cbdz
    idx = threadIdx%x + ((blockIdx%x-1) * blockDim%x)
    idy = threadIdx%y + ((blockIdx%y-1) * blockDim%y)
    do while (idx < num_cells_x)
        Hz(idx,idy,k) = Hz(idx,idy,k) + ((Ex(idx,idy+1,k)-Ex(idx,idy,k))*Cbdy(idx,idy,k) + (Ey(idx,idy,k)-Ey(idx+1,idy,k))*Cbdx(idx,idy,k))
        Hx(idx,idy,k) = Hx(idx,idy,k) + ((Ey(idx,idy,k+1)-Ey(idx,idy,k))*Cbdz(idx,idy,k) + (Ez(idx,idy,k)-Ez(idx,idy+1,k))*Cbdy(idx,idy,k))
        Hy(idx,idy,k) = Hy(idx,idy,k) + ((Ez(idx+1,idy,k)-Ez(idx,idy,k))*Cbdx(idx,idy,k) + (Ex(idx,idy,k)-Ex(idx,idy,k+1))*Cbdz(idx,idy,k))
        idx = idx + (blockDim%x * gridDim%x)
        idy = idy + (blockDim%y * gridDim%y)
    end do
end subroutine kernel_h

我的内核启动是:

bdim=dim3(16,16,1)
gdim=dim3((num_cells_x+(bdim%x-1))/bdim%x,(num_cells_y+(bdim%y-1))/bdim%y,1)
do k=1,num_cells_z
 call kernel_h<<<gdim,bdim>>>(k,num_cells_x,num_cells_y,num_cells_z,Hx_d,Hy_d,Hz_d,Ex_d,Ey_d,Ez_d,Cbdx_d,Cbdy_d,Cbdz_d)
end do

我的问题是:为什么我无法加载超过100x100x100的矩阵?如果我尝试我得到内核错误启动失败。我可以改善我的代码性能吗?我认为它可以用更好的方式编写。

1 个答案:

答案 0 :(得分:3)

我猜你正在访问越界。

考虑10x10x10体积(x,y,z)。在这种情况下,您将启动一个16x16线程的块。这些线程将访问17x17切片(因为模板半径为1),这显然最终会超出界限。您需要禁用那些将访问越界的线程,并禁用那些超出边界的线程来应用它们的模板。

考虑查看CUDA SDK中的FDTD3D示例。虽然它是在C中,但它说明了如何处理这个问题,它还展示了如何使用共享内存来实现更多更高效的实现。