c语言快速开平方常数的不完全优化报告
原始程序采用C1=0x5f3759df,本文采用C2=0x5f352267,
在对1-256之内的小数进行开平方时,测试报告如下:
程序外循环10000次*内循环256次、人工执行exe程序60次的结果:
C1=0x5f3759df19.48333333 ms
C2=0x5f35226719.28333333 ms
normal_c_sqrtf20.43333333 ms
分别一次牛顿迭代,相对c语言sqrtf计算结果的精度:
C1=0x5f3759df1.00098
C2=0x5f3522671.00073
在测试范围内,C2速度及精度略优。
值得说明的是,对于更大的数的开平方运算是否更优,尚需要进一步设置测试程序验证。
总体来说快速开平方时间上基本上无差别,相比c语言自身提供的函数,速度约提高5%左右,不知道c语言函数是否已经采用了快速开平方的运算方法,还没有仔细地去查看。
参考代码如下:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <windows.h>
float Q_rsqrt(float x)
{
long i;
float xhalf;
xhalf=x*0.5f;
i=*(long *)&x;
i=0x5f3759df-(i>>1); //原始常数
x=*(float *)&i;
x=x*(1.5f-(xhalf*x*x));
//x=x*(1.5f-(xhalf*x*x));
return 1.0f/x;
}
float Q_rsqrt_fast(float x)
{
long i;
float xhalf,y;
xhalf=x*0.5f;
i=*(long *)&x;
i=0x5f352267 -(i>>1); //本文常数
x=*(float *)&i;
x=x*(1.5f-(xhalf*x*x));
//x=x*(1.5f-(xhalf*x*x));
return 1.0f/x;
}
int main(int argc,char *argv[])
{
float ary0[300];
float ary1[300];
float ary2[300];
SYSTEMTIME t0;
GetSystemTime(&t0);
for(int j=0;j<10000;j++)
{
for(int i=1;i<=256;i++)
{
ary0[i-1]=Q_rsqrt(i+0.5);
}
}
SYSTEMTIME t1;
GetSystemTime(&t1);
for(int j=0;j<10000;j++)
{
for(int i=1;i<=256;i++)
{
ary1[i-1]=Q_rsqrt_fast(i+0.5);
}
}
SYSTEMTIME t2;
GetSystemTime(&t2);
for(int j=0;j<10000;j++)
{
for(int i=1;i<=256;i++)
{
ary2[i-1]=sqrtf(i+0.5);
}
}
SYSTEMTIME t3;
GetSystemTime(&t3);
printf("C1=0x5f3759df time1=%u C2=0x5f352267 time2=%u normalsqrtf time3=%u\n", t1.wSecond*1000+t1.wMilliseconds-t0.wMilliseconds-t0.wSecond*1000,
t2.wSecond*1000+t2.wMilliseconds-t1.wMilliseconds-t1.wSecond*1000,t3.wSecond*1000+t3.wMilliseconds-t2.wMilliseconds-t2.wSecond*1000);
float f1=0,f2=0;
for(int i=0;i<256;i++)
{
f1+=ary0[i]/ary2[i];
f2+=ary1[i]/ary2[i];
}
printf("C1=0x5f3759df p1=%.5f C2=0x5f352267 p2=%.5f\n", f1/256.0,f2/256.0);
return 0;
}
本文暂时没有评论,来添加一个吧(●'◡'●)