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

[讨论] 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. lea esi,[esi+4]
  22. lea edx,[edx+4]
  23. lea edi,[edi+4]
  24. dec ecx
  25. jnz loop00
  26. thisExit:
  27. mov eax,0
  28. adc eax,0
  29. pop esi
  30. pop edi
  31. ret
  32. }
  33. }
复制代码
//使用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. pxor mm0,mm0
  18. mov eax,ecx
  19. shr ecx,2
  20. and eax,3
  21. jz a10
  22. loop0:
  23. movd mm1, [esi]
  24. movd mm2, [edi]
  25. paddq mm0, mm1
  26. paddq mm0, mm2
  27. movd [ebx], mm0
  28. psrlq mm0, 32
  29. lea esi,[esi+4]
  30. lea edi,[edi+4]
  31. lea ebx,[ebx+4]
  32. dec eax
  33. jnz loop0
  34. a10:
  35. or ecx,ecx
  36. jz thisExit
  37. loop1:
  38. movd mm1, [esi]
  39. movd mm2, [edi]
  40. paddq mm1, mm2
  41. movd mm3, [esi+4]
  42. movd mm4, [edi+4]
  43. paddq mm3, mm4
  44. movd mm5, [esi+8]
  45. movd mm6, [edi+8]
  46. paddq mm5, mm6
  47. movd mm7, [esi+12]
  48. movd mm2, [edi+12]
  49. paddq mm7, mm2
  50. paddq mm0, mm1
  51. movd [ebx], mm0
  52. psrlq mm0, 32
  53. paddq mm0, mm3
  54. movd [ebx+4], mm0
  55. psrlq mm0, 32
  56. paddq mm0, mm5
  57. movd [ebx+8], mm0
  58. psrlq mm0, 32
  59. paddq mm0, mm7
  60. movd [ebx+12], mm0
  61. psrlq mm0, 32
  62. add esi, 16
  63. add edi, 16
  64. add ebx, 16
  65. sub ecx,1
  66. jne loop1
  67. thisExit:
  68. pop ebx
  69. pop edi
  70. pop esi
  71. movd eax,mm0
  72. emms
  73. ret
  74. }
  75. }
复制代码
//使用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. lea esi,[esi+4]
  26. lea edx,[edx+4]
  27. lea edi,[edi+4]
  28. dec ecx
  29. jnz loop00
  30. pop ecx
  31. a10:
  32. mov eax,0
  33. adc eax,0
  34. or ecx,ecx
  35. jz thisExit
  36. ALIGN 8
  37. loop01:
  38. mov eax,[esi]
  39. adc eax,[edx]
  40. mov [edi],eax
  41. mov eax,[esi+4]
  42. adc eax,[edx+4]
  43. mov [edi+4],eax
  44. mov eax,[esi+8]
  45. adc eax,[edx+8]
  46. mov [edi+8],eax
  47. mov eax,[esi+12]
  48. adc eax,[edx+12]
  49. mov [edi+12],eax
  50. mov eax,[esi+16]
  51. adc eax,[edx+16]
  52. mov [edi+16],eax
  53. mov eax,[esi+20]
  54. adc eax,[edx+20]
  55. mov [edi+20],eax
  56. mov eax,[esi+24]
  57. adc eax,[edx+24]
  58. mov [edi+24],eax
  59. mov eax,[esi+28]
  60. adc eax,[edx+28]
  61. mov [edi+28],eax
  62. lea esi,[esi+32]
  63. lea edx,[edx+32]
  64. lea edi,[edi+32]
  65. dec ecx
  66. jnz loop01
  67. mov eax,0
  68. adc eax,0
  69. thisExit:
  70. pop esi
  71. pop edi
  72. ret
  73. }
  74. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 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. mov ebx,[esp+12+PARAM_DST]
  15. mov esi,[esp+12+PARAM_SRC1]
  16. mov edi,[esp+12+PARAM_SRC2]
  17. mov ecx,[esp+12+PARAM_SIZE]
  18. xor edx,edx //clear carry
  19. or ecx,ecx
  20. jz thisExit
  21. loop00:
  22. mov eax,[esi]
  23. add eax,[edi]
  24. add eax,edx
  25. mov edx,eax
  26. and eax,BASE30_MASK
  27. shr edx,30
  28. mov [ebx],eax
  29. lea esi,[esi+4]
  30. lea edi,[edi+4]
  31. lea ebx,[ebx+4]
  32. dec ecx
  33. jnz loop00
  34. thisExit:
  35. pop ebx
  36. pop esi
  37. pop edi
  38. mov eax,0
  39. adc eax,0
  40. ret
  41. }
  42. }
