避免 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>
即可为您提供不可分割的 ++
和 --
运算符,您可以在此处使用它们。
我在阅读有关 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>
即可为您提供不可分割的 ++
和 --
运算符,您可以在此处使用它们。