SSE2加速DCT的试验
视频压缩及解压缩,DCT是耗速大户,相对运算密集,试将运算部分由SSE2取代,以期提高运算速度。
原程序:耗时59us
void __fastcall CDCT::FDCT(double fOutPut[][8], double fInPut[][8])//正向离散余玄变换 { double tmp; int u,v,i,j; for(u = 0; u < 8; u++) { for(v = 0; v < 8; v++) { tmp = 0.0; for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) { tmp += fInPut[i][j] * C2[u][i] * C3[v][j]; } fOutPut[u][v] = C4[u][v] * tmp; } } }
替换程序:耗时140us
double double_Mul(double fD1, double fD2, double fD3)//乘 { double fRet; asm { movsd XMM0, fD1 // XMM0 <- fD1 mulsd XMM0, fD2 // fD1 = fD1 * fD2 mulsd XMM0, fD3 // fD1 = fD1 * fD3 movsd fRet, XMM0 // fRet <- XMM0 } return fRet; } void __fastcall CDCT::FDCT(double fOutPut[][8], double fInPut[][8])//正向离散余玄变换 { double tmp; int u,v,i,j; for(u = 0; u < 8; u++) { for(v = 0; v < 8; v++) { tmp = 0.0; for(i = 0; i < 8; i++) for(j = 0; j < 8; j++) { //tmp += fInPut[i][j] * C2[u][i] * C3[v][j]; tmp += double_Mul(fInPut[i][j], C2[u][i], C3[v][j]);//乘 } fOutPut[u][v] = C4[u][v] * tmp; } } }
使用SSE2竟然慢一倍多!为什么?经过多次采用不同形式的试验,虽然有改善,但谈不上提速,后来终于悟出了道理,解释如下:
1. 处理器增加了8个XMM寄存器,同FPU速度相同甚至低于FPU,XMM寄存器的优势是SIMD,如果一次处理一个数据,等同FPU处理速度,甚至不如FPU处理速度。
2. 以SIMD方式组织数据比较困难,格式要求特殊,运算特殊,程序结构容易混乱,不易使用。
3. 对于SSE2指令仅支持2个双精度浮点数,即使进行SIMD方式的2个双精度浮点数同时运算,也不一定带来一倍的提升效果,甚至不如没优化的。
4. 如果4个单精度浮点数以SIMD方式同时运算,可能有提升效果,SSE2指令支持4个单精度浮点数同时运算。
5. BCB6优化的很好,即使使用SSE2指令优化双精度浮点运算,也无济于事,可能还会弄巧成拙。
6. 当Code optimization选择Speed,DCT时提速6us。
这3天的努力是值得的,为多媒体加速爱好者提供了参考。