避免 OpenMP 中的竞争条件?

Avoiding race condition in OpenMP?

我在阅读有关 OpenMP 和共享内存编程的内容时,发现了这个具有整数 x 和两个线程的伪代码

thread 1
x++;

thread 2
x--;

这会导致竞争条件,但可以避免。我想使用 OpenMP 避免它,应该怎么做?

我认为这是可以避免的:

int x;
#pragma omp parallel shared(X) num_threads(2)

int tid = omp_get_thread_num();
if(tid == 1)
    x++;
else
    x--;

我知道通过消除竞争条件会导致正确执行但也会导致性能不佳,但我不知道为什么?

如果多个线程正在修改 x,则代码存在竞争条件风险。采用您的示例的简化版本

int main()
{
    int x = 0;

    #pragma omp parallel sections
    {
        #pragma omp section {
            ++x;
        }
        #pragma omp section {
            --x;
        }
    }

    return x;
}

修改x的两个线程可能会相互交错,这意味着结果不一定为零。

保护修改的一种方法是将读取-修改-写入代码包装在 critical 区域中。

另一个适合此处简单操作的方法是用 #pragma omp atomic 标记 ++-- 行 - 将在它们存在的地方使用平台原生原子指令,与临界区相比,它是轻量级的。

另一种 通常 有效的方法(但 OpenMP 不严格保证)是将用于 x 的类型更改为标准原子类型。只需将它从 int 更改为 std::atomic<int> 即可为您提供不可分割的 ++-- 运算符,您可以在此处使用它们。