并行执行管道命令


16

请考虑以下情形。我有两个程序A和B。程序A输出到字符串的stdout行,而程序B处理来自stdin的行。当然,使用这两个程序的方法是:

foo @ bar:〜$ A | 乙

现在,我注意到这只占用了一个核心。因此,我想知道:

程序A和B是否共享相同的计算资源?如果是这样,是否可以同时运行A和B?

我注意到的另一件事是A的运行速度比B快得多,因此我想知道是否可以以某种方式运行更多的B程序并让它们并行处理A输出的行。

也就是说,A将输出其行,并且将有N个程序B实例读取这些行(无论谁先读取它们)来处理它们并在stdout上输出它们。

所以我的最后一个问题是:

有没有一种方法可以将输出传送到多个B进程中的A,而不必考虑竞争条件和其他可能引起的不一致?


1
尽管A | B | C在单独的过程中是并行的,但是由于管道的特性(B必须等待A的输出,C必须等待B的输出),在某些情况下它可能仍然是线性的。这完全取决于它们产生什么样的输出。在很多情况下,运行多次B会很有帮助,并行wc示例完全有可能比常规示例慢,wc因为拆分可能比正常计算行占用更多资源。小心使用。
frostschutz

Answers:


14

有问题 split --filter在于输出可能会混合在一起,因此您会从流程1获得一半的行,然后从流程2获得一半的行。

GNU Parallel保证不会混淆。

因此,假设您要执行以下操作:

 A | B | C

但是B太慢了,因此您要并行化它。然后,您可以执行以下操作:

A | parallel --pipe B | C

默认情况下,GNU Parallel分割为\ n,块大小为1 MB。可以使用--recend和--block进行调整。

您可以在以下位置找到有关GNU Parallel的更多信息: http //www.gnu.org/s/parallel/

您可以在10秒内安装GNU Parallel:

wget -O - pi.dk/3 | sh 

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


1
虽然我在安装方法:-)上存在很大分歧,但+1是因为您的解决方案解决了我的大多数问题。
LSerni 2013年

这确实不错。您还对要使用的参数有任何建议吗?我知道程序A将每分钟输出1TB以上的数据,约5GB。程序B处理数据的速度比A输出慢5倍,为此任务我拥有5个内核。
Jernej 2013年

目前,GNU Parallel最多可以处理大约100 MB / s的速度,因此您将要达到该限制。最佳选择--block-size取决于RAM的数量以及启动新磁盘的速度B。在您的情况下,我会使用--block 100M并查看效果如何。
Ole Tange 2013年

@lserni您能否提出一种更好的安装方法,该方法适用于大多数UNIX计算机,并且需要用户进行类似的工作?
Ole Tange 2013年

4
抱歉,我没有说清楚。安装方法-传递给脚本sh-很棒。问题在于将其传递给sh:从站点下载并运行可执行代码。提醒您,也许我只是太偏执,因为有人可能会反对定制RPM或DEB基本上是同一件事,甚至将代码张贴在要复制和粘贴的页面上也会导致人们盲目地这样做。无论如何。
LSerni 2013年

13

在编写时A | B,两个过程都已经并行运行。如果您认为它们仅使用一个内核,则可能是由于CPU相似性设置(也许有某种工具可以生成具有不同相似性的进程)或因为一个进程不足以容纳整个内核,而系统“倾向于“不要分散计算。

要与一个A一起运行多个B,您需要一个工具,例如split带有--filter选项的工具:

A | split [OPTIONS] --filter="B"

但是,这很容易弄乱输出中的行顺序,因为B作业不会以相同的速度运行。如果这是一个问题,则可能需要将第B i个输出重定向到中间文件,并在最后使用将它们缝合在一起cat。反过来,这可能需要大量的磁盘空间。

