Mik*_*ley 7 c++ floating-point optimization ieee-754
我目前正在阅读优秀的双双和四双算术库,在前几行我注意到他们通过以下方式执行求和:
std::pair<double, double> TwoSum(double a, double b)
{
double s = a + b;
double v = s - a;
double e = (a - (s - v)) + (b - v);
return std::make_pair(s, e);
}
Run Code Online (Sandbox Code Playgroud)
误差的计算e依赖于计算遵循该操作顺序的事实,因为IEEE-754浮点数学的非关联属性.
如果我在现代优化C++编译器(例如MSVC或gcc)中编译它,我可以确保编译器不会优化计算的方式吗?
其次,这在C++标准中是否可以保证?
是的,这是安全的(至少在这种情况下)。您在那里只使用两个“运算符”,主表达式(something)和二进制something +/- something(加法)。
部分1.9 Program execution(C++0x N3092)指出:
只有在运算符真正是结合的或可交换的时,才可以根据通常的数学规则重新组合运算符。
在分组方面,5.1 Primary expressions指出:
带括号的表达式是一个主要表达式,其类型和值与封闭表达式的类型和值相同。... 括号中的表达式可以在与可以使用封闭表达式的上下文完全相同的上下文中使用,并且具有相同的含义,除非另有说明。
我相信在该引用中使用“相同”一词需要一个一致的实现来保证它将以指定的顺序执行,除非另一个订单可以给出完全相同的结果。
对于加法和减法,部分5.7 Additive operators有:
加法运算符 + 和 - 从左到右分组。
所以标准决定了结果。如果编译器可以确定使用不同的操作顺序可以获得相同的结果,那么它可能会重新排列它们。但是,无论这种情况发生与否,您都无法辨别出差异。
您可以查看g ++手册页:http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Optimize-Options.html#Optimize-Options
特别是-fassociative-math,-ffast-math和-ffloat-store
根据g ++手册,除非您特别要求,否则它不会重新排序您的表达式.
这是一个非常有效的问题,因为英特尔的C++编译器(使用非常广泛)默认执行可以改变结果的优化.