TypechoJoeTheme

MetMan's Blog

网站页面

GNU Parallel并行加速脚本运行

MetMan博 主
2024-05-21
/
0 评论
/
184 阅读
/
828 个字
/
百度已收录
05/21
本文最后更新于 2024年05月21日,已超过 121天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!

GNU Parallel是xargs和shell循环的替代品,可以利用多核CPU并行执行任务(jobs),加快命令行脚本的运行速度。这里的任务(job)可以是单个命令或者一个shell小脚本。并行执行有一个任务池,将任务池中任务分发给每个进程单独执行,这里的任务池指输入源列表。一般输入源包括文件列表、主机列表、用户列表等等,每一个列表项就是一个任务的参数。本质上,parallel工具是一个perl脚本。

安装

如果机器上没有parallel命令,可以自行安装。

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \ fetch -o - http://pi.dk/3 ) > install.sh 
$ bash install.sh

并行执行

paralle可以替代xargs -P功能

# sleep 1+2+3+4+5 = 15秒
$ time echo {1..5} | xargs -n 1 sleep
#使用5个进程,最长的需要5秒
$ time echo {1..5} | xargs -n 1 -P 5 sleep # -n接受最多参数,-P最大进程数
# 以上命令可用paralle代替
$ time parallel sleep {} ::: {1..5}

{}是参数占位符,可以省略,具体参数来自于后面的:::输入源列表。

我们看看parallel执行情况。

$ parallel sleep {} ::: {30..40}
$ ps aux | grep sleep

从下图可以看出paralle命令根据输入的参数列表启动了多个进程运行,并且可以看出paralle命令实际上是一个perl脚本。

输入源

parallel可以从文件、命令行、stdin、管道读入参数列表。

$ parallel echo ::: A B C        # 命令行输入 
$ parallel -a abc-file echo      # 文件
$ cat abc-file | parallel echo   # 管道

多个输入源

如果命令需要多个参数,可以使用:::连接多组输入源,不同输入源两两组合。

$ parallel echo ::: A B C ::: D E F  # 多组输入源组合
A D
A E
A F
B D
B E
B F
C D
C E
C F
$ parallel -a abc-file -a def-file echo
$ cat abc-file | parallel -a - -a def-file echo #使用 - 组合
$ cat abc-file | parallel echo :::: - def-file  # ::::代替-

命令可以是bash函数

# only works in bash 
my_func() {
  echo in my_func $1
}
export -f my_func 
parallel my_func ::: 1 2 3

替换字符串

预定义的替换字符串操作,可以用于路径文件名处理

$ parallel echo ::: A/B.C  #不改变字符串,等价于{}
A/B.C
$ parallel echo {} ::: A/B.C   #缺省
A/B.C
$ parallel echo {.} ::: A/B.C   #去除扩展名
A/B
$ parallel echo {/} ::: A/B.C   #去除路径
B.C
$ parallel echo {//} ::: A/B.C  #保留路径
A
$ parallel echo {/.} ::: A/B.C   #去除路径和扩展
B
$ parallel echo {#} ::: A B C    #给出任务号,从1到任务总数
1
2
3
$ parallel echo {2} {1} ::: A B C ::: D E F  # {n} 第n组输入源
$ parallel echo {2} ::: A B C ::: D E F 
$ seq 5 | parallel echo placeholder_{}

控制并行任务数

默认情况下,paralle命令会自动侦测到节点可用CPU核数,并且尽可能多的使用CPU核并发运行作业。

比如测试的节点有32个CPU核,

$ parallel echo {%} ::: {1..33}
1
2
3
...
31
32
1

使用{%}输出job slot number,不同于任务号,根据同时并发运行任务数,将所有任务分配到每一个slot槽中并分配一个序号。如果任务总数超过允许的同时并发数目,一个slot中会分配超过一个任务数。上面例子中由于使用节点只有32个核,最多并发运行32个作业,因此slot number在1-32之间。

使用--jobs或者-j控制允许同时运行的任务数。

$ parallel --jobs 4 echo {%} ::: {1..33}
1
2
3
4
1
2
3
4
...
$ parallel --jobs 2 "sleep {}; echo {}" ::: 5 4 3 2 1

查看执行命令但不实际执行

使用--dryrun查看执行命令,但不实际执行,常用于开发验证阶段。

$ parallel --dryrun echo {2} {1} ::: bird flower fish ::: Red Green Blue
echo Red bird
echo Green bird
echo Blue bird
echo Red flower
echo Green flower
echo Blue flower
echo Red fish
echo Green fish
echo Blue fish

{2} {1}指定输入源顺序,第二组输入在前。

控制输出顺序

--keep-order或者-k控制输出顺序与输入顺序相同。默认是乱序的,按照命令执行快慢。

$ parallel --keep-order --tag "sleep {}; echo {}" ::: 5 4 3 2 1

管道模式

# 大文件切割多个块并行处理
$ cat bigfile | parallel --pipe wc -l

$ parallel --pipepart -a bigfile --block -l --recstart ">" grep foobar

循环并行

parallel命令代替shell循环for/while。下面示例中括号()中执行for或者while循环,是将命令放在子shell中执行。加括号执行好处是命令组合更加清晰,同时限定变量的作用范围。

# Standard for-loop that does something with each line in a file called 'list'
(for x in `cat list` ; do
  do_something $x
done) | process_output

# Standard while-read-loop that does something with each line in a file called 'list'
cat list | (while read x ; do
  do_something $x
done) | process_output

# Converted into GNU parallel command
cat list | parallel do_something | process_output

实例

wgrib2裁剪小区域grib数据

  • 生成文件列表再通过管道并行执行
#!/bin/bash                                                        #生成文件列表
for file in `ls 2022072600/*.grb2`                    
do                                                                  
   echo $file >> fnames.txt                                        
done     
# 使用4个进程并行执行
cat fnames.txt | parallel --jobs 4 wgrib2 {} -small_grib 100:120 30:50 result/{/.}_new.grb2  # {/.}去除路径和后缀名
  • 可以不用临时文件fnames.txt
$ ls 2022072600/*grb2 | parallel --jobs 4 wgrib2 {} -small_grib 100:120 30:50 result/{/.}_new.grb2

或者

$ find 2022072600 -name "*.grb2" -type f | parallel --jobs 4 wgrib2 {} -small_grib 100:120 30:50 result/{/.}_new.grb2

参考资料

parallel cheatsheet

parallel_tutorial.pdf (gnu.org)

Parallelising Jobs with GNU Parallel

15分钟并行神器gnu parallel入门指南

parallelbash
朗读
赞(0)
赞赏
感谢您的支持,我会继续努力哒!
版权属于:

MetMan's Blog

本文链接:

https://blog.metman.top/index.php/archives/102/(转载时请注明本文出处及文章链接)

评论 (0)

互动读者

标签云

最新回复

暂无回复

登录
X
用户名
密码