Linux下的并行神器——parallel

GNU Parallel是一個shell工具顾瞪,為了在一臺或多臺計算機上并行的執(zhí)行計算任務。本文簡要介紹GNU Parallel的使用抛蚁。

1陈醒、parallel 用法簡介

Usage:

parallel [options] [command [arguments]] < list_of_arguments
parallel [options] [command [arguments]] (::: arguments|:::: argfile(s))...
cat ... | parallel --pipe [options] [command [arguments]]

常用選項:
::: 后面接參數(shù)
:::: 后面接文件
-j、--jobs   并行任務數(shù)
-N  每次輸入的參數(shù)數(shù)量
--xargs會在一行中輸入盡可能多的參數(shù)
-xapply 從每一個源獲取一個參數(shù)(或文件一行)
--header  把每一行輸入中的第一個值做為參數(shù)名
-m   表示每個job不重復輸出“背景”(context)
-X   與-m相反瞧甩,會重復輸出“背景文本”
-q  保護后面的命令
--trim  lr 去除參數(shù)兩頭的空格钉跷,只能去除空格,換行符和tab都不能去除
--keep-order/-k   強制使輸出與參數(shù)保持順序 --keep-order/-k
--tmpdir/ --results   都是保存文件肚逸,但是后者可以有結構的保存
--delay  延遲每個任務啟動時間
--halt  終止任務
--pipe    該參數(shù)使得我們可以將輸入(stdin)分為多塊(block)
--block  參數(shù)可以指定每塊的大小
1.1 輸入源

GNU Parallel的輸入源支持文件爷辙、命令行和標準輸入(stdin或pipe)。

# 命令行單輸入源
[20:41 sxuan@hulab ~]$ parallel echo ::: a b c d e | tee a.txt
a
b
c
d
e
# stdin(標準輸入)作為輸入源
[20:42 sxuan@hulab ~]$ cat a.txt | parallel echo
a
b
c
d
e
# GNU Parallel支持通過命令行指定多個輸入源朦促,它會生成所有的組合膝晾。這在某些需要組合時非常好用
[20:45 sxuan@hulab ~]$ parallel echo ::: A B C ::: D E F | tee b.txt
A D
A E
A F
B D
B E
B F
C D
C E
C F
# 多個文件作為輸入,此時多個文件中的內容也會像上面那樣進行組合
[20:46 sxuan@hulab ~]$ parallel -a a.txt -a b.txt echo
# stdin(標準輸入)作為文件源中的一個务冕,使用 -血当, 輸出結果同上
[20:52 sxuan@hulab ~]$ cat a.txt |parallel -a - -a b.txt echo
# 可以使用::::代替-a,后面可接多個文件名
[20:55 sxuan@hulab ~]$ cat a.txt | parallel echo :::: - b.txt
# 最后禀忆,:::和::::可以同時使用臊旭,同樣的輸出結果也會進行組合
[20:55 sxuan@hulab ~]$ parallel echo ::: a b :::: b.txt 

當然,若不想像上面那樣進行組合油湖,可使用--xapply參數(shù)從每一個源獲取一個參數(shù)(或文件一行)巍扛,這個參數(shù)有些類似R中的函數(shù),具有廣播作用——如果其中一個輸入源的長度比較短乏德,它的值會被重復撤奸。

[20:57 sxuan@hulab ~]$ parallel --xapply echo ::: A B C ::: D E F
A D
B E
C F
[21:04 sxuan@hulab ~]$ parallel --xapply echo ::: A B C ::: D E F G H I
A D
B E
C F
A G
B H
C I
1.2 改變參數(shù)分隔符

GNU Parallel可以通過--arg-sep--arg-file-sep指定分隔符替代 ::: 或 ::::,當這兩個符號被其它命令占用的時候會特別有用喊括。

