You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在CMake中实现类似Makefile的-fprofile-arcs性能分析流程?

低版本CMake实现Makefile风格的PGO性能优化流程

针对遗留项目(独立构建目录、CMake <3.10),要实现Makefile中-fprofile-arcs生成profile数据、再用-fbranch-probabilities编译优化库的逻辑,可通过以下两种方案实现,核心是分阶段控制编译标志、保护*.gcda文件不被误删。

方案1:CMake自定义目标封装全流程

此方案无需额外脚本,直接在原有CMakeLists中添加逻辑,兼容CMake 2.8+。

核心修改(根CMakeLists.txt)

cmake_minimum_required(VERSION 2.8)
project(legacy_project)

# 控制PGO阶段的开关,默认关闭(第一阶段)
option(USE_PGO "Enable profile-guided optimization" OFF)

# 定义profile数据存储目录,避免gcda被误删
set(PROFILE_DIR ${CMAKE_BINARY_DIR}/profile_data)
file(MAKE_DIRECTORY ${PROFILE_DIR})

# 根据PGO阶段设置编译标志
if(USE_PGO)
  # 第二阶段:基于分支概率优化编译
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fbranch-probabilities -fprofile-dir=${PROFILE_DIR}")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fbranch-probabilities -fprofile-dir=${PROFILE_DIR}")
else()
  # 第一阶段:生成profile数据的编译配置
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -fprofile-dir=${PROFILE_DIR}")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -fprofile-dir=${PROFILE_DIR}")
endif()

# ------------------- 原有项目构建逻辑 -------------------
add_library(legacy_lib src/lib1.c src/lib2.cpp)
add_executable(benchmark src/benchmark.c)
target_link_libraries(benchmark legacy_lib)

# 添加测试目标(假设原有测试目标为all_tests)
add_custom_target(all_tests DEPENDS test1 test2)
# -------------------------------------------------------

# 自定义目标:运行基准程序生成gcda文件
add_custom_target(run_benchmark
  COMMAND $<TARGET_FILE:benchmark>
  # 若基准程序需要特定工作目录,添加以下行
  # WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/benchmark_data
  DEPENDS benchmark
  COMMENT "Running benchmark to generate profile data..."
)

# 自定义目标:清理库文件(仅删目标文件和库,保留profile数据)
get_target_property(LIB_FILE legacy_lib LOCATION)
get_target_property(LIB_OBJ_DIR legacy_lib BINARY_DIR)
set(LIB_SRC_OBJ_DIR "${LIB_OBJ_DIR}/CMakeFiles/legacy_lib.dir/src")

add_custom_target(clean_lib
  COMMAND ${CMAKE_COMMAND} -E remove ${LIB_FILE}
  COMMAND ${CMAKE_COMMAND} -E remove ${LIB_SRC_OBJ_DIR}/*.o
  COMMAND ${CMAKE_COMMAND} -E remove ${LIB_SRC_OBJ_DIR}/*.obj
  COMMENT "Cleaning legacy library object files (keeping profile data)..."
)

# 自定义目标:一键执行完整PGO流程
add_custom_target(pgo_full
  # 第一阶段:构建带profile的基准程序
  COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target benchmark
  # 运行基准生成gcda
  COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target run_benchmark
  # 清理旧库文件
  COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target clean_lib
  # 重新配置为PGO优化模式
  COMMAND ${CMAKE_COMMAND} -DUSE_PGO=ON ${CMAKE_SOURCE_DIR}
  # 第二阶段:构建优化后的库和测试
  COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target legacy_lib all_tests
  COMMENT "Executing full PGO optimization workflow..."
)

使用方式

  1. 初始化构建目录:
mkdir build && cd build
cmake ..
  1. 执行完整PGO流程:
make pgo_full
# 若用Ninja构建:ninja pgo_full

关键细节

  • 用PROFILE_DIR统一存储*.gcda,避免清理时误删;编译时通过-fprofile-dir指定路径,确保编译器能正确读写数据。
  • clean_lib仅删除库文件和目标文件(*.o/*.obj),保留profile数据目录和文件。
  • 兼容CMake 2.8:用get_target_property替代高版本generator表达式,确保路径获取可靠。

方案2:Shell脚本包装流程(更灵活)

若项目CMake逻辑复杂,自定义目标难以适配,可直接用Shell脚本封装全流程,完全规避CMake版本限制。

示例脚本(run_pgo.sh)

#!/bin/bash
set -e

# 构建目录路径
BUILD_DIR="./build"
PROFILE_DIR="${BUILD_DIR}/profile_data"

# 初始化构建目录
mkdir -p ${BUILD_DIR}
cd ${BUILD_DIR}

# ------------------- 第一阶段:生成profile数据 -------------------
echo "=== Phase 1: Building benchmark with profile generation ==="
cmake .. -DUSE_PGO=OFF
make benchmark

echo "=== Running benchmark to generate gcda files ==="
./benchmark

# ------------------- 清理旧库文件 -------------------
echo "=== Cleaning legacy library files (keeping profile data) ==="
# 替换为你的库文件路径,比如静态库liblegacy_lib.a或动态库liblegacy_lib.so
LIB_FILE="./liblegacy_lib.a"
LIB_OBJ_DIR="./CMakeFiles/legacy_lib.dir/src"

rm -f ${LIB_FILE}
rm -f ${LIB_OBJ_DIR}/*.o

# ------------------- 第二阶段:构建优化后的库和测试 -------------------
echo "=== Phase 2: Building optimized library with branch probabilities ==="
cmake .. -DUSE_PGO=ON
make legacy_lib all_tests

echo "=== PGO optimization completed ==="

使用方式

  1. 给脚本添加执行权限:
chmod +x run_pgo.sh
  1. 执行脚本:
./run_pgo.sh

优势

  • 逻辑直观,完全复刻Makefile的分步流程,无需修改原有CMake代码。
  • 对复杂项目兼容性更好,可灵活调整各步骤的命令(比如添加环境变量、修改清理规则等)。

内容的提问来源于stack exchange,提问作者deamentiaemundi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:15:17