gravatar

gcc -faltivec 的迷思

在一些大的 OSS 上很流行針對某種平台或架構作最佳化的編譯動作,像是 Firefox,以前在用 Windows,通常都會用什麼 -msse -msse2 -mcpu=pentium4 等等的選項,來編譯程式。到了 Mac OS X 也不例外,同樣也是有人提供例如 -faltivec -mcpu=7450 -mtune=7450 的編譯版本,來讓使用者盡可能發揮電腦 CPU 的運算單元,利用可以加速的輔助處理器,加快運算速度。就像 firefox 裡面有 JPEG library,DCT 可以加速等等。但是事實上是這樣嗎?我覺得並沒有,其實這些參數可能沒有幫助到什麼。

正確的說,如果 source code 裡面沒有針對這些 architectures 的個別寫出來的 code,那麼儘管加了再多這類 SIMD optimization flags,也是沒用。

舉下面這兩個 c code,

file: test.c
#include <stdio.h>
int main( void )
{
  vector float v1 = { 1., 2., 3., 4. };
  vector float v2 = { 2., 3., 4., 5. };
  vector float v3;
  v3=v1 + v2;
  printf("%vf\n", v3 );
  return 0;
}
file: test2.c
#include <stdio.h>
int main( void )
{
  float v1[4] = { 1., 2., 3., 4. };
  float v2[4] = { 2., 3., 4., 5. };
  float v3[4];
  v3[0] = v1[0] + v2[0];
  v3[1] = v1[1] + v2[1];
  v3[2] = v1[2] + v2[2];
  v3[3] = v1[3] + v2[3];
  printf("%f\n", v3[0] );
  printf("%f\n", v3[1] );
  printf("%f\n", v3[2] );
  printf("%f\n", v3[3] );
  return 0;
}
接著用 gcc 來編譯:
gcc-4.0 -faltivec -mcpu=7450 -O3 -c -S
然後可以得到 PowerPC 的組合語言輸出檔案,分別為 test.s 和 test2.s。在這邊擷取其中檔案一部份:
file: test.s
lvx v1,0,r2
addi r2,r1,64
lvx v0,0,r9
vaddfp v1,v1,v0
可以看到他把 data 載入到 vector registers 去,然後用 AltiVec 指令(v 開頭)加起來。至於 test2.s,完全是 PowerPC 指令,找不到 v 開頭的 instructions。反而要更多倍的指令來把個別的 entry 各自加起來。

假如程式像 test2.c 裡面的 pure C code,那麼加了再多的參數,也不可能讓 gcc 產生 AltiVec 的指令;除非有 directive #ifdef...#else...#endif 來額外編寫針對某種 architecture 的程式碼。所以總之,-faltivec 只是讓 gcc 認得那些額外的 syntax 像是 vector。如果不加,程式有這種寫法,gcc 便會當作未定義的型別。加了,但是程式卻沒有這種針對 vector unit/SIMD 寫法,gcc 也不會幫你產生 AltiVec 的指令來加速運算。那麼為什麼會感覺比較快呢?我的解釋為,可能加了更多針對 G4 general purpose CPU 的 optimization flags,像是 loops 處理、resource allocation、instruction schedule、frame pointer 等等吧。

Tags: , gcc, AltiVec, firefox