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 - 循环中最简单的累加器给出不正确的结果的主要内容,如果未能解决你的问题,请参考以下文章

OpenMP 没有给出正确的结果和不同的时间

C3015:OpenMP 'for' 语句中的初始化格式不正确

使用 OpenMP 在 C、C++ 中并行化嵌套 for 循环的几种方法之间的区别

如何使用 OpenMP 通过 C++ std::list 并行化 for 循环?

openMP C++ 简单并行区域 - 输出不一致

OpenMP 矩阵乘法嵌套循环