メインコンテンツに移動

始動テスト

管理サーバー

いろいろ試行錯誤した挙句,要するにこうだ.はじめてのユーザーに伝えるべきことは

  • Slurmは, 管理サーバー slurmcltd がユーザーのジョブを受け取り,実行サーバー slurmd に実行してもらいます.
  • 管理サーバー slurmcltd はジョブを管理しているだけなので, 特権ユーザーである必要はありません.
    • ユーザー slurm グループ slurm にしておくのがセキュリティ上安全です.だからさっさと作れ
    • /bin/mail が必要なので, mailx パッケージみたいなのインストールしとけタコ
  • 実行サーバー slurmd は,各ユーザーの権利を管理する必要がありますので, 特権 root で動作します.

よって,管理サーバでは,いくつかのフォルダーをあんたが準備する必要がございます. 所有者 slurm.slurmです.

/var/spool/slurmd/ 作業中のジョブを保存します
 /var/slurmd/ 管理サーバーの状態を保存しています.
/var/run/slurm/ systemdで管理サーバーの情報を保存します

必要な設定ファイルは(インストール時の設定にもよりますが)次の通り:(★管理サーバ☆計算ノード)

/etc/ld.so.conf.d/slurm.conf ★☆

共有ライブラリーのための設定ファイル. ​​​​​​ライブラリの場所を書く:

/usr/local/lib

/etc/tmpfiles.d/slurm.conf ★

/var/run はtmpfsで再起動でクリアされてしまいますので, フォルダーを準備する. なお /var/run は /run のシンボリックリンクであることに注意

d /run/slurm 0770 slurm slurm

/usr/lib/systemd/system/slurmctld.service ★ 

systemdで起動するためのファイル. 自動的にはインストールされないので注意(パッケージの etc/ フォルダーに落ちている) . 

/usr/lib/systemd/system/slurmd.service ☆ systemdで起動するためのファイル. 自動的にはインストールされないので注意(パッケージの etc/ フォルダーに落ちている) . 
/usr/local/etc/slurm.conf ★☆ システム構成ファイル. 下で述べる.
/usr/local/etc/cgroup.conf ☆ LinuxのCgroupに関するなにこれ設定(パッケージの etc/ フォルダーに落ちている) . 

構成ファイル設定

よい子は,初めて起動する前に,構成ファイルをシステムに応じて記述します. 今まで一度もよい子ではなかった人も,ここでは,よい子にした方が良いです.全体にわたる設定について書く:

# /usr/local/etc/slurm.conf
SlurmctldHost=h225    お前のサーバーのhostname -sで出るやつ
SlurmUser=slurm          サーバーを実行するひと
# Ports
SlurmctldPort=6817     これ,要るのか知らん
SlurmdPort=6818         しらねえって
# Folders
SlurmctldPidFile=/var/run/slurm/slurmctld.pid    systemdのserviceファイルに書いたよね?
SlurmdPidFile=/var/run/slurmd.pid                     systemdのserviceファイルに書いたよね?
SlurmdSpoolDir=/var/spool/slurmd
StateSaveLocation=/var/slurmd
# Cgroup
ProctrackType=proctrack/cgroup
# New Node Action  Failした計算ノードの取り扱い(自動復帰か,落ちっぱなしか)
ReturnToService=0
ClusterName=FDLAB
# Scheduling
SchedulerType=sched/backfill
SelectType=select/cons_res
SelectTypeParameters=CR_Core

続けて,計算ノードについて書く.

CPUの数や搭載メモリー量,テキトーに書いたらバレる

登録する前に,嘘書くとバレるので,計算ノードのスペックを調べると良い.以下のものが必要である.

Sockets マザー板上に半田付けされている,でかいICを嵌めるバネつきのゲジゲジの数
CoresPerSocket IC入れる穴に,石ころやらバナナを詰めるわけだが,一粒あたりのCoreの数. /proc/cpuinfo で言うところのCPUですね.
ThreadsPerCore Coreで走れるスレッドの数.BIOSで設定できるよね.砂利では1だな.
CPUs システムにより, Coreの総数あるいはThreadの総数となる. そうだ.
RealMemory 本当に搭載しているメモリーをメガバイト単位で

いやそんな知らねえよ,てのが普通ですよね.計算ノードで,次のコマンドで調べます