其他选项存在(例如,你可以B的每个实例限制为单行缓冲输出,等到整个B的的“圆圆”已经完成,运行等同的减少split地图,以及cat虚拟输出在一起)具有不同的效率水平。例如,刚刚描述的“回合”选项将等待B最慢实例完成,因此它将很大程度上取决于B的可用缓冲。[m]buffer可能有帮助,也可能没有帮助,具体取决于操作是什么。

例子

生成前1000个数字并并行计算行数:

seq 1 1000 | split -n r/10 -u --filter="wc -l"
100
100
100
100
100
100
100
100
100
100

如果我们要“标记”这些行,我们会看到第一行发送到进程#1,第五行发送到进程#5,依此类推。而且,在split产生第二个过程所需的时间中,第一个已经是进入其配额的好方法:

seq 1 1000 | split -n r/10 -u --filter="sed -e 's/^/$RANDOM - /g'" | head -n 10
19190 - 1
19190 - 11
19190 - 21
19190 - 31
19190 - 41
19190 - 51
19190 - 61
19190 - 71
19190 - 81

在2核计算机上执行时seqsplitwc进程共享内核。但仔细观察,系统会将前两个进程留在CPU0上,并在工作进程之间划分CPU1:

%Cpu0  : 47.2 us, 13.7 sy,  0.0 ni, 38.1 id,  1.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  : 15.8 us, 82.9 sy,  0.0 ni,  1.0 id,  0.0 wa,  0.3 hi,  0.0 si,  0.0 st
  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM     TIME+ COMMAND
 5314 lserni    20   0  4516  568  476 R 23.9  0.0   0:03.30 seq
 5315 lserni    20   0  4580  720  608 R 52.5  0.0   0:07.32 split
 5317 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.86 wc
 5318 lserni    20   0  4520  572  484 S 14.0  0.0   0:01.88 wc
 5319 lserni    20   0  4520  576  484 S 13.6  0.0   0:01.88 wc
 5320 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.85 wc
 5321 lserni    20   0  4520  572  484 S 13.3  0.0   0:01.84 wc
 5322 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.86 wc
 5323 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.86 wc
 5324 lserni    20   0  4520  576  484 S 13.3  0.0   0:01.87 wc

请特别注意,这split正在消耗大量的CPU。这将与A的需求成比例地减少;即,如果A是一个比A重的过程seq,则的相对开销split将减少。但是,如果A是一个非常轻量级的过程,而B则非常快(因此与A保持在一起,您只需要2-3个B就可以了),那么与split(或通常是管道)进行并行化可能就不值得了。


有趣的是,在Ubuntu上找到的拆分没有--filter选项。为此使用哪种操作系统?
Jernej 2013年

带有coreutils(gnu.org/software/coreutils/manual/html_node/…)的Linux OpenSuSE 12.3 。我将尝试使用Ubuntu,他们可能已经更改了名称,以容纳一些名称相似的工具。
LSerni 2013年

您确定split --filter缺少该选项吗?在我的Ubuntu 12.04-LTS(“ wheezy / sid”)上,它就在那里,我的示例也可以正常工作。您可以安装与splitGNU coreutils中的安装不同的安装吗?
LSerni 2013年

谢谢你 我必须安装更新版本的Coreutils。顺便说一句,我已经注意到,如果我单独运行程序A,那么如果我运行A |则它会消耗整个内核(100%)。然后B一起吃掉整个核心,A进程吃掉15%,B进程吃掉85%。您是否偶然知道为什么会这样?
Jernej 2013年

2
这可能是由于阻塞。如果B重于A,则A无法发送其输出并且速度变慢。另一种可能性是A 在操作过程中屈服于 B(例如磁盘/网络)。在其他系统上,您可能会看到B吞噬了100%的CPU1,而A则被分配了18%的CPU0。您可能需要85/15〜5.67 = B的5至6个实例才能获得单个A实例来使单个核饱和。但是,如果存在I / O,则可能会扭曲这些值。
LSerni 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.