找回密码
 欢迎注册
查看: 22853|回复: 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. __fload_withFB:
  22. var_A = tbyte ptr -0Ah
  23. mov eax, [edx+4]
  24. and eax, 7FF00000h
  25. cmp eax, 7FF00000h
  26. jz short loc_77C20C37
  27. fld qword ptr [edx]
  28. retn
  29. ; --------------------------------
  30. loc_77C20C37:
  31. mov eax, [edx+4]
  32. sub esp, 0Ah
  33. or eax, 7FFF0000h
  34. mov dword ptr [esp+0Ah+var_A+6], eax
  35. mov eax, [edx+4]
  36. mov ecx, [edx]
  37. shld eax, ecx, 0Bh
  38. shl ecx, 0Bh
  39. mov [esp+4], eax
  40. mov dword ptr [esp+0Ah+var_A], ecx
  41. fld [esp+0Ah+var_A]
  42. add esp, 0Ah
  43. test eax, 0
  44. mov eax, [edx+4]
  45. retn
  46. __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-11-24 08:14 , Processed in 0.027212 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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