This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
自作クラスタ計算機:mpiによる並列計算 [2020/03/02 14:56] koudai [準備] |
自作クラスタ計算機:mpiによる並列計算 [2020/03/03 16:03] koudai [通常の使い方] |
||
---|---|---|---|
Line 2: | Line 2: | ||
* 実際にMPIを用いたノード内およびノード間の並列計算を行います | * 実際にMPIを用いたノード内およびノード間の並列計算を行います | ||
- | * 事前にOpenMPIやMPICH2などのMPIライブラリを管理ノードにインストールしてください | + | * 事前にOpenMPI, MPICH2, Intel MPIなどのMPIライブラリを管理ノードにインストールしてください |
- | * 例えばOpenMPIであれば次のようにインストールできます< | + | * OpenMPIの場合、次のようにaptで簡単にインストールできるので、特にこだわりがなければお勧めです< |
$ sudo apt install openmpi-bin libopenmpi-dev | $ sudo apt install openmpi-bin libopenmpi-dev | ||
</ | </ | ||
+ | * **複数のMPIを一つのコンピュータに入れると、競合を起こしてMPIが動かなくなります** | ||
====== 準備 ====== | ====== 準備 ====== | ||
- | 事前に各ノードのCPUのコア数とスレッド数を確認してください | + | ===== ハードウェアの確認 ===== |
+ | |||
+ | 事前に各ノードのCPUのコア数(物理コア数)とスレッド数(論理コア数)を確認してください | ||
* CPU数< | * CPU数< | ||
* 出てきた数字の種類の数だけCPUがあります。0と1の2種類であれば、そのノードにはCPUが2つあります。 | * 出てきた数字の種類の数だけCPUがあります。0と1の2種類であれば、そのノードにはCPUが2つあります。 | ||
* CPUあたりのコア数< | * CPUあたりのコア数< | ||
- | * 出てきた数字がCPUあたりの物理コア数になります | + | * 出てきた数字がCPUあたりのコア数になります |
- | * スレッド数(論理コア数)< | + | * スレッド数< |
- | * 表示される行数が スレッド数 = CPU数 × CPUあたりのコア数 に対応します。Hyper-Threadingが有効の場合、論理コア数は物理コア数の2倍になります。 | + | * 表示される行数が スレッド数 = CPU数 × CPUあたりのコア数 に対応します。通常は論理コア数と物理コア数は等しいですが、Hyper-Threadingが有効の場合は論理コア数が物理コア数の2倍になります。 |
* Hyper-Threadingは見かけ上のコア数が2倍になる技術であり、並列計算プログラムで並列化効率が良い場合は逆に計算速度が著しく低下します。これは1つの物理コアに2つのジョブが投入されてしまうために発生します。 | * Hyper-Threadingは見かけ上のコア数が2倍になる技術であり、並列計算プログラムで並列化効率が良い場合は逆に計算速度が著しく低下します。これは1つの物理コアに2つのジョブが投入されてしまうために発生します。 | ||
- | * 並列化されたスレッドごとの並列化効率が著しく悪く、1つのスレッドの計算が終わっているのに別のスレッドの計算は続いている、というような場合にのみ有効です。 | + | * スレッドごとの計算の重さのバランスが著しく悪く、1つのスレッドの計算が終わっているのに別のスレッドの計算は続いている、というような場合にのみ有効です。 |
* よくわからない場合は、BIOSを使ってHyper-Threadingをオフにするか、MPIでのジョブ投入時に並列数を物理コア数以下にすることが望ましいです。 | * よくわからない場合は、BIOSを使ってHyper-Threadingをオフにするか、MPIでのジョブ投入時に並列数を物理コア数以下にすることが望ましいです。 | ||
+ | ===== SSHの導入 ===== | ||
+ | |||
+ | 管理ノードと計算ノードの間の通信はSSHで行います。 | ||
+ | * 現状のままだと管理ノードから計算ノードへ入る際にパスワードの入力が必要ですが、ジョブ投入のたびにパスワードを入力するのは現実的ではありません。 | ||
+ | * そこでパスフレーズなしのSSH鍵を作成することで、パスワードの入力を回避します | ||
+ | |||
+ | - 管理ノードのジョブを投げるユーザーのアカウント(以下ではsugimotoとします)にログインし、SSH鍵を作成します。パスフレーズを聞かれるところでは、**なにも入力せずに**エンターを押します< | ||
+ | $ ssh-keygen -t rsa | ||
+ | Generating public/ | ||
+ | Enter file in which to save the key (/ | ||
+ | Created directory '/ | ||
+ | Enter passphrase (empty for no passphrase): | ||
+ | Enter same passphrase again: | ||
+ | Your identification has been saved in / | ||
+ | Your public key has been saved in / | ||
+ | The key fingerprint is: | ||
+ | SHA256: | ||
+ | The key's randomart image is: | ||
+ | +---[RSA 2048]----+ | ||
+ | | | | ||
+ | | . . .| | ||
+ | | + . . ..| | ||
+ | | o o . .. .| | ||
+ | | S . + .o.| | ||
+ | | .E B .+| | ||
+ | | ooo@ B.o| | ||
+ | | .++%oX.=o| | ||
+ | | . +o@B*..| | ||
+ | +----[SHA256]-----+ | ||
+ | </ | ||
+ | - 公開鍵を設置します< | ||
+ | $ cat ~/ | ||
+ | </ | ||
+ | * NFSサーバを設置しているので、管理ノードにおいてある鍵は計算ノードでも見えます | ||
+ | - 初回接続時に表示されるメッセージを抑制させます< | ||
+ | $ echo " | ||
+ | </ | ||
+ | - 権限を変更します< | ||
+ | $ chmod 600 ~/ | ||
+ | $ chmod 600 ~/ | ||
+ | $ chmod 700 ~/.ssh/ | ||
+ | </ | ||
+ | - 実際にパスワード無しで計算ノードにログインできるか確かめます< | ||
+ | $ ssh keisan11 | ||
+ | </ | ||
====== 並列計算 ====== | ====== 並列計算 ====== | ||
Line 34: | Line 81: | ||
次のコードを使って説明します | 次のコードを使って説明します | ||
- | <file - test.c> | + | <file - hello.c> |
#include < | #include < | ||
- | # | + | # |
- | int main(int argc, char **argv) { | + | int main( int argc, char *argv[] ) |
+ | { | ||
int rank, size, len; | int rank, size, len; | ||
char name[MPI_MAX_PROCESSOR_NAME]; | char name[MPI_MAX_PROCESSOR_NAME]; | ||
Line 47: | Line 95: | ||
MPI_Get_processor_name( name, &len ); | MPI_Get_processor_name( name, &len ); | ||
name[len] = ' | name[len] = ' | ||
- | printf( "I am %d of %d from %s\n", rank, size, name ); | + | |
- | MPI_Barrier( MPI_COMM_WORLD ); | + | |
- | MPI_Finalize(); | + | |
+ | MPI_Finalize(); | ||
return 0; | return 0; | ||
} | } | ||
Line 56: | Line 104: | ||
* プログラムのコンパイルは次のようにします< | * プログラムのコンパイルは次のようにします< | ||
- | $ mpicc test.c | + | $ mpicc -o hello hello.c |
+ | $ mpiicc -o hello hello.c | ||
</ | </ | ||
+ | * 試しに管理ノードで走らせてみます< | ||
+ | $ 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で指定のホストに投げる場合は、オプション< | ||
+ | * 計算ノードのkeisan11にジョブを投げる場合は次のようにします< | ||
+ | $ mpirun -n 8 -hosts keisan11 ./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 | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== ノード間並列計算 ===== | ||
+ | |||
+ | ==== 通常の使い方 ==== | ||
+ | |||
+ | 複数の計算ノードにわたるジョブを投げてみます。 | ||
+ | |||
+ | * オプション< | ||
+ | * 計算ノードkeisan11, | ||
+ | $ mpirun -hosts keisan11, | ||
+ | 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 -> ... の順に割り振られていきます | ||
+ | |||
+ | ==== ホストファイルによるジョブの投入 ==== | ||
+ | |||
+ | 例えば計算ノードによってコア数が異なる場合など、ノードごとのプロセス数を自分で管理したい場合はホストファイルを作成します。 | ||
+ | |||
+ | * MPICH, Intel MPIの場合 | ||
+ | <file - my_hosts> | ||
+ | keisan11:2 | ||
+ | keisan12:4 | ||
+ | </ | ||
+ | * OpenMPIの場合 | ||
+ | <file - my_hosts> | ||
+ | keisan11 slots=2 | ||
+ | keisan12 slots=4 | ||
+ | </ | ||
+ | |||
+ | 次のように実行します | ||
+ | < | ||
+ | $ mpirun -n 6 -f my_hosts ./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の場合は< | ||
+ | * https:// | ||
+ | |||
+ | ====== 参考 ====== | ||
+ | |||
+ | * https:// | ||