PBSProを普通に使う場合にはcpu coreの空き数、メモリ搭載量とかでジョブの配送先が決まる。
ただ最近ではGPUの空き枚数でジョブの配送が決まってほしい場合もあり、基本のままでは不十分になりつつある。
例えば64coreなマシンで4枚GPUを搭載しているノードにジョブを入れたい場合、
64coreすべてを使用するような形でジョブを投げる必要がある
もし16coreで投げると、そのマシンはまだまだジョブを受け付けられる状態にあり、その他のジョブがGPUを使うようなら
4枚のGPUはその計算リソースを供給され遅くなるか、最悪ジョブが停止されてしまう。
ここではGPUの枚数で計算ノードが決定され(resource定義)、かつそのGPUがそのジョブにしか使われないようにしてみる(hook定義)。
*openpbs-20.0.1を使っています
一応「pbsnodes」コマンドには「ngpus」という欄がある. だた何もしなければ「0」のままで、
[saber@openpbs ~]$ pbsnodes -aS
vnode state OS hardware host queue mem ncpus nmics ngpus comment
--------------- --------------- -------- -------- --------------- ---------- -------- ------- ------- ------- ---------
pbs-node1 free -- -- pbs-node1 -- 8gb 4 0 0 --
[saber@openpbs ~]$
[saber@openpbs ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=0 -I
qsub: Unknown resource: ngpus
[saber@openpbs ~]$
かつそれを使うことも出来ない. 表記はされているが使えない状態で、まずはこれを調整します
既定ではGPUを定義する項目がないので、その定義項目をジョブ管理ノードに追加します。
[root@openpbs ~]# qmgr
Qmgr: create resource ngpus type=long, flag=nh <--「create resource ngpus type=long, flag=nh」を実行
Qmgr: list resource <--「list resource」で確認
#
# Create resources and set their properties.
#
Resource ngpus
type = long
flag = hn
Qmgr: quit
[root@openpbs ~]#
その後、pds機能を一旦停止させ、新たなリソース名として「ngpus(数値型)」を追加
「sched_config」を修正してpbsを再起動
[root@openpbs ~]# systemctl stop pbs
[root@openpbs ~]# vi /var/lib/pbs/sched_priv/sched_config
- resources: "ncpus, mem, arch, host, vnode, aoe, eoe"
+ resources: "ncpus, mem, arch, host, vnode, aoe, eoe, ngpus" <--- 242行目あたり、「ngpus」を追加
[root@openpbs ~]# systemctl start pbs
この後に、計算ノードにGPUを定義します. ここでは 計算ノードpbs-node1 にGPU1枚定義してます
[root@openpbs ~]# qmgr -c "set node pbs-node1 resources_available.ngpus=1"
(確認)
[root@openpbs ~]# qmgr -c "print node pbs-node1"
#
# Create nodes and set their properties.
#
#
# Create and define node pbs-node1
#
create node pbs-node1 Mom=pbs-node1.sybyl.local
set node pbs-node1 state = free
set node pbs-node1 resources_available.arch = linux
set node pbs-node1 resources_available.host = pbs-node1
set node pbs-node1 resources_available.mem = 8146060kb
set node pbs-node1 resources_available.ncpus = 4
set node pbs-node1 resources_available.ngpus = 1 <--- ここが追加されます.
set node pbs-node1 resources_available.vnode = pbs-node1
set node pbs-node1 resv_enable = True
[root@openpbs ~]#
ここでqsubのインターラクティヴモードで GPU を1つ使うようにしてみる
[illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=1 -I
qsub: waiting for job 7.openpbs to start
qsub: job 7.openpbs ready
[illya@s ~]$
nvidia-smiコマンドでgpuリソースを確認すると、、、
[illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
GPU 1: GeForce GT 710 (UUID: GPU-34c49ab7-b79d-e341-93e2-1659e9bd9e57)
[illya@s ~]$
と2つのGPUが列挙されてしまう。1つだけ使いたいのに、、っでそれを解消するのがhook
参照先: https://www.altair.com/resource/altair-pbs-professional-support-on-nvidia-dgx-systems
まずは下記を実行して「pbs_cgroups.json」を得ます。
[root@openpbs ~]# qmgr -c "export hook pbs_cgroups application/x-config default" > pbs_cgroups.json
取得した「pbs_cgroups.json」の中身に修正を加えます。
https://help.altair.com/2022.1.0/PBS%20Professional/PBS2022.1.pdf の AG-346(538ページ) 「6.5.5.4 Isolating NVIDIA GPUs」を参照
{
"cgroup_prefix" : "pbs_jobs",
"exclude_hosts" : [],
"exclude_vntypes" : ["no_cgroups"],
"run_only_on_hosts" : [],
"periodic_resc_update" : true,
"vnode_per_numa_node" : false,
"online_offlined_nodes" : true,
"use_hyperthreads" : false,
"ncpus_are_cores" : false,
"discover_gpus" : true,
"manage_rlimit_as" : true,
"cgroup" : {
"cpuacct" : {
"enabled" : true,
"exclude_hosts" : [],
"exclude_vntypes" : []
},
"cpuset" : {
"enabled" : true,
"exclude_cpus" : [],
"exclude_hosts" : [],
"exclude_vntypes" : [],
"mem_fences" : true,
"mem_hardwall" : false,
"memory_spread_page" : false
},
"devices" : {
"enabled" : true, <--ここを「false」から「true」に変更
"exclude_hosts" : [],
"exclude_vntypes" : [],
"allow" : [ # allow部分を下記に全変換(「"c *:* rwm"」はいれないように)
"b *:* m",
"b 7:* rwm",
"c *:* m",
"c 195:* m", # 195は「ls -l /dev」で表示されるデバイス番号. 195は /dev/nvidiaX, /dev/nvidiactl を持ちます
"c 136:* rwm", # 136は「ls -l /dev/pts」にあるデバイス番号
["infiniband/rdma_cm","rwm"], # infinibandを持たないなら削除
["fuse","rwm"],
["net/tun","rwm"],
["tty","rwm"],
["ptmx","rwm"],
["console","rwm"],
["null","rwm"],
["zero","rwm"],
["full","rwm"],
["random","rwm"],
["urandom","rwm"],
["cpu/0/cpuid","rwm","*"],
["nvidia-modeset", "rwm"], # /dev/nvidia-modeset が存在しないなら外してもいいのかも...
["nvidia-uvm", "rwm"],
["nvidia-uvm-tools", "rwm"],
["nvidiactl", "rwm"]
]
},
"hugetlb" : {
"enabled" : false,
"exclude_hosts" : [],
"exclude_vntypes" : [],
"default" : "0MB",
"reserve_percent" : 0,
"reserve_amount" : "0MB"
},
"memory" : {
"enabled" : true, # メモリー確保とか面倒ならfalseへ
"exclude_hosts" : [],
"exclude_vntypes" : [],
"soft_limit" : false,
"default" : "256MB",
"reserve_percent" : 0,
"reserve_amount" : "64MB"
},
"memsw" : {
"enabled" : true, # メモリー確保とか面倒ならfalseへ
"exclude_hosts" : [],
"exclude_vntypes" : [],
"default" : "256MB",
"reserve_percent" : 0,
"reserve_amount" : "64MB"
}
}
}
修正した「pbs_cgroups.json」ファイルをシステムに戻して反映させる
[root@openpbs ~]# qmgr -c "import hook pbs_cgroups application/x-config default pbs_cgroups.json"
hook 'pbs_cgroups' contents overwritten
[root@openpbs ~]#
その後に「pbs_cgroup」を有効にする
(現状の確認)
[root@pbspro ~]# qmgr
Qmgr: list hook
Hook pbs_cgroups
type = site
enabled = false
event = execjob_begin,execjob_epilogue,execjob_end,execjob_launch,
execjob_attach,
execjob_resize,
exechost_periodic,
exechost_startup
user = pbsadmin
alarm = 90
freq = 120
order = 100
debug = false
fail_action = offline_vnodes
(hookを有効にする)
Qmgr: set hook pbs_cgroups enabled = true
(有効になったかの確認)
Qmgr: list hook
Hook pbs_cgroups
type = site
enabled = true <-- trueに代わる
event = execjob_begin,execjob_epilogue,execjob_end,execjob_launch,
execjob_attach,
execjob_resize,
exechost_periodic,
exechost_startup
user = pbsadmin
alarm = 90
freq = 120
order = 100
debug = false
fail_action = offline_vnodes
Qmgr:
[root@pbspro ~]#
あとはpbs_serverと対象の計算ノードのpbsサービスを再起動します
[root@openpbs ~]# systemctl restart pbs
(gpuを持つ計算ノード)
[root@pbs-node1 ~]# systemctl restart pbs
rockylinux9は基本が cgroups v2 で稼働しています. 目下 OpenPBS は v1 としてリソース管理をしているので、そのままではGPUリソース制御は働きません。
参照 https://community.openpbs.org/t/openpbs-cgroups-v2-support/2667
この場合は cgroups v2 を cgroups v1 に変更して対応します.
cgroups v1ならkubernetesに影響あるとか...微妙なのですが..
目下のcgroupsのバージョン確認は
stat -fc %T /sys/fs/cgroup/
を実行して「cgroup2fs」が出れば cgroups v2. 「tmpfs」が出れば cgroups v1 となります
もしv2からv1へ変更したければ、下記のようにして修正します
(v2からv1へ)
grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"
reboot
(元に戻す)
grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=1"
reboot
reboot後に「stat -fc %T /sys/fs/cgroup/」の出力が「fmpfs」になっている事を確認します.
selinuxはenforcingのままでもいいみたい.
これで rockylinux9 もGPUリソース制御が達成できました.
同じようにqsubのインターラクティヴモードでテスト
この際、「-l nodes=1:ppn=1:ngpus=2」な書式はダメみたいで「-l select=1:ncpus=1:ngpus=2」と「select」と「ncpus」でないと無理みたい
[illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=1 -I
qsub: waiting for job 22.openpbs to start
qsub: job 22.openpbs ready
[illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
[illya@s ~]$ exit
[illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=2 -I
qsub: waiting for job 23.openpbs to start
qsub: job 23.openpbs ready
[illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
GPU 1: GeForce GT 710 (UUID: GPU-34c49ab7-b79d-e341-93e2-1659e9bd9e57)
[illya@s ~]$ exit
[illya@client ~]$ qsub -q workq -l select=1:ncpus=1 -I
qsub: waiting for job 24.openpbs to start
qsub: job 24.openpbs ready
[illya@s ~]$ nvidia-smi -L
No devices found.
[illya@s ~]$
1個指定、2個指定も問題なく使えたみたい。また何も指定しないとデバイスすら見えないみたい
複数のclientからGPUを一つづつ貰い受けた時のGPU IDはそれぞれ0となります(それぞれ別々のGPUです)
なので、8GPUマシンで4GPU毎に使用してもGPUカードは被りません
[illya@client ~]$ qsub -l select=1:ncpus=1:ngpus=1:mem=1gb -I [illya@client ~]$ qsub -q workq -l select=1:ncpus=1:ngpus=1 -I
qsub: waiting for job 11.openpbs to start qsub: waiting for job 10.openpbs to start
qsub: job 11.openpbs ready qsub: job 10.openpbs ready
[illya@s ~]$ nvidia-smi -L [illya@s ~]$ nvidia-smi -L
GPU 0: GeForce GT 710 (UUID: GPU-34c49ab7-b79d-e341-93e2-1659e9bd9e57) GPU 0: GeForce GT 710 (UUID: GPU-f0753e20-06f7-695a-f325-b5b6342393ba)
[illya@s ~]$ [illya@s ~]$
留意
ngpus=2でジョブリソースを確保しても、ncpusが余っていればジョブの投入は可能です. 単にGPUリソースにアクセスできないだけ
一応これでGPUリソースの排他的制限は出来たけど、今度は逆にCPUリソースの排他的制限は可能なのかと疑問がでる...未調査です
qsubで1coreリソースを確保して、でも展開されるスクリプトには1core以上を使うアプリが仕込まれると厄介極まりない...
1計算機ノード1coreな世界なら心配要らない話だけど、昨今のハイブリッドMPIなプログラムだと考慮が必要なのかも
「qload」と名付けてます
yum install perl-JSON
(ubuntu)
apt install libjson-perl
- ! - | ! - | | | | ! - | ! - | | | | | | | | ! - | ! - | - | ! ! - ! - | | - - | | | - | | | ! ! ! - | | | ! - | | | | | ! - | | - - | - | ! ! | ! |
|
中身は「pbsnodes -aSj」と同じなんだけどね。複数のqueueがあった場合の対策として準備
だいたいこんな出力になります
Queue Run wait Host CPU usage GPU
cpu 1 0 em01 20/20 ******************** 0/0
em02 24/48 ***********--------- 0/0
gpu 2 0 g01 16/16 ******************** 2/4 **--
g02 16/16 ******************** 4/4 ****