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指南