超音波流体屋のプログラム備忘録

MPICH2 (mpd, hydra)

最終更新:

usapfrog

- view
管理者のみ編集可
代表的なMPIソフト、MPICH2での並列計算方法の構築手順など。
CentOS Linux 6.5, mpich2 1.2.1。
ネットワークで繋がった複数の独立マシン間を通信する場合について扱う。
主にmpdの場合について扱うけど、バージョンが新しいhydra使うタイプのがずっと楽なので、
yumが対応してない場合は自分でビルドしたほうが良いかも。

1.双子マシンを準備する

最低限、Linuxのディストリビューションは揃える。
(CentOSとFedraで試したら、MPIライブラリの関係で駄目だった。)
ユーザー名も共通の物を準備しておく。

2.MPICH2のインストール

全マシンに。バージョンも揃えたほうがよい。
gcc, gfortranで良いなら、yumで mpich2とmpich2-develを取ってくる。
インテルやPGIのコンパイラを使いたければ、
環境変数CC, F77などを指定した後に自分でビルドする。
自分でビルドしたときは、/usr/local/mpich2以下のbinをPATHに、libをLD_LIBRARY_PATHに忘れずに追加する。
(参考)
MPICH2 : downloads
PGIコンパイラによる MPICH2 ライブラリ環境の構築(Linux)プロセス管理として MPD を使用
Intel CompilerとMPICH2のインストールメモ

3./etc/hostsの整備

これも全マシンで共通のほうがよい。例えば以下のとおり。
# vi /etc/hosts
127.0.0.1 localhost
192.168.1.2 server
192.168.1.3 client1
192.168.1.4 client2
server1などがhostnameをと違う場合はhostnameも登録しておくこと。
hostnameの調べ方はそのまま。
$ hostname
きちんとserver-clientマシン間でpingが通るかも確認する。

4.パスなしでssh通信の確立

RSA鍵認証でパスを打たなくてもseverからclientにsshできるようにしておく。
serverでssh-keygenをして、改行を連打(パスフレーズはいれない)
[server]
$ ssh-keygen
公開鍵をclient全員に送る
[server]
$ cd ~/.ssh
$ scp id_rsa.pub client1:

client側で公開鍵を登録する。パーミッションに注意する。
[client]
$ cd
$ cat id_rsa.pub >> .ssh/authorized_keys
$ rm id_rsa.pub
$ chmod 700 .ssh
$ chmod 600 .ssh/authorized_keys

(rootの場合)クライアント側でSELinuxを無効にする。
# setenforce 0
# vi /etc/sysconfig/selinux
SELINUX=disabled に変更

server側でパス無しでsshが動作するか確認する。
[server]
$ ssh client1 date

5..mpd.confの準備、mpdの動作チェック

hydraを使う場合は飛ばしてよい。
全マシンでsercretwordは共通とする。スペースや改行、形式も厳格に同じで。
後述するmpdboot時のエラー(handle_mpd_output 407)(handle_mpd_output 420)は主に.mpd.conf関連で発生するらしい。
$ vi .mpd.conf
secretword=hoge

$ chmod 600 .mpd.conf
mpdが正常に動作するか確認する。
$ mpd &
$ mpdallexit
mpdallexitはmpdデーモンの終了コマンド。
(参考)
MPICH2におけるmpdboot時の407エラー
handle_mpd_output 420

6.シングルプロセスおよびサーバのみでの実行テスト

以下のようなプログラム。
[~/mpitest.c]
  1. #include <unistd.h>
  2. #include "mpi.h"
  3. int main(int argc, char **argv)
  4. {
  5. int len,ierr;
  6. int my_rank;
  7. char hname[32];
  8. len = 32;
  9. MPI_Init( &argc, &argv );
  10. MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
  11. gethostname(hname,len);
  12. printf("My name is %s, Rank = %d \n",hname, my_rank);
  13. MPI_Finalize( );
  14. return 0;
  15. }
  16.  
コンパイルして、単純実行する、単マシンでのmpiexecを試す。
$ mpicc mpitest.c
$ ./a.out

[server, mpd]
$ mpd &
$ mpiexec -n 4 ./a.out
$ mpdallexit

[server, hydra]
$ mpiexec -n 4 ./a.out

以降しばらくmpdの場合。hydraを使う場合は、9-hydraまで飛ばしてよい。

7.ファイアウォールを切るかポート開放する

