找回密码
 欢迎注册
楼主: gxqcn

[讨论] 一个快速得到bit位索引的算法

[复制链接]
发表于 2008-3-4 08:43:41 | 显示全部楼层
根据那个链接,数1的比特位数目应该用查询表还要快一些。(特别对于16比特整数)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-4 08:50:41 | 显示全部楼层
原帖由 mathe 于 2008-3-4 08:40 发表 我们知道,像下面的代码(来源自http://www.everything2.com/index.pl?node_id=1181258)可以 比较快速计算出一个int中比特1的数目,稍微修改一下,就可以变成计算short中比特1的数目的代码(可能需要4个时钟周期?? 通过预先计算后半个short部分比特1的数目,我们应该可以将代码拆分成两个可以并行的部分。...
这个想法好是好,但最后如何并行并不容易啊。。。 不知道CPU是否支持函数级的并行:当两个紧邻的函数名一致、而输入输出没有依赖关系时?
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-4 08:58:56 | 显示全部楼层
还有,gxqcn的代码可以改成C代码
  1. unsigned find(unsigned code, int index[])
  2. {
  3. int i;
  4. int *p=index;
  5. for(i=0;i<32;i++){
  6. *p=i;
  7. p+=(code&(1<<i))!=0;
  8. }
  9. *p=-1;
  10. }
复制代码
看看,当然编译器优化选项要打开(这样循环才会被展开)。 如果当心编译器优化选项打开会影响测试,可以创建保换两个文件的工程,将这部分代码单独放在一个文件中,然后单独对这个文件优化。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-4 09:00:45 | 显示全部楼层
函数级的不行,没法做到指令级并行,而线程级并行显然不能使用。 发现你那个代码如果拆分成并行的两部分或者四部分,主要问题在于最后对于那些多余的0有些问题
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-4 09:01:43 | 显示全部楼层
别想了 目前的X86没并行功能 考虑Cell级别的CPU可能还行 哈
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-4 09:10:01 | 显示全部楼层
将上面代码用gcc -O3 -funroll-all-loops -S编译出来代码为: 不过不知道为什么前面要做一次跳转指令,估计是为了让内存同Cacheline边界对齐。 如果我们能够保证输入数组空间已经内存对齐,那么这部分指令可以拿掉。(特别对于重复运行多次进行测试的代码,这部分应该拿掉)
  1. .file "tta1.c"
  2. .text
  3. .p2align 4,,15
  4. .globl find
  5. .type find, @function
  6. find:
  7. pushl %ebp
  8. movl %esp, %ebp
  9. pushl %edi
  10. pushl %esi
  11. movl \$1, %esi
  12. pushl %ebx
  13. xorl %ebx, %ebx
  14. subl \$4, %esp
  15. movl 12(%ebp), %eax
  16. movl 8(%ebp), %edi
  17. movl %eax, -16(%ebp)
  18. jmp .L2
  19. .p2align 4,,7
  20. .L20:
  21. movl -16(%ebp), %eax
  22. .L2:
  23. movb %bl, %cl
  24. movl %esi, %edx
  25. sall %cl, %edx
  26. andl %edi, %edx
  27. movl %ebx, (%eax)
  28. cmpl \$1, %edx
  29. movl -16(%ebp), %eax
  30. sbbl %edx, %edx
  31. notl %edx
  32. andl \$4, %edx
  33. addl %eax, %edx
  34. movl %esi, %eax
  35. leal 1(%ebx), %ecx
  36. sall %cl, %eax
  37. movl %ecx, (%edx)
  38. movl %eax, %ecx
  39. andl %edi, %ecx
  40. cmpl \$1, %ecx
  41. sbbl %eax, %eax
  42. notl %eax
  43. andl \$4, %eax
  44. addl %eax, %edx
  45. movl %esi, %eax
  46. leal 2(%ebx), %ecx
  47. sall %cl, %eax
  48. movl %ecx, (%edx)
  49. movl %eax, %ecx
  50. andl %edi, %ecx
  51. cmpl \$1, %ecx
  52. sbbl %eax, %eax
  53. notl %eax
  54. andl \$4, %eax
  55. addl %eax, %edx
  56. movl %esi, %eax
  57. leal 3(%ebx), %ecx
  58. sall %cl, %eax
  59. movl %ecx, (%edx)
  60. movl %eax, %ecx
  61. andl %edi, %ecx
  62. cmpl \$1, %ecx
  63. sbbl %eax, %eax
  64. notl %eax
  65. andl \$4, %eax
  66. addl %eax, %edx
  67. movl %esi, %eax
  68. leal 4(%ebx), %ecx
  69. sall %cl, %eax
  70. movl %ecx, (%edx)
  71. movl %eax, %ecx
  72. andl %edi, %ecx
  73. cmpl \$1, %ecx
  74. sbbl %eax, %eax
  75. notl %eax
  76. andl \$4, %eax
  77. addl %eax, %edx
  78. movl %esi, %eax
  79. leal 5(%ebx), %ecx
  80. sall %cl, %eax
  81. movl %ecx, (%edx)
  82. movl %eax, %ecx
  83. andl %edi, %ecx
  84. cmpl \$1, %ecx
  85. sbbl %eax, %eax
  86. notl %eax
  87. andl \$4, %eax
  88. addl %eax, %edx
  89. movl %esi, %eax
  90. leal 6(%ebx), %ecx
  91. sall %cl, %eax
  92. movl %ecx, (%edx)
  93. movl %eax, %ecx
  94. andl %edi, %ecx
  95. cmpl \$1, %ecx
  96. sbbl %eax, %eax
  97. notl %eax
  98. andl \$4, %eax
  99. addl %eax, %edx
  100. movl %esi, %eax
  101. leal 7(%ebx), %ecx
  102. sall %cl, %eax
  103. movl %ecx, (%edx)
  104. movl %eax, %ecx
  105. andl %edi, %ecx
  106. cmpl \$1, %ecx
  107. sbbl %ecx, %ecx
  108. addl \$8, %ebx
  109. notl %ecx
  110. andl \$4, %ecx
  111. cmpl \$32, %ebx
  112. leal (%edx,%ecx), %eax
  113. movl %eax, -16(%ebp)
  114. jne .L20
  115. movl 12(%ebp), %ecx
  116. subl %ecx, -16(%ebp)
  117. sarl \$2, -16(%ebp)
  118. movl -16(%ebp), %eax
  119. popl %edx
  120. popl %ebx
  121. popl %esi
  122. popl %edi
  123. popl %ebp
  124. ret
复制代码
gxqcn: 刚才对上述代码进行了重新排版, 1、将所有的美元符前添加“\”,以防止误解析为数学公式 2、将所有的Tab符替换成四个空格,并适当删减空格使之对齐
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-4 09:18:43 | 显示全部楼层
好像上面编译器展开的代码有点问题,看不大懂,还是直接用手工展开的代码吧:
  1. #define STORE(i) *p=i; \
  2. p+=(code&(1<<i))!=0;
  3. unsigned find(unsigned code, int index[33])
  4. {
  5. int i;
  6. int *p=index;
  7. STORE(0)
  8. STORE(1)
  9. STORE(2)
  10. STORE(3)
  11. STORE(4)
  12. STORE(5)
  13. STORE(6)
  14. STORE(7)
  15. STORE(8)
  16. STORE(9)
  17. STORE(10)
  18. STORE(11)
  19. STORE(12)
  20. STORE(13)
  21. STORE(14)
  22. STORE(15)
  23. STORE(16)
  24. STORE(17)
  25. STORE(18)
  26. STORE(19)
  27. STORE(20)
  28. STORE(21)
  29. STORE(22)
  30. STORE(23)
  31. STORE(24)
  32. STORE(25)
  33. STORE(26)
  34. STORE(27)
  35. STORE(28)
  36. STORE(29)
  37. STORE(30)
  38. STORE(31)
  39. *p=-1;
  40. return p-index;
  41. }
复制代码
对应gcc编译汇编代码为:
  1. find:
  2. pushl %ebp
  3. movl %esp, %ebp
  4. movl 8(%ebp), %eax
  5. pushl %ebx
  6. movl 12(%ebp), %ebx
  7. movl %eax, %edx
  8. movl %eax, %ecx
  9. andl \$2, %edx
  10. andl \$1, %ecx
  11. cmpl \$1, %edx
  12. sbbl %edx, %edx
  13. notl %edx
  14. leal (%ebx,%ecx,4), %ecx
  15. andl \$4, %edx
  16. movl \$0, (%ebx)
  17. addl %ecx, %edx
  18. movl \$1, (%ecx)
  19. movl %eax, %ecx
  20. andl \$4, %ecx
  21. movl \$2, (%edx)
  22. addl %ecx, %edx
  23. movl %eax, %ecx
  24. andl \$8, %ecx
  25. cmpl \$1, %ecx
  26. sbbl %ecx, %ecx
  27. notl %ecx
  28. andl \$4, %ecx
  29. movl \$3, (%edx)
  30. addl %edx, %ecx
  31. movl %eax, %edx
  32. andl \$16, %edx
  33. cmpl \$1, %edx
  34. sbbl %edx, %edx
  35. notl %edx
  36. andl \$4, %edx
  37. movl \$4, (%ecx)
  38. addl %ecx, %edx
  39. movl %eax, %ecx
  40. andl \$32, %ecx
  41. cmpl \$1, %ecx
  42. sbbl %ecx, %ecx
  43. notl %ecx
  44. andl \$4, %ecx
  45. movl \$5, (%edx)
  46. addl %edx, %ecx
  47. movl %eax, %edx
  48. andl \$64, %edx
  49. cmpl \$1, %edx
  50. sbbl %edx, %edx
  51. notl %edx
  52. andl \$4, %edx
  53. movl \$6, (%ecx)
  54. addl %ecx, %edx
  55. movb %al, %cl
  56. andb \$-128, %cl
  57. cmpb \$1, %cl
  58. sbbl %ecx, %ecx
  59. notl %ecx
  60. andl \$4, %ecx
  61. movl \$7, (%edx)
  62. addl %edx, %ecx
  63. movl %eax, %edx
  64. andl \$256, %edx
  65. cmpl \$1, %edx
  66. sbbl %edx, %edx
  67. notl %edx
  68. andl \$4, %edx
  69. movl \$8, (%ecx)
  70. addl %ecx, %edx
  71. movl %eax, %ecx
  72. andl \$512, %ecx
  73. cmpl \$1, %ecx
  74. sbbl %ecx, %ecx
  75. notl %ecx
  76. andl \$4, %ecx
  77. movl \$9, (%edx)
  78. addl %edx, %ecx
  79. movl %eax, %edx
  80. andl \$1024, %edx
  81. cmpl \$1, %edx
  82. sbbl %edx, %edx
  83. notl %edx
  84. andl \$4, %edx
  85. movl \$10, (%ecx)
  86. addl %ecx, %edx
  87. movl %eax, %ecx
  88. andl \$2048, %ecx
  89. cmpl \$1, %ecx
  90. sbbl %ecx, %ecx
  91. notl %ecx
  92. andl \$4, %ecx
  93. movl \$11, (%edx)
  94. addl %edx, %ecx
  95. movl %eax, %edx
  96. andl \$4096, %edx
  97. cmpl \$1, %edx
  98. sbbl %edx, %edx
  99. notl %edx
  100. andl \$4, %edx
  101. movl \$12, (%ecx)
  102. addl %ecx, %edx
  103. movl %eax, %ecx
  104. andl \$8192, %ecx
  105. cmpl \$1, %ecx
  106. sbbl %ecx, %ecx
  107. notl %ecx
  108. andl \$4, %ecx
  109. movl \$13, (%edx)
  110. addl %edx, %ecx
  111. movl %eax, %edx
  112. andl \$16384, %edx
  113. cmpl \$1, %edx
  114. sbbl %edx, %edx
  115. notl %edx
  116. andl \$4, %edx
  117. movl \$14, (%ecx)
  118. addl %ecx, %edx
  119. movl %eax, %ecx
  120. andl \$32768, %ecx
  121. cmpw \$1, %cx
  122. sbbl %ecx, %ecx
  123. notl %ecx
  124. andl \$4, %ecx
  125. movl \$15, (%edx)
  126. addl %edx, %ecx
  127. movl %eax, %edx
  128. andl \$65536, %edx
  129. cmpl \$1, %edx
  130. sbbl %edx, %edx
  131. notl %edx
  132. andl \$4, %edx
  133. movl \$16, (%ecx)
  134. addl %ecx, %edx
  135. movl %eax, %ecx
  136. andl \$131072, %ecx
  137. cmpl \$1, %ecx
  138. sbbl %ecx, %ecx
  139. notl %ecx
  140. andl \$4, %ecx
  141. movl \$17, (%edx)
  142. addl %edx, %ecx
  143. movl %eax, %edx
  144. andl \$262144, %edx
  145. cmpl \$1, %edx
  146. sbbl %edx, %edx
  147. notl %edx
  148. andl \$4, %edx
  149. movl \$18, (%ecx)
  150. addl %ecx, %edx
  151. movl %eax, %ecx
  152. andl \$524288, %ecx
  153. cmpl \$1, %ecx
  154. sbbl %ecx, %ecx
  155. notl %ecx
  156. andl \$4, %ecx
  157. movl \$19, (%edx)
  158. addl %edx, %ecx
  159. movl %eax, %edx
  160. andl \$1048576, %edx
  161. cmpl \$1, %edx
  162. sbbl %edx, %edx
  163. notl %edx
  164. andl \$4, %edx
  165. movl \$20, (%ecx)
  166. addl %ecx, %edx
  167. movl %eax, %ecx
  168. andl \$2097152, %ecx
  169. cmpl \$1, %ecx
  170. sbbl %ecx, %ecx
  171. notl %ecx
  172. andl \$4, %ecx
  173. movl \$21, (%edx)
  174. addl %edx, %ecx
  175. movl %eax, %edx
  176. andl \$4194304, %edx
  177. cmpl \$1, %edx
  178. sbbl %edx, %edx
  179. notl %edx
  180. andl \$4, %edx
  181. movl \$22, (%ecx)
  182. addl %ecx, %edx
  183. movl %eax, %ecx
  184. andl \$8388608, %ecx
  185. cmpl \$1, %ecx
  186. sbbl %ecx, %ecx
  187. notl %ecx
  188. andl \$4, %ecx
  189. movl \$23, (%edx)
  190. addl %edx, %ecx
  191. movl %eax, %edx
  192. andl \$16777216, %edx
  193. cmpl \$1, %edx
  194. sbbl %edx, %edx
  195. notl %edx
  196. andl \$4, %edx
  197. movl \$24, (%ecx)
  198. addl %ecx, %edx
  199. movl %eax, %ecx
  200. andl \$33554432, %ecx
  201. cmpl \$1, %ecx
  202. sbbl %ecx, %ecx
  203. notl %ecx
  204. andl \$4, %ecx
  205. movl \$25, (%edx)
  206. addl %edx, %ecx
  207. movl %eax, %edx
  208. andl \$67108864, %edx
  209. cmpl \$1, %edx
  210. sbbl %edx, %edx
  211. notl %edx
  212. andl \$4, %edx
  213. addl %ecx, %edx
  214. movl \$26, (%ecx)
  215. movl %eax, %ecx
  216. andl \$134217728, %ecx
  217. cmpl \$1, %ecx
  218. sbbl %ecx, %ecx
  219. notl %ecx
  220. andl \$4, %ecx
  221. addl %edx, %ecx
  222. movl \$27, (%edx)
  223. movl %eax, %edx
  224. andl \$268435456, %edx
  225. cmpl \$1, %edx
  226. sbbl %edx, %edx
  227. notl %edx
  228. andl \$4, %edx
  229. addl %ecx, %edx
  230. movl \$28, (%ecx)
  231. movl %eax, %ecx
  232. andl \$536870912, %ecx
  233. cmpl \$1, %ecx
  234. sbbl %ecx, %ecx
  235. notl %ecx
  236. andl \$4, %ecx
  237. movl \$29, (%edx)
  238. addl %edx, %ecx
  239. movl %eax, %edx
  240. andl \$1073741824, %edx
  241. cmpl \$1, %edx
  242. sbbl %edx, %edx
  243. notl %edx
  244. andl \$4, %edx
  245. sarl \$31, %eax
  246. addl %ecx, %edx
  247. andl \$4, %eax
  248. addl %edx, %eax
  249. movl \$30, (%ecx)
  250. movl \$31, (%edx)
  251. movl \$-1, (%eax)
  252. subl %ebx, %eax
  253. popl %ebx
  254. sarl \$2, %eax
  255. popl %ebp
  256. ret
复制代码
对应
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-4 09:33:54 | 显示全部楼层
注意:我对16#、17#帖子进行过编辑排版。 似乎楼上的汇编指令数比我那版多了不少。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-4 09:54:31 | 显示全部楼层
指令数目并不说明任何问题,我觉得编译器这么选择应该有其理由,毕竟这种细节问题人通常没有编译器考虑得好
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-10 10:06:37 | 显示全部楼层
总感觉不对劲 终于觉醒了 似乎我是测试的1000万, 你们测试的是100万 把GXQ代码和我代码聚集在一起 终于比较出来了 还是我的快 我冤啊 FindBits.rar (8.41 KB, 下载次数: 1)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-24 10:07 , Processed in 0.027018 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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