编译器优化:g ++比intel慢
我最近购买了一台双启动电脑,以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 program.cpp -std = c ++ 11 -fopenmp -O3 -ffast-math
根据其他几个主题的建议,我尝试添加/替换其他几个标志,如:-funsafe-math-optimizations,-march = native,-fwhole-program,-Ofast等,只有轻微(或没有)性能增益。
icc真的更快,还是我错过了什么? 我对Linux相当陌生,所以我不知道,也许我忘了正确地安装一些东西(比如驱动程序),或者改变g ++中的某些选项? 我不知道情况是否正常,所以我更愿意问。 特别是因为我更喜欢使用linux来进行理想的编码,所以我宁愿让它达到速度。
编辑:我决定安装最后一个英特尔编译器(英特尔编译器C + + 17,update4)在Linux上进行检查。 我最终得出了减轻的结果:它不比gcc做得更好(事实上甚至更糟糕)。 我运行交叉比较linux / windows - icc / gcc - 并行与否,使用前面提到的标志(做直接比较),这里是我的结果(以ms为单位运行1次迭代的时间):
平滑循环,不平行化:
gcc = 122074; icc = 68799
gcc = _91042; icc = 92102
并行版本:
gcc = 27457; icc = 19800
gcc = 27000; icc = 30000
总结一下:这有点混乱。 在Linux上,gcc似乎总是比icc快,尤其是在涉及到并行时(我运行它以获得更长的程序,差异远高于此处的)。
在windows上,情况正好相反,icc明显支配gcc,特别是在没有并行化的情况下(在这种情况下gcc需要很长时间才能编译)。
最快的编译是在Windows上使用并行和icc完成的。 我不明白为什么我不能在linux上复制这个。 有什么我需要做的(Ubuntu的16.04)来帮助加快我的流程?
另一个区别是,在Windows上,我使用旧版的英特尔作曲家( Composer XE 2013 ),并在Linux上使用我昨天安装的最新版本时,调用'ia32'而不是intel64(这是我应该使用的那个)。 而在linux上,Intel Compiler 17文件夹在我的第二个硬盘上(而不是我安装Linux时的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 Compiler 17(update4) - Windows 8.1,英特尔Composer 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函数是一个经典而简单的优化算法(自定义黄金搜索),返回最优值及其参数:
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; }
优化函数(intra_value)在计算方面相当复杂(从预编译的网格中选取网格点(row_index),然后涉及大量的数值积分等)。
看起来您正在使用OpenMP,所以我怀疑它们在OpenMP实现方面有所不同,而不仅仅是优化代码的质量。
英特尔的OpenMP运行时被称为相当高的性能,而GCC很好但不是很好。
OpenMP程序具有非常不同的性能特征,它们不仅取决于编译器如何优化循环或内联函数调用。 OpenMP运行时的实现非常重要,以及线程和同步原语的操作系统实现,这在Windows和GNU / Linux之间是非常不同的。
请注意,“快速数学”会破坏一些语言规则以获得快速代码,并且在某些情况下可能会产生不正确的结果。
另外请注意, -O3
不能保证比-O2
或任何其他优化级别(取决于您的代码)更快 - 您应该测试多个版本。
您可能还想启用-Wl,-O1
- 链接器也可以进行一些优化。
您可能还想尝试使用LTO(链接时间优化)进行构建 - 通常可以产生重大改进。
我意识到这并不能回答你的问题。 但它应该给你一些东西来玩:-)
另外,gcc的改进速度非常快。 如果您尚未安装7.1,则可能需要尝试更新的版本。 也; 尝试Clang获取第三个数据点。 另外,如果你愿意,你可以在Linux上使用icc。
链接地址: http://www.djcxy.com/p/287.html