PGO 优化

两种方案:Linux C/C++ PGO优化说明_-fprofile-instr-generate-CSDN博客

 

来源:11-7.基于性能分析引导的优化(PGO) · 现代CPU上的性能分析与优化

 

覆盖率 - 标签 - KK_Yolanda - 博客园

 

目前在x86的pc机上使用交叉编译工具,使用-fprofile-generate -fprofile-correction选项生成插桩后的二进制目标文件,然后在嵌入式平台上运行,然后将生成的profile文件放回到pc机上二次编译,该怎么做

分步解决方案

在 交叉编译环境 中使用 GCC 的 Profile-Guided Optimization (PGO) 时,需确保插桩生成的 .gcda 文件路径在主机(PC)与目标机(嵌入式平台)之间正确映射。以下是详细操作步骤:


1. 插桩编译:生成带 Profile 采集的可执行文件

步骤

  1. 设置交叉编译工具链:

    export CC=arm-linux-gnueabihf-gcc
    export CXX=arm-linux-gnueabihf-g++
    
     
  2. 编译时指定 Profile 数据生成路径:

    # 使用 -fprofile-generate 并指定生成路径(主机端路径)
    $CXX -fprofile-generate=/host/path/to/profiles -O2 -o your_program your_source.cpp
    
     
    • 关键选项:
      • -fprofile-generate=DIR:强制生成 .gcda 到指定目录(需适配目标机路径映射)。

2. 在嵌入式平台运行并生成 Profile 数据

步骤

  1. 将可执行文件传输到嵌入式平台:

    scp your_program user@embedded-device:/path/to/run/
    
     
  2. 运行程序生成 .gcda 文件:

    # 在嵌入式设备上执行(确保程序退出正常)
    cd /path/to/run/
    ./your_program
    
     
  3. 收集 .gcda 文件:

    # 在嵌入式设备上打包数据
    tar czf profiles.tar.gz /path/to/run/*.gcda
    
    # 将数据传回主机
    scp user@embedded-device:/path/to/run/profiles.tar.gz /host/path/to/profiles/
    
     

3. 调整路径映射(关键步骤)

由于嵌入式平台的路径(如 /path/to/run/)与主机不同,需通过 环境变量 将目标机路径映射到主机路径。

方法 1:使用 GCOV_PREFIX 和 GCOV_PREFIX_STRIP

  1. 设置环境变量(二次编译时):

    export GCOV_PREFIX="/host/path/to/profiles"      # 主机上存储 .gcda 的目录
    export GCOV_PREFIX_STRIP=3                       # 剥离目标机路径的前3级目录
    
     
    • 示例:
      • 目标机路径:/path/to/run/your_program.gcda
      • 剥离后路径:/host/path/to/profiles/run/your_program.gcda

方法 2:手动复制并保持路径一致

将目标机的 .gcda 文件按原路径结构复制到主机:

# 在主机上创建模拟路径
mkdir -p /host/path/to/profiles/path/to/run/

# 解压目标机传回的 profiles.tar.gz 到对应目录
tar xzf profiles.tar.gz -C /host/path/to/profiles/path/to/run/
 

4. 二次编译:使用 Profile 数据优化代码

步骤

  1. 使用 -fprofile-use 指定 Profile 路径:

    $CXX -fprofile-use=/host/path/to/profiles -O2 -o your_program_optimized your_source.cpp
    
     
  2. 验证路径映射:

    • 确保编译器能找到 .gcda 文件:
      find /host/path/to/profiles -name "*.gcda"
      
       

5. 完整操作示例

插桩编译(主机端)

# 设置交叉编译工具链
export CC=arm-linux-gnueabihf-gcc
export CXX=arm-linux-gnueabihf-g++

# 编译插桩版本,指定 Profile 生成路径
$CXX -fprofile-generate=/host/pfs/profiles -O2 -o my_app main.cpp

# 传输到嵌入式设备
scp my_app user@embedded-device:/app/
 

在嵌入式设备运行

# 运行程序
cd /app
./my_app

# 打包 .gcda 文件
tar czf /tmp/profiles.tar.gz *.gcda
 

传回主机并调整路径

# 将数据传回主机
scp user@embedded-device:/tmp/profiles.tar.gz /host/pfs/

# 解压到 Profile 目录
mkdir -p /host/pfs/profiles
tar xzf /host/pfs/profiles.tar.gz -C /host/pfs/profiles

# 设置路径映射(假设嵌入式路径为 /app/)
export GCOV_PREFIX="/host/pfs/profiles"
export GCOV_PREFIX_STRIP=1  # 剥离 /app/ 的1级目录
 

二次编译(主机端)

$CXX -fprofile-use=/host/pfs/profiles -O2 -o my_app_optimized main.cpp
 

常见问题与解决

问题解决方案
二次编译时报错找不到 .gcda 检查 GCOV_PREFIX 和 GCOV_PREFIX_STRIP 是否匹配目标机路径结构。
Profile 数据为空(覆盖率0%) 确保程序在嵌入式设备上运行了完整流程,覆盖目标代码路径。
路径层级不匹配 调整 GCOV_PREFIX_STRIP 的值,或手动重组 .gcda 文件的目录结构。

总结

通过合理配置 GCOV_PREFIX 和 GCOV_PREFIX_STRIP,可解决交叉编译环境下 Profile 数据路径不一致的问题。核心步骤为:

  1. 插桩编译:指定 Profile 生成路径。
  2. 目标机运行:生成数据并传回主机。
  3. 路径映射:通过环境变量或目录重组对齐路径。
  4. 二次编译:使用优化后的 Profile 数据。
posted @ 2025-02-17 17:26  墨尔基阿德斯  阅读(113)  评论(0)    收藏  举报