复制代码
//基为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. loop00:
  25. mov eax,[esi]
  26. add eax,[edi]
  27. add eax,ecx
  28. mov ecx,eax
  29. and eax,BASE30_MASK
  30. shr ecx,30
  31. mov [ebx],eax
  32. lea esi,[esi+4]
  33. lea edi,[edi+4]
  34. lea ebx,[ebx+4]
  35. dec edx
  36. jnz loop00
  37. a10:
  38. jmp cmp00
  39. ALIGN 8
  40. loop01:
  41. //calc [ebx] and [ebx+4]
  42. mov edx,[esi]
  43. mov eax,[esi+4]
  44. add edx,[edi]
  45. add eax,[edi+4]
  46. add edx,ecx
  47. mov ecx,edx
  48. and edx,BASE30_MASK
  49. shr ecx,30
  50. mov [ebx],edx
  51. add eax,ecx
  52. mov ecx,eax
  53. and eax,BASE30_MASK
  54. shr ecx,30
  55. mov [ebx+4],eax
  56. //calc [ebx+8] and [ebx+12]
  57. mov edx,[esi+8]
  58. mov eax,[esi+12]
  59. add edx,[edi+8]
  60. add eax,[edi+12]
  61. add edx,ecx
  62. mov ecx,edx
  63. and edx,BASE30_MASK
  64. shr ecx,30
  65. mov [ebx+8],edx
  66. add eax,ecx
  67. mov ecx,eax
  68. and eax,BASE30_MASK
  69. shr ecx,30
  70. mov [ebx+12],eax
  71. lea esi,[esi+16]
  72. lea edi,[edi+16]
  73. lea ebx,[ebx+16]
  74. cmp00:
  75. cmp esi,[esp]
  76. jb loop01
  77. thisExit:
  78. add esp,4
  79. pop ebx
  80. pop esi
  81. pop edi
  82. mov eax,0
  83. adc eax,0
  84. ret
  85. }
  86. }
