スクリーンキャストで学ぶGNU Parallel

プログラムを並列処理する 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

Leave a comment