化指南)
1. 項(xiàng)目概述為什么要在飛騰CPU上折騰PhyGCC如果你手頭有一臺基于飛騰處理器的國產(chǎn)服務(wù)器或PC比如運(yùn)行著銀河麒麟V10系統(tǒng)當(dāng)你試圖從源碼編譯一些高性能計(jì)算庫、數(shù)據(jù)庫或者特定的行業(yè)應(yīng)用時可能會發(fā)現(xiàn)一個尷尬的情況系統(tǒng)自帶的GCC編譯器版本要么有點(diǎn)老要么在針對飛騰CPU的微架構(gòu)優(yōu)化上不夠“激進(jìn)”。這時候一個專門為飛騰平臺優(yōu)化過的高性能編譯器就顯得尤為重要。PhyGCC正是為了解決這個問題而生的一個GCC分支版本。它并非一個全新的編譯器而是在GNU GCC的基礎(chǔ)上針對飛騰CPU的微架構(gòu)特性如矩陣運(yùn)算擴(kuò)展、特定的流水線結(jié)構(gòu)和緩存層次進(jìn)行了深度調(diào)優(yōu)和指令集支持的增強(qiáng)。簡單來說PhyGCC可以理解為飛騰平臺的“官方推薦”或“社區(qū)優(yōu)化”版GCC。使用它來編譯你的C、C或Fortran代碼理論上可以在不修改一行源代碼的情況下獲得比通用GCC更佳的性能表現(xiàn)尤其是對于計(jì)算密集型的科學(xué)計(jì)算、大數(shù)據(jù)處理或底層中間件。這就像給你的飛騰機(jī)器換上了一套更貼合其“身體結(jié)構(gòu)”的專用工具干活效率自然更高。本篇文章我就以一個在飛騰FT-2000/64服務(wù)器上實(shí)際部署的經(jīng)驗(yàn)帶你走一遍PhyGCC從獲取、編譯安裝到基礎(chǔ)配置和驗(yàn)證的全過程并分享其中幾個關(guān)鍵的“坑”和解決技巧。2. 環(huán)境準(zhǔn)備與依賴梳理在開始編譯安裝PhyGCC之前一個干凈、依賴完備的基礎(chǔ)環(huán)境是成功的一半。很多人安裝失敗問題往往就出在環(huán)境準(zhǔn)備階段。2.1 系統(tǒng)環(huán)境確認(rèn)首先明確你的操作系統(tǒng)。PhyGCC主要面向飛騰平臺常見的操作系統(tǒng)是銀河麒麟KylinV10或其社區(qū)版以及統(tǒng)信UOS。我這次的操作環(huán)境是CPU:飛騰 FT-2000/64OS:銀河麒麟服務(wù)器操作系統(tǒng) V10 SP1內(nèi)核:4.19.90-23.8.v2101.ky10.aarch64當(dāng)前GCC:gcc version 7.3.0使用uname -a和cat /etc/os-release可以快速確認(rèn)你的系統(tǒng)信息。雖然理論上PhyGCC也支持其他Linux發(fā)行版但在麒麟或UOS上其依賴庫的兼容性最好。2.2 安裝必備的構(gòu)建工具和庫編譯GCC是一個資源密集型任務(wù)需要大量的基礎(chǔ)開發(fā)包。以下命令可以一次性安裝大部分必需工具和庫。請確保你的系統(tǒng)已配置好可用的軟件源如麒麟的yum源。sudo yum groupinstall -y Development Tools sudo yum install -y wget git make cmake gcc-c bzip2 sudo yum install -y texinfo byacc flex sudo yum install -y zlib-devel libmpc-devel mpfr-devel gmp-devel sudo yum install -y glibc-devel.i686 # 部分32位庫支持有時需要關(guān)鍵依賴解析“Development Tools”組包含了make、gcc現(xiàn)有的用于編譯新的GCC即“自舉”、binutils等核心工具鏈。texinfoGCC的文檔系統(tǒng)需要它來生成info格式的手冊。libmpc-devel, mpfr-devel, gmp-devel這三個是GCC進(jìn)行高精度數(shù)學(xué)運(yùn)算所必需的多精度庫。缺少它們configure階段會直接報(bào)錯。zlib-devel壓縮庫支持處理壓縮的源碼包時需要。注意如果你的系統(tǒng)是離線環(huán)境需要提前下載好這些依賴包的RPM文件及其依賴項(xiàng)這是一個比較繁瑣但必須完成的工作??梢栽谝慌_聯(lián)網(wǎng)的同構(gòu)系統(tǒng)上使用yum download --resolve命令來下載完整的包集合。2.3 規(guī)劃安裝路徑不建議將PhyGCC安裝到默認(rèn)的/usr/local以免與系統(tǒng)自帶的GCC產(chǎn)生沖突。我習(xí)慣為其創(chuàng)建一個獨(dú)立的目錄方便管理和卸載。export PHYGCC_PREFIX/opt/phy-gcc-10.2.0 sudo mkdir -p $PHYGCC_PREFIX sudo chown -R whoami:whoami $PHYGCC_PREFIX # 將所有權(quán)賦給當(dāng)前用戶避免sudo編譯這里我將安裝路徑設(shè)置為/opt/phy-gcc-10.2.0你可以根據(jù)你下載的PhyGCC版本號進(jìn)行修改。將其加入環(huán)境變量后系統(tǒng)可以無縫切換使用。3. 獲取PhyGCC源碼與編譯配置3.1 源碼獲取途徑PhyGCC的源碼通常可以從飛騰的官方社區(qū)、開源鏡像站或特定的Git倉庫獲取。由于網(wǎng)絡(luò)環(huán)境差異這里提供兩種思路官方/社區(qū)發(fā)布包推薦訪問飛騰開源平臺或相關(guān)生態(tài)網(wǎng)站尋找以phy-gcc-{version}.tar.gz命名的發(fā)布包。這是最穩(wěn)定的方式通常包含了針對該版本的補(bǔ)丁。Git倉庫克隆如果社區(qū)提供了Git倉庫可以使用git clone獲取最新代碼可能包含開發(fā)中的特性。例如git clone https://gitee.com/phytium/phy-gcc.git cd phy-gcc git checkout gcc-10_2_0-phytium # 切換到特定版本分支我本次使用的是從社區(qū)下載的phy-gcc-10.2.0-20211224.tar.gz源碼包。wget https://repo.example.com/phy-gcc-10.2.0-20211224.tar.gz # 替換為實(shí)際URL tar -zxvf phy-gcc-10.2.0-20211224.tar.gz cd phy-gcc-10.2.03.2 配置編譯選項(xiàng)詳解GCC的編譯采用經(jīng)典的“configure - make - make install”流程。configure步驟的選項(xiàng)至關(guān)重要它決定了編譯器的功能、目標(biāo)和安裝位置。在源碼目錄外創(chuàng)建一個構(gòu)建目錄是保持源碼清潔的好習(xí)慣mkdir build cd build然后執(zhí)行configure腳本下面是一個經(jīng)過驗(yàn)證的配置示例../configure \ --prefix$PHYGCC_PREFIX \ --enable-languagesc,c,fortran \ --disable-multilib \ --with-archarmv8-a \ --with-cpuft2000 \ --enable-threadsposix \ --enable-checkingrelease \ --enable-bootstrap \ --disable-libmpx \ --with-system-zlib \ --with-gmp/usr \ --with-mpfr/usr \ --with-mpc/usr \ --buildaarch64-unknown-linux-gnu \ --hostaarch64-unknown-linux-gnu \ --targetaarch64-unknown-linux-gnu關(guān)鍵選項(xiàng)拆解--prefix$PHYGCC_PREFIX指定安裝路徑就是我們之前設(shè)置的。--enable-languagesc,c,fortran選擇要編譯的語言前端。通常C和C是必選Fortran在科學(xué)計(jì)算中常用。如果不需要可以去掉fortran以節(jié)省編譯時間。--disable-multilib對于純64位aarch64的飛騰環(huán)境這個選項(xiàng)非常重要。它告訴編譯器不要構(gòu)建32位庫支持可以避免很多棘手的兼容性問題并簡化編譯過程。--with-archarmv8-a --with-cpuft2000這是針對飛騰優(yōu)化的核心armv8-a是ARMv8-A架構(gòu)ft2000則是指定飛騰FT2000系列CPU的微架構(gòu)模型。GCC會根據(jù)這個模型調(diào)整指令調(diào)度、流水線利用和分支預(yù)測等優(yōu)化策略。不同飛騰CPU型號如FT-1500A, FT-2000可能對應(yīng)不同的--with-cpu值需查閱對應(yīng)PhyGCC版本的文檔。--enable-bootstrap啟用“自舉”編譯即用系統(tǒng)已有的GCC編譯第一遍再用編譯出來的新GCC編譯第二遍最后用第二遍的結(jié)果編譯第三遍并比較第二、三遍的結(jié)果是否一致。這能確保編譯器在構(gòu)建過程中沒有被損壞生成的編譯器更可靠但會顯著增加編譯時間約3倍。--with-gmp/usr --with-mpfr/usr --with-mpc/usr指定多精度數(shù)學(xué)庫的路徑我們之前已通過yum安裝到系統(tǒng)默認(rèn)位置/usr。--build, --host, --target在同構(gòu)編譯即在飛騰機(jī)器上編譯用于飛騰的GCC時這三個值通常都設(shè)為aarch64-unknown-linux-gnu。這表示構(gòu)建平臺、運(yùn)行平臺和目標(biāo)代碼生成平臺都是aarch64 Linux。實(shí)操心得--disable-multilib是我踩過坑后強(qiáng)烈建議的選項(xiàng)。早期嘗試開啟multilib支持時經(jīng)常在編譯libgcc時遇到關(guān)于32位/64位模式切換的錯誤排查非常耗時。對于絕大多數(shù)服務(wù)器應(yīng)用場景64位環(huán)境已經(jīng)完全足夠。4. 編譯、安裝與系統(tǒng)集成配置完成后就進(jìn)入了最耗時的編譯階段。4.1 并行編譯與資源管理使用make命令并加上-j參數(shù)可以充分利用多核CPU加速編譯。FT-2000/64有64個物理核但全部用于編譯可能會導(dǎo)致內(nèi)存不足每個編譯進(jìn)程都需要內(nèi)存。一個經(jīng)驗(yàn)公式是-j $(($(nproc) * 3 / 4))即使用CPU核心數(shù)的75%。make -j 48 21 | tee make.log這里-j 48指定了48個并行任務(wù)。21 | tee make.log將標(biāo)準(zhǔn)輸出和錯誤輸出都重定向到屏幕的同時保存到make.log文件中。這個日志文件至關(guān)重要如果編譯出錯你需要從這里查找具體的錯誤信息。編譯過程視機(jī)器性能而定在FT-2000/64上可能需要1到3個小時。期間CPU使用率會接近100%。4.2 安裝與驗(yàn)證編譯成功后進(jìn)行安裝make install 21 | tee install.log安裝完成后驗(yàn)證編譯器是否可用$PHYGCC_PREFIX/bin/gcc --version你應(yīng)該能看到輸出信息中包含“gcc (PhyGCC) 10.2.0”等字樣以及--with-cpuft2000的配置信息這表明PhyGCC已經(jīng)安裝成功。4.3 集成到系統(tǒng)環(huán)境為了讓系統(tǒng)方便地使用PhyGCC需要將其加入PATH和庫路徑。方法一臨時使用推薦在測試時export PATH$PHYGCC_PREFIX/bin:$PATH export LD_LIBRARY_PATH$PHYGCC_PREFIX/lib64:$LD_LIBRARY_PATH方法二永久生效修改用戶配置文件編輯~/.bashrc或~/.bash_profile在末尾添加# PhyGCC Environment export PHYGCC_HOME/opt/phy-gcc-10.2.0 export PATH$PHYGCC_HOME/bin:$PATH export LD_LIBRARY_PATH$PHYGCC_HOME/lib64:$LD_LIBRARY_PATH export MANPATH$PHYGCC_HOME/share/man:$MANPATH export C_INCLUDE_PATH$PHYGCC_HOME/include:$C_INCLUDE_PATH export CPLUS_INCLUDE_PATH$PHYGCC_HOME/include:$CPLUS_INCLUDE_PATH然后執(zhí)行source ~/.bashrc使配置立即生效。注意事項(xiàng)修改系統(tǒng)級環(huán)境變量如/etc/profile需謹(jǐn)慎可能影響其他用戶和系統(tǒng)服務(wù)。建議優(yōu)先使用用戶級配置。切換編譯器后可以使用which gcc和gcc --version來確認(rèn)當(dāng)前生效的是否是PhyGCC。5. 性能測試與基礎(chǔ)使用示例安裝好后我們最關(guān)心的是它真的更快嗎這里用一個簡單的測試來感受一下。5.1 編譯優(yōu)化選項(xiàng)對比PhyGCC的優(yōu)勢在于它對飛騰CPU的微架構(gòu)有更深的理解。除了通用的-O2、-O3優(yōu)化級別外可以嘗試使用-mcpu和-mtune選項(xiàng)來指定目標(biāo)CPU。創(chuàng)建一個簡單的測試程序test_matrix.c進(jìn)行一個小型矩陣乘法運(yùn)算#include stdio.h #include stdlib.h #include time.h #define N 512 int main() { double *A (double*)malloc(N*N*sizeof(double)); double *B (double*)malloc(N*N*sizeof(double)); double *C (double*)malloc(N*N*sizeof(double)); // 初始化 for(int i0; iN*N; i) { A[i]rand()%10; B[i]rand()%10; C[i]0; } clock_t start clock(); // 樸素矩陣乘法 for(int i0; iN; i) for(int j0; jN; j) for(int k0; kN; k) C[i*Nj] A[i*Nk] * B[k*Nj]; clock_t end clock(); printf(Time: %.2f seconds\n, (double)(end-start)/CLOCKS_PER_SEC); free(A); free(B); free(C); return 0; }分別用系統(tǒng)GCC和PhyGCC進(jìn)行編譯和運(yùn)行# 使用系統(tǒng)GCC-O3優(yōu)化 /usr/bin/gcc -O3 test_matrix.c -o test_sys -lm time ./test_sys # 使用PhyGCC-O3優(yōu)化并指定CPU類型 $PHYGCC_PREFIX/bin/gcc -O3 -mcpuft2000 -mtuneft2000 test_matrix.c -o test_phy -lm time ./test_phy在我的測試中PhyGCC編譯的程序通常會有5%到15%的性能提升對于這種計(jì)算密集型循環(huán)優(yōu)化效果比較明顯。-mcpuft2000會啟用FT2000系列支持的所有指令集擴(kuò)展而-mtuneft2000則告訴編譯器針對該CPU的流水線特性進(jìn)行調(diào)度優(yōu)化。5.2 編譯實(shí)際項(xiàng)目示例NumPy以Python科學(xué)計(jì)算棧的核心庫NumPy為例展示如何使用PhyGCC來加速其原生擴(kuò)展的編譯。首先確保你的Python環(huán)境如pip可用。然后在編譯NumPy時通過環(huán)境變量指定編譯器# 設(shè)置編譯環(huán)境變量讓Python的構(gòu)建工具使用PhyGCC export CC$PHYGCC_PREFIX/bin/gcc export CXX$PHYGCC_PREFIX/bin/g export F77$PHYGCC_PREFIX/bin/gfortran # 如果用到Fortran export F90$PHYGCC_PREFIX/bin/gfortran export LDSHARED$CC -shared # 安裝NumPy它會從源碼編譯 pip3 install numpy --no-binary numpy--no-binary numpy強(qiáng)制pip從源碼編譯而不是安裝預(yù)編譯的wheel包預(yù)編譯包通常是通用架構(gòu)的未針對飛騰優(yōu)化。這樣NumPy中所有用C和Fortran寫的計(jì)算核心都會經(jīng)由PhyGCC編譯從而獲得潛在的性能收益。編譯過程會比較慢請耐心等待。6. 常見問題排查與解決實(shí)錄在實(shí)際安裝過程中你可能會遇到以下問題。這里記錄了我遇到的和社區(qū)反饋較多的幾個案例。6.1 編譯錯誤configure: error: cannot compute suffix of object files問題現(xiàn)象在運(yùn)行configure腳本時早期階段就報(bào)錯無法繼續(xù)。原因分析這通常是因?yàn)闃?gòu)建環(huán)境缺少基本的編譯工具或者現(xiàn)有的編譯器系統(tǒng)GCC工作不正常。解決方案確認(rèn)gcc,make,binutils等包已正確安裝rpm -qa | grep -E \^(gcc|make|binutils)\。嘗試使用絕對路徑指定一個已知可用的編譯器進(jìn)行配置CC/usr/bin/gcc CXX/usr/bin/g ../configure [其他選項(xiàng)...]檢查/tmp目錄的磁盤空間和權(quán)限是否足夠。6.2 編譯錯誤internal compiler error: Segmentation fault問題現(xiàn)象在make階段特別是進(jìn)行bootstrap自舉時GCC本身在編譯過程中崩潰。原因分析這可能是由于系統(tǒng)內(nèi)存不足、硬件不穩(wěn)定如ECC內(nèi)存錯誤或者宿主編譯器系統(tǒng)舊GCC本身有bug導(dǎo)致。解決方案降低并行度這是最有效的辦法。使用make -j 4或make -j 2減少并行任務(wù)數(shù)降低內(nèi)存和CPU壓力。關(guān)閉bootstrap在configure時去掉--enable-bootstrap選項(xiàng)。這犧牲了部分可靠性驗(yàn)證但能顯著降低編譯復(fù)雜度和內(nèi)存需求常用于首次嘗試。檢查內(nèi)存使用free -h查看可用內(nèi)存確保在編譯時有足夠的物理內(nèi)存和交換空間。如果內(nèi)存緊張可以嘗試增加swap分區(qū)。6.3 運(yùn)行時錯誤/lib64/libc.so.6: version \GLIBC_2.33 not found問題現(xiàn)象使用PhyGCC編譯的程序在另一臺系統(tǒng)版本稍舊的飛騰機(jī)器上運(yùn)行時報(bào)錯。原因分析PhyGCC在編譯時鏈接了其自帶的或編譯時宿主機(jī)的glibc庫。如果目標(biāo)運(yùn)行環(huán)境的glibc版本低于這個版本就會出現(xiàn)符號兼容性問題。解決方案靜態(tài)鏈接在編譯你的應(yīng)用程序時加上-static選項(xiàng)。這會將該程序依賴的所有庫包括glibc都靜態(tài)打包進(jìn)可執(zhí)行文件生成的文件會很大但兼容性最好。$PHYGCC_PREFIX/bin/gcc -O3 -static myapp.c -o myapp_static控制動態(tài)鏈接使用-Wl,-rpath,$PHYGCC_PREFIX/lib64將PhyGCC的庫路徑嵌入到可執(zhí)行文件中但要求目標(biāo)機(jī)器上相同路徑下有這些庫。統(tǒng)一環(huán)境最根本的辦法是在部署目標(biāo)機(jī)器上也安裝相同版本的PhyGCC或者確保生產(chǎn)環(huán)境的基礎(chǔ)庫版本與開發(fā)環(huán)境一致。6.4 性能提升不明顯問題現(xiàn)象使用了PhyGCC但程序跑分或?qū)嶋H業(yè)務(wù)性能提升微乎其微。原因分析編譯器優(yōu)化并非萬能。性能瓶頸可能不在CPU計(jì)算而在I/O、內(nèi)存帶寬、網(wǎng)絡(luò)或算法本身。排查思路確認(rèn)優(yōu)化選項(xiàng)檢查編譯命令是否包含了-O2或-O3以及-mcpuft2000等架構(gòu)特定選項(xiàng)。分析程序熱點(diǎn)使用性能剖析工具如gprof或perf找出程序中最耗時的函數(shù)。# 使用gprof $PHYGCC_PREFIX/bin/gcc -O3 -pg test.c -o test_gprof ./test_gprof gprof test_gprof gmon.out analysis.txt # 使用perf perf record ./test_program perf report檢查算法與數(shù)據(jù)結(jié)構(gòu)對于I/O密集型或存在大量條件分支的程序編譯器優(yōu)化空間有限。優(yōu)化算法如減少復(fù)雜度和數(shù)據(jù)結(jié)構(gòu)如提高緩存命中率往往更有效。對比匯編代碼使用-S選項(xiàng)生成匯編代碼對比PhyGCC和系統(tǒng)GCC在關(guān)鍵循環(huán)上的差異看指令調(diào)度、向量化等是否更優(yōu)。$PHYGCC_PREFIX/bin/gcc -O3 -S -mcpuft2000 test.c -o test_phy.s /usr/bin/gcc -O3 -S test.c -o test_sys.s diff -u test_sys.s test_phy.s | less7. 進(jìn)階配置與生態(tài)考量7.1 構(gòu)建完整的工具鏈一個完整的開發(fā)工具鏈不僅包括gcc還有g(shù)C、gfortranFortran、gdb調(diào)試器、binutils匯編器、鏈接器等。PhyGCC的源碼包通常包含了這些組件。我們的配置中通過--enable-languages指定了語言make install后這些工具都會安裝在$PHYGCC_PREFIX/bin下。如果你需要更專業(yè)的調(diào)試體驗(yàn)可以考慮單獨(dú)編譯和安裝針對飛騰優(yōu)化過的gdb但通常PhyGCC包內(nèi)集成的版本已足夠使用。7.2 與CMake、Autotools等構(gòu)建系統(tǒng)集成大型項(xiàng)目通常使用CMake或Autotools管理構(gòu)建。要讓它們使用PhyGCC可以通過環(huán)境變量或命令行參數(shù)指定。對于CMake項(xiàng)目mkdir build cd build export CC$PHYGCC_PREFIX/bin/gcc export CXX$PHYGCC_PREFIX/bin/g cmake -DCMAKE_C_COMPILER$CC -DCMAKE_CXX_COMPILER$CXX .. make對于Autotools項(xiàng)目./configure./configure CC$PHYGCC_PREFIX/bin/gcc CXX$PHYGCC_PREFIX/bin/g --prefix/your/install/path7.3 在持續(xù)集成CI環(huán)境中部署在團(tuán)隊(duì)開發(fā)或自動化構(gòu)建流水線中集成PhyGCC關(guān)鍵在于將安裝和配置步驟腳本化。你可以將編譯安裝好的$PHYGCC_PREFIX目錄打包成tar包存放在內(nèi)部文件服務(wù)器或制品倉庫中。在CI腳本如GitLab CI、Jenkins Pipeline中第一步就是下載并解壓這個工具鏈包然后設(shè)置環(huán)境變量。# CI腳本示例片段 TOOLCHAIN_URLhttp://internal-repo/toolchains/phy-gcc-10.2.0.tar.gz wget -q $TOOLCHAIN_URL -O phy-gcc.tar.gz tar -zxvf phy-gcc.tar.gz -C /opt export PATH/opt/phy-gcc-10.2.0/bin:$PATH # 后續(xù)執(zhí)行編譯命令...這種方式避免了在每次CI運(yùn)行時都花費(fèi)數(shù)小時從頭編譯PhyGCC極大地提升了效率。最后我想說的是在飛騰這樣的特定平臺上使用像PhyGCC這樣的定制化工具鏈?zhǔn)钦ジ捎布阅?、?gòu)建高性能原生應(yīng)用生態(tài)的重要一環(huán)。這個過程雖然前期有些繁瑣但一旦工具鏈就緒對于后續(xù)的軟件開發(fā)和性能調(diào)優(yōu)就是一次投入長期受益。尤其是在編譯像MySQL、PostgreSQL、OpenBLAS這樣的基礎(chǔ)軟件時性能收益會體現(xiàn)得更加明顯。我自己的經(jīng)驗(yàn)是在完成PhyGCC的部署后整個基于飛騰的研發(fā)和測試環(huán)境都感覺“順暢”了不少以前一些編譯時的警告和兼容性問題也少了。如果在安裝過程中遇到了上面沒覆蓋到的問題多關(guān)注編譯日志make.log的最后幾十行錯誤信息那通常是解決問題的關(guān)鍵線索。