CUDA学习笔记(五)——原子性操作

说明

原子性操作不是所有的显卡都支持的,只有算力在1.1及以上的才支持全局内存的原子操作,只有1.2及以上算力的才支持共享内存上的原子操作。
由于显卡算力高的是低的一个超集,类似可理解为于高算力版本可以向下兼容。同时,在编译代码的时候,可以告诉nvcc编译器需要什么样的版本,nvcc -arch=sm_1.2即需要1.2算力版本的支持。
如果不支持就需要考虑升级硬件了。

原子操作

原子操作的概念是由多部操作构成的一个操作集合,如果执行该操作集合,就必须全部执行,不能执行部分操作。
如:

x++;

定义上述++操作是一个原子操作,其共分为三步:

  1. 读取x
  2. x + 1
  3. 将2中的结果重新赋值给x

那么这三步是不能被打断,熟悉线程编码的可能很好理解,如果线程A和线程B同时对x执行这个操作,是无法保证这三步都是按照顺序执行的。可能出现A先读取x,在进行+1操作时,B线程完成了读取和+1以及写入的操作,A再进行+1赋值操作后,值就不再是我们预想的样子。
而原子操作,就不会出现这样的问题,如果A在执行这个原子操作,B线程会进入阻塞态,只有A全部执行完成后,B才能获取到资源继续执行。

常见的CUDA原子操作,如下表:

函数名释义
atomicAdd(&value, add_num)加法:value = value + add_num
atomicSub(&value, sub_num)减法:value = value + sub_num
atomicExch(&value, num)赋值:value = num
atomicMax(&value, num)求最大:value = max(value, num)
atomicMin(&value, num)求最小:value = min(value, num)
atomicInc(&value, compare)向上计数:如果(value <= compare)则value++,否则value = 0
atomicDec(&value, compare)向下计数:如果(value > compare或value == 0), 则value–,否则value = 0
atomicCAS(&value, compare)比较并交换:如果(value != compare),则value = compare
atomicAnd(&value, add_num)与运算:value = value & num
atomicOr(&value, add_num)或运算 value = value
atomicXor(&value, add_num)异或运算 value = value ^ num

但是CUDA中线程更多,操作相同地址的内存时,因为竞争关系,就变成了一系列线程在排队执行串行化操作。就失去了CUDA并行计算的优势,甚至会比cpu版本的更慢。

可以使用全局内存和共享内存的原子操作结合的方式,在每个block中将需要进行原子操作的变量存入共享内存中。此时发生竞争的线程只是当前block内的线程,多个block是可以并行计算的。
每个block计算完成后,再将block内的临时变量进行原子操作存入全局内存中,得到最终的结果。
例如:
需要统计一个数组中元素分布情况。
可以在block内统计完该block内所有线程应该访问的地址上的数据,再讲所有的block在合并起来,就能得到最终的结果。

由上可知,原子操作会影响程序性能,所以需要谨慎设置代码逻辑,不然会适得其反。


Reference

https://blog.csdn.net/q583956932/article/details/78826987

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值