PGO 优化
两种方案:Linux C/C++ PGO优化说明_-fprofile-instr-generate-CSDN博客
来源:11-7.基于性能分析引导的优化(PGO) · 现代CPU上的性能分析与优化
目前在x86的pc机上使用交叉编译工具,使用-fprofile-generate -fprofile-correction选项生成插桩后的二进制目标文件,然后在嵌入式平台上运行,然后将生成的profile文件放回到pc机上二次编译,该怎么做
分步解决方案
在 交叉编译环境 中使用 GCC 的 Profile-Guided Optimization (PGO) 时,需确保插桩生成的 .gcda
文件路径在主机(PC)与目标机(嵌入式平台)之间正确映射。以下是详细操作步骤:
1. 插桩编译:生成带 Profile 采集的可执行文件
步骤
-
设置交叉编译工具链:
export CC=arm-linux-gnueabihf-gcc export CXX=arm-linux-gnueabihf-g++
-
编译时指定 Profile 数据生成路径:
# 使用 -fprofile-generate 并指定生成路径(主机端路径) $CXX -fprofile-generate=/host/path/to/profiles -O2 -o your_program your_source.cpp
- 关键选项:
-fprofile-generate=DIR
:强制生成.gcda
到指定目录(需适配目标机路径映射)。
- 关键选项:
2. 在嵌入式平台运行并生成 Profile 数据
步骤
-
将可执行文件传输到嵌入式平台:
scp your_program user@embedded-device:/path/to/run/
-
运行程序生成
.gcda
文件:# 在嵌入式设备上执行(确保程序退出正常) cd /path/to/run/ ./your_program
-
收集
.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
-
设置环境变量(二次编译时):
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 数据优化代码
步骤
-
使用
-fprofile-use
指定 Profile 路径:$CXX -fprofile-use=/host/path/to/profiles -O2 -o your_program_optimized your_source.cpp
-
验证路径映射:
- 确保编译器能找到
.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 数据路径不一致的问题。核心步骤为:
- 插桩编译:指定 Profile 生成路径。
- 目标机运行:生成数据并传回主机。
- 路径映射:通过环境变量或目录重组对齐路径。
- 二次编译:使用优化后的 Profile 数据。