找回密码
 欢迎注册
楼主: 无心人

[讨论] 二进制32位整数快速平方根

[复制链接]
 楼主| 发表于 2009-2-17 16:17:08 | 显示全部楼层


我测试下吧
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-2-17 17:02:38 | 显示全部楼层
测试环境:
CPU:
  Intel Pentium4 2.6G
  L1 data 8KB, L1 trace 12KB
  L2 cache 512KB
RAM:
   DDR 768MB
OS: windows XP
compiler: VC++6.0 release


Test case1: n=0 to 65535

iSqt_c1_lbc#: 0.00082 s
iSqt_FPU1_lbc#: 0.00095 s
iSqt_FPU3_lbc#: 0.00127 s
iSqt_FPU2_lbc#: 0.00146 s
iSqt_c2_lbc#: 0.00151 s
iSqt_gxq_c#: 0.00173 s
iSqt_FPU1_yaos#: 0.00220 s
iSqt_FPU_yaos#: 0.00235 s
iSqt_FPU2_yaos#: 0.00246 s
iSqt_ref#: 0.00306 s
iSqt_16#: 0.00398 s
iSqt_gxq_90#: 0.00434 s  (新增,90楼那个版本)
iSqt_GxQ_asm#: 0.00449 s


Test case2: n=0- 2^28-1

iSqt_FPU1_lbc#: 3.97569 s
iSqt_FPU3_lbc#: 5.32763 s
iSqt_FPU2_lbc#: 7.59953 s
iSqt_gxq_c#: 7.64778 s
iSqt_c1_lbc#: 8.14219 s
iSqt_FPU1_yaos#: 9.24091 s
iSqt_FPU_yaos#: 9.51267 s
iSqt_c2_lbc#: 10.19276 s
iSqt_FPU2_yaos#: 10.54652 s
iSqt_ref#: 12.78721 s
iSqt_16#: 14.57529 s
iSqt_gxq_90#: 18.04432 s (新增,90楼那个版本)
iSqt_GxQ_asm#: 18.64220 s
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-17 19:09:14 | 显示全部楼层
宝宝:

    今天看你42# FPU3代码除了你么处理esp外, 你也么恢复ecx啊

     另外,似乎是连续的两个fntstcw, fldcw造成的你的代码速度比俺的快

    依据的什么原理??
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-2-17 21:24:26 | 显示全部楼层

回复 93# 无心人 的帖子

为什么我的版本比你的快,我没有仔细分析过,连续使用两个fntstcw没有什么特别的道理,我的原则是指令数尽可能少,另外要做到浮点寄存器栈的平衡。
  
我确实没有回回复ecx寄存器,我记得按照函数调用规则,如果你在子程序中修改了esi,edi,ebx,esp,ebp 等寄存器,你必须恢复它,但是你可以在子程序中仍以修改eax,edx,ecx 的值,调用者不能假定这些寄存器没有变化。
  但是如果指定了__fastcall关键字,是否必须保证调用子程序后不修改ecx的值,我刚刚查阅了一些资料,但依然没有找到确切的答案。我是假定在__fastcall子程序中可以修改ecx 的值的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-17 21:54:55 | 显示全部楼层


几乎同样的功能
几乎同样的指令

一个9.24
一个5.32

到底差距在哪里啊?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2009-2-17 22:03:38 | 显示全部楼层

我写的三个ALU汇编版本

  1. __declspec(naked)
  2. UINT32 __fastcall iSqrt_ALU( UINT32 n )
  3. {
  4.     __asm   push    esi;
  5.     __asm   push    edi;
  6.     __asm   xor     eax, eax;

  7. #if 1   /* Ver1: 指令数最少,但含跳转 */

  8. #define SQRT_CORE_ASM(x)                    \
  9.     __asm   lea     edx, [eax+(1UL<<(x))]   \
  10.     __asm   shr     eax, 1                  \
  11.     __asm   cmp     ecx, edx                \
  12.     __asm   jb      L_##x                   \
  13.     __asm   sub     ecx, edx                \
  14.     __asm   add     eax, (1UL<<(x))         \
  15.     __asm   L_##x:

  16. #elif 0 /* Ver2: 常规指令,无跳转 */

  17. #define SQRT_CORE_ASM(x)                    \
  18.     __asm   mov     edi, 1UL<<(x)           \
  19.     __asm   lea     edx, [eax+edi]          \
  20.     __asm   shr     eax, 1                  \
  21.     __asm   cmp     ecx, edx                \
  22.     __asm   sbb     esi, esi                \
  23.     __asm   not     esi                     \
  24.     __asm   and     edx, esi                \
  25.     __asm   and     edi, esi                \
  26.     __asm   sub     ecx, edx                \
  27.     __asm   add     eax, edi

  28. #else   /* Ver3: 含CMOVcc指令,无跳转 */

  29. #define SQRT_CORE_ASM(x)                    \
  30.     __asm   lea     edx, [eax+(1UL<<(x))]   \
  31.     __asm   shr     eax, 1                  \
  32.     __asm   mov     esi, ecx                \
  33.     __asm   sub     ecx, edx                \
  34.     __asm   lea     edi, [eax+(1UL<<(x))]   \
  35.     __asm   cmovb   ecx, esi                \
  36.     __asm   cmovae  eax, edi

  37. #endif

  38.     SQRT_CORE_ASM(30);
  39.     SQRT_CORE_ASM(28);
  40.     SQRT_CORE_ASM(26);
  41.     SQRT_CORE_ASM(24);
  42.     SQRT_CORE_ASM(22);
  43.     SQRT_CORE_ASM(20);
  44.     SQRT_CORE_ASM(18);
  45.     SQRT_CORE_ASM(16);
  46.     SQRT_CORE_ASM(14);
  47.     SQRT_CORE_ASM(12);
  48.     SQRT_CORE_ASM(10);
  49.     SQRT_CORE_ASM(8);
  50.     SQRT_CORE_ASM(6);
  51.     SQRT_CORE_ASM(4);
  52.     SQRT_CORE_ASM(2);
  53.     SQRT_CORE_ASM(0);

  54. #undef SQRT_CORE_ASM

  55.     __asm   pop     edi;
  56.     __asm   pop     esi;
  57.     __asm   ret;
  58. }
