OpenPBSの機能として1つの計算機を仮想的に2つ以上にする機能がある
Torqueで言うところのNUMA対応TORQUE#e6cf152cっぽいこと.
だがTorqueではCPUリソースにつてはNUMAを活用して仮想的に1つのマシンを複数の計算ノードに仕立てることができるもののGPUリソースの分割はダメでした.
ここではOpenPBSを用いてGPUリソースを分配できるかを調べてみた.
具体例としては 8GPU マシンを 4GPUと4GPUの2台として扱えるようにしたい とか
OpenPBSのバージョンは「20.0.1」とします.
*当初 18.1.4を対象にしてましたが、どうもうまくいかない. GPUの取り扱いに問題があるみたい
下拵え †
良くないけどrootで作業してます.
mkdir -p ~/rpmbuild/{SOURCES,SPECS}
git clone https://github.com/openpbs/openpbs
cd openpbs/
git checkout -b v20.0.1 refs/tags/v20.0.1
cd ..
tar cvfz ~/rpmbuild/SOURCES/openpbs-20.0.1.tar.gz openpbs --transform 's/openpbs/openpbs-20.0.1/' --exclude "openpbs/.git*"
cp openpbs/openpbs.spec rpmbuild/SPECS/
openpbs.specを調整します.
| --- rpmbuild/SPECS/openpbs.spec.orig 2021-01-03 12:36:41.439212969 +0900
+++ rpmbuild/SPECS/openpbs.spec 2021-01-03 14:43:11.884731139 +0900
@@ -56,7 +56,7 @@
%endif
%if !%{defined pbs_home}
-%define pbs_home /var/spool/pbs
+%define pbs_home /var/lib/pbs
%endif
%if !%{defined pbs_dbuser}
|
そしてrpmbuildを実行します
rpmbuild -ba rpmbuild/SPECS/openpbs.spec
完成品は rpmbuild/RPMS/x86_64/ に用意されます.
インストール †
OpenPBSの構築OpenPBS#e96e9feeを参照
ジョブ管理ノードで qmgr を実行して
計算ノード追加「create node <計算ノード>」と
ジョブ管理ノード以外からのジョブ発行を許可する「set server flatuid = True」を忘れずに
GPU resource の定義 †
OpenPBS/GPUとほぼ同じ内容です
「pbsnode」コマンドを実行すると
[illya@client ~]$ pbsnodes -aS
vnode state OS hardware host queue mem ncpus nmics ngpus comment
--------------- --------------- -------- -------- --------------- ---------- -------- ------- ------- ------- ---------
s free -- -- s -- 31gb 8 0 0 --
[illya@client ~]$
と「ngpus」項目があるのですが、これを使うにはジョブ管理ノードで追加設定が必要です
[root@openpbs ~]# qmgr -c "create resource ngpus type=long, flag=nh" <-- gpuの数をリソースとして加えてます
[root@openpbs ~]# vi /var/lib/pbs/sched_priv/sched_config
- resources: "ncpus, mem, arch, host, vnode, aoe"
+ resources: "ncpus, mem, arch, host, vnode, aoe, ngpus" <-- 280行目に「ngpus」を加える
[root@openpbs ~]# systemctl restart pbs <-- サービス再起動
計算ノードにはGPUが2枚あるので、同じくジョブ管理ノードでその計算ノードの「ngpus」を定義します
[root@openpbs ~]# qmgr -c "set node s resources_available.ngpus=2"
確認してみます
[illya@client ~]$ pbsnodes -aS
vnode state OS hardware host queue mem ncpus nmics ngpus comment
--------------- --------------- -------- -------- --------------- ---------- -------- ------- ------- ------- ---------
s free -- -- s -- 31gb 8 0 2 --
[illya@client ~]$
hookの定義 †
OpenPBS/GPU#lc0e0adfと同じようにジョブ管理ノードにて
qmgr -c "export hook pbs_cgroups application/x-config default" > pbs_cgroups.json
として、書き出した「pbs_cgroups.json」を下記のように修正して
| --- pbs_cgroups.json.orig 2021-01-03 15:07:58.958825413 +0900
+++ pbs_cgroups.json 2021-01-03 15:08:34.464036568 +0900
@@ -24,12 +24,28 @@
"memory_spread_page" : false
},
"devices" : {
- "enabled" : false,
+ "enabled" : true,
"exclude_hosts" : [],
"exclude_vntypes" : [],
"allow" : [
- "b *:* rwm",
- "c *:* rwm"
+ "c 195:* m",
+ "c 136:* rwm",
+ ["infiniband/rdma_cm","rwm"],
+ ["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"],
+ ["nvidia-uvm", "rwm"],
+ ["nvidia-uvm-tools", "rwm"],
+ ["nvidiactl", "rwm"]
]
},
"hugetlb" : {
|
それを元に戻して、hookを有効にする
qmgr -c "import hook pbs_cgroups application/x-config default pbs_cgroups.json"
qmgr -c "set hook pbs_cgroups enabled = true"
これでジョブ管理システム全体でhookが有効になります.
vnode設定 †
NUMAでGPUが組み合わせ出来るなら「vnode_per_numa_node」を定義すれが使えそうで
「lscpu」コマンドで
NUMA node0 CPU(s): 0-7
NUMA node1 CPU(s): 8-15
と表記され、「nvidia-smi topo -m」から
GPU0 GPU1 GPU2 GPU3 CPU Affinity
GPU0 X PHB SYS SYS 0-7
GPU1 PHB X SYS SYS 0-7
GPU2 SYS SYS X PHB 8-15
GPU3 SYS SYS PHB X 8-15
と表記されたならNUMA単位でGPUが分割されるかと思われる.
っが、実機が手元にないので未検証
上記はNUMAでGPUが奇麗に分割されているのでいいのですが、NUMAが1つしかない場合とかもあり
その場合は次の方法が使えるみたい.
GPUを持つジョブ実行ノードに設定ファイルを読ませて対応させる方法
初めにジョブ管理ノードで ngpus に加えて gpu_id カスタムリソースを加えます
[root@openpbs ~]# qmgr -c "create resource gpu_id type=string, flag=h"
[root@openpbs ~]# vi /var/lib/pbs/sched_priv/sched_config
- resources: "ncpus, mem, arch, host, vnode, aoe, eoe, ngpus"
+ resources: "ncpus, mem, arch, host, vnode, aoe, eoe, ngpus, gpu_id"
[root@openpbs ~]# systemctl restart pbs
設定ファイルはこんな感じ
*ジョブ実行ノード毎に行います
[root@s ~]# vi s_vnodes
$configversion 2
s: resources_available.ncpus = 0
s: resources_available.mem = 0
s: resources_available.ngpus = 0
s[0]: resources_available.ncpus = 3
s[0]: resources_available.mem = 16gb
s[0]: resources_available.ngpus = 1
s[0]: resources_available.gpu_id = gpu0
s[0]: sharing = default_excl
s[1]: resources_available.ncpus = 1
s[1]: resources_available.mem = 16gb
s[1]: resources_available.ngpus = 1
s[1]: resources_available.gpu_id = gpu1
s[1]: sharing = default_excl
[root@s ~]#
そして
[root@s ~]# pbs_mom -s insert vnodes_20201228 s_vnodes
[root@s ~]# systemctl restart pbs
と実行する. すると「s_vnodes」の内容が「/var/lib/pbs/mom_priv/config.d/vnodes_20201228」として保存されます。
反映にはジョブ実行ノードのデーモンの再起動が必要です
暫くすると
[illya@client ~]$ pbsnodes -aSv
vnode state OS hardware host queue mem ncpus nmics ngpus comment
--------------- --------------- -------- -------- --------------- ---------- -------- ------- ------- ------- ---------
s free -- -- s -- 31gb 4 0 2 --
s[0] free -- -- s -- 16gb 3 0 1 --
s[1] free -- -- s -- 16gb 1 0 1 --
[illya@client ~]$
となる.
元に戻すにはジョブ実行ノードで設定ファイルを取り消してデーモンを再起動して
[root@s ~]# pbs_mom -s remove vnodes_20201228
[root@s ~]# systemctl restart pbs
次にジョブ管理ノードで
[root@openpbs ~]# qmgr -c "delete node s[0]"
[root@openpbs ~]# qmgr -c "delete node s[1]"
でvnode自体を削除する必要があります. これで元に戻ります
一応GPUノードを仮想的に複数に分割してGPUデバイスを排他的に分配できた.
特定の仮想ノードへのジョブ投入は
qsub -q workq -l select=vnode=s[1]:ncpus=1:ngpus=1 -I
で行けるみたい.