1

使用parallel加速单线程程序

 3 years ago
source link: https://www.lujun9972.win/blog/2019/03/25/%E4%BD%BF%E7%94%A8parallel%E5%8A%A0%E9%80%9F%E5%8D%95%E7%BA%BF%E7%A8%8B%E7%A8%8B%E5%BA%8F/index.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用parallel加速单线程程序

Use Multiple CPU Cores(Parallelize) with Single Threaded Linux Commands 看到的,记录一下。

使用parallel加速单线程程序的原理

使用parallel加速单线程程序的原理在于使用 --pipe/--spreadstdin 将标准输入的内容切成多段,然后每段调用一个进程来处理,最后将处理结果整合在一起。比如:

ls -lh big.txt  
-rw-r--r--  1 westlund  staff   102M Nov  1 21:23 big.txt

time grep regex bigfile.txt  
real    0m2.376s  
user    0m2.354s  
sys     0m0.021s

time cat big.txt | parallel --pipe grep regex  
real    0m2.592s  
user    0m5.908s  
sys     0m2.498s  

但是你会发现上面用 parallel 进行并行处理后所花费的时间反而更多了,这是因为 --pipe 默认将stdin的内容分成每块1M,而且默认的并发量是CPU的个数。 也就是说上面 102M 的文件内容会分成 102 个块,然后调用 102grep 进程来处理,最后将结果进行合并,这个过程显然是太繁杂了。

为此我们可以使用 --block 参数来指定每块的大小,比如

time cat big.txt | parallel --block 25M --pipe grep regex
real    0m1.626s
user    0m4.634s
sys     0m0.620s

这就明显快了很多了。

使用parallel加速单线程程序可能遇到的问题

将STDIN拆分成多块后再并发处理在提高效率的同时也会带来一些问题:

并发运行多个进程时,就无法保证输出结果的一致性了, 比如下面这个例子:

echo -n 2 1 4 3 | parallel -d " " -j4 "sleep {}; echo {}" # -d的意思是设定分隔符,-j的意思是指定并发数

你会发现输出的顺序发生了改变。但这个问题可以通过 -k/--keep-order 来解决,比如:

echo -n 2 1 4 3 | parallel -d " " -k -j4 "sleep {}; echo {}" # -d的意思是设定分隔符,-j的意思是指定并发数
2
1
4
3

这次输出的顺序一样了

不是所有的任务都能够进行分拆

比如,我要计算一系列数字的总和,很明显这种任务不能单纯的用拆分来解决,拆分后还需要有一个合并的过程。比如

ls -lh random_numbers.txt
-rw-r--r--  1 westlund  staff    22M Nov  1 21:56 random_numbers.txt

time cat random_numbers.txt | awk '{sum+=$1} END {print sum}'
65538384640
real    0m2.408s
user    0m2.402s
sys     0m0.021s

time cat random_numbers.txt | parallel --block 2M --pipe awk \'{sum+=\$1} END {print sum}\'
6067097462
6064980068
6074889658
6068292593
6073256962
6065663642
6068441658
6071296753
4846052534
6072985491
6065427819
real    0m1.436s
user    0m4.390s
sys     0m0.358s

time cat random_numbers.txt | parallel --block 2M --pipe awk \'{sum+=\$1} END {print sum}\' | awk '{sum+=$1} END {print sum}'
65538384640
real    0m1.408s
user    0m4.341s
sys     0m0.356s

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK