找回密码
 欢迎注册
查看: 63546|回复: 51

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

[复制链接]
发表于 2008-3-28 22:25:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
有两个相同长度的双字串(可先不讨论四字串加)left, right, 长度len 现求两个双字串的加法结果,所谓加法是双字串以低地址做起始表示的长二进制数字的算术加 无论汇编还是C/C++,不论是否用双字还是四字,以1024个双字做输入参数,函数执行一百万次后的时间最少为最好 函数原型 DWORD longAdd(DWORD * result, DWORD * left, DWORD * right, DWORD len); 返回值为进位结果
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-29 16:28:45 | 显示全部楼层
目前有三个方案 1、一次加一个双字 2、一次加一个四字 3、一次加多个四字
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-29 16:49:41 | 显示全部楼层
一次加一个双字的, 未调试 DWORD longAdd4(DWORD * result, DWORD * left, DWORD * right, DWORD len) { __asm { mov eax, [left] mov edx, [right] mov ebx, [result] mov ecx, [len] pxor mm0, mm0 loop1: movd mm1, [eax] add eax, 4 paddq mm0, mm1 movd mm2, [edx] paddq mm0, mm2 add edx, 4 movd [ebx], mm0 psrlq mm0, 32 add ebx, 4 sub ecx, 1 jne loop1 movd eax, mm0 emms } }
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-29 16:56:31 | 显示全部楼层
一次加一个四字的, 未调试 DWORD longAdd8(DWORD * result, DWORD * left, DWORD * right, DWORD len) { __asm { mov eax, [left] mov edx, [right] mov ebx, [result] mov ecx, [len] pxor mm0, mm0 loop1: movd mm1, [eax] movd mm3, [eax+4] add eax, 8 paddq mm0, mm1 movd mm2, [edx] movd mm4, [edx+4] add edx, 8 paddq mm0, mm2 movd [ebx], mm0 psrlq mm0, 32 paddq mm0, mm3 paddq mm0, mm4 movd [ebx+4], mm0 add ebx, 8 psrlq mm0, 32 sub ecx, 2 jne loop1 movd eax, mm0 emms } }
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-29 17:32:17 | 显示全部楼层
DWORD longAdd8(DWORD result[], DWORD left[], DWORD right[], DWORD len) { __asm { mov eax, [left] mov edx, [right] mov ebx, [result] mov ecx, [len] pxor xmm0, xmm0 loop1: movq xmm1, qword ptr [eax] pshufd xmm1, xmm1, 11011100b paddq xmm0, xmm1 add eax, 8 movq xmm2, qword ptr [edx] pshufd xmm2, xmm2, 11011100b paddq xmm0, xmm2 add edx, 8 movd [ebx], xmm0 psrldq xmm0, 4 pshufd xmm1, xmm0, 11111001b psrldq xmm0, 4 paddq xmm0, xmm1 movd [ebx+4], xmm0 add ebx, 8 psrldq xmm0, 4 sub ecx, 2 jne loop1 movd eax, xmm0 } } longAdd4 1024+1024 执行100万次 3.208s 约6.2时钟周期/双字 P4 XEON 2.0 //加法改XMM寄存器则时间会增大到200% //一次加两个也不好,时间稍微增加 //如上面用XMM加两个,还不如用XMM一次加一个 //不知大家有什么一次加多个双字的好算法
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-29 22:11:41 | 显示全部楼层
有时间测试下面指令少的 DWORD longAdd4(DWORD * result, DWORD * left, DWORD * right, DWORD len) { __asm { xor ecx, ecx pxor mm0, mm0 loop1: movd mm1, left[4*ecx] paddq mm0, mm1 movd mm2, right[4*ecx] paddq mm0, mm2 movd result[4*ecx], mm0 psrlq mm0, 32 add ecx, 1 cmp ecx, [len] jne loop1 movd eax, mm0 emms } }
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-31 08:13:13 | 显示全部楼层
DWORD longAdd4s(DWORD result[], DWORD left[], DWORD right[], DWORD len) { __asm { mov eax, [left] mov edx, [right] mov ebx, [result] xor ecx, ecx pxor mm0, mm0 loop1: movd mm1, dword ptr [eax + 4*ecx] paddq mm0, mm1 movd mm2, dword ptr [edx + 4*ecx] paddq mm0, mm2 movd dword ptr [ebx + 4*ecx], mm0 psrlq mm0, 32 add ecx, 1 cmp ecx, [len] jb loop1 movd eax, mm0 emms } } 同时宣布楼上代码作废 此代码时间稍微比三楼的longAdd4长一点点 证明直接使用一个寄存器保存的地址访问是最快的
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-3-31 14:20:17 | 显示全部楼层
DWORD longAdd4c(DWORD result[], DWORD left[], DWORD right[], DWORD len) { __asm { mov esi, [left] mov edi, [right] mov ebx, [result] mov ecx, [len] clc xor eax, eax loop1: mov edx, [esi] add edx, [edi] adc edx, eax mov [ebx], edx xor eax, eax adc eax, 0 add esi, 4 add edi, 4 add ebx, 4 sub ecx, 1 jne loop1 } } DWORD longAdd4(DWORD result[], DWORD left[], DWORD right[], DWORD len) { __asm { mov eax, [left] mov edx, [right] mov ebx, [result] mov ecx, [len] pxor mm0, mm0 loop1: movd mm1, [eax] add eax, 4 paddq mm0, mm1 movd mm2, [edx] paddq mm0, mm2 add edx, 4 movd [ebx], mm0 psrlq mm0, 32 add ebx, 4 sub ecx, 1 jne loop1 movd eax, mm0 emms } } DWORD longAdd4s(DWORD result[], DWORD left[], DWORD right[], DWORD len) { __asm { mov eax, [left] mov edx, [right] mov ebx, [result] xor ecx, ecx pxor mm0, mm0 loop1: movd mm1, dword ptr [eax + 4*ecx] paddq mm0, mm1 movd mm2, dword ptr [edx + 4*ecx] paddq mm0, mm2 movd dword ptr [ebx + 4*ecx], mm0 psrlq mm0, 32 add ecx, 1 cmp ecx, [len] jb loop1 movd eax, mm0 emms } } 100 万次 1024*32Bit加法 4 3423ms 4s 3415ms 4c 3710ms
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2008-4-8 13:16:20 | 显示全部楼层
一次加四字 如果用 x< y: (~x&y) | ((~x|y) & (x-y)) 判断进位,因为共5个逻辑运算 则因为需要判断两次 每次指令大于5条 即可能造成最终指令条数超过一次加双字的情况 能不能通过XMM寄存器一次得到两个结果? 可以考虑
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2008-4-8 16:12:58 | 显示全部楼层
使用循环展开应该可以显著提高速度,你可以使用4路循环展开试一试。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

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

GMT+8, 2024-11-15 07:01 , Processed in 0.025821 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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