User Tools

Site Tools


自作クラスタ計算機:mpiによる並列計算

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
自作クラスタ計算機:mpiによる並列計算 [2020/03/02 14:57]
koudai [準備]
自作クラスタ計算機:mpiによる並列計算 [2020/03/02 18:42]
koudai [ノード間並列計算]
Line 2: Line 2:
  
   * 実際にMPIを用いたノード内およびノード間の並列計算を行います   * 実際にMPIを用いたノード内およびノード間の並列計算を行います
-  * 事前にOpenMPIMPICH2などのMPIライブラリを管理ノードにインストールしてください+  * 事前にOpenMPIMPICH2, Intel MPIなどのMPIライブラリを管理ノードにインストールしてください
   * 例えばOpenMPIであれば次のようにインストールできます<code>   * 例えばOpenMPIであれば次のようにインストールできます<code>
 $ sudo apt install openmpi-bin libopenmpi-dev $ sudo apt install openmpi-bin libopenmpi-dev
 </code> </code>
 +  * **同じコンピュータに複数のMPIを入れると競合を起こしてMPIが動かなくなることがあります**
  
 ====== 準備 ====== ====== 準備 ======
  
-事前に各ノードのCPUの物理コア数とスレッド数を確認してください+===== ハードウェアの確認 ===== 
 + 
 +事前に各ノードのCPUのコア数(物理コア数とスレッド数(論理コア数)を確認してください
  
   * CPU数<code>$ cat /proc/cpuinfo | grep "physical id"</code>   * CPU数<code>$ cat /proc/cpuinfo | grep "physical id"</code>
     * 出てきた数字の種類の数だけCPUがあります。0と1の2種類であれば、そのノードにはCPUが2つあります。      * 出てきた数字の種類の数だけCPUがあります。0と1の2種類であれば、そのノードにはCPUが2つあります。 
-  * CPUあたりの物理コア数<code>$ cat /proc/cpuinfo | grep "cpu cores"</code> +  * CPUあたりのコア数<code>$ cat /proc/cpuinfo | grep "cpu cores"</code> 
-    * 出てきた数字がCPUあたりの物理コア数になります  +    * 出てきた数字がCPUあたりのコア数になります  
-  * スレッド数(論理コア数)<code>$ cat /proc/cpuinfo | grep "processor"</code> +  * スレッド数<code>$ cat /proc/cpuinfo | grep "processor"</code> 
-    * 表示される行数が スレッド数 = 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鍵を作成します。パスフレーズを聞かれるところでは、**なにも入力せずに**エンターを押します<code>
 +$ ssh-keygen -t rsa
 +Generating public/private rsa key pair.
 +Enter file in which to save the key (/home/sugimoto/.ssh/id_rsa): 
 +Created directory '/home/sugimoto/.ssh'.
 +Enter passphrase (empty for no passphrase): 
 +Enter same passphrase again: 
 +Your identification has been saved in /home/sugimoto/.ssh/id_rsa.
 +Your public key has been saved in /home/sugimoto/.ssh/id_rsa.pub.
 +The key fingerprint is:
 +SHA256:ZLnV/uJ8+lml7EdU+j8sjGJdxqF6F+tyg8FrD2hP3hI sugimoto@kanri
 +The key's randomart image is:
 ++---[RSA 2048]----+
 +|                 |
 +|         . .    .|
 +|        + . .  ..|
 +|       o o . .. .|
 +|        S . + .o.|
 +|          .E B .+|
 +|         ooo@ B.o|
 +|        .++%oX.=o|
 +|        . +o@B*..|
 ++----[SHA256]-----+
 +</code>
 +  - 公開鍵を設置します<code>
 +$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
 +</code>
 +    * NFSサーバを設置しているので、管理ノードにおいてある鍵は計算ノードでも見えます
 +  - 初回接続時に表示されるメッセージを抑制させます<code>
 +$ echo "StrictHostKeyChecking no" >> ~/.ssh/config
 +</code>
 +  - 権限を変更します<code>
 +$ chmod 600 ~/.ssh/id_rsa
 +$ chmod 600 ~/.ssh/authorized_keys
 +$ chmod 700 ~/.ssh/
 +</code>
 +  - 実際にパスワード無しで計算ノードにログインできるか確かめます<code>
 +$ ssh keisan11
 +</code>
  
 ====== 並列計算 ====== ====== 並列計算 ======
Line 34: Line 81:
 次のコードを使って説明します 次のコードを使って説明します
  
-<file - test.c>+<file - hello.c>
 #include <stdio.h> #include <stdio.h>
-#include <mpi.h>+#include "mpi.h"
  
-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] = '\0';     name[len] = '\0';
-    printf( "I am %d of %d from %s\n", rank, size, name ); +     
-    MPI_Barrier( MPI_COMM_WORLD ); +    printf( "Hello World! I am %d of %d from %s.\n", rank, size, name );
-    MPI_Finalize();+
  
 +    MPI_Finalize();
     return 0;     return 0;
 } }
Line 56: Line 104:
  
   * プログラムのコンパイルは次のようにします<code>   * プログラムのコンパイルは次のようにします<code>
-$ mpicc test.c+$ mpicc -o hello hello.c 
 +$ mpiicc -o hello hello.c   # Intel MPIを使用する場合
 </code> </code>
 +  * 試しに管理ノードで走らせてみます<code>
 +$ mpirun -n 4 hello
 +Hello World! I am 0 of 4 from kanri.
 +Hello World! I am 1 of 4 from kanri.
 +Hello World! I am 2 of 4 from kanri.
 +Hello World! I am 3 of 4 from kanri.
 +</code>
 +
 +
 +
 +===== ノード内並列計算 =====
 +
 +指定した計算ノードにジョブを投げてみます。
 +
 +  * MPIで指定のホストに投げる場合は、オプション<nowiki>--host</nowiki>でホスト名を指定します
 +  * 計算ノードのkeisan11にジョブを投げる場合は次のようにします<code>
 +$ mpirun -n 24 --host keisan11 hello
 +Hello World! I am 0 of 24 from keisan11.
 +Hello World! I am 1 of 24 from keisan11.
 +Hello World! I am 2 of 24 from keisan11.
 +Hello World! I am 3 of 24 from keisan11.
 +(以下略)
 +</code>
 +
 +
 +===== ノード間並列計算 =====
 +
 +==== 通常の使い方 ====
 +
 +複数の計算ノードにわたるジョブを投げてみます。
 +
 +  * オプション<nowiki>--host</nowiki>で複数のホスト名を指定します
 +  * 計算ノードkeisan11, keisan12, keisan13にジョブを投げる場合は次のようにします<code>
 +$ mpirun -n 72 --host keisan11,keisan12,keisan13 hello
 +Hello World! I am 0 of 72 from keisan11.
 +Hello World! I am 1 of 72 from keisan12.
 +Hello World! I am 2 of 72 from keisan13.
 +Hello World! I am 3 of 72 from keisan11.
 +Hello World! I am 4 of 72 from keisan12.
 +Hello World! I am 5 of 72 from keisan13.
 +(以下略)
 +</code>
 +    * MPIが各ノードにプロセスを割り振ります
 +    * プロセスは keisan11 -> keisan12 -> keisan13 -> keisan11 -> ... の順に割り振られて行きます
 +
 +
 +==== ホストファイルによるジョブの投入 ====
 +
 +例えばノードごとに性能差がある場合など、ノードごとのプロセス数を自分で管理したい場合はホストファイルを作成します。
 +例えばkeisan11に2スレッド、keisan12に3スレッド割り振りたい場合は次のファイルを用意します。
 +
 +  * MPICH, Intel MPIの場合
 +<file - my_hosts>
 +keisan11:2
 +keisan12:3
 +</file>
 +  * OpenMPIの場合
 +<file - my_hosts>
 +keisan11 slots=2
 +keisan12 slots=3
 +</file>
 +
 +次のように実行します
 +<code>
 +$ mpirun -n 6 --host keisan11,keisan12,keisan13 hello
 +Hello World! I am 0 of 6 from keisan11.
 +Hello World! I am 1 of 6 from keisan11.
 +Hello World! I am 2 of 6 from keisan12.
 +Hello World! I am 3 of 6 from keisan12.
 +Hello World! I am 4 of 6 from keisan12.
 +Hello World! I am 5 of 6 from keisan11.
 +</code>
 +    * プロセスは keisan11 -> keisan11 -> keisan12 -> keisan12 -> keisan12 -> keisan11 -> keisan11 -> keisan12 -> keisan12 -> keisan12 -> keisan11 -> ... の順に割り振られて行きます
 +
 +====== 参考 ======
 +
 +  * https://www.hpci-office.jp/pages/seminar_texts
  
自作クラスタ計算機/mpiによる並列計算.txt · Last modified: 2023/12/26 23:43 by koudai