====== 概要 ======
* 実際にMPIを用いたノード内およびノード間の並列計算を行います
* 事前にOpenMPI, MPICH2, Intel MPIなどのMPIライブラリを管理ノードでビルドし、NFSによって計算ノードと共有してください -> [[数値計算ライブラリ:OpenMPI]]
* /homeディレクトリはNFSサーバによって、管理ノードと計算ノードで共有されているとします
====== 準備 ======
===== ハードウェアの確認 =====
事前に各ノードのCPUのコア数(物理コア数)とスレッド数(論理コア数)を確認してください
* CPU数$ cat /proc/cpuinfo | grep "physical id"
* 出てきた数字の種類の数だけCPUがあります。0と1の2種類であれば、そのノードにはCPUが2つあります。
* CPUあたりのコア数$ cat /proc/cpuinfo | grep "cpu cores"
* 出てきた数字がCPUあたりのコア数になります
* スレッド数$ cat /proc/cpuinfo | grep "processor"
* 表示される行数が スレッド数 = CPU数 × CPUあたりのコア数 に対応します。通常は論理コア数と物理コア数は等しいですが、Intel Hyper-Threadingが有効の場合は論理コア数が物理コア数の2倍になります。
* Hyper-Threadingは見かけ上のコア数が2倍になる技術です。2つのプロセスを1つのCPU物理コアで実行するときに、効率よくリソースを割り振ります
* OpenMPやMPIを使った並列計算をするときに物理コア数以上のプロセス数を割り当てても、トータルの計算速度にほとんどご利益がない(遅くなることもある)ことが多いです
* BIOSからHyper-Threadingをオフにすることもできます
====== 並列計算 ======
作業は全て管理ノードで行います
* mpirunを実行するノード(管理ノード)とプログラムを動かすノード(計算ノード)が異なる場合は、mpirunを実行したノードと同じ名前のディレクトリに移動してプログラムを動かす仕組みになっています
* 今回生成したクラスタマシンでは、NFSサーバの機能により、管理ノードにあるプログラムが全ノードに配布されます
===== サンプルプログラム =====
次のコードを使って説明します
#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 hello hello.c
$ mpiicc -o hello hello.c # Intel MPIを使用する場合
* 試しに管理ノードで走らせてみます
$ mpirun -n 4 ./hello
Hello world: rank 0 of 4 running on kanri
Hello world: rank 1 of 4 running on kanri
Hello world: rank 2 of 4 running on kanri
Hello world: rank 3 of 4 running on kanri
===== ノード内並列計算 =====
指定した計算ノードにジョブを投げてみます。
* MPIで指定のホストに投げる場合は、オプション-hostsでホスト名を指定します
* 計算ノードのkeisan11にジョブを投げる場合は次のようにします
$ mpirun -hosts keisan11 -n 8 ./hello
Hello world: rank 0 of 8 running on keisan11
Hello world: rank 1 of 8 running on keisan11
Hello world: rank 2 of 8 running on keisan11
Hello world: rank 3 of 8 running on keisan11
Hello world: rank 4 of 8 running on keisan11
Hello world: rank 5 of 8 running on keisan11
Hello world: rank 6 of 8 running on keisan11
Hello world: rank 7 of 8 running on keisan11
* ホスト名の代わりにIPアドレスでも可能です
===== ノード間並列計算 =====
==== 通常の使い方 ====
複数の計算ノードにわたるジョブを投げてみます。
* 計算ノードkeisan11, keisan12, keisan13にジョブを投げる場合は次のようにします
$ mpirun -hosts keisan11,keisan12,keisan13 -n 8 -ppn 2 ./hello
Hello world: rank 0 of 8 running on keisan11
Hello world: rank 1 of 8 running on keisan11
Hello world: rank 2 of 8 running on keisan12
Hello world: rank 3 of 8 running on keisan12
Hello world: rank 4 of 8 running on keisan13
Hello world: rank 5 of 8 running on keisan13
Hello world: rank 6 of 8 running on keisan11
Hello world: rank 7 of 8 running on keisan11
* オプション-ppnでノードあたりのプロセス数を指定します
* プロセスは keisan11 -> keisan11 -> keisan12 -> keisan12 -> keisan13 -> keisan13 -> keisan11 -> keisan11 -> keisan12 -> ... の順に割り振られていきます
==== ホストファイルによるジョブの投入 ====
ホスト名を毎回入力したくない、計算ノードによってプロセス数を変えたいなどの場合は、ホストファイルを作成します。
* OpenMPIの場合
keisan11 slots=2
keisan12 slots=4
* MPICH, Intel MPIの場合
keisan11:2
keisan12:4
次のように実行します
$ mpirun -n 6 -f hosts.txt ./hello
Hello world: rank 0 of 6 running on keisan11
Hello world: rank 1 of 6 running on keisan11
Hello world: rank 2 of 6 running on keisan12
Hello world: rank 3 of 6 running on keisan12
Hello world: rank 4 of 6 running on keisan12
Hello world: rank 5 of 6 running on keisan12
* プロセスは keisan11 -> keisan11 -> keisan12 -> keisan12 -> keisan12 -> keisan12 -> keisan11 -> keisan11 -> keisan12 -> keisan12 -> keisan12 -> keisan12 -> keisan11 -> ... の順に割り振られて行きます
* Intel MPIの場合は-fの代わりに-machinefileを使用してください
* https://software.intel.com/en-us/articles/controlling-process-placement-with-the-intel-mpi-library
====== 参考 ======
* https://www.hpci-office.jp/pages/seminar_texts