编译器优化:G 比英特尔慢

Compiler optimization: g++ slower than intel

本文关键字:英特尔 优化 编译器      更新时间:2023-10-16

我最近在C 中获取了一台带有双启动的计算机。在Windows上,我在Linux上使用Intel C 编译器和G 。我的程序主要由计算(具有数值集成等的固定点迭代算法等(组成。
我以为我可以在Linux上的Windows附近获得表演,但是到目前为止,我还没有:对于完全相同的代码,使用G 编译的程序比Intel编译器慢了2倍。从我阅读的内容来看,ICC可以更快,甚至可能收益20%至30%,但我没有读到有关它的速度两倍(总的来说,我实际上都读到两者都应该是同等的(。

首先,我使用的是大约等效的标志:

icl/openMP/i" c: boost_1_61_0"/fast Program.cpp

g -o program.cpp -std = c 11 -fopenmp -o3 -ffast -Math

遵循其他几个主题的建议,我尝试添加/替换其他几个标志,例如:-funsafe -math -optimizations,-march =本机,-f fhole -few program,-ofast,-ofast等。

ICC真的很快还是我缺少什么?我是Linux的新手,所以我不知道,也许我忘了正确安装某些内容(例如驱动程序(,或者在G 中更改某些选项?我不知道情况是否正常,这就是为什么我更喜欢问。尤其是因为我更喜欢使用Linux来理想地编码,因此我宁愿要尽快加速。

编辑:我决定在Linux上安装最后一个Intel编译器(Intel Compiler C 17,Update4(进行检查。我最终得到了缓解的结果:它的表现并不比GCC更好(实际上更糟糕(。我运行了交叉比较linux/Windows -ICC/GCC-使用帖子前面提到的标志(为了进行直接比较(,这是我的结果( time 运行1次迭代, MS (:

  1. 普通环,无平行化:

    • Windows:
      GCC = 122074;ICC = 68799
    • linux:
      GCC = _91042;ICC = 92102
  2. 并行版本:

    • Windows:
      GCC = 27457;ICC = 19800
    • linux:
      GCC = 27000;ICC = 30000

总结:这有点混乱。在Linux上,GCC似乎总是比ICC更快,尤其是在涉及并行化时(我将其用于更长的程序,差异比这里的差异要高得多(。
在Windows上,情况恰恰相反,ICC显然主导了海湾频道,尤其是在没有并行化的情况下(在这种情况下,GCC需要很长时间才能编译(。

最快的汇编是在Windows上使用并行化和ICC完成的。我不明白为什么我不能在Linux上复制它。我需要做什么(Ubuntu 16.04(来帮助固定我的流程吗?
另一个区别是,在Windows上,我使用旧的英特尔作曲家( Composer Xe 2013 (并调用' ia32 '而不是Intel64(这是我应该使用的(在Linux上,我使用昨天安装的最后一个版本。在Linux上,Intel编译器17文件夹在我的第二个HDD上(而不是我的SSD安装的SSD(,我不知道这是否也可能会减慢速度。
知道问题可能来自哪里吗?

编辑:精确的硬件: Intel(R(Core(TM(I7-4710HQ CPU @ 2.50GHz,8 CPU,4核,每个核心2个线程,体系结构x86_64-Linux ubuntu 16.04带有GCC 5.4.1和Intel编译器17(Update4(-Windows 8.1,英特尔作曲家2013

编辑:代码很长,这是我正在测试的循环的形式(即我的固定点迭代的一个迭代(。我想这是非常经典的...不确定它会带入这个话题。

// initialization of all the objects...
// length_grid1 is about 2000
vector< double > V_NEXT(length_grid1), PRICE_NEXT(length_grid1);
double V_min, price_min; 
#pragma omp parallel
{ 
#pragma omp for private(V_min, price_min, i, indexcurrent, alpha, beta)
    for (i = 0; i < length_grid1; i++) {
         indexcurrent = indexsum[i]; 
         V_min = V_compute(&price_min, indexcurrent, ...);
         V_NEXT[indexcurrent] = V_min; PRICE_NEXT[indexcurrent] = price_min;
     }
 }// end parallel

其中v_compute函数是一种经典而简单的优化算法(自定义 Golden Search (返回最佳值及其参数:

double V_compute(double *xmin, int row_index, ... ) {
double x1, x2, f1, f2, fxmin;
// golden_ratio=0.61803399; 
x1 = upper_bound - golden_ratio*(upper_bound - lower_bound);
x2 = lower_bound + golden_ratio*(upper_bound - lower_bound);
// Evaluate the function at the test points
f1 = intra_value(x1, row_index, ...);
f2 = intra_value(x2, row_index, ...);
while (fabs(upper_bound - lower_bound) > tolerance) {
    if (f2 > f1){
        upper_bound = x2; x2 = x1; f2 = f1;
        x1 = upper_bound - golden_ratio*(upper_bound - lower_bound);
        f1 = intra_value(x1, row_index, ...);
    } else {
        lower_bound = x1; x1 = x2; f1 = f2;
        x2 = lower_bound + golden_ratio*(upper_bound - lower_bound);
        f2 = intra_value(x2, row_index, ...);
    }
}
// Estimated minimizer = (lower bound + upper bound) / 2
*xmin = (lower_bound + upper_bound)/2;
fxmin = intra_value(*xmin, row_index, ...);
return - fxmin; }       

在计算(从预编译网格中选择一个网格点(row_index((方面,优化功能(intra_value(非常复杂,然后涉及大量的数值集成等(。

看起来您正在使用OpenMP,因此我怀疑差异在OpenMP实现中,而不仅仅是优化代码的质量。

Intel的OpenMP运行时众所周知,GCC很好,但不是很好。

OpenMP程序具有非常不同的性能特征,它们不仅取决于编译器可以如何优化循环或内联函数调用。OpenMP运行时的实现非常重要,并且在Windows和GNU/Linux之间大不相同。

请注意,"快速记忆"打破了某些语言规则以获取快速代码,并在某些情况下可能会产生不正确的结果。

还请注意,-O3不是保证-O2或其他任何优化级别(取决于您的代码( - 您应该测试多个版本。

您可能还需要启用-Wl,-O1-链接器也可以进行一些优化。

您可能还想尝试使用LTO建造(链接时间优化( - 通常可以取得重大改进。

我意识到这并没有回答您的问题。但这应该给您一些可以玩的东西: - (

此外,海湾合作委员会的进步很快。如果您尚未使用7.1,则可能需要尝试较新的版本。还;尝试clang以获取第三个数据点。此外,您 can (如果需要(在Linux上使用ICC。