• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

kaikai向前走

转职任务完成。崭新fn诞生
  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

卡马克的求平方根函数代码的陷阱

 首先感谢xq; lj定位问题!

 问题出在我签入的来自卡马克的求平方根函数代码。

Code
double InvSqrt(double number)
{
      __int64 i;
      
double x2, y;
      
const double threehalfs = 1.5F;
    
      x2
= number * 0.5F;
      y
= number;
      
i = *(__int64 *)&y;
      i
= 0x5fe6ec85e7de30da - (i >> 1);
      
y = *( double *)&i;
      y
= y * (threehalfs - (x2 * y * y)); //1st iteration
      y = y * (threehalfs - (x2 * y * y)); //2nd iteration, this can be removed
      return y;
}

红色部分代码在gcc开启-fstrict-aliasing选项后将得到错误的代码。由于使用了type-punned pointer将打破strict-aliasing规则。

由于-fstrict-aliasing选项在-O2, -O3, -Os等优化模式下都将开启(目前dev不带优化,main带-O3所以该问题只在main上出现)所以建议对linux编译中产生
warning: dereferencing type-punned pointer will break strict-aliasing rule
警告的情况作为编译失败。以便防止出现类似问题。
上述代码应当使用联合体重写为:

Code
double InvSqrt(double number)
{
      
double x2, y;
      
const double threehalfs = 1.5F;
      union
      {
            
double d;
            __int64 i;
      }d;
      x2
= number * 0.5F;
      y =
number;
      d.d =  y;
      d.i = 0x5fe6ec85e7de30da - (d.i >> 1);
      y = d.d;
      y
= y * (threehalfs - (x2 * y * y)); //1st iteration
      y = y * (threehalfs - (x2 * y * y)); //2nd iteration, this can be removed
      return y;
}

这样就不会打破该规则。

什么是
Strict Aliasing?请看:http://www.cellperformance.com/mike_acton/2006/06/understanding_strict_aliasing.html?

In C99, it is illegal to create an alias of a different type than the original.

在我们现在的代码中可以按正则表达式\([^()]+\*:b*\):b*&找到约180个匹配行,涉及60个文件。
这其中应该有一些是不符合这个strict-aliasing要求的。
处理方法
1是临时关闭strict-aliasing选项:在使用-O2, -O3, -Os编译的情况下使用-fno-strict-aliasing关闭strict-aliasing
2是要修改这类不满足该限制的代码,在完全修改完毕之后再打开。
要注意到,strict-aliasing选项提示编译器代码满足这个限制,所以可以提供编译器进行额外的代码优化的机会。

posted on 2009-07-23 14:19  kaikai  阅读(1109)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3