Cuda 对于GPU扭曲,哪种原子瞄准模式更好:完全相同还是完全不同?
假设我们有:Cuda 对于GPU扭曲,哪种原子瞄准模式更好:完全相同还是完全不同?,cuda,opencl,gpgpu,atomic,Cuda,Opencl,Gpgpu,Atomic,假设我们有: 单经纱(32线) 每个线程t有32个int值val t,0…val t,31 每个值val t,i需要原子地添加到变量desti中,该变量位于(选项1)全局设备内存(选项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 等等 换句话
- 单经纱(32线)
- 每个线程t有32个int值val t,0…val t,31
- 每个值val t,i需要原子地添加到变量desti中,该变量位于(选项1)全局设备内存(选项2)共享块内存中
- GPU有可能拥有将多个原子操作从同一个扭曲集中到一个目的地的硬件,这样它们实际上只算一个,或者至少可以一起调度,因此所有线程将同时执行下一条指令,不要等到所有其他的事情都做完了,最后一次原子行动才结束
- 这个问题的重点是英伟达与CUDA的硬件,但我希望得到有关AMD和其他GPU的答案
- 不管线程是如何得到它们的。假设它们在寄存器中并且没有溢出,或者它们是在寄存器中完成的一些算术运算的结果。忘记任何获取它们的内存访问
- 我就是这样理解您的问题的:
您有一个32x32整数矩阵:
Val0'0,Val1'0,…Val31'0
Val1'0,Val1'1,…Val31'1
.
.
Val31'0,Val31'1,…,Val31'31 您需要对每一行求和:
Val0'0+Val1'0+。。。Val31'0=dest0
Val0'1+Val1'1+。。。Val31'1=dest1等 问题是您的行值分布在不同的线程之间。 对于单个扭曲,最干净的方法是让每个线程使用共享内存(在32x32共享内存阵列中)共享其值。线程同步后,线程i对第i行求和,并将结果写入dest(i),dest(i)可以驻留在全局或共享内存中(取决于您的应用程序)。 通过这种方式,计算工作量(31x31)的增加在扭曲中的线程之间平均分配,您根本不需要原子操作(性能杀手)。
根据我的经验,原子操作通常可以而且应该通过线程之间不同的工作分配来避免。虽然我不知道确切的答案,但我的猜测是倾斜访问更可取。在理想情况下,每个周期至少要执行32个原子操作,但在实际硬件中,您的算法可能会遇到内存访问模式不好的问题。这听起来像是只有通过仔细的基准测试才能解决的问题。是什么阻止了你尝试它?@Talonmes:1。我只有一张(或者两张)卡片可以用来做基准测试。2.答案可能是“这可能取决于其他参数”,在这种情况下,我会考虑它们。3.对于我正在研究的实际问题,我试图减少原子的使用,而不是优化itI,我将使用第二个。第一个访问模式在所有车道的每个循环中具有相同的地址。当共享内存是目标时,这尤其会降低Maxwell之前的CUDA卡的性能(请参阅)。也请看一下和。