G++:优化 -march=haswell 和更新的变化数值结果
g++: optimization -march=haswell and newer changes numerical result
我一直在努力优化性能,当然也做回归测试,当我注意到 g++ 似乎会根据所选的优化改变结果时。到目前为止,我认为无论选择哪种架构,-O2 -march=[whatever]
都应该为数值计算产生完全相同的结果。然而,对于 g++ 来说,情况似乎并非如此。虽然使用旧架构到 ivybridge 会产生与 clang 对任何架构相同的结果,但我对 gcc 的 haswell 和更新得到不同的结果。这是 gcc 中的错误还是我对优化误解了某些内容?我真的很吃惊,因为叮当似乎没有表现出这种行为。
请注意,我很清楚差异在机器精度范围内,但它们仍然干扰我的简单回归检查。
下面是一些示例代码:
#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 位,在英特尔 Skylake 处理器上执行。
这是因为 GCC 默认使用融合-乘-加 (fma( 指令(如果可用(。相反,Clang 默认不使用它们,即使它可用。
无论是否使用 fma,a*b+c
的结果都可能不同,这就是为什么当您使用-march=haswell
时,您会得到不同的结果(Haswell 是第一个支持 fma 的英特尔 CPU(。
您可以决定是否要将此功能与-ffp-contract=XXX
一起使用。
-ffp-contract=off
,您不会得到FMA指令。-ffp-contract=on
,你会得到FMA指令,但只有在语言标准允许的情况下才会收缩。在当前版本的 GCC 中,这意味着关闭(因为它尚未实现(。-ffp-contract=fast
(这是 GCC 默认值(,您将获得 fma 入侵。
相关文章:
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- valgrind-hellgrind与泄漏检查的结果不同
- 用C++20 fmt限制结果的总大小
- 如何返回一个类的两个对象相加的结果
- C++取消引用指针.为什么会发生变化
- 为什么在读取文件大小时文件IO速度会发生变化
- 使用QProcess执行命令,并将结果存储在QStringList中
- 如果我std::dynamic_pointer_cast并且底层dynamic_cast的结果为null,那么返回的sh
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 序列化,没有库的整数,得到奇怪的结果
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 在更改for循环的第三部分后,未使用for循环结果
- 使用++运算符会导致意外的结果
- 为什么cudaMemGetInfo报告设备内存总量的变化
- 为什么在逗号分隔符上下文中将预增量的结果强制转换为void
- G++:优化 -march=haswell 和更新的变化数值结果
- 声明双重给它一个值0,但打印结果意外变化
- 整数变量与整数字面变化的乘法结果
- 当变量的顺序发生变化时C++双倍乘法会产生不同的结果
- OpenCV 3.1 + tesseract 3.04的OCR(文本识别)结果根据识别的顺序而变化