深酒とお昼寝で忘れる

深酒とお昼寝で忘れる

素面でも意図したことを忘れがちなしらふいとさんは、忘れる前に何かしら書き残せたらとても満足のようです

GNU Parallel という名の簡易ジョブスケジューラ

世間ではジョブスケジューラと聞くと具体的に何を思い浮かべる人が多いんでしょう。(HT)Condor や Torque のような共有計算機におけるジョブスケジューラや、Mesos、Omega や Borg のようなクラウド上の大規模クラスタスケジューラ?シンプルに OS のプロセス(タスク)スケジューラや、はたまた cron だったり、しますかね?いや、きっとジョブスケジューラなんて単語は聞いたことがない人がほとんどなんでしょう……。はい。今日は手元にある計算機の CPU リソースを存分に使いたおしつつ、たくさんのジョブをバッチ的にスケジューリングしたいときに役立つ GNU Parallel (以下 Parallel)の紹介をします。

Parallel は複数のジョブ(コマンドやスクリプト)を複数の CPU コアで並列に実行しくれるツールで、実は(あまり知られていない気がしますが)簡易ジョブスケジューラとして使うことができます。本家 manEXAMPLE: GNU Parallel as queue system/batch manager というところに簡単な例が書いてあって、いきなりですがこんなコマンドを実行します。

$ true > jobqueue; tail -n+0 -f jobqueue | parallel

jobqueue というファイルが実行するコマンドのキューになります。Parallel はファイルを読み終わったら終了してしまうので、tail -f をパイプに流し続けることで実行しっぱなしにします(-n+0 はなくても同じだと思うけど man に書いてあるとおりにしときます)。この状態で、jobqueue ファイルに実行したいコマンドをどんどん追記していきます。

$ echo "my_great_program"                 >> ./jobqueue
$ echo "my_great_program_with_args a b c" >> ./jobqueue
$ echo "bash my_great_shell_script.sh"    >> ./jobqueue
   :

そうすると jobqueue に実行するジョブが書き込まれる度に Parallel が空いてる CPU コアで実行してくれます。空いているコアがない場合は実行を待ってくれるので、キューには好きなだけジョブを書き込んで大丈夫です。便利ですね。

手元では 4 コアのマシンを使っていてそのうち 2 コアだけを処理に使いたい、てなこともあるでしょう。その場合は Parallel に -j+N オプションを渡すことで使う CPU コア数(N)が指定できます。

$ true > ./jobqueue; tail -n+0 -f ./jobqueue | parallel -j+2

デフォルトでは(たぶん)システムが搭載している数の CPU コア($ parallel --number-of-cores)が全部使われる気がします。

これだけでも結構使いどころはある気がしますが、もう少し。ローカルのマシンに加えて ssh 接続できるマシンが何台かあって、それらも使いたいとします。ローカルのマシン名を local_machine、ssh 接続するリモートのマシン名を remote_machine_alpha、remote_machine_beta とします(注意点として、各マシンはパスワードなしで ssh 接続ができる必要があります)。この場合、下記のようなファイルを用意します。ファイル名は my_machines としましょう。

2/local_machine
4/remote_machine_alpha
8/remote_machine_beta

2、4、8 というのはそれぞれのマシンで使用したい CPU コア数です。Parallel は下記のように --sshloginfile オプションを用い上記ファイルを指定して起動します。

$ true > jobqueue; tail -n+0 -f jobqueue | parallel --sshloginfile my_machines

このようにすることで、合計 14(2+4+8)の CPU コアをフルに使ってジョブを並列に実行することができます。どのジョブをどのマシンで実行すれば良いかといった面倒くさい処理は全部 Parallel がよきに計らってくれるわけです。とっても便利ですね!