OpenMP - 循环中最简单的累加器给出不正确的结果
Posted
技术标签:
【中文标题】OpenMP - 循环中最简单的累加器给出不正确的结果【英文标题】:OpenMP - simplest accumulator in loops gives incorrect result 【发布时间】:2014-05-20 15:13:17 【问题描述】:我正在使用英特尔 C++ 编译器并在 16 个线程上运行该程序。我希望第一个循环并行运行。我猜“计数”的结果应该是 30000000。但是,结果却是不到 30000000。错误在哪里?谢谢!
#include <stdio.h>
#include <omp.h>
int main()
long count = 0;
#pragma omp parallel
#pragma omp for
for (long i = 0; i < 10000000; i++)
for (int j = 0; j < 3; j++)
count++;
printf("%d", count);
【问题讨论】:
从我对OpenMP的有限理解来看,#pragma omp for
标记的循环的每个操作都必须相互独立。
@C.R. “独立”是什么意思?我的代码有什么问题?谢谢。
【参考方案1】:
您已经编写了规范的数据竞赛。程序中的所有线程都在竞争更新变量count
,并且无法保证每个线程读取、更新、然后将值写入变量的顺序。无论您认为 C++ 是否保证++
被原子应用。
您应该继续阅读您的 OpenMP 教程以了解共享(和私有)变量,以及减少。 p>
如果您在这里搜索 SO,您应该会发现类似的问题,其中一些问题的答案包括代码,以向您展示如何做您想做的事情。
【讨论】:
【参考方案2】:您还可以通过插入指令 omp 以原子方式执行增量:
#pragma omp atomic
在您的 count++ 行之前。然后,您避免了之前 HPM 描述的竞争条件。见http://msdn.microsoft.com/en-us/library/8ztckdts.aspx或https://computing.llnl.gov/tutorials/openMP/#ATOMIC
【讨论】:
好吧,可以强制执行原子增量,但这样做实际上会使计算序列化。 诚然,除了“#pragma omp parallel for”之外,我没有使用过任何 OMP,所以我不熟悉其中的来龙去脉 - 正如 HPM 所建议的那样,减少可能比原子更好。我假设最终代码会在增量之前或之后做一些有用的事情,这仍然是并行的,并且计数可以是原子的。否则两个循环都可以替换为 count+=30000000;以上是关于OpenMP - 循环中最简单的累加器给出不正确的结果的主要内容,如果未能解决你的问题,请参考以下文章
C3015:OpenMP 'for' 语句中的初始化格式不正确
使用 OpenMP 在 C、C++ 中并行化嵌套 for 循环的几种方法之间的区别