最近我一直在生成几个系列的输入文件,以使用 Slurm 排队系统在 HPC 上运行计算。这些计算都放在子目录中,形式为
D001
、D002
等(D
,后接三位数字,按数字顺序排列)。在这些目录中是我的输入文件,总是以.inp
结尾(对于我现在正在看的系列,文件都称为tma.h2s-2-vpt2-b97m-d4-qz_D001.inp
等,其中输入文件中的数字与其子目录的名称匹配),以及 Slurm 运行脚本(这些特定的脚本都称为 slurm-run-orca.job
)。
到目前为止,我一直在费力地手动运行每个计算,通过运行(从每个子目录所在的目录):
cd D001
sbatch -J tma.h2s-2-vpt2-b97m-D4-qz_D001 slurm-run-orca.job
cd ../D002
sbatch -J tma.h2s-2-vpt2-b97m-D4-qz_D002 slurm-run-orca.job
cd ../D003
sbatch -J tma.h2s-2-vpt2-b97m-D4-qz_D003 slurm-run-orca.job
etc.
这非常耗时,老实说,让我的手指很僵硬。我运行的最后一个系列有 66 次计算,我 did 最终通过了,但我当前的批次有 84...
有什么办法可以编写脚本来自动执行此操作? (请注意,尽管所有文件都包含 .inp
扩展名,但提交的输入文件
without
.inp
附加。)我搜索了几天以找到针对这种情况的类似问题/答案,但是,有趣的是,我还没有发现任何可以解决如此简单的问题的方法(至少,这个问题seems简单——不过我很可能会误会)...
编辑: 澄清一下,子目录中的唯一文件是作业文件和输入文件,即:
ls
D001 D002 D003 D004 ...
ls D001/
tma.h2s-2-vpt2-b97m-d4-qz_D001.inp slurp-run-orca.job
到目前为止,我已经尝试了几种方法——
if
/then
语句、while
和 for
循环——但事实是我对 bash 的了解还不够多,无法让这样的东西起作用(我可以编辑脚本,但我从来没有成功地从头开始编写过脚本)。我最接近使脚本工作的是:
#!/bin/bash
work_dir="pwd"
base=$1
n=001
submit_dir=$base$(( n ))
while ii in $submit_dir ; do
cd $submit_dir
squeue -J *.inp *.job
cd $work_dir
n=$(( $n + 1 ))
echo "Submitting calculations to queue"
done
我尝试添加一个 if/then 语句以确保循环在到达系列末尾时停止(尽管我觉得这是不必要的),并在相关时打印出
Could not find calculation subdirectories
,但随后开始专注于让 while
循环工作。我 am 知道我到目前为止所写的内容将包括 .inp
扩展名,但我认为值得让脚本首先识别目录中有文件,然后再担心剥离 .inp
...
此外,如果可能的话,我希望能够以特定的时间延迟或使用像
./job-submission <base-name-of-input-files> 001-020
这样的命令(例如)以 20 个为一组提交计算,这样我就不会阻塞队列(我们可用的节点数量非常有限)。
任何帮助让它工作的人都将不胜感激!
如果没有关于可能需要处理哪些其他
.job
文件以及是否有其他 .inp
文件的更多信息,就很难提供适合您所有用例的解决方案。希望以下代码至少可以为您指明正确的方向或给您新的见解。
#!/bin/bash
i=0;
find -name "*_D*"|\
while read fname;
do i=$(($i+1));
echo "sbatch -J ${fname%.*} slurm-run-orca.job;";
if [ $i = "20" ];
then echo "Sleeping 5 seconds";
sleep 5;
i=0;
fi;
done
find -name
允许我们根据模式迭代目录结构while
循环允许我们遍历找到的每个文件${fname%.*}
是 shell 参数扩展,允许我们比 cut
命令更简单地剥离文件扩展名。然而,这并不适用于所有 shellif
命令用于支持您希望按 20 个文件进行批处理,然后进行时间延迟请注意,此脚本做出的某些假设在您的情况下可能不正确。请在删除
echo
部分之前彻底测试
我会这样做:
#!/usr/bin/env bash
shopt -s nullglob
for workdir in "$@"
do
pushd "$workdir" > /dev/null || continue
for inpfile in *_"${PWD##*/}".inp
do
sbatch -J "${inpfile%.*}" slurm-run-orca.job
done
popd > /dev/null
done
然后指定要从中提交作业的目录作为参数:
./myscript.sh some/path/to/D*
pushd
和 popd
是 bash 内置函数,您可以使用它们来 cd
ing 到一个目录,然后返回到以前的位置。
环境变量
PWD
包含当前目录的路径,${PWD##*/}
扩展到它的最后一个组件(即,直到最后一个 /
的所有内容都被剥离)。