Linux on POWER 的移植指南

發表于:2007-05-25來源:作者:點擊數: 標簽:
級別: 初級 Calvin Sze Linux consultant, IBM 2005 年 7 月 04 日 要將 Linux C/C++ 程序從 x86 平臺(Intel 或 AMD)移植到 Linux on POWER 上,可以使用下面介紹的這些詳細步驟。首先,我們來了解要為這種移植準備哪些內容;然后再遵循本文介紹的實現技巧

級別: 初級

Calvin Sze
Linux consultant, IBM
2005 年 7 月 04 日

要將 Linux™ C/C++ 程序從 x86 平臺(Intel® 或 AMD)移植到 Linux on POWER™ 上,可以使用下面介紹的這些詳細步驟。首先,我們來了解要為這種移植準備哪些內容;然后再遵循本文介紹的實現技巧就可以將您的 x86 平臺的 Linux 上運行的代碼移植到 POWER 平臺上。

簡介
通常,將 Linux 程序從 x86 平臺移植到 Linux on POWER 上的過程非常簡單,因為這兩個平臺都是基于 Linux 的。實際上,大部分移植只需要對某些編譯器和鏈接器開關稍加修改并重新進行編譯即可。

然而,當一個應用程序依賴于某種特定的硬件體系結構時,通常都需要進行比較大的修改。這份移植指南會重點介紹一下 Linux on x86 和 Linux on POWER 之間的區別,并提供了一些建議,讓您可以將自己的 x86 代碼移植到 Linux on POWER 平臺上。

規劃
當您將應用程序移植到一個新的平臺上時,必須要正確地進行規劃。要對移植進行充分的準備,您應該:

  1. 注冊 IBM ®Chiphopper™ 計劃。
  2. 理解 IBM eServer® POWER 平臺的區別:POWER4™ 與 POWER5™ 之間。
  3. 確定要使用哪種 Linux for POWER 發行版:Red Hat Enterprise Linux 或 SUSE LINUX。
  4. 遷移到 GNU Make 編譯系統。
  5. 理解 x86 和 POWER 體系架構之間的區別。
  6. 確定要使用哪種編譯器:GCC(GNU Compiler Collection)或者 IBM XL C/C++ Advanced Edition for Linux。

 

這些任務都假設您的公司已經決定要將自己目前在 x86 平臺上運行的應用程序移植到 Linux on POWER 平臺上。如果您的情況并非如此,可能更想多了解一些有關 Linux on POWER 的特性和功能,那么您在閱讀本文之前,就應該先參閱一下 “Linux on POWER:開發概覽” (developerWorks,2005 年 3 月)。

注冊 Chiphopper 計劃
如果您的 Linux on x86 程序是用于商業用途的,而且代碼是使用 C/C++、Java™ 或二者混合編寫的,那么它可能就會是 IBM eServer Application Advantage™ for Linux(Chiphopper)程序的一個理想候選者。Chiphopper 提供了一些免費的工具和技術支持,可以幫助您很容易地實現 Linux on x86 上現有的程序到所有 IBM eServer 和中間件平臺的移植、測試和技術支持。這可以幫助您最大限度地把握 Linux 市場機會,同時能夠將成本控制到最低。有關 Chiphopper 計劃的更多信息,以及要確定您是否具備申請資格,請參閱 參考資料 一節的內容。

如果您的應用程序并不滿足 Chiphopper 計劃的要求,或者您希望自己進行移植,那么可以繼續閱讀下一節的內容:理解 POWER 平臺的區別。

理解 POWER 平臺的區別
要移植到的 POWER 平臺決定了可以使用哪些優化選項來編譯程序。當使用 XL C/C++ 編譯器時,這尤其重要,本文稍后就會詳細討論這個問題。

在 2004 年,IBM 發布了 POWER5 處理器,這是 POWER 家族處理器中最新的一代產品,所有 POWER 家族的處理器都是基于類似的基本架構的。除了具有以前版本的 POWER 芯片的優點之外,POWER5 處理器都具有內建的虛擬化能力,包括 IBM 的 Micro-Partitioning™(微分區)、DLPAR(Dynamic Logical Partitioning,動態邏輯分區)、虛擬存儲、虛擬以太網和 CoD(Capacity on Demand)。有關 POWER5 虛擬化的更多信息,請參閱“Linux on POWER: An overview for developers”(developerWorks,2005 年 3 月)。

如果您要同時移植到基于 POWER4 和 POWER5 處理器的服務器上,可以在使用 XL C/C++ 編譯器時對 -qarch-qtune 使用不同的標記來對應用程序進行優化。到底應該使用哪些具體的標記以及合適使用這些標記將在本文稍后進行介紹。

確定使用哪個 Linux for POWER 發行版
SUSE LINUX Enterprise Server(SLES)for POWER 是 SUSE、IBM 和開源社區經過 4 年多努力的結晶。除了要為 POWER 架構提供 64 位的內核之外,SLES9 現在還包括一個 64 位的運行時環境,以及用來編譯 64 位版本的流行開源軟件(例如 Apache Web 服務器或 MySQL)所使用的 GCC 工具鏈。IBM XL 編譯器是為對性能要求很高的應用程序準備的編譯器,使用它以及 SLES9 所提供的 64 位 Linux on POWER 環境(包括 IBM eServer OpenPower™、IBM eServer p5、IBM eServer i5 和 IBM eServer BladeCenter™ JS20 已經),可以提供為開發和部署 Linux 解決方案提供一個空前優秀的平臺。有關 SUSE LINUX 的更多信息,請參閱 參考資料 一節。