mpich2はssh22番以外のポートも経由して通信する。
支障がなければファイアウォールを切ってしまうのが早い。
CentOSは以下のコマンド。
[全マシン]
# /etc/init.d/iptables stop
(Fedra Coreは # systemctl stop iptables.service だった。)

ファイアウォールを維持して、計算したい場合はMPICHの使用するポートを環境変数で指定する。
(1プロセス1ポート使うので、ある程度の範囲は確保すること。狭すぎるとmpiexecで実行時にエラーが出る。)
[全マシン]
$ vi .bashrc
$ export MPICH_PORT_RANGE=57700:57800
その後、OS付属のファイアウォールツールや手動iptableなどで該当ポートを開放する。
CentOSなら、
# system-config-firewall
のその他から、57700-57800 TCPを指定し、iptableの再起動をする。
# /etc/init.d/iptables restart


8.mpdcheckでの相互通信の確認

[server]
$ mpdcheck -s 
で出てくるホスト、ポートをクライアント側で下記入力する。
[client]
$ mpdcheck -c [server] [port] 
無事通信できると以下のメッセージが出力される。
[server]
server successfully recvd msg from client: hello_from_client_to_server
[client]
client successfully recvd ack from server: ack_from_server_to_client

9.mpd.hostsの準備、mpdbootで手をつなぐ

mpd.hostsに計算に使用するサーバ、使用可能プロセス数を指定する。
[server]
$ vi mpd.hosts
server:2
client1:2
client2:4
mpdbootでclientマシンと連結する。ファイル名がmpd.hostsなら-f以下は省略可能。-n以降はマシン数を指定する。
[server]
$ mpdboot -n 3 -f mpd.hosts
エラーが出たら、--debugオプションを付けると詳細な原因を出力してくれる。
$ mpdboot -n 3 --debug
ファイアーウォールで引っかかると、(handle_mpd_output 407)エラーがでるので、上の設定を見直す。
/usr/bin/mpd.py以外にmpd.pyがあるためエラー(handle_mpd_output 420)となる場合は
clientの該当箇所にシンボリックリンクを貼るなどして対応する。

無事起動し、クライアントを認識しているかはmpdtraceで確認できる。
$ mpdtrace

10.実行(mpiexec, mpd)

mpdboot後、mpiexecで実行する。-nはプロセス数を指定する。
[server]
$ mpiexec -n 6 ./a.out
結果。通常順番はバラバラである。
My name is server, Rank = 0 
My name is server, Rank = 1 
My name is client1, Rank = 2 
My name is client1, Rank = 3 
My name is client2, Rank = 4 
My name is client2, Rank = 5
MPI系の実行エラーが出た場合は上記の使用ポート範囲が狭過ぎないか確認すること。

mpdを終了する。
[server]
$ mpdallexit


9-hydra.ホストの準備・実行ファイルの転送

適当なファイルmpi.hostsに計算に使用するサーバ、使用可能プロセス数を指定する。
[server]
$ vi mpi.hosts
server:2
client1:2
client2:4

NFSなどでストレージを共有してない場合、各マシンの同階層にプログラムを転送する必要がある。
[server]
$ scp a.out client1:
$ scp a.out client2:

mpi.hostsを使った全送信スクリプトなんかを組んでしまうと楽。
[bcast.sh (転送ファイル)] 現在ディレクトリを全クライアントノードに作成し、scpでファイルを転送する。
  1. #!/bin/bash
  2. CWD=`pwd`
  3. FILE=$1
  4. NUL=/dev/null
  5.  
  6. if [ $# -eq 0 ] ; then
  7. echo "no file specified."
  8. exit 1
  9. fi
  10.  
  11. for h in `cat mpi.hosts`; do
  12. host=${h%%:*}
  13. if [ $host != `hostname` ]; then
  14. echo $host
  15. ssh $host ls $CWD 1>$NUL 2>$NUL
  16. if [ $? -ne 0 ]; then
  17. ssh $host mkdir $CWD
  18. fi
  19. ls $FILE 1>$NUL 2>$NUL
  20. if [ $? -eq 0 ]; then
  21. scp $FILE $host:$CWD
  22. fi
  23. fi
  24. done
  25.  
$1=引数, $#=引数の数, $?=前コマンドの戻り値,
%%=最大マッチの後方置換,ワイルドカード'*'つき


10-hydra.実行(mpiexec,hydra)

mpiexecで実行する。-nはプロセス数, -fはホストファイルを指定する。結果は上記と同じ。
[server]
$ mpiexec -n 6 -f mpi.hosts ./a.out
びっくりするほど楽です。hydra版はドキュメントの少なさがネックかな。

参考


目安箱バナー