如何使用 xargs 并行执行数千条命令?

How to execute thousands of commands in parallel using xargs?

我目前正在循环中通过 qsub 排队一堆作业

for fn in $FNS; do
    queue_job $(options_a $fn) $(options_b $fn)
done

queue_job 是一个使用 qsub 对作业进行排队的脚本,options_a/b 是我编写的函数,它根据文件名添加了一些作业选项。我以这种方式排队多达 5k 个作业,我想立即将它们全部添加到队列中(或以更大的块,例如 40/次)而不是循环。

我知道我可以将行发送到 xargs 并作为

并行执行它们
??? | xargs -P 40 -I{} command {}

但我不确定如何将我的 for 循环转换为 xargs

qsub 接口允许一次提交一个作业 - 它不提供 bulk 提交,这将限制并行提交作业的优势(作业提交通常很快)。

对于特定情况,有两个 (bash) 函数(即 options_aoptions_b),它们将根据文件名扩展到作业特定参数。正如评论所建议的那样,这可能会限制使用 xargs 的直接执行 - 这些函数不太可能在路径中可用。

选项:

queue_job 创建一个包装器,它将获取(或包含)函数。使用 xargs

中的包装器
xargs -P40 -I{} queue_job_x1 '{}'
queue_job_x1

#! /bin/bash
function options_a {
   ...
}

function option_b {
   ...
}

queue_job $(options_a $fn) $(options_b $fn)'

将相关函数放入 .sh 文件中可能是个好主意,该文件可以由多个脚本获取。

xargs 不需要。

如果你后台任务,下一个任务可以立即进行。您可以为您的脚本添加一些智能,以便它可以限制同时执行的任务的数量。例如:

COUNT=1
LIMIT=40
for fn in $FNS; do
    queue_job $(options_a $fn) $(options_b $fn) &
    if [ $COUNT -lt $LIMIT ] ; then
        COUNT=$[COUNT+1]
        continue
    fi
    wait -n
done
wait

queue_job 命令置于后台。 if 主体继续生成并行 queue_job 任务,直到 COUNT 到达 LIMIT。如果 COUNT 已达到 LIMIT,则循环等待 运行 任务之一完成,然后再生成下一个任务。尾随 wait 让脚本阻塞,直到所有任务完成。

我通过模拟 queue_job 睡眠 2 秒、30 个任务并限制为 10 个并行任务来对此进行测试。正如预期的那样,模拟在大约 6 秒后完成。

Try it online!

使用 GNU Parallel 看起来像这样:

export -f options_a
export -f options_b

parallel -j40 'queue_job $(options_a {}) $(options_b {})' ::: $FNS