安装AMD uProf后需手动将/opt/amd-uprof/bin加入PATH或直接调用完整路径;分析AOT程序须编译时加-g和-O2、禁用strip,并确保符号表完整;报错Failed to initialize perf event subsystem通常因perf_event_paranoid值过高或CPU不支持Zen2+架构。

amd-u-profiler 安装后 uprof 命令找不到
AMD uProf(全称 AMD microarchitecture profiler)不是系统自带工具,安装完不自动加到 $PATH 里是常态。它默认装在 /opt/amd-uprof/ 下,可执行文件实际路径是 /opt/amd-uprof/bin/uprof。
- 运行前先确认路径是否存在:
ls /opt/amd-uprof/bin/uprof - 临时使用:直接调用完整路径,比如
/opt/amd-uprof/bin/uprof --help - 长期使用:把
/opt/amd-uprof/bin加进 shell 配置(如~/.bashrc中加export PATH="/opt/amd-uprof/bin:$PATH"),然后source ~/.bashrc - 注意:uProf 仅支持 Linux,且要求内核启用
perf_event_paranoid(建议设为-1或0),否则会报Permission denied错误
用 uprof 分析 C++ AOT 编译程序(如 ROCm HIP 应用)
AOT(Ahead-of-Time)编译的 C++ 程序(比如用 hipcc 编译的 HIP 二进制)没有 JIT 符号,uprof 默认只能看到地址和汇编,看不到函数名。关键在于让 profiler 能读到符号表和调试信息。
- 编译时必须加
-g(生成 DWARF),推荐同时加-O2(AOT 性能分析不能关优化,否则热点失真) - 避免 strip:确保最终二进制没被
strip过;如果用了 CMake,检查是否启用了INSTALL_STRIP或类似逻辑 - 运行命令示例:
uprof --mode=cpu --output=uprof-result.uprof ./my_aot_app,其中--mode=cpu是最常用模式,抓 CPU 指令周期、缓存缺失等微架构事件 - 注意:uProf 不支持直接分析 GPU kernel 的执行时间(那是
rocprof的事),它只看 CPU 侧调度、访存、分支预测等行为
uprof 报错 Failed to initialize perf event subsystem
这个错误基本锁定在内核权限或硬件兼容性上,不是程序写错了。uProf 依赖 Linux perf_events 接口,而该接口受安全策略限制。
- 检查当前值:
cat /proc/sys/kernel/perf_event_paranoid,值 ≥ 2 就会拒绝非 root 用户采集;临时修复:sudo sysctl -w kernel.perf_event_paranoid=-1 - 某些云环境或容器中,
perf_event_paranoid可能被硬限制,此时只能用 root 运行uprof(不推荐,有安全风险) - 确认 CPU 是否被支持:uProf 当前(v4.0+)只支持 AMD Zen2 及更新架构(如 EPYC 7xx2/9xx4、Ryzen 4000+/6000+),Zen1 和 Intel CPU 会静默失败或只返回空结果
- 别混淆
uprof和perf:虽然底层都用 perf_events,但 uProf 的采样精度和事件定义更贴近 AMD 微架构,不能靠perf record替代
导出结果后看不到 C++ 函数名,只有 [unknown]
符号解析失败是 uProf 最常见的“看得见但看不懂”问题。它不像 gprof 那样依赖插桩,而是靠运行时读取 ELF 的 .symtab 和 .debug_* 段,任一环节断掉就退化成地址流。
立即学习“C++免费学习笔记(深入)”;
- 验证符号存在:
readelf -S ./my_aot_app | grep -E "(symtab|debug)",应至少看到.symtab和.debug_info - 如果用了 LTO(
-flto),需额外加-grecord-gcc-switches,否则链接阶段可能丢调试信息 - 动态链接库(如
libhip.so)的符号默认不加载,若热点在驱动层,需手动指定:uprof --add-lib-path=/opt/rocm/lib ... - GUI 工具
uprof-gui比命令行更容错,建议先用它打开.uprof文件——有时 CLI 输出没刷新,GUI 却能正确关联符号
C++ AOT 场景下,符号完整性比运行时环境更难保障;哪怕编译参数全对,CI 流水线里的 strip 步骤、Docker 构建时的多阶段 COPY、甚至 rsync 的默认选项,都可能悄悄删掉 .debug_* 段。做性能归因前,先 file 和 readelf 看一眼二进制,比直接跑 profiler 更省时间。











