菜菜博士

欢迎来到 菜菜博士 在网络的家



一个Sqrt函数再次引发的血案


读 http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html 后感

这些神人啊,开平方居然有这么快的算法!!!
于是我决定看看 glibc 是怎么实现的!
如果 glibc 比较慢,我一定要改成神人的算法重新编译 glibc !!!

等等!先写一个程序测试两种算法的速度


#include <math.h>

float magic_sqrt(float number)
{
    long i;
    float x, y;
    const float f = 1.5F;

    x = number * 0.5F;
    y  = number;
    i  = * ( long *)    & y  ;
    i  = 0x5f3759df - ( i >>  1 wink.gif     ;
    y  = * ( float * wink.gif    & i  ;
    y  = y * ( f - ( x * y * y wink.gif wink.gif ;
    y  = y * ( f - ( x * y * y wink.gif wink.gif ;
    return number * y;
}
#define TIMES 2000000000
int main(int argc, char argv[0])
{
        unsigned int i;
   if(argv[1]=='s')
   {
     for(i=0;i < TIMES; i++)
     {
           sqrt(200.0);
     }
   }else
   {
     for(i=0;i < TIMES; i++)
     {
           magic_sqrt(200.0);
     }
   }
   return 0;
}


然后用 time ./a.out s 和 time ./a.out m 来测验两个开发算法的速度。
哥震惊了!!! 一样快!!!莫非 glibc 也使用了神一样的 ... ?????

于是经过漫长时间的下载, 解压 , grep 之后,我终于找到了我要的 glibc 中实现开方算法的文件

sysdeps/x86_64/fpu/e_sqrt.c

哥再次震惊了!哥再次吐血了!!!

居...居...居居然 ..... 只有一条指令

double
__ieee754_sqrt (double x)
{
  double res;

  asm ("sqrtsd %0, %1" : "=x" (res) : "x" (x));

  return res;
}


看来以后我可以放心的使用 glibc 的数学函数了 ... 事实证明, glibc 总是使用的最快的方法。
4 条评论
# 1: December 3, 2010, 9:28 pm, mythmgn said:

glibc是直接用的硬件的实现吧
# 2: December 8, 2010, 9:47 pm, microcai said:

.. SSE 没错
# 3: December 29, 2010, 10:17 pm, wiwor said:

测试了一下,怎么他们的执行时间还是差别很大呢?
我的代码如下:请指教。
#include<stdio.h>
#include<math.h>
#include<time.h>
float magic_sqrt(float number)
{
long i;
float x, y;
const float f = 1.5F;

x = number * 0.5F;
y = number;
i = * ( long *) & y ;
i = 0x5f3759df - ( i >> 1 ) ;
y = * ( float * ) & i ;
y = y * ( f - ( x * y * y )) ;
y = y * ( f - ( x * y * y )) ;
return number * y;
}
#define TIMES 200000000
int main(void)
{
unsigned int i;
clock_t start,finish;
double duran;
start=clock();
for(i=0;i < TIMES; i++)
{
magic_sqrt(200.0);
}
finish=clock();
duran=(double)(finish-start)/CLOCKS_PER_SEC;
printf("%f s\n",duran);
printf("---------\n");
start=clock();
for(i=0;i < TIMES; i++)
{
sqrt(200.0);
}
finish=clock();
duran=(double)(finish-start)/CLOCKS_PER_SEC;
printf("%f s\n",duran);
return 0;
}
www@www-Rev-1-0:~/文档$ gcc '/home/www/文档/mypro/my2.c'
www@www-Rev-1-0:~/文档$ '/home/www/文档/a.out'
3.800000 s
---------
0.640000 s

# 4: January 7, 2011, 3:06 am, microcai said:

用来测试时间的方式不对。
clock 是不够精确的
用 gettimeofday 重新测试试看
添加评论

昵称 *

E-mail