Slurm Job のZombieプロセスを何とかしたい 〜 SlurmとMPIの関係調査 〜

ほとんど公式マニュアルの日本語訳です。。。。
まだ、下記の情報でZombieが防げるか、確認できていません。

slurm.confで定義する `MpiDefault` とは
===========================================

使用するMPIのデフォルトの種類を指定します。Srunはこのコンフィギュレーションパラメータをオーバーライドすることができます。
現在サポートされているのは pmi2、pmix、none (デフォルト、他の多くの MPI のバージョンで動作) です。
MPI の使用に関するより詳しい情報は [mpi_guide](https://slurm.schedmd.com/mpi_guide.html) にあります。

NOTE: ここでのsrunのoverrideとは、sbatchの中で、pmiをMPIライブラリーの外に任せることで、`mpirun` のコマンドを`srun`に置き換えることができるという意味に解釈できます。

MPI and UPC Users Guide
===========================================

MPIの使用は、使用するMPIの種類に依存します。これらの様々なMPI実装で使用される動作モードは、基本的に3つあります。

1. Slurmは**直接タスクを起動**し、PMI2またはPMIx APIを通じて通信の初期化を行います(最近のMPI実装のほとんどでサポートされています)
2. Slurm が**ジョブの資源割り当てを作成**し、mpirun が Slurm のインフラストラクチャ (OpenMPI の古いバージョン) を使用してタスクを起動します。
3. Slurm が**ジョブの資源割り当てを作成**し、mpirun が SSH や RSH などの Slurm以外の機構を使ってタスクを起動します。これらのタスクは **Slurm の監視や制御の外で開始**されます。Slurm のエピログは、ジョブの割り当てを放棄したときにこれらのタスクをパージするように設定されるべきです。また、`pam_slurm_adopt` の使用も強く推奨します。

**NOTE**: 3の場合、Slurm はユーザアプリケーションを直接起動しないので、CPU やアカウンティングにタスクをバインドするという望ましい動作ができない可能性があります。MPI 実装のバージョンによっては動作するものもありますので、実際の動作を確認するためには、特定のインストールをテストする必要があるかもしれません。

2つのSlurmパラメータは、どのMPI実装をサポートするかを制御します。適切な環境変数を設定するなど、SlurmがMPIジョブに適切な環境を構築するために、適切な設定が不可欠です。

- slurm.conf の `MpiDefault` 設定パラメータは、サポートされるシステムのデフォルト MPI を設定します。
- srun オプション `--mpi=` (または同等の環境変数 `SLURM_MPI_TYPE`) を使用すると、個々のジョブで異なる MPI 実装をサポートするように指定することができます。

**NOTE**: 適切な Slurm プラグインがない MPI 実装を使用すると、アプリケーションに障害が発生することがあります。複数の MPI 実装を使用する場合、**一部のユーザーは適切な Slurm MPI プラグインを明示的に指定**する必要があります。

**NOTE**: RPMでSlurm をインストールする場合、slurm-libpmi パッケージは pmix-libpmi パッケージがインストールされていると衝突します。もしあなたのサイトのポリシーでソースからのインストールを許可している場合、これらのパッケージを異なる場所にインストールすることで、使用するライブラリを選択することができるようになります。
いくつかの MPI/PMI を Slurm で使用するための説明を以下で行います。


PMIx 
---------------------------

### PMIXの構築 

PMIxをビルドする前に、これらの[How-To Guide](https://openpmix.github.io/support/how-to/)を読むことが推奨されます。これらのガイドには、[ビルドの依存関係やインストール手順についての詳細](https://openpmix.github.io/code/getting-the-reference-implementation)と、[Slurmサポート](https://openpmix.github.io/support/how-to/slurm-support)に関するいくつかの関連する注意事項が記載されています。

このセクションは PMIx FAQ を補完する目的で、Slurm と PMIx を一緒に動作させるための準備に関するいくつかの注意事項を述べています。PMIxは公式の[PMIx GitHub](https://github.com/openpmix/openpmix)リポジトリからリポジトリをクローンするか、パッケージ化されたリリースをダウンロードすることで入手することができます。

PMIx の Slurm サポートは PMIx v1.2 リリースをベースにした Slurm 16.05 で初めて搭載されました。その後、以下の表にあるように PMIx v2.x および v3.x シリーズをサポートするように更新されています。

- Slurm 16.05+ は v1.2.0 以降の PMIx v1.x シリーズのみをサポートします。このバージョンのSlurmは、特にPMIx v2.x以降をサポートしていません。
- Slurm 17.11+ は PMIx v1.2+ と v2.x の両方をサポートしますが、v3.x はサポートしません。
- Slurm 18.08+ は PMIx v1.2+, v2.x, v3.x をサポートしています。

PMIx v1 を使用する場合、少なくとも 1.2.5 を実行することをお勧めします。古いバージョンでは pmi および pmi2 API のサポートに互換性の問題がある可能性があるからです。また、**Intel MPI は PMIx を公式にサポートしていない**ことにも注意してください。動作するかもしれませんが、動作の保証はありません。(マニュアルにはこう書いているが、最新のIntelMPIであれば、[サポートしているように見える](https://www.intel.com/content/www/us/en/develop/documentation/mpi-developer-reference-linux/top/environment-variable-reference/other-environment-variables.html))

PMIxは[パッケージリリース](https://github.com/openpmix/openpmix/releases)からビルドすることが推奨されていますが、ここではgitリポジトリをクローンしてPMIx v2.1をビルドする例を示します。



```bash:command
user@testbox:~/git$ mkdir -p pmix/build/2.1 pmix/install/2.1
user@testbox:~/git$ cd pmix
user@testbox:~/git/pmix$ git clone https://github.com/openpmix/openpmix.git source
user@testbox:~/git/pmix$ cd source/
user@testbox:~/git/pmix/source$ git branch -a
user@testbox:~/git/pmix/source$ git checkout v2.1
user@testbox:~/git/pmix/source$ git pull
user@testbox:~/git/pmix/source$ ./autogen.sh
user@testbox:~/git/pmix/source$ cd ../build/2.1/
user@testbox:~/git/pmix/build/2.1$ ../../source/configure \
> --prefix=/home/user/git/pmix/install/2.1
user@testbox:~/git/pmix/build/2.1$ make -j install >/dev/null
user@testbox:~/git/pmix/build/2.1$ cd ../../install/2.1/
user@testbox:~/git/pmix/install/2.1$ grep PMIX_VERSION include/pmix_version.h
#define PMIX_VERSION_MAJOR 2L
#define PMIX_VERSION_MINOR 1L
user@testbox:~/git/pmix/install/2.1$
```

ここでは、PMIx v2.1が以下のパスにインストールされていると仮定して説明します。

```bash:command
user@testbox:/home/user/git/pmix/install/2.1
```

PMIxに関するその他の注意事項は、[SchedMD Publications and Presentations](https://slurm.schedmd.com/publications.html)のページでご覧になれます。

### PMIx をサポートした slurm の構築

設定時に、SlurmはデフォルトでPMIxのインストール先を探します。

```bash:command
/usr
/usr/local
```

PMIx が以前のどの場所にもインストールされていない場合、Slurm の configure スクリプトはデフォルトでない場所を指すように要求することができます。以下はその例です。

```bash:command
user@testbox:~/slurm/17.11/testbox/slurm$ ../../slurm/configure \
> --prefix=/home/user/slurm/17.11/testbox \
> --with-pmix=/home/user/git/pmix/install/2.1
```

あるいは、RPMベースのビルディングとの類似性。

```bash:command
[user@testbox Downloads]$ rpmbuild \
> --define '_prefix /home/user/slurm/17.11/testbox' \
> --define '_slurm_sysconfdir /home/user/slurm/17.11/testbox/etc' \
> --define '_with_pmix --with-pmix=/home/user/git/pmix/install/2.1' \
> -ta slurm-17.11.1.tar.bz2
```

注: ':' を区切り文字として、複数の PMIx バージョンに対してビルドすることも可能です。例えば、1.2 と 2.1 に対してビルドすることができます。

```bash:command
> --with-pmix=/path/to/pmix/install/1.2:/path/to/pmix/install/2.1 \
```

**NOTE**: ジョブを投入する際に、-mpi=listから任意のバージョンを選択することができます。pmixのデフォルトは、ライブラリの最高バージョンになります。

```bash:command
user@testbox:~/t$ srun --mpi=list
srun: MPI types are...
srun: pmix_v1
srun: pmi2
srun: none
srun: pmix
srun: pmix_v2
```

続けて、Slurm が PMIx を見つけることができなかったり、見つけても使えないと判断した場合、configure の出力は以下のようになります。

```terminal
checking for pmix installation...
configure: WARNING: unable to locate pmix installation
```

そうでなければ、Slurmがそれを見つけて使えると判断したら、次のようなものです。

```terminal
checking for pmix installation... /home/user/git/pmix/install/2.1
```

Slurm のビルドディレクトリに生成された config.log を調べると、トラブルシューティングのためにさらに詳細な情報が得られるかもしれません。設定が終わったら、Slurm をインストールします (適宜 make や rpm を使用します)。

```bash:command
user@testbox:~/slurm/17.11/testbox/slurm$ make -j install > /dev/null
user@testbox:~/slurm/17.11/testbox/slurm$ cd ../lib/slurm/
user@testbox:~/slurm/17.11/testbox/lib/slurm$ ls -l | grep pmix
lrwxrwxrwx 1 user user       16 Dec  6 19:35 mpi_pmix.so -> ./mpi_pmix_v2.so
-rw-r--r-- 1 user user  7008260 Dec  6 19:35 mpi_pmix_v2.a
-rwxr-xr-x 1 user user     1040 Dec  6 19:35 mpi_pmix_v2.la
-rwxr-xr-x 1 user user  1020112 Dec  6 19:35 mpi_pmix_v2.so
user@testbox:~/slurm/17.11/testbox/lib/slurm$
```

PMI2版への対応も必要な場合は、contribsディレクトリからインストールすることも可能です。

```bash:command
user@testbox:~/slurm/17.11/testbox/lib/slurm$ cd ../../slurm/contribs/pmi2
user@testbox:~/slurm/17.11/testbox/slurm/contribs/pmi2$ make -j install
user@testbox:~/slurm/17.11/testbox/slurm/contribs/pmi2$ cd ../../../lib
user@testbox:~/slurm/17.11/testbox/lib$ ls -l | grep pmi
-rw-r--r-- 1 user user   498144 Dec  6 20:05 libpmi2.a
-rwxr-xr-x 1 user user      958 Dec  6 20:05 libpmi2.la
lrwxrwxrwx 1 user user       16 Dec  6 20:05 libpmi2.so -> libpmi2.so.0.0.0
lrwxrwxrwx 1 user user       16 Dec  6 20:05 libpmi2.so.0 -> libpmi2.so.0.0.0
-rwxr-xr-x 1 user user   214512 Dec  6 20:05 libpmi2.so.0.0.0
-rw-r--r-- 1 user user   414680 Dec  6 19:35 libpmi.a
-rwxr-xr-x 1 user user     1011 Dec  6 19:35 libpmi.la
lrwxrwxrwx 1 user user       15 Dec  6 19:35 libpmi.so -> libpmi.so.0.0.0
lrwxrwxrwx 1 user user       15 Dec  6 19:35 libpmi.so.0 -> libpmi.so.0.0.0
-rwxr-xr-x 1 user user   230552 Dec  6 19:35 libpmi.so.0.0.0
user@testbox:~/slurm/17.11/testbox/lib$
```

**NOTE**: Slurm と PMIx は共に libpmi[2].so ライブラリを提供していますので、両ソフトウェアを別の場所にインストールすることをお勧めします。そうしないと、Slurm と PMIx が提供する両方のライブラリが /usr/lib64 のような標準的な場所にインストールされてしまい、パッケージマネージャがエラーを起こして衝突を報告する可能性があります。これらのライブラリを別の libpmi-slurm パッケージに入れることで、この問題を軽減することが予定されています。

**NOTE**: multiple-slurmd を使ってテスト環境を構築する場合、 slurm.conf で TmpFS オプションを指定し、作成するディレクトリパスの数をノードの数 と同じにする必要があります。これらのディレクトリは、Slurm PMIx プラグインが一時ファイルや UNIX ソケットを作成するために使用されます。以下は、compute[1-2]という名前の2つのノードのセットアップの例です。

```bash:command
TmpFS=/home/user/slurm/17.11/testbox/spool/slurmd-tmpfs-%n
user@testbox:~/slurm/17.11/testbox$ mkdir spool/slurmd-tmpfs-compute1
user@testbox:~/slurm/17.11/testbox$ mkdir spool/slurmd-tmpfs-compute2
```

OpenMPI
---------------------

現在のバージョンのSlurmとOpenMPIは、srunコマンドによるタスク起動をサポートしています。これは、Open MPI version 1.5 が使用する通信ポートの予約を Slurm が管理することに依存しています。

OpenMPIが --with-pmi pmi または pmi2 で設定されている場合、OMPIジョブはsrunコマンドを使用して直接起動することができます。これは望ましい動作モードです。pmi2のサポートが有効な場合は、srunコマンドラインでオプション '--mpi=pmi2' または '--mpi=pmi2_v2' を指定する必要があります。また、slurm.conf で 'MpiDefault=pmi' または 'MpiDefault=pmi_v2' と設定することも可能です。

Open MPI version 3.1 からは PMIx version 2 がネイティブにサポートされています。PMIx version 2 を使って Open MPI アプリケーションを起動するには、 srun コマンドラインで '--mpi=pmix_v2' オプションを指定するか、 slurm.conf で 'MpiDefault=pmi_v2' を設定しなければなりません。Open MPI version 4.0 では PMIx version 3 がサポートされ、同じように '--mpi=pmix_v3' で起動します。

Open MPI version 2.0 では PMIx もネイティブにサポートされています。PMIxを使用してOpen MPIアプリケーションを起動するには、 srunコマンドラインで '--mpi=pmix' または '--mpi=pmix_v1' オプションを指定しなければなりません。また、外部でインストールしたPMIxを使用してOpenMPIをビルドすることも可能です。このオプションは3つの値のうちの1つを取ります。「internal"、"external"、または有効なディレクトリ名です。「internal" (または DIR の値がない場合) は Open MPI に PMIx の内部コピーを使用させます。「external" は Open MPI に PMIx の外部インストールを使用させます。有効なディレクトリ名を与えると、Open MPI は PMIx の外部インストールを使用するようになり、ヘッダやライブラリの検索パスに DIR/include、DIR/lib、DIR/lib64 が追加されます。Open MPI は --without-pmix をサポートしないことに注意してください。また、外部のPMIxインストレーションを使ってOpenMPIをビルドする場合、OpenMPIとPMIxは同じlibevent/hwlocインストレーションに対してビルドする必要があり、さもなければ警告が表示されることに注意してください。OpenMPI configureスクリプトは --with-libevent=PATH および/または --with-hwloc=PATH オプションを提供し、OpenMPIをPMIxがビルドされたものと一致させることができるようにします。

Slurm PMIxプラグインの動作を制御するために、一連の環境変数が利用可能です。

- SLURM_PMIX_SRV_TMPDIR PMIx/server サービスファイルのベースディレクトリです。
- SLURM_PMIX_TMPDIR アプリケーションセッションディレクトリのベースディレクトリ。
- SLURM_PMIX_DIRECT_CONN (default - yes) enable (1/yes/true) or disables (0/no/false) は slurmstepd の間で直接接続するか Slurm RPC でデータ交換するかどうかを制御します。PMIx が direct-modex モードで動作している場合、完全にパックされたノードでは直接接続の方が良い性能を発揮します。

pmi サポートでコンパイルされていない古いバージョンの OMPI の場合、システム管理者は slurm.conf ファイルで MpiParams パラメータを使って予約するポートの範囲を指定する必要があります。例えば MpiParams=ports=12000-12999

また、タスクは srun コマンドに `--resv-ports` オプションを付けて起動するか、環境変数 `SLURM_RESV_PORT` を使用して起動することも可能です。割り当てられた各ノードで予約されたポートは、`SLURM_STEP_RESV_PORTS=12000-12015` のようにタスクが利用できる環境変数で識別されます。


```bash:command
$ salloc -n4 sh   # allocates 4 processors and spawns shell for job
> srun a.out
> exit   # exits shell spawned by initial salloc command
```

もしくは

```bash:command
> srun -n 4 a.out
```

またはpmi2サポートを使用する

```bash:command
> srun --mpi=pmi2 -n 4 a.out
```


ジョブステップが予約したポートがOpen MPIライブラリによって使用中であることが判明した場合、次のようなメッセージが表示され、ジョブステップが再立ち上げされます。
srun: error: sun000: task 0 unable to claim reserved port, retrying
3回失敗すると、ジョブステップは中断されます。失敗を繰り返す場合は、システム管理者に報告し、そのポートを保持しているプロセスをキャンセルして問題を解決する必要があります。

**NOTE**: OpenMPIには制限があり、Slurmのアロケーション内からMPI_Comm_spawn()を呼び出すことはできません。もし MPI_Comm_spawn() 関数を使用する必要がある場合は、PMIx もサポートしていないので、 PMI-2 と組み合わせた別の MPI 実装を使用する必要があります。

**NOTE**: いくつかのカーネルやシステム構成では、ロックされたメモリが小さすぎて適切な OpemMPI 機能が得られず、セグメンテーションフォールトでアプリケーションに失敗することがありました。これは、より大きな制限値で実行するように slurmd デーモンを設定することで修正できるかもしれません。例えば、slurmd.service ファイルに "LimitMEMLOCK=infinity" を追加してください。



IntelMPI
--------------------------

以下はSlurmの公式マニュアルの和訳ですが、最新のIntelMPI (現在のOneAPI)と、齟齬が出てきています。
対応する検証結果を、以下のQiitaページにまとめましたので、そちらも参照ください。

https://qiita.com/daikumatan/items/928a743db58e67c9c923

インテル® MPI ライブラリー Linux OS 版では、Slurm ジョブ・マネージャーの制御下で MPI ジョブを起動する方法として、以下の方法をサポートしています。

- [MPD プロセス・マネージャー (PM) 上で mpirun コマンドを実行](https://slurm.schedmd.com/mpi_guide.html#intel_mpirun_mpd)
- [Hydra PM 上で mpirun コマンドを実行](https://slurm.schedmd.com/mpi_guide.html#intel_mpirun_hydra)
- [mpiexec.hydra コマンド (Hydra PM)](https://slurm.schedmd.com/mpi_guide.html#intel_mpiexec_hydra)
- [srunコマンド（Slurm、推奨）](https://slurm.schedmd.com/mpi_guide.html#intel_srun)


この説明では、これらすべての方法について詳しく説明します。

### mpd プロセスマネージャ上の mpirun コマンド 

Slurm は、インテル® MPI ライブラリー 3.1 Build 029 for Linux OS およびそれ以降のリリースの mpirun コマンドでサポートされています。

Slurm コマンド sbatch または salloc を使用して割り当てられたセッション内で起動すると、 mpirun コマンドは自動的に特定の Slurm 環境変数を検出して問い合わせ、割り当てられたクラスター・ノードのリストを取得します。

MPD PM 上で既存の Slurm セッション内で MPI ジョブを起動するには、以下のコマンドを使用します。

```bash:command
export I_MPI_PROCESS_MANAGER=mpd
mpirun -n <num_procs> a.out
```


### hydra プロセスマネージャ上の mpirun コマンド 

Slurm は、インテル® MPI ライブラリー 4.0 Update 3 の mpirun コマンドにより、 Hydra PM を介してデフォルトでサポートされています。このコマンドの動作は、前述の MPD の場合と類似しています。

Hydra PM 上の既存の Slurm セッションで MPI ジョブを開始するには、以下のコマンドのいずれかを使用します。

```bash:command
mpirun -n <num_procs> a.out
```

または

```bash:command
mpirun -bootstrap slurm -n <num_procs> a.out
```

2番目のコマンドを使用することをお勧めします。これはリモートの Hydra PM サービスプロセスを起動するのに、デフォルトの ssh ベースの方法ではなく srun コマンドを使用します。

### mpiexec.hydra コマンド (Hydra プロセスマネージャ) 

Slurm はインテル® MPI ライブラリー 4.0 Update 3 で Hydra PM を介して直接サポートされています。
既存の Slurm セッションで MPI ジョブを開始するには、次のコマンドを使用します。

```bash:command
mpiexec.hydra -bootstrap slurm -n <num_procs> a.out
```

### srunコマンド(slurm, 推奨) 

この高度な方法は、インテル® MPI ライブラリー 4.0 Update 3 でサポートされています。**この方法は Slurm と最もよく統合されており、プロセスの追跡、アカウンティング、タスク・アフィニティー、サスペンド/レジュームなどの機能をサポート**しています。以下のコマンドを使用して、Slurm セッションを割り当ててその中で MPI ジョブを開始するか、 sbatch または salloc コマンドを使用して既に作成されている Slurm セッションの中で MPI ジョブを開始します。

- 環境変数 I_MPI_PMI_LIBRARY を設定して Slurm Process Management Interface (PMI) ライブラリを指すようにします。

```bash:command
export I_MPI_PMI_LIBRARY=/path/to/slurm/pmi/library/libpmi.so
```

**NOTE**: ライセンスの関係で、IMPIは外部のPMI実装に直接リンクしていません。代わりに、上記の環境変数をエクスポートして目的のライブラリを指定する必要があり、そのライブラリはIMPIによってdlopenedされます。また、Intel は PMIx ライブラリに対して公式なサポートを提供していません。IMPIはMPICHをベースにしているため、MPICHで使われているpmiやpmi2と互換性を保っているPMIxをIntelで使うと動作する場合がありますが、すべてのケースで動作が保証されるわけではありません。

- MPIジョブを起動するにはsrunコマンドを使用します。

```bash:command
srun -n <num_procs> a.out
```

上記の情報は、インテルの許可を得て使用しています。詳細はインテル MPI ライブラリを参照してください。

MPICH (通称: MPICH2) 
----------------------------

MPICH2のジョブは、pmi 1または2、あるいはmpiexecを使用してsrunコマンドで起動することができます。すべての動作モードについて以下に説明します。

### srunとpmiバージョン2によるMPICH2 

MPICH2 は Slurm と PMI2 で使用するために、以下のような configure 行でビルドする必要があります。

```bash:command
./configure --with-slurm=<PATH> --with-pmi=pmi2
```

PATHはSlurmのインストールディレクトリ、言い換えればbinとlibの親ディレクトリを指している必要があります。また、Slurm に MpiDefault=pmi2 が設定されていない場合は、以下の例のように --mpi=pmi2 オプションを付けて srun コマンドを起動する必要があります。

```bash:command
srun -n4 --mpi=pmi2 ./a.out
```

SlurmのPMI2サポートは、MPI実装がサポートしている場合、言い換えればMPIにPMI2インタフェースが実装されている場合のみ動作します。--mpi=pmi2 は lib/slurm/mpi_pmi2.so というライブラリをロードし、サーバ側の機能を提供しますが、クライアント側は PMI2_Init() やその他のインターフェースコールを実装しなければなりません。
このため、MPICH のインストール時に --with-pmi=pmi2 configure オプションを指定する必要があります。
使用している MPI のバージョンが PMI2 をサポートしているかどうかを調べるには、 MPI ライブラリに PMI2_* シンボルがあるかどうか調べてください。

SlurmはcontribsディレクトリにPMI2クライアントライブラリを提供しています。このライブラリは Slurm の lib ディレクトリにインストールされます。もし、あなたのMPI実装がPMI2をサポートしており、Slurmが提供するライブラリを使用したい場合は、Slurmが提供するライブラリを明示的にリンクする必要があります。

```bash:command
mpicc -L<path_to_pmi2_lib>・lpmi2 ...
$ srun -n20 a.out
```

mpich2 と srun および pmi バージョン 1 の組み合わせ 
タスクが起動時にホストとポート情報を通信できるように、あなたのプログラムを Slurm の PMI ライブラリの実装とリンクしてください。(システム管理者が直接 mpicc と mpif77 コマンドにこれらのオプションを追加できるので、ユーザが悩む必要はありません)。例えば

```bash:command
mpicc -L<path_to_slurm_lib>・lpmi ...
$ srun -n20 a.out
```

**NOTES**:

- 現在、Slurm に統合されている PMI ライブラリでは、一部の MPICH2 関数がサポートされていません。
- PMIライブラリがデバッグ情報を表示するように、環境変数PMI_DEBUGに1以上の数値を設定してください。srun の -l オプションを使用すると、より分かりやすくなります。
- 環境変数 `SLURM_PMI_KVS_NO_DUP_KEYS` を設定すると、MPICH2 での重複キーのテストが無くなり、パフォーマンスが向上します。
- 環境変数を使用すると、ネットワーク性能に応じて性能を調整することができます。PMI_FANOUT, PMI_FANOUT_OFF_HOST, PMI_TIME です。詳細は srun man pages の INPUT ENVIRONMENT VARIABLES セクションを参照してください。
- Slurm で使用するための MPICH2 のビルドに関する情報は、 MPICH2 FAQ ウェブページと以下に記述されています。

### mpich2 と mpiexec

mpich にはフラグを追加せず、デフォルトのままビルドします（例："./configure -prefix ..."）。". --with-slurm, --with-pmi, --enable-pmiport オプションを渡さないでください)。
アプリケーションに -lpmi をつけないでください (PMI_Spawn_multiple をサポートしない slurm の pmi 1 インターフェイスを強制的に使わせます)。
salloc を使ってジョブアロケーションを作成し、mpiexec を使ってタスクを起動します。以下に簡単な例を示します。

```bash:command
salloc -N 2 mpiexec my_application
```

すべての MPI_comm_spawn は hydra の PMI 1.1 インターフェイスを経由して正常に動作するようになりました。



MVAPICH（通称：MVAPICH2） 
----------------------------

MVAPICH2 は mpirun_rsh と同様に Slurm によるマルチスレッドプログラムの起動をサポートしています。srun を使用する場合は、以下のようなコマンドラインで Slurm をサポートした MVAPICH2 をビルドする必要があることに注意してください。

```bash:command
$ ./configure --with-pmi=pmi2 --with-pm=slurm
```

Slurmのpmi2プラグインを使用することで、Slurmのpmiプラグインよりも大幅に高いパフォーマンスとスケーラビリティを得ることができます。pmi2 が Slurm のデフォルト MPI プラグインとして設定されていない場合、以下のように srun コマンドの "--mpi-pmi2" オプションで指定するか、環境変数に "SLURM_MPI_TYPE=pmi2" を設定してください。

```bash:command
$ srun -n16 --mpi=pmi2 a.out
MVAPICH2は以下のオプションでビルドすることができます。
--with-pmi=pmi2 \.
--with-pm=slurm \
--with-slurm=<インストール先ディレクトリ> \!
--enable-slurm=yes
```

詳しくは、MVAPICH2ユーザーガイドをご覧ください。


UPC（ユニファイドパラレルC） 
-----------------------------

Berkeley UPC（および他のUPC実装）は、リソースの割り当てとアプリケーションのタスクの起動をSlurmに依存しています。その後、UPC ライブラリが読み取ります。Slurm の環境変数を読み込んで、ジョブのタスク数と場所を決定します。通常の方法で UPC プログラムを構築し、次のようなコマンドラインを使用して起動します。

```bash:command
$ srun -N4 -n16 a.out
```


pam_slurm_adopt
======================

このモジュールの目的は、ユーザが実行中のジョブがないノードに ssh で接続することを防ぎ、ssh 接続と他の生成されたプロセスを追跡して会計処理を行い、ジョブが終了したときに完全なジョブクリーンアップを保証することです。このモジュールは、ssh 接続を発生させたジョブを決定することで、 これを行ないます。ユーザーの接続は、ジョブの "外部" のステップに "採用" されます。

Installation
---------------------

### SOURCE

Slurm のビルドディレクトリで `slurm/contribs/pam_slurm_adopt/` に移動し、以下をrootで実行します。

```bash:command
make && make install
```

これにより、pam_slurm_adopt.a, pam_slurm_adopt.la, pam_slurm_adopt.so が /lib/security/ (Debian システム) または /lib64/security/ (RedHat/SuSE システム) に置かれることになります。

### RPM

同梱の slurm.spec を使って slurm-pam_slurm RPM を構築し，pam_slurm_adopt をインストールします．RPM ベースのインストールを管理する方法については、[クイックスタート管理者ガイド](https://slurm.schedmd.com/quickstart_admin.html)を参照してください。

PAM Configuration
---------------------

system-authやsshdなど、`/etc/pam.d` の適切なファイルに以下の行を追加します（PAM制御フラグは「required」または「sufficient」のどちらかを使用します）

```bash
account    required      pam_slurm_adopt.so
```

プラグインの順番は非常に重要です。pam_slurm_adopt.so は、アカウントスタックの最後の PAM モジュールであるべきです。common-account のようなインクルードファイルは、通常 pam_slurm_adopt の前にインクルードする必要があります。sshd では、次のようなアカウントスタックになっていることでしょう。

```bash
account    required      pam_nologin.so
account    include       password-auth
...
-account    required      pam_slurm_adopt.so
```

pam_slurm_adoptのアカウントエントリの前にある`-`に注意してください。これは pam_slurm_adopt.so ファイルが見つからない場合に、PAM が優雅に失敗するようにするためです。Slurm が NFS のような共有ファイルシステム上にある場合、共有ファイルシステムのマウント中またはダウン中にノードからロックアウトされるのを避けるために、この方法が推奨されます。

pam_slurm_adopt は task/cgroup タスクプラグインと proctrack/cgroup または proctrack/cray_aries proctrack プラグインと一緒に使用する必要があります。pam_systemd モジュールは pam_slurm_adopt と衝突しますので、sshd や system-auth に含まれるすべてのファイル (password-auth, common-session など) で無効化する必要があります。また、systemd-logind を停止してマスクする必要があります。また、別の PAM モジュールが pam_slurm_adopt.so に到達する前にアカウントスタックをショートさせていないことを確認する必要があります。上記の例から、次の2行は含まれるpassword-authファイルでコメントアウトされています。

```bash
#account    sufficient    pam_localuser.so
#-session   optional      pam_systemd.so
```

**NOTE**: これは自動生成されるファイルの編集を伴うかもしれません。このファイルを生成するconfigスクリプトを実行しないでください。

管理者グループ (例: wheel) のアクセスを常に許可したい場合は、pam_slurm_adopt の後に pam_access モジュールをスタックします。pam_slurm_adoptで成功すればアクセスを許可するのに十分ですが、pam_accessモジュールは、そのノードにジョブがなくても管理スタッフのような他の人にアクセスを許可することができます。

```bash
account    sufficient    pam_slurm_adopt.so
account    required      pam_access.so
```

次に、pam_accessの設定ファイル(/etc/security/access.conf)を編集します。

```bash
+:wheel:ALL
-:ALL:ALL
```

pam_accessの代わりに、pam_listfile.soをpam_slurm_adopt.soの前に配置する方法もあります。例えば

```bash
account    sufficient    pam_listfile.so item=user sense=allow onerr=fail file=/path/to/allowed_users_file
account    required      pam_slurm_adopt.so
```

allowed_users_fileに許可されたユーザのユーザ名を列挙します。
アクセスが拒否された場合、ユーザは関連するエラーメッセージを受け取ります。

pam_slurm_adopt Module Options 
-----------------------------------

このモジュールは設定可能です。/etc/pam.d/ の適切なファイル (例: sshd や system-auth) の pam_slurm_adopt 行の最後に、以下のオプションを追加してください。

```
account sufficient pam_slurm_adopt.so optionname=optionvalue
```

このモジュールには以下のオプションがあります。

### `action_no_jobs`

The action to perform if the user has no jobs on the node. Configurable values are:

- `ignore`: 
    - 何もしない。次の pam モジュールにフォールスルーします。
- `deny` (default):
    - 接続を拒否します。

### `action_unknown`

ユーザがノード上に複数のジョブを持っていて、RPCがソース・ジョブを見つけられない場合に実行するアクションを指定します。RPCメカニズムが環境で適切に動作している場合、このオプションはログイン・ノードから接続する場合にのみ関連する可能性があります。設定可能な値は以下の通りです。

- `newest` (デフォルト)
    - そのノードで最も新しいジョブを選びます。
    - 最新の "ジョブは、ジョブのstep_extern cgroupのmtimeに基づいて選択されます; 
        - Slurmに問い合わせると、コントローラへのRPCが必要になります。
        - したがって、コードが cgroup ディレクトリの mtimes をチェックできるように、メモリ cgroup が使用中でなければなりません。
    - ユーザは ssh でログインできますが、チェックしようとしたジョブよりも早く終了するジョブに採用される可能性があります。
    - ssh 接続は少なくとも適切な制限を受けることになり、これが問題になった場合には、 ユーザーは目的を達成するためのより良い方法を知ることができます。
    - 注意: モジュールが cgroup mtime の取得に失敗した場合、選ばれたジョブが 最新のものでない可能性があります。
- `allow`
    - 採用せずに接続を通す
- `deny`
    - 接続を拒否します

### `action_adopt_failure`

何らかの理由でプロセスがどのジョブにも採用されない場合に実行するアクション。callerid RPC で特定されたジョブにプロセスが採用できない場合、 action_unknown コードにフォールスルーしてそこで採用しようとする。この時点で失敗した場合、またはジョブが1つしかない場合、このアクションが実行されることになります。設定可能な値は以下の通り。

- `allow` (デフォルト)
    - 採用せずに接続を通過させます。
    - 警告: この値は安全ではないので、テスト目的のみに使用することをお勧めします。"deny "を使用することをお勧めします。
- `deny`
    - 接続を拒否します。

### `action_generic_failure`

ローカルのslurmdと会話できない、カーネルが正しい設備を提供しないなど、特定の障害が発生した場合に実行するアクション。設定可能な値は以下の通りです。

- `ignore` (default)
    - 何もしない。次の pam モジュールにフォールスルーします。警告: この値は安全ではないので、テスト目的のみに使用することをお勧めします。"deny "を使用することをお勧めします。
- `allow` 
    - 採用せずに接続を通します。
- `deny`
    - 接続を拒否します。

### `disable_x11`

Slurm内蔵のX11転送のサポートをオフにします。設定可能な値は以下の通りです。

- `0` (デフォルト)
    - 接続が採用されたジョブがSlurmのX11転送を有効にしている場合、DISPLAY変数はX11トンネルエンドポイントの詳細で上書きされます。
- `1`
    - SlurmのX11転送のサポートをチェックせず、DISPLAY変数を変更しない。

### `log_level`

利用可能なオプションについては、slurm.confのSlurmdDebugを参照してください。デフォルトのlog_levelはinfoです。

### `nodename`

slurm.conf で定義された NodeName がこのノードのホスト名と異なる場合 (hostname -s で報告される)、このホストが動作する slurm.conf の NodeName に設定する必要があります。

### `service`

このモジュールが実行されるべき pam サービス名。デフォルトでは、このモジュールが設計された sshd に対してのみ実行されます。login" や "*" のような別のサービス名を指定することで、 どのようなサービスコンテキストでもこのモジュールが動作するようになります。ローカルの pam ログインの場合、このモジュールは予期しない動作やセキュリティの問題を引き起こす可能性があります。したがって、サービス名が一致しない場合、このモジュールは採用ロジックを実行せず、即座に PAM_IGNORE を返します。




Slurm Configuration 
-------------------------
 
slurm.confに`PrologFlags=contain` を設定する必要があります。これは、ssh で起動されたプロセスが採用される "extern" ステップを設定します。また、slurm.confでtask/cgroupプラグインを有効にする必要があります。Slurm cgroups ガイドを参照してください。

### 重要 

このモジュールを使用する前に、`PrologFlags=contain` を設定する必要があります。このモジュールは、すでに起動されているローカルステップのチェックを基本としています。externステップのように、ユーザがノード上にステップを持っていない場合、モジュールは、ユーザがノードに割り当てられたジョブを持っていないと仮定します。PAMモジュールの構成によっては、`PrologFlags=contain` を指定しないユーザーのssh試行をすべて誤って拒否することがあります。

slurm.conf の UsePAM オプションは pam_slurm_adopt とは関係ありません。

Other Configuration
-----------------------

`/etc/ssh/sshd_config` で `UsePAM` が `On` に設定されていることを確認します (デフォルトでは On のはずです)。

### ファイアウォール、IPアドレス、その他

ユーザが ssh を起動するような IP アドレスであれば、slurmd にアクセスできるはずです。ソースジョブを決定する RPC は、その特定の IP アドレス上の slurmd ポートに到達できる必要があります。ログインノードなど、送信元ノードに slurmd がない場合は、RPC を黙って落とすのではなく、拒否させる方がよいでしょう。これにより、RPC イニシエータへの応答がより良くなります。

### SELINUX

SELinuxはpam_slurm_adoptと衝突する可能性がありますが、一般的には並行して動作させることが可能です。これは、かなり標準的な Debian システムで使用された、タイプ強制ファイルの例です。これは、いくつかの方向性を示し、これを動作させるために必要なものを示すために提供されていますが、さらなる修正が必要な場合もあります。

```terminal
module pam_slurm_adopt 1.0;

require {
	type sshd_t;
	type var_spool_t;
	type unconfined_t;
	type initrc_var_run_t;
	class sock_file write;
	class dir { read search };
	class unix_stream_socket connectto;
}

#============= sshd_t ==============
allow sshd_t initrc_var_run_t:dir search;
allow sshd_t initrc_var_run_t:sock_file write;
allow sshd_t unconfined_t:unix_stream_socket connectto;
allow sshd_t var_spool_t:dir read;
allow sshd_t var_spool_t:sock_file write;
```

プラグインによっては、これ以上のパーミッションを要求されることもあり得ます。特に、job_container/tmpfsはこのようなものを要求します。

```terminal
module pam_slurm_adopt 1.0;

require {
	type nsfs_t;
	type var_spool_t;
	type initrc_var_run_t;
	type unconfined_t;
	type sshd_t;
	class sock_file write;
	class dir { read search };
	class unix_stream_socket connectto;
	class fd use;
	class file read;
	class capability sys_admin;
}

#============= sshd_t ==============
allow sshd_t initrc_var_run_t:dir search;
allow sshd_t initrc_var_run_t:sock_file write;
allow sshd_t nsfs_t:file read;
allow sshd_t unconfined_t:fd use;
allow sshd_t unconfined_t:unix_stream_socket connectto;
allow sshd_t var_spool_t:dir read;
allow sshd_t var_spool_t:sock_file write;
allow sshd_t self:capability sys_admin;
```

制限事項 
----------------

多要素認証のような代替認証方式では、pam_slurm_adopt によるプロセス採用が失敗する可能性があります。
Slurm で SELinux サポートを使用する場合、pam_slurm_adopt で開始したセッションは必ずしも関連するジョブと同じコンテキストになるとは限りません。

Intel MPI Library Developer Guide for Linux* OS から抜粋
========================

Job Schedulers Support
---------------------------------

### Slurm

https://www.intel.com/content/www/us/en/develop/documentation/mpi-developer-guide-linux/top/running-applications/job-schedulers-support.html

Slurm のジョブスケジューラは mpirun と mpiexec で自動的に検出されます。ジョブスケジューラの検出は mpirun ではデフォルトで有効、mpiexec では(マシンファイルで)ホスト名が指定されていない場合に有効です。唯一の前提条件は、`I_MPI_PIN_RESPECT_CPUSET=0` に設定することです。

自動検出のために、Hydraプロセスマネージャは以下の環境変数を使用します。

- `SLURM_JOBID`
- `SLURM_NODELIST`
- `SLURM_NNODES`
- `SLURM_NTASKS_PER_NODE` または `SLURM_NTASKS`
- `SLURM_CPUS_PER_TASK`

これらの変数を用いて、Hydraはどのノードが利用可能か、いくつのノードが割り当てられたか、ノードあたりのMPIプロセスの数、およびMPIプロセスあたりのドメインサイズを決定することができます。

- `SLURM_NTASKS_PER_NODE` は `I_MPI_PERHOST` の暗黙の指定に使われ、代わりに`SLURM_NTASKS`/`SLURM_NNODES` が使われます。
- `SLURM_CPUS_PER_TASK` の値は、暗黙のうちに `I_MPI_PIN_DOMAIN` を定義し、デフォルトの "auto" を上書きします。

Slurm 変数のいくつかが定義されていない場合、対応する Intel MPI のデフォルトが使用されます。この環境では、Slurm で次のようなコマンドを実行するだけで十分です。

```bash:command
export I_MPI_PIN_RESPECT_CPUSET=0; mpirun ./myprog
```

この方法は、単純なSlurmのピン留め（例えば、Slurmフラグ `--cpus-per-task` のみを使用した場合）の標準的な状況で動作します。

Slurm のジョブがより複雑な pinning 設定を必要とする場合 (Slurm フラグ `--cpu-bind` を使用)、プロセスの pinning が不正確になる可能性があります。この場合、以下のどちらかにするとと、ピン留めを完全に制御できます (Developer Reference の「プロセスのピン留め」および「プロセスのピン留めに関する環境変数」 を参照)。

- srun で MPI を起動する
- 環境変数 `I_MPI_PIN_RESPECT_CPUSET=0` を設定してインテル® MPI ライブラリーのピン留めを有効にする

mpirun を使用する場合、必要な pinning は `I_MPI_PIN_DOMAIN` を使用して明示的に複製される必要があります。

Slurm ジョブスケジューラが自動的に検出されなかった場合、 `I_MPI_HYDRA_RMK=slurm` または `I_MPI_HYDRA_BOOTSTRAP=slurm` 変数を設定します (Developer Reference, "Hydra Environment Variables" を参照して下さい)。

リモートノードでプロセスを実行するために、Hydra は srun ユーティリティを使用します。これらの環境変数は、この場合にどのユーティリティを使うかを制御します (デベロッパーリファレンス "Hydra 環境変数" を参照してください)。

- `i_mpi_hydra_bootstrap`
- `i_mpi_hydra_bootstrap_exec`
- `i_mpi_hydra_bootstrap_exec_extra_args`

`I_MPI_PMI_LIBRARY` 環境変数を設定することにより、 Hydra を使わずに srun ユーティリティでアプリケーションを起動することもできます (Developer Reference, "その他の環境変数" を参照してください)。
現在サポートされている PMI のバージョンは PMI-1 と PMI-2 です。
デフォルトでは、インテル® MPI ライブラリーはスケジューラーが提供するホストごとのプロ セス配置を使用します。つまり、`-ppn` オプションは何の効果もありません。この動作を変更し、`-ppn` (および関連するオプションと変数) でプロセス配置を制御するには、 `I_MPI_JOB_RESPECT_PROCESS_PLACEMENT=off` に設定します。




参考
=================

- https://slurm.schedmd.com/slurm.conf.html#OPT_MpiDefault
- https://slurm.schedmd.com/mpi_guide.html#intel_mpi
- https://slurm.schedmd.com/pam_slurm_adopt.html
- https://www.intel.com/content/www/us/en/develop/documentation/mpi-developer-reference-linux/top/environment-variable-reference/other-environment-variables.html
- https://keichi.dev/post/pmi/