# /usr/local/sbin/slurmd -C
NodeName=h225 CPUs=2 Boards=1 SocketsPerBoard=1 CoresPerSocket=2 ThreadsPerCore=1 RealMemory=3937

嘘書くとゴネ始めて結構面倒なので,真面目に書きましょう.  スペックとしては, 他に

  • Feature=noroma,gomi     計算ノード選択に役立つ文字列をコンマで複数指定可能です.
  • Gres=gpu:K20:2,gpu:K40:1   計算ノードに固有のリソースをコンマで複数指定可能.

計算ノードの宣言はこんな感じ

NodeName=登録名[範囲] NodeHostname=正式名[範囲] NodeAddr=IPアドレス マシンスペック

正式名はhostname -sで得られる名前と一致していなければならない. 登録名がNodeHostnameと同じならば, 正式名NodeHostnameは省略可能である.登録名, 正式名として範囲指定が利用できる.つまりh[192,201-220] では, h192, h201,h202,...,h220 を宣言することになる.

NodeName=mynode[1,2,4-5] NodeHostname=h[225,226,228-229]    これはOK
NodeName=mynode[a,b,d-e] NodeHostname=h[225,226,228-229]    これはだめ

IPアドレスは,純粋な計算ノードで,IPアドレスが正式名からDNSで得られるならば省略できる.計算ノードが管理サーバーと同じものであれば,ローカルホスト127.0.0.1を記入する必要がある(外部のマシンであると誤認し外部アクセスを試みてしまう). マシンスペックは,上で取得したものを入れておけば良い.

例えばこんな感じですね:

NodeName=ib2007-3 NodeHostname=h225 NodeAddr=127.0.0.1 CPUs=2 RealMemory=3936 Sockets=1 CoresPerSocket=2 ThreadsPerCore=1,Feature=noroma,Gres=gpu:K40:0

ジョブクラスを定義

ジョブクラスは,優先度や継続時間によって複数定義するものですが,まずはテスト用に一つ定義します.例えば

PartitionName=f3h Nodes=ib2007-3 State=Up MaxTime=0-3:05:00

ここでは,クラス名 f3h, 継続時間が0日3時間5分のジョブクラスを定義しています.参加ノードは,登録名がib2007-3の計算ノード(実は管理サーバ)です.

起動

一台のサーバー機で,管理サーバーを起動

# systemctl start slurmctld

全ての計算ノード(必要ならサーバー機でも)で,ノードサーバーを起動

# systemctl start slurmd

slurm.conf を書き換えた後は,再読み込み:

# scontrol reconfigure

さてさて.状況を見てみる:

# sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
f3h             up       3:05:00       1           idle      ib2007_3

オーケーだ.にゃお,STATEの意味は:

State一覧
ALLOC 先約あり ALLOCATED 先約あり
COMP 絶賛計算中 COMPLETING 終了処理中
DOWN 死んでる・・・ DRAIN 気分が悪い
FAIL 堕ちた IDLE 暇してる
MAINT 修理してる POWER_DOWN 切れてる

一度落ちると,自動では復活しない.

# scontrol
scontrol: update NodeName=h225 State=IDLE Reason="OKOK Ure OK all right ?"
scolnrol: quit

これで治る.

ジョブ投入

ではジョブを投入してみる. ジョブ文は

first.job:
#!/bin/bash
#SBATCH -p f3h
#SBATCH -o myjob.stdout
#SBATCH -e myjob.stderr
#SBATCH --job-name="MyFirst..."
pwd
sleep 300

では投入:

$ sbatch first.job

すると実行が始まる

$ squeue  -l
JOBID PARTITION     NAME     USER    STATE       TIME TIME_LIMI  NODES NODELIST(REASON)
5        f3h     MyFirst.  sugimoto  RUNNING   0:13   3:05:00      1 ib2007-3

計算機が全て使用中になっちまった:

$ sinfo
PARTITION AVAIL  TIMELIMIT  NODES  STATE NODELIST
f3h          up    3:05:00      1  alloc ib2007-3

クライアントノード

クライアントノードを作成してみる.あり?slurmのconfigureがmungeが見つからないと言っている. dnf でインストールしたのに・・・なぜ?お?こいつはincludeファイルを探しているのか・・・困ったな.

