OpenMP 没有给出正确的结果和不同的时间
Posted
技术标签:
【中文标题】OpenMP 没有给出正确的结果和不同的时间【英文标题】:OpenMP doesn't give right result and different time 【发布时间】:2022-01-22 12:55:02 【问题描述】:我是 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;
以下是三个不同测试运行的结果:
-
第一个结果:
-
第二个结果:
-
第三个结果:
【问题讨论】:
浮点加法有精度损失。 不要使用原子。您的 for 循环应标记为reduction(+:sum)
。
好的,谢谢。我想我明白了。
您可以将运行结果包含为文本(在代码块中),而不是文本的屏幕截图。
好的,我接下来改进
【参考方案1】:
用OMP求和的正确方法是:
#pragma omp for reduction(+:sum)
而不是
#pragma omp for private(x)
...
#pragma omp atomic
据我所知,原子子句在执行过于频繁时会增加很大的开销(实际上就是这样)。
另外,x
的范围可以大大缩小,简化代码:不需要使用private。
关于不同的结果,这是正常的,因为您在不同的执行中以不同的顺序添加浮点数。用小数操作大数时问题更大,因为它们需要在操作时进行归一化并且会降低精度。双打的情况下,精度是15位,所以如果你加1000000000000000 + 1,结果还是1000000000000000,即使你做了很多次。
【讨论】:
谢谢你的回答,加深了我的理解。以上是关于OpenMP 没有给出正确的结果和不同的时间的主要内容,如果未能解决你的问题,请参考以下文章