【问题标题】:Memory padding vs coalesced access内存填充与合并访问
【发布时间】:2022-01-20 19:18:41
【问题描述】:

我对银行冲突有点困惑,使用内存填充和合并内存访问来避免它们。到目前为止我读过的内容:从全局内存中合并内存访问是最佳的。如果无法实现,则可以使用共享内存对当前块所需的数据进行重新排序,从而使合并访问成为可能。但是,当使用共享内存时,必须注意银行冲突。避免存储库冲突的一种策略是将存储在共享内存中的数组填充 1。考虑 this blog post 中的示例,其中 16x16 矩阵的每一行都填充 1,使其成为共享内存中的 16x17 矩阵。

现在我明白了使用内存填充可能会避免银行冲突,但这是否也意味着内存不再对齐?例如。如果我将全局内存移动 1 从而使其未对齐,则一个扭曲将需要访问两个内存通道而不是一个,因为最后一个数字与所有其他数字不在同一通道中。因此,据我了解,合并内存访问和内存填充是相互矛盾的概念,不是吗?非常感谢一些澄清!

【问题讨论】:

  • 对全局内存的非合并访问非常昂贵。在共享内存中,与银行冲突相比,这不是问题(如果有的话)。
  • @PaulG。谢谢你的评论。你有这方面的参考吗?例如。它是由 nvidia 官方声明还是有某种研究?
  • This 专门用于 Ampere,但旧架构的文档也是如此。在全局内存的上下文中明确提到了合并。其他提及不那么明确,但我没有找到(快速搜索)任何明确提及共享内存的内容。
  • 顺便说一句,您还可以使用 warp shuffle 指令更正数据布局(这也是由共享内存单元完成的,只是没有实际存储数据)。您将以合并的方式读取数据(可能不止一条记录),然后根据实际需要在线程之间重新洗牌。存储的相反方式。
  • 您可以使用 Nsight Compute 获得有关您的代码的明确答案。对于共享内存,只有使用的通道数很重要,因此访问同一个元素(而不仅仅是同一个通道中的几个元素)只计算一次。因此,对齐(int/float 的 4 个字节除外)和访问内存地址的连续性都不是共享内存的问题。

标签: cuda memory-access bank-conflict


【解决方案1】:

评论太长了,所以我把它放在这里。但仍然不是一个完整的答案。

当我找到 Mark Harris 的 this post 时,它演示了使用共享内存来促进合并内存访问。这个问题的重要结论似乎是:

在此示例中使用共享内存的原因是为了促进旧 CUDA 设备(Compute Capability 1.1 或更早版本)上的全局内存合并。读取和写入都实现了最佳全局内存合并,因为始终通过线性对齐索引 t 访问全局内存。反向索引tr只用于访问共享内存,它没有全局内存的顺序访问限制以获得最佳性能。共享内存的唯一性能问题是银行冲突,我们将在后面讨论。

我最初的理解是,如果无法合并访问全局内存,则将其读取为未合并的,然后在共享内存中重新排序,以实现从共享内存进一步合并访问。但相反,数据是以连续方式从全局内存中读取的,然后可以以非合并方式从共享内存中读取所需的实际数据。 Harris 还指出,从共享内存中进行非合并访问不是问题,但不幸的是,该帖子没有解释原因。

【讨论】:

    猜你喜欢
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2015-01-06
    • 2012-05-06
    • 2011-07-06
    • 1970-01-01
    相关资源
    最近更新 更多