[21:18 sxuan@hulab ~]$ parallel -k --arg-sep ,,, echo ,,, a b ,,, c d | tee c.txt 
a c
a d
b c
b d
[21:22 sxuan@hulab ~]$ parallel --xapply --arg-file-sep ,,,, echo ,,,, a.txt  b.txt 
a A D
b A E
c A F
d B D
e B E
a B F
b C D
c C E
d C F
1.3 改變輸入分隔符

GNU Parallel默認把一行做為一個參數(shù):使用 \n 做為參數(shù)定界符胧瓜。可以使用 -d 改變:

[21:25 sxuan@hulab ~]$ parallel -d b echo :::: a.txt 
a

c
d
e
1.4 提前結束和跳過空行

GNU Parallel支持通過-E參數(shù)指定一個值做為結束標志:

[21:26 sxuan@hulab ~]$ parallel -E stop echo ::: A B stop C D
A
B

GNU Parallel使用 --no-run-if-empty 來跳過空行:

[21:28 sxuan@hulab ~]$ (echo 1; echo; echo 2) | parallel --no-run-if-empty echo
1
2
1.5 構建命令行

如果parallel之后沒有給定命令郑什,那么這些參數(shù)會被當做命令:

[21:29 sxuan@hulab ~]$ parallel ::: ls 'echo foo' pwd
a.txt
b.txt
c.txt
jianchen
mypipe
scripts
snake_test
WGS_snake
foo
/home/sxuan

此外府喳,命令還可以是一個腳本文件,一個二進制可執(zhí)行文件或一個bash的函數(shù)(須用 export -f 導出函數(shù))

[21:42 sxuan@hulab ~]$ echo "echo \$*" > s.sh
[21:44 sxuan@hulab ~]$ parallel ./s.sh ::: "a b c f" "1 2 3 4"
a b c f
1 2 3 4
1.6 替換字符串