git clone https://sugimoto605@bitbucket.org/rgdkyotou/thirdparty.git
# ここでMakefileのSLURMサーバーアドレスを設定する
make munge.key.copy   計算ノードではサーバーで使っているキーをコピー
scp 10.249.229.225:/local/packages/thirdparty/rc/munge.key rc/
Password:いつもの
# ここで slurm-19.05.4.tar.bz2 をネットで探し出して CLUSTER/BASE にコピー
make slurm-client
# ここで /usr/local/etc/slurm.conf で良いか,目視で確認せよ
systemctl start slurmd

で,稼働を確認した. 試しにたくしゃん入れよ.面倒やし連打爆撃

$ squeue
JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
10       f3h MyFirst. sugimoto PD       0:00      1 (Resources)
11       f3h MyFirst. sugimoto PD       0:00      1 (Priority)
12       f3h MyFirst. sugimoto PD       0:00      1 (Priority)
13       f3h MyFirst. sugimoto PD       0:00      1 (Priority)
14       f3h MyFirst. sugimoto PD       0:00      1 (Priority)
6       f3h MyFirst. sugimoto  R       1:01      1 ib2007-1
7       f3h MyFirst. sugimoto  R       0:33      1 ib2007-1
8       f3h MyFirst. sugimoto  R       0:30      1 ib2007-3
9       f3h MyFirst. sugimoto  R       0:30      1 ib2007-3
$ sinfo -Nl
NODELIST   NODES PARTITION       STATE CPUS    S:C:T MEMORY TMP_DISK WEIGHT AVAIL_FE REASON              
ib2007-1       1       f3h   allocated    2    1:2:1   3935        0      1   kuzu none                
ib2007-2       1       f3h       down*    2    1:2:1   3935        0      1 noroma Not responding      
ib2007-3       1       f3h   allocated    2    1:2:1   3935        0      1   kuzu none                
ib2007-4       1       f3h       down*    2    1:2:1   3935        0      1 noroma Not responding      

やっほう.コアが2つって,今から考えるとさみしいね〜.やっぱ何十個かないとつまらん.

slurm.confを苛めてみる

疑問だ.Torque/PBSでは

  • 計算ノードの設定ファイルには, 「お前の親分はこのマシン」しか書かない
  • 管理サーバーの設定ファイルに,ジョブクラスだの他の設定が全部書かれる

一方,Slurmでは全設定を書いた slurm.conf を,管理サーバー・計算ノードで共有せよ.ということなのだが.

  • いや・・・そんなもん,そのうち,1台くらい,なんか古いファイルつかったノード

とか出てくるのは避けられない.大事故が起こる前に,ありがちな事故は発生させよう.

とりあえずわかっていることは

  • slurmdは, 起動するときに, slurm.conf のケツの方のNodeNameとPartitionから,自分の場所を探す.

つまり, NodeNameの宣言は,さすがに計算ノードでも必要である. 

管理サーバーが勝手にPartition設定を変えたらどうなる?

試してみた.計算ノードが生きたまま,そのpartition設定を管理サーバーで変更し, 

# scontrol reconfigure

すると?おや.計算ノードでもついてくるな. ジョブも実行できるね.

つまり,計算ノードは, Partition設定を見ていない.サーバーが,これやれよ,と言ったものをやる.

管理サーバーが勝手に計算ノードを増やしたらどうなる?

クライアントが勝手に一台増えた. 管理サーバーに連絡するのが面倒なので,とりあえず計算ノードでクライアントをインストールし,勝手に起動してみると,無事に起動する.しかし,どのPartitionにも参加していないので,せっかつ追加した計算ノードを利用することはできない.

仕方がないので,管理サーバーでも, その新しいノードを記述して reconfigure してみた.すると無事に認識され, Partitionにも入る. ジョブも正常に実行され,問題はない.と,いうわけで

  • 管理サーバーの slurm.conf には,全ての計算ノードの定義,全てのPartitionの定義が必要
  • 計算ノードの slurm.conf は,全体的な設定は管理サーバーと一致する必要がある.
    • ノードについては,自分のNodeNameが定義されていれば十分
    • ノードの slurm.conf には,Partitionの設定は不要

じゃあ共有するほどのものではないな.計算ノードでは,インストール時に,まあ自分だけが記載されている一発を持ってれば十分なのだ.必要なのは,管理サーバーやログファイルの名前,ポート番号くらいですな.

