求高效的基础运算库~~~
本人新手,请问VC++下有没有比math.h库更加高效的基础运算库,或者对pow、log、sin、cos、sqrt等函数的优化方法~~(只考虑一般情况即可,不需要考虑大数及高精度),请各位高手赐教!!!万分感谢!!! 这些数学函数的实现是通过CPU/FPU指令实现的,已经非常快了,应该能够满足绝大多数需要,而楼主似乎对其性能不满意却又提到不考虑高精度和大数,这就让人搞不懂了。个人认为就double精度而言,这些函数很难有实质的改进了,任何算法的实现都应该快不过CPU指令。 弱弱问一句,哪里能看到math.c? 2# liangbch刚才写了一个程序,对VC6中的数学函数的性能进行了测试。结果如下,我的CPU是Intel E8500, CPU频率是3.16GH
sqrt() 花费时间约4.3 CPU 周期
sin() 花费时间约13 CPU周期
log() 花费时间约10 CPU周期 这里贴出所有的代码,注意,需要修改 CPU_FREQ的定义,使得它的值和你的CPU一致。
编译环境为VC6.0
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <windows.h>
#definePI 3.1415926535897932384626433832795
#defineDATA_COUNT 1000
#defineCPU_FREQ(3.16e9)//CPU frequency, need always change this definition for match your CPU
typedef double ( *lpfn_math )(double);
unsigned __int64 s_u64Frequency = 1;
unsigned __int64 s_u64Start, s_u64End;
double data;
double result;
void testFun( const lpfn_math pFun,
const char* lpszFunName,
const inttestTimes )
{
int i,j;
double t;
double ns;
QueryPerformanceFrequency((LARGE_INTEGER *)&s_u64Frequency );
printf( "\nTest function: %s() %u times\n",
lpszFunName, testTimes*DATA_COUNT );
QueryPerformanceCounter((LARGE_INTEGER *)&s_u64Start );
for (i=0;i<testTimes;i++)
{
for (j=0;j<DATA_COUNT;j++)
{
result=pFun(data);
}
}
QueryPerformanceCounter((LARGE_INTEGER *)&s_u64End );
t = (double)(( s_u64End - s_u64Start ) / (double) s_u64Frequency );
printf( "Elapsed time: %d ms\n", (int)(t*1000));
ns=(t * 1e9) /(double)(DATA_COUNT *testTimes); //calc the time of one sqrt function call in nanosecond
printf("%s() spend %f ns\n", lpszFunName,ns );
printf("%s() spend %f cpu cycle\n", lpszFunName, (ns*1e9)/CPU_FREQ);
}
void test_sqrt()
{
int c,n1,n2;
c=0;
while (c<DATA_COUNT)
{
n1=rand();
n2=rand();
if (n1!=0 && n2!=0)
{
data=double(n1) / double(n2);
c++;
}
}
testFun( sqrt,"sqrt",1000);
}
void test_sine()
{
int c,n;
c=0;
while (c<DATA_COUNT)
{
n=(rand() % 1000)+1;
data=double(n) / 1000.00 * PI * 0.5;//data is i/1000*PI/2, i=1..1000
c++;
}
testFun(sin,"sin",1000);
}
void test_log()
{
int c,n1,n2;
c=0;
while (c<DATA_COUNT)
{
n1=(rand() % 1000)+1;
n2=rand() % 1000;
data=double(n1) + double(n2) * 0.001;//data[ i ] always between 1.000 to 1000.999
c++;
}
testFun( log,"log",1000);
}
int main(int argc, char* argv[])
{
test_sqrt();
test_sine();
test_log();
return 0;
}
2# liangbch
刚才写了一个程序,对VC6中的数学函数的性能进行了测试。结果如下,我的CPU是Intel E8500, CPU频率是3.16GH
sqrt() 花费时间约4.3 CPU 周期
sin() 花费时间约13 CPU周期
log() 花费时间约10 CPU周 ...
liangbch 发表于 2012-2-13 13:35 http://bbs.emath.ac.cn/images/common/back.gif
感觉比我想象的快多了,我原本以为它们都得耗上百余个指令周期呢。 很不幸,VC6中没有数学函数的源代码,即使在安装了VC是选择 VC++ Runtime Libraries ->CRT Source Code 也是如此。我能够在调试时进入其他库函数的源文件,如memset,但是不能进入数学函数所在的源文件。搜索CRT源码目录,仅仅找到2个导入库的定义文件,见下。
C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\Intel\_SAMPLD_.DEF
C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\Intel\_SAMPLE_.DEF 查看了一下,msvcrt.dll和 相关的LIBC.LIB 库,以上函数还是对fsqrt , fsin ,fcos 的封装。
不知是否还有用到其它库函数。_sqrt:
var_4 = word ptr -4
arg_0 = dword ptr4
arg_4 = dword ptr8
lea edx,
call __fload_withFB
loc_77C1D52D:
push edx
fstcw
mov eax,
jz short loc_77C1D589
cmp , 27Fh
jz short loc_77C1D545
call __load_CW
loc_77C1D545:
test eax, 80000000h
jnz short loc_77C1D56B
fsqrt
....
;=======================================
__fload_withFB:
var_A = tbyte ptr -0Ah
mov eax,
and eax, 7FF00000h
cmp eax, 7FF00000h
jz short loc_77C20C37
fld qword ptr
retn
; --------------------------------
loc_77C20C37:
mov eax,
sub esp, 0Ah
or eax, 7FFF0000h
mov dword ptr , eax
mov eax,
mov ecx,
shld eax, ecx, 0Bh
shl ecx, 0Bh
mov , eax
mov dword ptr , ecx
fld
add esp, 0Ah
test eax, 0
mov eax,
retn
__fload_withFB endp 关于求浮点数(单精度和双精度)的平方根,下面的文章值得一看,它利用IEEE754浮点数的格式,直接求出一个比较好的初值,然后使用牛顿迭代求精。
http://ilab.usc.edu/wiki/index.php/Fast_Square_Root 在 Android 源码目录的 bionic/libm/src路径下找到 平方根的实现e_sqrt.c:
感兴趣的可以看看:
页:
[1]
2