我想知道 OpenGL 中线程的执行顺序。
假设我有一个移动 GPU,n_cores
通常在 8 ... 32 之间(例如 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)
),就好像存在某种竞争条件一样。我不确定工作组中的线程是否真正并发(就像流式多处理器中的扭曲)。
还有多少个核心映射到工作组/着色器?
您对此有何看法?谢谢
最佳答案
It happens that
b
is different from execution to execution (glDispatchCompute(1, 100, 1)
) as if there is some race condition.
那是因为有一个:
a[tid % 16] += 1;
对于本地大小为 256 的工作组,该工作组中至少有两个调用具有相同的 tid % 16
值。因此,这些调用将尝试操作 a
的相同索引。
由于没有障碍或任何其他机制来阻止这种情况,因此这是 a
元素上的竞争条件。因此,您会得到未定义的行为。
现在,您可以通过 atomic operations 操作 a
:
atomicAdd(a[tid % 16], 1);
这是明确定义的行为。
I am not sure wether threads within a work group are really concurrent (like warps in a streaming multiprocessor).
这无关紧要。您必须将它们视为并发执行。
Also how many cores are mapped to work groups/shaders?
同样,本质上是无关紧要的。这对于性能而言很重要,但这主要是关于本地团队规模的大小。但就您的代码是否有效而言,这并不重要。
关于c++ - OpenGL计算着色器中线程的执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41667701/