【问题标题】:Building an index using atomic operation in cuda在 cuda 中使用原子操作构建索引
【发布时间】: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; 是否适合我的情况?
  • 对不起,如果你给我一行源代码,并问我它是否“适合你的情况”,我无法回答。您甚至(在我看来)都没有充分描述您正在尝试做什么或“您的情况”是什么。 SO expects:“1.有关您编写的代码问题的问题必须在问题本身中描述具体问题 - 并包括有效的代码来重现它。有关指导,请参阅 SSCCE.org。”

标签: parallel-processing cuda gpgpu gpu


【解决方案1】:

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

例子:

atomicAdd(atomicAdd(x, 1), 1);

不作为

atomicAdd(x, 2);

但是:

atomicAdd(x, 1);
atomicAdd(x, 1);

评论后编辑:

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

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" 
}

【讨论】:

  • 我的第一个版本没有使用 atomicAdd atomicCAS((int*)&index[val], -1, index_pos++);。我希望 index_pos 只有在 index[val] 未初始化(-1)时才增加。 atomicCAS 操作提供的正是这种语义,不是吗?
猜你喜欢
  • 1970-01-01
  • 2012-02-13
  • 2012-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-28
  • 2014-01-11
  • 2011-01-22
相关资源
最近更新 更多