我想知道OpenGL中线程的执行顺序。
假设我的移动GPU通常在8 ... 32之间n_cores
(例如 ARM Mali )。这意味着它们与Nvidia(AMD)经线(波前)不同。
我问的原因是因为以下玩具示例
layout(local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
shared float a[16];
void main() {
uint tid = gl_GlobalInvocationID.x; // <-- thread id
// set all a to 0
if (tid < 16) {
a[tid] = 0;
}
barrier();
memoryBarrierShared();
a[tid % 16] += 1;
barrier();
memoryBarrierShared();
float b = 0;
b = REDUCE(a); // <-- reduction of a array a
}
b
与执行(glDispatchCompute(1, 100, 1)
)不同,好像有一些竞争条件。
我不确定工作组中的线程是否真正并发(如流式多处理器中的warp)。
还有多少核心映射到工作组/着色器?
您对此有何看法?感谢
答案 0 :(得分:3)
恰好有
b
执行与执行(glDispatchCompute(1, 100, 1)
)不同,好像有一些竞争条件。
那是因为有一个:
a[tid % 16] += 1;
对于本地大小为256的工作组,该工作组中至少有两个具有相同值tid % 16
的调用。因此,这些调用将尝试操纵a
的相同索引。
由于没有障碍或任何其他机制来阻止这种情况,因此这是a
元素的竞争条件。因此,您会得到未定义的行为。
现在,您可以通过atomic operations:
操纵a
atomicAdd(a[tid % 16], 1);
这是明确定义的行为。
我不确定工作组中的线程是否真正并发(如流式多处理器中的warp)。
这是无关紧要的。您必须将它们视为同时执行。
还有多少核心映射到工作组/着色器?
再次,基本上无关紧要。这在性能方面很重要,但这主要取决于你的本地团队规模有多大。但就你的代码是否有效而言,它并不重要。