【发布时间】:2014-02-08 23:47:48
【问题描述】:
我正在尝试在内核代码中构建索引结构:
atomicCAS((int*)&index[val], -1, atomicAdd((unsigned int*)&index_pos, 1));
index[] 声明为动态共享内存数组并初始化为 -1,index_pos 声明为 volatile。
直觉如下:只有块中的第一个线程应该初始化index并增加index_pos。但是我注意到 index_pos 通过冲突线程多次递增。 为什么会这样?
【问题讨论】:
-
所有线程(至少在 warp 中)将在其他任何事情发生之前递增
index_pos。为什么你的直觉是只有块中的第一个线程应该这样做?这行源代码被转换为一系列汇编语言指令,由warp 锁步执行。如果一个线程执行atomicAdd,那么warp 中的所有线程也会执行它。也许您应该转储汇编指令 (cuobjdump -sass my_app) 并考虑那里发生了什么。我认为这将是有益的。 -
一旦第一个线程将获得锁并执行CAS操作(index[val]=index_pos++)index[val]的值将不再是-1。其他线程将无法进入 CAS 块。对不对?
-
不,这不正确。也许你应该重新阅读我的评论。您显示的单行源代码并未在各个方面都以原子方式执行。大约执行的第一个操作是
atomicAdd,这将由所有线程完成(至少在经线中)。我认为如果您考虑到将其分解为汇编语言指令序列。整个汇编指令序列不是原子执行的。 -
好的,我明白了。那么
while ((new_index_cache_pos=atomicCAS((int*)&region_index_cache[region], -1, index_cache_pos + 1)) == -1); index_cache_pos = new_index_cache_pos;是否适合我的情况?
标签: parallel-processing cuda gpgpu gpu