使用parallel加速单线程程序
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
个块,然后调用 102
个 grep
进程来处理,最后将结果进行合并,这个过程显然是太繁杂了。
为此我们可以使用 --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
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK