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

[讨论] B计划之长加法最佳算法讨论

[复制链接]
发表于 2008-4-16 15:22:46 | 显示全部楼层
回29楼,当然!
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 15:30:59 | 显示全部楼层


那,怎么说呢
我觉得为了一点速度的提高
有点不值吧
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 15:31:56 | 显示全部楼层
而且,2^32也可以一次加2^30个整数而不溢出啊
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 15:35:51 | 显示全部楼层
另外
有一个操作2^30基是无法高效的
就是x=x+1操作
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 16:35:14 | 显示全部楼层
为了阅读方便,现将23楼附件中的2进制 大数加法的代码给出。

#define PARAM_SIZE 16
#define PARAM_SRC2 12
#define PARAM_SRC1 8
#define PARAM_DST  4

//1. 普通的加法,不使用循环展开
  1. _declspec(naked)
  2. DWORD binAdd_ALU(DWORD *dst,
  3.                 const DWORD *src1,
  4.                 const DWORD *src2,
  5.                 int   size)
  6. {
  7.         _asm
  8.         {
  9.         push edi
  10.         push esi

  11.         mov        edi,[esp+8+PARAM_DST]
  12.         mov        esi,[esp+8+PARAM_SRC1]
  13.         mov        edx,[esp+8+PARAM_SRC2]
  14.         mov        ecx,[esp+8+PARAM_SIZE]

  15.         or  ecx,ecx
  16.         jz thisExit

  17. loop00:
  18.         mov eax,[esi]
  19.         adc eax,[edx]
  20.         mov [edi],eax
  21.        
  22.         lea esi,[esi+4]
  23.         lea edx,[edx+4]
  24.         lea edi,[edi+4]
  25.         dec ecx
  26.         jnz loop00
  27.        
  28. thisExit:
  29.         mov eax,0
  30.         adc eax,0
  31.         pop esi
  32.         pop edi
  33.         ret
  34.         }
  35. }
复制代码
//使用4路循环展开的MMX版本
// 循环主题采用yaos的代码,(有bug,己经fix),liangbch加上了收尾部分和变量初始化部分
// 使用4路循环展开
  1. _declspec(naked)
  2. DWORD binAdd_Yaos_MMX_4way_unroll(DWORD *dst,
  3.                 const DWORD *src1,
  4.                 const DWORD *src2,
  5.                 int   size)
  6. {
  7. #define STACK_FRAME 12
  8.         _asm
  9.         {
  10.                 push esi
  11.                 push edi
  12.                 push ebx

  13.                 mov ebx,dword ptr [esp+4+STACK_FRAME]        //dst
  14.                 mov esi,dword ptr [esp+8+STACK_FRAME]        //src1
  15.                 mov edi,dword ptr [esp+12+STACK_FRAME]        //src2
  16.                 mov ecx,dword ptr [esp+16+STACK_FRAME]        //size
  17.                
  18.                 pxor mm0,mm0
  19.                 mov eax,ecx
  20.                 shr ecx,2       
  21.                 and eax,3
  22.                 jz  a10

  23. loop0:
  24.                 movd mm1, [esi]
  25.                 movd mm2, [edi]
  26.                 paddq mm0,  mm1
  27.                 paddq mm0,  mm2
  28.                 movd [ebx], mm0
  29.                 psrlq mm0, 32
  30.                
  31.                 lea esi,[esi+4]
  32.                 lea edi,[edi+4]
  33.                 lea ebx,[ebx+4]
  34.                 dec eax
  35.                 jnz loop0
  36. a10:       
  37.                 or ecx,ecx
  38.                 jz thisExit
  39. loop1:
  40.                 movd mm1, [esi]
  41.                 movd mm2, [edi]
  42.                 paddq mm1,  mm2
  43.                
  44.                 movd mm3, [esi+4]
  45.                 movd mm4, [edi+4]
  46.                 paddq mm3, mm4
  47.                
  48.                 movd mm5, [esi+8]
  49.                 movd mm6, [edi+8]
  50.                 paddq mm5, mm6
  51.                
  52.                 movd mm7, [esi+12]
  53.                 movd mm2, [edi+12]
  54.                 paddq mm7, mm2
  55.                 paddq mm0, mm1
  56.                 movd [ebx], mm0
  57.                 psrlq mm0, 32
  58.                 paddq mm0, mm3
  59.                 movd [ebx+4], mm0
  60.                 psrlq mm0, 32
  61.                 paddq mm0, mm5
  62.                 movd [ebx+8], mm0
  63.                 psrlq mm0, 32
  64.                 paddq mm0, mm7
  65.                 movd [ebx+12], mm0
  66.                 psrlq mm0, 32
  67.                
  68.                 add esi, 16
  69.                 add edi, 16
  70.                 add ebx, 16
  71.                 sub ecx,1
  72.                 jne loop1

  73. thisExit:
  74.                
  75.                 pop ebx
  76.                 pop edi
  77.                 pop esi
  78.                
  79.                 movd eax,mm0
  80.                 emms
  81.                 ret
  82.         }
  83. }
