PBS pro (openpbs) のインストールと設定
インストール
PBS pro (openpbs) は Debian パッケージがないので, 手動でインストールする.
$ sudo apt-get install git $ mkdir src $ cd src $ git clone https://github.com/openpbs/openpbs $ cd openpbs
インストール方法を確認する.
$ lv INSTALL
PBS のビルトに必要なパッケージを導入する.
$ sudo apt-get install gcc make libtool libhwloc-dev libx11-dev \ libxt-dev libedit-dev libical-dev ncurses-dev perl \ postgresql-server-dev-all postgresql-contrib python3-dev tcl-dev tk-dev swig \ libexpat-dev libssl-dev libxext-dev libxft-dev autoconf \ automake
PBS を動作させるに必要なパッケージを導入する.
$ sudo apt-get install expat libedit2 postgresql python3 postgresql-contrib sendmail-bin \ sudo tcl tk libical3
configure スクリプトと Makefile の作成
$ ./autogen.sh
configure
$ ./configure --prefix=/opt/pbs
make & make install
$ make $ sudo make install
Configure PBS by executing the post-install script
$ sudo /opt/pbs/libexec/pbs_postinstall
Some file permissions must be modified to add SUID privilege.
$ sudo chmod 4755 /opt/pbs/sbin/pbs_iff /opt/pbs/sbin/pbs_rcp
PATH と MANPATH の追加. /etc/skel/.bashrc にも登録しておく.
$ . /etc/profile.d/pbs.sh # cat /etc/profile.d/pbs.sh >> /etc/skel/.bashrc
設定
- 10.0.100.24 : 管理ノード / 計算ノード (Jupyter)
- GPU 3 本.
- CPU 32 コア.
- 10.0.100.21 : 計算ノード
- GPU 1 本.
- CPU 128 コア
- 10.0.100.22,23 : 計算ノード
- GPU 3 本.
- CPU 32 コア
ホスト名の登録
お互いのホスト名を /etc/hosts に登録しておく.
# /etc/hosts 10.0.100.21 ncsv1.matsue-ct.jp ncsv1 10.0.100.22 ncsv2.matsue-ct.jp ncsv2 10.0.100.23 ncsv3.matsue-ct.jp ncsv3 10.0.100.24 ncsv4.matsue-ct.jp ncsv4 10.0.100.25 nfsv1.matsue-ct.jp nfsv1 10.0.100.26 nfsv2.matsue-ct.jp nfsv2 10.0.100.27 nfsv3.matsue-ct.jp nfsv3 10.0.100.28 nfsv4.matsue-ct.jp nfsv4
NFS
既に 10.0.100.24:/work が 10.0.100.21 ~ 10.0.100.23 に NFS マウントされている.
管理ノード
PBS_SERVER に管理ノードのホスト名を登録する. 管理のために pbs_server, pbs_sched, pbs_comm を起動する必要がある. 管理ノードでは PBS での計算はさせないので, pbs_mom は起動しない.
# vi /etc/pbs.conf PBS_SERVER=ncsv4 PBS_START_SERVER=1 PBS_START_SCHED=1 PBS_START_COMM=1 PBS_START_MOM=0 PBS_EXEC=/opt/pbs PBS_HOME=/var/spool/pbs PBS_CORE_LIMIT=unlimited PBS_SCP=/usr/bin/scp
計算実行場所として使う /work は NFS で共有するために, scp ではなく cp コマンドで ジョブ実行結果をコピーするようにする. $usecp の行を追加する.
# vi /var/spool/pbs/mom_priv/config $clienthost ncsv4 $restrict_user_maxsysid 999 $usecp *:/work/ /work/
PBS の再起動
# /etc/init.d/pbs restart
起動の確認
# /etc/init.d/pbs status pbs_server is pid 33802 pbs_mom is pid 33567 pbs_sched is pid 33569 pbs_comm is 33557
計算ノード
PBS_SERVER に管理ノードのホスト名を入れる. 計算サーバは MON のみ 1 とし (起動するの意味), SERVER, SCHED, COMM は 0 (起動しない) とする. こうすることで pbs_mom のみ起動させる.
# vi /etc/pbs.conf PBS_SERVER=ncsv4 PBS_START_SERVER=0 PBS_START_SCHED=0 PBS_START_COMM=0 PBS_START_MOM=1 PBS_EXEC=/opt/pbs PBS_HOME=/var/spool/pbs PBS_CORE_LIMIT=unlimited PBS_SCP=/usr/bin/scp
/work を NFS で共有するために, scp ではなく cp コマンドで ジョブ実行結果をコピーするようにする. $usecp の行を追加する. また, 管理ノード名を入れる.
# vi /var/spool/pbs/mom_priv/config $clienthost ncsv4 $restrict_user_maxsysid 999 $usecp *:/work/ /work/
PBS の再起動
# /etc/init.d/pbs restart
pbs_mon が起動していることを確認.
# /etc/init.d/pbs status pbs_mom is pid 48528
ジョブの作成
管理ノードで実行する.
計算ノードの登録.
# /opt/pbs/bin/qmgr -c "create node ncsv1" # /opt/pbs/bin/qmgr -c "create node ncsv2" # /opt/pbs/bin/qmgr -c "create node ncsv3"
デバッグ用の debug という名前のジョブを作る. 制限時間を 10 分とする.
# /opt/pbs/bin/qmgr -c "create queue debug queue_type=execution" # /opt/pbs/bin/qmgr -c "set queue debug enabled=True" # /opt/pbs/bin/qmgr -c "set queue debug priority=50" # /opt/pbs/bin/qmgr -c "set queue debug resources_default.nodes=1" # /opt/pbs/bin/qmgr -c "set queue debug resources_default.walltime=600" # /opt/pbs/bin/qmgr -c "set queue debug started=True" # /opt/pbs/bin/qmgr -c "set server acl_hosts = ncsv4" # /opt/pbs/bin/qmgr -c "set server default_queue = debug" # /opt/pbs/bin/qmgr -c "set server scheduling = True" # /opt/pbs/bin/qmgr -c "set server node_pack = True"
他のユーザのジョブも qstat で見えるようにする.
# /opt/pbs/bin/qmgr -c "set server query_other_jobs = True"
確認
# /opt/pbs/bin/pbsnodes -a ncsv1 Mom = ncsv1.matsue-ct.jp Port = 15002 pbs_version = 20.0.0 ntype = PBS state = free pcpus = 256 ...(略)... ncsv2 Mom = ncsv2.matsue-ct.jp Port = 15002 pbs_version = 20.0.0 ntype = PBS state = free pcpus = 32 ...(略)... ncsv3 Mom = ncsv3.matsue-ct.jp Port = 15002 pbs_version = 20.0.0 ntype = PBS state = free pcpus = 32 ...(略)...
作成したジョブのテスト
$ mkdir /work/jxxxx $ chown adm01.adm01 /work/jxxxx $ cd /work/jxxxx $ echo "sleep 60; echo done" | qsub $ qstat Job id Name User Time Use S Queue ---------------- ---------------- ---------------- -------- - ----- 0.ncsv1 STDIN adm01 00:00:00 R debug
実行後に標準出力・エラー出力がジョブを実行したディレクトリに作られる.
$ ls STDIN.e0 STDIN.o0
なお, 各計算ノードで ps aux | grep sleep をすると, 計算ノードでプログラムが 実行されていることがわかる.
また, ホストを指定してジョブを投げることもできる.
$ cd /work/sugiyama $ echo "sleep 60; hostname; echo done" | qsub -l select=host=ncsv1 $ echo "sleep 60; hostname; echo done" | qsub -l select=host=ncsv2 $ echo "sleep 60; hostname; echo done" | qsub -l select=host=ncsv3
確認
$ qstat -s pbs: Req'd Req'd Elap Job ID Username Queue Jobname SessID NDS TSK Memory Time S Time --------------- -------- -------- ---------- ------ --- --- ------ ----- - ----- 1.ncsv1 adm01 debug STDIN 34728 1 1 -- 00:10 R 00:00 Job run at Sat Jan 09 at 17:33 on (ncsv1:ncpus=1) 2.ncsv1 adm01 debug STDIN 6473 1 1 -- 00:10 R 00:00 Job run at Sat Jan 09 at 17:33 on (ncsv2:ncpus=1) 3.ncsv1 adm01 debug STDIN 7910 1 1 -- 00:10 R 00:00 Job run at Sat Jan 09 at 17:33 on (ncsv3:ncpus=1) $ cat STDIN.o3 ncsv3 done
GPU を計算リソースとして管理するための設定
GPU 数の登録
管理ノードで実行する. リソースとして GPU の数 (ngpus) を登録.
$ sudo /opt/pbs/bin/qmgr -c "create resource ngpus type=long, flag=nh"
管理ノードの設定ファイルの resource: の行に ngpus を追加
$ sudo vi /var/spool/pbs/sched_priv/sched_config resources: "ncpus, mem, arch, host, vnode, aoe, eoe, ngpus"
GPU の数の設定
$ sudo /opt/pbs/bin/qmgr -c "set node ncsv1 resources_available.ngpus=1" $ sudo /opt/pbs/bin/qmgr -c "set node ncsv2 resources_available.ngpus=3" $ sudo /opt/pbs/bin/qmgr -c "set node ncsv3 resources_available.ngpus=3"
登録内容の確認. ngpus の項目が増えていることがわかる.
$ pbsnodes -a ncsv1 Mom = ncsv1.matsue-ct.jp ntype = PBS state = free pcpus = 256 resources_available.arch = linux resources_available.host = ncsv1 resources_available.mem = 792503920kb resources_available.ncpus = 256 resources_available.ngpus = 1 <===== 注目! resources_available.vnode = ncsv1 resources_assigned.accelerator_memory = 0kb resources_assigned.hbmem = 0kb resources_assigned.mem = 0kb resources_assigned.naccelerators = 0 resources_assigned.ncpus = 0 resources_assigned.vmem = 0kb resv_enable = True sharing = default_shared license = l last_state_change_time = Thu Dec 10 00:08:24 2020 last_used_time = Wed Dec 9 23:31:10 2020 ...(以下略)...
ジョブを投入してみる.
$ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv1:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv1:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv1:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv2:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv2:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv2:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv2:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv2:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv3:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv3:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv3:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv3:ngpus=1 $ echo 'sleep 120; nvidia-smi' | qsub -l select=host=ncsv3:ngpus=1 $ qstat -s ncsv4: Req'd Req'd Elap Job ID Username Queue Jobname SessID NDS TSK Memory Time S Time --------------- -------- -------- ---------- ------ --- --- ------ ----- - ----- 3.ncsv4 sugiyama debug STDIN 239666 1 1 -- 00:10 R 00:00 Job run at Sat Feb 27 at 13:13 on (ncsv1:ngpus=1:ncpus=1) 4.ncsv4 sugiyama debug STDIN -- 1 1 -- 00:10 Q -- Not Running: Insufficient amount of resource: ngpus (R: 1 A: 0 T: 7) 5.ncsv4 sugiyama debug STDIN -- 1 1 -- 00:10 Q -- Not Running: Insufficient amount of resource: ngpus (R: 1 A: 0 T: 7) 6.ncsv4 sugiyama debug STDIN 20408 1 1 -- 00:10 R 00:00 Job run at Sat Feb 27 at 13:13 on (ncsv2:ngpus=1:ncpus=1) 7.ncsv4 sugiyama debug STDIN 20417 1 1 -- 00:10 R 00:00 Job run at Sat Feb 27 at 13:13 on (ncsv2:ngpus=1:ncpus=1) 8.ncsv4 sugiyama debug STDIN 20426 1 1 -- 00:10 R 00:00 Job run at Sat Feb 27 at 13:13 on (ncsv2:ngpus=1:ncpus=1) 9.ncsv4 sugiyama debug STDIN -- 1 1 -- 00:10 Q -- Not Running: Insufficient amount of resource: ngpus (R: 1 A: 0 T: 7) 10.ncsv4 sugiyama debug STDIN 16641 1 1 -- 00:10 R 00:00 Job run at Sat Feb 27 at 13:13 on (ncsv3:ngpus=1:ncpus=1) 11.ncsv4 sugiyama debug STDIN 16650 1 1 -- 00:10 R 00:00 Job run at Sat Feb 27 at 13:13 on (ncsv3:ngpus=1:ncpus=1) 12.ncsv4 sugiyama debug STDIN 16659 1 1 -- 00:10 R 00:00 Job run at Sat Feb 27 at 13:13 on (ncsv3:ngpus=1:ncpus=1) 13.ncsv4 sugiyama debug STDIN -- 1 1 -- 00:10 Q -- Not Running: Insufficient amount of resource: ngpus (R: 1 A: 0 T: 7)
実行結果をみると, GPU 1 本しか指定していないのに, GPU 3 本が全部見えている.
$ cat STDIN.o13 Sat Jan 9 17:45:42 2021 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 460.27.04 Driver Version: 460.27.04 CUDA Version: 11.2 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 Tesla V100S-PCI... On | 00000000:3B:00.0 Off | 0 | | N/A 39C P0 26W / 250W | 0MiB / 32510MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ | 1 Tesla V100S-PCI... On | 00000000:86:00.0 Off | 0 | | N/A 40C P0 27W / 250W | 0MiB / 32510MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ | 2 Tesla V100S-PCI... On | 00000000:AF:00.0 Off | 0 | | N/A 40C P0 27W / 250W | 0MiB / 32510MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
cgroups用hookの設定 (cgroupsによるGPUリソースの分離)
PBSProにおいてcgroupsの設定は,ジョブ実行時のhookでpythonスクリプトを実行して実現している. そのPythonスクリプトの設定ファイルを編集するために,まずは現在の設定をpbs_cgroups.json というファイルにエクスポートする.
$ sudo /opt/pbs/bin/qmgr -c "export hook pbs_cgroups application/x-config default" > pbs_cgroups.json
設定の変更が, 以下のように修正する.
- devices の enabled をtrueに変更 (cgroupによるデバイスのアクセス制限を有効化)
- devices の allow にnvidia-uvm等のデバイスを追加 (nvidia-docker関連のデバイスは常にアクセスを許可する)
- memory のデフォルト値を 20GB に. リザーブを 5GB に.
device の書き方は以下のようになっている. 実際に ls -l してみると nvidia 関連は 195 になっている. <URL:https://www.altairjp.co.jp/pdfs/pbsworks/PBSAdminGuide2020.1.pdf> 参照.
p.578-579 The allow parameter specifies how access to devices will be controlled. The list consists of entries in one of the follow- ing formats: • A single string entry, used verbatim. For example: • “b *:* rwm” allows full access (read, write, and mknod) to all block devices • “c *:* rwm” allows full access to all character devices with that major number. • If ls /dev/nvidiactl reported “crw-rw-rw- 1 root root 284, 1 Mar 30 14:50 nvidiactl” then the line added to the allow file looks like “c 284:* rwm” p.589-590 15.5.5.1.ii Isolating NVIDIA GPUs For NVIDIA GPU isolation to work, you need to restrict access to only those devices assigned to the job. In the “allow” subsection of the devices stion of the configuration file, do not use the broad “c *:* rwm”. Make sure that the “allow” section excludes read and write access for the 195 major number (“c 195:* m”), which is what all NVIDIA devices use. Preserve mknod (“m”) access, since other software such as the container hook may need “m” access.
エクスポートしたファイルを以下のように修正する. <URL:https://www.altairjp.co.jp/pdfs/pbsworks/PBSAdminGuide2020.1.pdf> p.590 の記述に従うが, “b *:* m”, “c *:* m”, が入っているとうまくいかなかったので, そこは削除する. また, キャラクタデバイスの 136 は本システムにないので削除しても良さそうな気がするが, とりあえず残しておいた.
$ sudo vi pbs_cgroups.json ...(略)... "devices" : { "enabled" : true, "exclude_hosts" : [], "exclude_vntypes" : [], "allow" : [ "c 195:* m", "c 136:* 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"] ] }, ...(略)... "memory" : { "enabled" : true, "exclude_hosts" : [], "exclude_vntypes" : [], "soft_limit" : false, "default" : "50GB", "reserve_percent" : 0, "reserve_amount" : "32GB" (PBS の使わないメモリ量) }, ...(略)...
作成した設定ファイル pbs_cgroups.json をPBSProにインポートする.
$ sudo /opt/pbs/bin/qmgr -c "import hook pbs_cgroups application/x-config default pbs_cgroups.json"
cgroups のためのhookを有効化
$ sudo /opt/pbs/bin/qmgr -c "set hook pbs_cgroups enabled = true"
PBSを再起動し,設定を反映させる.
$ sudo /etc/init.d/pbs restart
cgroups による制限のテスト
$ cd /work/jxxxx
1 GPU を用いて実行
$ echo 'hostname; echo CUDA_VISIBLE_DEVICES=$CUDA_VISIBLE_DEVICES; nvidia-smi ' | qsub -l select=1:host=ncsv1:ngpus=1 -N test1 $ echo 'hostname; echo CUDA_VISIBLE_DEVICES=$CUDA_VISIBLE_DEVICES; nvidia-smi ' | qsub -l select=1:host=ncsv2:ngpus=1 -N test2 $ echo 'hostname; echo CUDA_VISIBLE_DEVICES=$CUDA_VISIBLE_DEVICES; nvidia-smi ' | qsub -l select=1:host=ncsv3:ngpus=1 -N test3 $ cat test3.o16 ncsv3 CUDA_VISIBLE_DEVICES=GPU-a478fcef-90a8-f595-6260-85b310526d6d Sat Feb 27 13:22:15 2021 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 Tesla V100S-PCI... On | 00000000:AF:00.0 Off | 0 | | N/A 41C P0 27W / 250W | 0MiB / 32510MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
2 GPU を用いて実行
$ echo 'hostname; echo CUDA_VISIBLE_DEVICES=$CUDA_VISIBLE_DEVICES; nvidia-smi ' | qsub -l select=1:host=ncsv2:ngpus=2 -N test $ cat test.o17 ncsv2 CUDA_VISIBLE_DEVICES=GPU-c6d14151-65dd-a54b-accb-7419b3a7a457,GPU-c0cf94f2-e63f-2c04-f286-43b7d3cd746f Sat Feb 27 13:24:07 2021 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 Tesla V100S-PCI... On | 00000000:3B:00.0 Off | 0 | | N/A 37C P0 25W / 250W | 0MiB / 32510MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ | 1 Tesla V100S-PCI... On | 00000000:AF:00.0 Off | 0 | | N/A 37C P0 28W / 250W | 0MiB / 32510MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| | No running processes found | +-----------------------------------------------------------------------------+
docker からの利用. 前もってジョブを実行するユーザを計算ノードの docker グループに加えておく必要がある.
計算ノード$ sudo usermod -aG docker sugiyama
PBS では GPU 数を 1 に制限し, docker では特に GPU 数に制限をかけないで実行してみる. cgroups でうまく docker に制限をかけられていないことがわかる.
$ echo 'sleep 30; docker run --gpus all --rm nvidia/cuda nvidia-smi -L' | qsub -l select=1:host=ncsv3:ngpus=1 $ cat STDIN.o46 GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-d19054e2-f863-3da6-c30b-f299bb053a27) GPU 1: Tesla V100S-PCIE-32GB (UUID: GPU-cf4c7b4a-6a73-1407-4d80-c5a8000eca26) GPU 2: Tesla V100S-PCIE-32GB (UUID: GPU-a478fcef-90a8-f595-6260-85b310526d6d)
なお,計算ノードにインストールされていない docker イメージを指定すると, 計算ノードが自動でそのイメージをインストールする.
$ cat STDIN.e46 Unable to find image 'nvidia/cuda:latest' locally latest: Pulling from nvidia/cuda da7391352a9b: Pulling fs layer ...(以下略)...
- 注) PBS から docker を利用する方法として, PBS で docker のコンテナエンジンを使う設定を行う方法もあるらしい. <URL:https://www.altairjp.co.jp/pdfs/pbsworks/PBSAdminGuide2020.1.pdf> の p.597 の 16 章を参照のこと.
docker での GPU 制限
<URL:https://github.com/puyogo-suzuki/gpudocker-inside-batchsys> を利用する (Thanks to Suzuki-kun).
元々のパスを確認
$ which docker /usr/bin/docker
各ノードで以下を実行する.
$ wget https://raw.githubusercontent.com/puyogo-suzuki/gpudocker-inside-batchsys/main/docker.sh $ sudo mv docker.sh /usr/local/bin/docker $ sudo chmod 755 /usr/local/bin/docker
パスが正しく設定されているか確認する.
$ which docker /usr/local/bin/docker
但し, /usr/local/bin/docker の 54 行目はフルパス (/usr/bin/docker) に書き換えた.
実際に試してみる. GPU 数に制限がかかっていることがわかる.
$ echo 'hostname; docker run --gpus all --rm nvidia/cuda nvidia-smi -L' | qsub -l select=1:host=ncsv2:ngpus=119.ncsv4 $ echo 'hostname; docker run --gpus all --rm nvidia/cuda nvidia-smi -L' | qsub -l select=1:host=ncsv3:ngpus=120.ncsv4 $ echo 'hostname; docker run --gpus all --rm nvidia/cuda nvidia-smi -L' | qsub -l select=1:host=ncsv3:ngpus=2 $ cat STDIN.o19 ncsv2 GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-c0cf94f2-e63f-2c04-f286-43b7d3cd746f) $ cat STDIN.o20 ncsv3 GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-d19054e2-f863-3da6-c30b-f299bb053a27) $ cat STDIN.o21 ncsv3 GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-d19054e2-f863-3da6-c30b-f299bb053a27) GPU 1: Tesla V100S-PCIE-32GB (UUID: GPU-cf4c7b4a-6a73-1407-4d80-c5a8000eca26)
queue の追加設定
デフォルトのキューを削除.
# /opt/pbs/bin/qmgr -c "delete queue workq"
CPU メイン (GPU なし) のキューの作成
# /opt/pbs/bin/qmgr -c "create queue cpu queue_type=execution" # /opt/pbs/bin/qmgr -c "set queue cpu enabled=True" # /opt/pbs/bin/qmgr -c "set queue cpu priority=30" # /opt/pbs/bin/qmgr -c "set queue cpu resources_default.nodes=1" # /opt/pbs/bin/qmgr -c "set queue cpu resources_default.ncpus=1" # /opt/pbs/bin/qmgr -c "set queue cpu resources_default.ngpus=0" # /opt/pbs/bin/qmgr -c "set queue cpu resources_default.walltime=72:00:00" # /opt/pbs/bin/qmgr -c "set queue cpu resources_max.nodes=1" # /opt/pbs/bin/qmgr -c "set queue cpu resources_max.ncpus=64" # /opt/pbs/bin/qmgr -c "set queue cpu resources_max.ngpus=0" # /opt/pbs/bin/qmgr -c "set queue cpu max_group_run=2" # /opt/pbs/bin/qmgr -c "set queue cpu started=True" # /opt/pbs/bin/qmgr -c "set queue cpu resources_default.mem=100gb"
GPU 利用のキューの作成
# /opt/pbs/bin/qmgr -c "create queue gpu queue_type=execution" # /opt/pbs/bin/qmgr -c "set queue gpu enabled=True" # /opt/pbs/bin/qmgr -c "set queue gpu priority=30" # /opt/pbs/bin/qmgr -c "set queue gpu resources_default.nodes=1" # /opt/pbs/bin/qmgr -c "set queue gpu resources_default.ncpus=1" # /opt/pbs/bin/qmgr -c "set queue gpu resources_default.ngpus=1" # /opt/pbs/bin/qmgr -c "set queue gpu resources_max.nodes=1" # /opt/pbs/bin/qmgr -c "set queue gpu resources_max.ncpus=6" # /opt/pbs/bin/qmgr -c "set queue gpu resources_max.ngpus=1" # /opt/pbs/bin/qmgr -c "set queue gpu resources_default.walltime=72:00:00" # /opt/pbs/bin/qmgr -c "set queue gpu max_group_run=3" # /opt/pbs/bin/qmgr -c "set queue gpu started=True" # /opt/pbs/bin/qmgr -c "set queue gpu resources_default.mem=50gb"
確認
$ /opt/pbs/bin/qmgr -c "p s" # /opt/pbs/bin/qmgr -c "p s" # # Create resources and set their properties. # # # Create and define resource ngpus # create resource ngpus set resource ngpus type = long set resource ngpus flag = hn # # Create queues and set their attributes. # # # Create and define queue debug # create queue debug set queue debug queue_type = Execution set queue debug Priority = 50 set queue debug resources_default.ncpus = 1 set queue debug resources_default.nodect = 1 set queue debug resources_default.nodes = 1 set queue debug resources_default.walltime = 00:10:00 set queue debug enabled = True set queue debug started = True set queue debug started = True # # Create and define queue cpu # create queue cpu set queue cpu queue_type = Execution set queue cpu Priority = 30 set queue cpu resources_max.ncpus = 64 set queue cpu resources_max.ngpus = 0 set queue cpu resources_max.nodes = 1 set queue cpu resources_default.mem = 20gb set queue cpu resources_default.ncpus = 1 set queue cpu resources_default.ngpus = 0 set queue cpu resources_default.nodect = 1 set queue cpu resources_default.nodes = 1 set queue cpu resources_default.walltime = 48:00:00 set queue cpu max_group_run = 2 set queue cpu enabled = True set queue cpu started = True # # Create and define queue gpu # create queue gpu set queue gpu queue_type = Execution set queue gpu Priority = 30 set queue gpu resources_max.ncpus = 6 set queue gpu resources_max.ngpus = 1 set queue gpu resources_max.nodes = 1 set queue gpu resources_default.mem = 20gb set queue gpu resources_default.ncpus = 1 set queue gpu resources_default.ngpus = 1 set queue gpu resources_default.nodect = 1 set queue gpu resources_default.nodes = 1 set queue gpu resources_default.walltime = 48:00:00 set queue gpu max_group_run = 3 set queue gpu enabled = True set queue gpu started = True # # Set server attributes. # set server scheduling = True set server acl_hosts = ncsv1 set server default_queue = debug set server log_events = 511 set server mailer = /usr/sbin/sendmail set server mail_from = adm set server query_other_jobs = True set server resources_default.ncpus = 1 set server default_chunk.ncpus = 1 set server scheduler_iteration = 600 set server node_pack = True set server resv_enable = True set server node_fail_requeue = 310 set server max_array_size = 10000 set server pbs_license_min = 0 set server pbs_license_max = 2147483647 set server pbs_license_linger_time = 31536000 set server eligible_time_enable = False set server max_concurrent_provision = 5 set server max_job_sequence_id = 9999999 # /opt/pbs/bin/pbsnodes -aS vnode state OS hardware host queue mem ncpus nmics ngpus comment --------------- --------------- -------- -------- --------------- ---------- -------- ------- ------- ------- --------- ncsv1 free -- -- ncsv1 -- 756gb 128 0 1 -- ncsv2 free -- -- ncsv2 -- 251gb 16 0 3 -- ncsv3 free -- -- ncsv3 -- 251gb 16 0 3 -- # /opt/pbs/bin/qstat -Qf Queue: debug queue_type = Execution Priority = 50 total_jobs = 0 state_count = Transit:0 Queued:0 Held:0 Waiting:0 Running:0 Exiting:0 Begun :0 resources_default.ncpus = 1 resources_default.nodect = 1 resources_default.nodes = 1 resources_default.walltime = 00:10:00 resources_assigned.ncpus = 0 resources_assigned.nodect = 0 enabled = True started = True Queue: cpu queue_type = Execution Priority = 30 total_jobs = 0 state_count = Transit:0 Queued:0 Held:0 Waiting:0 Running:0 Exiting:0 Begun :0 resources_max.ncpus = 64 resources_max.ngpus = 0 resources_max.nodes = 1 resources_default.mem = 100gb resources_default.ncpus = 1 resources_default.ngpus = 0 resources_default.nodect = 1 resources_default.nodes = 1 resources_default.walltime = 72:00:00 max_group_run = 2 enabled = True started = True Queue: gpu queue_type = Execution Priority = 30 total_jobs = 0 state_count = Transit:0 Queued:0 Held:0 Waiting:0 Running:0 Exiting:0 Begun :0 resources_max.ncpus = 6 resources_max.ngpus = 1 resources_max.nodes = 1 resources_default.mem = 50gb resources_default.ncpus = 1 resources_default.ngpus = 1 resources_default.nodect = 1 resources_default.nodes = 1 resources_default.walltime = 72:00:00 max_group_run = 3 enabled = True started = True
ジョブのテスト (C, Fortran)
以下で使うプログラムとスクリプトは /work/SAMPLES/CPU に置いてある.
C + MPI
$ vi c_mpi-hello.c #include "mpi.h" #include <stdio.h> int main(int argc, char **argv) { int n, myid, numprocs, i; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid); printf ("Hello World %d \n", myid); MPI_Finalize(); }
ノード数を select に, 全 CPU コアを ncpus に, MPI の並列数を mpiprocs に指定する. ncpus = mpiprocs にすること.
$ vi c_mpi-hello.sh #!/bin/sh #PBS -q cpu #PBS -l select=1:ncpus=8:mpiprocs=8 cd $PBS_O_WORKDIR mpicc -o c_mpi-hello c_mpi-hello.c mpirun ./c_mpi-hello
実行と確認
$ qsub c_mpi-hello.sh $ cat c_mpi-hello.sh.o52 Hello World 6 Hello World 0 Hello World 8 Hello World 5 Hello World 9 Hello World 4 Hello World 1 Hello World 2 Hello World 3 Hello World 7
Fortran + MPI
$ vi mpi-hello.f90 program sample00 use mpi implicit none integer :: myrank, numprocs, ierr call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD, numprocs, ierr) print *, repeat('#',myrank+1) call MPI_FINALIZE(ierr) end program sample00
ノード数を select に, 全 CPU コア数を ncpus に, MPI の並列数を mpiprocs に指定する. ncpus = mpiprocs にすること.
$ vi mpi-hello.sh #!/bin/sh #PBS -q cpu #PBS -l select=1:ncpus=8:mpiprocs=8 cd $PBS_O_WORKDIR mpif90 -o mpi-hello mpi-hello.f90 mpirun ./mpi-hello
実行と確認.
$ qsub mpi-hello.sh $ cat mpi-hello.sh.o53 # ## ### #### #####
C + OpenMP
$ cat c_omp-hello.c #include <stdio.h> #include <omp.h> int main() { #pragma omp parallel { printf("Hello World from %d of %d\n", omp_get_thread_num(), omp_get_num_threads()); } }
ノード数を select に, 全 CPU コア数を ncpus に, OMP の並列数を ompthreads に指定する. ncpus = ompthreads にすること.
$ vi c_omp-hello.sh #!/bin/sh #PBS -q cpu #PBS -l select=1:ncpus=8:ompthreads=8 cd $PBS_O_WORKDIR gcc -fopenmp -o c_omp-hello c_omp-hello.c ./c_omp-hello
実行と確認.
$ qsub c_omp-hello.sh $ cat c_omp-hello.sh.o59 Hello World from 6 of 10 Hello World from 0 of 10 Hello World from 9 of 10 Hello World from 7 of 10 Hello World from 3 of 10 Hello World from 1 of 10 Hello World from 4 of 10 Hello World from 8 of 10 Hello World from 2 of 10 Hello World from 5 of 10
Fortran + OpenMP
$ cat omp-hello.f90 program helloOpenMP !$ use omp_lib implicit none print *, "START" !$omp parallel print *, "Hello! N =", omp_get_num_threads(), " and I am ", omp_get_thread_num() !$omp end parallel print *, "END" end
ノード数を select に, 全 CPU コア数を ncpus に, OMP の並列数を ompthreads に指定する. ncpus = ompthreads にすること.
$ cat omp-hello.sh #!/bin/sh #PBS -q cpu #PBS -l select=1:ncpus=8:ompthreads=8 cd $PBS_O_WORKDIR gfortran -fopenmp -o omp-hello omp-hello.f90 ./omp-hello
実行と確認
$ qsub omphello.sh $ cat omphello.sh.o57 START Hello! N = 10 and I am 0 Hello! N = 10 and I am 5 Hello! N = 10 and I am 8 Hello! N = 10 and I am 9 Hello! N = 10 and I am 4 Hello! N = 10 and I am 7 Hello! N = 10 and I am 3 Hello! N = 10 and I am 6 Hello! N = 10 and I am 2 Hello! N = 10 and I am 1 END
C + MPI + OpenMP
$ cat c_mpi-omp-hello.f90 #include <stdio.h> #include <mpi.h> #include <omp.h> int main(int argc, char *argv[]) { int numprocs, rank, namelen; char processor_name[MPI_MAX_PROCESSOR_NAME]; int iam = 0, np = 1; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Get_processor_name(processor_name, &namelen); //omp_set_num_threads(4); #pragma omp parallel default(shared) private(iam, np) { np = omp_get_num_threads(); iam = omp_get_thread_num(); printf("Hello from thread %d out of %d from process %d out of %d on %s\n", iam, np, rank, numprocs, processor_name); } MPI_Finalize(); }
ノード数を select に, 全 CPU コア数を ncpus に, MPI の並列数を mpiprocs に, OMP の並列数を ompthreads に指定する. ncpus = mpiprocs * ompthreads にすること.
$ cat c_mpi-omp-hello.sh #!/bin/sh #PBS -q cpu #PBS -l select=1:ncpus=8:mpiprocs=4:ompthreads=2 cd $PBS_O_WORKDIR mpicc -fopenmp -o c_mpi-omp-hello c_mpi-omp-hello.c mpirun ./c_mpi-omp-hello
実行と確認
$ qsub c_mpi-omp-hello.sh $ cat c_mpi-omp-hello.sh.o124 Hello from thread 0 out of 2 from process 0 out of 4 on ncsv1 Hello from thread 1 out of 2 from process 0 out of 4 on ncsv1 Hello from thread 0 out of 2 from process 1 out of 4 on ncsv1 Hello from thread 1 out of 2 from process 1 out of 4 on ncsv1 Hello from thread 0 out of 2 from process 3 out of 4 on ncsv1 Hello from thread 1 out of 2 from process 3 out of 4 on ncsv1 Hello from thread 0 out of 2 from process 2 out of 4 on ncsv1 Hello from thread 1 out of 2 from process 2 out of 4 on ncsv1
テスト: venv 環境
以下のようなスクリプトを用意する.
#!/bin/sh #PBS -q gpu #PBS -l select=1:ncpus=1:ngpus=1 cd $PBS_O_WORKDIR hostname . venv-chainer/venv/bin/activate nvidia-smi -L python chainer-sample.py -g 0 deactivate
実行する. 別の端末で nvidia-smi を実行すると, GPU で実行されていることが確認できる.
$ qsub venv-chainer.sh
結果の表示
$ cat venv-chainer.sh.o80 ncsv1 GPU 0: Tesla V100S-PCIE-32GB (UUID: GPU-8a30728d-e5e5-a945-aeeb-410b8dd12855) Device: @cupy:0 # unit: 1000 # Minibatch-size: 100 # epoch: 20 epoch main/loss validation/main/loss main/accuracy validation/main/accuracy elapsed_time 0 2.30979 0.106 0.93721 1 0.190622 0.100971 0.942067 0.9689 3.24492 2 0.0728783 0.076452 0.977199 0.977 5.40519 ...(以下略)...
テスト : docker 環境
以下のようなスクリプトを用意する.
#!/bin/sh #PBS -q gpu #PBS -l select=1:ncpus=1:ngpus=1 cd $PBS_O_WORKDIR docker image build -t chainer/sugiyama mydocker docker run --gpus all -v $PWD:/tmp -w /tmp --rm chainer/sugiyama python3 chainer-sample.py -g 0
実行する. 別の端末で nvidia-smi を実行すると, GPU で実行されていることが確認できる.
$ qsub mydocker.sh
結果の表示
$ cat mydocker.sh.o81 Sending build context to Docker daemon 2.048kB Step 1/2 : FROM chainer/chainer ---> 2c0563bd9e2b Step 2/2 : RUN pip3 install matplotlib ---> Running in 01f3df21f1bd Collecting matplotlib ...(略)... Device: @cupy:0 # unit: 1000 # Minibatch-size: 100 # epoch: 20 epoch main/loss validation/main/loss main/accuracy validation/main/accuracy elapsed_time 0 2.30979 0.106 0.93721 1 0.190622 0.100971 0.942067 0.9689 3.24492 2 0.0728783 0.076452 0.977199 0.977 5.40519 ...(以下略)...
docker は内部では root 権限で動いているようで, ファイルやディレクトリを作成すると 所有者が root になってしまう. とりあえずの対処法としては, プログラム中で umask 002 する (group に write 権限をつける) と簡単かもしれない.
...(略)... import os ...(略)... os.umask(0o002) ...(略)...
覚書
現在は使っていないが使うと良さそうな設定
各キューを実行できるホストを登録する. 設定すると, 当該キューは設定されたホストでしか実行できなくなる.
# /opt/pbs/bin/qmgr -c "set node ncsv2 queue = gpu" # /opt/pbs/bin/qmgr -c "set node ncsv3 queue = gpu" # /opt/pbs/bin/qmgr -c "set node ncsv4 queue = gpu"
キューの実行数の制限
# qmgr -c "set queue QNAME max_running = 10"
各キューについてユーザの実行可能数を制限
# qmgr -c "set queue QNAME max_user_run = 3"
各キューについてユーザの実行可能数な制限を解除
# qmgr -c "unset queue QNAME max_user_run
テスト (メールの送信)
以下のように -M, -m オプションをつけると, 実行開始時・終了時・何らかのエラーの時, にメールを送ってくれる. 但し, 学内宛のメールしか出せない (おそらく上流で 25 ポートが開いていない).
$ cat mpi-hello.sh #!/bin/sh #PBS -q debug #PBS -M XXXX@matsue-ct.jp #PBS -m abe #PBS -l select=1:ncpus=5:ngpus=0:host=ncsv3 cd $PBS_O_WORKDIR mpiexec -launcher fork -n 5 ./mpihello
CPU の制限?
- ncpus = mpiprocs * ompthreads であることが保証されていない?
- CPU コア数は PBS で適切に管理されている? どうやって確認するかな?
参考
- <URL:https://qiita.com/MasafumiTsuyuki/items/acf4b19b54937496e32b>
- <URL:https://qiita.com/MasafumiTsuyuki/items/a3674c2654fc50477d0b>
- <URL:https://web.chaperone.jp/w/index.php?OpenPBS/GPU>
- <URL:https://web.chaperone.jp/w/index.php?OpenPBS>
- <URL:https://www.altairjp.co.jp/pdfs/pbsworks/PBSAdminGuide2020.1.pdf>
- <URL:https://ccportal.ims.ac.jp/QuickStart>