Table of Contents
概要
- 一人でクラスタ計算機を使用する場合は問題ありませんが、もし複数人で使用する場合は、プログラムの実行が同じノードでかち合ってしまう可能性があります。
- これを避けるため、各ユーザーのプログラムの実行を管理するジョブ管理ソフト PBS Professional (PBS Pro) を使用します
- もちろん、一人でクラスタ計算機を利用する場合でも、複数のジョブの実行を管理してくれるので非常に便利です
- PBS ProはGitHubにて公開されています
- 2020年より無償版はOpenPBSに名称変更になりました。
環境
- Ubuntu 20.04 LTS
- 管理ノードと計算ノードで、OSはバージョンも含めて同一のものを使用してください
構成
PBS Proによるジョブ管理システムは、次のコンポーネントより構成されます
コンポーネント名 | 識別子 | 役割 |
---|---|---|
Server | pbs_server | ユーザーからジョブの投入や取り消しなどのコマンドを受け付けます |
Scheduler | pbs_sched | ジョブの実行開始や終了のタイミング、どのノードで実行するか、などを管理します |
Communication daemon | pbs_comm | ノード間の通信を仲介します |
Job Executor | pbs_mom | ジョブを実行します。momは Machine Oriented Mini-server の略で、全ての実行中のジョブの母親という意味も込められています |
- 上の3つはまとめてフロントエンド (front end) と呼ばれ、同じノード(今回のクラスタ計算機では管理ノード)にまとめるのが普通です。
- ジョブ・エグゼキュータは計算ノードで動かします。
- ジョブのコマンドは計算ノードのある1つに送られて、そこで実行されます。この計算ノードをMother superiorノードと呼びます。
- 他の計算ノードはSisterノードと呼ばれます。Mother superiorノードは(自分を含めた)計算ノードにMPI並列計算のプロセスを割り振ります。
PBSの設置
以下ではNFSサーバによって、管理ノードの
- /home
- /opt
が計算ノードと共有されているとします。 また、hostsファイルはNISによって共有されているとします。
準備
hostsファイルの編集
管理ノードで行います
- /etc/hosts に、管理ノードと計算ノードのプライベートLAN内におけるIPアドレスとホスト名を登録します
$ sudo vi /etc/hosts
- hosts
127.0.0.1 localhost 127.0.0.1 kanri 192.168.0.1 kanri 192.168.0.11 keisan11 192.168.0.12 keisan12 192.168.0.13 keisan13 (以下略)
- Ubuntuでは自己参照アドレスに127.0.1.1が割り当てられていますが、このままだと後述のQmgrがなぜか編集できなくなるので変更します。
- NISの情報を更新します
$ sudo make -C /var/yp
必要なパッケージのインストール
管理ノードと計算ノードのそれぞれで、アップデートと(必要ならば)再起動を行います
$ sudo apt update $ sudo apt upgrade $ sudo reboot
PBS Proには次のパッケージが必要です。
- PBS Proのコンパイルに必要なもの(管理ノードにインストール)
$ sudo apt 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 Proの実行に必要なもの(管理ノードと計算ノードの両方にインストール)
$ sudo apt install expat libedit2 postgresql python3 postgresql-contrib sendmail-bin tcl tk libical3 postgresql-server-dev-all libhwloc-dev # OpenPBS v20 $ sudo apt install expat libedit2 postgresql python3 postgresql-contrib sendmail-bin tcl tk libical3 postgresql-server-dev-all # PBS Pro v19
- 必要なパッケージはOSのバージョンによるので、必ず https://github.com/PBSPro/pbspro/blob/master/INSTALL をチェックしてください。
管理ノードでの作業
ここでは /opt/pbs/ にPBS Proを設置することにします。
- GitHubのPBS Proの配布ページから最新版のソースコードをダウンロードします
$ sudo apt install git $ git clone https://github.com/openpbs/openpbs.git $ cd openpbs
- プログラムをコンパイルします
$ ./autogen.sh $ ./configure -prefix=/opt/pbs $ make
- 現在のバージョン(pbs20.0.0)ではPythonのバージョンが3.5であることを要求してくるので、configureで文句を言われたときはpyenvなどを使って変更してください。
- PBSのインストールを完了させます
$ sudo make install $ sudo /opt/pbs/libexec/pbs_postinstall
- (Ubuntu20.04 & pbs20.0.0) pbs_postinstallの際に“update-rc.d: error: no runlevel symlinks to modify, aborting!”と出てきたら自動起動の設定に失敗しています。手動で次のようにしてください
$ sudo update-rc.d pbs defaults
- 設定ファイルで PBS_START_SERVER, PBS_START_SCHED, PBS_START_COMM をすべて1にして、このノードがフロントエンドであることを設定します。
$ sudo vi /etc/pbs.conf
- pbs.conf
PBS_SERVER=kanri 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
- 必要な実行権限を付与します
$ sudo chmod 4755 /opt/pbs/sbin/pbs_iff /opt/pbs/sbin/pbs_rcp
- PBSを起動します
$ sudo /etc/init.d/pbs start
- 環境変数を読み込む設定をします。すべてのユーザーがPBSを使えるように /etc/bash.bashrcを編集します
$ sudo vim /etc/bash.bashrc
- bash.bashrc
(略) . /etc/profile.d/pbs.sh
- いったんログアウトして、再ログインします
計算ノードでの作業
- 計算ノードでPBSのインストールを完了させます
$ sudo /opt/pbs/libexec/pbs_postinstall
- (Ubuntu20.04 & pbs20.0.0) pbs_postinstallの際に“update-rc.d: error: no runlevel symlinks to modify, aborting!”と出てきたら自動起動の設定に失敗しています。手動で次のようにしてください
$ sudo update-rc.d pbs defaults
- 設定ファイルで PBS_START_MOM=1 とすることで、このノードが計算ノードであることを指定します。またPBSサーバのホスト名を PBS_SERVER で設定します。
$ sudo vi /etc/pbs.conf
- pbs.conf
PBS_SERVER=kanri 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
- 計算ノードでもPBSを起動します
$ sudo /etc/init.d/pbs start
計算ノードでの作業はこれで終わりですので、ログアウトして構いません。
動作確認
すべて管理ノードで作業します
Qmgr
QmgrはPBSの設定を管理するソフトで、操作には管理者権限が必要です。 このページでは必ず設定が必要なものだけを紹介します。
Qmgrは次のようにして起動します。
$ sudo -i qmgr
現在どのような設定がされているかは次のようにして確認します
Qmgr: print server
- ちなみに全部入力しなくても、頭文字だけで “p s” とするだけでも表示されます
Qmgrを終了するにはqあるいはexitと入力します
Qmgr: q
また、Qmgr用のプロンプトを起動せずに操作することもできます
$ sudo -i qmgr -c "print server"
ユーザーの登録
計算ノードからでもPBSが使えるようにします
Qmgr: set server flatuid = True
qstatコマンドで他のユーザーのジョブの実行状況が見えるようにします
Qmgr: set server query_other_jobs = True
計算ノードの登録
計算ノードのホスト名を入力します
Qmgr: create node keisan11 Qmgr: create node keisan12 ...
ノードあたりに使用できる最大スレッド数も指定できます(ここでは24コア)。
Qmgr: set node keisan11 resources_available.ncpus=24 Qmgr: set node keisan12 resources_available.ncpus=24 ...
ノードの設定状況も確認できます
Qmgr: print node keisan11 # # Create nodes and set their properties. # # # Create and define node yagami11 # create node yagami11 set node keisan11 state = free set node keisan11 resources_available.arch = linux set node keisan11 resources_available.host = keisan11 set node keisan11 resources_available.mem = 131666992kb set node keisan11 resources_available.ncpus = 24 set node keisan11 resources_available.vnode = keisan11 set node keisan11 resv_enable = True
使わなくなったノードはdeleteで消せます
Qmgr: delete node keisan11
登録された計算ノードはpbsnodesコマンドを使って確認します
$ pbsnodes -a
- 計算ノードになんらかのトラブルがあって認識されていない場合は state = down と表示されます。管理ノードから計算ノードにSSHで正しく接続できるにも関わらずこのようなメッセージが出る場合は、計算ノードのPBSを再起動します
$ sudo /etc/init.d/pbs restart
ジョブの実行
試しに「60秒間何もしない」というジョブを投げてみます。 クラスタ計算機を使用するユーザーで管理ノードにログインしてください。 qsubはジョブを投入するコマンドです
$ echo 'sleep 60' | qsub
ジョブの現在の状態はqstatコマンドで確認できます
$ qstat -s kanri: Req'd Req'd Elap Job ID Username Queue Jobname SessID NDS TSK Memory Time S Time --------------- -------- -------- ---------- ------ --- --- ------ ----- - ----- 1.kanri sugimoto workq STDIN 9007 1 1 -- -- R 00:00 Job run at Tue Dec 03 at 04:56 on (keisan11:ncpus=1)
Sの列が状態を表し、Qだと実行待ち、Rだと実行中を意味します。 ジョブが計算ノードkeisan11で実行されていることがわかります。
ジョブを終了または削除したい場合は qdel を使います
$ qdel 1.kanri
- $ qdel 1 でも可
プログラムの実行
MPIの設置
- OpenMPI, MPICH2, Intel MPIなどのMPIライブラリを管理ノードの /usr/local や /opt などにインストールし、NFSによって各計算ノードに共有してください
ソースコード
実際にPBSを使ってクラスタ計算機にプログラムを投げてみます。 次のプログラムを使用します。
- test.c
#include <stdio.h> #include "mpi.h" int main( int argc, char *argv[] ) { int rank, size, len; char name[MPI_MAX_PROCESSOR_NAME]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Get_processor_name( name, &len ); name[len] = '\0'; printf( "Hello world: rank %d of %d running on %s\n", rank, size, name ); MPI_Finalize(); return 0; }
コンパイルは次のようにします。
$ mpicc -o hello hello.c $ mpiicc -o hello hello.c # Intel MPIを使用する場合
ジョブ投入用スクリプト
次のスクリプトを作成します。
- run.sh
#!/bin/bash #PBS -V #PBS -l select=2:ncpus=24:mpiprocs=24 cd $PBS_O_WORKDIR mpirun ./hello
- #PBS -V … 現在の環境を計算ノードでも引き継ぎます
- #PBS -l … 使用するリソースの量を指定します
- select … ノードの数。指定しなければ1になります
- ncpus … ノードあたりに確保するコアの数。指定しなければ1になります
- mpiprocs … ノードあたりのMPIプロセスの数。指定しなければMPI実行時に $ mpirun -n 48 ./hello とMPIプロセス数を明示する必要があります
- ジョブを受け付けたPBSサーバは、#PBSで始まる行を読み込んで設定を行ったのち、Mother superiorノードにシェルスクリプトを送ります
- シェルスクリプトを受け取ったMother superiorノードは、管理ノードのユーザ名と同じユーザ名のホームディレクトリで実行します。$PBS_O_WORKDIRには管理ノードで実行したときのディレクトリのパスが格納されているので、計算ノード内の同じ名前のディレクトリに移動します
- MPIのホストファイル(プログラムを実行するノードのホスト名が書かれたファイル)は、Mother superiorノードの $PBS_NODEFILE = /var/spool/pbs/aux/<Job ID> に生成されたものが使われます
実行権限を付与します。
$ chmod +x run.sh
ジョブを実行します
$ qsub run.sh 1.kanri
結果を見てみます
$ cat run.sh.o1 Hello world: rank 0 of 48 running on keisan11 Hello world: rank 1 of 48 running on keisan11 (略) Hello world: rank 23 of 48 running on keisan11 Hello world: rank 24 of 48 running on keisan12 Hello world: rank 25 of 48 running on keisan12 (略) Hello world: rank 47 of 48 running on keisan12
(追記:2023/01/25)
oneAPIをアップデートしたら、ノード間並列をするときにエラーが出るようになってしまいました。 (バージョン:Intel(R) MPI Library 2021.5 for Linux) 次のようにしてください。
- run.sh
#!/bin/bash #PBS -V #PBS -l select=2:ncpus=24:mpiprocs=24 cd $PBS_O_WORKDIR mpirun -bootstrap ssh ./hello
OpenMPを使用する場合
OpenMPのみ、あるいはMPI+OpenMPのハイブリッドで使用する場合は、次のようにOpenMPのスレッド数を指定してください
- run.sh
#!/bin/bash #PBS -V #PBS -l select=2:ncpus=24:mpiprocs=2:ompthreads=12 cd $PBS_O_WORKDIR mpirun ./hello
- ompthreadsはMPIの1プロセスあたりのOpenMPのスレッド数です
- 基本的には mpiprocs * ompthreads = ncpus となるようにします
Fairshare
複数のユーザーが同時に使用する場合に、うまく計算資源を割り当てる機能です。
ノードごとの負荷の分散
ジョブを投入したら、デフォルトでは1番目の計算ノードにジョブを埋めていき、その計算ノードのリソースが全て埋まってから次の計算ノードでジョブが走るようになります。 これを、各ノードの負荷を分散させるようにジョブが投入されるように変更します。
設定ファイル /var/spool/pbs/sched_priv/sched_config から node_sort_key を探して次のように変更します。
- 使用しているCPUのコア数が一番少ないノードにジョブを割り当てたい場合
- sched_config
node_sort_key: "ncpus LOW assigned" ALL
- 使用していないCPUのコア数が一番多いノードにジョブを割り当てたい場合
- sched_config
node_sort_key: "ncpus HIGH unused" ALL
(各計算ノードのコア数がすべて同じ場合は、どちらも同じ結果になります)
PBSを再起動します。
sudo /etc/init.d/pbs restart
- PBS Professional 2022.1 Administrator's Guide, Sec. 4.9.49
アンインストール
- (管理ノードのみ)計算ノードの情報を削除します
$ sudo -i qmgr -c "delete node @default"
- PBSを終了します
$ sudo /etc/init.d/pbs stop
- インストール時に設置されたファイルを削除します
$ sudo rm -f /etc/pbs.* $ sudo rm -f /etc/profile.d/pbs.* $ sudo rm -f /etc/rc*.d/*pbs $ sudo rm -f /etc/init.d/pbs $ sudo rm -rf /var/spool/pbs $ sudo rm -rf /opt/pbs/
PBS Proについて
Altair Engineering社が提供するジョブ管理ソフトです。もともとは有償でしたが、2016年にオープンソース化しました
参考
-
- 公式サイトです。必要な情報はここですべて手に入ります
-
- ラズベリーパイによるクラスターマシン作成方法です。OSがUbuntuと同じDebian系なのでそっくり参考になります。
-
- パッケージを作っておくと、たくさんの計算ノードにインストールするとき楽です。