无心人
发表于 2008-3-27 13:39:04
想到一个节约指令的拆解方法
假设数据在mm0
mm7=0
movq mm1, mm0
punpckhdq mm1, mm7
punpckldq mm0, mm7
则分解mm0=mm1:mm0
无心人
发表于 2008-3-27 14:46:54
void UInt128x128To256_SSE2_92F( UINT32 * const result,
const UINT32 * const left,
const UINT32 * const right )
{
__asm
{
mov eax,
mov edx,
mov ecx,
movd mm0,
pmuludq mm0, //mm0 = 0:0
pxor mm7, mm7 //mm7 = 0
movd , mm0
punpckhdq mm0, mm7
movd mm1,
pmuludq mm1, //mm1=0:1
movd mm2,
pmuludq mm2, //mm2=1:0
movq mm3, mm1
punpckhdq mm3, mm7
punpckldq mm1, mm7
movq mm4, mm2
punpckhdq mm4, mm7
punpckldq mm2, mm7
paddq mm0, mm1
paddq mm0, mm2
paddq mm3, mm4
movd , mm0
punpckhdq mm0, mm7
paddq mm0, mm3
movd mm1,
pmuludq mm1, //mm1=1:1
movd mm2,
pmuludq mm2, //mm2=0:2
movd mm3,
pmuludq mm3, //mm3=2:0
movq mm4, mm1
punpckhdq mm4, mm7
punpckldq mm1, mm7
movq mm5, mm2
punpckhdq mm5, mm7
punpckldq mm2, mm7
movq mm6, mm3
punpckhdq mm6, mm7
punpckldq mm3, mm7
paddq mm0, mm1
paddq mm4, mm5
paddq mm0, mm2
paddq mm4, mm6
paddq mm0, mm3
movd , mm0
punpckhdq mm0, mm7
paddq mm0, mm4
movd mm1,
pmuludq mm1, //mm1=0:3
movd mm2,
pmuludq mm2, //mm2=3:0
movq mm4, mm1
punpckhdq mm4, mm7
punpckldq mm1, mm7
movq mm5, mm2
punpckhdq mm5, mm7
punpckldq mm2, mm7
paddq mm0, mm1
paddq mm4, mm5
paddq mm0, mm2
movd mm1,
pmuludq mm1, //mm1=1:2
movd mm2,
pmuludq mm2, //mm2=2:1
movq mm5, mm1
punpckhdq mm5, mm7
punpckldq mm1, mm7
movq mm6, mm2
punpckhdq mm6, mm7
punpckldq mm2, mm7
paddq mm0, mm1
paddq mm4, mm5
paddq mm0, mm2
paddq mm4, mm6
movd , mm0
punpckhdq mm0, mm7
paddq mm0, mm4
movd mm1,
pmuludq mm1, //mm1=2:2
movd mm2,
pmuludq mm2, //mm2=1:3
movd mm3,
pmuludq mm3, //mm3=3:1
movq mm4, mm1
punpckhdq mm4, mm7
punpckldq mm1, mm7
movq mm5, mm2
punpckhdq mm5, mm7
punpckldq mm2, mm7
movq mm6, mm3
punpckhdq mm6, mm7
punpckldq mm3, mm7
paddq mm0, mm1
paddq mm4, mm5
paddq mm0, mm2
paddq mm4, mm6
paddq mm0, mm3
movd , mm0
punpckhdq mm0, mm7
paddq mm0, mm4
movd mm1,
pmuludq mm1, //mm1=2:3
movd mm2,
pmuludq mm2, //mm2=3:2
movq mm3, mm1
punpckhdq mm3, mm7
punpckldq mm1, mm7
movq mm4, mm2
punpckhdq mm4, mm7
punpckldq mm2, mm7
paddq mm0, mm1
paddq mm0, mm2
paddq mm3, mm4
movd , mm0
punpckhdq mm0, mm7
paddq mm0, mm3
movd mm1,
pmuludq mm1,
paddq mm0, mm1
movq , mm0
emms
}
}
时间不理想
无心人
发表于 2008-3-27 21:32:25
76有问题
movq , mm5
psrlq mm5, 32 //carry
//------保存最高DWORD
movq , mm5 //mm3,中间结果
=================================
就是movq,mm5
不知道后面两条啥意思?
另外最后一条应该是movd 如果写movq 存在内存溢出危险
liangbch
发表于 2008-3-27 22:30:59
完全采用SSE2指令的一个版本,指令数110条,比预期的指令少要多,仅仅比76楼少一条指令。这个版本全部使用XMM寄存器。解包主要采用pshufd指令来实现。尽管指令数不多,但却比采用我的另一个使用MMX寄存器的版本慢上好多(在PIV 2.6G上测试的结果).
个人感觉,一次计算2组 32bit * 32bit 的SSE2指令并没有带来多大收益,就这个题目而言,使用MMX寄存器可能是一个好的选择。下面是完整的源代码。_declspec(naked)
void UInt128x128To256_SSE2_94F( UINT32 * const result,
const UINT32 * const left,
const UINT32 * const right )
// 使用XMM寄存器
// 16次乘法,分4趟,
// 操作数一律在xmm 寄存器中进行,每次乘法 计算2 组 32bit * 32 bit 乘法,每次加法 仅仅使用低64bit
// 第1趟计算 left[] * right
// 第2趟计算 left[] * right
// 第3趟计算 left[] * right
// 第4趟计算 left[] * right
// 每趟的计算结果为 5 DWORD,最低位DWORD 直接存储到result, 前3趟的计算结果的高4个DWORD(中间结果)存储到一组寄存器
// 寄存器的使用
// 1. 中间结果 放入 xmm0,xmm1,xmm2,xmm3
// 2。乘数使用 xmm4
// 2. 乘积1 使用 xmm5
// 3. 乘积2 使用 xmm6
// 4. 进位使用 xmm7
// 5. 掩码依然使用xmm5, 和 乘积1 分时复用
// 可以看到8个mmx寄存器全部派上用场
{
#define LEFT_REG eax
#define RIGHT_REG edx
#define RESULT_REG ecx
#define T0_REG xmm0
#define T1_REG xmm1
#define T2_REG xmm2
#define T3_REG xmm3
#undefMUL_REG
#define MUL_REG xmm4
#undefMASK_REG
#define MASK_REG xmm5
#define PROD_1_REG xmm5
#define PROD_2_REG xmm6
#define CARRY_REG xmm7
//记号 XX00, 表示当前 128bit 寄存器的 值状态,每个字符表示32bit, X表示有数,0表示这部分为0
// 第1个字符bit0-bit31,第2个表示bit32-bit63,
// 第3个字符bit64-bit95, 最后1个字符表示bit96-bit127
//D0: 表示寄存器的 bit0-bit31
//D1: 表示寄存器的 bit32-bit63,
//D2: 表示寄存器的 bit64-bit95,
//D3: 表示寄存器的 bit96-bit127
// -〉表示传送
__asm
{
mov RIGHT_REG, dword ptr ;right
mov LEFT_REG,dword ptr ; left
mov RESULT_REG, dword ptr ; result
push ebx
mov ebx,0xffffffff //置掩码,用来清除高位,仅仅保留低32bit
//第1趟乘开始---
movq MUL_REG,qword ptr
pshufd MUL_REG,MUL_REG, 01000100b // R -> 0:3, R -> 2:4
movdqu PROD_1_REG, // 将4个DWORD一次载入
pshufd PROD_2_REG, PROD_1_REG, 00110010b // L -> PROD_2_REG
pshufd PROD_1_REG, PROD_1_REG, 11011100b // L -> PROD_1_REG
//-------- 第1,2次乘
pmuludq PROD_1_REG, MUL_REG // L * R,XXXX
movd ,PROD_1_REG // store low32 bit of L0 * R
psrldq PROD_1_REG, 4 // PROD_1_REG >>= 32, high 32 bit is full zero,shape XXX0
pshufd CARRY_REG, PROD_1_REG, 11111100b // 将carry分解出来, X0000
psrldq PROD_1_REG, 4 // PROD_1_REG:= L1*R,RROD_1_REG: XX00
paddq PROD_1_REG, CARRY_REG // PROD_1_REG:= L1 * R + carry, RROD_1_REG: XX00
//----插入第3,4次乘指令
pmuludq PROD_2_REG, MUL_REG //PROD_2_REG:= L * R,PROD_2_REG:XXXX
pshufd T0_REG, PROD_1_REG, 11111100b // T0= L1 * R, T0_REG: X0000
pshufd CARRY_REG, PROD_1_REG, 11111101b // high 32bit ofL1 * R -->carry, carry,X0000
movd MASK_REG, ebx
paddq PROD_2_REG, CARRY_REG // PROD_2_REG +=carry, PROD_2_REG:XXXX
movdqa T1_REG, PROD_2_REG // T1= L2 * RO,T1_REG: XXXX
psrldq PROD_2_REG, 4 // PROD_2_REG:XXX0
pand T1_REG, MASK_REG //T1_REG: X0000
pshufd CARRY_REG, PROD_2_REG, 11111100b // 将carry分解出来, CARRY_REG:X0000
psrldq PROD_2_REG, 4 // PROD_2_REG = L3 *R, PROD_2_REG:XX00
paddq PROD_2_REG, CARRY_REG // PROD_2_REG = L3 *R + carry, PROD_2_REG:XX00
pshufd T2_REG, PROD_2_REG, 11111100b // PROD_2_REG:D0 -> T2, T2:X0000
pshufd T3_REG, PROD_2_REG, 11111101b // PROD_2_REG:D0 -> T3, T3 :X0000
//----第二趟乘开始
psrldq MUL_REG, 4
movdqu PROD_1_REG, // 将4个DWORD一次载入
pshufd PROD_2_REG, PROD_1_REG, 00110010b // L -> PROD_2_REG
pshufd PROD_1_REG, PROD_1_REG, 11011100b // L -> PROD_1_REG
// 第5,6次乘
pmuludq PROD_1_REG, MUL_REG //L * R,PROD_1_REG:XXXX
paddq PROD_1_REG, T0_REG //L * R +t0, PROD_1_REG:XXXX
movd ,PROD_1_REG // PROD_1_REG:D0 -> result
psrldq PROD_1_REG, 4 // PROD_1_REG >>= 32, PROD_1_REG: XXX0
pshufd CARRY_REG, PROD_1_REG, 11111100b // 将carry分解出来,PROD_1_REG:D0-> carry
psrldq PROD_1_REG, 4 // PROD_1_REG>>32, PROD_1_REG: XX00
paddq PROD_1_REG, CARRY_REG // PROD_1_REG += carry, PROD_1_REG:XX00
paddq PROD_1_REG, T1_REG // PROD_1_REG += T1, PROD_1_REG:XX00
//- 插入第7,8次乘指令
pmuludq PROD_2_REG, MUL_REG // L * R, PROD_2_REG:XXXX
pshufd T0_REG, PROD_1_REG, 11111100b // PROD_1_REG:D0 -> T0, T0:X000
pshufd CARRY_REG, PROD_1_REG, 11111101b // PROD_1_REG:D1 -> carry, carry:X000
movd MASK_REG, ebx
paddq PROD_2_REG, CARRY_REG // PROD_2_REG +=carry
paddq PROD_2_REG, T2_REG // PROD_2_REG += T2, PROD_2_REG:XX00
movdqa T1_REG, PROD_2_REG // PROD_2_REG -> T1, T1:XXXX
psrldq PROD_2_REG, 4 //PROD_2_REG: XXX0
pand T1_REG, MASK_REG //T1:X000
pshufd CARRY_REG, PROD_2_REG, 11111100b // 将carry分解出来, carry:X0000
psrldq PROD_2_REG, 4 // PROD_2_REG>>32, PROD_2_REG: XX00
paddq PROD_2_REG, CARRY_REG // PROD_2_REG += carry, PROD_2_REG:XX00
paddq PROD_2_REG, T3_REG // PROD_2_REG += T3, PROD_2_REG:XX00
pshufd T2_REG, PROD_2_REG, 11111100b //PROD_2_REG:D0 -> T2, T2:X000
pshufd T3_REG, PROD_2_REG, 11111101b //PROD_2_REG:D1 -> T3, T3:X000
//第3趟乘开始 -
movq MUL_REG,qword ptr
pshufd MUL_REG,MUL_REG, 01000100b // R -> 0:3, R -> 2:4
movdqu PROD_1_REG, // 将4个DWORD一次载入
pshufd PROD_2_REG, PROD_1_REG, 00110010b // L -> PROD_2_REG
pshufd PROD_1_REG, PROD_1_REG, 11011100b // L -> PROD_1_REG
// 第9,10 次乘
pmuludq PROD_1_REG, MUL_REG // L * R,PROD_1_REG:XXXX
paddq PROD_1_REG, T0_REG // L * R + t0, PROD_1_REG:XXXX
movd ,PROD_1_REG // PROD_1_REG:D0 -> result
psrldq PROD_1_REG, 4 // PROD_1_REG >>= 32, PROD_1_REG: XXX0
pshufd CARRY_REG, PROD_1_REG, 11111100b // 将carry分解出来,PROD_1_REG:D0-> carry
psrldq PROD_1_REG, 4 // PROD_1_REG: XX00
paddq PROD_1_REG, CARRY_REG // PROD_1_REG += carry, PROD_1_REG:XX00
paddq PROD_1_REG, T1_REG // PROD_1_REG += T1, PROD_1_REG:XX00
//- 插入第11,12次乘指令
pmuludq PROD_2_REG, MUL_REG // L * R, PROD_2_REG:XXXX
pshufd T0_REG, PROD_1_REG, 11111100b // PROD_1_REG:D0 -> T0, T0:X000
pshufd CARRY_REG, PROD_1_REG, 11111101b // PROD_1_REG:D1 -> carry, carry:X000
movd MASK_REG, ebx
paddq PROD_2_REG, CARRY_REG // PROD_2_REG += carry
paddq PROD_2_REG, T2_REG // PROD_1_REG += T2, PROD_1_REG:XX00
movdqa T1_REG, PROD_2_REG // PROD_2_REG -> T1, T1:XXXX
psrldq PROD_2_REG, 4 // PROD_2_REG>>32,PROD_2_REG: XXX0
pand T1_REG, MASK_REG // T1:X000
pshufd CARRY_REG, PROD_2_REG, 11111100b // 将carry分解出来, carry:X0000
psrldq PROD_2_REG, 4 // PROD_2_REG>>32, PROD_2_REG: XX00
paddq PROD_2_REG, CARRY_REG // PROD_2_REG += carry, PROD_2_REG:XX00
paddq PROD_2_REG, T3_REG // PROD_2_REG += T3, PROD_2_REG:XX00
pshufd T2_REG, PROD_2_REG, 11111100b //PROD_2_REG:D0 -> T2, T2:X000
pshufd T3_REG, PROD_2_REG, 11111101b //PROD_2_REG:D1 -> T3, T3:X000
// 第4 趟乘开始 -
psrldq MUL_REG, 4 //
movdqu PROD_1_REG, // 将4个DWORD一次载入
pshufd PROD_2_REG, PROD_1_REG, 00110010b // L -> PROD_2_REG
pshufd PROD_1_REG, PROD_1_REG, 11011100b // L -> PROD_1_REG
// 第13,14 次乘
pmuludq PROD_1_REG, MUL_REG //L * R,PROD_1_REG:XXXX
paddq PROD_1_REG, T0_REG //L * R+t0, PROD_1_REG:XXXX
movd ,PROD_1_REG // PROD_1_REG:D0 -> result
psrldq PROD_1_REG, 4 // PROD_1_REG >>= 32, PROD_1_REG: XXX0
pshufd CARRY_REG, PROD_1_REG, 11111100b // 将carry分解出来,PROD_1_REG:D0-> carry
psrldq PROD_1_REG, 4 // PROD_1_REG>>32, PROD_1_REG: XX00
paddq PROD_1_REG, CARRY_REG // PROD_1_REG += carry, PROD_1_REG:XX00
paddq PROD_1_REG, T1_REG
//- 插入第15,16次乘指令
pmuludq PROD_2_REG, MUL_REG // L * R, PROD_2_REG:XXXX
movd , PROD_1_REG // PROD_1_REG:D0
pshufd CARRY_REG, PROD_1_REG, 11111101b // PROD_1_REG:D1 -> carry, carry:X000
paddq PROD_2_REG, CARRY_REG // PROD_2_REG +=carry
paddq PROD_2_REG, T2_REG // PROD_2_REG +=carry
movd , PROD_2_REG // PROD_2_REG -> T1, T1:XXXX
psrldq PROD_2_REG, 4 //PROD_2_REG>>32, PROD_2_REG: XXX0
pshufd CARRY_REG, PROD_2_REG, 11111100b // 将carry分解出来, carry:X0000
psrldq PROD_2_REG, 4 // PROD_2_REG>>32, PROD_2_REG: XX00
paddq PROD_2_REG, CARRY_REG // PROD_2_REG += carry, PROD_2_REG:XX00
paddq PROD_2_REG, T3_REG
movq qword ptr ,PROD_2_REG
// 恢复寄存器
pop ebx
ret
}
}
liangbch
发表于 2008-3-27 22:37:41
原帖由 无心人 于 2008-3-27 21:32 发表 http://images.5d6d.net/dz60/common/back.gif
76有问题
movq , mm5
psrlq mm5, 32 //carry
//------保存最高DWORD
...
movq 表示一次写2个DWORD(8个byte)和movdqa不同,并不需要16字节对齐。如果不是特别处理,right,left,result应为DWORD数组,一定是4字节对齐的,所以使用这条指令不会出错。
关于最后的指令,我仔细看了下,确实有问题,下面的2条指令应该删除。
“psrlq mm5, 32” 和 “movq , mm5”,如此速度更快些。
liangbch
发表于 2008-3-27 22:50:57
正如无心人所言,第76#程序有个bug,就是对result缓冲区多写了4个byte,不过结果却是正确的。修复后的版本见下,减少了2条指令,加上Emms指令,指令条数和94楼,56楼持平(110 条)。不知有谁会破了这个记录。_declspec(naked)
void UInt128x128To256_SSE2_96F( UINT32 * const result,
const UINT32 * const left,
const UINT32 * const right )
// 使用MMX寄存器, 但用SSE2指令
// 指令的使用,乘法 使用 32bit * 32bit 的MMX指令,加法使用 64 bit + 64 bit 的SSE2指令
// 16次乘法,分4趟, 操作数一律在mmx 寄存器中进行
// 第1趟计算 left[] * right
// 第2趟计算 left[] * right
// 第3趟计算 left[] * right
// 第4趟计算 left[] * right
// 每趟的计算结果为 5 DWORD,最低位DWORD 直接存储到result, 前3趟的计算结果的高4个DWORD(中间结果)存储到一组寄存器
// 寄存器的使用
// 中间结果 放入 mm0,mm1,mm2,mm3
// 掩码寄存器 mm7,用来请64位寄存器的高32bit
// 进位 寄存器 和 当前乘积寄存器 为 mm4 和 mm5,轮换使用
// 乘数 寄存器 mm6
// 可以看到8个mmx寄存器全部派上用场
{
#define LEFT_REG eax
#define RIGHT_REG edx
#define RESULT_REG ecx
#define MASK_REG mm7
#define MUL_REG mm6
__asm
{
mov eax, 0xffffffff
mov RESULT_REG, dword ptr ; result
movd MASK_REG, eax
mov RIGHT_REG, dword ptr ; right
movq MUL_REG,
mov LEFT_REG,dword ptr ; left
//--------第1次乘
movd mm4,
pmuludq mm4, MUL_REG
movd , mm4
psrlq mm4, 32 //carry
//------第2次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
movq mm0, mm5
psrlq mm5, 32 //carry
pand mm0, MASK_REG //mm0,中间结果
//------第3次乘
movd mm4,
pmuludq mm4, MUL_REG
paddq mm4, mm5 //64bit + 32 bit carry
movq mm1, mm4
psrlq mm4, 32 //carry
pand mm1, MASK_REG //mm1,中间结果
//------第4次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
movq mm2, mm5
psrlq mm5, 32 //carry
pand mm2, MASK_REG //mm2,中间结果
movq mm3, mm5 //mm3,中间结果
//----得到乘数
psrlq MUL_REG, 32 //得到right
//---第二趟乘---------
//--------第5次乘
movd mm4,
pmuludq mm4, MUL_REG
paddq mm4, mm0 // 64bit + 32 bit 中间结果
movd , mm4
psrlq mm4, 32 //carry
//------第6次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
paddq mm5, mm1 //64bit + 32 bit 中间结果
movq mm0, mm5
psrlq mm5, 32 //carry
pand mm0, MASK_REG //mm0,中间结果
//------第7次乘
movd mm4,
pmuludq mm4, MUL_REG
paddq mm4, mm5 //64bit + 32 bit carry
paddq mm4, mm2 //64bit + 32 bit 中间结果
movq mm1, mm4
psrlq mm4, 32 //carry
pand mm1, MASK_REG //mm1,中间结果
//------第8次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
paddq mm5, mm3 //64bit + 32 bit 中间结果
movq mm2, mm5
psrlq mm5, 32 //carry
pand mm2, MASK_REG //mm2,中间结果
movq mm3, mm5 //mm3,中间结果
//----得到乘数
movq MUL_REG,
//--------第9次乘
movd mm4,
pmuludq mm4, MUL_REG
paddq mm4, mm0 // 64bit + 32 bit 中间结果
movd , mm4
psrlq mm4, 32 //carry
//------第10次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
paddq mm5, mm1 //64bit + 32 bit 中间结果
movq mm0, mm5
psrlq mm5, 32 //carry
pand mm0, MASK_REG //mm0,中间结果
//------第11次乘
movd mm4,
pmuludq mm4, MUL_REG
paddq mm4, mm5 //64bit + 32 bit carry
paddq mm4, mm2 //64bit + 32 bit 中间结果
movq mm1, mm4
psrlq mm4, 32 //carry
pand mm1, MASK_REG //mm1,中间结果
//------第12次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
paddq mm5, mm3 //64bit + 32 bit 中间结果
movq mm2, mm5
psrlq mm5, 32 //carry
pand mm2, MASK_REG //mm2,中间结果
movq mm3, mm5 //mm3,中间结果
//----得到乘数
psrlq MUL_REG, 32 //得到right
//--------第13次乘
movd mm4,
pmuludq mm4, MUL_REG
paddq mm4, mm0 // 64bit + 32 bit 中间结果
movd , mm4
psrlq mm4, 32 //carry
//------第14次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
paddq mm5, mm1 //64bit + 32 bit 中间结果
movd , mm5
psrlq mm5, 32 //carry
//------第15次乘
movd mm4,
pmuludq mm4, MUL_REG
paddq mm4, mm5 //64bit + 32 bit carry
paddq mm4, mm2 //64bit + 32 bit 中间结果
movd , mm4
psrlq mm4, 32 //carry
//------第16次乘
movd mm5,
pmuludq mm5, MUL_REG
paddq mm5, mm4 //64bit + 32 bit carry
paddq mm5, mm3 //64bit + 32 bit
movq , mm5
emms
ret
}
}
无心人
发表于 2008-3-28 07:58:00
我说的并不是他指令错误
而是最后还4个字节位置
用8字节写,至少在我的VC2008肯定是抛出异常的
:)
========================================
另外,我觉得
双乘并不弱于MMX,关键在我们的指令安排可能存在问题
现在想起来,16个乘,如果每条用6个指令加结果,就至少100条了
而我想,减少每次乘法后结果的指令数是很困难的
如果仔细比较,你们会发现,这次时间已逼近你们96bit的算法的时间了
而按照比率,这次最佳时间是上次的1.5倍以上
现在是否突破了上次的1.5倍呢?
无心人
发表于 2008-3-31 11:09:15
怎么停顿了
不想讨论了么?
liangbch
发表于 2008-3-31 11:31:24
原帖由 无心人 于 2008-3-31 11:09 发表 http://images.5d6d.net/dz60/common/back.gif
怎么停顿了
不想讨论了么?
好吧, 我将编写一个完全使用X86指令(不使用任何MMX,SSE,SSE2指令的版本)的版本,再对比现在的SSE2,MMX版本,看看使用 SIMD 指令的 最高加速比是多少。
无心人
发表于 2008-3-31 11:36:15
SSE2代码似乎还存在优化可能
页:
1
2
3
4
5
6
7
8
9
[10]
11
12
13
14
15