【发布时间】:2017-11-06 07:07:00
【问题描述】:
我最近购买了一台具有双启动 C++ 代码的计算机。在 Windows 上,我在 Linux 上使用英特尔 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 来进行理想的编码,所以我宁愿让它跟上速度。
编辑:我决定在 linux 上安装最后一个 intel 编译器(Intel Compiler C++ 17,update4)来检查。我最终得到了缓解的结果:它并不比 gcc 做得更好(实际上更糟)。 我运行了交叉比较 linux/windows - icc/gcc - 是否并行化,使用前面提到的标志(进行直接比较),这是我的结果(time 运行 1 次迭代测量毫秒):
-
普通循环,没有并行化:
- 视窗:
gcc = 122074 ; icc = 68799 - Linux:
gcc = _91042 ; icc = 92102
- 视窗:
-
并行化版本:
- 视窗:
gcc = 27457 ; icc = 19800 - Linux:
gcc = 27000 ; icc = 30000
- 视窗:
总结一下:有点乱。
在 linux 上,gcc 似乎总是比 icc 快,尤其是在涉及并行化时(我为更长的程序运行它,差异比这里的要高得多)。
在 Windows 上,情况正好相反,icc 明显优于 gcc,尤其是在没有并行化的情况下(在这种情况下 gcc 需要很长时间才能编译)。
最快的编译是在 windows 上使用并行化和 icc 完成的。我不明白为什么我不能在 linux 上复制它。我需要做些什么(ubuntu 16.04)来帮助加快我的流程吗?
另一个区别是,在 Windows 上,我使用较旧的英特尔作曲家 (Composer XE 2013) 并调用 'ia32' 而不是 intel64(即我应该使用的那个)在Linux上我使用我昨天安装的最后一个版本。在 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 编译器 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),然后涉及大量的数值积分等)。
【问题讨论】:
-
您可能想尝试在 Windows 上的 GCC 中编译您的代码。你可以使用mingw-w64。
-
“使用 g++ 编译大约慢 2 倍” 我假设您的意思是编译的程序更慢,而不是编译更慢。说编译较慢意味着编译代码需要更长的时间,但我认为这不是你在说的
-
你在 Intel CPU 上运行它吗?如果没有记错的话,ICC 可以为英特尔处理器提供更好的优化(与它自己相比),并且可能比其他编译器更快(由于他们自己知道如何以最佳方式利用其 CPU 指令)。
-
您是否尝试使用
-fprofile-generatethen-fprofile-use进行配置文件引导优化?你也应该试试-march=native -
如果您愿意发布两个编译器的源代码和程序集转储,这将有所帮助。
标签: c++ performance g++ intel compiler-optimization