2006年12月6日

Compiling program targeting 32 bit on linux X86-64

沒想到,第二篇文章會這麼久時間才出來,懶惰的個性要改啊-.- 。

今天因為無聊,想在實驗室的電腦上跑一些程式,才發現有很大的問題。因為實驗室機器是安裝Ubnutu 6.06 X86-64版,gcc預設產生x86-64,glibc則是64位元版,更不用說其他的函式庫了。

直接將程式移植到64位元或許會省掉一些編譯上的麻煩,但是可能會有其他的問題產生,就拿我測試的程式(好吧,就是phoneME Advanced)來說好了,他包含了一些必要的組語檔案,這部份可能要以64位元的規範重新改寫。另外也不確定是否對於平台的data type有無任何假設(e.g long是32 bits, long long則是64 bits)。這些工作我暫時沒什麼興趣去作。

因此,方向就變成搞定編譯方式,經過一番google,檢閱許多不甚清楚的討論外加嘗試錯誤後,終於搞定。步驟如下:

1. 安裝32位元程式庫
apt-get install lib32gcc1 lib32stdc++6 libc6-i386 libc6-dev-i386 ia32-libs
可以看需求再安裝lib32xxx以及ia32-libs-xxx的套件

2. 修改編譯參數
以phoneME Advanced為例:
修改build/linux-x86-generic/GNUmakefile,在ASM_ARCH_FLAGSCC_ARCH_FLAGS之後加上-m32要求GCC產生32位元的程式碼。然後在LINK_ARCH_FLAGS加上-m32 -L/usr/lib32指示linker把輸入通通看成32位元(預設是64位元),並從/usr/lib32搜尋需要的函式庫,linker會去預設目錄(/usr/lib:/usr/lib32)搜尋32位元的shared library。

3. 編譯收工

這樣就可以編出可以執行的32位元版本囉,只是好像速度會比較慢喔?我只簡單的和64位元版的JamVM比較過。就我之前的經驗,JamVM本來就比較快,可是不會差很多。但64位元版的jamvm和32位元版的cvm(就是phoneME Advanced啦)速度卻差了不少。我猜想這和64位元的linux怎麼去執行32位元的程式有關吧,需要再做一些survey。

事實上是因為,之前CVM測試的編譯組態不盡相同,在x86上必須設CVM_INTERPRETER_LOOP=Split,將interpreter設定由兩個分開的小interpreter組成,分別直譯不同的bytecode。主要的好處就是減少register pressure、增進instruction cache的locality。效能可以增加不少,但是會帶來一些壞處(X86 JIT的速度會大幅下降,原因不明)。如果只看interpreter的效能,還是比不上JamVM,主要差別來自於JamVM實做了direct threaded dispatch等技術(有空再來介紹吧)。

另外,根據Wikipedia這篇這篇,64位元程式還有可能的優勢:
  1. 多了8個一般register及8個floating point register可用
  2. RIP addressing mode可以加速shared library的連結
  3. 較好的ABI(可用register傳遞參數)
  4. 較大的定址空間
目前來看,64位元的JamVM的確比32位元的JamVM快不少(尚未精確量測),值得玩味的是,在i386下因為register pressure所以預設關閉的stack caching,在x86-64下開啟後效能同樣會變差,即使多了不少register?

沒有留言:

張貼留言