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)
将是无穷大。