【问题标题】:Openmp results are not robust?Openmp 结果不稳健?
【发布时间】:2018-08-02 22:55:56
【问题描述】:

我是openmp的新手,当我将openmp添加到我的代码中时,我发现在不同的运行中结果不一样。这是openmp的固有问题还是我的代码问题?谢谢!

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <math.h>
#include<sstream>
#include <omp.h>
using namespace std;

int main()
{
    double a[1000];
    for (int i = 0; i < 1000; i++)
    {
        a[i] = 0;
    }
    for (int m = 0; m < 1000; m++)
    {
    #pragma omp parallel for shared(a)
        for (int i = 0; i < 1000000; i++)
        {
            int b = pow(i, 0.5);
            if (b < 1000)
            {
                //cout << i <<" "<<sin(i)<< endl;

                a[b] += sin(i);
            }
        }
    }

    fstream all_temp;
    all_temp.open("temperatureabcd.dat", fstream::out);
    for (int aaa = 0; aaa < 1000; aaa++)
    {
        all_temp << a[aaa] << endl;
    }
    all_temp.close();
    return 0;
}

【问题讨论】:

  • 两个问题。你正在做一个数组缩减。您需要#pragma omp parallel for reduction(+:a[1000]),但您使用的是不支持数组缩减的 MSVC。获得更好的编译器(GCC、Clang 或 ICC)或手动进行缩减。第二个问题:浮点运算不是关联的,因此添加数字的顺序很重要。但是减少数组是你的主要问题。

标签: c++ visual-c++ openmp robust


【解决方案1】:

您的代码正在减少数组。简单的解决方案是做

#pragma omp parallel for reduction(+:a[:1000])

但是,您使用的 MSVC(我从预编译的标头 stdafx.h 推断)不支持 OpenMP 数组缩减。您可以通过像这样更改代码来手动进行数组缩减

double a[1000] = {0};
for (int m = 0; m < 1000; m++) {
  #pragma omp parallel
  {
    double a2[1000] = {0};
    #pragma omp for nowait
    for (int i = 0; i < 1000000; i++) {
      int b = pow(i, 0.5);
      if (b < 1000) a2[b] += sin(i);
    }
    #pragma omp critical
    for(int i = 0; i < 1000; i++) a[i] += a2[i];
  }
}

另一个问题是浮点加法不是关联的,因此减少的顺序很重要。这可以通过更多的工作来解决,但这可能不是您的主要问题。

【讨论】:

  • 感谢您的帮助!你能告诉我你使用什么编译器而不是 MSVC 吗?由于我的代码只有一个文件,因此很容易移植到其他编译器。我的代码对耗时有点敏感,我想检查在其他编译器中使用缩减时是否更省时。再次感谢1
  • @LunLi,我主要使用 GCC 和 ICC。 GCC、ICC、Clang,我认为甚至 PGI(也支持 OpenMP 的最佳 OpenACC 编译器)也支持数组缩减。 MSVC 是唯一没有的。
  • 再次感谢您的帮助。很抱歉再次打扰您。实际上,数组是我的代码中的动态打开数组。如果我使用归约,我应该使用归约(+:a[n])吗?我将英特尔 C++ 编译器集成到 Visual Studio 中。它是否与独立的 ICC 编译器一样工作?谢谢
  • @LunLi,ICC 在 Visual Studio 中应该可以正常工作。我想我记错了。它是reduction(+:a[:1000])。事实上我认为你可以做reduction(+:a)。但我认为a 必须是一个数组而不是一个指针。我不太确定。见stackoverflow.com/questions/20413995/…
  • 感谢您的帮助。我的代码现在是并行的,但它甚至比非并行代码还要慢。我认为可能是循环部分不够大。
猜你喜欢
  • 2018-04-02
  • 1970-01-01
  • 2013-12-07
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 2014-10-19
  • 2018-03-17
相关资源
最近更新 更多