ジョブスケジュールSCHED

RMSの基本機能は,ある仕事が終わったら自動的に次の仕事を行う,です.有名店にお客が列をなしている,ってイメージです.基本,みんな平等に並びます(貴族や金持ちが平民を追い越して優先的に入るってのは「優先度」の概念です).これはスケジューラが行います.Slurmのデフォルトはバックフィルで,全体設定で決定:

SchedulerType=sched/backfill

sched/backfill  各ジョブ文の申請使用時間を見て,隙間に入りそうな奴は入れて総時間を最小にしようと足掻く

チュートリアルによると,要するにこうだ
back

????/fairshare  各ユーザーの過去の使用時間を見て, 平等感を演出. サポートされていないのかも?不明だ

計算資源SELECT

計算資源の割り当て方法も全体設定で決める.例えば

SelectType=select/cons_res
SelectTypeParameters=CR_Core 

select/linear 

(デフォルト)ううん?多分1ノードに1ジョブってことなのかな.

select/cons_res 

資源が許せばジョブを入れる.1ノードで複数のジョブが実行され得る.あるジョブが計算機のIOを使い切ったりすると,他方のジョブが影響を受ける可能性がある.

CR_Core  資源とは, CPUのコアのことである.

CR_CPU 資源とは, CPUのことである.

CR_Memory 資源とは, メモリーのことである.

CR_Core_Memory 資源とは, CPUのコアとメモリーのことである.

CR_CPU_Memory 資源とは, CPUとメモリーのことである.

slurm.conf のマニュアルがひどく読みにくい理由がわかった.属性を説明するときに,それが「全体の」属性であるのか,「ジョブクラス」の属性であるのか,「計算ノード」の属性であるのかを,示していないんだ.だから,そもそも,なんの話をしているのかのベースが不明なので,いくら細かく書いても意味不明で読みにくい・・・

逆に言えば,読み手が,そこを補えば,解読可能だ.

こころで,宣言したメモリー量を超えて使おうとすると,何が起こるのかなあ?もしかして死を賜るのかな?

ジョブ優先度

ジョブには優先度を設定することができる(Ttorqueのjobclass,ですね). 優先度は次の要素から構成されます

  • 差別(エコノミーよりもビジネス,それよかファーストクラスが優先して席に座るってやつ)
  • 弱肉強食(弱いジョブが走ってたら,後から来た強い奴に踏んづけられ,強い奴が先に走るやつ)
    • 仕事なのだから優先順位,時間スパンってのがあるのよね
  • 束縛(計算時間が切れたら止まっちまうやつ.メモリー・ディスクはTorqueでは困難で結局できなかった)
    • 巨大メモリープログラムをわざわざメモリーの小さいマシンで走らせて,「僕の計算って大変なんですよ〜」て偉そうにしてた奴がいたなあ・・・CPU使用率が0.2%以下だったが
    • 通信が遅いと思ったら,計算時間の99%をリモートディスクのアクセスに使ってた奴もいたな.
    • 計算時間制限しないと,「それ,いつ終わるの?」「知るわけないじゃないですか」というのが普通で常識的になってしまう

うむ.全部必要だ.どうやって設定するのだ?

弱肉強食の実現

Preemption(やばくなったら,ずらかる)を利用する.これは全体設定

PreemptType=preempt/partition_prio
PreemptMode=SUSPEND,GANG

で決定される. 

preempt/none

もちろん何も起こらない

preempt/partition_prio

ジョブクラスPartitionの属性 Priority に応じてやば加減を検出.もちろん,あるノードが複数のPartitionに属してないと無意味.

preempt/qos

何かのQuality Of Serviceに応じて Preemption を行う.何の品質に,どのサービスか,謎に包まれている

やばくなったときの行動をPreemptModeで設定しなければならぬ. これは全体設定に応じて,各ジョブクラスに別の値を指定できる.

PreemptMode=OFF なんで俺がどかなあかんのや?どくわけないやろ?と宣言

PreemptMode=SUSPEND SIGSTOPでおねんねする. 高貴な方々がいっちまったらSIGCONTで目覚める. Torqueと違い,メモリーが溢れるならばおねんねしない(←なんでや?太すぎるやろ?)該当ジョブクラスでOverSubscribe=FORCEを指定しないと発動しない.

