Edited at

シェルスクリプトで単純に並列実行・直列実行を行う

More than 1 year has passed since last update.


実行環境

MacのBash

$ bash --version

GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc.


単純な直列実行

$ sleep 2

$ sleep 4
$ sleep 1
$ sleep 4 # 合計で2+4+1+4=11秒かかる


バックグラウンドプロセスを用いた単純な並列実行

$ sleep 2 & # コマンド末尾に&をつけて呼び出すとバックグラウンドプロセスになり、並列で実行される

$ sleep 4 &
$ sleep 1 &
$ sleep 4 &
$ wait # 上記のバックグラウンドプロセスたちを待機。もっともかかるもので4秒なため、合計で4秒かかる
[1] 38498
[2] 38499
[3] 38500
[4] 38501
[3] - 38500 done sleep 1 # 1秒後([1]のプロセスより先に終了)
[1] 38498 done sleep 2 # 2秒後
[4] + 38501 done sleep 4 # 4秒後([2]のプロセスとほぼ同時に終了)
[2] + 38499 done sleep 4 # 4秒後([4]のプロセスとほぼ同時に終了)


バックグラウンドプロセスを用いて直列実行がしたい場合

echo "hogehoge.shを実行します"

./hogehoge.sh & # バックグラウンドプロセスとして起動
wait $! # $!で直前のバックグラウンドのプロセスIDが得られるため、それが終わるまで待機
echo $? # hogehoge.shの終了ステータス
echo "fugafuga.shを実行します"
./fugafuga.sh & # hogehoge.shが終了してから実行されるバックグラウンドプロセス
wait $!
echo $? # fugafuga.shの終了ステータス

そもそもバックグラウンドプロセスにしている時点で直列実行する必要がないだろうが、上記のようにプロセスIDを$!で取得し指定すれば可能


xargsを用いた並列実行

xargsに-P (--max-procs)というオプションがあって、それで指定してやれば指定のプロセス数まで並列実行してくれます。

xargs -P (並列プロセス数) (実行したいコマンド)だけなので簡単。

参照: xargs を使ってカジュアルに並列処理


普通にxargsで実行(上から順に実行される)

$ time seq 1 5 | xargs -I ZZ -P 1 sleep 1

seq 1 5 0.00s user 0.00s system 49% cpu 0.006 total
xargs -I ZZ -P 1 sleep 1 0.01s user 0.01s system 0% cpu 5.034 total # 5.034秒かかった

1秒かかるプロセスを5つ実行すると5秒かかる


並列実行(-P 5 で5プロセスまでの並列実行)

$ time seq 1 5 | xargs -I ZZ -P 5 sleep 1

seq 1 5 0.00s user 0.00s system 60% cpu 0.009 total
xargs -I ZZ -P 5 sleep 1 0.01s user 0.01s system 1% cpu 1.015 total # 1.015秒かかった

5プロセスまで並行実行する設定で

1秒かかるプロセスを5つ実行すると1秒かかる

$ time seq 1 7 | xargs -I ZZ -P 5 sleep 1

seq 1 7 0.00s user 0.00s system 65% cpu 0.006 total
xargs -I ZZ -P 5 sleep 1 0.01s user 0.02s system 1% cpu 2.032 total # 2.032秒かかった

5プロセスまで並行実行する設定で

1秒かかるプロセスを7つ実行すると2秒かかる


他の手法

GNU Parallelというものもあるらしい。とりあえず brew install parallel でインストールすることが出来た。

xargsの例を真似て

time seq 1 100 | parallel -j 100%  sleep 1

ということもしてみた。こちらのほうが高機能そう。

参照: GNU Parallelがすごすぎて生きるのがつらい