C 快速平方根优化?

C 快速平方根优化?,c,optimization,C,Optimization,如果您查看这个非常好的页面: 您将看到以下程序: #define SQRT_MAGIC_F 0x5f3759df float sqrt2(const float x) { const float xhalf = 0.5f*x; union // get bits for floating value { float x; int i; } u; u.x = x; u.i = SQRT_MAGIC_F - (u.i >> 1); //

如果您查看这个非常好的页面:

您将看到以下程序:

#define SQRT_MAGIC_F 0x5f3759df 
 float  sqrt2(const float x)
{
  const float xhalf = 0.5f*x;

  union // get bits for floating value
  {
    float x;
    int i;
  } u;
  u.x = x;
  u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0
  return x*u.x*(1.5f - xhalf*u.x*u.x);// Newton step, repeating increases accuracy 
}
我的问题是:有没有什么特别的原因使它不能实现为:

#define SQRT_MAGIC_F 0x5f3759df 
 float  sqrt2(const float x)
{

  union // get bits for floating value
  {
    float x;
    int i;
  } u;
  u.x = x;
  u.i = SQRT_MAGIC_F - (u.i >> 1);  // gives initial guess y0

  const float xux = x*u.x;

  return xux*(1.5f - .5f*xux*u.x);// Newton step, repeating increases accuracy 
}

从反汇编中,我看到一个
MUL
更少。出现
xhalf
有什么目的吗?

可能是使用80位寄存器的传统浮点数学,当乘法器在最后一行链接在一起作为中间结果保存在80位寄存器中时,会更精确

上面实现中的第一次乘法与后面的整数运算并行进行,它们使用不同的执行资源。 另一方面,第二个函数看起来更快,但很难判断是否真的是因为上述原因。 此外,常量浮点xux=x*u.x语句将结果还原为32位浮点,这可能会降低总体精度


您可以直接测试这些函数,并将它们与math.h中的sqrt函数进行比较(使用double not float)。通过这种方式,您可以看到哪个更快,哪个更准确。

您是否启用了编译器优化,以及您是否对两个版本进行了基准测试?事实上,这是一种非常古老的技术,在Quake等人的时代,它在旧的x86 CPU上运行良好,但现在只在缺少快速sqrt(或sqrt估计)指令的CPU上真正有用,例如嵌入式微控制器。很好-今天我第一次对某些事情做出正确的判断。;-)我猜他是按照评论的思路进行实验的:重复牛顿步骤,这只是他的一步版本。通过多个步骤,它会有某种意义。但我同意优化器会找到机会以任何方式获得相同的结果。@PascalCuoq:第一个代码序列具有子表达式
xhalf*u.x
,而第二个代码序列具有
.5f*xux
。在这些函数中展开
xhalf
xux
将得到
(.5f*x)*u.x
.5f*(x*u.x)
。如果我们不希望编译器知道关于
u.x
的值的任何信息,它就无法确定这些值是否相等。如果
x
FLT\u MAX
u.x
是两个,那么
(.5*x)*u.x
将是
FLT\u MAX
.5f*(x*u.x)
将是无穷大。