將螺旋槳與 Linux 核心一起使用

在使用 Clang 編譯器時,這可以為核心啟用螺旋槳構建支援。螺旋槳是一種配置檔案引導最佳化 (PGO) 方法,用於最佳化二進位制可執行檔案。與 AutoFDO 類似,它利用硬體取樣來收集關於二進位制檔案中不同程式碼路徑執行頻率的資訊。與 AutoFDO 不同,這些資訊在連結階段之前立即使用,以最佳化函式內部和跨函式的塊佈局等。

關於採用螺旋槳最佳化的一些重要注意事項

  1. 雖然它可以作為獨立的最佳化步驟使用,但強烈建議在 AutoFDO、AutoFDO+ThinLTO 或 Instrument FDO 之上應用螺旋槳。本文件的其餘部分假設了這種模式。

  2. 螺旋槳在 AutoFDO/AutoFDO+ThinLTO/iFDO 之上使用了另一輪分析。整個構建過程包括“build-afdo - train-afdo - build-propeller - train-propeller - build-optimized”。

  3. 螺旋槳需要 LLVM 19 或更高版本才能使用 Clang/Clang++ 和連結器 (ld.lld)。

  4. 除了 LLVM 工具鏈之外,螺旋槳還需要一個分析轉換工具:https://github.com/google/autofdo,版本必須在 v0.30.1 之後:https://github.com/google/autofdo/releases/tag/v0.30.1

螺旋槳最佳化過程包括以下步驟

  1. 初始構建:像往常一樣構建 AutoFDO 或 AutoFDO+ThinLTO 二進位制檔案,但使用一組編譯時/連結時標誌,以便在核心二進位制檔案中建立一個特殊的元資料部分。該特殊部分僅供分析工具使用,它不是執行時映象的一部分,也不會更改核心執行時文字段。

  2. 分析:然後,使用代表性工作負載執行上述核心,以收集執行頻率資料。此資料使用硬體取樣透過 perf 收集。螺旋槳在支援高階 PMU 功能(如 Intel 機器上的 LBR)的平臺上最有效。此步驟與為 AutoFDO 分析核心相同(確切的 perf 引數可能不同)。

  3. 螺旋槳配置檔案生成:Perf 輸出檔案透過離線工具轉換為一對螺旋槳配置檔案。

  4. 最佳化構建:像往常一樣構建 AutoFDO 或 AutoFDO+ThinLTO 最佳化二進位制檔案,但使用編譯時/連結時標誌來獲取螺旋槳編譯時和連結時配置檔案。此構建步驟使用 3 個配置檔案 - AutoFDO 配置檔案、螺旋槳編譯時配置檔案和螺旋槳連結時配置檔案。

  5. 部署:最佳化的核心二進位制檔案部署並在生產環境中使用,從而提高效能並減少延遲。

準備工作

使用以下配置核心

CONFIG_AUTOFDO_CLANG=y
CONFIG_PROPELLER_CLANG=y

自定義

預設的 CONFIG_PROPELLER_CLANG 設定涵蓋螺旋槳構建的核心空間物件。但是,可以透過將類似於以下行的程式碼新增到相應的核心 Makefile 中來為單個檔案和目錄啟用或停用螺旋槳構建

  • 對於啟用單個檔案(例如 foo.o)

    PROPELLER_PROFILE_foo.o := y
    
  • 對於啟用一個目錄中的所有檔案

    PROPELLER_PROFILE := y
    
  • 對於停用一個檔案

    PROPELLER_PROFILE_foo.o := n
    
  • 對於停用一個目錄中的所有檔案

    PROPELLER__PROFILE := n
    

工作流程

這是一個構建 AutoFDO+螺旋槳核心的工作流程示例

  1. 假設已按照 AutoFDO 文件中的說明收集了 AutoFDO 配置檔案,請使用 AutoFDO 和螺旋槳構建配置在主機上構建核心

    CONFIG_AUTOFDO_CLANG=y
    CONFIG_PROPELLER_CLANG=y
    

    $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<autofdo-profile-name>
    
  2. 將核心安裝在測試機器上。

  3. 執行負載測試。perf 中的“-c”選項指定取樣事件週期。我們建議為此目的使用合適的素數,例如 500009。

    • 對於 Intel 平臺

      $ perf record -e BR_INST_RETIRED.NEAR_TAKEN:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
      
    • 對於 AMD 平臺

      $ perf record --pfm-event RETIRED_TAKEN_BRANCH_INSTRUCTIONS:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
      

    請注意,您可以重複上述步驟以收集多個 <perf_file>。

  4. (可選)將原始 perf 檔案下載到主機。

  5. 使用 create_llvm_prof 工具 (https://github.com/google/autofdo) 生成螺旋槳配置檔案。

    $ create_llvm_prof --binary=<vmlinux> --profile=<perf_file>
                       --format=propeller --propeller_output_module_name
                       --out=<propeller_profile_prefix>_cc_profile.txt
                       --propeller_symorder=<propeller_profile_prefix>_ld_profile.txt
    

    “<propeller_profile_prefix>”可以是類似“/home/user/dir/any_string”的內容。

    此命令生成一對螺旋槳配置檔案:“<propeller_profile_prefix>_cc_profile.txt”和“<propeller_profile_prefix>_ld_profile.txt”。

    如果在上一步中收集了多個 perf_file,您可以建立一個臨時列表檔案“<perf_file_list>”,其中每行包含一個 perf 檔名,並執行

    $ create_llvm_prof --binary=<vmlinux> --profile=@<perf_file_list>
                       --format=propeller --propeller_output_module_name
                       --out=<propeller_profile_prefix>_cc_profile.txt
                       --propeller_symorder=<propeller_profile_prefix>_ld_profile.txt
    
  6. 使用 AutoFDO 和螺旋槳配置檔案重建核心。

    CONFIG_AUTOFDO_CLANG=y
    CONFIG_PROPELLER_CLANG=y
    

    $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<profile_file> CLANG_PROPELLER_PROFILE_PREFIX=<propeller_profile_prefix>