CUDA atomicAdd函数执行结果不符预期的原因咨询
问题原因分析及修正
核心问题1:预期值错误
你给出的数组初始值中slist[1] = 2,对它执行加10操作后,正确结果就是12,你预期的11是错误的——显然是混淆了slist[0](初始值1)和slist[1]的初始值。
核心问题2:atomicAdd返回值误用
atomicAdd(ptr, val)的行为是:将ptr指向的内存值加上val,同时返回操作前的原始值。你的代码中把这个返回值赋值给了slist[0],导致两个关键问题:
- 线程0执行时,
atomicAdd(slist+0,10)先把slist[0]从1改成11,但随后你用返回的原始值1覆盖了slist[0],直接抵消了原子加的效果,所以最终slist[0]停留在1。 - 所有线程都在修改
slist[0],这是无保护的非原子赋值,存在竞态条件——多个线程同时写slist[0],最终值取决于最后完成赋值的线程,只是你的输出刚好显示了线程0赋值后的结果。
修正后的核函数代码
如果你的目标是对每个数组元素执行原子加10操作,不需要修改slist[0],代码应改为:
__global__ void RunAtomicAdd(int* slist, int* val) { int id = threadIdx.x; // 仅执行原子加,可选保存原始值用于调试 int old_value = atomicAdd(&slist[id], 10); printf("list[0]= %d, list[%d]= %d (原始值: %d)\n", slist[0], id, slist[id], old_value); }
执行后,数组元素会变为:slist[0]=11、slist[1]=12、slist[2]=13、slist[3]=14、slist[4]=15,符合原子加的预期。
内容的提问来源于stack exchange,提问作者JungW
相关产品推荐
相关产品推荐

