使用 xargs 并行运行程序

Posted

技术标签:

【中文标题】使用 xargs 并行运行程序【英文标题】:Running programs in parallel using xargs 【发布时间】:2015-04-06 03:16:33 【问题描述】:

我目前有当前脚本。

#!/bin/bash
# script.sh

for i in 0..99; do
   script-to-run.sh input/ output/ $i
done

我希望使用 xargs 并行运行它。我试过了

script.sh | xargs -P8

但是执行上述操作一次只执行一次。 -n8 也没有运气。 在要在 for 循环脚本中执行的行的末尾添加 & 将尝试一次运行脚本 99 次。如何一次只执行 8 个循环,总共最多 100 个。

【问题讨论】:

这是我最初想做的,但由于我在 Windows 上,所以不得不求助于 xargs。我无法让 GNU Parallel 在 Windows 上运行 该脚本是在调用自己还是您在此处询问时只是混淆了名称? 对不起,它应该调用另一个脚本。我会解决的 ***.com/questions/3321738/… 的答案与此处相关。 【参考方案1】:

来自xargs 手册页:

本手册页记录了 xargs 的 GNU 版本。 xargs 读取项目 来自标准输入,由空格分隔(可以保护 带双引号或单引号或反斜杠)或换行符,并执行 该命令(默认为 /bin/echo)一次或多次,带有任何初始 - 参数后跟从标准输入读取的项目。上的空行 标准输入被忽略。

这意味着对于您的示例,xargs 正在等待并收集脚本的所有输出,然后运行 ​​echo <that output>。并非完全有用,也不是您想要的。

-n 参数是输入中的多少项与每个运行的命令一起使用(这里没有关于并行性的内容)。

要使用xargs 做你想做的事,你需要做更多这样的事情(未经测试):

printf %s\\n 0..99 | xargs -n 1 -P 8 script-to-run.sh input/ output/

像这样分解。

printf %s\\n 0..99 - 从099 每行打印一个数字。 运行xargs 最多每个运行命令行使用一个参数 并一次运行最多八个进程

【讨论】:

其实你不需要把参数放在不同的行上; xargs 分词。所以echo 0..99 | 也可以。 <<<0..99 似乎不起作用;尽管<<<word 被记录为大括号扩展词,但它不适用于我手头的任何版本的 bash。 @rici 看起来像一个文档错误,特别是因为 Here Documents 的文档 没有 提到大括号扩展(在快速测试中也没有发生)尽管他们也没有提到波浪号扩展(<< 不会发生这种情况,但<<< 所以*shrug* 会发生这种情况)。在我看来,here docs 和 here strings 中发生和未发生的扩展有点奇怪。 如何将不同运行的结果分开,例如换行符? 演示:time head -12 <(yes "1") | xargs -n1 -P4 sleep 将运行 12 个sleep 1 命令,4 个并行。该命令将需要 3 秒。 可能值得注意的是-P 0会使用系统上的cpu数量【参考方案2】:

使用 GNU Parallel,您可以:

parallel script-to-run.sh input/ output/  ::: 0..99

如果您希望每个 CPU 内核运行一项作业,请添加 -P8

相反 xargs 它会做正确的事,即使输入包含空格、' 或 "(但这里不是这种情况)。它还确保不同作业的输出不会混合在一起,所以如果你使用的输出保证你不会从两个不同的工作中得到半行。

GNU Parallel 是一种通用的并行化器,可以轻松地在同一台机器上或在您可以通过 ssh 访问的多台机器上并行运行作业。

如果您想在 4 个 CPU 上运行 32 个不同的作业,那么并行化的直接方法是在每个 CPU 上运行 8 个作业:

GNU Parallel 会在完成后生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:

安装

如果没有为您的发行版打包 GNU Parallel,您可以进行个人安装,这不需要 root 访问权限。这样做可以在 10 秒内完成:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh

有关其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README

了解详情

查看更多示例:http://www.gnu.org/software/parallel/man.html

观看介绍视频:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

浏览教程:http://www.gnu.org/software/parallel/parallel_tutorial.html

注册电子邮件列表以获得支持:https://lists.gnu.org/mailman/listinfo/parallel

【讨论】:

这并没有回答问题,也没有指出为什么 xargs 不能达到同样的效果。 投反对票,因为 xarg 对我来说与第二张图片显示的完全一样。 @noonex 你知道不是每个人都使用你使用的 xargs 版本,而且 -P 不是所有版本的 xargs 吗? 也许不是所有人都知道这个答案是由 GNU parallel 的作者提供的。 由于在第一次尝试时描述的无法正确运行的软件上的明确广告而被否决,因为交互式提示会弄乱大多数脚本。【参考方案3】:

您可以使用这个简单的 1 行命令

seq 1 500 | xargs -n 1 -P 8 script-to-run.sh input/ output/

【讨论】:

以上是关于使用 xargs 并行运行程序的主要内容,如果未能解决你的问题,请参考以下文章

在包中并行执行程序[重复]

在 bash 中的并行进程之间添加等待

判断 Python 程序是不是并行运行

使用多个 jdbc 连接运行并行查询的 Spring Boot 应用程序

如何从 bash 脚本并行运行多个程序?

运行并行 AsyncTask