我有一个CUDA内核,其中输入是一个全局数组,输出是另一个相同大小的数组。我试图将值重新映射从一个数组到另一个数组的值由其中一个邻居的值决定。伪代码看起来像这样:
remap(int* in, int* out, int* counter) {
idx = threadIdx
q = index calculated based on idx
if ( in[q] > 0 ) {
newValue = in[q];
} else {
newValue = *counter;
*counter += 1;
in[q] = newValue;
}
out[idx] = newValue;
}
此代码的问题是多个线程将尝试同时检查和更新q
索引的值。真正的代码更接近我想要达到的目标:
__global__
void remap(int* in, const int* out, int* counter) {
idx = threadIdx;
q = index calculated based on idx;
newValue = atomicCAS(&in[q], 0, atomicAdd(counter, 1));
out[idx] = newValue;
}X
根据文档,上述atomicCAS
会计算(in[q] == 0) ? newCounter : in[q]
并根据需要存储结果。问题是无论条件是否满足,newCounter = counter + 1
都会得到更新。我一直在找东西:
(in[q] == 0) ? in[q] = (counter += 1) : in[q]
我确实意识到上面的语法在语法上是不正确的,只是试图说明我试图同时原子化两个更新操作,counter
的增量和{{1的更新但是,只有在满足条件的情况下,如果不满足,我不想要它们中的任何一个。
希望问题相当清楚。现在的问题是,这一切都可行吗?如果满足条件则对两个缓冲区进行原子更新,否则为缓冲区的值。或者这在CUDA中是不可行的,我应该在其他地方寻找。