OpenGL计算着色器中线程的执行顺序

时间:2017-01-15 23:57:11

标签: c++ opengl arm

我想知道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)。

  • 还有多少核心映射到工作组/着色器?

  • 您对此有何看法?感谢

1 个答案:

答案 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)。

这是无关紧要的。您必须将它们视为同时执行。

  

还有多少核心映射到工作组/着色器?

再次,基本上无关紧要。这在性能方面很重要,但这主要取决于你的本地团队规模有多大。但就你的代码是否有效而言,它并不重要。