コア数が多いマシンが手に入ったのでslurmで計算クラスターにする
slurmはオープンソースのジョブスケジューラーだ。
これは何かというと、例えば、俺は今から1000種類の条件でシミュレーションを投げるぞ! ウオオ という時に、サーバーにログインして、シェルのfor文で1000個のバッチスクリプトを登録し、そのままログアウトして家で寝ていると勝手に順次実行されていくという便利ソフトウェアだ。
普通こういうのはサーバーラックに挿す系の大型クラスターとか、複数台のデスクトップマシンをネットワークで繋いだものとかで色々大変な設定をして使うものだが、今回は全てが面倒に感じたので(あと手元にコントロールノードに使えそうないい感じのマシンがなかったので)、1台をコントロールノードかつ計算ノードとして完結させることにした。共有ストレージとか必要なくなる(自明に共有されている)ので多分色々楽。
それくらいの気持ちなので割と適当にやっていきます。OSはUbuntu 18.04。やりながら書いてるわけではない(history見て要約して書いてる)ので、何か必須手順忘れてるかも。その時は頑張って下さい。
まず、slurmのコントロールノード用デーモンslurmctldと計算ノード用デーモンslurmdをaptで入れる。Ubuntu 18で入るやつは17.11.2でちょっと古い(これを書いている時点で最新版は20.02.0)が見なかったことにする。
$ sudo apt install slurmctld slurmd
最新版を使いたい場合は本家からダウンロードする。
aptを使えば依存関係はもちろんslurmユーザーの登録とsystemctlへのserviceファイルの配置まで済んでいるので楽。あと必要なのはクラスターの構成を書くためのslurm.confだ。
これを簡単に作るためのインターフェースがhtmlファイルとして提供されているので、これを開いて適当に書いていく。CPUとかメモリはあるだけ書く。コントロールノードと計算ノードのIPと名前を同じにしておく。Resource SelectionをCons_resにして、あとは全部デフォルト。
$ firefox /usr/share/doc/slurmctld/slurm-wlm-configurator.easy.html
出てきたファイル(slurm.conf)を/etc/slurm-llnlにコピーして、所有者をslurm:slurmにする。
$ sudo cp slurm.conf /etc/slurm-llnl $ sudo chown slurm:slurm /etc/slurm-llnl/slurm.conf
多分これで大丈夫なので、必要なやつを全部systemctlに立ち上げてもらうために再起動。手動でsystemctlからやったほうが良いのかも知れないけど面倒だったので再起動した。
再起動したら、slurmdとslurmctldがちゃんと動いているか確認。その後sinfoで何か出力されるか確認。おかしくなってたらエラーメッセージ見てググって下さい。
$ sudo systemctl status slurmd $ sudo systemctl status slurmctld $ sinfo
ちゃんと動いていたら何かテストスクリプトを投げてみる。
#!/bin/bash echo "sleeping..." sleep 10 echo "done!"
$ sbatch test.sh $ squeue (ジョブが流れているという表示) $ ls slurm-1.out test.sh
ちゃんと動いてるようなら終わりです。
(3/11追記)
スルーしていたslurm.confの中身だが、hyperthreadingを使って全スレッドを動かすための設定はハマりがちっぽいので書いておこうと思う。
まず、スケジューリングの際に各ノードで複数のジョブが走ることを許す必要がある。slurm.confのスケジューリング関係の設定を以下のようにする。
# ... # SCHEDULING FastSchedule=1 # これはデフォルト SchedulerType=sched/backfill # これもデフォルト SelectType=select/cons_res # これにする SelectTypeParameters=CR_CPU # またはCR_Core # ...
ハイパースレッディングを使わず、単に1ノードでコア数分の複数ジョブを動かす場合はこれだけでよい。
続いて、Partitionでオーバーサブスクライブを許す(複数の異なるジョブがハイパースレッディングでコアを共有することを許す)。デフォルトで生成したslurm.confには、最後に以下のような行があるはずだ。ここでOverSubscribe=FORCEにする。YESだと一つのジョブ内ではハイパースレッディングができても、異なるジョブ同士はコアを共有しないようだ。
PartitionName=<name> Nodes=<yournode> OverSubscribe=FORCE Default=YES MaxTime=INFINITE State=UP
これで動くはずだ。
作業上の注意点として、slurm.confを書き換える際にはsystemctl stop slurmd slurmctldでslurmを落としておこう。書き換え終わったら、systemctl start slurmd slurmctldで起動して動くかどうか確かめる。
また、上で書いた環境だとslurm.confの中にtypoなどがある状態でslurmctldをstartすると、slurmctldがsystemctl stop slurmctldで止まってくれなくなることがある。この場合、落ち着いてslurm.confを動く状態のものに戻してからsystemctl restart slurmctldをすると正しく動き始め、かつ正しく止められるようになる。
今適当な値を入れて作りなおしたが、概ねこんな感じになると思う。ノードの名前やIP、リソースの量は入れ替えないといけないが、それをするくらいならslurmのeasy-configuratorを使ったほうが速い。確認用ということで。
# slurm.conf file generated by configurator easy.html. # Put this file on all nodes of your cluster. # See the slurm.conf man page for more information. # ControlMachine=linux0 ControlAddr=10.1.1.100 # #MailProg=/bin/mail MpiDefault=none #MpiParams=ports=#-# ProctrackType=proctrack/pgid ReturnToService=1 SlurmctldPidFile=/var/run/slurm-llnl/slurmctld.pid #SlurmctldPort=6817 SlurmdPidFile=/var/run/slurm-llnl/slurmd.pid #SlurmdPort=6818 SlurmdSpoolDir=/var/lib/slurm-llnl/slurmd SlurmUser=slurm #SlurmdUser=root StateSaveLocation=/var/lib/slurm-llnl/slurmctld SwitchType=switch/none TaskPlugin=task/none # # # TIMERS #KillWait=30 #MinJobAge=300 #SlurmctldTimeout=120 #SlurmdTimeout=300 # # # SCHEDULING FastSchedule=1 SchedulerType=sched/backfill #SchedulerPort=7321 SelectType=select/cons_res SelectTypeParameters=CR_CPU # # # LOGGING AND ACCOUNTING AccountingStorageType=accounting_storage/none ClusterName=cluster #JobAcctGatherFrequency=30 JobAcctGatherType=jobacct_gather/none #SlurmctldDebug=3 SlurmctldLogFile=/var/log/slurm-llnl/slurmctld.log #SlurmdDebug=3 SlurmdLogFile=/var/log/slurm-llnl/slurmd.log # # # COMPUTE NODES NodeName=linux0 NodeAddr=10.1.1.100 RealMemory=32031 Sockets=1 CoresPerSocket=6 ThreadsPerCore=2 State=UNKNOWN PartitionName=debug Nodes=linux0 Default=YES MaxTime=INFINITE State=UP
どうやらRealMemoryにslurmから見えている量以上の値を入れると起動した時のstateがdrainになって、scontrolから状態をidleにしないとジョブが入らないらしい。
計算ノードでslurmd -Cというコマンドを流すとメモリの量を確認できるので、適当な値を書くよりはこの値をコピペするのが無難だろう。
(追記)
systemctl status slurmctldしたときに「pidファイルがない」みたいなエラーで落ちている場合、slurm.confとslurmctld.serviceで*.pidファイルのpathが異なっている可能性がある。それを確認し、適切に揃えてみてほしい。
(追記2) 訂正:SelectTypeParameter -> SelectTypeParameters