Parallel processing 在cuda中使用原子操作建立索引

Parallel processing 在cuda中使用原子操作建立索引,parallel-processing,cuda,gpgpu,gpu,Parallel Processing,Cuda,Gpgpu,Gpu,我正在尝试在内核代码中构建索引结构: atomicCAS((int*)&index[val], -1, atomicAdd((unsigned int*)&index_pos, 1)); 索引[]声明为动态共享内存数组,并用-1初始化为,索引_pos声明为volatile 直觉是这样的:只有块中的第一个线程应该初始化index和increment index_pos。但是我注意到,index_pos被冲突的线程多次递增。 为什么会发生这种情况?我无法理解您的代码应该做什么,但是

我正在尝试在内核代码中构建索引结构:

atomicCAS((int*)&index[val], -1, atomicAdd((unsigned int*)&index_pos, 1));
索引[]声明为动态共享内存数组,并用-1初始化为,索引_pos声明为volatile

直觉是这样的:只有块中的第一个线程应该初始化index和increment index_pos。但是我注意到,index_pos被冲突的线程多次递增。
为什么会发生这种情况?

我无法理解您的代码应该做什么,但是,我看不出变量
index\u pos
不应该增加更多次的原因。将一个原子操作嵌套到另一个原子操作中不会产生复合原子操作

例如:

atomicAdd(atomicAdd(x, 1), 1);
不作为

atomicAdd(x, 2);
但是:

评论后编辑:

从您的评论中获得信息后,我将确保使用以下代码描述功能:

if(index[val] == -1) { // this is just an optimization
    atomicCAS((int*)&index[val], -1, threadId); // initialization by the only thread
}

__threadfence_block();

if(index[val] == threadId) {
    index_pos++; //index_pos will be incremented only "once" 
}

所有的线程(至少在翘曲中)将在任何其他情况发生之前增加
index\u pos
。为什么你的直觉认为只有块中的第一个线程应该这样做?这行源代码被转换成一系列汇编语言指令,这些指令由warp锁步执行。如果一个线程执行原子添加,那么warp中的所有线程也将执行它。也许您应该转储汇编指令(
cuobjdump-sass my_app
)并思考那里发生了什么。我认为这会很有启发性。一旦第一个线程获得锁并执行CAS操作(index[val]=index_pos++),index[val]的值将不再是-1。其他线程将无法进入CAS块。是吗?不,那不对。也许你应该重读我的评论。您展示的一行源代码并不是在各个方面都以原子方式执行的。大约执行的第一个操作是一个
atomicAdd
,这将由所有线程(至少在warp中)完成。如果您考虑到这一事实,即它被分解为一系列汇编语言指令,那么我认为这将是一个有指导意义的操作。整个汇编指令序列不是原子式执行的。好吧,我明白你的意思了。因此,
while((new_index_cache_pos=atomicCAS((int*)和region_index_cache[region],-1,index_cache_pos+1))==-1);索引缓存位置=新索引缓存位置为我的案例工作?对不起,如果你给我一行源代码,问我它是否“为你的案例工作”,我无法回答。你甚至(在我看来)没有充分描述你想做什么或者“你的情况”是什么。因此:“1.关于您编写的代码问题的问题必须在问题本身中描述具体问题,并包括复制问题的有效代码。请参阅以获取指导。”我的第一个版本没有使用atomicAdd
atomicCAS((int*)和index[val],-1,index_pos++)。我希望只有在索引[val]未初始化(-1)时,索引_pos才会递增。atomicCAS操作正提供了这种语义,不是吗?
if(index[val] == -1) { // this is just an optimization
    atomicCAS((int*)&index[val], -1, threadId); // initialization by the only thread
}

__threadfence_block();

if(index[val] == threadId) {
    index_pos++; //index_pos will be incremented only "once" 
}