我正在开发一个CUDA内核来计算图像的直方图( NVIDIA GTX 480 )。我注意到使用cuda剖析器发现了82.2%的分支差异。探查器指示以下函数作为分歧的来源,位于名为 device_functions.h 的文件中(特别是包含return语句的行)。
static __forceinline__
unsigned int __uAtomicAdd(unsigned int *p, unsigned int val)
{
return __nvvm_atom_add_gen_i((volatile int *)p, (int)val);
}
说原子操作会导致分支发散是否正确?
答案 0 :(得分:4)
在某种程度上,CUDA中的原子实现可能因GPU架构而异。但是专门针对GTX 480(费米级GPU),__shared__
内存原子不是作为单个机器指令实现的,而是实际上由a sequence of machine (SASS) instructions that form a loop实现的。
这个循环主要是争夺锁。当某个线程获取锁定时,该线程将在标识的共享内存单元上以原子方式完成所请求的内存操作,然后释放锁定。
获取锁定的循环过程必然涉及分支分歧。在这种情况下,分支差异的可能性在C / C ++源代码中并不明显,但是如果你检查SASS代码就会很明显。
全局原子通常实现为单个(ATOM
或RED
)SASS指令。然而,如果由warp中的多个线程执行,则全局原子可能仍然涉及访问的序列化。我通常不认为这是“分歧”的情况,但我不完全确定分析器如何报告它。如果你进行的实验只涉及全局原子,我认为它会变得清晰。
在您的案例中报告的差异可能完全是由于共享内存分歧(预期),如上所述。