假设(CUDA 内核网格)块中的许多扭曲正在重复更新相当数量的共享内存位置。
哪些情况下这样的工作会更快完成?:
- 内部warp访问局部性的情况,例如每个warp访问的内存位置总数很少,其中大部分确实是由多个通道访问的
- 访问反局部性的情况,所有车道通常都访问不同的位置(并且可能是为了避免银行冲突)?
同样重要的是——这种微架构是依赖于微架构的,还是在所有最近的 NVIDIA 微架构上都基本相同?
假设(CUDA 内核网格)块中的许多扭曲正在重复更新相当数量的共享内存位置。
哪些情况下这样的工作会更快完成?:
同样重要的是——这种微架构是依赖于微架构的,还是在所有最近的 NVIDIA 微架构上都基本相同?
在 SM5.0 (Maxwell) 及更高版本的 GPU 上,共享内存原子(假设 add)由于地址冲突(两个通道具有相同地址),共享内存单元将重播指令。正常的银行冲突重播也适用。在 Maxwell/Pascal 上,共享内存单元在两个 SM 分区之间具有固定的循环访问(每个分区中有 2 个调度程序)。对于每个分区,共享内存单元将在移动到下一条指令之前完成该指令的所有重播。Volta SM 将在任何其他共享内存指令之前完成该指令。
在 Fermi 和 Kepler 架构上,必须在读修改写操作之前执行共享内存锁定操作。这阻止了所有其他经纱指令。
感谢 Fermi/Kepler,Maxwell 和更新的 GPU 具有明显更快的共享内存原子性能。
可以编写一个非常简单的内核来对您的两种不同情况进行微基准测试。CUDA 分析器为共享内存访问提供指令执行计数和重放计数,但不区分由于原子操作引起的重放和由于加载/存储冲突或向量访问引起的重放。
即使不需要知道任何关于如何在 CUDA 硬件中实现共享内存原子,也可以提出一个非常简单的论点:归根结底,原子操作必须在某些时候以某种方式序列化。这通常是正确的,无论您在哪个平台或硬件上运行都没有关系。原子性有点天生就需要它。如果您有多个并行发出的原子操作,则必须以某种方式以确保原子性的方式执行它们。这意味着原子操作总是会随着争用的增加而变慢,无论我们谈论的是 GPU 还是 CPU。唯一的问题是:多少。这取决于具体的实现。
因此,一般来说,您希望保持争用级别,即将尝试在同一内存位置并行执行原子操作的线程数尽可能低……</p>
这是一个推测性的部分答案。
考虑相关问题:共享内存上原子操作的性能及其接受的答案。
如果那里接受的答案是正确的(并且即使在今天仍然是正确的),那么更本地化的访问中的扭曲线程将相互妨碍,使得许多通道原子操作的速度变慢,即使扭曲原子的反局部性更好的。
但老实说 - 我不确定我是否完全接受这一论点,也不知道自从写完答案后情况是否发生了变化。