プログラムを並列処理する GNU Parallel 作者の Ole Tange が YouTube で GNU Parallel の初心者向けチュートリアル(スクリーンキャスト)を2本(ともに10分)公開していたので内容をざっとメモ。
GNU Parallel はコマンドラインツールなので、コマンドを実行しながらひたすらしゃべって解説しているだけ。
スクリーンキャストといっても、Web フレームワークのような華やかさは全くない。
Part 1: GNU Parallel script processing and execution
GNU PARALLEL – BASIC USAGE
GET GNU PARALLEL
ダウンロードとインストール
YOUR FIRST PARALLEL JOBS
合計1GB の大量のログファイルを圧縮&解凍
$ /usr/bin/time gzip -l * $ /usr/bin/time gunzip *
GNU Parallel を使うと、デュアルコア CPUx1 の環境では CPU 使用率は2倍になり、処理時間は 1/2 になる。
$ ls | time parallel gzip -l $ ls | time parallel gunzip
gzip に -l(–list) オプションをつけると、以下の情報も表示される。
- compressed size: size of the compressed file
- uncompressed size: size of the uncompressed file
- ratio: compression ratio (0.0% if unknown)
- uncompressed_name: name of the uncompressed file
RECOMPRESS GZ TO BZ2
ファイルの圧縮形式を GZ から BZ2 に変更
$ ls *.gz | time parallel -j+0 --eta 'zcat {} | bzip2 -9 >{.}.bz2'
-j+0 オプションは run as many jobs
–eta オプションは Show the estimated number of seconds before finishing. estimate は rough guess で not very accurate.
bzip2 -9(–best) オプションは Get the best possible compression, although it will take longer. 反対は -1(–fast)
RECOMPRESS GZ TO BZ2 USING LOCAL(:)AND REMOTE SERVER1-4
ローカルマシンだけでなく、リモートマシンも活用してジョブを実行。基本的に ssh でコマンド実行しているだけ。
$ ls *.gz | time parallel -j+0 --eta -Sserver1,server2,server3,server4,: --transfer --return {.}.bz2 --cleanup 'zcat {} | bzip2 -9 >{.}.bz2'
gz から bz2 への変換を -S で指定した各マシンで実行。「:」はローカルマシンを表す。
RECOMPRESS GZ TO BZ2 USING A SCRIPT ON LOCAL AND REMOVE SERVER1-2,4
- 処理の遅いserver3を省く
- gz から bz2 への変換処理はベタでコマンドを書かずに、シェルスクリプトの /tmp/recompress プログラムに集約。
$ ls *.gz | time parallel -j+0 --progress -Sserver1,server2,server4,: --trc {.}.bz2 --basefile /tmp/recompress '/tmp/recompress {} {.}.bz2'
–progress オプションは Show progress of computations.
–trc オプションは transfer & return & cleanup のショートカット(アクロニム)
Part 2: GNU Parallel script processing and execution
MAKING SMALL SCRIPTS
$ ls *.zip | parallel 'mkdir {.} && cd {.} && unzip ../{}'
ワーキングディレクトリにある zip ファイルを個別のディレクトリに展開。
GROUP OUTPUT
Parallel を使うと、並列実行するジョブの出力を混在させずに表示させられる。
$ traceroute debian.org & traceroute freenetproject.org $ (echo debian.org; echo freenetproject.org) | parallel traceroute
KEEP ORDER
$ (echo debian.org; echo freenetproject.org) | parallel -k traceroute
並列実行したジョブを実行が終わった順ではなく、引数の順に表示させるには -k オプションを利用。
RUN MANY JOBS. USE OUTPUT
FIND THE NUMBER OF HOSTS RESPONDING TO PING
$ ping -c 1 178.63.11.1 $ ping -c 1 178.63.11.1 | grep '64 bytes'
PING コマンドを一回送信し、通信結果を元に PING が通るかチェック。
$ seq 1 255 | parallel -j255 ping -c 1 178.63.11.{} 2>&1 > | grep '64 bytes' | wc -l
Parallel を使って、ポートスキャンのように一定の範囲内のIPに対して高速に PING を実行
MULTIPLE ARGUMENTS
MAKE DIR: TEST-(1-5000).DIR
$ seq 1 10 | parallel echo mkdir test-{}.dir mkdir test-1.dir ... mkdir test-10.dir
echo されるディレクトリを作成
$ seq 1 5000 | time parallel mkdir test-{}.dir
echo 結果からわかるように 5000 回 mkdir を spawn しないといけないので spawn のオーバーヘッドが大きい。
$ seq 1 10 | parallel -X echo mkdir test-{}.dir mkdir test-1.dir ... test-10.dir
作成するディレクトリ名は引数でまとめて渡し、spawn 1回で済ませてオーバーヘッドを減らすと高速に処理できる。
$ seq 1 5000 | time parallel -X mkdir test-{}.dir
CALLING GNU PARALLEL FROM GNU PARALLEL
MAKE DIR: TOP-(1-100)/SUB-(1-100)
$ seq 1 100 | time parallel -I @@ > 'mkdir top-@@; seq 1 100 | parallel -X mkdir top-@@/sub-{}'
-I @@ はデフォルトの {} の代わりに @@ で置換を行う(The replacement string {} can be changed with -I.)
xargs の -P オプション
YouTube のコメント欄から。
xargs には -P オプションがあり、 spawn するプロセス数を制御できる。
xargs -P 0 には特別な意味があり、parallel -j0 と同じくコア数分だけ spawn される。
-P max-procs
Run simultaneously up to max-procs processes at once; the default is 1. If max-procs is 0, xargs will run as many processes as possible simultaneously.
http://www.gnu.org/software/findutils/manual/html_node/find_html/xargs-options.html#xargs-options
References
- Documentation for GNU Parallel
http://www.gnu.org/software/parallel/man.html - [YouTube]Part 1: GNU Parallel script processing and execution
http://www.youtube.com/watch?v=OpaiGYxkSuQ - [YouTube]Part 2: GNU Parallel script processing and execution
http://www.youtube.com/watch?v=P40akGWJ_gY