OpenCL原子操作疑问:为何x[1]结果为8而非1024?
为什么OpenCL Kernel中x[1]的值是8而不是1024?
嘿,这个问题的核心是搞懂OpenCL中local内存的作用域,我来一步步给你拆解清楚:
首先先明确两个关键概念:
__local修饰的变量是每个工作组(workgroup)独有的内存空间:你设置了workgroup_size=8、global_size=1024,所以总共有1024/8=128个独立的工作组,每个组里有8个work-item。这128个工作组各自拥有一套独立的a和b变量,互相之间完全不共享。__global修饰的变量是所有work-item共享的全局内存,比如你代码里的x数组。
接下来看你的Kernel代码执行逻辑:
__kernel void atomic(__global int* x) { __local int a, b; a = 0; b = 0; a++; atomic_inc(&b); x[0] = a; x[1] = b; x[2]++; atomic_inc(x+3); }
关于b和x[1]的结果:
- 每个工作组的8个work-item共享同一个组内的
b:- 虽然每个work-item都执行了
b=0,但因为是同一个工作组的local变量,最终b会被初始化为0(多个work-item同时写0,结果还是0)。 - 之后每个work-item都调用
atomic_inc(&b),对同一个b做原子递增。8次原子递增后,这个工作组的b值就变成了8。
- 虽然每个work-item都执行了
- 所有工作组都会向x[1]写入自己的
b值:- 128个工作组都会执行
x[1] = b,但全局内存的写操作会互相覆盖,最终只有最后一个完成写入的工作组的b值会保留在x[1]里——也就是8。
- 128个工作组都会执行
对比你理解的x[3]:
x[3]是全局变量,所有1024个work-item都对它调用atomic_inc(x+3),相当于对同一个变量做了1024次原子递增,所以结果是1024,这和b的local内存特性形成了鲜明对比。
额外补充:
如果想要让b的最终结果是1024,只需要把b的修饰符从__local改成__global,这样所有work-item共享同一个b,1024次原子递增后就会得到1024。
内容的提问来源于stack exchange,提问作者zcaudate
相关产品推荐
相关产品推荐

