找回密码
 欢迎注册
查看: 15014|回复: 11

[求助] 求高效的基础运算库~~~

[复制链接]
发表于 2012-2-8 20:06:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
本人新手,请问VC++下有没有比math.h库更加高效的基础运算库,或者对pow、log、sin、cos、sqrt等函数的优化方法~~(只考虑一般情况即可,不需要考虑大数及高精度),请各位高手赐教!!!万分感谢!!!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-9 13:46:16 | 显示全部楼层
这些数学函数的实现是通过CPU/FPU指令实现的,已经非常快了,应该能够满足绝大多数需要,而楼主似乎对其性能不满意却又提到不考虑高精度和大数,这就让人搞不懂了。个人认为就double精度而言,这些函数很难有实质的改进了,任何算法的实现都应该快不过CPU指令。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-13 09:53:32 | 显示全部楼层
弱弱问一句,哪里能看到math.c?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-13 13:35:19 | 显示全部楼层
2# liangbch
刚才写了一个程序,对VC6中的数学函数的性能进行了测试。结果如下,我的CPU是Intel E8500, CPU频率是3.16GH
sqrt() 花费时间约4.3 CPU 周期
sin() 花费时间约13 CPU周期
log() 花费时间约10 CPU周期
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-13 13:38:33 | 显示全部楼层
这里贴出所有的代码,注意,需要修改 CPU_FREQ的定义,使得它的值和你的CPU一致。
编译环境为VC6.0

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <windows.h>

  5. #define  PI 3.1415926535897932384626433832795
  6. #define  DATA_COUNT 1000
  7. #define  CPU_FREQ  (3.16e9)  //CPU frequency, need always change this definition for match your CPU

  8. typedef double ( *lpfn_math )(double);

  9. unsigned __int64 s_u64Frequency = 1;
  10. unsigned __int64 s_u64Start, s_u64End;

  11. double data[DATA_COUNT];
  12. double result[DATA_COUNT];

  13. void testFun( const lpfn_math pFun,
  14.                          const char* lpszFunName,
  15.                          const int  testTimes )
  16. {

  17.         int i,j;
  18.         double t;
  19.         double ns;

  20.         QueryPerformanceFrequency((LARGE_INTEGER *)&s_u64Frequency );

  21.         printf( "\nTest function: %s() %u times\n",
  22.                 lpszFunName, testTimes*DATA_COUNT );

  23.         QueryPerformanceCounter((LARGE_INTEGER *)&s_u64Start );
  24.         for (i=0;i<testTimes;i++)
  25.         {
  26.                 for (j=0;j<DATA_COUNT;j++)
  27.                 {
  28.                         result[j]=pFun(data[j]);
  29.                 }
  30.         }
  31.         QueryPerformanceCounter((LARGE_INTEGER *)&s_u64End );

  32.         t = (double)(( s_u64End - s_u64Start ) / (double) s_u64Frequency );
  33.         printf( "Elapsed time: %d ms\n", (int)(t*1000));

  34.         ns=(t * 1e9) /(double)(DATA_COUNT *testTimes); //calc the time of one sqrt function call in nanosecond
  35.         printf("%s() spend %f ns\n", lpszFunName,ns );
  36.         printf("%s() spend %f cpu cycle\n", lpszFunName, (ns*1e9)/CPU_FREQ);
  37. }

  38. void test_sqrt()
  39. {
  40.         int c,n1,n2;
  41.         c=0;
  42.         while (c<DATA_COUNT)
  43.         {
  44.                 n1=rand();
  45.                 n2=rand();
  46.                 if (n1!=0 && n2!=0)
  47.                 {
  48.                         data[c]=double(n1) / double(n2);
  49.                         c++;
  50.                 }
  51.         }
  52.         testFun( sqrt,"sqrt",1000);
  53. }

  54. void test_sine()
  55. {
  56.         int c,n;
  57.         c=0;
  58.         while (c<DATA_COUNT)
  59.         {
  60.                 n=(rand() % 1000)+1;
  61.                 data[c]=double(n) / 1000.00 * PI * 0.5;  //data[c] is i/1000*PI/2, i=1..1000
  62.                 c++;
  63.         }
  64.         testFun(sin,"sin",1000);
  65. }

  66. void test_log()
  67. {
  68.         int c,n1,n2;
  69.         c=0;
  70.         while (c<DATA_COUNT)
  71.         {
  72.                 n1=(rand() % 1000)+1;
  73.                 n2=rand() % 1000;
  74.                 data[c]=double(n1) + double(n2) * 0.001;  //data[ i ] always between 1.000 to 1000.999
  75.                 c++;
  76.         }
  77.         testFun( log,"log",1000);
  78. }

  79. int main(int argc, char* argv[])
  80. {
  81.         test_sqrt();
  82.         test_sine();
  83.         test_log();
  84.         return 0;
  85. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-13 14:19:36 | 显示全部楼层
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


感觉比我想象的快多了,我原本以为它们都得耗上百余个指令周期呢。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-13 14:32:55 | 显示全部楼层
很不幸,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
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-13 16:43:45 | 显示全部楼层
查看了一下,msvcrt.dll  和 相关的LIBC.LIB 库,以上函数还是对fsqrt , fsin ,fcos 的封装。
不知是否还有用到其它库函数。
  1. _sqrt:

  2. var_4                = word ptr -4
  3. arg_0                = dword        ptr  4
  4. arg_4                = dword        ptr  8

  5.                 lea        edx, [esp+arg_0]
  6.                 call        __fload_withFB

  7. loc_77C1D52D:
  8.                 push        edx
  9.                 fstcw        [esp+4+var_4]
  10.                 mov        eax, [esp+4+arg_4]
  11.                 jz        short loc_77C1D589
  12.                 cmp        [esp+4+var_4], 27Fh
  13.                 jz        short loc_77C1D545
  14.                 call        __load_CW

  15. loc_77C1D545:
  16.                 test        eax, 80000000h
  17.                 jnz        short loc_77C1D56B
  18.                 fsqrt
  19.         
  20.         ....

  21. ;=======================================


  22. __fload_withFB:

  23. var_A                = tbyte        ptr -0Ah

  24.                 mov        eax, [edx+4]
  25.                 and        eax, 7FF00000h
  26.                 cmp        eax, 7FF00000h
  27.                 jz        short loc_77C20C37
  28.                 fld        qword ptr [edx]
  29.                 retn
  30. ; --------------------------------

  31. loc_77C20C37:
  32.                 mov        eax, [edx+4]
  33.                 sub        esp, 0Ah
  34.                 or        eax, 7FFF0000h
  35.                 mov        dword ptr [esp+0Ah+var_A+6], eax
  36.                 mov        eax, [edx+4]
  37.                 mov        ecx, [edx]
  38.                 shld        eax, ecx, 0Bh
  39.                 shl        ecx, 0Bh
  40.                 mov        [esp+4], eax
  41.                 mov        dword ptr [esp+0Ah+var_A], ecx
  42.                 fld        [esp+0Ah+var_A]
  43.                 add        esp, 0Ah
  44.                 test        eax, 0
  45.                 mov        eax, [edx+4]
  46.                 retn
  47. __fload_withFB        endp
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-13 22:33:41 | 显示全部楼层
关于求浮点数(单精度和双精度)的平方根,下面的文章值得一看,它利用IEEE754浮点数的格式,直接求出一个比较好的初值,然后使用牛顿迭代求精。
http://ilab.usc.edu/wiki/index.php/Fast_Square_Root
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2012-2-15 11:37:45 | 显示全部楼层
在 Android 源码目录的 bionic/libm/src路径下找到 平方根的实现e_sqrt.c:
感兴趣的可以看看:

e_sqrt.c (14.1 KB, 下载次数: 1)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-26 00:50 , Processed in 0.050833 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表