実行環境
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で実行(上から順に実行される)
$ 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
ということもしてみた。こちらのほうが高機能そう。