CUDA线程交互内存可见性问题:验证原子操作与__threadfence()正确性
CUDA线程间内存可见性问题解答
你的推理是否正确?
是正确的。核心逻辑完全成立:
__threadfence()的作用是强制栅栏前的所有写操作,必须在栅栏后的内存操作开始前完成全局内存的可见性同步。对线程A来说,修改a的原子写一定会在读取b的操作前,让所有其他线程可见;线程B同理。- 两种场景都能满足需求:
- 如果A读取
b时,B对b的修改还没完成,那后续B读取a时,A对a的修改已经因__threadfence()完成全局同步,B必然能读到修改后的a,感知到A的操作; - 如果B先完成对
b的修改,A读取b时会拿到修改后的值,直接感知到B的操作。
- 如果A读取
能否将atomicOr(.,0)替换为普通读操作?
绝对不能。原因在于:
- CUDA的普通全局读操作(比如直接
b_read_by_A = *b;)可能从线程私有缓存或L1缓存中取数据,无法保证读取到全局内存中最新的修改结果。 atomicOr(b, 0)本质是一个原子读操作(因为Or0不会改变原变量的值),但它会强制走全局内存的原子操作通路,确保读取到的是当前全局内存中b的最新状态,不会被缓存旧值干扰。- 换成普通读的话,可能出现A和B都读取到对方修改前的旧值,导致两个线程都感知不到对方的修改,完全违反你的需求。
是否必须使用__threadfence()?
是的,必须用。如果去掉__threadfence(),CUDA的内存模型允许编译器或硬件对内存操作进行重排序:
- 比如线程A中,读取
b的操作可能被提前到修改a的操作之前执行,这样A读到的是b的旧值,同时a的修改还没同步到全局内存,B读取a时也拿到旧值,最终两个线程都没感知到对方的修改,直接破坏了你需要的保证。 __threadfence()就是用来锁死这个顺序,确保写操作的全局可见性完成后,再执行后续的读操作,让你的逻辑闭环成立。
内容的提问来源于stack exchange,提问作者JohnB
相关产品推荐
相关产品推荐

