性能分析过程
前提条件
- 服务器和操作系统正常运行。
- PC端已经安装SSH远程登录工具。
- 目标环境上
鲲鹏性能定界工具 、系统性能分析工具已经安装完成,并正常运行。
操作步骤
- 从GitHub下载cpu_branch_prediction_before.cpp文件,上传到“/home/demo”目录,执行如下命令切换至源码目录。
cd /home/demo
- 编译源码文件。
g++ -o cpu_branch_prediction_before cpu_branch_prediction_before.cpp
- 查看应用运行时间。
time /home/demo/cpu_branch_prediction_before
执行命令后,发现应用的运行时间为61秒。可使用鲲鹏性能定界工具定位应用有无性能问题,若应用中确实存在优化项则优化源代码。当前应用运行时间作为时间开销的基线。
图1 运行时间
- 使用鲲鹏性能定界工具定位问题。进入鲲鹏性能定界工具安装目录,xxx指版本号,请根据实际情况替换。
cd /home/ksys-x.x.x-Linux-aarch64
- 采集应用的性能数据。
./ksys collect /home/demo/cpu_branch_prediction_before
/home/demo/cpu_branch_prediction_before:指定采集的应用。
图2 微架构统计数据
在微架构统计数据部分,可以看出Bad speculation(%)中的Branch Mispredicts(%)较高,Branch Mispredicts即分支预测错误,该指标的数值是指在程序运行期间CPU发生了多少次分支预测错误。在CPU流水线中,一次分支预测错误会带来较大的时间开销,即Branch Mispredicts指标越高,分支预测失败次数越多,CPU额外开销越大,对应性能越差。鲲鹏性能定界工具采集的Topdown指标是系统性能分析工具微架构分析采集的子集,想要看到更详细的指标推荐使用系统性能分析工具的微架构分析。
- 使用系统性能分析工具进一步分析程序。切换至系统性能分析工具安装目录,xxx指版本号,请根据实际情况替换。
cd /home/DevKit-Tuner-CLI-x.x.x-Linux-Kunpeng
- 使用系统性能分析工具对应用进行微架构分析。
./devkit tuner top-down -d 30 /home/demo/cpu_branch_prediction_before
- -d 30:指定采集时间为30秒。
- “/home/demo/cpu_branch_prediction_before”:指定采集的应用。
图3 微架构分析报告
查看微架构分析报告,发现其中Branch Mispredicts下的Other Branch占比较高,也就是Branch Mispredicts占比高,与鲲鹏性能定界工具定位结果相同,说明程序中CPU分支预测失败较多,需关注源代码中的条件跳转/无条件直接跳转。
每种Branch对应含义以及常见源代码使用场景:
- Indirect Branch:间接分支。跳转目标地址不是立即数,而是来自寄存器或者内存,常见于虚函数、函数指针、switch跳转表。
- Push Branch:入栈分支。对应x86的汇编命令为call,对应Arm的汇编命令为bl,常见于函数的调用。
- Pop Branch:出栈分支。对应x86和Arm的汇编命令为ret,常见于函数的返回。
- Other Branch:其他分支。条件跳转和无条件直接跳转,常见于if-else/for/while/do-while/三元运算符/break/continue/goto等代码。
- 查看源码文件,确定源码问题。
vim /home/demo/cpu_branch_prediction_before.cpp
图4 源码文件
源码中对生成的每个随机数都进行if-else判断,在生成的随机数没有进行排序时,CPU分支预测失败率较高,频繁切换策略导致耗时较长。
父主题: 实践1:微架构分析