【问题标题】:How to make GNU GCC optimize OpenMP threads similarly如何使 GNU GCC 类似地优化 OpenMP 线程
【发布时间】:2016-03-01 13:23:23
【问题描述】:

这是我在这里的第一篇文章。耶!回到问题:

我正在学习如何使用 OpenMP。我的 IDE 是 Code::Blocks。我想改进我的一些旧程序。我需要确保结果将完全相同。看来“for”循环在主线程中的优化方式与在其他线程中不同。

示例:

#include <iostream>
#include <omp.h>
int main()
{
    std::cout.precision(17);
    #pragma omp parallel for schedule(static, 1) ordered
    for(int i=0; i<4; i++)
    {
        double sum = 0.;
        for(int j=0; j<10; j++)
        {
            sum += 10.1;
        }
        #pragma omp ordered
        std::cout << "thread " << omp_get_thread_num() <<  " says " << sum << "\n";
    }
    return 0;
}

生产

thread 0 says 101
thread 1 says 100.99999999999998579
thread 2 says 100.99999999999998579
thread 3 says 100.99999999999998579

我能否以某种方式确保所有线程都收到与我的单线程程序(未使用 OpenMP)收到的相同的优化?

编辑:

编译器是“来自 TDM-GCC(版本 4.9.2,32 位,SJLJ)的编译器和 GDB 调试器”,不管是什么意思。这是 IDE 的“默认值”。我不熟悉编译器的差异。

提供的输出来自“Release”构建,它添加了“-O2”参数。

“-O”、“-O1”和“-O3”参数都不会产生“101”。

你可以从dropbox (zip file, also contains possibly required dlls)试试我的.exe。

【问题讨论】:

  • 您能提供更多信息吗?您使用的是哪个编译器?例如,如果我使用 gcc 4.8.x,我会得到:线程 X 表示所有线程的 100.99999999999999。话虽如此,大多数 OpenMP 运行时只是为循环体创建一个新的概述例程,并且每个线程都执行相同的例程。
  • gcc 4.9 和 5.3 的同义词
  • 完成。你也在使用“发布”版本吗?
  • @Gilles 是同一个 IDE 吗?因为 Code::Blocks 在构建过程中添加了额外的参数,比如“-O2”。
  • 我尝试在 32 和 64b 模式下使用 gcc 4.9.3 和 gcc 5.3.0,并进行了各种优化:我总是让所有线程打印相同的输出,这是大多数时候“100.99999999999999”。 只有在 32b 模式下使用 -O2 时,我会得到“101”,但对于所有线程,所以没有差异,即使在这里......

标签: c++ multithreading gcc openmp gcc4.9


【解决方案1】:

这是因为 float 或 double 数据类型不能表示某些数字,例如 20.2

#include <iostream>
int main()
{
    std::cout.precision(17);
    double a=20.2;
    std::cout << a << std::endl;
    return 0;
}

它的输出将是

20.199999999999999

有关更多信息,请参阅 Unexpected Output when adding two float numbers

不知道为什么第一个线程不会发生这种情况,但是如果您删除 openMP,那么您也会得到相同的结果。

【讨论】:

  • 问题是为什么应该做完全相同的线程得到不同的结果,而不是为什么真的可能不是你对有理数的期望。
  • @Voo 是正确的。我知道我不会得到 20.2,但如果我将它乘以 10,我需要始终保持 201.999999999999997 或 202,无论单线程程序会产生哪个。
【解决方案2】:

据我所知,这只是数值准确性。对于双精度值类型,您应该期望 16 位精度。

即结果是 101 +/- 1.e-16*101

这正是你得到的范围。除非您使用四倍精度之类的东西,否则这已经足够了。

【讨论】:

  • 问题是为什么应该做完全相同的线程得到不同的结果,而不是为什么真的可能不是你对有理数的期望。
  • 最初的问题是“我想改进我的一些旧程序。我需要确保 [b] 结果完全相同。[/b]”。在可达到的精度范围内,结果是相同的。除非您使用某些四倍精度数据类型,否则这不会变得更好。即使你这样做了,你也会面临完全相同的问题,只是移动了 16 位。
  • @Voo 是正确的。在我的程序中,由于“蝴蝶效应”link,最后一位数字很重要。
  • @Stratubas “在我的程序中,最后一位数字很重要”嗯,如果您使用任何物理测量作为输入,它们显然不能。米的长度不知道精确度,其他基本单位也有类似的问题!
  • @Jim Sure... 但我没有使用物理测量值 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-21
  • 1970-01-01
相关资源
最近更新 更多