首先写了一个InvSqrt(x)(求x^-(1/2)),
测试结果无误后复制了其代码,在末尾加上"结果*x"再返回,封装为fsqrt(x)函数
灵异现象出现了:fsqrt(x)跑得比InvSqrt(x)还快!这是为什么?
#ifndef sqrt_h
#define sqrt_h 1
__fastcall float fsqrt(float s);
__fastcall float InvSqrt(float s);
asm(
"fsqrt:;"
"movd %xmm0,%eax;"
"mov %eax,%edx;"
"not %eax;"
"add $0xbe6f02e3,%eax;"//or maby 0xbe6f02e2
"shr %eax;"
"movd %eax,%xmm0;"//guessnum
"add $0x7f800000,%edx;"
"movd %edx,%xmm2;"//-s/2
"mov $0x3fc00000,%eax;"
"movd %eax,%xmm3;"//1.5
"movss %xmm0,%xmm1;"
"mulss %xmm0,%xmm0;"
"mulss %xmm2,%xmm0;"
"addss %xmm3,%xmm0;"
"mulss %xmm1,%xmm0;"
"movss %xmm0,%xmm1;"
"mulss %xmm0,%xmm0;"
"mulss %xmm2,%xmm0;"
"addss %xmm3,%xmm0;"
"mulss %xmm1,%xmm0;"
"movss %xmm0,%xmm1;"
"mulss %xmm0,%xmm0;"
"mulss %xmm2,%xmm0;"
"addss %xmm3,%xmm0;"
"mulss %xmm1,%xmm0;"
"add $0x80800000,%edx;"
"movd %edx,%xmm1;"
"mulss %xmm1,%xmm0;"
"ret;"
);
asm(
"InvSqrt:"
"movd %xmm0,%eax;"
"mov %eax,%edx;"
"not %eax;"
"add $0xbe6f02e3,%eax;"//or maby 0xbe6f02e2
"shr %eax;"
"movd %eax,%xmm0;"//guessnum
"add $0x7f800000,%edx;"
"movd %edx,%xmm2;"//-s/2
"mov $0x3fc00000,%eax;"
"movd %eax,%xmm3;"//1.5
"movss %xmm0,%xmm1;"
"mulss %xmm0,%xmm0;"
"mulss %xmm2,%xmm0;"
"addss %xmm3,%xmm0;"
"mulss %xmm1,%xmm0;"
"movss %xmm0,%xmm1;"
"mulss %xmm0,%xmm0;"
"mulss %xmm2,%xmm0;"
"addss %xmm3,%xmm0;"
"mulss %xmm1,%xmm0;"
"movss %xmm0,%xmm1;"
"mulss %xmm0,%xmm0;"
"mulss %xmm2,%xmm0;"
"addss %xmm3,%xmm0;"
"mulss %xmm1,%xmm0;"
"ret;"
);
#endif
#include <stdio.h>
#include <time.h>
#include <conio.h>
#include <math.h>
#include "sqrt.h"
int main()
{
register int a,n=100000000;
int t;
again:
//下面的部分进行速度测试
printf("speed tests:\n");
t=clock();
for(a=0;a<n;++a) InvSqrt(a);
printf("%lf\n",(double)(clock()-t)/CLOCKS_PER_SEC);
t=clock();
for(a=0;a<n;++a) fsqrt(a);
printf("%lf\n",(double)(clock()-t)/CLOCKS_PER_SEC);
t=clock();
for(a=0;a<n;++a) sqrtf(a);
printf("%lf\n",(double)(clock()-t)/CLOCKS_PER_SEC);
t=clock();
for(a=0;a<n;++a) sqrt(a);
printf("%lf\n",(double)(clock()-t)/CLOCKS_PER_SEC);
t=clock();
for(a=0;a<n;++a) sqrtl(a);
printf("%lf\n",(double)(clock()-t)/CLOCKS_PER_SEC);
system("pause");
goto again;//再测试一遍
return 0;
}
CPU: Intel(R) Pentium(R) CPU G630 @2.7GHz
GPU: Intel(R) HD Graphics
用的是Dev-C++
系统是WIN10
speed tests:
1.390000
0.902000
1.418000
1.520000
1.761000
请按任意键继续. . .
speed tests:
1.154000
0.975000
1.168000
1.092000
1.720000
请按任意键继续. . .
speed tests:
1.156000
0.909000
1.188000
1.233000
1.641000
请按任意键继续. . .
speed tests:
1.221000
0.877000
1.135000
1.221000
1.653000
请按任意键继续. . .
就是这样,无论测试多少遍都是fsqrt比InvSqrt快!
我有试过,交换两个汇编代码块的位置,交换两个测试代码的位置,也都是fsqrt比InvSqrt快。
为什么呢?
还有我发现如果把fsqrt最末尾的两个xmm1改为xmm2,速度会降很多。
为什么呢?
以及,这个代码好像只能用64位编译器(TDM-GCC 4.9.2 64-bit Release/Debug/Profiling)编译,我这里面的其他编译器都不会通过。
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!