Slurm集群多节点运行多场景Fortran代码免重编译sbatch方法
实现方案
完全可以实现,全程只需要编译一次代码,靠Slurm作业数组就能自动把3个场景任务调度到不同节点运行,不需要手动改源码反复提交。
第一步:改造Fortran代码支持运行时传参
你现在把场景号硬编码在源码里才需要每次改值重编译,只要把场景号改成从命令行参数读取,同一份编译产物就能通过传入不同参数切换运行场景。
把原来硬编码场景号的代码段替换成下面的内容:
integer :: scenario_no integer :: arg_err character(len=4) :: cmd_arg ! 读取第一个命令行参数作为场景号 call get_command_argument(1, cmd_arg, status=arg_err) if (arg_err /= 0) error stop "启动时需传入场景号参数,可选值1/2/3" read(cmd_arg, *) scenario_no if (scenario_no < 1 .or. scenario_no > 3) then error stop "非法场景号,仅支持传入1、2、3" end if
改完之后执行一次编译,生成固定的可执行文件(比如命名为scenario_run),后续不需要再重复编译。测试的时候直接在命令行执行./scenario_run 1就会跑场景1,传2、3就对应另外两个场景。
第二步:编写sbatch作业数组提交脚本
Slurm的作业数组功能可以一次性生成3个独立的子作业,每个子作业自带唯一的数组ID,正好和3个场景号一一对应,调度器会自动给子作业分配空闲节点资源。
脚本示例如下,你可以根据自己集群的资源配置调整对应参数:
#!/bin/bash #SBATCH --job-name=fortran_scenarios #SBATCH --nodes=1 # 每个子任务独占1个节点 #SBATCH --ntasks-per-node=32 # 单任务调用的CPU核数,按你实际需求修改 #SBATCH --array=1-3 # 生成ID为1、2、3的3个子作业,对应3个场景 #SBATCH --output=./logs/run_%a_%j.log # 每个场景单独存运行日志,%a为场景号,%j为作业ID #SBATCH --error=./logs/run_%a_%j.err #SBATCH --time=48:00:00 # 单任务最大运行时长,按实际需求修改 #SBATCH --partition=common # 提交的计算分区,按集群实际分区名修改 # 提前创建日志存放目录 mkdir -p ./logs # 直接运行编译好的程序,把当前子作业的数组ID作为场景号传入 ./scenario_run $SLURM_ARRAY_TASK_ID
写好脚本之后,只需要执行一次sbatch 你的脚本名.sh就可以提交全部3个任务,不需要手动操作三次。
补充说明
- 如果你的集群资源充足,3个子作业会自动被调度到不同的空闲节点运行;如果需要强制要求子作业分散在不同节点,可以在sbatch参数里加一行
#SBATCH --distribution=block:block,避免多个任务挤在同一个节点。 - 提交前建议先在登录节点手动测试参数读取逻辑:直接执行
./scenario_run 1确认程序能正确识别场景号,避免批量提交后因为参数读取问题报错。 - 如果你暂时不想修改Fortran源码,也可以在每个子任务启动时用
sed命令动态替换源码里的场景号取值、临时编译后运行,但这种方案会产生重复编译开销,远不如改命令行传参的方案简洁,长期用还是推荐前者。
内容的提问来源于stack exchange,提问作者phdstudent
相关产品推荐
相关产品推荐

