Prog-G

岐阜大学プログラミングサークル

複数プロセスを立てての並列処理にxargsコマンドが便利

Shell

並列処理が便利です。 例えば、なにか大量のファイルを HTTP でダウンロードするとき8個のプロセスで並列作業すれば1つのプロセスで直列作業するよりも圧倒的爆速になります(ただしアーキテクチャにもよる)。

ただしプログラム自体を並列に書き直すのはめんどくさいときがあります。 シェルの xargs コマンドを使うといい感じにプロセスを回して並列処理を実現してくれるので紹介します(GNU 版 xargs で検証しています)。

xargs コマンドとは

標準入力からコマンドライン引数を与えるコマンドです。

例えば xargs ls と打ったあとに、標準入力から -A と打ち込む(終わったら Return して Ctrl+D)のは ls -A を実行するのと同じになります。 標準入力から複数行にわたる入力をした場合は改行も引数の区切りとみなされます。

-L オプション

このオプションは一度に与える引数の数を制限します。 このオプションをつけなかった場合、シェルが与えられる最大値までコマンドライン引数を一度に与えてしまいます。 どういうことかというと seq 1 10 | xargs echoecho 1 2 3 4 5 6 7 8 9 10 と同じになります。 単一の引数しかとらないプログラムではこれは困ります。

そこで -L オプションをつけて一度に与える引数の数を制限します。 例えば seq 1 10 | xargs -L 3 echo は echo 1 2 3; echo 4 5 6; echo 7 8 9; echo 10 と等価です。 つまり入り切らなかった引数は別のプログラム実行に渡されて逐次処理されます。

-P オプション

このオプションを使うと一度に複数のプロセスを立てることを許可します。 デフォルトではこのオプション値は 1 になっているので直列の逐次処理になっていました。 -P 8 と与えてやると xargs は最大で 8 個のプロセスが起動しているように、うまいこと仕事を回してくれます。

事例

連番の Zip がサーバーに置かれていて、番号を与えると対応する Zip をダウンロードする Python スクリプトがあったとします。 1〜100 の Zip を 8 並列でダウンロードするコマンドはこのような入力になります。

seq 1 100 | xargs -P 8 -L 1 python download.py