CUDA / OpenCL缓存一致性,局部性和空间填充曲线

时间:2013-05-26 16:07:39

标签: caching cuda space-filling-curve

我正在开发一个使用卡上所有可用内存的CUDA应用程序,并试图找出减少缓存未命中的不同方法。

问题域由大型2或3-D网格组成,具体取决于要解决的问题类型。 (对于那些感兴趣的人,它是FDTD模拟器)。每个元素依赖于“并行”数组中的两个或四个元素(即,几乎相同维度的另一个数组),因此内核必须访问三个或六个不同的数组。

问题

*希望这不是“过于本地化”。随意编辑问题

三个数组之间的关系可以看作是(为平庸的ASCII艺术道歉)

  A[0,0] -C[0,0]- A ---- C ---- A ---- C ---- A
    |             |             |             |
    |             |             |             |
  B[0,0]          B             B             B
    |             |             |             |
    |             |             |             |
    A ---- C ---- A ---- C ---- A ---- C ---- A
    |             |             |             |
    |             |             |             |
    B             B             B             B
    |             |             |             |
    |             |             |             |
    A ---- C ---- A ---- C ---- A ---- C ---- A
    |             |             |             |
    |             |             |             |
    B             B             B             B[3,2]
    |             |             |             |
    |             |             |             |
    A ---- C ---- A ---- C ---- A ---- C ---- A[3,3]
                                      [2,3]

通过线连接的项目是耦合的。如上所示,A[]取决于B[]C[],而B[]仅取决于A[]C[]也是如此。所有A[]都在第一个内核中更新,所有B[]C[]都会在第二次更新时更新。

如果我将这些数组声明为简单的2D数组,我最终会使用跨步内存访问。对于非常大的域大小(上面的网格中为3x3 + 1),这会导致占用率和性能不足。

所以,我考虑在Z顺序曲线中重新排列数组布局:

Z-order space filling curve

此外,将这些交织成一个数组是相当简单的,这应该提高获取性能,因为(取决于交错顺序)给定单元更新所需的至少一半元素将彼此接近。但是,我不清楚GPU在访问多个阵列时是否使用多个数据指针。如果是这样,这种想象的好处实际上可能是一种障碍。

问题

我已经读过NVidia在使用纹理内存或cudaArray时在幕后自动执行此操作。如果不是这种情况,我是否应该期望在跨越大跨度时(当Z曲线在高细分级别从右上角到左下角时)延迟增加,以消除较小网格中局部性的好处?

  1. 将网格划分为可以放入共享内存的较小块应该会有所帮助,而Z顺序使得这相当简单。我应该有一个单独的内核传递来更新块之间的边界吗?与我期望的节省相比,启动另一个内核的开销是否显着?

  2. 使用2D vs 1D阵列有什么好处吗?我希望记忆是线性的,但我不确定在CUDA文献中经常使用的2D内存布局隐喻是否有任何实际意义。

  3. 哇 - 哇 - 长问题。感谢您阅读和回答任何/所有这些。

1 个答案:

答案 0 :(得分:1)

只需将其从未答复的列表中删除即可:

经过大量的基准测试和不同的安排后,我发现最快的方法是使数组以z顺序交错,以便线程所需的大多数值在RAM中彼此靠近。这样改善了缓存行为(从而提高了性能)。显然,在许多情况下,Z阶无法将所需值保持在一起。我想知道是否旋转象限以减小Z末端和下一个象限之间的“距离”,但是我还没有尝试过。

感谢大家的建议。