我使用Kahan求和算法:
inline void KahanSum(float value, float & sum, float & correction)
{
float term = value - correction;
float temp = sum + term;
correction = (temp - sum) - term;
sum = temp;
}
float KahanSum(const float * ptr, size_t size)
{
float sum = 0, correction = 0;
for(size_t i = 0; i < size; ++i)
KahanSum(ptr[i], sum, correction);
return sum;
}
如果使用MSVS编译它可以正常工作,但是当我使用GCC时它有很大的计算错误。
麻烦在哪里?
答案 0 :(得分:2)
我认为,这是积极的编译器优化的结果。所以GCC可以减少表达式:
float term = value - correction;
float temp = sum + term;
correction = (temp - sum) - term;
sum = temp;
到
float term = value - correction;
correction = 0;
sum += term;
因为这种转换在数学上是正确的,但是这种优化会杀死Kahan算法。
为了避免这个问题,您可以使用&#34; -O1&#34; GCC编译器选项来编译代码。 它将是这样的:
#if defined(__GNUC__)
# pragma GCC push_options
# pragma GCC optimize ("O1")
#endif
inline void KahanSum(float value, float & sum, float & correction)
{
float term = value - correction;
float temp = sum + term;
correction = (temp - sum) - term;
sum = temp;
}
float KahanSum(const float * ptr, size_t size)
{
float sum = 0, correction = 0;
for(size_t i = 0; i < size; ++i)
KahanSum(ptr[i], sum, correction);
return sum;
}
#if defined(__GNUC__)
# pragma GCC pop_options
#endif