前阵子帮组里一位做流体仿真的同事搭性能分析环境,他那边攒了几个跑得很慢的 MPI 作业,程序本身没有报错,但就是能用一半核不干活的那种“匀速慢”。我想着用 Score-P 和 Scalasca 这套组合给他做一次插桩和同步错误检查,结果装工具这一步就花掉了大半个下午——不是下载慢,而是版本匹配、依赖顺序、编译器 wrapper 这些细节环环相扣,稍不注意 configure 就给你撂挑子。
这篇不是官方文档的搬运,是我实际装完一遍踩完坑之后的完整记录。里面会讲到为什么我不建议直接apt install、Score-P 和 Scalasca 的分工、OTF2 和 Cube 到底该怎么就位、源码编译时 configure 参数逐条怎么选,最后还会给出一个跑通的 MPI 示例和一份排错清单。适合需要在学校集群、公司服务器或自己工作站上从零部署这套工具的 HPC 使用者、平台管理员,以及刚接触并行性能分析的同学参考。
1. 装这两个工具前,先搞清楚它们的分工和配套组件
1.1 Score-P 与 Scalasca 各自负责什么
很多人第一次听到 Score-P 和 Scalasca 会以为它们是同一个软件的两种安装方式,其实它们的分工非常清晰:Score-P 负责“采集”,Scalasca 负责“分析和报告”。
Score-P 是一套插桩基础设施。它通过包裹编译器(scorep gcc、scorep mpicc)的方式,在编译阶段自动往你的程序里插入性能采集代码,然后在程序运行时把函数调用、MPI 通信、OpenMP 并行区域、硬件计数器等信息写进 trace 文件。你可以简单把它理解成“给程序装了个行车记录仪”,跑一遍,行为全部录下来。
Scalasca 则是在 Score-P 产出的 trace 基础上做自动分析。它最出名的是同步错误检测(比如 MPI 死锁、集合操作不匹配),以及给出 2D/3D 的并行行为热点报告。它能告诉你某个通信到底慢在哪里、是不是某几个进程在等其他人。
所以实际工作流是:scorep编译插桩,mpirun跑出 trace,scalasca -analyze自动分析 trace,最后用 Cube 可视化报告。这也解释了为什么安装时必须先有 Score-P,再装 Scalasca,顺序反了 configure 会直接报找不到前者。
1.2 三大配套组件:OTF2、Cube 与 MPI 环境
除了两个主角,这套生态里还有三个绕不开的配套组件:
- OTF2(Open Trace Format 2):trace 文件的底层格式库。Score-P 和 Scalasca 都通过它读写 trace,它是两者之间的公共数据方言。版本不匹配时,Score-P 生成的 trace 可能根本没法被 Scalasca 读出。
- Cube:报告查看器和指标库。Scalasca 的分析结果会转成 Cube 格式,你可以用 GUI 看进程×函数的二维热力图,也可以在命令行里只输出文本摘要。
- MPI 环境:OpenMPI、MPICH 或 Intel MPI 都行。工具在 configure 阶段会执行小测试程序来探测 MPI,所以环境变量
PATH里必须能直接找到mpicc/mpirun,否则后面会死在这一步。
我在实际安装中发现,很多人卡在“装好了 Score-P 却跑不了 Scalasca”,几乎都是因为它们拿到的 OTF2 或 Cube 版本不一致。这里我建议的经验是:把 OTF2、Cube、Score-P、Scalasca 四个项目当作一个大版本族来管理,尽量使用各自接近的 release 版本,或者干脆用下文会提到的 Spack/EasyBuild 一次性固定版本。
1.3 为什么我一律建议源码编译而不是包管理器
Ubuntu/Debian 的软件源里其实有scorep包,但版本更新很慢,而且多数发行版仓库里根本没有 Scalasca。即使通过apt install scorep装成功,你大概率会遇到两个尴尬:一是版本太老,和当前编译器的 ABI 对不上;二是 apt 会把依赖装进系统目录,等你后面想换版本或者装到用户目录时,清理起来特别麻烦。
另外,HPC 场景有个特殊性——trace 文件格式是带版本约定的。你用手头旧版工具采集的 trace,很可能打不开新版 Scalasca 生成的报告。源码编译虽然多花几分钟,但能让你明确知道装的是哪个版本、依赖在哪,后续排错成本反而最低。
如果你所在集群已经有 EasyBuild 或 Spack 这类环境管理工具,直接用它们安装 Score-P 和 Scalasca 是最省心的。下面我默认的场景是你只有一台服务器、一个普通用户账号,需要从源码自己装,这也是最通用的情况。
2. 环境准备:先花十分钟把编译器与依赖项对齐
2.1 编译器与 MPI 的版本确认
开工前先在终端里确认这几个信息,能省掉后面一多半的麻烦:
gcc --version gfortran --version mpirun --version which mpicc我这次所用的环境是 GCC 11.4 + OpenMPI 4.1 的组合。这里有个容易被忽略的点:Score-P 的 configure 会调用mpicc去编译测试程序,而mpicc又是基于 GCC 的,所以如果你的 GCC 版本和 MPI 是不同时间装的,最好先跑一个简单的 MPI Hello World 确认基础编译链没问题,再进行下一步。
如果你用的是 Intel oneAPI 工具链,也没问题,只需要确保mpiicc/mpirun在路径里,并且 configure 时指定到对应的 MPI 家族即可(后面第 3 节会详细说)。Fortran 编译器不是严格必需,但如果你要分析 Fortran 的 MPI 程序,没有gfortran会导致 configure 阶段跳过 Fortran 支持,插桩时才发现没法用,所以我建议提前装好。
2.2 依赖库清单:哪些必须、哪些可选
下表是我整理的高频依赖项,按“必须”和“可选”分开:
| 依赖项 | 必选/可选 | 作用 | 备注 |
|---|---|---|---|
| libz(zlib1g-dev) | 必须 | 压缩 trace 数据 | 几乎所有发行版默认都有 |
| OTF2 | 必须 | trace 格式库 | 建议手动编译,路径后面让给 configure |
| Cube 库 | Scalasca 必须 | 报告读写与视图 | GUI 可以不装,但库必须有 |
| PAPI | 可选 | 硬件计数器(Cache miss 等) | 没有也能装,但指标少一截 |
| libunwind | 可选 | 采样模式调用栈展开 | 建议装,性能分析很有用 |
| Qt5 | 可选 | Cube GUI 显示 | 只在你想看图形报告时才需要 |
其中最容易忽略的是zlib。如果 configure 报“cannot find zlib.h”,不要怀疑别的,先apt install zlib1g-dev(或yum install zlib-devel)把它装上,再重新 configure。
2.3 决定安装前缀:用户目录安装还是系统安装
这个决定影响后面所有路径,我建议非必要不要装进/usr/local。原因是:这类工具升级频率不低,而且不同项目可能需要不同版本共存。装进你的$HOME/tools下,管理、卸载、切换版本都只需改环境变量。
我推荐的目录结构是:
$HOME/tools/ ├── otf2 ├── cube ├── scorep └── scalasca每个组件一个前缀目录,互不污染。用--prefix=$HOME/tools/otf2这种方式指定。这样即使其中一个需要重装,其他三个不会受影响。
3. 构建 Score-P:configure 参数逐条说明
3.1 获取源码与解压
Score-P 的源码包在官网下载页可以拿到,我写这篇时主线版本是 8.x。下载后解压:
cd $HOME/src wget https://www.score-p.org/release/scorep-8.0.tar.gz tar xf scorep-8.0.tar.gz cd scorep-8.0如果你的服务器无法访问外网,可以在有网机器上下好之后传上去,不需要额外依赖。注意源码目录不要放在 NFS 上编译构建,否则大量小文件的 IO 会让你怀疑人生,建议先在本地磁盘解压构建。
3.2 configure 到底该怎么写
这是我整个安装过程中最关键的一步。我的建议是不要直接./configure --prefix=...就完事,而是要显式告诉它 OTF2、Cube、MPI 的位置。下面是我实测可用的配置:
./configure \ --prefix=$HOME/tools/scorep \ --with-otf2=$HOME/tools/otf2 \ --with-cube=$HOME/tools/cube \ --with-mpi=openmpi \ --with-papi=/usr/local \ --with-libunwind=/usr \ --enable-shared逐条解释一下:
--with-otf2:显式指定 OTF2 安装前缀。如果不指定,Score-P 有时会尝试在内部下载并构建 OTF2,但那样到了 Scalasca 阶段你还得再装一份,容易造成路径混乱。--with-cube:和上面同理,指定 Cube 库位置。Cube 可以先装库,也可以连 GUI 一起装,关键是这里要让 configure 找到它的头文件和库文件。--with-mpi=openmpi:告诉 configure 它面对的是 OpenMPI。如果用了 MPICH 就写--with-mpi=mpich,Intel MPI 则常见用--with-mpi=impiv2。不指定的情况下 configure 会尝试自动探测,绝大多数失败都发生在这个“自动探测”上,所以建议总是手动指定。--with-papi:指定 PAPI 安装前缀。如果你的机器没装 PAPI,直接去掉这一行,工具也能正常编译,只是后续看不到硬件计数器相关指标。--enable-shared:生成动态库,避免后续运行时反复调整 LD_LIBRARY_PATH 的麻烦。
如果你是在集群登录节点上远程编译而没有图形界面,Cube GUI 没必要现在就配齐。可以先让 Cube 库就位,GUI 后面需要再补。
3.3 编译安装与快速自检
configure 跑完后,在config.log里确认没有 fatal error,然后:
make -j$(nproc) make install这里的一个提示:make -j的并行数量取决于机器核数,但 Score-P 编译过程对内存比较敏感,如果你用的是登录节点且机器内存不大,保守一点用make -j4即可,避免 OOM 导致出现莫名其妙的编译失败。
装完后先不要急着往下走,做一次自检:
export PATH=$HOME/tools/scorep/bin:$PATH scorep --version如果能看到版本号输出,说明基础安装成功。接着可以再跑一条:
scorep info这个命令会列出 Score-P 构建时支持的功能,比如 MPI、OpenMP、PAPI 等。我建议在这里停留半分钟,确认里面确实有MPI字样,否则后面插桩 MPI 程序时会发现工具根本不认你的并行代码。
4. 接着装 Scalasca:OTF2、Cube、Score-P 三者的版本铁三角
4.1 为什么 OTF2 和 Cube 要先就位
安装 Scalasca 之前,我强烈建议先确认 OTF2 和 Cube 都已经独立装好。原因在于:Scalasca 的 configure 同时需要找到 OTF2(用于读写 trace)和 Cube(用于生成报告),如果你想让 Scalasca 与刚才装的 Score-P 配合使用,它还需要知道 Score-P 的安装位置。
听起来像是废话,但实际中很多人因为“先装了 Score-P 再装 Scalasca”,结果在 configure 阶段反复报“otf2 not found”,一查才发现自己没有预先编译 OTF2,而是让 Score-P 内部自动构建了一份藏在它的 build 目录里。这种情况下哪怕 Scalasca 装上了,运行时找库也会莫名其妙。
所以我的建议一直是:把 OTF2 和 Cube 当作独立软件先装好,给出明确 prefix,然后 Score-P 和 Scalasca 都指向同一份。这样才能保证它们三个“说同一种语言”。
OTF2 和 Cube 的编译通常没什么坑,标准三步:
wget <otf2-source-url> tar xf otf2-*.tar.gz && cd otf2-* ./configure --prefix=$HOME/tools/otf2 && make -j8 && make installCube 我会先只编译库而不编译 GUI,这样能省去 Qt 依赖:
./configure --prefix=$HOME/tools/cube --without-qt make -j8 && make install其实--without-qt这个选项非常有用。HPC 集群上绝大多数是没有图形界面的,Cube GUI 装了也只能偶尔加个ssh -X来看,但它带来的 Qt 依赖却可能在编译期给你制造麻烦。先只装库,将来想看图形报告再单独编译带 GUI 的版本,不影响已经生成的 trace 文件。
4.2 Scalasca 的 configure 与 make 流程
拿到 Scalasca 源码后,我的典型配置是:
./configure \ --prefix=$HOME/tools/scalasca \ --with-scorep=$HOME/tools/scorep \ --with-otf2=$HOME/tools/otf2 \ --with-cube=$HOME/tools/cube这里有几个细节值得注意:
--with-scorep是可选的,但建议写上。因为 Scalasca 需要调用scorep进行交叉插桩,如果找不到,它可能退化成只做纯在线分析,功能会少一大截。- 如果 configure 报“Cube library not found”,先确认是不是之前的 Cube 只装了 GUI 没装库,或者
--without-qt后有没有执行make install。 make -j$(nproc)后,务必看一眼make install的输出有没有 error。Scalasca 偶尔会因为 Cube 版本过新或过老在链接报告组件时报错,这种错误往往不影响主程序安装,但会让你后面分析时摸不着头脑。
装完后同样验证:
export PATH=$HOME/tools/scalasca/bin:$PATH scalasca --version如果输出正常,就说明核心组件都已经就位。
4.3 版本匹配参考表
“版本不匹配”是我在所有安装问题中见到最多的一类,因为它不会在安装时报错,而是等到分析 trace 时才炸开。我根据自己和同行踩坑的经验,整理了一个大致的版本对应关系,仅供快速参考:
| 工具族版本 | Score-P | Scalasca | OTF2 | Cube |
|---|---|---|---|---|
| 较新主线 | 8.x | 2.6.x | 2.3.x | 4.8.x |
| 较老主线 | 7.x | 2.5.x | 2.2.x | 4.6.x |
严格来说,每个项目的 release notes 里会写明兼容关系,所以最稳妥的做法是:下载源码时,同时打开四个项目各自的 release notes,确保它们的主线版本处于同一时期。不要混搭“Score-P 8 + Scalasca 2.4”这种组合,容易踩到隐性的 ABI 断裂。如果你嫌逐个项目检查麻烦,Spack 路线就更有优势了,它会把版本矩阵帮你管好。
5. 跑通一个 MPI 示例来验证整套工具链
5.1 bashrc 环境变量建议
在集群上,我不太建议把路径直接写进.bashrc里让每个用户都生效——除非你是管理员。更灵活的做法是为这个工具集单独准备一个环境脚本,比如$HOME/tools/env.sh:
export PATH=$HOME/tools/otf2/bin:$HOME/tools/cube/bin:$HOME/tools/scorep/bin:$HOME/tools/scalasca/bin:$PATH export LD_LIBRARY_PATH=$HOME/tools/otf2/lib:$HOME/tools/cube/lib:$HOME/tools/scorep/lib:$HOME/tools/scalasca/lib:$LD_LIBRARY_PATH这样的好处是:需要用时source ~/tools/env.sh,不需要时就不加载,避免和其他软件的环境变量打架。我在帮同事配置时就发现他先前自己往.bashrc里加了好几条不存在的LD_LIBRARY_PATH,结果很多程序启动变慢、偶发找不到库,都是这类“全局污染”引起的。
5.2 用 scorep 包装编译器完成插桩
我们写一个简单的 MPI 程序来验证整个链路。文件叫mpi_ping.c,内容大致是进程两两通信一个消息,统计耗时。
#include <mpi.h> #include <stdio.h> int main(int argc, char **argv) { int rank, size; int msg = 42; double start, end; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); start = MPI_Wtime(); MPI_Barrier(MPI_COMM_WORLD); if (rank == 0) { MPI_Send(&msg, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); MPI_Recv(&msg, 1, MPI_INT, size-1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } else if (rank == 1) { MPI_Recv(&msg, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); } MPI_Barrier(MPI_COMM_WORLD); end = MPI_Wtime(); if (rank == 0) { printf("barrier + ring time = %f s\n", end - start); } MPI_Finalize(); return 0; }用 Score-P 编译插桩只需要把普通的编译命令换成:
source ~/tools/env.sh scorep mpicc -o mpi_ping_inst mpi_ping.c这一步不需要额外写-I、-L,因为scorepwrapper 会自动把 OTF2、Cube 等头文件和库路径加进去。如果这里报找不到mpicc,说明前面 MPI 环境没配对;如果报一堆链接错误,大概率是 Score-P 与 MPI 的匹配出了问题,回到第 3 节重新核对--with-mpi参数。
5.3 scalasca 分析流程与结果文件解读
插桩后的程序直接用mpirun跑:
mpirun -n 4 ./mpi_ping_inst运行完后,当前目录下会多出一个类似scorep_mpi_ping_inst_*的目录,里面就是 trace 文件。确认有了 trace 后,用 Scalasca 做自动分析:
scalasca -analyze mpiexec -n 4 ./mpi_ping_inst注意这里换成了scalasca -analyze,它内部会自动跑一遍程序并分析同步行为,所以不需要手动指定 trace 目录。分析结束后会生成一个scalasca_*报告目录,里面包含 Cube 格式的时间和通信摘要。
想看文本结果,直接敲:
scalasca -examine scalasca_*这条命令会逐条列出程序中的同步错误和性能热点,如果代码里有死锁,这里通常会出现 timeout 提示。想可视化,就在有图形环境的机器上用 Cube 打开:
cube scalasca_*/scorep_*/traces.cubex正常打开的界面里,左侧是函数列表,中间是进程/线程分布,右侧是指标。能同时看到每条 MPI 调用花了多少时间、哪个函数在哪个进程上最慢。
我自己的经验是,第一次看到跑成功的 ScalaSca 报告目录时,事就成了。后续再做实际项目,基本就是从“验证链路”过渡到“定位问题”了。
6. 安装过程中最常出现的坑与排错清单
6.1 找不到 OTF2/Cube 库
这类问题通常表现为 configure 时的OTF2 not found,或运行时libotf2.so: cannot open shared object file。前者多半是路径没对,回到--with-otf2参数检查$HOME/tools/otf2/lib是否存在;后者则说明安装成功但运行时找不到库,需要在LD_LIBRARY_PATH里把它加上。
这里有个技巧:configure 成功后,把当时的config.log里和otf2、cube相关的搜索路径记下来。后面排错时对照看,能快速确认到底是头文件缺了还是库文件没找到。别问我怎么知道的,我第一次排这种错就把大量时间花在了瞎改环境变量上。
6.2 MPI 识别失败
configure 报错说找不到 MPI,或者干脆卡在checking for mpi_init...很久。这通常不是因为 MPI 没装,而是因为你没有指定--with-mpi=openmpi/mpich/impiv2,configure 的自动探测在你的环境里失效了。
解决办法很简单:
export PATH=/path/to/openmpi/bin:$PATH export LD_LIBRARY_PATH=/path/to/openmpi/lib:$LD_LIBRARY_PATH ./configure --with-mpi=openmpi ...另一个我见过的坑是机器上同时装了多个 MPI 实现,configure 探测到的mpicc和实际使用的mpirun来自不同套件。这种情况建议在 configure 之前先用which mpicc mpirun确认它们属于同一个安装前缀。
6.3 报告内存不足与乱码
分析大型作业时,Scalasca 会默认给 trace 设置一个总内存预算,默认值往往不够大。如果你在分析时看到报错或 trace 信息被截断,可以在运行前设置:
export SCOREP_TOTAL_MEMORY=2G这个变量控制 Score-P 运行时用于缓冲 trace 的内存上限,预算太小会丢弃数据或报告失败。官方默认应该在 128MB 左右,对小的测试程序够用,但在真实CFD、分子动力学这类高通信频次的应用里一定要调大。
另外如果你的程序用了大量小消息通信,生成的 trace 文件可能非常大(几十 GB 不夸张),所以要留意磁盘空间,最好在 scratch 目录下跑分析,而不是丢在/home里。
6.4 没有 root 权限时怎么办:Spack 与 EasyBuild 路线
如果你的集群里已经装了 Spack,那么安装要轻松得多:
spack install scorep scalascaSpack 会自动处理 OTF2、Cube、MPI 依赖和版本匹配,并且支持在一个环境里锁定版本。EasyBuild 也类似,用eb ScoreP-...和eb Scalasca-...就能装。对平台管理员来说,我其实是推荐用这类工具统一管理的,毕竟源码编译的灵活性是有代价的——版本组合一多就容易上头。
但如果你是单机用户,没有 root、也不想引入 Spack 一大套体系,那手动源码编译完全够用,我在文中给的这套就是我实际长期使用的方式。
6.5 卸载与升级的建议
最后说一个容易忽略的点。当你需要升级 Score-P 或 Scalasca 时,不要只是在旧版本目录上重新make install。我建议先单独下载新版本、编译到另一个前缀目录,比如$HOME/tools/scorep-8.1,然后切换环境变量指过去。这样做的好处是,如果新版本出问题,你可以立刻切回旧版;旧 trace 也能用旧版工具重新打开,免得升级后出现读不了旧 trace 的尴尬。
我在实际使用中发现,只要把 OTF2、Cube、Score-P、Scalasca 这个“铁三角”的版本固定好,后续基本能稳定用很久。真正容易出问题的反而是隔了几个月后升级了其中一个。所以我现在都会习惯性地记录一份“当时安装环境和版本号”的备忘,放在工具目录旁边,方便自己和同事日后排查。