将 AutoFDO 用于 Linux 内核

这在使用 Clang 编译器时启用内核的 AutoFDO 构建支持。 AutoFDO(自动反馈定向优化)是一种配置文件引导优化 (PGO),用于增强二进制可执行文件的性能。 它使用硬件采样来收集二进制文件中各种代码路径执行频率的信息。 然后,此数据用于指导编译器的优化决策,从而产生更高效的二进制文件。 AutoFDO 是一种强大的优化技术,数据显示它可以显着提高内核性能。 它对于受前端停顿影响的工作负载特别有益。

对于 AutoFDO 构建,与非 FDO 构建不同,用户必须提供配置文件。 获取 AutoFDO 配置文件可以通过多种方式完成。 AutoFDO 配置文件是通过使用“perf”工具转换硬件采样来创建的。 至关重要的是,用于创建这些 perf 文件的工作负载具有代表性; 它们必须表现出与旨在优化的工作负载相似的运行时特性。 否则将导致编译器针对错误的目标进行优化。

AutoFDO 配置文件通常封装了程序的行为。 如果性能关键代码与架构无关,则可以将该配置文件应用于跨平台,以实现性能提升。 例如,使用在 Intel 架构上生成的配置文件来构建 AMD 架构的内核也可以产生性能改进。

有两种方法可以获取有代表性的配置文件:(1)使用生产环境中的实际工作负载进行采样。(2)使用有代表性的负载测试生成配置文件。 在启用 AutoFDO 构建配置而不提供 AutoFDO 配置文件时,编译器只会修改内核中的 dwarf 信息,而不会影响运行时性能。 建议使用使用相同的 AutoFDO 配置构建的内核二进制文件来收集 perf 配置文件。 虽然可以使用使用不同选项构建的内核,但可能会导致性能下降。

可以使用先前内核的 AutoFDO 构建来收集配置文件。 AutoFDO 采用相对行号来匹配配置文件,从而为源代码更改提供了一定的容忍度。 此模式通常用于生产环境中进行配置文件收集。

在基于负载测试的配置文件收集过程中,AutoFDO 收集过程包括以下步骤

  1. 初始构建:使用 AutoFDO 选项构建内核,但不使用配置文件。

  2. 分析:然后使用上述内核运行有代表性的工作负载以收集执行频率数据。 此数据通过 perf 使用硬件采样来收集。 AutoFDO 在支持高级 PMU 功能(例如 Intel 机器上的 LBR)的平台上最为有效。

  3. AutoFDO 配置文件生成:Perf 输出文件通过离线工具转换为 AutoFDO 配置文件。

该支持需要 Clang 编译器 LLVM 17 或更高版本。

准备工作

使用以下命令配置内核

CONFIG_AUTOFDO_CLANG=y

定制

默认的 CONFIG_AUTOFDO_CLANG 设置涵盖 AutoFDO 构建的内核空间对象。 但是,可以通过将类似于以下内容的行添加到相应的内核 Makefile 中来启用或禁用单个文件和目录的 AutoFDO 构建

  • 对于启用单个文件 (例如 foo.o)

    AUTOFDO_PROFILE_foo.o := y
    
  • 对于启用一个目录中的所有文件

    AUTOFDO_PROFILE := y
    
  • 对于禁用一个文件

    AUTOFDO_PROFILE_foo.o := n
    
  • 对于禁用一个目录中的所有文件

    AUTOFDO_PROFILE := n
    

工作流程

以下是 AutoFDO 内核的示例工作流程

  1. 在主机上启用 LLVM 构建内核,例如,

    $ make menuconfig LLVM=1
    

    启用 AutoFDO 构建配置

    CONFIG_AUTOFDO_CLANG=y
    

    使用启用 LLVM 的配置,使用以下命令

    $ scripts/config -e AUTOFDO_CLANG
    

    获得配置后,使用以下命令构建

    $ make LLVM=1
    
  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 平台

      支持的系统有:带有 BRS 的 Zen3 或带有 amd_lbr_v2 的 Zen4。 要检查,

      对于 Zen3

      $ cat proc/cpuinfo | grep " brs"
      

      对于 Zen4

      $ cat proc/cpuinfo | grep amd_lbr_v2
      

      以下命令生成 perf 数据文件

      $ perf record --pfm-events RETIRED_TAKEN_BRANCH_INSTRUCTIONS:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
      
  4. (可选) 将原始 perf 文件下载到主机。

  5. 要生成 AutoFDO 配置文件,可以使用两个离线工具:create_llvm_prof 和 llvm_profgen。 create_llvm_prof 工具是 AutoFDO 项目的一部分,可以在 GitHub 上找到 (https://github.com/google/autofdo),版本 v0.30.1 或更高版本。 llvm_profgen 工具包含在 LLVM 编译器本身中。 重要的是要注意 llvm_profgen 的版本不需要与 Clang 的版本匹配。 它需要是 Clang 的 LLVM 19 版本或更高版本,或者只是来自 LLVM 主干。

    $ llvm-profgen --kernel --binary=<vmlinux> --perfdata=<perf_file> -o <profile_file>
    

    $ create_llvm_prof --binary=<vmlinux> --profile=<perf_file> --format=extbinary --out=<profile_file>
    

    请注意,可以通过以下方式将多个 AutoFDO 配置文件合并为一个

    $ llvm-profdata merge -o <profile_file> <profile_1> <profile_2> ... <profile_n>
    
  6. 使用 AutoFDO 配置文件(使用与步骤 1 相同的配置)重建内核,(注意 CONFIG_AUTOFDO_CLANG 需要启用)

    $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<profile_file>