GNU Parallel支持多種替換字符串蘑拯,默認使用 {}钝满,使用 -I 改變替換字符串符號 {}兜粘。其最常見的字符串替換包括以下幾種:{.},去掉擴展名弯蚜;{/},去掉路徑孔轴,只保留文件名;{//}碎捺,只保留路徑路鹰;{/.},同時去掉路徑和擴展名收厨;{#}晋柱,輸出任務編號。同時對于每一個字符串替換都可以自己指定符號:-I對應{}诵叁;--extensionreplace替換 {.}雁竞;--basenamereplace替換 {/}--dirnamereplace替換{//}黎休;--basenameextensionreplace替換 {/.}浓领;--seqreplace替換 {#}

[22:02 sxuan@hulab ~]$ parallel echo ::: A/B.C ; parallel echo {} ::: A/B.C ; parallel -I ,, echo ,, ::: A/B.C
A/B.C
A/B.C
A/B.C
[22:04 sxuan@hulab ~]$ parallel echo {.} ::: A/B.C ; parallel --extensionreplace ,, echo ,, ::: A/B.C
A/B
A/B
[22:08 sxuan@hulab ~]$ parallel echo {/} ::: A/B.C ; parallel --basenamereplace ,, echo ,, ::: A/B.C
B.C
B.C
[22:08 sxuan@hulab ~]$ parallel echo {//} ::: A/B.C ; parallel --dirnamereplace ,, echo ,, ::: A/B.C 
A
A
[22:10 sxuan@hulab ~]$ parallel echo {/.} ::: A/B.C ; parallel --basenameextensionreplace ,, echo ,, ::: A/B.C
B
B
[22:13 sxuan@hulab ~]$ parallel echo {#} ::: A B C ; parallel --seqreplace ,, echo ,, ::: A B C
1
2
3
1
2
3

同時势腮,如果有多個輸入源時,可以通過 {編號} 指定某一個輸入源的參數(shù):

[22:14 sxuan@hulab ~]$ parallel --xapply  echo {1} and {2} ::: A B ::: C D
A and C
B and D
# 可以使用 / // /. 和 . 改變指定替換字符串
[22:14 sxuan@hulab ~]$ parallel echo /={1/} //={1//} /.={1/.} .={1.} ::: A/B.C D/E.F
/=B.C //=A /.=B .=A/B
/=E.F //=D /.=E .=D/E
# 位置可以是負數(shù)漫仆,表示倒著數(shù)
[22:16 sxuan@hulab ~]$ parallel echo 1={1} 2={2} 3={3} -1={-1} -2={-2} -3={-3} ::: A B ::: C D ::: E F
1=A 2=C 3=E -1=E -2=C -3=A
1=A 2=C 3=F -1=F -2=C -3=A
1=A 2=D 3=E -1=E -2=D -3=A
1=A 2=D 3=F -1=F -2=D -3=A
1=B 2=C 3=E -1=E -2=C -3=B
1=B 2=C 3=F -1=F -2=C -3=B
1=B 2=D 3=E -1=E -2=D -3=B
1=B 2=D 3=F -1=F -2=D -3=B
1.7 按列輸入和指定參數(shù)名

使用 --header 把每一行輸入中的第一個值做為參數(shù)名捎拯。

[22:17 sxuan@hulab ~]$ parallel --xapply --header : echo f1={f1} f2={f2} ::: f1 A B ::: f2 C D | tee d.txt
f1=A f2=C
f1=B f2=D

使用 --colsep 把文件中的行切分為列,做為輸入?yún)?shù)盲厌。

[22:31 sxuan@hulab ~]$ perl -e 'printf "f1\tf2\nA\tB\nC\tD\n"' > tsv-file.tsv
[22:32 sxuan@hulab ~]$ parallel --header : --colsep '\t' echo f1={f1} f2={f2} :::: tsv-file.tsv 
f1=A f2=B
f1=C f2=D
1.8 多參數(shù)

--xargs會在一行中輸入盡可能多的參數(shù)(與參數(shù)字符串長度有關)署照,通過-s可指定一行中參數(shù)的上限。

[09:44 sxuan@hulab ~]$ perl -e 'for(1..30000){print "$_\n"}' > num30000
[09:50 sxuan@hulab ~]$ cat num30000 | parallel --xargs echo | wc -l
3
### 這里官網(wǎng)給出的例子是2行吗浩,我的計算機centos7上面的結果是3行建芙,應該跟linux版本有關
[09:50 sxuan@hulab ~]$ cat num30000 | parallel --xargs -s 10000 echo | wc -l
17

為了獲得更好的并發(fā)性,GNU Parallel會在文件讀取結束后再分發(fā)參數(shù)懂扼。
GNU Parallel 在讀取完最后一個參數(shù)之后禁荸,才開始第二個任務,此時會把所有的參數(shù)平均分配到4個任務(如果指定了4個任務)阀湿。
第一個任務與上面使用 --xargs 的例子一樣赶熟,但是第二個任務會被平均的分成4個任務,最終一共5個任務陷嘴。(奇怪的是我的結果與官網(wǎng)教程的結果不一樣)

[11:44 sxuan@hulab ~]$ cat num30000 | parallel --jobs 4 -m echo | wc -l
6    ### 官網(wǎng)教程里這里是5
# 10分參數(shù)分配到4個任務可以看得更清晰 (這里的結果與官網(wǎng)一致)
[11:50 sxuan@hulab ~]$ parallel --jobs 4 -m echo ::: {1..10}
1 2 3
4 5 6
7 8 9
10

替換字符串可以是輸出字符的一部分映砖,使用-m參數(shù)表示每個job不重復輸出“背景”(context),-X則與-m相反灾挨,會重復輸出“背景文本”邑退,具體通過下面幾個例子進行理解:

[11:36 sxuan@hulab ~]$ parallel --jobs 4 echo pre-{}-post ::: A B C D E F G
pre-A-post
pre-B-post
pre-C-post
pre-D-post
pre-E-post
pre-F-post
pre-G-post
[11:51 sxuan@hulab ~]$ parallel --jobs 4 -m echo pre-{}-post ::: A B C D E F G
pre-A B-post
pre-C D-post
pre-E F-post
pre-G-post
[11:57 sxuan@hulab ~]$ parallel --jobs 4 -X echo pre-{}-post ::: A B C D E F G
pre-A-post pre-B-post
pre-C-post pre-D-post
pre-E-post pre-F-post
pre-G-post

使用 -N 限制每行參數(shù)的個數(shù)竹宋,其中-N0表示一次只讀取一個參數(shù),且不輸入這個參數(shù)(作為計數(shù)器來使用)地技。

[12:04 sxuan@hulab ~]$ parallel -N4 echo 1={1} 2={2} 3={3} ::: A B C D E F G H
1=A 2=B 3=C
1=E 2=F 3=G
[12:05 sxuan@hulab ~]$ parallel -N0 echo foo ::: 1 2 3
foo
foo
foo
1.9 引用

如果命令行中包含特殊字符蜈七,就需要使用引號保護起來。
perl腳本 'print "@ARGV\n"' 與linux的 echo 的功能一樣乓土。

[12:05 sxuan@hulab ~]$ perl -e 'print "@ARGV\n"' A
A

使用GNU Parallel運行這條命令的時候宪潮,perl命令需要用引號包起來,也可以使用-q保護perl命令:

[12:08 sxuan@hulab ~]$ parallel perl -e 'print "@ARGV\n"' ::: This wont work
[12:09 sxuan@hulab ~]$ parallel -q perl -e 'print "@ARGV\n"' ::: This works
This
works
[12:10 sxuan@hulab ~]$ parallel perl -e \''print "@ARGV\n"'\' ::: This works, too
This
works,
too
1.10 去除空格

使用--trim去除參數(shù)兩頭的空格:

[12:10 sxuan@hulab ~]$ parallel --trim r echo pre-{}-post ::: ' A '
pre- A-post
[12:12 sxuan@hulab ~]$ parallel --trim l echo pre-{}-post ::: ' A '
pre-A -post
[12:12 sxuan@hulab ~]$ parallel --trim lr echo pre-{}-post ::: ' A '
pre-A-post
1.11 控制輸出

使用--tag以參數(shù)做為輸出前綴趣苏,使用--tagstring修改輸出前綴:

[12:17 sxuan@hulab ~]$ parallel --tag echo foo-{} ::: A B C
A   foo-A
B   foo-B
C   foo-C
[12:19 sxuan@hulab ~]$ parallel --tagstring {}-bar echo foo-{} ::: A B C
A-bar   foo-A
B-bar   foo-B
C-bar   foo-C

--dryrun作用類似于echo:

[12:19 sxuan@hulab ~]$ parallel --dryrun echo {} ::: A B C
echo A
echo B
echo C
[12:20 sxuan@hulab ~]$ parallel echo {} ::: A B C
A
B
C

--verbose則在運行之前先打印命令:

[12:21 sxuan@hulab ~]$ parallel --verbose echo {} ::: A B C
echo A
echo B
echo C
A
B
C

一般來說狡相,GNU Parallel 會延遲輸出,直到一組命令執(zhí)行完成食磕。使用--ungroup尽棕,可立刻打印輸出已完成部分。

[13:45 sxuan@hulab ~]$ parallel -j2 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1
2-start
2-middle
2-end
1-start
1-middle
1-end
4-start
4-middle
4-end
[13:45 sxuan@hulab ~]$ parallel -j2 --ungroup 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1
4-start
42-start
2-middle
2-end
1-start
1-middle
1-end
-middle
4-end

使用 --ungroup 會很快彬伦,但會導致輸出錯亂滔悉,一個任務的行輸出可能會被另一個任務的輸出截斷。像上例所示单绑,第二行輸出混合了兩個任務: '4-middle' '2-start'回官。使用 --linebuffer避免這個問題(稍慢一點):

4-start
2-start
2-middle
2-end
1-start
1-middle
1-end
4-middle
4-end

強制使輸出與參數(shù)保持順序 --keep-order/-k

[13:53 sxuan@hulab ~]$ parallel -j2 -k 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1
4-start
4-middle
4-end
2-start
2-middle
2-end
1-start
1-middle
1-end
1.12 將輸出保存到文件

GNU Parallel可以把每一個任務的輸出保存到文件中,臨時文件默認保存在 /tmp 中搂橙,可以使用 --tmpdir改變(或者修改 $TMPDIR):

[13:55 sxuan@hulab ~]$ parallel --files ::: A B C
/tmp/parfmNTJ.par
/tmp/parmioFz.par
/tmp/pargaTxf.par
[13:57 sxuan@hulab ~]$ parallel --tmpdir ~ --files ::: A B C
/home/sxuan/parLEXH7.par
/home/sxuan/parXsKsR.par
/home/sxuan/parZxytI.par
[13:58 sxuan@hulab ~]$ TMPDIR=~ parallel --files ::: A B C
/home/sxuan/par2tX6C.par
/home/sxuan/parorPJy.par
/home/sxuan/pari5TkI.par

輸出文件可以有結構的保存 --results歉提,輸出文件不僅包含標準輸出(stdout)也會包含標準錯誤輸出(stderr):

[13:59 sxuan@hulab ~]$ parallel --results outdir echo ::: A B C
A
B
C
[14:00 sxuan@hulab ~]$ tree outdir/
outdir/
└── 1
    ├── A
    │   ├── seq
    │   ├── stderr
    │   └── stdout
    ├── B
    │   ├── seq
    │   ├── stderr
    │   └── stdout
    └── C
        ├── seq
        ├── stderr
        └── stdout

4 directories, 9 files

在使用多個變量的時候會顯示很有用:

# --header : will take the first value as name and use that in the directory structure.
[14:02 sxuan@hulab ~]$ parallel --header : --results outdir echo ::: f1 A B ::: f2 C D
A C
A D
B C
B D
[14:02 sxuan@hulab ~]$ tree outdir/
outdir/
└── f1
    ├── A
    │   └── f2
    │       ├── C
    │       │   ├── seq
    │       │   ├── stderr
    │       │   └── stdout
    │       └── D
    │           ├── seq
    │           ├── stderr
    │           └── stdout
    └── B
        └── f2
            ├── C
            │   ├── seq
            │   ├── stderr
            │   └── stdout
            └── D
                ├── seq
                ├── stderr
                └── stdout

9 directories, 12 files
1.13 控制執(zhí)行

使用 --jobs/-j 指定并行任務數(shù)。

# 使用64個任務執(zhí)行128個休眠命令
[15:02 sxuan@hulab ~]$ time parallel -N0 -j64 sleep 1 ::: {1..128}

real    0m2.759s
user    0m0.657s
sys 0m1.345s
# 默認情況下并行任務數(shù)與cpu核心數(shù)相同, 所以這條命令會比每個cpu兩個任務的耗時多一倍
[15:03 sxuan@hulab ~]$ time parallel -N0 sleep 1 ::: {1..128}

real    0m3.478s
user    0m0.656s
sys 0m1.344s
# 每個cpu兩個任務
[15:03 sxuan@hulab ~]$ time parallel -N0 --jobs 200% sleep 1 ::: {1..128}

real    0m2.659s
user    0m0.734s
sys 0m1.423s
# 使用 --jobs 0 表示執(zhí)行盡可能多的并行任務
[15:03 sxuan@hulab ~]$ time parallel -N0 --jobs 0 sleep 1 ::: {1..128}

real    0m2.135s
user    0m0.651s
sys 0m1.477s
# 除了基于cpu使用率之外区转,也可以基于cpu數(shù)
[15:03 sxuan@hulab ~]$ time parallel --use-cpus-instead-of-cores -N0 sleep 1 ::: {1..128}

real    1m5.499s
user    0m0.950s
sys 0m1.897s
1.14 交互

通過使用 --interactive 在一個任務執(zhí)行之前讓用戶決定是否執(zhí)行苔巨。

[15:08 sxuan@hulab ~]$ parallel --interactive echo ::: 1 2 3
echo 1 ?...y
echo 2 ?...y
echo 3 ?...y
1
2
3
1.15 耗時

當job有大量的IO操作時,為避免“驚群效應”废离,可使用--delay參數(shù)指定各個job開始的時間間隔侄泽。

[15:16 sxuan@hulab ~]$ parallel --delay 2.5 echo Starting {}\;date ::: 1 2 3
Starting 1
Tue Apr 17 15:21:41 CST 2018
Starting 2
Tue Apr 17 15:21:44 CST 2018
Starting 3
Tue Apr 17 15:21:46 CST 2018

若已知任務超過一定時間未反應則為失敗則可以通過--timeout指定等待時間避免無謂的等待。GNU parallel能計算所有任務運行時間的中位數(shù)蜻韭,因此可以指定時間為中位數(shù)的倍數(shù)關系悼尾。

[15:35 sxuan@hulab ~]$ parallel --timeout 4.1 sleep {}\; echo {} ::: 2 4 6 8
2
4
[15:36 sxuan@hulab ~]$ parallel --timeout 200% sleep {}\; echo {} ::: 2.1 2.2 3 7 2.3
2.1
2.2
2.3
3
1.16 顯示任務進度信息

GNU parallel有多種方式可用來動態(tài)的顯示任務進度信息,如:

parallel --eta sleep ::: 1 3 2 2 1 3 3 2 1
parallel --progress sleep ::: 1 3 2 2 1 3 3 2 1
seq 1000 | parallel -j10 --bar '(echo -n {};sleep 0.1)'  2> >(zenity --progress --auto-kill --auto-close)

使用--joblog參數(shù)能夠生成各個任務的日志文件:

[15:39 sxuan@hulab ~]$ parallel --joblog /tmp/log exit  ::: 1 2 3 0
[15:41 sxuan@hulab ~]$ cat /tmp/log 
Seq Host    Starttime   JobRuntime  Send    Receive Exitval Signal  Command
1   :   1523950890.344       0.018  0   0   1   0   exit 1
2   :   1523950890.350       0.014  0   0   2   0   exit 2
3   :   1523950890.357       0.006  0   0   3   0   exit 3
4   :   1523950890.363       0.006  0   0   0   0   exit 0

通過--resume-failed參數(shù)可以重新運行失敗的任務; --retry-failed的作用與--resume-failed類似湘捎,只是--resume-failed從命令行讀取失敗任務诀豁,而--retry-failed則是從日志文件中讀取失敗任務:

[15:41 sxuan@hulab ~]$ parallel --resume-failed --joblog /tmp/log exit  ::: 1 2 3 0 0 0
[15:48 sxuan@hulab ~]$ cat /tmp/log
Seq Host    Starttime   JobRuntime  Send    Receive Exitval Signal  Command
1   :   1523950890.344       0.018  0   0   1   0   exit 1
2   :   1523950890.350       0.014  0   0   2   0   exit 2
3   :   1523950890.357       0.006  0   0   3   0   exit 3
4   :   1523950890.363       0.006  0   0   0   0   exit 0
1   :   1523951289.575       0.029  0   0   1   0   exit 1
2   :   1523951289.580       0.025  0   0   2   0   exit 2
3   :   1523951289.585       0.019  0   0   3   0   exit 3
5   :   1523951289.591       0.013  0   0   0   0   exit 0
6   :   1523951289.604       0.004  0   0   0   0   exit 0
[15:48 sxuan@hulab ~]$ parallel --retry-failed --joblog /tmp/log
[15:50 sxuan@hulab ~]$ cat /tmp/log
Seq Host    Starttime   JobRuntime  Send    Receive Exitval Signal  Command
1   :   1523950890.344       0.018  0   0   1   0   exit 1
2   :   1523950890.350       0.014  0   0   2   0   exit 2
3   :   1523950890.357       0.006  0   0   3   0   exit 3
4   :   1523950890.363       0.006  0   0   0   0   exit 0
1   :   1523951289.575       0.029  0   0   1   0   exit 1
2   :   1523951289.580       0.025  0   0   2   0   exit 2
3   :   1523951289.585       0.019  0   0   3   0   exit 3
5   :   1523951289.591       0.013  0   0   0   0   exit 0
6   :   1523951289.604       0.004  0   0   0   0   exit 0
1   :   1523951445.089       0.013  0   0   1   0   exit 1
2   :   1523951445.094       0.009  0   0   2   0   exit 2
3   :   1523951445.102       0.007  0   0   3   0   exit 3
1.17 終止任務

GNU parallel支持在某一情況下(如第一個失敗或成功時,或者20%任務失敗時)終止任務窥妇,終止任務又有兩種類型舷胜,其一為立即終止(通過--halt now指定),殺死所有正在運行的任務并停止生成新的任務,其二為稍后終止(通過--halt soon指定)烹骨,停止生成新任務并等待正在運行任務完成翻伺。

[15:50 sxuan@hulab ~]$ parallel -j2 --halt soon,fail=1 echo {}\; exit {} ::: 0 0 1 2 3
0
0
1
parallel: This job failed:
echo 1; exit 1
parallel: Starting no more jobs. Waiting for 1 jobs to finish.
2
parallel: This job failed:
echo 2; exit 2
[16:04 sxuan@hulab ~]$ parallel -j2 --halt now,fail=1 echo {}\; exit {} ::: 0 0 1 2 3
0
0
1
parallel: This job failed:
echo 1; exit 1
[16:05 sxuan@hulab ~]$ parallel -j2 --halt soon,fail=20% echo {}\; exit {} ::: 0 1 2 3 4 5 6 7 8 9
0
1
parallel: This job failed:
echo 1; exit 1
2
parallel: This job failed:
echo 2; exit 2
parallel: Starting no more jobs. Waiting for 1 jobs to finish.
3
parallel: This job failed:
echo 3; exit 3
[16:05 sxuan@hulab ~]$ parallel -j2 --halt now,success=1 echo {}\; exit {} ::: 1 2 3 0 4 5 6
1
2
3
0
parallel: This job succeeded:
echo 0; exit 0

GNU parallel還支持在任務失敗后重試運行--retries:

[16:06 sxuan@hulab ~]$ parallel -k --retries 3 'echo tried {} >>/tmp/runs; echo completed {}; exit {}' ::: 1 2 0
completed 1
completed 2
completed 0
[16:09 sxuan@hulab ~]$ cat /tmp/runs 
tried 1
tried 2
tried 0
tried 1
tried 2
tried 1
tried 2

關于終止信號的高級用法參考官方入門文檔

1.18 資源限制

GNU parallel能夠在開始一個新的任務前檢查系統(tǒng)的負載情況防止過載(通過--load可指定負載)沮焕,同時還能檢查系統(tǒng)是否使用了交換空間(swap)(通過--noswap限制使用swap)吨岭。

[16:09 sxuan@hulab ~]$ parallel --load 100% echo load is less than {} job per cpu ::: 1
load is less than 1 job per cpu
[16:19 sxuan@hulab ~]$ parallel --noswap echo the system is not swapping ::: now
the system is not swapping now

同時,對于某些占用內存較多的程序峦树,parallel會檢查內存只有內存滿足時才啟動任務(通過--memfree指定需要內存大欣北琛),而且在啟動任務后內存不夠50%時會殺掉最新開始的任務魁巩,直到這個任務完成再重新開始那些殺死的任務急灭。

[16:24 sxuan@hulab ~]$ parallel --memfree 1G echo will run if more than 1 GB is ::: free
will run if more than 1 GB is free

還可以通過--nice來指定任務的優(yōu)先級。

[16:27 sxuan@hulab ~]$ parallel --nice 17 echo this is being run with nice -n ::: 17
this is being run with nice -n 17
1.19 遠程操作

可使用-S host來進行遠程登陸:
parallel -S username@$SERVER1 echo running on ::: username@$SERVER1

1.20 文件傳輸

GNU parallel 文件傳輸使用的是rsync谷遂。

echo This is input_file > input_file
parallel -S $SERVER1 --transferfile {} cat ::: input_file

更多遠程操作參見入門文檔葬馋。

1.21 --pipe

--pipe參數(shù)使得我們可以將輸入(stdin)分為多塊(block),然后分配給多個任務多個cpu以達到負載均衡肾扰,最后的結果順序與原始順序一致畴嘶。使用--block參數(shù)可以指定每塊的大小,默認為1M集晚。

[17:15 sxuan@hulab ~]$ perl -e 'for(1..1000000){print "$_\n"}' > num1000000
[17:16 sxuan@hulab ~]$ cat num1000000 | parallel --pipe wc
 165668  165668 1048571
 149796  149796 1048572
 149796  149796 1048572
 149796  149796 1048572
 149796  149796 1048572
 149796  149796 1048572
  85352   85352  597465

如果不關心結果順序窗悯,只想要快速的得到結果,可使用--round-robin參數(shù)偷拔。沒有這個參數(shù)時每塊文件都會啟動一個命令桑包,使用這個參數(shù)后會將這些文件塊分配給job數(shù)任務(通過--jobs進行指定)钢猛。若想分配更為均勻還可同時指定--block參數(shù)砖第。

[17:17 sxuan@hulab ~]$ cat num1000000 | parallel --pipe -j4 --round-robin wc
 299592  299592 2097144
 315464  315464 2097143
 149796  149796 1048572
 235148  235148 1646037
[17:23 sxuan@hulab ~]$ cat num1000000 | parallel --pipe -j4 --block 2M --round-robin wc
 299593  299593 2097151
 315465  315465 2097150
 299593  299593 2097151
  85349   85349  597444

參考:
官方文檔
GNU Parallel指南

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末毯侦,一起剝皮案震驚了整個濱河市澎嚣,隨后出現(xiàn)的幾起案子院溺,更是在濱河造成了極大的恐慌浓利,老刑警劉巖型将,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彻坛,死亡現(xiàn)場離奇詭異顷啼,居然都是意外死亡,警方通過查閱死者的電腦和手機昌屉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門钙蒙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人间驮,你說我怎么就攤上這事躬厌。” “怎么了竞帽?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵扛施,是天一觀的道長鸿捧。 經常有香客問我,道長疙渣,這世上最難降的妖魔是什么匙奴? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮妄荔,結果婚禮上泼菌,老公的妹妹穿的比我還像新娘。我一直安慰自己啦租,他們只是感情好哗伯,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刷钢,像睡著了一般笋颤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上内地,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天伴澄,我揣著相機與錄音,去河邊找鬼阱缓。 笑死非凌,一個胖子當著我的面吹牛,可吹牛的內容都是我干的荆针。 我是一名探鬼主播敞嗡,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼航背!你這毒婦竟也來了喉悴?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤玖媚,失蹤者是張志新(化名)和其女友劉穎箕肃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體今魔,經...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡勺像,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了错森。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吟宦。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖涩维,靈堂內的尸體忽然破棺而出殃姓,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布辰狡,位于F島的核電站锋叨,受9級特大地震影響,放射性物質發(fā)生泄漏宛篇。R本人自食惡果不足惜娃磺,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望叫倍。 院中可真熱鬧偷卧,春花似錦、人聲如沸吆倦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚕泽。三九已至晌梨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間须妻,已是汗流浹背仔蝌。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荒吏,地道東北人敛惊。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像绰更,于是被迫代替她去往敵國和親瞧挤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內容