【问题标题】:OpenMP doesn't give right result and different timeOpenMP 没有给出正确的结果和不同的时间
【发布时间】:2023-03-09 10:31:01
【问题描述】:

我是 OpenMP 的新手,现在我正在研究 atomic 的用法。每次跑步我都有不同的结果和时间。有时大约一分钟,有时大约 19 秒。

下面是我的代码:

#include <iostream>
#include<iomanip>
#include<cmath>
#include<omp.h>
#include"KiTimer.h"

int main() 
{
    using namespace std;

    const int NUM_REPEAT = 100000000;
    KiTimer timer;
    timer.MakeTimer(0, "ADD");
    timer.Start();

    double sum = 0., x = 0.;
#pragma omp parallel
    {
#pragma omp single
        cout << "Thread num:" << omp_get_num_threads() << endl;
#pragma omp for private(x)
        for (int i = 0; i < NUM_REPEAT; i++) {
            x = sqrt(i);
#pragma omp atomic
            sum += x;
        }
    }

    cout << setprecision(20) << "total:" << sum << endl;
    timer.Stop();
    timer.Print();
    return 0;
}

以下是三个不同测试运行的结果:

  1. 第一个结果:

  1. 第二个结果:

  1. 第三个结果:

【问题讨论】:

  • 浮点加法有精度损失。
  • 不要使用原子。您的 for 循环应标记为 reduction(+:sum)
  • 好的,谢谢。我想我明白了。
  • 您可以将运行结果包含为文本(在代码块中),而不是文本的屏幕截图。
  • 好的,我接下来改进

标签: c++ openmp


【解决方案1】:

用OMP求和的正确方法是:

#pragma omp for reduction(+:sum)

而不是

#pragma omp for private(x)
...
#pragma omp atomic

据我所知,原子子句在执行过于频繁时会增加很大的开销(实际上就是这样)。

另外,x的范围可以大大缩小,简化代码:不需要使用private。

关于不同的结果,这是正常的,因为您在不同的执行中以不同的顺序添加浮点数。用小数操作大数时问题更大,因为它们需要在操作时进行归一化并且会降低精度。双打的情况下,精度是15位,所以如果你加1000000000000000 + 1,结果还是1000000000000000,即使你做了很多次。

【讨论】:

  • 谢谢你的回答,加深了我的理解。
猜你喜欢
  • 2012-01-16
  • 1970-01-01
  • 2012-05-27
  • 2014-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多