4

当我注意到 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

铿锵版本:3.8.0

编译为 64 位,在 Intel Skylake 处理器上执行。

4

1 回答 1

8

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

无论是否使用 fma,结果a*b+c都会有所不同-march=haswell,这就是为什么您在使用时会得到不同的结果(Haswell 是第一个支持 fma 的 Intel CPU)。

您可以决定是否要将此功能与-ffp-contract=XXX.

  • -ffp-contract=off,你不会得到 fma 指令。
  • -ffp-contract=on,你会得到 fma 指令,但只有在语言标准允许的情况下才会出现收缩。在当前版本的 GCC 中,这意味着关闭(因为它还没有实现)。
  • -ffp-contract=fast(这是 GCC 的默认设置),你会得到 fma 指令。
于 2017-07-27T17:20:36.013 回答