如何使用 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_a
和 options_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 秒后完成。
使用 GNU Parallel 看起来像这样:
export -f options_a
export -f options_b
parallel -j40 'queue_job $(options_a {}) $(options_b {})' ::: $FNS
我目前正在循环中通过 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_a
和 options_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 秒后完成。
使用 GNU Parallel 看起来像这样:
export -f options_a
export -f options_b
parallel -j40 'queue_job $(options_a {}) $(options_b {})' ::: $FNS