【问题标题】:CUDA / OpenCL cache coherence, locality and space-filling curvesCUDA / OpenCL 缓存一致性、局部性和空间填充曲线
【发布时间】:2013-05-21 14:19:37
【问题描述】:

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

问题域由一个大的 2 维或 3 维网格组成,具体取决于所解决问题的类型。 (对于那些感兴趣的人,它是一个 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 顺序曲线重新排列数组布局:

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

问题

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

  1. 将网格划分为可以放入共享内存的更小块肯定会有所帮助,而 Z 顺序使这变得相当简单。我应该有一个单独的内核通道来更新块之间的边界吗?与我预期的节省相比,启动另一个内核的开销会很大吗?

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

哇 - 很长的问题。感谢您阅读并回答所有这些内容。

【问题讨论】:

  • 据我了解,您在 ABC 之间存在依赖关系,如下所示:A[i] = B[i] op C[i]B[i] = op A[i]C[i] = op A[i]?一些代码也会有所帮助。

标签: caching cuda space-filling-curve


【解决方案1】:

只是为了将其从未答复列表中删除:

经过大量基准测试和不同排列方式后,我发现最快的方法是让数组按 z 顺序交错,这样线程所需的大部分值在 RAM 中彼此靠近。这改进了缓存行为(以及性能)。显然,在许多情况下,Z 顺序未能将所需值保持在一起。我想知道旋转象限是否可以减少 Z 末端和下一个象限之间的“距离”,但我没有尝试过。

感谢大家的建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2021-08-08
    • 2019-01-17
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    相关资源
    最近更新 更多