PreemptMode=GANG 下で説明するキャングスケジューリングが発動する.

PreemptMode=REQUEUE 高貴な方々の姿を見ると自殺(←あきらかに,やりすぎだろう?)するが, 高貴な方々が逝っちまったら,こそっと再投入される

PreemptMode=CANCEL 高貴な方々の姿を見ると自殺(←あきらかに,やりすぎだろう?)し,死んだまま

PreemptMode=CHECKPOINT 高貴な方々の姿を見るとなんらかの機能を使って自殺. Checkpointについては後述. 設定していないならばCANCELと同じになる

可能な組み合わせ:

Partition設定 全体設定
SUSPEND GANG REQUEUE CANCEL CHECKPOINT  
SUSPEND OK OK ? ? ?  
GANG OK OK ? ? ?  
REQUEUE ? ? ? ? ?  
CANCEL ? ? ? ? ?  
CHECKPOINT ? ? ? ? ?  

ギャングスケジューリング 優先度の高いジョブが入ってくると,優先度の低いジョブを定期的にサスペンドし,優先度の高いジョブを優先して実行するようにする.へえ・・・優先度が低い方が完全に止まるわけではない,名前に似合わぬ紳士的なポリシーだなのね.いいじゃないか,実現しよう.

GangSchedulingでは,メモリー溢れをすることは避けなければなりません.そうしなければメモリーがハードディスクに書き出されるswapが発生し,計算速度が著しく落ちます.メモリー溢れを防ぐため,以下の設定が必要です.

  • select/linear  CR_Memory

  • select/cons_res CR_Core_Memory  CR_CPU_Meomry  CR_socket_Memory  

怠慢なユーザーは,自分の使用メモリーをジョブ文に書かないです.すると最大メモリーを割り当ててしまうため,メモリー制限に100%引っかかります. 怠慢でないユーザーは存在しないため,ギャングスケジューリングが有効になることは一度もありません.じゃけん,DefMemPerCPU か DefMemPerNode を宣言しておかないと,ほぼ意味はないです.

SchedulerTimeSlice デフォルトで30(秒). この時間間隔ごとにジョブを切り替えます.

OverSubscribe=FORCE:2 これが宣言してあるジョブクラスで, ギャングスケジューリングが有効になります. この例では, 2つのジョブまでが,TimeSliceによって実行されます.もちろん2以上も設定可能.

つあmりDefMemPerNodeをノードの半分くらいに設定しておけば,まあまあ,寝ることができる.よさそうな考えではあるが,怠慢なユーザーが最大メモリーを設定することは考えにくい.彼らは確実に次の文句を言ってくるだろう:

  • この計算機,128GBメモリーなのに,俺のジョブがMEMORY OVERで止まった!死ねやコラ!そのクソ設定のせいだ!止めろやオラオラ!

困ったな.こんな奴に,メモリー使用量の設定をお前のジョブ文に書けよ解決するから,と説明しても

  • 俺がどんな量のメモリーを使っているか?知るわけないやろタコ

となる未来が見えるな.この事態を防ぐには,ジョブが終了するたびに,使用メモリーレポートを出す必要があるなあ.

preemot/part_prio の具体的な例は,こげな感じばい:

#行の最初が#である場合のみ,コメント
PreemptType=preempt/partition_prio
PreemptMode=SUSPEND,GANG
SchedulerTimeSlice=60        ←1分でタイムスライス
DefMemPerCPU=1000         ←デフォルトで1GBメモリ確保(実質的にメモリー指定必須ですね)
PartitionName=first OverSubscribe=FORCE:1 PriorityTier=5 PreemptMode=off
PartitionName=business OverSubscribe=FORCE:1 PriorityTier=3 PreemptMode=suspend
PartitionName=economy OverSubscribe=NO PriorityTier=1 PreemptMode=requeue

firstクラスは,他の誰にも邪魔されない.businessクラスは, firstクラスの人が来たらsuspend行動をとる. economyクラスは,businessクラスやfirstクラスの人を見ただけで目が潰れてジョブがキャンセルされ,高貴な人がいなくなったらジョブを打ち直す. Shared=FORCE:1 (Timeslice実行数が1)であるので,ギャングスケジューリングは発動しない.

いや・・・幾ら何でも,ジョブがキャンセルされる・・・っていうのは非人道的じゃないか?