はじめに
研究で使っているワークステーション/クラスターも台数が多くなり、
一台一台ログインしてjobを投げるのも手間です。
そこで登場するのがjob管理システムなるソフト。
今回ではその中でもスパコン等にも使われていながらフリーで利用できるSLURMを利用したいと思います。
国内でクラスターを持っている方々はTruqueというソフトを使っている場合が多いみたいですね。ではなぜ今回SLURMを使うかというと、研究で利用している六ヶ所村のスパコン(通称:六ちゃん)でSLURMが使われているからです。
さてそのSLURMですが、現時点でweb上には日本語の資料が殆どありません。英語の資料を探しても、公式サイトくらいしかまともなものがありません。公式サイトも分かりにくいですが。。。資料が少ないからこそ、ホームページのネタになるってことで、いきましょう。
参考サイト:
今回の環境など
このメモを書くにあたりインストールを行った環境について記します。
公式サイトや参考サイトの説明では、管理ノード、ジョブ発行ノード、計算ノードの三種類のマシンが必要な様に書かれていましたが、
試してみた限りでは管理サーバーとジョブ発行サーバーは1台のマシンで兼用できました。
次の様に管理サーバー兼ジョブ発行サーバーには安価で話題のIntel NUCを使いました。十分な動きをしてくれて、コスト削減です。
管理サーバー 兼 ジョブ発行ノード
- hostname:mdgw
- マシン:Intel NUC D54250WYKH
- OS:CentOS 6.6
計算ノード(1-4)
- hostname:md-sandy[51-54]
- マシン:Intel Xeon E5-2680
- OS:CentOS 6.2 - 6.3
計算ノード(5)
- hostname:md-haswell01
- マシン:Intel Xeon E5-2670v3
- OS:CentOS 6.5
インストール手順
まず最初に大まかなインストール手順を書きます。
SLURMの利用に合わせてMUNGEという認証システムをインストールする必要があります。
大まかに言って以下の手順になります。
- MUNGEのインストール
- SLURMのインストール
また、管理サーバーと計算ノードではインストール内容も若干異なります。
MUNGEのインストール
まず、MUNGEをインストールします。
ここは管理サーバー,計算ノード共に同じことを行います。
上記のMUNGE公式サイトから最新版をダウンロードしてください。
おそらく、munge-0.5.11.tar.bz2というようなファイル名です(versionは時期のよって変わるでしょう)。
適当なディレクトリ(ここでは、/root/installとします)にコピーします。
そこでまずはrpmを作ります。
#管理サーバー,計算ノード共通作業
su -
cd install
rpmbuild -tb --clean munge-0.5.11.tar.bz2
|
上手くいけば、/root/rpmbuild/RPMSに。パッケージが出来上がります。
こんどはこれをインストールします。
#管理サーバー,計算ノード共通作業
rpm -ivh /root/rpmbuild/RPMS/x86_64/munge-libs-0.5.11-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/munge-0.5.11-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/munge-devel-0.5.11-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/munge-debuginfo-0.5.11-1.el6.x86_64.rpm
|
これでインストールは完了です。
うまくいけば、mungeという名前のユーザーとグループが作成されているはずです。
NISを張っている場合は、NISのデータベースをこの時点で更新してください。
ここからはMUNGEの環境設定です。
まず管理ノードにて認証用の鍵を発行し、各計算ノードに配布します。
#管理ノードのみで実行
#mungeの鍵の作成(hogehogeを書き変えて)
echo -n "hogehoge" | sha1sum | cut -d' ' -f1 >/etc/munge/munge.key
#属性の変更
chown munge:munge /etc/munge/munge.key
chmod 400 /etc/munge/munge.key
#mungeの鍵の配布
scp -p /etc/munge/munge.key md-sandy51:/etc/munge/
・・・
(全ての計算ノードに向けて行ってください)
|
さて、これで鍵が配布できました。
今度は、mungeの認証用に、各種ディレクトリの属性を変更します。
管理サーバー,計算ノード共に行います。
#管理サーバー,計算ノード共通作業
chmod -R 700 /etc/munge/
chmod -R 711 /var/lib/munge/
chmod -R 700 /var/log/munge/
chmod -R 755 /var/run/munge/
chown -R munge:munge /var/run/munge/
|
あとはサービスを立ち上げます。
#管理サーバー,計算ノード共通作業
service munge start
chkconfig munge on
|
以上です。
ここで、mungeによる認証ができるかを確認しましょう。
ここの確認は非常に重要です。MUNGEによる認証がうまくいっていないと、後のSLURMの通信がうまくいかずにハマります。
ええ、ハマりました。
#管理サーバー,計算ノード共通作業
munge -n | unmunge
#管理サーバーから実行し、計算ノードで解読
munge -n | ssh md-sandy51 unmunge
・・・
(全ての計算ノードに向けて行ってください)
|
エラーかどうかはメッセージから一目瞭然だと思います。
うまく認証できない場合は、mungeの鍵を再配布してから、munge serviceを再起動してみてください。
鍵配布後にserviceを起動しないとうまくいきません。
SLURMのインストール
続いて、SLURMをインストールします。
ここは管理サーバーと計算ノードでインストールするものが少し違います。
上記のSLURM公式サイトから最新版をダウンロードしてください。
slurm-14.11.4.tar.bz2というようなファイル名です(versionは時期のよって変わるでしょう)。
適当なディレクトリ(ここでは、/root/installとします)にコピーします。
そこでまずはrpmを作ります。
#管理サーバー,計算ノード共通作業
su -
cd install
rpmbuild -taslurm-14.11.4.tar.bz2
|
続いて、管理サーバーに必要なものをインストールします
#管理サーバーで実行
rpm -ivh /root/rpmbuild/SRPMS/slurm-14.11.4-1.el6.src.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-perlapi-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-devel-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-munge-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-slurmdbd-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-sql-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-plugins-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-torque-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-sjobexit-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-slurmdb-direct-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-sjstat-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-pam_slurm-14.11.4-1.el6.x86_64.rpm
|
今度は計算ノードに必要なものをインストールします
#計算ノードで実行
rpm -ivh /root/rpmbuild/SRPMS/slurm-14.11.4-1.el6.src.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-perlapi-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-devel-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-munge-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-plugins-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-torque-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-sjobexit-14.11.4-1.el6.x86_64.rpm \
/root/rpmbuild/RPMS/x86_64/slurm-sjstat-14.11.4-1.el6.x86_64.rpm
|
本当はもっとパーッケージを減らせるかもしれませんが、試行錯誤でこうなったという感じです。
まあ、動くのでこの辺はアバウトに。
今度はSLURMのjob管理を担当してくれるslurmという名のユーザーを作ってあげます。
MUNGEでもmungeというユーザーがいましたが自動で生成されました。
しかし、SLURMでは手動で生成する必要があります。
NISを張っていない場合は管理サーバーおよび全計算ノードでユーザーを追加してください。
ここでは、管理サーバーがNISサーバー(yp-serv)を兼ねているとして、
管理サーバーのみでユーザーを作ります。IDは適当で結構です。
#管理サーバーでユーザーおよびグループ作成
groupadd -g 5000 slurm
useradd -d /var/lib/slurm -u 5000 -g 5000 slurm
cd /var/yp/
make
|
ここで、ユーザーslurmのホームディレクトリを /var/lib/slurmにしたのがポイントみたいです。
続いて、ユーザーslurmが使うディレクトリの作成と属性変更を行います。
/varにNFSとかは張らないと思うので、全計算ノードでも行ってください。
#管理サーバー,計算ノード共通作業
mkdir -p /var/lib/slurm
mkdir -p /var/lib/slurm/spool
mkdir -p /var/log/slurm
chown -R slurm:slurm /var/lib/slurm
chown -R slurm:slurm /var/log/slurm
|
今度は、slurmの設定ファイル(slurm.conf)を書き変えます。
デフォルトではサンプルがあるだけなので、コピーして作成してから、
内容を書き変えます。
#管理サーバーにて実行
#slurmの設定ファイルを書き変え
cp /etc/slurm/slurm.conf.example /etc/slurm/slurm.conf
vi /etc/slurm/slurm.conf
|
今回は以下のようにslurm.confを設定しました。
# 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.
#
ClusterName=cluster ##ドメインとは独立に自由な名前で良いらしい##
ControlMachine=mdgw ##管理サーバーのホスト名##
#ControlAddr=
#
SlurmUser=slurm
SlurmctldPort=6817
SlurmdPort=6818
AuthType=auth/munge
#StateSaveLocation=/var/spool
StateSaveLocation=/tmp
#SlurmdSpoolDir=/var/spool/slurmd
SlurmdSpoolDir=/tmp/slurmd
#MailProg=/bin/mail
MpiDefault=none
#MpiParams=ports=#-#
ProctrackType=proctrack/pgid
ReturnToService=1 ##計算ノードの状態更新の為に1が良いらしい##
SlurmctldPidFile=/var/run/slurmctld.pid
SlurmdPidFile=/var/run/slurmd.pid
#SlurmdUser=root
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/linear ##一つの計算ノードでは1つのジョブしか実行させたたくない場合(ノードを跨いだ並列計算は可能)##
SelectType=select/cons_res ##一つの計算ノードにて複数のジョブを実行させたい場合(ノードを跨いだ並列計算も可能)##
SelectTypeParameters=CR_CPU ##後者の場合のjobの割り振り方、CPU単位か、socket単位かなど##
#
#
# LOGGING AND ACCOUNTING
#AccountingStorageType=accounting_storage/none
#JobAcctGatherFrequency=30
#JobAcctGatherType=jobacct_gather/none
#SlurmctldDebug=3
#SlurmctldLogFile=
#SlurmdDebug=3
#SlurmdLogFile=
#
#
# COMPUTE NODES
##計算ノードの登録##
NodeName=md-sandy5[1-4] CPUs=16 Sockets=2 CoresPerSocket=8 ThreadsPerCore=1 RealMemory=64399 State=UNKNOWN
NodeName=md-haswell01 CPUs=24 Sockets=2 CoresPerSocket=12 ThreadsPerCore=1 RealMemory=128958 State=UNKNOWN
##ジョブパーティションの登録
PartitionName=debug Nodes=md-haswell01 MaxTime=INFINITE State=UP
PartitionName=sandy5x Nodes=md-sandy5[1-4] Default=YES MaxTime=INFINITE State=UP
|
実際には付属のサンプルから日本語でコメントをしたところだけ書き変えました。
管理サーバーはControlMachineとして、計算ノードはNodeNameとして登録します。
CPUの個数以外の詳細な値は無くてよさそうですが、slurmのサービスを立ち上げた後に個々の計算ノードで"scontril show node"コマンドを実行するとこういった情報が取れますので、コピペすればOK。
PartitionNameは計算ノードの纏まり(まさにクラスター)を指定します。今回は、sandy bridgeの四台と、haswellの一台を分けたクラスターにしてみました。job投入時にどちらのクラスターに投入するかを指定することができます。
ポイントは、SelectTypeです。これはデフォルトではselect/linearが設定されています。select/linearの場合、一つのノードあたりjobが一つしか実行されない様になります。もちろん、4ノードを跨いだ並列jobを流すことは可能ですが、1ノードの中でCPU個の未並列ジョブを投げたりとかはできません。
スパコンだと、ユーザー間の干渉が無く、この方が良いのです。しかし、研究室レベルのクラスターですと、コード作成途中の学生さんの計算や、解析のための軽い計算なども比較的多く、CPUがノードあたり16や24もある時代にこれでは不便なこともあります。そんな時は、SelectTypeをselect/cons_resに設定します。これで、ノードあたりに複数のjobを投げることが可能になります。さらに、SelectTypeParametersにてCR_CPUを設定しておけば、ノードのCPUが使い切られた段階で、それ以上のjob投入は待機させられます。openmpの様なスレッド並列でも、並列数分のCPUを使っっているとみなしてくれるので、コア数分のjobが流れて、個々のjobはさらにマルチスレッドでCPUを取り合うなんてことはなさそうです。
他にもいろいろありそうですが、まずは、こんなところで。
私もこれ以上は調べてません。
さて、slurm.confが出来上がったら、全計算ノードに配布しましょう。
#管理ノードのみで実行
#slurm.confの配布
scp -p /etc/slurm/slurm.conf md-sandy51:/etc/slurm/
・・・
(全ての計算ノードに向けて行ってください)
|
鍵が配布出来たら、全てのマシンでserviceを立ち上げます。
#管理サーバー,計算ノード共通作業
service slurm start
chkconfig slurm on
|
これで完了です。
確認の為、sinfoコマンドを実行してみてください。
次のような画面が出ます。
#管理サーバーで実行
sinfo
PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
debug up infinite 1 idle md-haswell01
sandy5x* up infinite 4 idle md-sandy[51-54]
|
全ての計算ノードが"idol"になっていれば成功です。
"dawn"とか"unknown"になっているノードがある場合は、どこか設定がうまくいっていません。
私も相当ハマりました。複数の原因がありましたが、通信がうまくいっていないのが多くの原因です。
以下の点を確認してみて下さい
- firewall(iptables)でポートが閉じられていないか。ポートは6817,6818がデフォルトで使われます。
- SELinuxが邪魔していないか。
- host名が解決されているか。/etc/hostsの設定やNISでのhostsの配布が間違っていないか。
- ユーザーmungeやユーザーslurmの使うファイルのpermissionが正しいか。緩くし過ぎてもだめみたい。
- mungeでノードを跨いだ認証ができるか(前述の方法)。できない場合はmunge.keyを再作成・再配布してサービス再起動
また、"sinfo -R"コマンドで、idleにならない原因が分かるかもしれません。
次の様に、メモリの設定がおかしいとか教えてくれます。
#管理サーバーで実行
sinfo -R
REASON USER TIMESTAMP NODELIST
Low RealMemory slurm 2015-11-18T18:43:10 md-haswell[02-04]
Not responding slurm 2015-11-18T18:49:51 md-sandy[01-08]
|
私は特に最後のmunge.keyに気づくのに時間がかかりました。
海外サイトを延々回りましたが、盲点でした。
ちなみに、slurmのサービスの再起動ではrestartよりも、stopとstartcleanを使うことが推奨されます。
#管理サーバー,計算ノード共通作業
service slurm stop
service slurm startclean
|
restartだと前回の設定が残ってしまうようです。
皆さんもうまくいくことを祈っています。
job投入
さて、ジョブ投入ですが、これに関しては多くの資料が出回っています。要はスパコンユーザー用の資料です。
sbatch等を利用して管理サーバー上から投げてもらえばいいですので、注意点だけいくつか。
- NISおよびNFS等でユーザーとファイル領域の共有をしておくこと。私はglusterfsで共有ファイル領域を作成しています。
- nodeのstateがdownになってしまう場合は、downしているnodeだけでなく管理サーバー側でもslurmサービスを再起動してみること。
- 通常のmpirunと異なり、SLURM経由でmpirunを実行する場合はログインシェルスクリプトが読まれないっぽい。よってパスが通らないとかでこける場合がある。
なので、sbarchで読み込ますスクリプトの中にログインシェルスクリプトも書いておくとよい。 この場合の対策として、srunやsbatchの引数として、"--get_user_env"を付ける。
sbatch --get-user-env ./job.sh
|
もしくは、job.shの中に、#SBATCH --get-user-envを明示する。job.shの中身の例は次のようなもの
#!/bin/bash
#SBATCH --get-user-env
#SBATCH -A accountname
#SBATCH -p partitionnane
#SBATCH -J jobname
#SBATCH -N 3 #num of node
#SBATCH -n 2 #num of total mpi processes
#SBATCH -c 1 #num of threads per mpi processes
#SBATCH -o log
#SBATCH -e err
##SBATCH -t 01:10:00
export OMP_NUM_THREADS=6
export MKL_NUM_THREADS=6
mpirun -bind-to socket -mca btl openib,self -np 2 ./osu_bw
|
こうすると、"su - (uidが同じユーザー名) -c /usr/bin/env "と同様の動きをして、パスが通る。
- 管理ノードにはInfinibandが付いておらず、計算ノードにだけInfinibandが付いているような構成でも、Infinibandを利用したMPI計算が可能。さらに、管理ノードでコンパイル、ジョブ投入までを行ってもよい。ただし、上記の"--get-user-env"の指定が必要な場合ある(これを見つけるまでかなりハマりました。。)。
- 以下、気づく度に列挙していきます。
追記(2017/12/27)
downしていたノードのstateをidelに変更する方法がこれまでわからず、毎回slurmサービスの再起動をしていました。今回、手動で特定のノードのstateだけを変更する方法が分かったので記述します。
まず、復旧したいノードにrootでログインし、以下のコマンドでslurmの再起動をしておきます。reboot直後でもこれをしないとDAPL関連が上手く動かないことがありました。
service slurm stop
service munge restart
service slurm startclean
|
次に、マスターノードにrootでログインし、scontrolコマンドが発行できる状態にします。そこで、以下のコマンドを入力すれば指定したノードのstateがidleになります。
scontrol update nodename=node_name_in_slurm.conf state=idle
|
余談
まだわからないことはあって、計算ノード間だけinfinibandで管理サーバーは通常のLANの場合に、infiniband経由の並列計算って投入できるのかどうか。。。うーん。
それから、まさかの新VAIO Z。発表でテンションが上がりっぱなし。しかし、冷静に考えると、今使っているDUO13も優れている点が沢山あってまだまだ現役でいてほしい。年末のskylate+windows10まで生暖かく見守ろう。
上記のNUCでもwindows 10 previewがあっさり動いて感心しました。windows タブレットも使えるアプリ(OneCalenderお勧め)が見つかると意外と便利で、自分でも色々と開発していこうかと思います。