自動矢量化技術,是編譯器代碼優化技術的一種,即在不改變C/C++源代碼的情況下,自動編譯産生使用單指令多資料(Single Instruction Multiple Data,SIMD)指令集的二進制碼,包括MMX,SSE,SSE2,SSE3,SSSE3,SSE4,AVX,而不是程式員手動編寫彙編層次的優化代碼。
舉例如下:
float a[N], b[N], c[N];
for(int i=0; i<N; ++i)
c[i] = a[i] + b[i];
上述代碼中,逐項相加,并且a,b,c三個資料間是互相獨立的,因而編譯器可以對其進行矢量化優化,比如對于SSE指令集,XMM 128位寄存器,一次可以執行4個浮點運算,即
float a[N], b[N], c[N];
int i;
for(i=0; i<N-4; i+=4)
{
__asm
{
movups xmm0, a[i];
addps xmm0, b[i];
movups c[i], xmm0;
}
}
for(; i<N; ++i)
c[i] = a[i] + b[i];
當N較大時,如大于100,矢量優化後的執行速度提升是明顯的。
同樣,對于其它類型的數值運算,如整形和雙精度浮點數,可用類似的指令如mulps,mulpd,addpd,subps,subpd等進行優化。
當循環内部有依賴關系導緻無法優化時,編譯器将産生通用彙編代碼。
目前矢量優化技術在目前流行的編譯器上已經得到支援,如Intel C++ Compiler,GCC,預計Microsoft Visual Studio 2010也支援,并且從Microsoft Visual Studio 2008的編譯結果中發現,對于浮點操作,已經使用SSE指令movss,cvttps2dq等代替x87指令集。
當然,當循環體嵌套層次更深,循環體内實作代碼較多時,編譯器判斷循環體内是否能進行矢量優化将會比較耗時。同時,雖然支援SSE2指令集的處理器已經非常普遍,但不保證會有使用較老機器的使用者,因而在進行矢量化編譯優化時,也可選擇産生多份代碼,如同時編譯出通用彙編代碼和SIMD優化彙編代碼,運作時使用CPUID指令檢測目前CPU支援的指令集進行跳轉選擇執行。
自動矢量編譯優化技術是一個巨大的進步,并且具有更好的可移植性。這是由于編寫可移植的C/C++代碼更容易,而對于彙編底層的開發者而言,由于Intel彙編和AT&T的彙編格式大不相同,因而移植非常困難。
期待自動矢量優化的進一步發展,關注中。。。
參考文獻:
(1)I've Fallen In Love With the Vectoriser
(2)Auto-vectorization in GCC
(3)Auto-Vectorization and C++