做冷冻电镜数据处理的朋友,基本都绕不开RELION。这个软件在单颗粒分析里算是一站式平台,从运动校正、颗粒挑选到三维分类、精修,都能在同一个GUI里串起来。但真正让人头疼的往往不是算法本身,而是怎么把RELION装好,并且让它和你所在集群上的SLURM调度器配合起来。很多同学装完RELION,打开GUI,填好参数,点下Submit,结果任务要么不排队,要么秒失败,最后只能在图形界面里干瞪眼。这篇文章我就把RELION安装和GUI中配置SLURM调度这条线完整捋一遍,按我实际踩坑的顺序讲,适合刚接手冷冻电镜数据处理任务、需要在课题组或中心集群上跑RELION的读者。
先说清楚一个底层逻辑:RELION在GUI里做的事情,是帮你拼装命令、生成作业脚本,然后把脚本交给调度器去排队执行。和你手动打开终端敲一串命令行没有任何本质区别,GUI只是降低了操作门槛。所以,配置的核心就是让GUI生成的脚本符合SLURM的规矩,同时确保作业在计算节点上能找到RELION的运行环境。这两点只要搞定,后面用起来非常顺。
1. 整体设计与思路拆解
1.1 RELION、GUI和SLURM三者到底是什么关系
我习惯把这三者的关系类比成“点菜、后厨、跑堂”。GUI是点菜界面,你勾选算法、参数,它生成一份“菜单”(一个shell脚本);SLURM是跑堂,负责把这单菜按顺序送到后厨(计算节点)烹饪;RELION本身是后厨大厨,真正完成计算。三者各司其职,一旦配合不好,整个流程就卡壳。
在单机工作站上跑RELION时,不需要调度器,GUI直接调用本机资源,所有进程都由MPI启动器直接拉起来,简单粗暴。但在多用户、多节点的集群上,资源分配必须由SLURM统一管理,否则大家抢CPU、抢内存,集群会乱成一锅粥。所以,我们配置的并不是“让RELION变成SLURM”,而是“让RELION通过SLURM来运行任务”。
这一点一旦理解,后面很多术语就不会绕晕。比如RELION GUI里常出现的Queue submit command,翻译过来就是“把脚本交给哪个调度命令”。在SLURM上是sbatch,在PBS上是qsub,在SGE上是qsub(参数不同)。如果你在配置文件里填的是别的集群的命令,任务自然送不出去。
1.2 为什么推荐源码编译安装而不是无脑conda
现在很多软件都能用conda一键装好,RELION也不例外。conda install -c conda-forge relion这条命令一敲,确实能跑起来。但我个人在实际项目里更推荐源码编译,至少要在集群上重新编译一次。
原因有三。第一,集群的网络文件系统(NFS)通常比较大,conda环境默认装在用户home目录下,如果home目录空间有限,装几个环境就爆了。第二,conda默认二进制包采用的是通用指令集,没有针对集群CPU型号做优化。像Intel或AMD新一些的处理器支持的AVX2、AVX512指令集,通用包未必用得上,计算速度会有损失。冷冻电镜数据处理动不动跑几天,哪怕只有百分之几的速度提升,节省的时间都相当可观。第三,如果课题组打算用GPU加速做三维分类或子区域精修,conda默认包不一定带CUDA加速,源码编译时可以用-DGPU_ACCELERATION=on显式开启,并且可以指定CUDA架构,编译出适配本机显卡的二进制。
当然,我绝不是说conda一无是处。如果你是临时测试、只想快速看下结果,或者集群没有编译工具链,那么conda是个很不错的逃生方案。但正式跑数据,尤其是大项目,源码编译仍然是最稳妥的选择。
1.3 安装前先摸清集群的家底
装软件最忌讳的一件事是“上来就./configure && make”。RELION编译依赖一大堆库,版本不匹配会让错误看起来非常诡异。我最怕的报错是那种指向头文件缺失的,例如fftw3.h: No such file or directory,查了半天才发现系统里压根没装FFTW的开发包。
所以,动手之前先花十分钟盘点一下集群环境。需要看清楚四个维度:
- 操作系统版本和架构:
cat /etc/os-release、uname -m - 编译器版本:
gcc --version、g++ --version - MPI实现和版本:
mpirun --version,看是OpenMPI还是MPICH还是Intel MPI - 是否需要module加载:很多集群使用
module load管理软件环境,安装前要确认需要加载哪些模块,比如module load gcc/9.3.0 openmpi/4.1.1。
这些信息会直接决定编译参数怎么填。比如MPI用的是OpenMPI 4.x,那编译时指定-DCMAKE_CXX_COMPILER=mpicxx基本不会错;如果集群上同时装了好几套MPI,就要小心mpicxx到底指向哪个版本,必要时用绝对路径。
1.4 调度器配置在整条链路中的优先级
我见过很多初次接触集群的人,把大量精力花在配GUI的“流水线”颜色、显示风格上,结果真正跑任务时排不上队。实际上,在这套体系里,调度器配置就是那根“最后一公里”的导线。即使RELION装得再完美,GUI交互再顺畅,只要SLURM参数不匹配,任务照样死掉。
所以我的建议是:先把安装做好,第二步在命令行验证SLURM的基本用法,第三步才进入GUI做调度配置。不要试图跨过前两步。命令行跑不通的任务,GUI里百分之百也跑不通,反而还会因为GUI封装了细节,让你更难排查错误。
2. 安装细节与编译参数选型
2.1 依赖准备:缺什么会非常明显
RELION版本不同,依赖会有细微差别。以RELION 4.x/5.x为例,必装的依赖大致有这些:
- CMake(建议3.16以上)
- GNU编译器,老版本用g++ 8,新版5.x我试过用GCC 12没问题
- MPI库,OpenMPI或MPICH都可以
- FFTW3库,必须带开发头文件,注意区分
fftw3和fftw3-dev两个包 - libtiff,用于读显微图
- PCRE库,用于正则表达式,这个很多教程会漏掉
- CUDA Toolkit(如果要用GPU加速)
- Python 3环境(部分模块和工具脚本依赖)
这些依赖在Ubuntu/Debian系可以用apt-get install装,在CentOS/Rocky系用dnf install。但集群通常没有root权限,这时候就建议用conda单独建一个编译环境,把依赖装进去,再在编译时通过CMAKE_PREFIX_PATH指定路径。这个方法我实测很管用,等于“造一个假系统目录”来骗过CMake搜索。
2.2 源码编译的完整命令与参数解释
我用的编译流程如下,先建目录,再配置,再编译安装。假设我把RELION安装在/home/user/software/relion:
module purge module load gcc/12.2.0 openmpi/4.1.5 cmake/3.24.3 git clone --branch v5.0 https://github.com/RELION/RELION.git cd RELION mkdir build && cd build cmake .. \ -DCMAKE_INSTALL_PREFIX=/home/user/software/relion \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_COMPILER=mpicc \ -DCMAKE_CXX_COMPILER=mpicxx \ -DGPU_ACCELERATION=on \ -DCUDA_TOOLKIT_ROOT_DIR=/path/to/cuda \ -DALTCPU=on \ -DMPI_BUILD=on make -j 16 make install-DCMAKE_BUILD_TYPE=Release开启编译器优化;-DMPI_BUILD=on表示编译MPI版本;-DALTCPU=on是启用CPU指令集优化,若集群CPU较老可能要慎重;-DGPU_ACCELERATION=on配合CUDA_TOOLKIT_ROOT_DIR指定CUDA路径。
编译过程中最恶心的是CUDA和GCC版本配合问题。老版本CUDA不认太新的GCC,新版本CUDA又要求GCC最低版本。如果遇到unsupported GNU version之类的报错,要么降低GCC版本,要么升级CUDA。我吃过这亏,后来养成了先看nvcc --version再决定加载哪套GCC的习惯。
2.3 安装后的环境验证不能偷懒
装完后,直接跑relion --version能识别到,只是第一步。更关键的是验证它是否能以MPI模式跑起来,因为GUI里的调度配置最终就是靠mpirun/srun去拉多进程。
我在临时目录里测试的方式:
cd /tmp relion_estimate_gain --version mpirun -np 2 echo "MPI ok"如果MPI这步都报错,那说明你的环境中mpirun有问题,赶紧检查LD_LIBRARY_PATH或PATH。另外,确认relion_refine_mpi这个可执行文件存在,它是后面精修任务最常调用的主程序。如果编译时MPI没开,这个文件就不会生成,那后续GUI里即使提交SLURM,也只能跑单进程,毫无意义。
还有一个容易忽略的点:把安装目录下bin路径加进~/.bashrc后,要重新登录或source ~/.bashrc。很多人在集群上明明装了软件,却一直报“command not found”,基本就是忘了这一步。
3. GUI中的SLURM调度配置实操
3.1 打开GUI并进入调度配置界面
安装完成后,在终端输入relion启动GUI。默认会看到一个主窗口,上面有“File”“Search”“Scheduling”“Running”等菜单项。有些版本可能叫法不完全一样,但核心入口都在“Scheduling”或“Preferences”里。
以RELION 5.0为例,点击主菜单上的“Scheduling”,打开“Scheduler”窗口。这个窗口就是GUI和SLURM之间的接口。在那个窗口里有一项“Use a system for submission of jobs”,它是一个开关,勾选后,下面所有调度参数才会变成可填状态,GUI才会把任务提交动作交给调度脚本而不是本地直接执行。
这个“系统提交”开关,是整条配置链路的分水岭。没勾选之前,GUI直接调用mpirun在登录节点跑任务,这在集群上属于违规操作,系统管理员一般都会禁止长时间占用登录节点资源。勾选之后,GUI才会生成一个提交命令(比如sbatch),把脚本交给调度器。
3.2 关键参数逐项对照与填法
下面这张表是我自己整理的RELION GUI字段和SLURM参数对应关系,照着填基本不会跑偏。
| RELION GUI字段 | 含义 | SLURM对应/示例 |
|---|---|---|
| Queue submit command | 提交作业的命令名 | sbatch |
| Queue name | 队列/分区名 | compute或gpu |
| Number of MPI procs | 进程数 | --ntasks |
| Number of threads | 每个进程的线程数 | --cpus-per-task |
| Core increment | 每次增加的资源增量 | 可留空 |
| Extra arguments for submission | 额外的sbatch参数 | --gres=gpu:1 |
注意,“Queue name”和SLURM里的“partition”是对应的。比如你的是slurm管理的集群,用scontrol show partition命令能查看有哪些分区,可能叫cpuq、gpuq。填错分区名,任务直接提交失败。如果不确定,填默认分区也行,但要问管理员默认分区允许跑多少核。
“Number of MPI procs”和“Number of threads”是两个最容易被混淆的参数。RELION的并行模式是MPI进程加上OpenMP线程组成的混合并行。假如分配了32核,最好MPI进程数设为8、线程数设为4,乘积刚好等于总核数。SLURM那边,--ntasks=8、--cpus-per-task=4,这样调度器才会把32个核都分配给你,不会只给8个核。
3.3 完整的配置方案示例
我用的一套比较规范的方案如下,适合在拥有SLURM的CPU集群上运行:
- Use a system for submission of jobs:勾选
- Queue submit command:
sbatch - Queue name:
compute - Number of MPI procs:
8 - Number of threads:
4 - Extra arguments for submission:
--time=48:00:00 --mem=64G
--time和--mem那两个参数特别关键。很多作业挂在排队中或者被系统kill掉,就是因为没有指定足够的时间或者内存。SLURM不认识“你一个任务要跑一天”这种说法,你必须在--time里写明最长运行时间,格式是天-小时:分钟:秒或者小时:分钟:秒。内存则用--mem或--mem-per-cpu,不写的话默认值可能小得可怜。
如果你要跑GPU任务,需要确认GPU节点能通过SLURM申请到。在Extra arguments里加上--gres=gpu:1,同时确保GUI里的“Number of MPI procs”不大于单节点允许的GPU卡数,否则会显示资源不足。许多集群的GPU分区与CPU分区不同,Queue name可能要填写gpuq或gpu。
RELION在生成提交脚本时,会把上述参数拼装成一个标准的sbatch命令。如果拼出来的命令在终端里手动执行会报错,GUI里自然也不会有好结果。所以遇到问题,第一反应是去排查这个命令行参数,而不是盯着GUI面板发呆。
3.4 配置文件是怎么落地的
RELION GUI的偏好设置会保存在用户目录下的隐藏文件里,路径通常是~/.config/RELION/relion_gui.cfg。直接编辑这个文件也行,但GUI的操作会更安全,因为GUI会在写文件前做校验,防止格式错误。
基于上面的配置,relion_gui.cfg里对应的内容大致长这样:
RELION_MODE=1 QUEUE_SUBMIT_TIMEOUT=60 QUEUE_NAME=compute QUEUE_SUBMIT_COMMAND=sbatch QUEUE_SUBMIT_EXTRA=--time=48:00:00 --mem=64G QUEUE_MPI_PROCS=8 QUEUE_THREADS=4注意,不同小版本的变量名可能有轻微差异,不要照搬。我的建议是先用GUI页面设置一次,然后打开这个文件对照理解,就不会出大问题。
之所以提到这个文件,是因为很多管理员会要求用户把默认配置固化下来,避免每次启动GUI还要重新填一遍。你在自己的用户目录下改好,整个账号的后续任务都受益。如果团队里多人共用一个账号,这个文件就变成“共享配置模板”,大家的基础参数一致,更方便管理。
4. 实操验证与常见问题排查
4.1 从GUI提交一个任务,观察日志与状态
配置好之后,随便建一个小测试任务,比如“Find particles”里的一个简单步骤,或者直接用relion_run_ctffind的测试。点击Submit后,GUI下方会有一个“Messages”窗口,里面会打印提交命令和返回信息。看到Submitted batch job 123456这行,就说明SLURM已经受理任务。
然后回到终端,用squeue -u 你的用户名查看任务状态。状态可能是PD(排队中)、R(运行中)、CG(正在结束)。
如果看到PD一直不动,先别慌,大概率是分区资源不足或--time太短导致调度器选了无法满足的节点。用scontrol show job 123456查看排队原因,SLURM会明确告诉你Resources还是PartitionTimeLimit,照着调整就行。
如果任务状态变成F(失败)或ST(被强杀),就要求助日志文件。RELION把标准输出和标准错误写在项目目录下的templates和Logfile目录,在GUI的“Display”->“Messages”里也能看运行日志。最经典的失败原因我会在下面展开。
4.2 典型失败案例与排查方法
下面这几个坑,我几乎每次换新集群都能遇到。
第一个坑:任务提交了,但运行日志显示command not found: relion_refine_mpi。原因很简单:计算节点上的环境变量和登录节点不一样。即使你在~/.bashrc里写了export PATH=/path/to/relion/bin:$PATH,SLURM作业不一定source那个文件。解决办法是在任务脚本里显式声明环境。RELION允许你在“Extra arguments”之外的“Queue submit command”里写一个包装脚本,比如sbatch_wrapper,在脚本里先source ~/.bashrc再加sbatch "$@"。
更稳妥的做法是在~/.bashrc末尾加上:
export RELION_SRC=/path/to/relion/bin export PATH=$PATH:$RELION_SRC并且确认计算节点会读取这个文件。如果集群用module体系,每次提交前需要在作业脚本里module load相关依赖。
第二个坑:任务一下跑了,但CPU占用率只用了1个核。这多半是MPI进程数和线程数没有正确传达给SLURM。标准配置必须是--ntasks对应MPI进程数,--cpus-per-task对应线程数,而且RELION内部用OMP_NUM_THREADS控制线程,GUI会把它写进脚本。你可以打开作业脚本检查里面有没有export OMP_NUM_THREADS=4。如果没有,手动加上,或者在“Extra arguments”里传入--ntasks=8 --cpus-per-task=4。
第三个坑:任务报srun: error: Unable to allocate resources: Invalid account or account/partition combination specified。这种情况通常是SLURM分区的账户名没写对。有些集群用--account=xxx标识课题组,RELION GUI里可能没有直接对应字段,你需要把--account=xxx塞到“Extra arguments for submission”里。登录节点上跑sacctmgr show assoc -p user=$USER能看到自己的账户名。
第四个坑:超时被杀。SLURM任务有硬性时间限制,接近--time上限时会被系统直接终止。日志文件里会有CANCELLED AT...或DUE TO TIME LIMIT字样。排查方法很直接:查看正常跑完的任务耗时,把--time写到略微超过最大耗时的时间,比如--time=6-00:00:00表示6天。
第五个坑:GPU任务没用到GPU。检查日志中是否有CUDA_ERROR,用nvidia-smi看显卡占用。GPU节点上RELIon的GPU加速需要额外指定--gpu参数给运行程序,并不是有显卡就会自动使用。在GUI的“Extra arguments”里有时要写--gpu 0,或者在运行参数里选中“Use GPU”并填设备ID。同时确认编译时确实开启了GPU_ACCELERATION,否则RELION只是普通CPU版。
4.3 一个测试脚本:在命令行手动验证调度链路
为了彻底区分“RELION问题”和“SLURM问题”,我强烈建议先用一个最简测试脚本,把整条链路跑通,再回到GUI。把下面内容保存成test_relion_slurm.sh:
#!/bin/bash #SBATCH --partition=compute #SBATCH --ntasks=8 #SBATCH --cpus-per-task=4 #SBATCH --time=00:10:00 #SBATCH --mem=8G module purge module load gcc/12.2.0 openmpi/4.1.5 source /home/user/software/relion/bin-activate.sh srun echo "SLURM job ok, $(which relion_refine_mpi)"执行:
sbatch test_relion_slurm.sh squeue -u $USER如果这个脚本能成功输出relion路径,说明编译与调度系统基本通畅。之后再回到GUI填参数,就有了一个“基线”。这也是我通常在正式开工前会做的一次“系统自检”。
最后再分享一个小技巧:把relion --no-gui作为一种调试模式使用。有些环境下图形界面无法启动,或者你想在后台快速跑一个命令,用relion --no-gui --do_something能绕过GUI直接执行,这时候错误信息会直接刷在终端里,比GUI的“Messages”窗口直观得多。我在处理诡异问题时会先这么干,确认命令行参数无误后,再去GUI里重跑,能省下不少排查时间。我个人在长期使用中,最大的体会就是:GUI只是壳,真正值得花心思的还是底层环境和调度器映射关系。只要把本文讲的三步——编译、调度器配置、命令行验证——走扎实,后续跑任何冷冻电镜项目都会顺畅很多。