Kahan求和算法在GCC编译时有很大的计算错误 [英] Kahan summation algorithm has big computing error when it is compiled by GCC

查看:282
本文介绍了Kahan求和算法在GCC编译时有很大的计算错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Kahan求和算法:

  inline void KahanSum(float value,float& sum,float& 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);
回报金额;
}

如果使用MSVS进行编译,它可以正常工作,但它有一个我使用GCC时出现大的计算错误。



麻烦在哪里?

解决方案

这是编译器优化的结果。因此GCC可以减少表达式:

  float term = value  -  correction; 
float temp = sum + term;
correction =(temp - sum) - term;
sum = temp;

 浮动期=价值 - 修正; 
校正= 0;
sum + = term;

因为这个转换在数学上是正确的,但是这个优化杀死了Kahan算法。



为了避免此问题,您可以使用-O1GCC编译器选项来编译代码。
它会是这样的:

$ $ p $ #if defined(__ GNUC__)
#pragma GCC push_options
#编译指令GCC优化(O1)
#endif
内嵌void KahanSum(浮点值,浮点数和浮点数和浮点数)
{
浮点数=价值 - 修正;
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);
回报金额;

#if defined(__ GNUC__)
#pragma GCC pop_options
#endif


I use Kahan summation algorithm:

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;
}

It works fine if it is compiled with using of MSVS, but it has a big computing error when I use GCC.

Where is the trouble here?

解决方案

I suppouse, that it's a result of aggresive compiler optimization. So GCC can reduce the expression from:

    float term = value - correction;
    float temp = sum + term;
    correction = (temp - sum) - term;
    sum = temp;

to

    float term = value - correction;
    correction = 0;
    sum += term;

because this transformation is mathematically correct, but this optimization kills Kahan algorithm.

In order to avoid this problem you can use "-O1" GCC compiler options to compile the code. It will be something like this:

#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 

这篇关于Kahan求和算法在GCC编译时有很大的计算错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