====== 概要 ======
* 一人でクラスタ計算機を使用する場合は問題ありませんが、もし複数人で使用する場合は、プログラムの実行が同じノードでかち合ってしまう可能性があります。
* これを避けるため、各ユーザーのプログラムの実行を管理するジョブ管理ソフト PBS Professional (PBS Pro) を使用します
* もちろん、一人でクラスタ計算機を利用する場合でも、複数のジョブの実行を管理してくれるので非常に便利です
* PBS ProはGitHubにて公開されています
* https://github.com/PBSPro/pbspro
* 2020年より無償版はOpenPBSに名称変更になりました。
====== 環境 ======
* Ubuntu 26.04 LTS
* OpenPBS v23.06.06
* 管理ノードと計算ノードで、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も共有されているとします。
===== 準備 =====
==== SSHの設定 ====
パスフレーズ無しで計算ノードにSSHログインできるようにします。
PBSを使用する全ユーザーは、管理ノードで以下を実行してください。
$ ssh-keygen -N ""
$ cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys
$ echo "StrictHostKeyChecking no" >> ~/.ssh/config
==== hostsファイルの編集 ====
管理ノードと計算ノードで行います
* 192.168.0.1のホスト名と自己参照アドレス(localhost)127.0.1.1のホスト名が同じだとPBSが動かなくなるのでコメントアウトします。$ sudo nano /etc/hosts
127.0.0.1 localhost
#127.0.1.1 head
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
==== 必要なパッケージのインストール ====
管理ノードと計算ノードのそれぞれで、アップデートと(必要ならば)再起動を行います
$ sudo apt update
$ sudo apt upgrade
$ sudo reboot
OpenPBSには次のパッケージが必要です。
* OpenPBSのコンパイルに必要なもの(管理ノードにインストール)
$ 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 g++ libcjson-dev
* OpenPBSの実行に必要なもの(管理ノードと計算ノードの両方にインストール)
$ sudo apt install expat libedit2 postgresql python3 postgresql-contrib sendmail-bin tcl tk libical3 postgresql-server-dev-all libhwloc-dev libcjson-dev # OpenPBS v23
* 必要なパッケージはOSのバージョンによるので、必ず https://github.com/openpbs/openpbs/blob/master/INSTALL をチェックしてください。
===== 管理ノードでの作業 =====
ここでは /opt/pbs/ にOpenPBSを設置することにします。
- GitHubの[[https://github.com/openpbs/openpbs/|OpenPBSの配布ページ]]から最新版のソースコードをダウンロードします
$ sudo apt install git
$ git clone https://github.com/openpbs/openpbs.git
$ cd openpbs
- プログラムをコンパイルします
$ ./autogen.sh
$ ./configure -prefix=/opt/pbs
$ make
- PBSのインストールを完了させます
$ sudo make install
$ sudo /opt/pbs/libexec/pbs_postinstall
* (Ubuntu26.04 & pbs23.06.06) 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 nano /etc/pbs.conf
PBS_SERVER=head
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 nano /etc/bash.bashrc
(略)
. /etc/profile.d/pbs.sh
- いったんログアウトして、再ログインします
===== 計算ノードでの作業 =====
- 計算ノードでPBSのインストールを完了させます
$ sudo /opt/pbs/libexec/pbs_postinstall
* (Ubuntu26.04 & pbs23.06.06) 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 nano /etc/pbs.conf
PBS_SERVER=head
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"
==== ユーザーの登録 ====
管理サーバーと計算ノードでUIDが一致していなくてもジョブを投入できるようになります。
Qmgr: set server flatuid = True
qstatコマンドで他のユーザーのジョブの実行状況が見えるようにします
Qmgr: set server query_other_jobs = True
==== 計算ノードの登録 ====
計算ノードのホスト名を入力します
Qmgr: create node node11
Qmgr: create node node12
...
ノードあたりに使用できる最大スレッド数も指定できます(ここでは24コア)。
Qmgr: set node node11 resources_available.ncpus=24
Qmgr: set node node12 resources_available.ncpus=24
...
ノードの設定状況も確認できます
Qmgr: print node node11
#
# Create nodes and set their properties.
#
#
# Create and define node node11
#
create node node11
set node node11 state = free
set node node11 resources_available.arch = linux
set node node11 resources_available.host = node11
set node node11 resources_available.mem = 131666992kb
set node node11 resources_available.ncpus = 24
set node node11 resources_available.vnode = node11
set node node11 resv_enable = True
使わなくなったノードはdeleteで消せます
Qmgr: delete node node11
登録された計算ノードはpbsnodesコマンドを使って確認します
$ pbsnodes -a
* 計算ノードになんらかのトラブルがあって認識されていない場合は state = state-unknown (あるいはdown)と表示されます。管理ノードから計算ノードにSSHで正しく接続できるにも関わらずこのようなメッセージが出る場合は、計算ノードのPBSを再起動します
$ sudo /etc/init.d/pbs restart
===== ジョブの実行 =====
試しに「60秒間何もしない」というジョブを投げてみます。
クラスタ計算機を使用するユーザーで管理ノードにログインしてください。
qsubはジョブを投入するコマンドです
$ echo 'sleep 60' | qsub
ジョブの現在の状態はqstatコマンドで確認できます
$ qstat -s
head:
Req'd Req'd Elap
Job ID Username Queue Jobname SessID NDS TSK Memory Time S Time
--------------- -------- -------- ---------- ------ --- --- ------ ----- - -----
0.head sugimoto workq STDIN 9007 1 1 -- -- R 00:00
Job run at Tue Dec 03 at 04:56 on (node11:ncpus=1)
Sの列が状態を表し、Qだと実行待ち、Rだと実行中を意味します。
ジョブが計算ノードnode11で実行されていることがわかります。
ジョブを強制終了したい場合は qdel を使います
$ qdel
====== プログラムの実行 ======
===== MPIの設置 =====
* OpenMPI, MPICH2, Intel MPIなどのMPIライブラリを管理ノードの /opt にインストールし、NFSによって各計算ノードに共有してください
===== ソースコード =====
実際にPBSを使ってクラスタ計算機にプログラムを投げてみます。
次のプログラムを使用します。
#include
#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 test test.c
$ mpiicx -o test test.c # Intel MPIを使用する場合
===== ジョブ投入用スクリプト =====
次のスクリプトを作成します。
#!/bin/bash
#PBS -V
#PBS -l select=2:ncpus=24:mpiprocs=24
cd $PBS_O_WORKDIR
mpirun ./test
* #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/ に生成されたものが使われます
実行権限を付与します。
$ chmod +x run.sh
ジョブを実行します
$ qsub run.sh
1.head
結果を見てみます
$ cat run.sh.o1
Hello world: rank 0 of 48 running on node11
Hello world: rank 1 of 48 running on node11
(略)
Hello world: rank 23 of 48 running on node11
Hello world: rank 24 of 48 running on node12
Hello world: rank 25 of 48 running on node12
(略)
Hello world: rank 47 of 48 running on node12
==== (追記:2023/01/25) ====
oneAPIをアップデートしたら、ノード間並列をするときにエラーが出るようになってしまいました。
(バージョン:Intel(R) MPI Library 2021.5 for Linux)
次のようにしてください。
#!/bin/bash
#PBS -V
#PBS -l select=2:ncpus=24:mpiprocs=24
cd $PBS_O_WORKDIR
mpirun -bootstrap ssh ./hello
参考:https://community.intel.com/t5/Intel-oneAPI-HPC-Toolkit/faild-running-intel-oneAPI-MPI-mpihell-f90-example-on-multiple/m-p/1357061
==== OpenMPを使用する場合 ====
OpenMPのみ、あるいはMPI+OpenMPのハイブリッドで使用する場合は、次のようにOpenMPのスレッド数を指定してください
#!/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 ======
複数のユーザーが同時に使用する場合に、うまく計算資源を割り当てる機能です。
* https://www.altairjp.co.jp/resource/basic-fairshare-for-altair-pbs-professional
====== ノードごとの負荷の分散 ======
ジョブを投入したら、デフォルトでは1番目の計算ノードにジョブを埋めていき、その計算ノードのリソースが全て埋まってから次の計算ノードでジョブが走るようになります。
これを、各ノードの負荷を分散させるようにジョブが投入されるように変更します。
設定ファイル /var/spool/pbs/sched_priv/sched_config から node_sort_key を探して次のように変更します。
* 使用しているCPUのコア数が一番少ないノードにジョブを割り当てたい場合
node_sort_key: "ncpus LOW assigned" ALL
* 使用していないCPUのコア数が一番多いノードにジョブを割り当てたい場合
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/
====== トラブルシューティング ======
===== Supermicroのマザボを使った計算ノードが認識されない =====
* Ubuntu 26.04で確認
SupermicroのIPMI LANポートが搭載されたマザーボードでは、そのポートにローカルIPアドレス169.254.3.1が自動で割り振られた上で、管理ノードにこのIPがこの計算ノードのIPアドレスだと登録されてしまうことがあります。
実際、計算ノードにログインして、ログを確認すると
$ sudo tail -n 10 /var/spool/pbs/mom_logs/20260629
06/29/2026 07:11:24;0c06;pbs_mom;TPP;pbs_mom(Thread 0);Connected to pbs_comm head:17001
06/29/2026 07:11:24;0001;pbs_mom;Svr;net_restore_handler;net restore handler called
06/29/2026 07:11:24;0c06;pbs_mom;TPP;pbs_mom(Thread 0);Connection to pbs_comm head:17001 down
06/29/2026 07:11:24;0001;pbs_mom;Svr;net_down_handler;net down handler called
06/29/2026 07:11:26;0c06;pbs_mom;TPP;pbs_mom(Thread 0);Registering address 169.254.3.1:15003 to pbs_comm head:17001
06/29/2026 07:11:26;0c06;pbs_mom;TPP;pbs_mom(Thread 0);Registering address 192.168.0.27:15003 to pbs_comm head:17001
06/29/2026 07:11:26;0c06;pbs_mom;TPP;pbs_mom(Thread 0);Connected to pbs_comm head:17001
06/29/2026 07:11:26;0001;pbs_mom;Svr;net_restore_handler;net restore handler called
06/29/2026 07:11:26;0c06;pbs_mom;TPP;pbs_mom(Thread 0);Connection to pbs_comm head:17001 down
06/29/2026 07:11:26;0001;pbs_mom;Svr;net_down_handler;net down handler called
となっています。
169.254.3.1が割り当てられてしまっているポートを確認します
$ ip a
1: lo: mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enxbe3af2b6059f: mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
link/ether be:3a:f2:b6:05:9f brd ff:ff:ff:ff:ff:ff
inet 169.254.3.1/24 metric 1024 brd 169.254.3.255 scope global dynamic enxbe3af2b6059f
valid_lft 861890sec preferred_lft 861890sec
inet6 fe80::bc3a:f2ff:feb6:59f/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
3: eno1np0: mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 7c:c2:55:84:d2:e8 brd ff:ff:ff:ff:ff:ff
altname enp61s0f0np0
altname enx7cc25584d2e8
inet 192.168.0.27/24 metric 100 brd 192.168.0.255 scope global dynamic eno1np0
valid_lft 231sec preferred_lft 231sec
inet6 fe80::7ec2:55ff:fe84:d2e8/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
4: eno2np1: mtu 1500 qdisc mq state DOWN group default qlen 1000
link/ether 7c:c2:55:84:d2:e9 brd ff:ff:ff:ff:ff:ff
altname enp61s0f1np1
altname enx7cc25584d2e9
enxbe3af2b6059fというポートに169.254.3.1が割り当てられてしまっていることがわかるため、netplanの設定でIPアドレスが割り当てられないようにします。
$ sudo nano /etc/netplan/00-installer-config.yaml
network:
ethernets:
eno1np0:
dhcp4: true
dhcp6: true
dhcp-identifier: mac
enxbe3af2b6059f:
addresses: []
version: 2
$ sudo netplan apply
$ sudo /etc/init.d/pbs restart
====== OpenPBSについて ======
* Altair Engineering社が提供するジョブ管理ソフトです。有償版のPBS Proの機能を制限したオープンソース版です。
* 昔(2015年くらいまで)はジョブスケジューラといえば[[https://en.wikipedia.org/wiki/Portable_Batch_System|PBS]](特にそこから派生したTorque)という印象でした。PBSは有償版が中心となってからは一気に[[https://ja.wikipedia.org/wiki/Slurm_Workload_Manager|Slurm]]への移行が進んだ気がします。mungeというSlurm用の認証システムを入れる必要があり、以前は導入のハードルが少し高かったのですが、今は整備されて割と簡単に導入できます。
====== 参考 ======
* https://www.altair.com/pbs-works-documentation/
* 公式サイトです。必要な情報はここですべて手に入ります
* https://www.nas.nasa.gov/assets/pdf/staff/RasberryPiClusterBuild.pdf
* ラズベリーパイによるクラスターマシン作成方法です。OSがUbuntuと同じDebian系なのでそっくり参考になります。
* https://qiita.com/MasafumiTsuyuki/items/acf4b19b54937496e32b
* https://web.chaperone.jp/w/index.php?pbspro
* https://pbspro.atlassian.net/wiki/spaces/PBSPro/pages/22183970/Building+and+Packaging+PBS+on+Debian+Ubuntu
* パッケージを作っておくと、たくさんの計算ノードにインストールするとき楽です。