Windows(Visual Studio 2012)上でboost::MPIで並列計算できるようになるまで

# Visual StudioでMPIの開発がしたい #

VSの強力なIDE支援を受けて開発したいんですが、MPIとなると、分散メモリ型システムが手元にある前提で説明されることが多くて、あまり情報がありませんでした。
しかも割とboost使いたがりなので、boostのないC++開発とかしたくありません。
もちろんC言語そのままとか、もっと嫌です。

というわけで、これは、私がVS2012を使ってboost::MPIを動かせるようにするまでの記録です。

（前提として、Visual Studioとboostをある程度使えることを想定しています）

## 目標 ##

最終的にこれを動かすのを目標にします↓

```cpp:MsMpiBoost.cpp
#define MSMPI_NO_DEPRECATE_20

#include <iostream>
#include <boost/mpi.hpp>

int main()
{
	// MPI環境（MPI_InitとFinalizeをやってくれる）
	boost::mpi::environment  env(true);

	// MPI_COMM_WORLDで通信するよう
	boost::mpi::communicator world;


	// 交換するデータ
	std::string msg = "Hi";

	// 偶数番プロセスから
	if((world.rank()%2) == 0)
	{
		// 奇数番プロセスへ"Hello"を送信
		world.send(world.rank()+1, 0, std::string("Hello"));
	}	
	// 奇数番プロセスでは
	else
	{
		// 偶数番プロセスから送られてきた文字列を受信
		world.recv(world.rank()-1, 0, msg);
	}
	

	// メッセージを表示
	std::cout << msg << " @ " << world.rank() << std::endl;

	
	// 終了
	if(world.rank() == 0 )
	{
		system("pause");
	}
	return 0;
}
```

## 1. MS-MPIの準備 ##

0. MPI実装はいくつかありますが、MS-MPIを使います（OpenMPIやMPICHだとVS連携が大変面倒っぽかったのでやめました）。今回はバージョン2012を使用しました。MSのダウンロードリンクはコロコロ変わるので、"HPC Pack 2012 MS-MPI"あたりで[検索](http://www.bing.com/search?q=HPC+Pack+2012+MS-MPI)すれば一番上とかにヒットします。
0. ダウンロード＆インストールしてください。
0. HPC Packのインストールディレクトリを確認して下さい（以降、`C:\Program Files\Microsoft HPC Pack 2012`にあるものとして話を進めます）
0. インクルードディレクトリに`C:\Program Files\Microsoft HPC Pack 2012\Inc`を加えます
0. ライブラリディレクトリに`C:\Program Files\Microsoft HPC Pack 2012\Lib\amd64`を加えます（x64の場合）。Win32の場合は`C:\Program Files\Microsoft HPC Pack 2012\Lib\i386`です。両方追加しておいても大丈夫なようです。
0. リンカの追加の依存ライブラリに`msmpi.lib`を追加します。
0. 構成プロパティちょっかのデバッグで、ローカル Windows デバッガーを変更します。コマンドを`C:\Program Files\Microsoft HPC Pack 2012\Bin\mpiexec.exe`にして、引数を`-n 8 $(TargetPath)`にします。8の部分を増やすと実行プロセス数が変化します。なお、MPI Cluster DebuggerはVS2012には未対応のようです・・・。

## 2. MS-MPIの動作確認 ##

↓をビルド＆実行(F5)してみてください。Rank 0 OKとRank 2 Readyが表示されれば動いています。

```cpp:MsMpiTest.cpp
#include <iostream>
#include <mpi.h>

int main(int argc, char* argv[])
{
	// 初期化
	MPI_Init(&argc, &argv);

	// rank取得
	int rank;
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);

	// rank0のみ
	if (rank == 0)
	{
		// OKで一時停止
		std::cout << "Rank 0 OK!" << std::endl;
		std::system("pause");
	}
	// それ以外は
	else
	{
		// Ready
		std::cout << "Rank " << rank << " Ready!" << std::endl;
	}

	// 終了
	MPI_Finalize();
	return 0;
}
```

## 3. boost::MPIの準備 ##
「boost::MPIなんて使わないよ！」って人は、↑までで完了しているので、良きナマMPIライフをお送りください。

0. [boost](http://boost.org)を持ってきます。私は1.51を使ってますが、開発版でも動いたので、あまりバージョン依存ないようです。
（余談ですが、boostの開発版はsvnでしか提供されていませんが、gitで使いたい場合、 [githubにあるmirrorプロジェクト](https://github.com/mirror/boost)から持ってくるとよいです。）
0. bootstrapとb2を使って、まずは普通にビルドしてみます（詳細な手順は[letsboost](http://www.kmonos.net/alang/boost/install.html)あたりが参考になります）。この時点でビルドできなかったらboostそのものが使えてないので修正してください。
0. tools/build/v2/user-config.jamを修正します。テキストエディタで開いて、一番最後に`using mpi ;`を追加します。
0. tools/build/v2/tools/mpi.jamを修正します。テキストエディタで開いて、`cluster_pack_path_native`をHPC Packのインストールディレクトリに修正します(`local cluster_pack_path_native = "C:\\Program Files\\Microsoft HPC Pack 2012" ;`)。
0. その下の`if [ GLOB $(cluster_pack_path_native)\\Include : mpi.h ]`を`if [ GLOB $(cluster_pack_path_native)\\Inc : mpi.h ]`に修正します。
0. さらにその下の`options = <include>$(cluster_pack_path)/Include`を`options = <include>$(cluster_pack_path)/Inc`に修正します。
0. もう一度b2でビルドします。C4996とかの警告がいっぱい出ますが、無視して大丈夫っぽいです（boostをcl.exeでビルドすると警告盛りだくさんなのはいつものことなので）。
0. インクルードディレクトリおよびライブラリディレクトリにboostを入れ忘れないようにしてください（インクルード＝boostのディレクトリ、ライブラリ＝BOOST_INC\stage\lib）

## 4. boost::MPIの動作準備 ##

冒頭のMsMpiBoost.cppをビルド＆実行してみてください。偶数番プロセスでHi、奇数番プロセスでHelloが出たら実行できています。

## おわりに ##

mpi.jamの修正あたりはあまり情報がなかったので、役に立てばなによりです。
MPIそのものの使い方等は別途勉強してください（私も勉強中です）。

最後に、参考文献を挙げておきます。よく分からなかったり端折った部分はこっちを参照してください。

* [boostのインストール方法](http://www.kmonos.net/alang/boost/install.html)
* [Visual Studio 2012におけるMS-MPIの利用](http://www-fps.nifs.ac.jp/ito/memo/msmpi03.html)
* [boost::MPIの使い方](http://www.kmonos.net/alang/boost/classes/mpi.html)
* [MPI による並列計算](https://sites.google.com/site/boostjp/tips/mpi)