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

[擂台] x86上128位二进制乘法最快速算法征解

[复制链接]
 楼主| 发表于 2008-3-18 14:00:51 | 显示全部楼层
共143条指令 全SSE2程序指令数必须小于该数字才有效率
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-18 14:12:09 | 显示全部楼层
运行时间高于MMX寄存器版本 指令数多16条 void UInt128x128To256_SSE2_42F( UINT32 * const result, const UINT32 * const left, const UINT32 * const right ) { //使用SSE寄存器, 用SSE2指令, 但只利用低64位 __asm { mov esi, left mov edi, right mov ebx, result //0:0 movd xmm0, dword ptr [esi] movd xmm2, dword ptr [edi] pmuludq xmm0, xmm2 movd [ebx], xmm0 psrlq xmm0, 32 // 0:1 1:0 movd xmm1, dword ptr [esi] movd xmm3, dword ptr [edi+4] pmuludq xmm1, xmm3 movd xmm2, dword ptr [edi] movd xmm4, dword ptr [esi+4] pmuludq xmm2, xmm4 mov eax, -1 //xmm0+xmm1+xmm2 paddq xmm0, xmm1//xmm0=xmm0+xmm1 xmm0肯定小于 2^64 movd xmm1, eax pand xmm1, xmm0 psrlq xmm0, 32 //分解xmm0 = xmm0:xmm1 movd xmm3, eax pand xmm3, xmm2 psrlq xmm2, 32 //分解xmm2=xmm2:xmm3 paddq xmm1, xmm3 //xmm1=xmm1+xmm3 paddq xmm0, xmm2 //xmm0=xmm0+xmm2 movd dword ptr [ebx+4], xmm1 //xmm1低位存储 psrlq xmm1, 32 //xmm1高位 paddq xmm0, xmm1 //得到进位 //1:1 0:2 2:0 movd xmm1, dword ptr [esi+4] movd xmm4, dword ptr [edi+4] pmuludq xmm1, xmm4 movd xmm2, dword ptr [esi] movd xmm5, dword ptr [edi+8] pmuludq xmm2, xmm5 movd xmm3, dword ptr [edi] movd xmm7, dword ptr [esi+8] pmuludq xmm3, xmm7 //xmm0+xmm1+xmm2+xmm3 movd xmm6, eax pand xmm6, xmm0 psrlq xmm0, 32 //分解xmm0=xmm0:xmm6 movd xmm5, eax pand xmm5, xmm1 psrlq xmm1, 32 //分解xmm1=xmm1:xmm5 paddq xmm6, xmm5 //xmm6=xmm6+xmm5 paddq xmm0, xmm1 //xmm0=xmm0+xmm1 movd xmm4, eax pand xmm4, xmm2 psrlq xmm2, 32 //分解xmm2=xmm2:xmm4 paddq xmm6, xmm4 //xmm6=xmm6+xmm4 paddq xmm0, xmm2 //xmm0=xmm0+xmm2 movd xmm7, eax pand xmm7, xmm3 psrlq xmm3, 32 //分解xmm3=xmm3:xmm7 paddq xmm6, xmm7 //xmm6=xmm6+xmm7 paddq xmm0, xmm3 //xmm0=xmm0+xmm3 movd dword ptr [ebx+8], xmm6 //xmm6低位存储 psrlq xmm6, 32 paddq xmm0, xmm6 //得到进位 //0:3 1:2 2:1 3:0 movd xmm1, dword ptr [esi] movd xmm5, dword ptr [edi+12] pmuludq xmm1, xmm5 movd xmm2, dword ptr [esi+4] movd xmm6, dword ptr [edi+8] pmuludq xmm2, xmm6 movd xmm3, dword ptr [esi+8] movd xmm7, dword ptr [edi+4] pmuludq xmm3, xmm7 movd xmm4, dword ptr [esi+12] movd xmm6, dword ptr [edi] pmuludq xmm4, xmm6 //xmm0+xmm1+xmm2+xmm3+xmm4 movd xmm5, eax pand xmm5, xmm1 psrlq xmm1, 32 //分解xmm1=xmm1:xmm5 paddq xmm0, xmm5 //xmm0=xmm0+xmm5 movd xmm6, eax pand xmm6, xmm2 psrlq xmm2, 32 //分解xmm2=xmm2:xmm6 paddq xmm0, xmm6 //xmm0=xmm0+xmm6 paddq xmm1, xmm2 //xmm1=xmm1+xmm2 movd xmm7, eax pand xmm7, xmm3 psrlq xmm3, 32 //分解xmm3=xmm3:xmm7 paddq xmm0, xmm7 //xmm0=xmm0+xmm7 paddq xmm1, xmm3 //xmm1=xmm1+xmm3 movd xmm5, eax pand xmm5, xmm4 psrlq xmm4, 32 //分解xmm4=xmm4:xmm5 paddq xmm0, xmm5 //xmm0=xmm0+xmm5 paddq xmm1, xmm4 //xmm1=xmm1+xmm4 movd dword ptr [ebx+12], xmm0 //xmm0低位存储 psrlq xmm0, 32 paddq xmm0, xmm1 //新进位 //1:3 2:2 3:1 movd xmm2, dword ptr [esi+4] movd xmm4, dword ptr [edi+12] pmuludq xmm2, xmm4 movd xmm1, dword ptr [esi+8] movd xmm5, dword ptr [edi+8] pmuludq xmm1, xmm5 movd xmm3, dword ptr [esi+12] movd xmm6, dword ptr [edi+4] pmuludq xmm3, xmm6 //xmm0+xmm1+xmm2+xmm3 movd xmm7, eax pand xmm7, xmm0 psrlq xmm0, 32 //分解xmm0=xmm0:xmm7 movd xmm6, eax pand xmm6, xmm1 psrlq xmm1, 32 //分解xmm1=xmm1:xmm6 paddq xmm7, xmm6 //xmm7=xmm7+xmm6 paddq xmm0, xmm1 //xmm0=xmm0+xmm1 movd xmm5, eax pand xmm5, xmm2 psrlq xmm2, 32 //分解xmm2=xmm2:xmm5 paddq xmm7, xmm5 //xmm7=xmm7+xmm5 paddq xmm0, xmm2 //xmm0=xmm0+xmm2 movd xmm4, eax pand xmm4, xmm3 psrlq xmm3, 32 //分解xmm3=xmm3:xmm4 paddq xmm7, xmm4 //xmm7=xmm7+xmm4 paddq xmm0, xmm3 //xmm0=xmm0+xmm3 movd dword ptr [ebx+16], xmm7 //xmm7低位存储 psrlq xmm7, 32 paddq xmm0, xmm7 //得到进位 //2:3 3:2 movd xmm1, dword ptr [esi+8] movd xmm3, dword ptr [edi+12] pmuludq xmm1, xmm3 movd xmm2, dword ptr [esi+12] movd xmm4, dword ptr [edi+8] pmuludq xmm2, xmm4 //xmm0+xmm1+xmm2 movd xmm7, eax pand xmm7, xmm0 psrlq xmm0, 32 //分解xmm0=xmm0:xmm7 movd xmm6, eax pand xmm6, xmm1 psrlq xmm1, 32 //分解xmm1=xmm1:xmm6 paddq xmm7, xmm6 //xmm7=xmm7+xmm6 paddq xmm0, xmm1 //xmm0=xmm0+xmm1 movd xmm5, eax pand xmm5, xmm2 psrlq xmm2, 32 //分解xmm2=xmm2:xmm5 paddq xmm7, xmm5 //xmm7=xmm7+xmm5 paddq xmm0, xmm2 //xmm0=xmm0+xmm2 movd dword ptr [ebx+20], xmm7 //xmm7低位存储 psrlq xmm7, 32 paddq xmm0, xmm7 //得到进位 //3:3 movd xmm1, dword ptr [esi+12] movd xmm2, dword ptr [edi+12] pmuludq xmm1, xmm2 //xmm0+xmm1 movd xmm6, eax pand xmm6, xmm0 psrlq xmm0, 32 //分解xmm0=xmm0:xmm6 movd xmm7, eax pand xmm7, xmm1 psrlq xmm1, 32 //分解xmm1=xmm1:xmm7 paddq xmm6, xmm7 //xmm6=xmm6+xmm7 paddq xmm0, xmm1 //xmm0=xmm0+xmm1 movd dword ptr [ebx+24], xmm6 //xmm6低位存储 psrlq xmm6, 32 paddq xmm0, xmm6 //进位 movd dword ptr [ebx+28], xmm0 //存储 // ret } }
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-18 14:14:25 | 显示全部楼层
1000万次 C版本 5132338 MMX版SSE2 1585527 XMM版SSE2 1753418 全SSE2双乘版暂时没写 上面两个版本还可优化 ========================== 另外 GxQ给的模板存在错误 时间单位是us而不是ms
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-18 14:26:44 | 显示全部楼层
谢谢指正错误!我晚上回家后去修正那个附件。 由于想让测试程序编译好后可在各种机台上直接运行, 所以测试模版中特意增加了指令集支持与否的自动测试。 而算法是否可被正常运行,关键是所用指令是否被支持,所以我将楼主的两个测试函数名做了修正。 在我的机器上测试结果如下:
  1. Test function: UInt128x128To256_ANSI_C32(..) 10000000 times...
  2. Elapsed time: 696.680ms
  3. FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF * FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
  4. = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE 00000000 00000000 00000000 00000001
  5. Test function: UInt128x128To256_SSE2_40F(..) 10000000 times...
  6. Elapsed time: 483.896ms
  7. FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF * FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
  8. = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE 00000000 00000000 00000000 00000001
  9. Test function: UInt128x128To256_SSE2_42F(..) 10000000 times...
  10. Elapsed time: 826.723ms
  11. FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF * FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF
  12. = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE 00000000 00000000 00000000 00000001
  13. 请按任意键继续. . .
复制代码
测试环境:Windows XP SP2,AMD Athlon 64 Processor 3200+,1GB DDR - 200MHz
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-18 14:32:49 | 显示全部楼层
嘿嘿 想把你CPU给顺来 比我这里快4倍啊 另外C版本你的快很多 编译器优化???
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-18 14:36:04 | 显示全部楼层
我没利用 _declspec(naked) 利用了是否要加 push ebp mov ebp, esp push ebx push esi push edi ...... ,,,,,, pop edi pop esi pop ebx pop ebp ret
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-18 14:39:31 | 显示全部楼层
原帖由 无心人 于 2008-3-18 14:32 发表 嘿嘿 想把你CPU给顺来 比我这里快4倍啊 另外C版本你的快很多 编译器优化???
我的编译环境是 VC6.0 + ICC10.0.027,编译选项全部为默认,未作任何优化。 在我机器上C版本快很多,估计又与 AMD 的 adc 指令较快相关。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-3-18 14:41:25 | 显示全部楼层

回复 46# 的帖子

应该是: _asm { push ebx; push ebp; push esi; push edi; //... pop edi; pop esi; pop ebp; pop ebx; ret; } 寄存器 esp 也要保持平衡。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-18 15:54:24 | 显示全部楼层
哦, 差不了三瓜俩枣的, 就不加了 我刚又看了你们的96bit的讨论 现在问你 MMX寄存器的版本和那里的比较差多少? 刚仔细搜索了SSE指令 发现感兴趣的指令全是SSE4的 我倒啊 就PSHUFD PAND PADDQ PMULUDQ几个可利用 乘加全是16位的就没32位的乘加 否则可大大简化运算
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-18 17:52:54 | 显示全部楼层
SSE2代码终于在回家前赶完,明天调试 比预想的简单 mov esi, dword ptr [left] mov edi, dword ptr [right] mov ebx, dword ptr [result] movq xmm0, qword ptr [esi] pmuludq xmm0, qword ptr [edi] pcmpeqq xmm7, xmm7 psrlq xmm7, 32 //00000000FFFFFFFF00000000FFFFFFFF movd [ebx], xmm0 //0:0结果低位保存 pshufd xmm1, qword ptr [esi], 00010000b pshufd xmm2, qword ptr [edi], 00000010b pmuludq xmm1, xmm2 //xmm1= 1:0/0:1 movq xmm4, xmm0 pshufd xmm4, xmm4, 11111101b pshufd xmm3, xmm1, 00010000b pand xmm3, xmm7 pshufd xmm2, xmm1, 00110010b pand xmm2, xmm7 paddq xmm2, xmm3 //0:1+1:0=xmm2 paddq xmm2, xmm4 psrldq xmm0, 8 //xmm0=1:1 movd [ebx+4], xmm2 psrldq xmm2, 4 pshufd xmm3, xmm2, 11111001b paddq xmm2, xmm3 //2:0 0:2 pshufd xmm4, qword ptr [esi], 00100000b pshufd xmm5, qword ptr [edi], 00000010b pmuludq xmm4, xmm5 //xmm4=2:0/0:2 movq xmm2, xmm2 //xmm2=进位 pshufd xmm3, xmm4, 00010000b pand xmm3, xmm7 pshufd xmm4, xmm4, 00110010b pand xmm4, xmm7 paddq xmm3, xmm4 //xmm3=2:0 + 0:2 xmm0=1:1 xmm2=进位 pshufd xmm0, xmm0, 11011000b paddq xmm3, xmm2 paddq xmm3, xmm0 movd [ebx+8], xmm3 psrldq xmm3, 4 pshufd xmm0, xmm3, 11111001b pshufd xmm3, xmm3, 11111100b paddq xmm0, xmm3 //xmm0=进位 //1:2 2:1 3:0 0:3 pshufd xmm1, qword ptr [esi], 00010010b pshufd xmm5, qword ptr [edi], 00100001b pmuludq xmm1, xmm5 pshufd xmm2, qword ptr [esi], 00110000b pshufd xmm6, qword ptr [edi], 00000011b pmuludq xmm2, xmm6 //xmm0进位 xmm1=1:2/2:1 xmm2=3:0/0:3 pshufd xmm3, xmm1, 00010000b pand xmm3, xmm7 pshufd xmm1, xmm1, 00110010b pand xmm1, xmm7 paddq xmm1, xmm3 pshufd xmm4, xmm2, 00010000b pand xmm4, xmm7 pshufd xmm2, xmm2, 00110010b pand xmm2, xmm7 paddq xmm2, xmm4 paddq xmm0, xmm1 paddq xmm0, xmm2 movd [ebx+12], xmm0 psrldq xmm0, 4 pshufd xmm3, xmm0, 11111001b pshufd xmm0, xmm0, 11111100b paddq xmm0, xmm3 //xmm0进位 //1:3 2:2 3:1 pshufd xmm6, [esi], 00110010b pshufd xmm5, [edi], 00110010b pmuludq xmm6, xmm5 //xmm6=3:3/2:2 pshufd xmm2, [esi], 00110001b pshufd xmm4, [edi], 00010011b pmuludq xmm2, xmm4 //xmm2=3:1/1:3 movq xmm1, xmm6 //xmm1=2:2 psrldq xmm6, 8 //xmm6=3:3 pshufd xmm3, xmm2, 00110001b pand xmm3, xmm7 pshufd xmm2, xmm2, 00010010b pand xmm2, xmm7 paddq xmm2, xmm3 pshufd xmm1, xmm1, 11011100b paddq xmm1, xmm2 paddq xmm0, xmm1 movd [ebx+16], xmm0 psrldq xmm0, 4 pshufd xmm4, xmm0, 11111001b pshufd xmm0, xmm0, 11111100b paddq xmm0, xmm4 //xmm0=进位 //2:3 3:2 pshufd xmm1, qword ptr [esi], 00100011b pshufd xmm2, qword ptr [edi], 00110010b pmuludq xmm1, xmm2 pshufd xmm3, xmm1, 00010000b pand xmm3, xmm7 pshufd xmm1, xmm1, 00110010b pand xmm1, xmm7 paddq xmm1, xmm3 paddq xmm0, xmm1 movd [ebx+20], xmm0 psrldq xmm0, 4 pshufd xmm2, xmm0, 11111001b pshufd xmm0, xmm0, 11111100b paddq xmm0, xmm2 //进位 pshufd xmm6, xmm6, 11011100b paddq xmm0, xmm6 movd [ebx+24], xmm0 psrldq xmm0, 4 pshufd xmm1, xmm0, 11111001b pshufd xmm0, xmm0, 11111100b paddq xmm0, xmm1 movd [ebx+28], xmm0
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-12-22 00:15 , Processed in 0.023948 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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