error: reduction variable is private in outer context (omp reduction)

error: reduction variable is private in outer context (omp reduction)

我对下面两种情况下变量acc的数据共享范围感到困惑。在案例 1 中,我得到以下编译错误:error: reduction variable ‘acc’ is private in outer context,而案例 2 编译没有任何问题。

根据 this article 在并行区域外定义的变量是共享的。

为什么添加 for 循环并行性私有化 acc? 在这种情况下,我如何累积在 for 循环中计算的结果并将循环的迭代 space 分布到线程组?

案例 1

            float acc = 0.0f;
            
            #pragma omp for simd reduction(+: acc)
            for (int k = 0; k < MATRIX_SIZE; k++) {
                float mul = alpha;
                mul *=  a[i * MATRIX_SIZE + k];
                mul *=  b[j * MATRIX_SIZE + k];
                acc += mul;
            }

案例 2

            float acc = 0.0f;
            
            #pragma omp simd reduction(+: acc)
            for (int k = 0; k < MATRIX_SIZE; k++) {
                float mul = alpha;
                mul *=  a[i * MATRIX_SIZE + k];
                mul *=  b[j * MATRIX_SIZE + k];
                acc += mul;
            }


您的案例 1 违反了 OpenMP 语义,因为存在一个包含 acc 定义的隐式并行区域(参见 OpenMP Language Terminology,“顺序部分”)。因此,acc 确实是该隐式并行区域的私有对象。这就是编译器所抱怨的。

您的案例 2 的不同之处在于 simd 构造不是工作共享构造,因此对 reduction 子句的语义有不同的定义。

如果您这样写,情况 1 将是正确的:

void example(void) {
    float acc = 0.0f;

    #pragma omp parallel for simd reduction(+: acc)
    for (int k = 0; k < MATRIX_SIZE; k++) {
        float mul = alpha;
        mul *=  a[i * MATRIX_SIZE + k];
        mul *=  b[j * MATRIX_SIZE + k];
        acc += mul;
    }
}

acc 变量现在定义在 for simd 构造绑定到的 parallel 之外。