CUDA 原子操作
CUDA 原子操作和 C++ 的原子操作概念基本是一样的。
给出定义:An atomic function performs a read-modify-write atomic operation on one 32-bit, 64-bit, or 128-bit word residing in global or shared memory.
128 bit 的支持似乎是新版本加的,网上部分资料还仅限于 32 和 64 bit
本文记录一些特殊点和坑点。
使用
CUDA 原子操作被包装成了函数。
比如原子加法 atomicAdd(int* addr, int val)
。向 addr 地址加上 val。
对于操作的对象,如定义所言,只支持 32, 64, 128 bit 的类型。
返回旧值
原子函数的返回值是参数地址被修改前的值。
利用这一点,可以实现 filter。
__global__ void myCudaFilter(int *dest, const int *arr, int len){
int idx = ...; // linear index of current thread
__shared__ int sum = 0;
// filter element that greater than 114
if (arr[idx] > 114) {
// loc is the value before increment
int loc = atomicAdd(&sum, 1);
dest[loc] = arr[idx];
}
}
实现任意原子操作
atomicCAS
先介绍 atomicCAS。全称:atomic Compare And Swap
int atomicCAS(int *addr, int cmp, int val)
查看 addr 里的值是否等于 cmp,如果等于,将 addr 的值置为 val。
任意原子操作
__device__ __inline__ int myAtomicAdd(int *dest, int src) {
int old = *dst, expect;
do {
expect = old;
old = atomicCAS(dest, expect, expect + src);
} while (expect != old);
return old;
}
访存性能优化
如果很多线程在一小段时间内对同一使用原子操作,这些线程会串行执行而损失并行度。
可以使用线程局部变量作为缓存,最后再将局部变量使用原子操作同步到目标地址。