复制代码
//基为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. loop00:
  25. mov eax,[esi]
  26. add eax,[edi]
  27. add eax,ecx
  28. mov ecx,eax
  29. and eax,BASE30_MASK
  30. shr ecx,30
  31. mov [ebx],eax
  32. lea esi,[esi+4]
  33. lea edi,[edi+4]
  34. lea ebx,[ebx+4]
  35. dec edx
  36. jnz loop00
  37. a10:
  38. jmp cmp00
  39. ALIGN 8
  40. loop01:
  41. //calc [ebx] and [ebx+4]
  42. mov edx,[esi]
  43. mov eax,[esi+4]
  44. add edx,[edi]
  45. add eax,[edi+4]
  46. add edx,ecx
  47. mov ecx,edx
  48. and edx,BASE30_MASK
  49. shr ecx,30
  50. mov [ebx],edx
  51. add eax,ecx
  52. mov ecx,eax
  53. and eax,BASE30_MASK
  54. shr ecx,30
  55. mov [ebx+4],eax
  56. //calc [ebx+8] and [ebx+12]
  57. mov edx,[esi+8]
  58. mov eax,[esi+12]
  59. add edx,[edi+8]
  60. add eax,[edi+12]
  61. add edx,ecx
  62. mov ecx,edx
  63. and edx,BASE30_MASK
  64. shr ecx,30
  65. mov [ebx+8],edx
  66. add eax,ecx
  67. mov ecx,eax
  68. and eax,BASE30_MASK
  69. shr ecx,30
  70. mov [ebx+12],eax
  71. //calc [ebx+16] and [ebx+20]
  72. mov edx,[esi+16]
  73. mov eax,[esi+20]
  74. add edx,[edi+16]
  75. add eax,[edi+20]
  76. add edx,ecx
  77. mov ecx,edx
  78. and edx,BASE30_MASK
  79. shr ecx,30
  80. mov [ebx+16],edx
  81. add eax,ecx
  82. mov ecx,eax
  83. and eax,BASE30_MASK
  84. shr ecx,30
  85. mov [ebx+20],eax
  86. //calc [ebx+24] and [ebx+28]
  87. mov edx,[esi+24]
  88. mov eax,[esi+28]
  89. add edx,[edi+24]
  90. add eax,[edi+28]
  91. add edx,ecx
  92. mov ecx,edx
  93. and edx,BASE30_MASK
  94. shr ecx,30
  95. mov [ebx+24],edx
  96. add eax,ecx
  97. mov ecx,eax
  98. and eax,BASE30_MASK
  99. shr ecx,30
  100. mov [ebx+28],eax
  101. lea esi,[esi+32]
  102. lea edi,[edi+32]
  103. lea ebx,[ebx+32]
  104. cmp00:
  105. cmp esi,[esp]
  106. jb loop01
  107. thisExit:
  108. add esp,4
  109. pop ebx
  110. pop esi
  111. pop edi
  112. mov eax,0
  113. adc eax,0
  114. ret
  115. }
  116. }
复制代码
// 使用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. pxor mm0,mm0
  20. mov eax,BASE30_MASK
  21. movd mm7,eax
  22. mov eax,ecx
  23. shr ecx,2
  24. and eax,3
  25. jz a10
  26. loop0:
  27. movd mm1, [esi]
  28. movd mm2, [edi]
  29. paddq mm0, mm1
  30. paddq mm0, mm2
  31. movq mm1, mm0
  32. psrlq mm0, 30
  33. pand mm1, mm7
  34. movd [ebx],mm1
  35. lea esi,[esi+4]
  36. lea edi,[edi+4]
  37. lea ebx,[ebx+4]
  38. dec eax
  39. jnz loop0
  40. a10:
  41. or ecx,ecx
  42. jz thisExit
  43. loop1:
  44. //calc [ebx] and [ebx+4]
  45. movd mm1,[esi]
  46. movd mm3,[edi]
  47. movd mm2,[esi+4]
  48. movd mm4,[edi+4]
  49. paddq mm1,mm3
  50. paddq mm2,mm4
  51. paddq mm0,mm1
  52. movq mm3,mm0
  53. psrlq mm0,30
  54. pand mm3,mm7
  55. movd [ebx],mm3
  56. paddq mm0,mm2
  57. movq mm4,mm0
  58. psrlq mm0,30
  59. pand mm4,mm7
  60. movd [ebx+4],mm4
  61. //calc [ebx+8] and [ebx+12]
  62. movd mm1,[esi+8]
  63. movd mm3,[edi+8]
  64. movd mm2,[esi+12]
  65. movd mm4,[edi+12]
  66. paddq mm1,mm3
  67. paddq mm2,mm4
  68. paddq mm0,mm1
  69. movq mm3,mm0
  70. psrlq mm0,30
  71. pand mm3,mm7
  72. movd [ebx+8],mm3
  73. paddq mm0,mm2
  74. movq mm4,mm0
  75. psrlq mm0,30
  76. pand mm4,mm7
  77. movd [ebx+12],mm4
  78. add esi, 16
  79. add edi, 16
  80. add ebx, 16
  81. sub ecx,1
  82. jne loop1
  83. thisExit:
  84. pop ebx
  85. pop edi
  86. pop esi
  87. movd eax,mm0
  88. emms
  89. ret
  90. }
  91. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 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-11-15 10:16 , Processed in 0.026309 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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