我猜,循环试图访问相同的内存位置
同时。
TL,DR : 是的,在变量n 的更新期间,您有一个竞态条件。一种解决方法是使用 OpenMP 缩减子句。
我是 OpenMP 新手,只知道一些命令,仅此而已。现在在
我上面写的代码,最终结果出错(n = 9 是
正确答案)。
更长的答案:
#pragma omp parallel for 将创建一个parallel region,并使用default chunk size 和default schedule 为该区域的threads 分配它所包含的循环的迭代,即通常 static。但是请记住,default schedule 在 OpenMP 标准的不同具体实现之间可能会有所不同。
您可以从OpenMP 5.1 阅读更正式的描述:
worksharing-loop 结构指定一个或一个的迭代
更多相关的循环将由线程中的线程并行执行
团队在他们的隐含任务的背景下。 迭代是
分布在团队中已经存在的线程中
执行工作共享循环区域所在的并行区域
绑定。
Moreover,
并行循环结构是指定并行循环的快捷方式
包含带有一个或多个相关联的循环构造的构造
循环,没有其他语句。
或者非正式地,#pragma omp parallel for 是构造函数 #pragma omp parallel 和 #pragma omp for 的组合。
因此,您的代码中发生的情况是,您有多个线程同时修改 n 的值,要解决此问题,您应该使用 OpenMP 缩减子句,从 OpenMP 标准可以阅读:
归约子句可用于执行某些形式的递归
并行计算 (...)。 用于并行和工作共享
构造,创建每个列表项的私有副本,每个列表项一个
隐式任务,好像使用了 private 子句。 (...) 这
然后按上面指定的方式初始化私有副本。在结束时
指定缩减子句的区域,原始列表
通过将其原始值与最终值组合来更新项目
每个私有副本,使用指定的组合器
减少标识符。
有关 reduction 子句如何工作的更详细说明,请查看SO Thread。
所以要解决代码中的 race-condition,只需将其更改为:
int n = 0;
#pragma omp parallel for collapse(2) reduction(+:n)
for (int i = 0; i < 3; i++)
for(int j = 0; j < 3; j++)
n++;