【发布时间】:2018-01-03 07:57:23
【问题描述】:
当我注意到 g++ 似乎会根据选择的优化改变结果时,我一直致力于优化性能,当然还进行了回归测试。到目前为止,我认为-O2 -march=[whatever] 应该为数值计算产生完全相同的结果,无论选择什么架构。然而,这似乎不是 g++ 的情况。虽然使用一直到 ivybridge 的旧架构产生的结果与 clang 对任何架构的结果相同,但对于 haswell 和更新的 gcc,我得到不同的结果。这是 gcc 中的错误还是我误解了一些关于优化的问题?我真的很吃惊,因为 clang 似乎没有表现出这种行为。
请注意,我很清楚这些差异在机器精度范围内,但它们仍然干扰了我的简单回归检查。
下面是一些示例代码:
#include <iostream>
#include <armadillo>
int main(){
arma::arma_rng::set_seed(3);
arma::sp_cx_mat A = arma::sprandn<arma::sp_cx_mat>(20,20, 0.1);
arma::sp_cx_mat B = A + A.t();
arma::cx_vec eig;
arma::eigs_gen(eig, B, 1, "lm", 0.001);
std::cout << "eigenvalue: " << eig << std::endl;
}
编译使用:
g++ -march=[architecture] -std=c++14 -O2 -o test example.cpp -larmadillo
gcc 版本:6.2.1
clang 版本:3.8.0
针对 64 位编译,在 Intel Skylake 处理器上执行。
【问题讨论】:
-
你编译的是 32 位还是 64 位?
-
我记得使用英特尔编译器时遇到过这样的问题,这在 Haswell 上也给出了不同的结果。在我从事的项目中,英特尔的某个人给了我们一大堆编译器标志,基本上是为了不使用编译器提供的完整优化。我不知道标志了,但我记得它是在-O3。请注意,英特尔编译器(通常)使用与 GCC 编译器相同的标志。
-
我之前听说过与 Intel 编译器的不同之处,并且有充分的理由避免使用 -O3。令我惊讶的是 gcc 给出的结果与 gcc 不同...尤其是 gcc -march=core2,sandybridge,ivybridge 给出的结果与 clang -march=core2,sandybridge,ivybridge,haswell,broadwell 相同。
-
我认为这是由于 fused-multiply-add 指令而发生的。如果你使用
-mno-fused-add,你能重现这些差异吗? -
@geza:你是对的。如果我使用
-mno-fused-madd,我会消除差异(但会收到弃用警告;-))。那么这是否意味着 clang 不使用 fused-multiply-add,即使我使用-O3和-march=haswell?在任何情况下,我都没有在我的项目中观察到 fused-multiply-add 带来的任何实际速度提升。
标签: c++ g++ compiler-optimization gcc6