Red Hat Linux 在桌面和企業級的 Linux 市場方面都是被廣泛認可的業界領導者。在最新的 Red Hat Enterprise Linux Advanced Server(RHEL4)中,Red Hat 在 V3 版本的基礎上又提供了很多重要的技術改進。具體到開發領域來說,它包含了對安全性方面的改進,增強了服務器的性能和可擴展性,并增強了桌面應用的能力--所有這些都可以改進都可以確保與之前的版本保持高度的兼容性。RHEL4 是世界上領先的專注于企業級市場的 Linux 環境。有關 RHEL4 的更多信息,請參閱 參考資料 一節的內容。

決定是要使用 SLES 還是 RHEL,對移植過程并不會產生什么直接的影響。然而,要知道 SUSE 和 Red Hat 具有不同的發行版本,對于二進制兼容性也有不同的策略,這可能會影響到您長期的應用程序更新決策。

除了這兩個 IBM 所支持的 Linux 發行版本之外,還有其他幾個發行版本也可以在 Power 體系結構上運行,包括 Yellow Dog、Debian Linux 和 Gentoo(請參閱 參考資料)。

遷移至 GNU Make
如果您現在還沒有使用 GNU Make 來編譯程序,可以先考慮遷移到這上面來。使用一個工具來控制生成可執行程序,而不是依賴于一些腳本或直接與編譯器進行交互來生成可執行程序,這是一個很好的編程實踐。大部分 C 和 C++ 程序員都使用 Make 作為編譯工具。切換到 GNU Make 上,讓您可以在多個平臺上使用相同的編譯工具 makefile 確保編譯操作都是一致的。GNU Make 在 SLES9 和 RHEL4 中都已經集成了。有關 GNU Make 的更多信息,請參閱 參考資料 一節的內容。

理解 x86 和 POWER 體系結構的區別
在將 x86 平臺上的 Linux 應用程序移植到 POWER 架構上之前,您需要了解體系結構特有的幾點區別。下面是這兩種體系結構的一些區別--都是需要特別注意的一些問題:

  • Endianness 或字節次序
  • 32 位環境和 64 位環境中的數據類型的長度
  • 體系結構中數據調整的區別

 

Endianness(字節次序)
POWER 處理器使用的是 big-endian 的體系架構,而 x86 處理器使用的是 little-endian 的體系架構。本節將介紹 endianness (也稱為字節次序,byte ordering)的問題,并介紹處理這種問題的技術。開發者在將應用程序、設備驅動程序或數據文件從 x86 體系結構遷移到 POWER 體系結構上時,通常會碰到字節次序的問題。

Big endian 和 little endian
Endianness 是指數據元素及其各個字節是如何在內存中進行存儲和尋址的。在一個多位組成的數字中,數量級越大的數字就認為是越重要的。例如,在一個 4 位數字 8472 中,4 就比 7 重要。同理,在多字節的數字數據中,該字節中所代表的數字越大,它也就越重要。例如,16 進制的數字 0x89ABCDEF 可以分成 4 個字節:0x89、0xAB、0xCD 和 0xEF,它們代表的數值分別為 0x89000000、0xAB0000、0xCD00 和 0xEF。顯然,字節 0x89 的值最大;因此,它是最重要的值,而字節 0xEF 是最小的一部分,因此它最次要。

在將一個數字放到內存中時,從最低地址開始,只有兩種選擇:

  1. 首先放最不重要的字節(little endian)。
  2. 首先放最重要的字節(big endian)。

 

下圖顯式了 big-endian 和 little-endian 處理器是如何在內存中存放一個 32 位的 16 進制數值的,例如 0x89ABCDEF:

圖 1. Big-endian 和 little-endian 處理器存放 16 機制的數值
Big-endian 和 little-endian 處理器存放 16 機制的數值

0x89 是最重要的字節,0xEF 是最次要的字節。在 big-endian 的系統上,最重要的字節被保存在最低的內存地址中。在 little-endian 的系統中,最次要的字節被保存在最低的內存地址中。

如果一個程序將一個字寫入內存,然后有從相同的位置作為一個字將其讀出,那么字節次序就不是什么問題,因為在引用某個變量時,它看到的值是相同的。如果一個程序試圖按照一個字節來讀取相同的值(而該值是按照一個字寫入的),那么根據處理器是 big endian 還是 little endian,所讀取的值就可能有所不同。

POWER 處理器家族都使用 big-endian 數據布局,而 x86 處理器家族則都使用 little-endian 數據布局。在將 x86 程序遷移到 POWER 平臺上時,確定哪些代碼段是依賴于 endian 的,并將它們轉換為 big-endian 等效的代碼是非常重要的。

處理 endianess
本節將介紹如何判斷代碼中哪些部分是依賴于 endian 的,以及如何將這些代碼轉換成正確的 endian 格式。

依賴于 endian 的代碼
對于數據的不一致引用是 C 語言的優點,這使得它在系統級軟件的編程中非常通用,包括操作系統和設備驅動程序。這包括類型轉換、指針操作、聯合、位域、結構以及靈活的類型檢查。然而,這些特性同時也是 endianness 移植問題的源頭。我們可以考慮以下的代碼:

清單 1. 使用指針引用不一致的數據

            #include <stdio.h>
            int main(void) {
            int val;
            unsigned char *ptr;
            ptr = (char*) &val; /* pointer ‘ptr’ points to ‘val’ */
            val = 0x89ABCDEF; /* four bytes constant */
            printf("%X.%X.%X.%X\n", ptr[0], ptr[1], ptr[2], ptr[3]);
            exit(0);
            }
            

清單 2. 使用聯合引用不一致的數據

            #include <stdio.h>
            union {
            int val;
            unsigned char c[sizeof(int)];
            }u;
            int main(void) {
            u.val = 0x89ABCDEF; /* four bytes constant */
            printf("%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
            exit(0);
            }
            

在 x86 系統上,結果如下:


            EF.CD.AB.89
            

在 POWER 系統上,結果如下:


            89.AB.CD.EF
            

endianness 的問題從表面上來看是由于 val 而引起的,它在被讀取時,是一個字節一個字節從最重要的字節開始讀取的。

雖然基于 POWER 處理器的系統可以支持 big-endian 的數據存儲模型,但是有一個例外:其 I/O 總線。IBM Micro Channel® 以及最新的 PCI 都是基于 little-endian 的。在 POWER 系統中,I/O 控制器是系統總線與 I/O 總線之間的橋梁,它提供了一種功能,可以在從設備讀寫數據時,將這些數據在 little endian 和 big endian 格式之間進行轉換。這種數據轉換功能對于 Direct Memory Access(DMA)和 Program I/O(PIO)或 Memory-Mapped I/O(MMIO)數據全部適用。實際上,I/O 控制器會將數據作為字節流,這樣系統中的字節 0 就可以對應 I/O 中的字節 0,字節 1 對應字節 1,依此類推。結果是,在移植與 I/O 無關的代碼時,little-endian 的代碼應該保持不變,因為 I/O 設備也是基于 little-endian 的。然而,我們建議您要確定所有依賴于 endian 的代碼(這可以檢查代碼實現,也可以使用諸如 lint 之類的編程工具實現),并手工進行這種轉換。

除了與 I/O 有關的程序之外,用來進行 TCP/IP 協議處理的程序可能也具有依賴于 endian 的代碼。因為 TCP/IP 協議指定自己的數據格式是 big endian 的,而一個基于 x86 的程序在開始進行數學計算之前,可能會將 TCP/IP 數據轉換成自己的 endianness 格式(little endian)。實際上,在 POSIX 標準(Portable Operating System Interface)中,已經定義了一些轉換程序。這些程序包括 htonl()、ntohl()、htons()ntohs()。這些程序名字中的 s 代表 short,l 代表一個 32 位的數據。雖然調用這些函數的程序應該不會有什么 endianness 的問題,但是可能某些依賴于 endian 的代碼會顯式地自行操作 TCP/IP 數據。

編寫 endian 中立的代碼

如果一個程序能夠移植到不同 endianness 的平臺上并能維持自己的功能,那么它就被認為是 endian 中立的。換言之,其功能與所運行平臺的 endianness 之間沒有什么關系。以下是編寫 endian 中立的代碼的一些建議:

  • 使用宏和原語
    要使代碼是可移植的,您可以使用宏和條件編譯原語,如 清單 3 和 清單 4 所示。

清單 3. 使用原語來實現 endianness 中立的代碼

            #include <stdio.h>
            #define BIG_ENDIAN 0
            #define LITTLE_ENDIAN 1
            #define BYTE_ORDER BIG_ENDIAN
            union {
            int val;
            unsigned char c[sizeof(int)];
            }u;
            int main(void) {
            u.val = 0x89ABCDEF;
            #if (BYTE_ORDER == BIG_ENDIAN)
            printf("%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
            #else /*! BYTE_ORDER == BIG_ENDIAN*/
            printf("%X.%X.%X.%X\n", u.c[3], u.c[2], u.c[1], u.c[0]);
            #endif /*BYTE_ORDER == BIG_ENDIAN*/
            exit(0);
            }
            

清單 4. 使用宏來訪問 4 字節整數的 16 到 23 位

            #define INTB16TO23(a)  ((a>>16) & 0xff)
            int main(void) {
            int a=0x11121314
            int b
            b = INTB16TO23(a)      // b is 0x12 in LE and BE
            }
            

  • 使用編譯時選項
    實現這種功能一種比較好的方法是在編譯器命令行中定義 BYTE_ORDER 選項的值:-DBYTE_ORDER=BIG_ENDIAN。這樣在一個具有不同字節次序的新平臺上編譯時,就不用對設備驅動程序或應用程序的每個文件都進行編輯了。相反,您可以只編輯用來編譯驅動程序或應用程序的 makefile 即可。

  • 測試內存的布局
    清單 5 中的例子對一個多字節整數的第一個字節進行了測試,從而確定它是 0 還是 1。如果它是 1,那么就認為所運行的平臺是 little endian 的。這種方法的缺點是每次訪問這種數據類型時,都要進行一次測試,然后向代碼路徑中添加其他的一些指令,這可能會對性能造成影響。應用程序或設備驅動程序的目標平臺以及該平臺所采用的 endianness,在編譯時都是已知的。由于設備驅動程序和應用程序都有性能方面的考慮,因此使用編譯時的定義是選擇適當依賴于 endian 的代碼段的最好的一種方法。

清單 5. 在運行時確定 endianness

            const int endian = 1;
            #define is_bigendian() ( (*(char*)&endian) == 0 )
            union {
            unsigned char c[sizeof(int)];
            }u;
            int main(void) {
            u.val = 0x89ABCDEF;
            if (is_bigendian()) {
            printf("%X.%X.%X.%X\n", u.c[0], u.c[1], u.c[2], u.c[3]);
            }
            else {
            printf("%X.%X.%X.%X\n", u.c[3], u.c[2], u.c[1], u.c[0]);
            }
            exit(0);
            }
            


32 位環境和 64 位環境中數據類型的長度

Linux 操作系統上的 GCC 和 XL C/C++ 編譯器都提供兩種不同的編程模型:ILP32 和 LP64。ILP32 代表 integer/long/pointer 32,這是 Linux 上的 32 位編程環境。ILP32 數據模型提供了 32 位的地址空間,其理論內存上限是 4 GB。LP64 代表 long/pointer 64,這是 Linux 上的 64 位編程環境。表 1 給出了在 POWER 和 x86 平臺中 ILP32 和 LP64 模型中基本數據類型的寬度。

表 1. POWER 和 x86 平臺中 ILP32 和 LP64 模型中基本數據類型的寬度(位數)
POWER x86
ILP32 ILP64 ILP32 ILP64
char 8 8 8 8
short 16 16 16 16
int 32 32 32 32
float 32 32 32 32
long 32 64 32 64
long long 64 64 64 64
double 64 64 64 64
long double 64/128* 64/128* 96 128
pointer 32 64 32 64

* 在 Linux on POWER 中,long double 缺省為 64 位。如果您使用 XL C/C++ 編譯器的 -qlongdouble 選項,可以將其設置為 128 位的。

所有有關數字類型的定義在 POWER 和 x86 平臺上都可以在 /usr/include/limits.h 中找到。

現在大部分 x86 平臺上的 Linux 應用程序都是以 32 位模式運行的。然而,隨著 x86 64 位擴展的出現(x86-64),越來越多的程序將會直接編寫為 64 位的。在將 x86 應用程序移植到 POWER 平臺上時,您應該使用與源環境匹配的 Linux POWER 環境。換言之,在遷移到 POWER 平臺上的過程中,要避免從一個 32 位編程模型遷移到 64 位的編程模型,因為這種嘗試并不是單純的移植,而是一次開發任務。如果您將一個 32 位的 x86 應用程序移植到 64 位 POWER 編程模型中,那么可以將這次遷移分為兩個步驟:

  1. 移植到 Linux on POWER 的 32 位環境中(包括測試和驗證)。
  2. 遷移到 64 位環境中。

 

這就是說,如果一個程序可以滿足以下條件,就應該被移植到 64 位環境中:

  • 可以利用超過 4 GB 的虛擬地址空間。
  • 可以利用更多的物理內存(超過 4 GB),如果用戶希望將其部署到一個具有多于 4 GB 物理內存的系統上。
  • 可以利用 64 位的 long integer 類型。
  • 可以利用全部的 64 位寄存器實現更有效的 64 位數學計算。
  • 使用大于 2 GB 的文件。

 

可以從遷移到 64 位程序中獲益的一些程序包括:

  • 數據庫應用程序,尤其是那些進行數據挖掘的程序
  • Web 緩存和 Web 搜索引擎
  • CAD/CAE 模擬和建模工具的組件
  • 科學計算程序,例如流體力學、遺傳仿真

 

一個程序可以保持是 32 位的,但仍然可以在 64 位的 Linux on POWER 內核上運行,而不需要修改代碼。IBM 基于 POWER 處理器的服務器上的 Linux 可以支持在 64 位體系結構上同時運行 32 位和 64 位的應用程序,而不會造成這兩種模式的性能降低,這是因為 64 位的 POWER 體系結構中包含了對本地 32 位模式的完全支持。

在不同的平臺(從 x86 到 POWER)或編程模式(從 ILP32 到 LP64)之間移植程序時,您應該考慮不同環境中數據寬度和對齊設置的不同,這樣才能防止出現可能的性能降低或數據崩潰的問題。

在從 x86 ILP32 移植到 POWER ILP32 上或從 x86 LP64 移植到 POWER LP64 上時,注意在 表 1 中,所有的基本數據類型的寬度都是相同的,long double 例外,對于 64/128 位的 IPL32 來說,它是 96 位;而對于 64/128 位的 LP64 來說,它是 128 位。這意味著您應該盡可能地檢查以下代碼中與 long double 數據類型有關的地方。如果您計劃要使用 XL C/C++ 編譯器,請使用 -qlongdouble 編譯標記來保證 long double 數據類型具有最好的可移植性。

數據對齊
在不同的平臺或 32 位和 64 位模式之間移植程序時,要考慮不同環境中對齊設置的不同,從而避免出現可能的性能降低和數據崩潰的問題。最好的實踐方法是確保數據都是自然對齊的。自然對齊的意思是說將數據項存儲在是其大小的整數倍的地址處(例如,8 字節的數據的地址就應該是 8 的整數倍)。對于 XL C/C++ 編譯器來說,聚集類型(C/C++ 結構/聯合和 C++ 類)中的每種數據類型都會根據 linuxppc 或位填充規則按照字節邊界進行對齊,其中 linuxppc 是缺省值,它是自然對齊的。linuxppc 也是與缺省的 GCC 對齊規則兼容的。表 2 顯式了 POWER 和 x86 上的對齊值,以及它們的數據類型的寬度(以字節為單位)。

表 2. POWER 和 x86 上的對齊值(以字節為單位)
POWER x86
ILP32 ILP64 ILP32 ILP64
寬度 對齊 寬度 對齊 寬度 對齊 寬度 對齊
char 1 1 1 1 1 1 1 1
short 2 2 2 2 2 2 2 2
int 4 4 4 4 4 4 4 4
float 4 4 4 4 4 4 4 4
long 4 4 8 8 4 4 8 8
long long 8 8 8 8 8 8 8 8
double 8 8 8 8 8 8 8 8
long double 8/16 8 8/16 8 12 4 16 16
pointer 4 4 8 8 4 4 8 8

GCC 和 XL C/C++ 中的關鍵字 __alignof__ 讓您可以了解一個對象是如何對齊的。它的語法與 sizeof 類似。例如,如果目標及其要求一個 double 類型的值按照 8 字節邊界進行對齊,那么 __alignof__ (double) 就是 8。

正如在 表 2 中介紹的一樣,long double 類型的變量在 x86 平臺上是按照 4 個字節進行對齊的,而在 POWER 平臺上則是按照 8 個字節進行對齊的。因此,在不同的平臺上,這種結構就有不同的布局。不要將大小和偏移量都在編碼中寫死了,這一點非常重要。相反,使用 C 語言中的 sizeof 操作可以查詢基本類型和復雜類型的大小。宏 offsetof 是一個變量,它可以獲取結構程序從該結構開始地址處的偏移量。

確定使用哪種編譯器:GCC 或 IBM XL C/C++
在 Linux on POWER 上有兩種 C/C++ 編譯器:GCC 和 IBM XL C/C++。GCC 為那些在 Linux 上編譯的代碼提供了很好的可移植性,而 IBM XL 編譯器與 GCC 相比,則提供了很好的性能改進,它可以使用更高級的優化。這兩種編譯器都提供了 32 位和 64 位的編譯模式,Linux on POWER 環境允許同時運行 32 位和 64 位的代碼,而不會降低程序的性能。

使用 GCC 編譯器進行移植
對于在多種 GCC 編譯器就是原始編譯器的平臺上開發的項目來說,GCC 編譯器通常被用來為 Linux on POWER 部署應用程序。在性能不太關鍵的情況中,例如一些小工具,這都沒有什么問題。GCC 可以使用一些只有 GCC 才理解的代碼原型,例如 GCC 特有的宏。然而,這些 GCC 特有的特性中有很多也都已經集成進到 XL C/C++ 編譯器中了。

通常,使用 GCC 來遷移代碼應該比較簡單。在大部分情況中,這只需要簡單地重新編譯一下即可,也就是之需要鍵入 make 命令即可。體系結構可能會有所區別,偶然可能會出現庫程序的版本不同的問題。但是對于大部分情況來說,在哪種體系結構上運行并無關緊要。體系結構特有的標記,例如 -m486-mpowerpc64 并鼓勵在 Linux on POWER 的編譯過程中采用,因為 GCC 沒有這么豐富的處理器映射來對這些體系結構上的程序進行優化。而且,不使用體系結構特有的標記,在不同的 POWER 硬件模型之間就能保證更好的可移植性。

在 SLES9 和 RHEL4 中也包含了 64 位的 GNU 編譯器,推薦您使用這些 Linux 發行版本中所提供的編譯器。

在所有的體系結構中,庫都必須使用 -fPIC 標記進行編譯;在 x86 平臺上,GCC 會缺省就應用這個標記。在 POWER 平臺上,這個標記規定所生成的代碼必須在一個共享對象中使用。更多信息請參閱 GCC 編譯器手冊(請參閱 參考資料)。

使用 IBM XL C/C++ 編譯器進行移植
IBM XL C/C++ V7.1 是 IBM VisualAge® V6.0 for Linux 的下一個發行版本。XL C/C++ 編譯器可以作為 GCC 的一種高性能的替代品,同時它還提供了很多其他的特性。

幸運的是,XL C/C++ 使用的是 GNU C 和 C++ 的頭文件,所生成的應用程序也是被鏈接到 GCC 所提供的 C 和 C++ 運行時庫上。這意味著 XL C/C++ 編譯器會產生 GNU 的 elf 對象,后者是與 GCC 編譯器所生成的對象完全兼容的。XL C/C++ 預裝了 SMP 運行時庫來支持 XL C/C++ 編譯器的自動并行處理和 OpenMP 特性。

從 GCC 遷移到 XL C/C++ for Linux on POWER 上非常簡單。XL C/C++ 可以通過提供一個選項 -qinfo=por 來幫助實現這個任務,從而幫助您對所產生的診斷消息進行過濾,只顯示那些與移植性有關的問題。另外,XL C/C++ 也可以支持 GNU 對 gcc 和 gcc-c++ 擴展的一個子集。有關 XL C/C++ 所支持的特性的完整列表,以及哪些語法可以接受,哪些語法會被忽略,請參閱“XL C/C++ for Linux on pSeries Compiler Reference”。

要在 C 代碼中使用這些支持特性,請指定 -qlanglvl=extended-qlanglvl=extc89 選項。在 C++ 中,所有支持的 GNU gcc/gcc-c++ 特性缺省都是可以接受的。此外,gxlc 和 gxlc++ 可以用來幫助在使用 GNU 編譯器編譯現有應用程序時,對 makefile 所做的修改可以降至最小。

XL C/C++ 文檔
在安裝 XL C/C++ 時,會提供以下的 PDF 文檔:

  • “XL C/C++ for Linux Getting Started”(getstart.pdf)。
  • “XL C/C++ for Linux Installation Guide”(install.pdf),這份文檔中包含了有關安裝編譯器和使用手冊頁的用法說明。
  • “XL C/C++ for Linux C/C++ Language Reference”(language.pdf),這份文檔中包含了有關 IBM 所支持的 C 和 C++ 語言的信息。
  • “XL C/C++ for Linux Compiler Reference”(compiler.pdf),這份文檔中包含了有關各種編譯器選項、程序、宏和內嵌函數的信息,包括它們對于并行處理的用法。
  • “XL C/C++ for Linux Programming Guide”(proguide.pdf),這份文檔中包含了(其他文檔中都未曾介紹過的)有關使用 XL C/C++ 進行編程的信息。

 

這些文檔可以在下面的地方找到:

  • 安裝 CD 的 /docs/LANG/pdf 目錄,其中 LANG 標識語言和位置編碼
  • 安裝之后位于 /opt/ibmcmp/vacpp/7.0/doc/LANG/pdf 目錄

 

另外還有一個 HTML 版本的產品文檔被安裝到 /opt/ibmcmp/vacpp/7.0/doc/LANG/html 目錄中。在這個目錄中,打開 index.html 文件就可以查看 HTML 文件的內容。

XL C/C++ 中的優化選項
XL C/C++ 為 IBM 硬件提供了很多優化選項。對于 Linux on POWER 來說,很多使用 XL C/C++ 編譯的程序的性能都比使用 GCC 編譯的程序有顯著的提高。注意并不是所有的優化對于所有的應用程序都是有益的。通常在編譯器所實現的優化級別與編譯時間的增長以及調試能力的減弱之間是一種平衡。

優化級別
優化級別是由編譯器選項指定的。下表對編譯器在每種優化等級下的行為進行了總結:

表 3. 每種優化級別中編譯器的行為
選項 行為
-qnoopt 快速編譯,完全調試支持
-O2(與 -O 相同) 執行編譯器開發人員認為是編譯速度和運行時性能最佳組合的優化。如果沒有使用 -qnostrict_induction-qnostrict 明確否定,那么這個設置中將包含 -qstrict–qstrict_induction
-O3 執行內存占用大、編譯時間長或兩者都有的其他優化。當運行時改善比最大程度地減少編譯資源使用重要時,建議使用這些優化
-O4 和 -O5 執行過程間優化、循環優化和自動計算機調整

目標機器選項是那些可以引導編譯器為某種給定的微處理器或體系結構家族生成優化代碼的選項。通過選擇適當的目標機器選項,您可以對不同范圍的目標機器進行合適的優化:這可以是一組選定的目標處理器,一個給定家族的處理器體系結構中的一組處理器,或者某個特定的處理器。以下選項可以控制影響特定目標機器優化措施:

表 4. 影響特定目標機器的優化選項
選項 行為
-qarch 選擇應該為其生成指令代碼的處理器架構系列。默認值是 -qarch=ppc64grsq。還可以使用以下子選項: auto、 pwr3、 pwr4、 pwr5、 ppc970、 ppc64、 ppcgr、 rs64b、 rs64c
-qtune 偏向于對給定微處理器上的執行操作進行優化,但這并不意味著將與指令集合架構有關的任何操作作為目標。Linux 上的默認值是 -qtune=pwr3??捎玫淖舆x項包括: auto、 pwr3、 pwr4、 pwr5、 ppc970、 rs64b、 rs64c
-qcache 定義特定緩存或內存布局。如果使用了 -qcache,則將 -qhot-qsmp 與其一起使用
-qhot High-Order Transformations:該優化可以通過諸如交換、合并及展開等方法特別地提高循環性能。指定 -qhot 時,默認值為選項 -qhot=vector。嘗試將 -qhot-O2-O3 一起使用。它被設計用來在沒有機會進行這種轉換時,也具有很自然的效果
-qsmp 生成共享內存并行處理所需的線程代碼。指定 -qsmp 時,默認值為選項 -qsmp=auto。如果在 OpenMP 程序中編譯且不想進行自動并行化,則使用 -qsmp=omp:noauto。使用 -qsmp 時,總是使用 _r 編譯器調用

要獲得最好的目標機器選項,您應該:

  • 使用 –qarch 選項指定您期望代碼能夠運行良好的最小系列的機器。
  • 使用 –qtune 選項指定在哪種機器上的性能最好。例如,如果您的應用程序只支持 POWER5 系統,就可以使用 -O3 -qarch=pwr5 -qtune=pwr5 選項。修改緩存布局在某些情況中可能會非常有用,例如系統具有可配置的 L2 和 L3 緩存.或者整型模式會減小緩存共享級別的有效大?。ɡ?,POWER5 中雙核芯片的 SMP)。如果您的程序只要在 POWER4 上運行,或者要在 POWER4 和 POWER5 上運行,可以使用 -qarch=pwr4 -qtune=pwr4。

 

POWER 平臺可以支持其他平臺上所沒有的一些指令。XL C/C++ 提供了一組內嵌的函數,它們可以直接映射為特定的 POWER 指令。使用這些函數可以消除函數調用返回、參數傳遞、堆棧調整以及其他與函數調用有關的開銷。有關所支持的內嵌函數的完整列表,請參閱“XL C/C++ C++ for Linux on pSeries Compiler Reference”安裝文檔。

然而,那些最初是想使用 GCC 編譯器進行編譯的程序在使用 IBM XL C/C++ 編譯器進行編譯時需要多加注意。您需要編輯 makefile 來體現 XL C/C++ 編譯器的正確路徑,它缺省位于 /opt/ibmcmp/ 中。您還需要為特定的體系結構設置正確的優化標記(例如對于 IBM POWER5 來說是 -03 –qarch=pwr5 –qtune=pwr5)。

除了對各種 POWER 體系結構進行優化的優化選項之外,XL C/C++ 編譯器還可以使用通用的模式來編譯軟件。這可以保證在所有的 POWER 體系結構上程序都是兼容的,代價是性能不如對具體某種體系結構進行優化后的結果好。在編譯 64 位的代碼時,編譯器必須要為 64 位的編譯給出一個標記(即 -q64),因為它缺省是 32 位模式。

下面是使用 XL C/C++ 編譯器來編譯面向 GCC 的代碼時的一些技巧:

  • C++ 注釋:GCC 缺省允許在 C 文件中使用 C++ 風格的注釋,但是在 XLC(XL C 編譯器)中則并非如此。因為要對源代碼中所有的注釋進行修改以便它們可以遵守 C 風格的注釋,這并不經濟,因此 XLC 提供了一個 -q 參數允許使用這種注釋:-q cpluscmt。當使用這個標記編譯 C 代碼時,C 和 C++ 風格的注釋都會進行解釋。
  • 環境變量通常是用來配置編譯腳本最簡單的方法。您無需手工編輯配置腳本和 makefile,而是應該設置適當的環境變量,例如 $CC 和 $CFLAGS,這樣就可以讓配置腳本生成 makefile,而不需要手工進行編輯。
  • 配置腳本還需要注意適當的平臺類型。這可能是 linux-powerpc-unknown-gnu 或 linux-powerpc64-unknown-gnu。您應該通過為配置腳本添加一個 -target= 標記來為 GCC 或 XL C/C++ 設置這個編譯選項。
  • 雖然對于 IBM XL C/C++ 編譯器來說已經有非常豐富的文檔了,但是不加參數運行編譯器命令,例如 $COMPILER_PATH/bin/cc 就可以得到完整的參數列表。

 

GCC 和 XL C/C++ 編譯器選項的比較
下 表 對 GCC 和 XL C/C++ 常用的編譯器選項進行了比較:

表 5. GCC 和 XL C/C++ 的常用編譯器選項
GCC XL C/C++ C/C++ 說明
-v -v, -V, -# 開啟詳細模式
-p/-profile -p 設置編譯器生成的對象文件進行概要分析
n/a -q32, -q64 或設置 OBJECT_MODE 環境變量 創建 32 位或 64 位對象。GCC 64 位編譯器位于 /opt/cross/bin 中
-fsyntax-only -qsyntaxonly 執行語法檢查,不生成對象文件
-fpic -qpic=small 生成共享庫中使用的 Position-Independent Code。在 XL C/C++ 中,Global Offset Table 的大小不超過 64 Kb。如果指定 –qpic,而無任何子選項,則假設 -qpic=small。如果指定了 -qmkshrobj 編譯器選項,則啟用 –qpic 選項
-fPIC -qpic=large 允許 Global Offset Table 大于 64 Kb
-pthread -qthreaded or _r invocation mode 創建在多線程環境中運行的程序
-fno-rtti -qnortti 對于異常處理和 typeid 和 dynamic_cast 操作符的使用,禁止生成運行時類型 –qrtti 識別(RTTI)。在 XL C/C++ 中,默認值為 -qnortti
-static -qstaticlink 使用這個選項生成的對象將無法與共享庫進行鏈接
-static-libgcc -qstaticlink=libgcc 指示編譯器與 libgcc 的靜態版本鏈接
-shared -qmkshrobj 指示編譯器生成共享對象
-shared-libgcc -qnostaticlink=libgcc 指示編譯器與 libgcc 的共享版本鏈接
-Wl,-rpath -Wl,-rpath 或 –R 傳遞用冒號分隔的目錄列表,用它來指定運行時鏈接程序搜索的目錄
-fno-implicit-templates, -frepo -qtempinc, -qtemplateregistry, -qtemplaterecompile 模板實例化
-w -w 取消警告消息
-warn64 允許對長型到整型的截斷舍位(long-to-integer truncation)進行檢查
-qinfo=<…> 生成信息消息
-fpack-struct -qalign=bit_packed 使用 bit_packed 排列規則
-qalign=linuxppc 使用默認 GCC 排列規則來維護與 GCC 對象的兼容性。這個值是默認值
-O,-O2,-O3 -O,-O2,-O3,-O4,-O5 優化級別
-qarch, -qtune, -qcache 特定處理器的優化選項

請參閱“How to use IBM XL C/C++ Advanced Edition V7.0 for Linux on POWER: A guide for GCC users”(developerWorks,2004 年 10 月)中有關 IBM C/C++ 編譯器的更多信息。

移植
在完成規劃的所有步驟之后,您就應該準備好開始進行移植了。本節將簡要討論成功將程序移植到 Linux on POWER 上的一些推薦步驟。

  1. 將編譯系統遷移到 GNU Make 上(如果需要)
    這是構建一個或多個 makefile 的過程。您也可以利用 GNU 的自動編譯工具,例如 Autoconf、Automake 和 Build 工具,從而最大程度地保證程序在不同 UNIX® 平臺之間的可移植能力。GNU 的自動編譯工具位于 directory.fsf.org/devel/build/ 中。

  2. 修改依賴于體系結構的代碼(如果需要)
    考慮字節次序(endianness)、32 位和 64 位模式中的數據長度以及不同平臺上數據對齊的問題,這在 理解 x86 和 POWER 體系結構之間的區別 一節中介紹過了。

  3. 編譯
    在構建 makefile 并對所有的程序進行修改之后,編譯過程就非常簡單了,這只是執行一個命令而已,例如 make。如果您在編譯過程中碰到了錯誤,那么通常都是編譯器的或鏈接器的錯誤,或者是程序的語法錯誤。通常通過 makefile 修改編譯器選項或修改代碼中的語法都可以修復這些錯誤。編譯器的參考手冊和編程指南是這個過程中最好的參考資料。對于 IBM XL C/C++ 來說,請參考“XL C/C++ for Linux Compiler Reference”(compiler.pdf)和“XL C/C++ for Linux Programming Guide”(proguide.pdf)。對于 GCC 來說,編譯器的參考手冊和編程指南都可以在 gcc.gnu.org/onlinedocs 中找到。

  4. 測試和故障診斷
    在成功編譯好程序之后,要對其進行測試是否存在運行時的錯誤。運行時錯誤通常都是與這個步驟中的程序邏輯有關的。通常編寫幾個測試程序來驗證程序的輸出如您所期望的一樣是個好主意。

  5. 性能調優
    現在所移植的代碼已經可以在 POWER 平臺上運行了,對其進行監視,以確保它的執行情況符合我們的預期。如果不符合,就需要徹底進行性能調優。您可以使用以下的工具來判斷應用程序中的問題,并顯示應用程序與 Linux 內核之間的交互:

    1. OProfile
      OProfile 會根據與硬件相關的事件對代碼進行分析,例如緩存命中率或 CPU 周期。例如,OProfile 可以幫助您判斷哪些源代碼中的程序引起了緩存的不命中。OProfile 利用了很多 CPU 中所提供的硬件性能計數器,包括 IBM POWER4、POWER5 和 PowerPC™ 970。有關 OProfile for Linux on POWER 的更多信息,請參閱“Identify performance bottlenecks with OProfile for Linux on POWER”(developerWorks,2005 年 5 月),或訪問 OProfile 的 Web 站點(請參閱 參考資料)。

    2. Post-Link 優化
      Post-Link 優化工具可以在典型的負載情況中運行程序時搜集程序的行為信息,從而對程序的執行影響進行優化。然后再對程序重新進行分析(同時使用所搜集到的 profile),并應用全局優化選項(包括程序重構),并為這種負載情況創建一個新版本的優化后的程序。與原有的程序相比,優化器所生成的新程序通常運行的速度更快,并且使用的物理內存也更少。更多信息,請訪問 Post-Link 優化的 Web 站點(請參閱 參考資料)。

    3. TProf
      TProf 是一個定時的 profiler,它可以判斷在用戶指定的時間間隔內哪些代碼正在 CPU 上運行。它可以用來報告應用程序和內核中的熱點區域。TProf 記錄了在每個系統時鐘中斷時(每個 CPU 每秒 100 次)哪些代碼正在運行。

    4. PTT
      PTT 搜集每個線程的統計信息,例如 CPU 循環的次數、中斷次數以及該線程被調度的時間。

    5. AI
      AI 顯式在用戶指定的時間間隔那 CPU 的使用情況統計信息。

  6. Package
    如果您移植的程序是一個商業產品,或者您希望將程序分發給第三方進行安裝,那么您可能需要對所移植的程序進行打包,包括庫和文檔,有時還包括源代碼。Linux 提供了幾種方法來對應用程序進行打包,例如 tarball、自安裝的 shell 腳本和 RPM。RPM 是 Linux 上最流行的一種打包工具。有關 RPM 的更多信息, 請參閱 參考資料 一節的內容。

圖 2. 上面介紹的移植操作 6 個步驟中第一個步驟的流程

結束語
Linux on POWER 提供了一個企業級的 Linux 環境,以及完整的 32 位和 64 位的應用環境和工具鏈。Linux on POWER 提供了兩套編譯器集,它們可以簡化開源代碼的移植,并促進廣受好評的 POWER 體系結構這種高性能的平臺的采用。將您的 x86 平臺上的程序移植到 Linux on POWER 上,您就可以在 POWER 架構上充分利用程序的性能,現在以及在 Linux 操作系統上提供的一些前所未有的工具??傊?,Linux on POWER 是部署高性能的 Linux 程序的業界領先的平臺。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97