g ++:optimization -march = haswell和更新更改数值结果

时间:2017-07-27 14:10:29

标签: c++ g++ compiler-optimization gcc6

当我注意到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处理器上执行。

1 个答案:

答案 0 :(得分:5)

这是因为GCC默认使用fusion-multiply-add(fma)指令(如果可用)。相反,Clang默认情况下不会使用它们,即使它可用。

来自a*b+c differ的结果是否使用了fma,这是您使用-march=haswell时获得不同结果的原因(Haswell是第一个支持的英特尔CPU) FMA)。

您可以决定是否要将此功能与-ffp-contract=XXX一起使用。

  • -ffp-contract=off,您无法获得fma说明。
  • -ffp-contract=on,您可以获得fma说明,但仅限于语言标准允许的收缩情况。在当前版本的GCC中,这意味着关闭(因为它尚未实现)。
  • -ffp-contract=fast(这是GCC的默认设置),您将获得fma指示。