复制代码
//使用8路循环展开的ALU版本
/*
下面的代码由原始的GMP代码转译而来,限於对GMP的理解的限制,
  部分代码不得不重写,GMP源代码请参见 aors_n.asm
  使用8路循环展开
*/
  1. _declspec(naked)
  2. DWORD binAdd_GMP_ALU_8way_unroll(DWORD *dst,
  3.                 const DWORD *src1,
  4.                 const DWORD *src2,
  5.                 int   size)
  6. {
  7.         _asm
  8.         {
  9.         push edi
  10.         push esi

  11.         mov        edi,[esp+8+PARAM_DST]
  12.         mov        esi,[esp+8+PARAM_SRC1]
  13.         mov        edx,[esp+8+PARAM_SRC2]
  14.         mov        ecx,[esp+8+PARAM_SIZE]

  15.         mov        eax,ecx
  16.         shr ecx,3       
  17.         and eax,7
  18.         jz  a10

  19.         push ecx
  20.         mov  ecx,eax

  21. loop00:
  22.         mov eax,[esi]
  23.         adc eax,[edx]
  24.         mov [edi],eax
  25.        
  26.         lea esi,[esi+4]
  27.         lea edx,[edx+4]
  28.         lea edi,[edi+4]
  29.         dec ecx
  30.         jnz loop00
  31.         pop ecx

  32. a10:
  33.         mov eax,0
  34.         adc eax,0
  35.         or ecx,ecx
  36.         jz thisExit
  37.         ALIGN 8
  38. loop01:
  39.         mov        eax,[esi]
  40.         adc        eax,[edx]
  41.         mov        [edi],eax
  42.        
  43.         mov        eax,[esi+4]
  44.         adc        eax,[edx+4]
  45.         mov        [edi+4],eax
  46.        
  47.         mov        eax,[esi+8]
  48.         adc        eax,[edx+8]
  49.         mov        [edi+8],eax
  50.        
  51.         mov        eax,[esi+12]
  52.         adc        eax,[edx+12]
  53.         mov        [edi+12],eax

  54.         mov        eax,[esi+16]
  55.         adc        eax,[edx+16]
  56.         mov        [edi+16],eax

  57.         mov        eax,[esi+20]
  58.         adc        eax,[edx+20]
  59.         mov        [edi+20],eax

  60.         mov        eax,[esi+24]
  61.         adc        eax,[edx+24]
  62.         mov        [edi+24],eax
  63.        
  64.         mov        eax,[esi+28]
  65.         adc        eax,[edx+28]
  66.         mov        [edi+28],eax

  67.        
  68.         lea esi,[esi+32]
  69.         lea edx,[edx+32]
  70.         lea edi,[edi+32]

  71.         dec        ecx
  72.         jnz        loop01
  73.         mov        eax,0
  74.         adc        eax,0
  75. thisExit:
  76.         pop        esi
  77.         pop        edi
  78.         ret
  79.         }
  80. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 16:39:54 | 显示全部楼层


你还没回答我问题呢?
2^32的MMX版本也是可以多次加不进位的

X = X+1的2^30版本如何高效?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 16:43:45 | 显示全部楼层
// 接楼上,给出剩余的几个采用$2^30$进制的大数加法的函数


//基为2^30的版本,不采用循环展开
  1. _declspec(naked)
  2. DWORD binAdd_base30_ALU(DWORD *dst,
  3.                 const DWORD *src1,
  4.                 const DWORD *src2,
  5.                 int   size)
  6. {
  7. #undef  BASE30_MASK
  8. #define BASE30_MASK 0x3fffffff
  9.         _asm
  10.         {
  11.         push edi
  12.         push esi
  13.         push ebx
  14.        

  15.         mov        ebx,[esp+12+PARAM_DST]
  16.         mov        esi,[esp+12+PARAM_SRC1]
  17.         mov        edi,[esp+12+PARAM_SRC2]
  18.         mov        ecx,[esp+12+PARAM_SIZE]

  19.         xor        edx,edx        //clear carry
  20.         or  ecx,ecx
  21.         jz thisExit
  22.        
  23. loop00:
  24.         mov eax,[esi]
  25.         add eax,[edi]
  26.         add eax,edx
  27.         mov edx,eax
  28.         and eax,BASE30_MASK
  29.         shr edx,30
  30.         mov [ebx],eax
  31.         lea esi,[esi+4]
  32.         lea edi,[edi+4]
  33.         lea ebx,[ebx+4]
  34.         dec ecx
  35.         jnz loop00

  36. thisExit:
  37.        
  38.         pop ebx
  39.         pop esi
  40.         pop edi
  41.         mov eax,0
  42.         adc eax,0
  43.         ret
  44.         }
  45. }
复制代码
//基为2^30的版本,采用4路循环展开
  1. _declspec(naked)
  2. DWORD binAdd_base30_ALU_4way_unroll(DWORD *dst,
  3.                 const DWORD *src1,
  4.                 const DWORD *src2,
  5.                 int   size)
  6. {
  7. #undef  BASE30_MASK
  8. #define BASE30_MASK 0x3fffffff
  9.         _asm
  10.         {
  11.         push edi
  12.         push esi
  13.         push ebx
  14.         sub  esp,4

  15.         mov ebx,[esp+16+PARAM_DST]
  16.         mov esi,[esp+16+PARAM_SRC1]
  17.         mov edi,[esp+16+PARAM_SRC2]
  18.         mov edx,[esp+16+PARAM_SIZE]

  19.         lea eax,[esi+edx*4]
  20.         mov [esp],eax

  21.         xor ecx,ecx                //clear carry
  22.         and edx,3
  23.         jz  a10
  24.        
  25. loop00:
  26.         mov eax,[esi]
  27.         add eax,[edi]
  28.         add eax,ecx
  29.         mov ecx,eax
  30.         and eax,BASE30_MASK
  31.         shr ecx,30
  32.         mov [ebx],eax
  33.         lea esi,[esi+4]
  34.         lea edi,[edi+4]
  35.         lea ebx,[ebx+4]
  36.         dec edx
  37.         jnz loop00
  38. a10:
  39.         jmp cmp00

  40.         ALIGN 8
  41. loop01:
  42.         //calc [ebx] and [ebx+4]
  43.         mov edx,[esi]
  44.         mov eax,[esi+4]
  45.         add edx,[edi]
  46.         add eax,[edi+4]
  47.        
  48.         add edx,ecx
  49.         mov ecx,edx
  50.         and edx,BASE30_MASK
  51.         shr ecx,30
  52.         mov [ebx],edx
  53.        
  54.         add eax,ecx
  55.         mov ecx,eax
  56.         and eax,BASE30_MASK
  57.         shr ecx,30
  58.         mov [ebx+4],eax

  59.         //calc [ebx+8] and [ebx+12]
  60.         mov edx,[esi+8]
  61.         mov eax,[esi+12]
  62.         add edx,[edi+8]
  63.         add eax,[edi+12]

  64.         add edx,ecx
  65.         mov ecx,edx
  66.         and edx,BASE30_MASK
  67.         shr ecx,30
  68.         mov [ebx+8],edx
  69.        
  70.         add eax,ecx
  71.         mov ecx,eax
  72.         and eax,BASE30_MASK
  73.         shr ecx,30
  74.         mov [ebx+12],eax

  75.         lea esi,[esi+16]
  76.         lea edi,[edi+16]
  77.         lea ebx,[ebx+16]
  78. cmp00:
  79.         cmp esi,[esp]
  80.         jb loop01

  81. thisExit:
  82.         add esp,4
  83.        
  84.         pop ebx
  85.         pop esi
  86.         pop edi
  87.         mov eax,0
  88.         adc eax,0
  89.         ret
  90.         }
  91. }
复制代码
//基为2^30的版本,采用8路循环展开
  1. _declspec(naked)
  2. DWORD binAdd_base30_ALU_8way_unroll(DWORD *dst,
  3.                 const DWORD *src1,
  4.                 const DWORD *src2,
  5.                 int   size)
  6. {
  7. #undef  BASE30_MASK
  8. #define BASE30_MASK 0x3fffffff
  9.         _asm
  10.         {
  11.         push edi
  12.         push esi
  13.         push ebx
  14.         sub  esp,4

  15.         mov ebx,[esp+16+PARAM_DST]
  16.         mov esi,[esp+16+PARAM_SRC1]
  17.         mov edi,[esp+16+PARAM_SRC2]
  18.         mov edx,[esp+16+PARAM_SIZE]

  19.         lea eax,[esi+edx*4]
  20.         mov [esp],eax

  21.         xor ecx,ecx
  22.         and edx,7
  23.         jz  a10
  24.        
  25. loop00:
  26.         mov eax,[esi]
  27.         add eax,[edi]
  28.         add eax,ecx
  29.         mov ecx,eax
  30.         and eax,BASE30_MASK
  31.         shr ecx,30
  32.         mov [ebx],eax
  33.         lea esi,[esi+4]
  34.         lea edi,[edi+4]
  35.         lea ebx,[ebx+4]
  36.         dec edx
  37.         jnz loop00
  38. a10:
  39.         jmp cmp00

  40.         ALIGN 8
  41. loop01:
  42.         //calc [ebx] and [ebx+4]
  43.         mov edx,[esi]
  44.         mov eax,[esi+4]
  45.         add edx,[edi]
  46.         add eax,[edi+4]
  47.        
  48.         add edx,ecx
  49.         mov ecx,edx
  50.         and edx,BASE30_MASK
  51.         shr ecx,30
  52.         mov [ebx],edx
  53.        
  54.         add eax,ecx
  55.         mov ecx,eax
  56.         and eax,BASE30_MASK
  57.         shr ecx,30
  58.         mov [ebx+4],eax
  59.        
  60.         //calc [ebx+8] and [ebx+12]
  61.         mov edx,[esi+8]
  62.         mov eax,[esi+12]
  63.         add edx,[edi+8]
  64.         add eax,[edi+12]
  65.        
  66.         add edx,ecx
  67.         mov ecx,edx
  68.         and edx,BASE30_MASK
  69.         shr ecx,30
  70.         mov [ebx+8],edx
  71.        
  72.         add eax,ecx
  73.         mov ecx,eax
  74.         and eax,BASE30_MASK
  75.         shr ecx,30
  76.         mov [ebx+12],eax

  77.         //calc [ebx+16] and [ebx+20]
  78.         mov edx,[esi+16]
  79.         mov eax,[esi+20]
  80.         add edx,[edi+16]
  81.         add eax,[edi+20]
  82.        
  83.         add edx,ecx
  84.         mov ecx,edx
  85.         and edx,BASE30_MASK
  86.         shr ecx,30
  87.         mov [ebx+16],edx
  88.        
  89.         add eax,ecx
  90.         mov ecx,eax
  91.         and eax,BASE30_MASK
  92.         shr ecx,30
  93.         mov [ebx+20],eax

  94.         //calc [ebx+24] and [ebx+28]
  95.         mov edx,[esi+24]
  96.         mov eax,[esi+28]
  97.         add edx,[edi+24]
  98.         add eax,[edi+28]
  99.        
  100.         add edx,ecx
  101.         mov ecx,edx
  102.         and edx,BASE30_MASK
  103.         shr ecx,30
  104.         mov [ebx+24],edx
  105.        
  106.         add eax,ecx
  107.         mov ecx,eax
  108.         and eax,BASE30_MASK
  109.         shr ecx,30
  110.         mov [ebx+28],eax

  111.         lea esi,[esi+32]
  112.         lea edi,[edi+32]
  113.         lea ebx,[ebx+32]
  114. cmp00:
  115.         cmp esi,[esp]
  116.         jb loop01

  117. thisExit:
  118.         add esp,4
  119.         pop ebx
  120.         pop esi
  121.         pop edi
  122.         mov eax,0
  123.         adc eax,0
  124.         ret
  125.         }
  126. }
复制代码
// 使用4路循环展开
  1. _declspec(naked)
  2. DWORD binAdd_Base30_MMX_4way_unroll(DWORD *dst,
  3.                 const DWORD *src1,
  4.                 const DWORD *src2,
  5.                 int   size)
  6. {
  7. #define STACK_FRAME 12
  8. #undef  BASE30_MASK
  9. #define BASE30_MASK 0x3fffffff
  10.         _asm
  11.         {
  12.                 push esi
  13.                 push edi
  14.                 push ebx

  15.                 mov ebx,dword ptr [esp+4+STACK_FRAME]        //dst
  16.                 mov esi,dword ptr [esp+8+STACK_FRAME]        //src1
  17.                 mov edi,dword ptr [esp+12+STACK_FRAME]        //src2
  18.                 mov ecx,dword ptr [esp+16+STACK_FRAME]        //size
  19.                
  20.                 pxor mm0,mm0
  21.                 mov  eax,BASE30_MASK
  22.                 movd mm7,eax

  23.                 mov eax,ecx
  24.                 shr ecx,2       
  25.                 and eax,3
  26.                 jz  a10

  27. loop0:
  28.                 movd mm1, [esi]
  29.                 movd mm2, [edi]
  30.                 paddq mm0,  mm1
  31.                 paddq mm0,  mm2
  32.                
  33.                 movq mm1, mm0
  34.                 psrlq mm0, 30
  35.                 pand mm1, mm7
  36.                 movd [ebx],mm1
  37.                
  38.                 lea esi,[esi+4]
  39.                 lea edi,[edi+4]
  40.                 lea ebx,[ebx+4]
  41.                 dec eax
  42.                 jnz loop0
  43. a10:       
  44.                 or ecx,ecx
  45.                 jz thisExit
  46. loop1:
  47.                 //calc [ebx] and [ebx+4]
  48.                 movd        mm1,[esi]
  49.                 movd        mm3,[edi]
  50.                 movd         mm2,[esi+4]
  51.                 movd        mm4,[edi+4]
  52.                 paddq         mm1,mm3
  53.                 paddq        mm2,mm4
  54.        
  55.                 paddq        mm0,mm1
  56.                 movq        mm3,mm0
  57.                 psrlq        mm0,30
  58.                 pand        mm3,mm7
  59.                 movd        [ebx],mm3
  60.        
  61.                 paddq        mm0,mm2
  62.                 movq        mm4,mm0
  63.                 psrlq        mm0,30
  64.                 pand        mm4,mm7
  65.                 movd        [ebx+4],mm4

  66.                 //calc [ebx+8] and [ebx+12]
  67.                
  68.                 movd        mm1,[esi+8]
  69.                 movd        mm3,[edi+8]
  70.                 movd         mm2,[esi+12]
  71.                 movd        mm4,[edi+12]
  72.                 paddq         mm1,mm3
  73.                 paddq        mm2,mm4
  74.                
  75.                 paddq        mm0,mm1
  76.                 movq        mm3,mm0
  77.                 psrlq        mm0,30
  78.                 pand        mm3,mm7
  79.                 movd        [ebx+8],mm3
  80.        
  81.                 paddq        mm0,mm2
  82.                 movq        mm4,mm0
  83.                 psrlq        mm0,30
  84.                 pand        mm4,mm7
  85.                 movd        [ebx+12],mm4
  86.                
  87.                 add esi, 16
  88.                 add edi, 16
  89.                 add ebx, 16
  90.                 sub ecx,1
  91.                 jne loop1

  92. thisExit:
  93.                
  94.                 pop ebx
  95.                 pop edi
  96.                 pop esi
  97.                
  98.                 movd eax,mm0
  99.                 emms
  100.                 ret
  101.         }
  102. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 17:01:23 | 显示全部楼层
1.
2^32的MMX版本也是可以多次加不进位的

我不带明白你指的是什么,是大数乘法还是大数加法。
如果是大数加法,使用ALU指令必然会进位。

我们不但要考虑MMX指令,更多的情况下,我们需要考虑ALU指令,我们不能假定我的程序总是运行在支持SSE2指令的计算机。我的程序应该自动侦测CPU,在任何386以上的CPU上运行。

2.对于大数x,计算x=x+1,并不是一个常用的操作,一般情况下,其复杂度为常数,不值得考虑。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-16 17:04:17 | 显示全部楼层

当然是加法了
就你说的 A+B+C+D
。。。。。。。。。。。。。。。。。。。。。。。。
2.对于大数x,计算x=x+1,并不是一个常用的操作,一般情况下,其复杂度为常数,不值得考虑。这个不是吧,在不等长的加法里是常见的操作啊
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-16 17:07:01 | 显示全部楼层
在99.99999999...%的情况下,x=x+1,不会连续进位,所以我说是一个常数时间。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-5-3 22:44 , Processed in 0.047707 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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