Content
整体介绍
Scalasca是一个工具集,包括插桩工具Score-P, 后处理工具Cube等.
- scorep插桩
scalasca -instrument = skin = scorep
, skin过时了, 官方建议直接使用scorep
命令进行插桩.
需在编译器前加scorep
命令编译源码,如g++ -o main main.cpp
要变成scorep g++ -o main main.cpp
,实际操作比较灵活, 如可改变Makefile文件中CXX
等环境变量为CXX="scorep g++"
,也可以直接使用Score-p封装的command,如scorep-g++
进行编译,或者使用CXX=scorep-g++
等等.
scorep
默认自动插桩每一个函数的入口和出口,包括MPI函数.
默认插桩会产生太多测量数据, 尤其是项目比较大, 函数比较多的情况, 此时可使用选择性插桩方式进行过滤.详情见下文Scorep安装使用.
- 运行时配置
scalasca -analyze [options] [<launch_cmd> [<launch flags>]] <target> [<target_args>]
以mpi应用程序为例:
- launch_cmd = mpirun
- launch flags 是mpirun可运行选项如
-np 8
指定运行核心数 - target 是可执行文件
- target_args 是可执行文件的可选参数
完整的例子如:
scalasca -analyze mpirun -np 8 ./myapp
测量数据默认写到测量结果路径scorep_<target>_xx中.包括运行时间数据等.
event trace默认不打开, 打开需添加选项-t
如scalasca -analyze -t ...
或者设置环境变量export SCOREP_ENABLE_TRACING=1
. 但是需要注意, event trace数据很容易变得很大,需仔细配置选择性插桩文件等过滤措施.
- 分析数据
运行时收集的数据保存在cube4文件格式中, 此文件可使用如下命令进行处理
scalasca -examine [options] <experiment_name>
上面的命令会打开CubeGUI进行交互式的后处理. 也可使用-s
选项打印文本报告:
scalasca -examine -s <experiment_name>
也可直接使用cube
命令打开CubeGUI进行交互式后处理:
cube <experiment_name>
cube <file>.cubex
Scorep安装使用
根据scorep官方文档, 其可充当Scalasca, Vampir, Tau等性能测试工具的通用插桩器. 如何在Tau中使用暂不清楚.
支持phases, dynamic regions 和 parameter-based profiling, 需使用选择性插桩过滤文件.
Scorep支持MPI wait time prfiling,将MPI wait time单独作为一个度量进行统计.
Scorep支持tracing mode 和 profiling mode两种模式, tracing mode占用内存大,包括时间线的信息, profiling mode只包含call-path信息.
支持automatic插桩(compiler-based instrument)和manual插桩, compiler-based instrument对于小函数调用会产生相当大的测量负载,尤其是对c++项目中stl函数的插桩, 如begin,end,operator*() const, length(char const*)…, 并且使用基于编译器的自动化插桩无法阻止对这些函数的插桩.
Scorep同时支持插桩和采样两种性能测试方法, 插桩准确度最高但是会产生比较大的负载,采样可以通过控制采样频率达到准确度和负载的平衡.
Scorep常用运行时环境变量:
export SCOREP_ENABLE_PROFILING=true# or 1, 默认为true/1, 记录profiling数据
export SCOREP_ENABLE_TRACING=true# or 1, 默认为false/0, 用于记录event tracing 数据, 默认关闭
export SCOREP_PROFILING_MAX_CALLPATH_DEPTH=30#默认是30, 最大的call-path深度
export SCOREP_ENABLE_UNWINDING=false # 默认是false, true代表使用采样的方式来记录profiling和tracing数据,可以减小性能测试的负载, 但准确度(与采样频率有关)有所下降
export SCOREP_SAMPLING_EVENTS=perf_cycles@200000 #采样频率?
export SCOREP_EXPERIMENT_DIRECTORY=path_to_disired_directory #指定性能数据存储目录,默认在当前路径
export SCOREP_PROFILE_BASE_NAME=profile_name #默认是profile.cubex, 设置后为profile_name.cubex
export SCOREP_FILTERING_FILE=path_to_profiler #设置filtering file路径, 用于profile filtering
export SCOREP_SELECTIVE_CONFIG_FILE=path_to_config_file #设置config file路径, 用于selective record, 只适用于user instrument定义的region.
安装
- 安装binutils库, configure Scorep时需要.
sudo apt install binutils-dev
- 配置安装Scorep
../configure --prefix=/usr/local/scorep-8.4 --with-mpi=openmpi --with-shmem=openmpi
make
sudo make install
- 设置环境变量
PATH
,LD_LIBRARY_PATH
.
使用
Usage: scorep [options] <original command>
也可使用scorep的编译器wrapper, 如scorep-mpicxx
其展开为scorep $SCOREP_WRAPPER_INSTRUMENTER_FLAGS mpicxx $SCOREP_WRAPPER_COMPILER_FLAGS ...
, 此时[options]
通过设置SCOREP_WRAPPER_INSTRUMENTER_FLAGS环境变量进行控制.
基于编译器的自动插桩
只需在常规编译方式的编译器前加scorep前缀即可, 可通过改变上述环境变量来控制编译行为. 下面是常见的几种编译方式
- 源码直接编译
scorep-mpicxx main.cpp -o main
#或者
scorep mpicxx main.cpp -o main
- CMAKE
SCOREP_WRAPPER=off cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER=scorep-mpicc \
-DCMAKE_CXX_COMPILER=scorep-mpicxx \
..
make SCOREP_WRAPPER_INSTRUMENTER_FLAGS='--user --verbose' SCOREP_WRAPPER_COMPILER_FLAGS=''
- Makefile
#makefile中定义CC,CXX,MPICXX,MPICC
CC="scorep [options] gcc"
CXX="scorep [options] g++"
MPICXX="scorep [options] mpicxx"
MPICC="scorep [options] mpicc"
...
手动插桩
给自动插桩增加region或phase标识,用于改进性能报告的组织结构.
#include <scorep/SCOREP_User.h>
void foo()
{
SCOREP_USER_REGION_DEFINE( my_region_handle )
// more declarations
SCOREP_USER_REGION_BEGIN( my_region_handle, "foo",
SCOREP_USER_REGION_TYPE_COMMON )
// do something
SCOREP_USER_REGION_END( my_region_handle )
}
手动插桩需传递--user
选项给scorep
, 否则SCOREP_USER_REGION_XXX宏不起作用.
Filtering
Filtering文件格式如下
SCOREP_FILE_NAMES_BEGIN # This is a comment
EXCLUDE */filtering/filter* # 可使用bash-like通配符, 不同的是*可匹配路径
INCLUDE */filter_test.c
SCOREP_FILE_NAMES_END
SCOREP_REGION_NAMES_BEGIN # This is a comment
EXCLUDE myfunc
SCOREP_REGION_NAMES_END
运行时设置环境变量SCOREP_FILTERING_FILE指向过滤文件export SCOREP_FILTERING_FILE=xxx
.
对于c++项目来说, 编译器会改变函数的名字(mangled), 如myadd经过编译器会变成mangled名字_Z5myaddii, 此时过滤文件中EXCLUDE myadd
不起作用, 测试发现需改成EXCLUDE MANGLED _Z5myaddii
才行.
Scorep性能分析一般流程
- 对应用程序进行插桩
- 执行一次插桩程序运行并记录一个profile
- 使用scorep-score为应用程序定义适当的filter file,否则跟踪文件可能会变成太大。
用法: scorep-score [options] <profile>
- -r, 显示所有regions:
scorep-score -r profile.cubex > scorep.score
- -s <choice>, 对结果进行排序, 可选totaltime,timepervisit, maxbuffer(default), visits, name, 如
scorep-score -r -s totaltime profile.cubex > scorep.score
- -g [<list>] , 自动生成过滤文件initial_scorep.filter, 默认list是bufferpercent=1,timepervisit=1,如
scorep-score -g bufferpercent=0.005,timepervisit=2 profile.cubex
- -f <filter>, 将生成的filter应用到score文件中,
scorep-score -r -s totaltime -f initial_scorep.filter > scorep_filter.score
重复上述步骤,直至满足内存占用要求(一般认为full trace的内存占用<10GB是可以接受的见此文章).
- 在启用了trace并应用了filter-file的情况下执行一次插桩程序运行
- 对跟踪数据执行深入分析
CUBE教程
CUBE性能空间分三个维度, 在CUBE软件中分三列: Metri dimension, program dimension 和 system dimension.
- Metri dimension: 总时间,总访问数,传递消息大小等
- program dimension: 包含程序的call path, 调用树,与Metri对应,如时间树等
- system dimension: 代表每个树节点的metri在不同节点/进程/线程上的分布.
Advior插件的性能参数解读
Only-MPI Assessment
Parallel_Efficiency = Load_Balance_Efficiency * Communication_Efficiency, 简化成
P E = L B ∗ C o m m E PE=LB*CommE PE=LB∗CommE
其中, L B = a v g ( c o m p u t a t i o n t i m e ) / m a x ( c o m p u t a t i o n t i m e ) LB=avg(computation time) / max(computation time) LB=avg(computationtime)/max(computationtime), computation_time排除MPI等待和传输时间? 有Time Metri即可.
C o m m E = m a x i m u m _ a c r o s s _ p r o c e s s e s ( c o m p u t a t i o n _ t i m e / t o t a l _ r u n t i m e ) CommE=maximum\_across\_processes(computation\_time/total\_runtime) CommE=maximum_across_processes(computation_time/total_runtime), 比值越高说明MPI等待和传输时间越低, 通信效率越高. 有Time Metri即可.
CommE又可以进一步分解成Serialisation Efficiency(SerE)和 Transfer Efficiency(TE), 但需要trace analysis数据:
C o m m E = S e r E ∗ T E CommE = SerE * TE CommE=SerE∗TE
SerE = maximum_across_processes(computation_time/total_runtime_on_ideal_network), total_runtime_on_ideal_network不包含MPI wait time 和 IO time. 这不跟computation_time一样了吗,剔除wait time和IO time?
TE = maximum_across_processes(total_runtime_on_ideal_network)/maximum_across_processes(total_measured_runtime), 越接近