复制代码
其对应的C代码是一样的,只是采用了不同的汇编手法。

测试结果如下:
n: 0-0x10000
iSqt_ref#: 0.00098 s
iSqt_c1_lbc#: 0.00071 s
iSqt_c2_lbc#: 0.00133 s
iSqt_FPU1_lbc#: 0.00092 s
iSqt_FPU2_lbc#: 0.00134 s
iSqt_FPU3_lbc#: 0.00118 s
iSqt_FPU_yaos#: 0.00217 s
iSqt_FPU1_yaos#: 0.00217 s
iSqt_FPU2_yaos#: 0.00208 s
iSqt_gxq_c#: 0.00140 s
iSqt_GxQ_asm#: 0.00471 s
iSqt_ALU_v1#: 0.00115 s
iSqt_ALU_v2#: 0.00580 s
iSqt_ALU_v3#: 0.00426 s
iSqt_16#: 0.00298 s


n: 0-0x4000000
iSqt_ref#: 1.03851 s
iSqt_c1_lbc#: 2.05060 s
iSqt_c2_lbc#: 1.94235 s
iSqt_FPU1_lbc#: 0.99109 s
iSqt_FPU2_lbc#: 1.41954 s
iSqt_FPU3_lbc#: 1.24257 s
iSqt_FPU_yaos#: 2.31683 s
iSqt_FPU1_yaos#: 2.38967 s
iSqt_FPU2_yaos#: 2.22774 s
iSqt_gxq_c#: 1.11229 s
iSqt_GxQ_asm#: 5.01363 s
iSqt_ALU_v1#: 1.17843 s
iSqt_ALU_v2#: 6.18305 s
iSqt_ALU_v3#: 4.54953 s
iSqt_16#: 2.95849 s


测试平台为:Windows XP SP3, P4 2.93GHz
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-17 22:11:44 | 显示全部楼层
46#代码存在冗余
需要修改
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-17 22:15:36 | 显示全部楼层
如果我的Core2Xeon测试
应该是你的V3版本最好了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-17 22:38:23 | 显示全部楼层

  1. __declspec(naked)
  2. DWORD __fastcall iSqrt_FPU1_yaos(DWORD n)
  3. {
  4. __asm
  5. {
  6.    sub esp, 8
  7.    mov [esp + 4], ecx
  8.    fnstcw word ptr  [esp]
  9.    fnstcw word ptr [esp + 2]
  10.    or word ptr [esp], 0x0E60
  11.    mov eax, ecx  
  12.    shr eax, 31
  13.    fld qword ptr [b32 + eax * 8]
  14.    fild dword ptr [esp + 4]
  15.    faddp st(1), st
  16.    fsqrt
  17.    fldcw word ptr [esp]
  18.    fistp dword ptr [esp + 4]
  19.    fldcw word ptr [esp + 2]
  20.    mov eax, [esp + 4]
  21.    add esp, 8
  22.    ret
  23.    }
  24. }
复制代码
宝宝的代码里我的函数FPU1应该是这样的
稍微优化了点
执行时间减少了至少40%
我明天去学校看我机器里的代码

可能存在版本差异
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2009-2-18 07:51:09 | 显示全部楼层
今天早上
翻MMX的书

看到说,内存的内部和全部
即128位内部的64位,64位内部的32位等等。。。
如果同时发生写和读
将发生阻塞

可能是我程序代码速度慢的原因
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-4-27 07:12 , Processed in 0.068579 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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