Caching CUDA/OpenCL缓存一致性、局部性和空间填充曲线
我正在开发一个CUDA应用程序,它利用了卡上所有可用的RAM,并试图找出不同的方法来减少缓存未命中 问题域由大型二维或三维网格组成,具体取决于所解决问题的类型。(对于那些感兴趣的人来说,这是一个FDTD模拟器)。每个元素依赖于“并行”数组中的两个或四个元素(即,另一个维度几乎相同的数组),因此内核必须访问三个或六个不同的数组 问题 *希望这不是“太本地化”。请随意编辑问题 三个数组之间的关系可以可视化为(为平庸的ASCII艺术道歉) 通过线连接的项目是耦合的。如上所述,Caching CUDA/OpenCL缓存一致性、局部性和空间填充曲线,caching,cuda,space-filling-curve,Caching,Cuda,Space Filling Curve,我正在开发一个CUDA应用程序,它利用了卡上所有可用的RAM,并试图找出不同的方法来减少缓存未命中 问题域由大型二维或三维网格组成,具体取决于所解决问题的类型。(对于那些感兴趣的人来说,这是一个FDTD模拟器)。每个元素依赖于“并行”数组中的两个或四个元素(即,另一个维度几乎相同的数组),因此内核必须访问三个或六个不同的数组 问题 *希望这不是“太本地化”。请随意编辑问题 三个数组之间的关系可以可视化为(为平庸的ASCII艺术道歉) 通过线连接的项目是耦合的。如上所述,A[]既依赖于B[]又依赖
A[]
既依赖于B[]
又依赖于C[]
,而B[]
只依赖于A[]
,就像C[]
一样。所有A[]
在第一个内核中更新,所有B[]
和C[]
在第二个内核中更新
如果我将这些数组声明为简单的2D数组,那么我最终会得到快速的内存访问。对于非常大的域大小(上述网格中为3x3+-1),这会导致占用率和性能不足
因此,我考虑在Z顺序曲线中重新排列阵列布局:
此外,将这些元素交织到一个数组中是相当简单的,这将提高获取性能,因为(取决于交织顺序)给定单元更新所需的元素中至少有一半彼此接近。然而,我不清楚GPU在访问多个数组时是否使用多个数据指针。如果是这样,这种想象中的好处实际上可能是一种障碍
问题
我听说NVidia在使用纹理内存或cudaArray
时会在后台自动执行此操作。如果不是这样,我是否应该期望在跨越大跨度时(当Z曲线在高细分级别从右上角到左下角时)延迟增加,以消除较小网格中局部性的好处
好长的问题。感谢您阅读并回答所有这些问题。从未回答列表中删除以下内容: 在进行了大量的基准测试并使用不同的安排之后,我发现的最快的方法是保持数组以z顺序交错,以便线程所需的大多数值都位于RAM中彼此相邻的位置。这改善了缓存行为(从而提高了性能)。显然,在许多情况下,Z顺序无法将所需值保持在一起。我想知道旋转象限是否可以减少Z末端和下一象限之间的“距离”,但我还没有尝试过
谢谢大家的建议。据我所知,在
A
、B
和C
之间有这样的依赖关系:A[I]=B[I]op C[I]
,B[I]=op A[I]
?一些代码也会有帮助。
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]