【发布时间】:2014-05-30 15:28:08
【问题描述】:
假设我们有:
- 一根经线(32 根线)
- 每个线程 t 都有 32 个 int 值 val t,0...val t,31,
- 每个值 val t,i 需要以原子方式添加到位于(选项 1)中的变量 desti全局设备内存(选项 2)共享块内存。
哪种访问模式执行这些添加会更快:
-
所有线程原子添加 val t,1 到 dest 1。
所有线程原子添加 val t,2 到 dest 2。
等等
-
每个索引为 t 的线程将 val t,t 写入 dest t
索引为 t 的每个线程将 val t, (t+1) mod 32 写入 dest (t+1) mod 32
等等
换句话说,当一个warp的所有线程在同一个周期中进行原子写入时会更快,还是没有原子写入同时发生更好?我可以想到更快地执行任一选项的硬件,我想知道实际实现了什么。
想法:
- GPU 有可能拥有将来自同一个 warp 的多个原子操作聚合到一个目标的硬件,因此它们实际上只是一个,或者至少可以一起调度,因此所有线程都将继续执行下一条指令同时执行,而不是等待所有其他操作完成后最后一个原子操作结束。
注意事项:
- 此问题侧重于具有 CUDA 的 NVidia 硬件,但我希望能提供有关 AMD 和其他 GPU 的答案。
- 别管线程是如何得到它们的。假设它们在寄存器中并且没有溢出,或者它们是在寄存器中完成的一些算术运算的结果。忘记任何内存访问来获取它们。
【问题讨论】:
-
虽然我不知道确切的答案,但我的猜测是偏斜访问更可取。至少每个周期您将发出 32 个原子操作(在理想情况下),但在实际硬件中,您的算法可能会受到较差的内存访问模式的影响。
-
这听起来只能通过大量仔细的基准测试来回答。是什么阻止你尝试它?
-
@talonmies: 1. 我只有一张(或两张)卡可以用来做基准测试。 2. 答案可能是“它可能取决于其他参数”,在这种情况下我会考虑它们。 3. 对于我正在处理的实际问题,我试图减少原子的使用而不是优化它