linuxparallel命令,Linux并⾏处理神器GNUParallel简明教程Bash命令通常单线程运⾏,这意味着所有的处理⼯作只在单个 CPU 上执⾏。随着 CPU 规模的扩⼤以及核⼼数⽬的增加,这意味着只有⼀⼩部分的 CPU 资源⽤于处理任务,这样就造成了很⼤的资源浪费。 这种情况在进⾏多媒体转换(⽐如:图⽚和视频转换)以及数据压缩中经常遇到。
本⽂我们将介绍如何使⽤ GNU Parallel 程序在所有 CPU 核上并⾏地执⾏计算任务。
Parallel 介绍GNU Parallel 是⼀种通⽤的并⾏化程序,可以在同⼀台机器上或在您具有 SSH 访问权限的多台机器上轻松并⾏运⾏作业。
如果要在 4 个 CPU 上运⾏ 32 个不同的作业,并⾏化的⼀种直接⽅法是在每个 CPU 上运⾏ 8 个作业。
GNU Parallel 会在完成后⽣成⼀个新进程,并保持 CPU 处于活动状态,从⽽节省时间。
Parallel 安装
1. 通过包安装
·CentOS / RHEL
$ yum install parallel
·Ubuntu / Debian
$ sudo apt install parallel
2. 通过脚本安装
$ (wget -O - pi.dk/3 || curl pi.dk/3/) | bash
Parallel 使⽤
Parallel 语法简介
Usage:parallel [options] [command [arguments]] < list_of_argumentsparallel [options] [command [arguments]] (:::
arguments|:::: argfile(s))...cat ... | parallel --pipe [options] [command [arguments]]
·Parallel 常⽤选项
:
:: 后⾯接参数。:::: 后⾯接⽂件。-j、--jobs 并⾏任务数,不想并⾏执⾏可以设为 1。若不加 -j,则预设为每个 CPU 执⾏⼀个 job。-N 每次输⼊的参数数量。-L N: ⼀次最多读取 N ⾏。--xargs 会在⼀⾏中输⼊尽可能多的参数。-xapply 从每⼀个源获取⼀个参数(或⽂件⼀⾏)。--header 把每⼀⾏输⼊中的第⼀个值做为参数名。-m 表⽰每个 job 不重复输出“背景”(context)。-X 与 -m 相反,会重复输
出“背景⽂本”。-q 保护后⾯的命令。--trim lr 去除参数两头的空格,只能去除空格,换⾏符和 tab 都不能去除。--keep-order/-k 强制使输出与参数保持顺序 --keep-order/-k。--tmpdir/ --results 都是保存⽂件,但是后者可以有结构的保存。--delay 延迟每个任务启动时间。--halt 终⽌任务。--pipe 该参数使得我们可以将输⼊(stdin)分为多块(block),再将 stdin 的资料分给各个 jobs。--block 参数可以指定每块的⼤⼩。
Parallel ⽤法简介
1. 输⼊源
GNU Parallel 的输⼊源⽀持⽂件、命令⾏和标准输⼊( Stdin 或 Pipe)。
以命令⾏做为输⼊源。
$ parallel echo ::: a b c d e | abcde
以 Stdin(标准输⼊)作为输⼊源。
$ | parallel echoabcde
GNU Parallel ⽀持通过命令⾏指定多个输⼊源,它会⽣成所有的组合。
$ parallel echo ::: A B C ::: D E F | A DA EA FB DB EB FC DC EC F
多个⽂件作为输⼊,此时多个⽂件中的内容也会像上⾯那样进⾏组合。
$ parallel - - echo
Stdin(标准输⼊)作为⽂件源中的⼀个,使⽤ -, 输出结果同上。
$ |parallel -a - - echo
使⽤ :::: 代替 -a,后⾯可接多个⽂件名。
$ | parallel echo :::: - b.txt
::: 和 :::: 可以同时使⽤,同样的输出结果也会进⾏组合。
$ parallel echo ::: a b :::: b.txt
当然,若不想像上⾯那样进⾏组合,可使⽤--xapply参数从每⼀个源获取⼀个参数(或⽂件⼀⾏),这个参数有些类似 R 中的函数,具有⼴播作⽤。如果其中⼀个输⼊源的长度⽐较短,它的值会被重复。
$ parallel --xapply echo ::: A B C ::: D E FA DB EC F$ parallel --xapply echo ::: A B C ::: D E F G H IA DB EC FA GB HC I
2. 改变参数分隔符
GNU Parallel 可以通过 --arg-sep 和 --arg-file-sep 指定分隔符替代 ::: 或 ::::,当这两个符号被其它命令占⽤的时候会特别有⽤。
$parallel -k --arg-sep ,,, echo ,,, a b ,,, c d | a ca db cb d$parallel --xapply --arg-file-sep ,,,, echo ,,,, a.txt b.txta A Db A Ec A Fd B De B Ea B Fb C Dc C Ed C F
3. 改变输⼊分隔符
GNU Parallel 默认把⼀⾏做为⼀个参数。使⽤ \n 做为参数定界符,可以使⽤ -d 改变。
$ parallel -d b echo :::: a.txtacde
4. 提前结束和跳过空⾏
GNU Parallel ⽀持通过 -E 参数指定⼀个值做为结束标志。
$ parallel -E stop echo ::: A B stop C DAB
perl下载安装教程GNU Parallel 使⽤ --no-run-if-empty 来跳过空⾏。
$ (echo 1; echo; echo 2) | parallel --no-run-if-empty echo12
5. 构建命令⾏
如果 Parallel 之后没有给定命令,那么这些参数会被当做命令。
$ parallel ::: ls 'echo foo' xtjianchenmypipescriptssnake_testWGS_snakefoo/home/sxuan
此外,命令还可以是⼀个脚本⽂件,⼀个⼆进制可执⾏⽂件或⼀个Bash的函数(须⽤export -f导出函数)。
$ echo "echo \$*" > s.sh$ parallel ./s.sh ::: "a b c f" "1 2 3 4"a b c f1 2 3 4
6. 替换字符串
GNU Parallel ⽀持多种替换字符串,默认使⽤ {},使⽤ -I 改变替换字符串符号 {}。
其最常见的字符串替换包括以下⼏种:
·{.},去掉扩展名·{/},去掉路径,只保留⽂件名·{//},只保留路径·{/.},同时去掉路径和扩展名·{#},输出任务编号
同时对于每⼀个字符串替换都可以⾃⼰指定符号:
·-I 对应{}·--extensionreplace 替换 {.}·--basenamereplace 替换 {/}·--dirnamereplace 替换 {//}·--basenameextensionreplace 替换 {/.}·--seqreplace 替换 {#}
$ parallel echo ::: A/B.C ; parallel echo {} ::: A/B.C ; parallel -I ,, echo ,, ::: A/B.CA/B.CA/B.CA/B.C$ parallel echo {.} ::: A/B.C ; parallel --extensionreplace ,, echo ,, ::: A/B.CA/BA/B$ parallel echo {/} ::: A/B.C ; parallel --basenamereplace ,, echo ,, :::
A/B.CB.CB.C$ parallel echo {//} ::: A/B.C ; parallel --dirnamereplace ,, echo ,, ::: A/B.CAA$ parallel echo {/.} ::: A/B.C ; parallel --basenameextensionreplace ,, echo ,, ::: A/B.CBB$ parallel echo {#} ::: A B C ; parallel --seqreplace ,, echo ,, ::: A B C123123
同时,如果有多个输⼊源时,可以通过 {编号} 指定某⼀个输⼊源的参数。
$ parallel --xapply echo {1} and {2} ::: A B ::: C DA and CB and D
可以使⽤ / // /. 和 . 改变指定替换字符串。
$ parallel echo /={1/} //={1//} /.={1/.} .={1.} ::: A/B.C D/E.F/=B.C //=A /.=B .=A/B/=E.F //=D /.=E .=D/E
位置可以是负数,表⽰倒着数。
$ parallel echo 1={1} 2={2} 3={3} -1={-1} -2={-2} -3={-3} ::: A B ::: C D ::: E F1=A 2=C 3=E -1=E -2=C -3=A1=A 2=C 3=F -
1=F -2=C -3=A1=A 2=D 3=E -1=E -2=D -3=A1=A 2=D 3=F -1=F -2=D -3=A1=B 2=C 3=E -1=E -2=C -3=B1=B 2=C 3=F -1=F -2=C -3=B1=B 2=D 3=E -1=E -2=D -3=B1=B 2=D 3=F -1=F -2=D -3=B
7. 按列输⼊和指定参数名
使⽤ --header 把每⼀⾏输⼊中的第⼀个值做为参数名。
$ parallel --xapply --header : echo f1={f1} f2={f2} ::: f1 A B ::: f2 C D | f1=A f2=Cf1=B f2=D
使⽤ --colsep 把⽂件中的⾏切分为列,做为输⼊参数。
$ perl -e 'printf "f1\tf2\nA\tB\nC\tD\n"' > tsv-file.tsv$ parallel --header : --colsep '\t' echo f1={f1} f2={f2} :::: tsv-
file.tsv f1=A f2=Bf1=C f2=D
8. 多参数
--xargs 会在⼀⾏中输⼊尽可能多的参数(与参数字符串长度有关),通过 -s 可指定⼀⾏中参数的上限。
$ perl -e 'for(1..30000){print "$_\n"}' > num30000$ cat num30000 | parallel --xargs echo | wc -l3$ cat num30000 | parallel --xargs -s 10000 echo | wc -l17
为了获得更好的并发性,GNU Parallel 会在⽂件读取结束后再分发参数。
GNU Parallel 在读取完最后⼀个参数之后,才开始第⼆个任务,此时会把所有的参数平均分配到 4 个任务(如果指定了4个任务)。
第⼀个任务与上⾯使⽤ --xargs 的例⼦⼀样,但是第⼆个任务会被平均的分成 4 个任务,最终⼀共 5 个任务。
$ cat num30000 | parallel --jobs 4 -m echo | wc -l5
将 1-10 分参数分配到4个任务可以看得更清晰。
$ parallel --jobs 4 -m echo ::: {1..10}1 2 34 5 67 8 910
替换字符串可以是输出字符的⼀部分,使⽤ -m 参数表⽰每个 job 不重复输出 “背景”(context),-X 则与 -m 相反,会重复输出 “背景⽂本”,具体通过下⾯⼏个例⼦进⾏理解。
$ parallel --jobs 4 echo pre-{}-post ::: A B C D E F Gpre-A-postpre-B-postpre-C-postpre-D-postpre-E-postpre-F-postpre-G-post$ parallel --jobs 4 -m echo pre-{}-post ::: A B C D E F Gpre-A B-postpre-C D-postpre-E F-postpre-G-post$ parallel --jobs 4 -X echo pre-{}-post ::: A B C D E F Gpre-A-post pre-B-postpre-C-post pre-D-postpre-E-post pre-F-postpre-G-post
使⽤ -N 限制每⾏参数的个数,其中 -N0 表⽰⼀次只读取⼀个参数,且不输⼊这个参数(作为计数器来使⽤)。
$ parallel -N4 echo 1={1} 2={2} 3={3} ::: A B C D E F G H1=A 2=B 3=C1=E 2=F 3=G$parallel -N0 echo foo ::: 1 2
3foofoofoo
9. 引⽤
如果命令⾏中包含特殊字符,就需要使⽤引号保护起来。
Perl 脚本 'print "@ARGV\n"' 与 Linux 的 echo 的功能⼀样。
$ perl -e 'print "@ARGV\n"' AA
使⽤ GNU Parallel 运⾏这条命令的时候,Perl 命令需要⽤引号包起来,也可以使⽤ -q 保护 Perl 命令。
$ parallel perl -e 'print "@ARGV\n"' ::: This wont work$parallel -q perl -e 'print "@ARGV\n"' ::: This worksThisworks$ parallel perl -e \''print "@ARGV\n"'\' ::: This works, tooThisworks,too
10. 去除空格
使⽤--trim去除参数两头的空格。
$ parallel --trim r echo pre-{}-post ::: ' A 'pre- A-post$ parallel --trim l echo pre-{}-post ::: ' A 'pre-A -post$ parallel --trim lr echo pre-{}-post ::: ' A 'pre-A-post
11. 控制输出
使⽤ --tag 以参数做为输出前缀,使⽤ --tagstring 修改输出前缀。
$ parallel --tag echo foo-{} ::: A B CA foo-AB foo-BC foo-C$ parallel --tagstring {}-bar echo foo-{} ::: A B CA-bar foo-AB-bar foo-BC-bar foo-C
--dryrun 作⽤类似于 echo 。
$ parallel --dryrun echo {} ::: A B Cecho Aecho Becho C$ parallel echo {} ::: A B CABC
--verbose 则在运⾏之前先打印命令。
$ parallel --verbose echo {} ::: A B Cecho Aecho Becho CABC
⼀般来说,GNU Parallel 会延迟输出,直到⼀组命令执⾏完成。使⽤ --ungroup,可⽴刻打印输出已完成部分。
$ parallel -j2 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 12-start2-middle2-end1-start1-middle1-end4-start4-middle4-end$ parallel -j2 --ungroup 'printf "%s-start\n%s" {}
{};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 14-start42-start2-middle2-end1-start1-middle1-end-middle4-end
使⽤ --ungroup 会很快,但会导致输出错乱,⼀个任务的⾏输出可能会被另⼀个任务的输出截断。像上例所⽰,第⼆⾏输出混合了两个任务:'4-middle' '2-start'。使⽤ --linebuffer 避免这个问题(稍慢⼀点)。
4-start2-start2-middle2-end1-start1-middle1-end4-middle4-end
强制使输出与参数保持顺序 --keep-order/-k。
$ parallel -j2 -k 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 14-start4-middle4-end2-start2-middle2-end1-start1-middle1-end
12. 将输出保存到⽂件
GNU Parallel 可以把每⼀个任务的输出保存到⽂件中,临时⽂件默认保存在 /tmp 中,可以使⽤ --tmpdir 改变(或者修改 $TMPDIR)。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论