我编写了一个shell程序,它使用csplit
自动将文件分成4个部分,然后使用nohup
在后台执行相同命令的4个shell程序,一个while循环将查找这些文件的完成情况四个进程,最后是cat
output1.txt .... output4.txt> finaloutput.txt
但后来我开始了解这个命令parallel
,我尝试使用大文件,但看起来它没有按预期工作。此文件是以下命令的输出 -
for i in $(seq 1 1000000);do cat /etc/passwd >> data.txt1;done
time wc -l data.txt1
10000000 data.txt1
real 0m0.507s
user 0m0.080s
sys 0m0.424s
并行
time cat data.txt1 | parallel --pipe wc -l | awk '{s+=$1} END {print s}'
10000000
real 0m41.984s
user 0m1.122s
sys 0m36.251s
当我尝试使用2GB文件(~1000万)记录时,花了20多分钟。
此命令是否仅适用于多核系统(我目前使用的是单核系统)
nproc --all
1
答案 0 :(得分:3)
--pipe
效率低下(虽然不是你所测量的规模 - 你系统上的某些东西是非常错误的)。它可以以1 GB / s(总计)的顺序提供。
--pipepart
非常高效。如果您的磁盘足够快,它可以以每核1 GB / s的速度提供。这应该是处理data.txt1
的最有效方式。它会将data.txt1
拆分为每个cpu核心一个块,并将这些块提供给每个核心上运行的wc -l
:
parallel --block -1 --pipepart -a data.txt1 wc -l
您需要版本20161222或更高版本才能使block -1
正常工作。
这些是来自我的旧双核笔记本电脑的时间。 seq 200000000
生成1.8 GB的数据。
$ time seq 200000000 | LANG=C wc -c
1888888898
real 0m7.072s
user 0m3.612s
sys 0m2.444s
$ time seq 200000000 | parallel --pipe LANG=C wc -c | awk '{s+=$1} END {print s}'
1888888898
real 1m28.101s
user 0m25.892s
sys 0m40.672s
这里的时间主要是由于GNU Parallel为每个1 MB块生成一个新的wc -c
。增加块大小会使其更快:
$ time seq 200000000 | parallel --block 10m --pipe LANG=C wc -c | awk '{s+=$1} END {print s}'
1888888898
real 0m26.269s
user 0m8.988s
sys 0m11.920s
$ time seq 200000000 | parallel --block 30m --pipe LANG=C wc -c | awk '{s+=$1} END {print s}'
1888888898
real 0m21.628s
user 0m7.636s
sys 0m9.516s
如上所述--pipepart
如果文件中包含数据则要快得多:
$ seq 200000000 > data.txt1
$ time parallel --block -1 --pipepart -a data.txt1 LANG=C wc -c | awk '{s+=$1} END {print s}'
1888888898
real 0m2.242s
user 0m0.424s
sys 0m2.880s
因此,在我的旧笔记本电脑上,我可以在2.2秒内处理1.8 GB。
如果您只有一个核心并且您的工作依赖于CPU,那么并行化将无助于您。如果大部分时间都花在等待(例如,等待网络),那么在单个核心机器上并行化是有意义的。
但是,计算机的时间告诉我这是非常错误的。我建议你在另一台电脑上测试你的程序。
答案 1 :(得分:0)
简而言之是..您需要在机器上使用更多物理内核才能从并行中获益。只是为了理解你的任务;以下是你打算做的事情
file1 is a 10,000,000 line file
split into 4 files >
file1.1 > processing > output1
file1.2 > processing > output2
file1.3 > processing > output3
file1.4 > processing > output4
>> cat output* > output
________________________________
并且您希望并行化中间部分并同时在4个核心(希望是4个核心)上运行它。我对么?我认为你可以用更好的方式使用GNU parallel为其中一个文件编写代码并使用该命令(psuedocode warning)
parallel --jobs 4 "processing code on the file segments with sequence variable {}" ::: 1 2 3 4
其中-j表示处理器数量。
UPDATE 为什么要在file1.1 1.2 1.3和1.4中尝试并行执行顺序执行命令?让它成为你编码的常规顺序处理
parallel 'for i in $(seq 1 250000);do cat file1.{} >> output{}.txt;done' ::: 1 2 3 4
以上代码将在4核上并行运行csplit的4个分段文件
for i in $(seq 1 250000);do cat file1.1 >> output1.txt;done
for i in $(seq 1 250000);do cat file1.2 >> output2.txt;done
for i in $(seq 1 250000);do cat file1.3 >> output3.txt;done
for i in $(seq 1 250000);do cat file1.4 >> output4.txt;done
我很确定 - Ole上面提到的--diskpart是更好的方法;鉴于您可以从HDD进行高速数据访问。