使用parallel加速单线程程序

该博客探讨了如何利用GNU Parallel工具加速单线程程序,解释了其原理是通过分割标准输入并并行处理,同时指出可能出现的乱序问题和并非所有任务都适合分拆的挑战。通过示例展示了如何调整块大小以提高效率,并提到了解决方案来保持输出顺序的一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:https://raw.githubusercontent.com/lujun9972/lujun9972.github.com/source/linux和它的小伙伴/使用parallel加速单线程程序.org

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的意思是指定并发数
1
2
3
4

你会发现输出的顺序发生了改变。但这个问题可以通过 -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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值