GNU 并行作业队列脚本

GNU 并行作业队列脚本

我在 GitHub 上找到了一个脚本,我对其进行了轻微修改,以满足我尝试在队列中运行的程序的需求。

但是它不起作用,我不知道为什么。它实际上从未将作业回显到队列文件。

以下是 GitHub 页面的链接:

https://gist.github.com/tubaterry/c6ef393a39cfbc82e13b8716c60f7824

这是我修改的版本:

#!/bin/sh

END="END"
true > queue

tail -n+0 -f queue | parallel -j 16 -E "$END"

while read i; do
    echo "command [args] > ${i%.inp}.log 2> ${i%.inp}.err" > queue
done < "jobs.txt"

echo "$END" >> queue
echo "Waiting for jobs to complete"

while [ "$(pgrep 'perl /usr/local/bin/parallel' | grep -evc 'grep' | tr -d " ")" -gt "0" ]; do
    sleep 1
done

touch killtail
mv killtail queue
rm queue

我唯一能想到的是,其中一个步骤在 OpenBSD 上没有按预期运行。但我重新安排了一个步骤,一切都执行没有错误,但它只提交了一项作业。更改是tail -n+0 -f queue | parallel -j 16 -E "$END"在第一个 while 循环之后移动并更改true > queue为,touch queue因为我不太确定true > queue意味着什么。

任何帮助,将不胜感激。

编辑:

我有一个 jobs.txt 文件,其中填充了我计划运行的命令的输入文件的路径。 jobs.txt 中的文件将是命令的参数之一,然后我将计算结果输出到日志文件,并将任何错误输出到错误文件。

我的期望是,每个作业将被添加到队列中,并且并行将执行最多 16 个作业,每个核心一个,因为命令的参数之一是每次计算一个核心的利用率。这将继续,直到到达由并行的 -E 参数表示的“END”。

正如所写,jobs.txt 没有任何回显到队列。我会再试一次 >>

我对原剧本中的很多内容提出了质疑。我改变了我确定的事情,但有些功能我感到非常困惑,并决定保持原样。

我不清楚的事情之一是 tail -n+0

我不知道那是做什么的

编辑2:

${PROGRAM} ${JOB}.inp ${NCPU} > ${JOB}.log 2> ${JOB}.err

${JOB} 是对 1 到 ∞ 计算之间任意位置的引用,具体取决于我在给定时间需要执行的操作数量。目前,jobs.txt 有 374 个我需要运行的单独测试。 ${PROGRAM} 是从 ${JOB}.inp 获取参数并进行相应计算的软件。 ${NCPU} 是每个作业要使用的核心数量;目前我正在尝试在 16 核处理器上串行运行每个作业。

目标是根据需要对尽可能多的计算进行排队,而无需输入完整的命令。我只想使用生成一个列表find calculations -name '*.inp' -print > jobs.txt,然后运行一个脚本(例如 SerialRun.sh 或 ParallelRun.sh)并让它生成结果。这些作业可能会嵌套在许多不同的目录中,具体取决于不同用户选择如何组织其工作,并且使用 find 的这种方法允许我非常快速地提交作业并将结果生成到正确的路径。每次计算完成后,我可以在系统继续运行测试的同时分析数据。

该脚本很可能过于复杂。我一直在寻找一个作业队列系统,并找到了 nqs,它成为了 GNU Parallel 项目。我找不到很多并行队列作业的示例,但在 GitHub 上发现了该脚本,并决定尝试一下。我对它的编写方式有很多疑问,但我对并行的理解还不足以质疑它。

我认为为它建立一个队列应该比这更简单一些。

编辑3:

也许正确的方法是这样做:

while read i; do
    command "$i" > "${i%.inp}".log 2> "${i%.inp}".err | parallel -j 16
done < "jobs.txt"

那行得通吗?

答案1

你不需要这个复杂的脚本,parallel可以自己做你想做的事情。只需.inp使用您选择的任何其他工具从文件列表中删除扩展名sed,然后输入基本名称,如下parallel所示:

sed 's/\.inp//' jobs.txt | parallel -j 16 "${PROGRAM} {}.inp > {}.log 2> {}.err"

{}符号是并行基本功能的一部分,描述man parallel如下:

{} 输入行。

该替换字符串将被从输入源读取的整行替换。输入源通常是 stdin(标准输入),但也可以用--arg-file:::或给出::::

因此,它只是被您传递给并行的任何内容替换,在本例中是文件名列表,其扩展名被sed.

或者,您可以使用{.}以下内容:

{.} 不带扩展名的输入行。

此替换字符串将被删除扩展名的输入替换。如果输入行包含 .最后一个 / 之后,最后一个 .直到字符串的末尾将被删除,并且 {.} 将被剩余的部分替换。例如 foo.jpg 变为 foo,subdir/foo.jpg 变为 subdir/foo,sub.dir/foo.jpg 变为 sub.dir/foo,sub.dir/bar 仍为 sub.dir/bar。如果输入行不包含 .它将保持不变。

替换字符串 {.} 可以使用 --extensionreplace 更改

有了这个,您甚至不需要该jobs.txt文件。如果所有文件都位于同一目录中,您可以执行以下操作:

parallel -j 16 "${PROGRAM} {.}.inp > {.}.log 2> {.}.err" ::: *.inp

或者,要使其递归地下降到子目录,假设您正在使用bash,您可以执行以下操作:

shopt -s globstar
parallel -j 16 "${PROGRAM} {.}.inp > {.}.log 2> {.}.err" ::: **/*.inp

相关内容