gnu parallel
您是否曾经获得过一种有趣的感觉,那就是您的计算机并没有达到应有的速度? 我曾经有这种感觉,然后我找到了GNU Parallel。
GNU Parallel是用于并行执行作业的Shell实用程序。 它可以解析多个输入,从而针对数据集同时运行脚本或命令。 您最终可以使用所有 CPU!
如果您曾经使用过xargs
,那么您已经知道如何使用Parallel。 如果您不这样做,那么本文将教您以及许多其他用例。
您的Linux或BSD计算机上可能未预安装GNU Parallel。 从您的存储库或端口集合安装它。 例如,在Fedora上:
$ sudo dnf install parallel
或在NetBSD上:
# pkg_add parallel
如果其他所有方法均失败,请参考项目主页 。
顾名思义,Parallel的优势在于它并行运行作业,而不是像我们中许多人一样依次运行作业。
当对多个对象运行一个命令时,本质上是在创建队列。 该命令可以处理一定数量的对象,而所有其他对象只是站着等待它们的转弯。 效率低下。 给定足够的数据,总会有一个队列,但是为什么不只有一个队列,却为什么不拥有很多小队列呢?
假设您有一个文件夹,其中包含要从JPEG转换为PNG的图像。 有很多方法可以做到这一点。 有手动的方式可以在GIMP中打开每个图像并将其导出为新格式。 这通常是最糟糕的方法。 这不仅费时,而且很费力。
基于此主题的外壳程序是一个非常简洁的变体:
$ convert 001.jpeg 001.png
$ convert 002.jpeg 002.png
$ convert 003.jpeg 003.png
... and so on ...
初学时这是一个绝妙的技巧,一开始它是一个巨大的进步。 无需GUI和持续单击。 但是它仍然是劳动密集型的。
更好的是:
$ for i in *jpeg; do convert $i $i.png ; done
至少,这可以使工作动起来,并使您腾出更多精力来做更有生产力的事情。 问题是,它仍然是一个串行过程。 一幅图像被转换,然后队列中的下一幅图像逐步转换,依此类推,直到清空队列。
使用并行:
$ find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png
这是两个命令的组合: find
命令(收集要操作的对象)和parallel
命令(对对象进行排序,并确保按需处理所有内容)。
find . -name "*jpeg"
find . -name "*jpeg"
查找当前目录中所有以jpeg
结尾的文件。 parallel
调用GNU Parallel。 -I%
创建了一个占位符,称为%
,以代替任何find
到并行手中。 之所以使用它,是因为否则必须为find
每个结果手动编写一个新命令,而这正是您要避免的事情。 --max-args 1
限制Parallel从队列中请求新对象的速率。 由于运行Parallel的命令仅需要一个文件,因此将速率限制为1。如果您执行的是更复杂的命令,需要两个文件(例如cat 001.txt 002.txt > new.txt
),那么您将限制速率至2。 convert % %.png
是要并行运行的命令。 该命令的结果是find
收集所有相关文件并将其移交给parallel
,这将启动作业并立即请求下一个内联文件。 只要可以安全地启动新作业而不会损坏计算机,Parallel就会继续执行此操作。 旧工作完成后,它将用新工作替换,直到处理完提供给它的所有数据为止。 在使用Parallel之前,需要10分钟的时间可能只需要5或3。
只要您熟悉find
和xargs
(统称为GNU Find Utilities或findutils
), find
命令就是通往Parallel的绝佳网关。 它提供了一个灵活的界面,许多Linux用户已经熟悉了该界面,如果您是新手,则非常容易学习。
find
命令非常简单:为find
提供要搜索目录的路径以及要搜索的文件名的一部分。 使用通配符将您的网络覆盖更广; 在此示例中,星号表示任何内容 ,因此find
查找以字符串searchterm
结尾的所有文件:
$ find /path/to/directory -name "*searchterm"
默认情况下, find
返回一项搜索结果,每行一项:
$ find ~/graphics -name "*jpg"
/home/seth/graphics/001.jpg
/home/seth/graphics/cat.jpg
/home/seth/graphics/penguin.jpg
/home/seth/graphics/IMG_0135.jpg
当将find
的结果通过管道传递给parallel
,每一行中的每一项都被视为parallel
正在仲裁的命令的一个参数。 另一方面,如果您需要在一个命令中处理多个参数,则可以拆分将队列中的数据移交给parallel
。
这是一个简单的,不现实的示例,稍后我将把它变成更有用的示例。 只要安装了GNU Parallel,就可以继续执行此示例。
假设您有四个文件。 列出它们,每行列出一个,以查看您所拥有的确切信息:
$ echo ada > ada ; echo lovelace > lovelace
$ echo richard > richard ; echo stallman > stallman
$ ls -1
ada
lovelace
richard
stallman
您想将两个文件合并为一个包含两个文件内容的第三个文件。 这要求Parallel可以访问两个文件,因此-I%
变量在这种情况下不起作用。
Parallel的默认行为基本上是不可见的:
$ ls -1 | parallel echo
ada
lovelace
richard
stallman
现在告诉Parallel您想为每个作业获取两个对象:
$ ls -1 | parallel --max-args=2 echo
ada lovelace
richard stallman
现在,这些行已合并。 具体来说,来自ls -1
两个结果立即全部传递给Parallel。 这是完成此任务的合适参数,但实际上,它们现在实际上是一个参数:“ ada lovelace”和“ richard stallman”。 您真正想要的是每个作业两个不同的参数。
幸运的是,这种技术性是由Parallel本身解析的。 如果将--max-args
设置为2
,则会得到两个变量{1}
和{2}
,分别代表参数的第一部分和第二部分:
$ ls -1 | parallel --max-args=2 cat {1} {2} ">" {1}_{2}.person
在此命令中,变量{1}
是ada或richard(取决于您要看的工作),而变量{1}
{2}
是lovelace
或stallman
。 这些文件的内容与在引号中的重定向符号重定向(报价从猛砸抢重定向符号使并行可以使用它),并放置到所谓的新文件ada_lovelace.person
和richard_stallman.person
。
$ ls -1
ada
ada_lovelace.person
lovelace
richard
richard_stallman.person
stallman
$ cat ada_*person
ada lovelace
$ cat ri*person
richard stallman
如果一整天都在分析大小为数百兆字节的日志文件,那么您可能会发现并行化文本解析对您很有用; 否则,这主要是说明性练习。
但是,这种处理不仅对文本解析有重要的作用。 这是电影界的真实例子。 考虑需要结合在一起的视频文件和音频文件的目录。
$ ls -1
12_LS_establishing-manor.avi
12_wildsound.flac
14_butler-dialogue-mixed.flac
14_MS_butler.avi
...and so on...
使用相同的原理,可以创建一个简单的命令,以便将文件并行组合:
$ ls -1 | parallel --max-args=2 ffmpeg -i {1} -i {2} -vcodec copy -acodec copy {1}.mkv
所有这些花哨的输入和输出解析都不符合每个人的喜好。 如果您希望使用更直接的方法,则可以在Parallel处抛出命令然后走开。
首先,在每一行上使用一个命令创建一个文本文件:
$ cat jobs2run
bzip2 oldstuff.tar
oggenc music.flac
opusenc ambiance.wav
convert bigfile.tiff small.jpeg
ffmepg -i foo.avi -v:b 12000k foo.mp4
xsltproc --output build/tmp.fo style/dm.xsl src/tmp.xml
bzip2 archive.tar
然后将文件交给Parallel:
$ parallel --jobs 6 < jobs2run
现在,文件中的所有作业均以并行方式运行。 如果存在的作业多于允许的作业,则Parallel会形成并维护队列,直到所有作业都运行为止。
GNU Parallel是一个功能强大且灵活的工具,用例远远超出了本文的适用范围。 它的手册页提供了您可以执行的非常酷的操作的示例,从通过SSH远程执行到将Bash函数合并到Parallel命令中。 YouTube上甚至有广泛的演示系列,因此您可以直接向GNU Parallel团队学习。 GNU Parallel首席维护人员还刚刚发布了该命令的官方指南,该指南可从Lulu.com获得 。
GNU Parallel可以改变您的计算方式,如果不这样做,它至少会改变您的计算机计算时间。 立即尝试!
gnu parallel