并行缩减顺序寻址中的内存库冲突

memory bank conflict in parallel reduction sequential addressing

我正在阅读 NVIDIA 的一张幻灯片,其中讨论了可用的并行缩减算法 here

在幻灯片 15 中:

作者讨论了使用顺序寻址可以避免内存库冲突。我认为这是错误的,这是我的理由: 在幻灯片 10 中,我们假设每个线程块内部有 128 个线程。在图中蓝色框中提供的顺序代码中,线程 0 尝试同时使用 sdata[0]sdata[64] 并且由于我们有 32 个内存库,这 2 个访问导致内存库冲突. 我的推理哪一部分是错误的?

这与读取端 (sdata[tid + s]) 和写入端 (sdata[tid]) 之间的存储体冲突无关。它是关于一个或另一个操作内的库冲突,但在相邻线程之间。

请记住,半扭曲内的线程同时进行内存访问。在第一个代码中,该索引跨度为 2 * s。因此,例如对于 2 * s == 32,每个线程访问同一个内存库,假设有 32 个内存库。

在第二个代码中,所有线程都按顺序访问数组元素,没有步幅,索引仅因线程ID而异。所以他们总是命中不同的内存库。

编辑

快速警告:请注意 Nvidia 的 Volta Tuning Guide

Applications that assume reads and writes are implicitly visible to other threads in the same warp need to insert the new __syncwarp() warp-wide barrier synchronization instruction between steps where data is exchanged between threads via global or shared memory. Assumptions that code is executed in lockstep or that reads/writes from separate threads are visible across a warp without synchronization are invalid.

这会影响幻灯片 22 中的代码(最后一个扭曲的展开)。另外,我很确定使用 Warp Shuffle Functions 而不是使用共享内存可以更好地解决这部分问题。

编辑 2

github 存储库中的 Example Code 已适当更新。网络研讨会的某个地方可能也有更新版本。