CUDA by Example: Appendex
再次考虑 dot 计算
在第 5 章的 dot 计算中,我们在每个块上做完 reduction 之后就将数据拷贝回到 CPU 了,然后让 CPU 做最后的加法。
为什么在 compute capability 2.0 之前,atomicAdd
只支持整数?因为原子加法是不能指定计算的发生顺序的,因而每个计算都必须遵守结合律,也就是 $(A+B)+C$ 必须等于 $A+(B+C)$。但是浮点数因为中间结果的舍入问题,并不能保证这一点!!
本节接下来是讲解用原子操作实现一个忙等待的 mutex,用于同步多个 CUDA 线程(因为在写书的时候浮点数的原子加法还没有受到设备的广泛支持)。atomicCAS
就是 CUDA 上的比较并交换。
// mutex 的类型是 int *,而且是分配在 GPU 上的
__device__ void lock( void ) {
while( atomicCAS( mutex, 0, 1 ) != 0 );
}
__device__ void unlock( void ) {
atomicExch( mutex, 1 );
}
Note
这里的 unlock
方法并不是直接对 *mutex
赋值为 1,因为 CUDA 中原子操作和普通的内存访问经过的路径不同,所以应该在 unlock
的时候也统一使用原子操作。