複数のWindows10 PCでMPIプログラムを並列実行したい！

並列計算プログラムが書きたくてMPIについて調べたけど
Windows 10環境でMPIプログラムの複数PC上での実行方法を書いている日本語記事が見つからなくて苦労したので
自分用の備忘録も兼ねて記事にします．

# はじめに
## MPIとは
**MPI**は**M**essage **P**assing **I**nterfaceの略で，分散メモリ間のメッセージ通信APIの規格です．
MPIライブラリとしてmpich, OpenMPI, MS-MPIなどがあります．

## 環境
* Windows 10のPC複数台
* Microsoft MPI(MS-MPI) 10.1.12498.18
* Visual Studio 2019

# 準備
## Microsoft MPIのインストール
[Microsoft MPIのGithubリポジトリ](https://github.com/Microsoft/Microsoft-MPI)に行き，readme.mdの`MS-MPI Downloads`から`MS-MPI v**.*.*`をクリック．
Microsoftのダウンロードページに飛ぶので，Downloadをクリック．下記画面が表示されるので，
`msmpisetup.exe`と`msmpisdk.msi`の**両方**にチェックを入れてNextをクリック．
適当なディレクトリに保存して両方実行する．規約に同意して手順通りインストールする．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334127/605a280b-dd31-f9c5-aa94-84c78ecd69f7.png)

## Visual Studioの設定とプログラムの作成
Microsoft MPIがインストール出来たら，Visual StudioでMPIプログラムを作成します．
言語はC++で，Empty Projectを作成します．
プロジェクトを作成したら，プラットフォームを`x64`にして，プロジェクトのプロパティを開いて以下の作業を行います．

* `Configuration Properties\C/C++\General`にある**Additional Include Directories**に
`$(MSMPI_INC);$(MSMPI_INC)\x64`を入力します．
* `Configuration Properties\Linker\General`にある**Additional Library Directories**に
`$(MSMPI_LIB64)`を入力します．
* `Configuration Properties\Linker\Input`にある**Additional Dependencies**のドロップダウンから，`<Edit...>`を選択してテキストボックスに`msmpi.lib`を入力し，OKをクリックします．

プロパティを適用したら`main.cpp`を作成します．`main.cpp`には以下の内容を入力します．
これは，各プロセスが自分のランクを出力するだけの簡単なプログラムです．入力したらビルドします．

※本記事ではプログラムの内容について詳しくは解説しません．詳しくは[公式のリファレンス](https://docs.microsoft.com/en-us/message-passing-interface/mpi-reference)等をご覧ください．

```C++:main.cpp
#include <mpi.h>
#include <iostream>

using namespace std;

int main(int argc, char* argv[]) {
	int rank, numprocs;
	int ierr;

	ierr = MPI_Init(&argc, &argv);

	ierr = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	ierr = MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

	cout << "Hello Parallel World! from " << rank << endl;

	ierr = MPI_Finalize();

	return 0;
}
```

コマンドプロンプトを起動してビルドしたプログラムの実行ファイルがあるディレクトリに移動して以下を実行します．`-np`の数字は実行するプロセスの数です．`%Program%`には実行ファイル名を入力してください．

```winbatch
mpiexec -np 4 .\%Program%.exe
```

実行結果は以下のようになると思います．順番がバラバラなことからプロセスごと別々に実行されているのが分かります．

```
Hello Parallel World! from 0
Hello Parallel World! from 2
Hello Parallel World! from 1
Hello Parallel World! from 3
```

# 複数台実行環境の整備
実行するMPIプログラムも完成したので，ここから複数台実行する環境を整備していきます．
使用するPCは全て同じネットワーク上に置いてください．
まず，使用するPCすべてにMicrosoft MPIをインストールします．
次に，全てのPCで共通のディレクトリにフォルダを作成します．今回は`C:\mpiwork`とします．

## 共有の設定
作成したフォルダのプロパティを開き，共有の設定を行います．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334127/bb0ae8b0-033a-654d-a026-08a29df7fd7c.png)
Sharingタブの`Share...`を開きます．ドロップダウンから`Everyone`を選択してAddをクリックします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334127/63c80c73-4411-a270-321a-bf5169d67cef.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334127/1f67f613-c83b-766f-8286-2288dee7d194.png)
`Share`をクリックして画面を閉じます．
共有の設定ができたら，コントロールパネルのNetwork and Sharing Centerを開きます．
画面左側にある`Change advanced sharing settings`を開きます．
All networksを開いて`Password protected sharing`の項目で`Turn on password protected sharing`を選択してください．

## 資格情報の設定
コントロールパネルのホームに戻って，Credential Managerを開きます．
Windows CredentialをクリックしてAdd Windows Credentialから資格情報を追加します．
PC名，ユーザー名，パスワードを入力して，自身以外のすべての資格情報を追加します．
PC名はWindowsの設定の`System\About`にある`Device Name`を参照してください．
全てのPCで資格情報を設定し終えたら，
プログラムを作成したPCのエクスプローラーで，各PCの`C:\mpiwork`にアクセスします．
ネットワーク上のフォルダにアクセスするには，アドレスバーに`\\%Device Name%\mpiwork\`を入力します．
`%Device Name%`には各PC名を入力してください．
アクセス出来たら，すべてのPCの共有フォルダに実行ファイルをコピーします．
## smpdの起動
MPIプログラムを実行する前に，smpdを起動しておきます．
smpdはMPI通信を処理するためのデーモンです．
全てのPCでコマンドプロンプトから以下を実行してsmpdを起動します．`-d 3`はデバッグ用途のため，なくても構いません．

```winbatch
smpd -d 3 -p 8677
```

# MPIプログラムの複数のPCでの実行
プログラムを作成したPCでMPIプログラムを実行します．
コマンドプロンプトで以下を実行してください`PC1`にはプログラムを作成したPCのPC名，`PC2`,`PC3`はほかのPCのPC名です．
`-hosts`の後の数字は使用するPCの数，その後使用するPCのPC名を羅列します．

```winbatch
mpiexec -hosts 3 PC1 PC2 PC3 .\%Program%.exe
```

成功すれば，単体での実行の時と同じように，PCの数だけ`Hello Parallel World!`が表示されたと思います．

# さいごに
初めての記事投稿なのでつたない文章であったと思いますが最後までご覧いただきありがとうございました．困っている方の助けになれたのなら光栄です．「同じ手順を踏んでも実行できなかった」「この手順はいらないのでは」「ここが間違っているなど」あればコメントいただけると助かります．