并行执行Unix命令?
Parallel execution of Unix command?
我写了一个 shell 程序,它使用 csplit
自动将文件分成 4 个部分,然后是四个 shell 程序,它使用 nohup
在后台执行相同的命令和一个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+=} END {print s}'
10000000
real 0m41.984s
user 0m1.122s
sys 0m36.251s
当我为 2GB 文件(约 1000 万)条记录尝试此操作时,它花费了 20 多分钟。
这个命令只能在多核系统上使用吗(我目前使用的是单核系统)
nproc --all
1
简而言之,是的。您将需要机器上的更多物理内核才能从并行中获益。只是为了了解你的任务;以下是您打算执行的操作
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 代表处理器数量。
更新
为什么要在 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 进行高速数据访问。
--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+=} 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+=} 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+=} 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+=} END {print s}'
1888888898
real 0m2.242s
user 0m0.424s
sys 0m2.880s
所以在我的旧笔记本电脑上,我可以在 2.2 秒内处理 1.8 GB。
如果您只有一个核心并且您的工作是 CPU 依赖的,那么并行化将无济于事。如果大部分时间都花在等待上(例如等待网络),在单核机器上并行化是有意义的。
但是,您计算机的时间告诉我,这其中有一些非常不对劲的地方。我会建议您在另一台计算机上测试您的程序。
我写了一个 shell 程序,它使用 csplit
自动将文件分成 4 个部分,然后是四个 shell 程序,它使用 nohup
在后台执行相同的命令和一个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+=} END {print s}'
10000000
real 0m41.984s
user 0m1.122s
sys 0m36.251s
当我为 2GB 文件(约 1000 万)条记录尝试此操作时,它花费了 20 多分钟。
这个命令只能在多核系统上使用吗(我目前使用的是单核系统)
nproc --all
1
简而言之,是的。您将需要机器上的更多物理内核才能从并行中获益。只是为了了解你的任务;以下是您打算执行的操作
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 代表处理器数量。
更新 为什么要在 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 进行高速数据访问。
--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+=} 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+=} 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+=} 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+=} END {print s}'
1888888898
real 0m2.242s
user 0m0.424s
sys 0m2.880s
所以在我的旧笔记本电脑上,我可以在 2.2 秒内处理 1.8 GB。
如果您只有一个核心并且您的工作是 CPU 依赖的,那么并行化将无济于事。如果大部分时间都花在等待上(例如等待网络),在单核机器上并行化是有意义的。
但是,您计算机的时间告诉我,这其中有一些非常不对劲的地方。我会建议您在另一台计算机上测试您的程序。