在编写时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核计算机上执行时seq
,split
和wc
进程共享内核。但仔细观察,系统会将前两个进程留在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
(或通常是管道)进行并行化可能就不值得了。
A | B | C
在单独的过程中是并行的,但是由于管道的特性(B必须等待A的输出,C必须等待B的输出),在某些情况下它可能仍然是线性的。这完全取决于它们产生什么样的输出。在很多情况下,运行多次B
会很有帮助,并行wc示例完全有可能比常规示例慢,wc
因为拆分可能比正常计算行占用更多资源。小心使用。