如何处理大型3D数据阵列以获得更好的性能?

时间:2017-06-10 23:26:31

标签: arrays cuda fortran

我正在处理存储在3D数组中的大数据。这是我所做的内核示例(由CPU在for循环中调用):

attributes(global) subroutine mykernel (A,B,C,p,nx,ny,nz)

real,dimension(:,:,:),device :: A,B
real,dimension(:),device :: C
real,device :: p
integer,device :: nx,ny,nz

xInd = blockDim.x * (blockIdx.x-1) + threadIdx.x;
yInd = blockDim.y * (blockIdx.y-1) + threadIdx.y;
zInd = blockDim.z * (blockIdx.z-1) + threadIdx.z;

if (xInd<=nx) then
 if (yInd<=ny) then
  if (zInd<=nz) then
   A(xInd,yInd,zInd)=(A(xInd,yInd+1,zInd)-A(xInd,yInd,zInd))*p-(B(xInd,yInd,zInd+1)-C(yInd)+B(xInd+1,yInd,zInd))*p+C(yInd+1)
  end if
 end if
end if

end subroutine mykernel

当我启动内核时,一切似乎都很好,GPU结果与CPU结果相同......但就时间而言,表现并不是很好。

我认为这是由于内存访问,但我不确定。我会把我的3D数组放在共享内存中,但我正在处理nx ny nz&gt; 1M数据,因此共享内存中没有足够的空间。

所以我的以下问题是关于表演问题,有大量数据:

  • 我应该将3D阵列展平为1D阵列吗?我能得到提升吗?
  • 是否可以在不使用全局或共享内存的情况下读取(内存访问)大型数据?
  • 在这种情况下,表演问题的其他可能性有哪些?

1 个答案:

答案 0 :(得分:1)

好吧所以我想我已经弄明白我的问题在我的案例中。

首先,我的内核的执行配置。使用3D数组似乎不是一个好主意,因为我使用太多线程。例如,在这里我选择使用512个线程的块。所以我用512 *(348/8 + 1)(145/8 + 1)(113/8 + 1)= 6 590 628线程调用mykernel。 如果我将我的3D数组展平为1D,我只使用512 *((348 * 145 * 113)/ 512 + 1)= 5 702 492个线程。 但为什么使用更多线程会影响我的表现?

Morover,在CPU循环中(我称之为mykernel):我在CPU和GPU之间使用了太多的传输。因此,为了减少这些传输的时间,我使用了非常有效的固定内存。我强烈建议您使用此链接获取有关how to optimize data transfers的更多解释。

通过所有这些功能,我的GPU代码比CPU代码快16倍,这非常棒!我的代码的第一个版本正在运行&#34;仅#34; x7倍。

希望它可以提供帮助。