トップ > ライブラリ > 計算機 > 並列化(MS-MPI)

計算機・並列化(MS-MPI)

現在工事中です。
過去の2010年に、Argonne National LaboratoryのサイトでMPICH2をダウンロードし、Fortranで組んだテストプログラムを並列実行した経験がある。

今回は最新版(2013年11月時点)のMPICH(注1)をダウンロードし、Windows環境でFortran言語による並列計算プログラムを実行するまでの経過を以下紹介する。

【注1】2010年当時は"MPICH2"と末尾に"2"がついていたが、今回サイトを閲覧すると"2"がなくなっている。 なお、2010年のダウンロードファイルは、"mpich2-1.2.1p1-win-ia32.msi"および"mpich2-1.2.1.p1-win-x86-64.msi"というファイルをダウンロードしていた。

MPIツールとして、今回MicrosoftのWindows版を使ったが、IntelのCluster Studio(有償)はMPIをサポートしており、Intelの方がメジャーなMPIなのかも知れない。 Linux版は、ANLのサイトでかなり更新されているようだが、MS-MPIは使用方法のドキュメントが整っていないため、試行錯誤のところがある。 過去2010年のMPICH2は、割合とドキュメントが揃っていて、すんなり実行できた。

機会があれば、IntelのCluster Studio(無償の評価版)を試してみたいと思う。

【注】数式表示にはMathJaxを利用しています。IE8以下では表示が遅くなる可能性があります。FireFox などIE8以外のブラウザを利用下さい。

MPIについて

Windows版のMPIについて、またFortran言語から利用することを前提に概略を紹介する。

MPIのダウンロード

MPI(Message Passing Interface)を使った並列計算では、ネットワークで繋がった複数のマシンを使い、プログラムコードを分担・協調して実行し、実質的な計算時間を短くする並列化の手法である。 詳しくは、サイト http://www.mpich.orgを参照されたい。Stableな最新版は、現在 ver 3.0.4との記述がある。

mpich.orgのサイトから、WindowsのMPICHを選択すると、MicrosoftのHPC Packのサイト http://www.microsoft.com/en-us/download/details.aspx?id=39961にジャンプし、ダウンロードすることができる。 ダウンロードの際に、64bit版のmpi(mpi_x64.msi)および32bit版のmpi(mpi_x86.msi)の選択画面に以降し、チェックマークを入れることでファイル選択することができる。インストールするマシンのOSが64bitなら64bit版を、 32bitOSなら32bit版をダウンロードする。

並列計算に参加するすべてのマシンにmpichをインストールする必要がある。Windows XPもサポートしているので、32bit版XPマシンを使うときにはx86版もインストールしておく。

なお、Microsoft Teamの作ったmpichは、Microsoftのサイトでは"MS-MPI"と呼んでおり、以下MS-MPIを本サイトでも使う。

MPICHは、主にLinux OS上で利用されるようだが、ダウンロードサイトの最後のほうに Micfosoft MPI Teamが作ったMicrosoft Windows版(ver 1.0.3)が掲載されている。今回のインストールおよび実行テストでは このVer1.0.3をダウンロードし、インストールした。なおインストールしたマシンのOSは、Windows 7(64Bit,Ultimate,CPU:core i7)である。また並列実行のために利用したマシンは Windows 7 (64Bit, Ultimate, CPU: core i5)のノートマシンを用いた。

先頭に戻る

MPIとは

日本語のテキストとして、C言語からMPIを利用する秋葉訳、P.パチェコの図書1)、およびFortran言語からMPIを利用する樫山ら2)の図書がある。 MPIを使ったプログラムは、プログラマーがMPI関数を適切に利用し並列計算を考えながらコーディングしなければならず、コード 開発者にとってはハードルが高い。OpenMPのように自動化が難しい面がある。 逆に、プログラマーの裁量により、高速な並列化プログラムが書ける自由度があるといえる。

ネットワークを通して、メッセージをやり取りすることから、スパコンのような高性能なマシンに仕上げるには 高速で特殊なネットワークが必要となるが、イーサネットでも原理的には利用可能である。

現時点では、並列化のメリットがある技術計算としては、流体解析などのような大規模計算 が思い浮かぶ。これ以外の化学工学の計算でクラスタ構成のマシンを使って並列計算を実行しなければならない 負荷の重い課題(蒸留計算などの反復計算にしても負荷が重いとは言い難い)はすぐには思いつかない。 最適化手法で、遺伝的アルゴリズムのように、数多くのメンバーに同じ処理をさせる計算には向いているが、問題により負荷の軽重があろう。 しかしいずれ、PCの低廉化により分散環境が当たり前になると考えられ、今のうちに基礎を整えておき、利用分野の拡大を視野に入れておく必要がある。

先頭に戻る

MS-MPIのインストール

ここでは、Windows 7(64bitOS)のマシンに、MS-MPIをインストールすることを前提に解説する。 またFortran(後の並列計算の実行テストで使う)は、Intel Parallel Studio XE 2013を用いる。 インストールマシンには、MS Visual Studio 2010がすでにインストールされているが、 Visual Studio経由でFortranコードを作成せず、Command Promptベースでコンパイル、リンクを実行することを前提に解説する。

並列計算に参加させるマシンのすべてにMS-MPIをインストールする必要があり、以下のインストール手順をすべてのマシンで実行する。

【ステップ1】msi_x64.msiを右クリックで、インストールを開始する。Welcomeスクリーン、Copyrightsスクリーンを経由して インストールフォルダを指定する。

【ステップ2】フォルダはデフォルトのまま、あるいはユーザ指定でも可能。ハードドライブを指定する。SDカードドライブなどは不可。
このフォルダに、以下のサブフォルダが作られる。
\Bin: mpiexec.exe, smpd.exeなどの実行可能ファイルがインストールされる
\Inc: mpi.f90, mpi.hなどヘッダファイルがインストール
\Lib\amd64: amd64用のライブラリファイルがインストール
\Lib\i386: i386用のライブラリファイルがインストール

【ステップ3】インストールボタンをクリックし、インストールを開始する。

【ステップ4】環境変数を確認する。コントロールパネル「システム」の「システムの詳細設定」-「環境変数」を 選択し、システム環境変数の "Path"に、上のステップ2で指定したフォルダが追加されていることを確認する。 追加されていなければ、編集し、手動で追加する。

ver 1.0.3のMS-MPIは、自動的に環境変数Pathを設定してくれるようだ。MPICH2では手動で設定していた。

【ステップ5】環境変数を更新するため、マシンを再起動する。

【ステップ6】再起動後、「アクセサリ」-「コマンドプロンプト」またはIntel FortranのCommand Promptを選択し、 コマンドプロンプトから、c:\>mpiexec.exe /? を実行する。実行結果を図1(注)に示す。

図1:mpiexecのpathを確認

(注)Intel Parallel Studioをインストールしていると、Intel社のmpiexec.exeファイルが実行されることがある。 この場合の例として、図2に -version スイッチをつけたときの実行結果を示す。

図2:mpiexec(Intel社)

Intel社のmpiexecが実行される(設定したPathでIntelのPathが先に指定されている)とき、図1のようにMS-MPIをインストールしたフォルダ指定してmpiexec.exeを実行すればよい。

以上で、MS-MPIのインストールと環境設定が終わったことになる。ヘッダファイル、ライブラリファイルの利用方法は次章で述べる。

先頭に戻る

単一マシンの実行テスト

MS-MPIをインストールした直後の、単一のマルチコアCPUマシン(core i7, 920) でMPIコードの実行テストを実施しました。 言語は、Fortranと C言語で試しています。コードの中身は図書1),2)で紹介されているように簡単なものです。

Fortranプログラム

もっとも簡単なMPIを利用したFortranプログラムのコードをリスト1に示す。 また、コンパイル、リンク、実行を含むメイクファイルをリスト2に示す。 利用するFortranコンパイラーは、Intel Visual Fortran Ver 13.1.1.171を利用した。

なお、リスト1のコード中のコメントにあるように、コマンド"mk"は、バッチコマンド mk.batで、 "nmake /f %1.mak %2"と定義している。なお、nmake.exeはVisual Studio付属のコマンドである。

リスト1:MS-MPIを利用したもっとも簡単なFortranサンプル(test11.for)

C------------------------------------------------------------------------
      PROGRAM      TEST11
C
C   MPICHのもっとも簡単なサンプル
C
C          revised by Y.Sakakibara      2013.11.12. (IVF 13.1.1.171)
C
C  インターネットからダウンロード:
C  MPICH2による並列計算環境の構築WindowsVista,7編(64bit環境対応)20100819TN-0.pdf
C  から作成。
C
C    compile :  >mk test11
C    clean:     >mk test11 clean
C    run:       >mk test11 run
C
C    run:       >test11			single nodeで実行、 0,1を返す
C
      IMPLICIT     NONE
      INCLUDE      'MPIF.H'	! ヘッダファイル
      INTEGER(4)   IERR,MYID,NPROC
!
      CALL         MPI_INIT( IERR )	! MPIの初期化
      CALL         MPI_COMM_RANK( MPI_COMM_WORLD,MYID,IERR )	! カレントプロセスのランクを求める
      CALL         MPI_COMM_SIZE( MPI_COMM_WORLD,NPROC,IERR )	! プロセスの数を求める
!
      WRITE(*,*) ' MYID,NPROC = ',MYID,NPROC	!
!
      CALL         MPI_FINALIZE( IERR )	! MPIの終了処理
!
      STOP
      END PROGRAM TEST11

Fortranコード中の、MPI_XXXXが、MPIルーチンを示している。MPI関連のヘッダファイルとして、Fortran用の"MPIF.H"をINCLUDEしている。

リスト2:TEST11のメイクファイル (test11.mak)

#
#  ivf 13.1.1.171 (2013 Nov.12,On i7-920, Win7)
#
#  mpich(64bit版)による並列計算
#

TAR=test11
INC=
MOD=
MPI=d:\Systools\2013\MS-HPC_2012\	# MS-MPIインストールフォルダ

FOR=ifort
LINK=ifort

FOR_OPT1=/Od
FOR_OPT2=/include:$(MPI)\Inc		# ヘッダファイルの所在
FOR_OPT3=
FOR_OPT=$(FOR_OPT1) $(FOR_OPT2) $(FOR_OPT3)

# Fortran用のライブラリとCとの共用ライブラリ
LIBS=	$(MPI)\lib\i386\msmpifmc.lib $(MPI)\lib\i386\msmpi.lib

LNK_OPT=$(LIBS) /link /out:$(TAR).exe

OBJ=	$(TAR).obj

OBJ1=	

OBJ2=	

ALL:		$(TAR).exe

$(TAR).exe:	$(OBJ) $(OBJ1) $(OBJ2) $(INC) $(TAR).mak
		$(LINK) $(FOR_OPT) $(OBJ) $(OBJ1) $(OBJ2) $(LNK_OPT)

$(TAR).obj:	$*.for $(INC)
		$(FOR) /c $(FOR_OPT) $*.for
.for.obj:
		$(FOR) /c $(FOR_OPT) $*.for
.f.obj:
		$(FOR) /c $(FOR_OPT) $*.f

clean:
	del *.obj
	del $(TAR).exe
	del *.lib
	del *.exp

run:
	$(MPI)\bin\mpiexec -n 4 $(TAR)

変数MPIに、MS-MPIをインストールしたディレクトリを定義し、INCLUDEファイルの所在を、FOR_OPT2変数に設定している。 またMPI用のライブラリファイルを、LIBS変数で"msmpifmc.lib"、"msmpi.lib"の2つを設定している。

実行時は、オプション"run"をつけることで、mpiexec.exeをフラグ"-n 4"つきでTEST11.EXEを実行する。 フラグ"-n 4"はプロセッサー数を4つ使うことを意味している。この段階ではサーバーマシン上の4つのプロセスを起動している。

まだネットワークを介して、クラスター構成のマシン群を利用していない。 この段階では、OpenMPの並列化と大きな差はない。明示的にMPIルーチンをFortran文として指定することがMPIの特徴である。 一方、OpenMPではディレクティブと呼ばれる、Fortran文法にはない構文を用い、コードに並列化用の指示を与えている。

mpiexecを経由しないで実行した結果(test11.exeをコマンドプロンプトで直接実行)と、 mpiexecを経由し、ノード数4に設定して実行した結果を図3に示す。

図3:TEST11の実行結果

test11.exeの直接実行では、ランク0のプロセスが1つである。一方 "mk test11 run"でmpiexec経由で実行すると、 ランクが2,3,0,1の合計4つのプロセスが起動されていることがわかる。

なお、Windows 7上で実行するとき、ファイアウォールでブロックされるというセキュリティの警告が出力される。 出力例を図4に示す。このメッセージに対し”アクセスを許可”すると実行を継続する。

図4:TEST11の実行時のセキュリティ警告

また、ウィルス対策ソフトで、実行時に実行を拒絶される可能性がある。avast!では拒絶されるため、実行ファイルをウィルス検索対象から除外するソフトに追加し、 実行可能なように設定する必要があった。実行可能ファイルのあるフォルダを丸ごと除外するよう図5の(1)の部分にフォルダ名を追加している。

図5:avast!のウィルス保護の解除画面

avast!の場合、MPIコードを実行するといきなりウィルスチェストという場所に隔離されてしまう。ウィルスチェストを開き、復元し、上のグローバル除外指定しないと 起動するたびに隔離されてしまう。他のウィルス対策ソフトの場合は経験ないので不明。

先頭に戻る

Cプログラム

リスト1のFortran言語のサンプルをC言語に変えただけの簡単なプログラムです。 コードをリスト3に示します。

ファイアウォール警告などはFortranコードと全く同じ。

リスト3:簡単なC言語によるMPIサンプル (test21.c)

/*
   program file :     test21.c
   revised by Y.Saka  2013/11/13

   自分のrankを表示させる

   Compile: >mk test21
   Clean:   >mk test21 clean
   Run:     >mk test21 run
実行結果:
My rank is 2 in 4
My rank is 1 in 4
My rank is 0 in 4
My rank is 3 in 4

*/
#include 
#include 

int main(int argc, char **argv)
{
  int numprocs;		//プロセス数を格納する 
  int myrank;		//自分のrankを取得する
  MPI_Init(&argc,&argv);	//MPIライブラリを使用するための準備(初期化)を行う.
  MPI_Comm_size(MPI_COMM_WORLD, &numprocs);	//コミュニケータ内のプロセス数をnumprocsに取得する.
  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);	//コミュニケータ内の各プロセスが自分もrankをmyrankに取得
  printf("My rank is %d in %d\n",myrank,numprocs);

  MPI_Finalize();
  return 0;
}

同様にC言語ソースのコンパイル、リンク、実行用のメイクファイルをリスト4に示す。 コンパイラーは、Intel Composer XEに付属するC言語コンパイラー icl.exeを利用している。

リスト4:test21.cのメイクファイル(test21.mak)

#
#  icl 13.1.1.171 (2013 Nov.12,On i7-920, Win7)
#
#  mpich(64bit版)による並列計算
#

TAR=test21
INC=
MOD=
MPI=d:\Systools\2013\MS-HPC_2012\	# MPIのインストールフォルダ

CC=icl
LINK=icl

CC_OPT1=/Od
CC_OPT2=/I$(MPI)\Inc			# ヘッダファイルの場所
CC_OPT3=
CC_OPT=$(CC_OPT1) $(CC_OPT2) $(CC_OPT3)

LIBS=	$(MPI)\lib\i386\msmpi.lib	# MS-MPI用のライブラリ

LNK_OPT=$(LIBS) /link /out:$(TAR).exe

OBJ=	$(TAR).obj

OBJ1=	

OBJ2=	

ALL:		$(TAR).exe

$(TAR).exe:	$(OBJ) $(OBJ1) $(OBJ2) $(INC) $(TAR).mak
		$(LINK) $(FOR_OPT) $(OBJ) $(OBJ1) $(OBJ2) $(LNK_OPT)

$(TAR).obj:	$*.c $(INC)
		$(CC) /c $(CC_OPT) $*.c
.c.obj:
		$(CC) /c $(CC_OPT) $*.c

clean:
	del *.obj
	del $(TAR).exe
	del *.lib
	del *.exp

run:
	$(MPI)\bin\mpiexec -n 4 $(TAR)		# 実行用

メイクファイルの構成は、Fortranの場合とほぼ同様である。実行結果は図3とほとんど同じであり掲載を省略する。

先頭に戻る

クラスタ構成で並列計算のテスト

次に、複数のマシンをネットワークで結んだクラスター構成の場合の、MPIによる並列計算のサンプルを以下に示す。

2010年当時、MPICH2を用いた並列計算サンプルを、今回のMS-MPIで実行するため、更新したFortranコードを リスト5に示す。複数のプロセスを、複数のマシンで並列起動させるテストコード(プログラム名:test12)である。

コードのコンパイル・リンク

実行モジュールtest12.exeは、リスト6に示す、ユーザー作成のモジュール(M_MOD1)を使用している。

リスト5:クラスター構成環境のMPIによるFortranコード(test12.for)

C------------------------------------------------------------------------
      PROGRAM      TEST12
C
C   MPICHのもっとも簡単なサンプル	2010.09.30.
C                                       BY Y.SAKAKIBARA
C
C   revised by Y.Sakakibara		2013.11.12.
C
C
C  インターネットからダウンロードした次のファイルに記載するサンプル
C  MPICH2による並列計算環境の構築WindowsVista,7編(64bit環境対応)20100819TN-0.pdf
C  中野のサンプル:
C   (usage)  \>test12.exe  xxx.xxx  yyy.yyy
C   (function)  ランク0のプロセスが、テキストファイルxxx.xxxを読み込み、
C               テキストファイルyyy.yyyに書き込む。
C               そのほかのプロセスは、ランクを割り当てられ、メッセージを受け取るが何もしない。
C
C    compile :  >mk test12
C    clean:     >mk test12 clean
C    run:       >mk test12 run0		単独のマシンで実行
C    run:       >mk test12 run1		i7_920で実行
C    run:       >mk test12 run		i7_920,note_sx2で実行
C    run:       >test12 input.txt log.txt	single nodeで実行、 0,1を返す
C
!--------------------------------------------------------------
      USE          M_MOD1,ONLY:UNIT_IN,UNIT_OUT
      IMPLICIT     NONE
      INCLUDE      'MPIF.H'
!
      INTEGER(4)   IERR,MYID,NPROC
      INTEGER(4)   NARG
      CHARACTER(1024) INPUT_FILE_NAME,OUTPUT_FILE_NAME
      INTEGER(4)    LENGTH,ILEN
      CHARACTER(1024) S,PCNAME
!
      IERR=0
      CALL         MPI_INIT( IERR )
      WRITE(*,*) ' IERR (INIT) = ',IERR
      CALL         MPI_COMM_RANK( MPI_COMM_WORLD,MYID,IERR )
      WRITE(*,*) ' MYID,IERR (RANK) = ',MYID,IERR
      CALL         MPI_COMM_SIZE( MPI_COMM_WORLD,NPROC,IERR )
      WRITE(*,*) ' NPROC,IERR (SIZE) = ',NPROC,IERR
!
!  次のサブルーチンで実行時、アクセス違反となる (2013.Nov)
!      CALL         MPI_GET_PROCESSOR_NAME( PCNAME,ILEN,IERR );
!      WRITE(*,*) ' PCNAME,ILEN = ',TRIM(PCNAME),' ',ILEN
!
      IF(MYID == 0) THEN
        NARG=COMMAND_ARGUMENT_COUNT()	! 実行プログラムを含む引数の数を返す
        IF(NARG /= 2) THEN
          WRITE(*,*) 'ERROR: INVAID NUMBER OF ARGUMENTS'
          IERR=1
        ENDIF
      ENDIF
!  送信元rootの送信バッファbufferから、その他すべてのプロセスの受信バッファbuffer
!  にメッセージを送信する

!  MPI_BCAST(buffer,count,datatype,root,comm,ierr)
!      buffer: 送信元プロセスでは送信バッファの先頭アドレス、
!              受信元プロセスでは受信バッファの先頭アドレス
!       count: INT4 メッセージの要素数
!   datatype : INT4 メッセージのデータタイプ
!        root: 送信元プロセスのランク
!        comm: 送受信に参加するすべてのプロセスを含むコミュニケーた
!        ierr: INT4 実行結果コード
!
      CALL         MPI_BCAST( IERR,1,MPI_INTEGER,0,MPI_COMM_WORLD,IERR )
      IF(IERR /= 0) THEN
        GOTO 1
      ENDIF
      IF(MYID == 0) THEN
!              1番目の引数の文字列を、INPUT_FILE_NAMEに返す
!               length: 文字列の長さを返す
!               ierr:  
        CALL       GET_COMMAND_ARGUMENT( 1,INPUT_FILE_NAME,LENGTH,IERR )
        SELECT CASE(IERR)
          CASE(0)	! 正常終了
!-- SUCCEEDED
          CASE(-1)
            WRITE(*,*) 'ERROR: TOO LONG INPUT FILE NAME'
          CASE DEFAULT
            WRITE(*,*) 'ERROR: INVALID INPUT FILE NAME'
        END SELECT
      ENDIF
!
      CALL         MPI_BCAST( IERR,1,MPI_INTEGER,0,MPI_COMM_WORLD,IERR )
      IF(IERR /= 0) THEN
        GOTO 1
      ENDIF
      IF(MYID == 0) THEN
        CALL      GET_COMMAND_ARGUMENT( 2,OUTPUT_FILE_NAME,LENGTH,IERR )
        SELECT CASE(IERR)
          CASE(0)
!   SUCCEEDED
          CASE(-1)
            WRITE(*,*) 'ERROR: TOO LONG OUTPUT FILE NAME'
          CASE DEFAULT
            WRITE(*,*) 'ERROR: INVALID OUTPUT FILE NAME'
        END SELECT
      ENDIF
      CALL         MPI_BCAST( IERR,1,MPI_INTEGER,0,MPI_COMM_WORLD,IERR )
      IF(IERR /= 0) THEN
        GOTO 1
      ENDIF
      IF(MYID == 0) THEN
        OPEN(UNIT=UNIT_IN,FILE=INPUT_FILE_NAME,IOSTAT=IERR)
        IF(IERR /= 0) THEN
          WRITE(*,*) 'ERROR: INVALID INPUT FILE NAME'
        ENDIF
      ENDIF
      CALL         MPI_BCAST( IERR,1,MPI_INTEGER,0,MPI_COMM_WORLD,IERR )
      IF(IERR /= 0) THEN
        GOTO 1
      ENDIF
      IF(MYID == 0) THEN
        OPEN(UNIT=UNIT_OUT,FILE=OUTPUT_FILE_NAME,IOSTAT=IERR)
        IF(IERR /= 0) THEN
          WRITE(*,*) 'ERROR: INVALID OUTPUT FILE NAME'
        ENDIF
      ENDIF
      CALL         MPI_BCAST( IERR,1,MPI_INTEGER,0,MPI_COMM_WORLD,IERR )
      IF(IERR /= 0) THEN
        GOTO 1
      ENDIF
      IF(MYID == 0) THEN
        WRITE(UNIT_OUT,*) 'MYID, NPROC=',MYID,NPROC
        READ(UNIT_IN,'(A)') S
        WRITE(UNIT_OUT,'(1X,A)') TRIM(S)
      ENDIF
    1 CONTINUE
      CALL         MPI_FINALIZE(IERR)
      STOP
      END PROGRAM TEST12
リスト6:test12.for用のモジュールファイル(m_mod1.for)

C------------------------------------------------------------------------
      MODULE       M_MOD1
C
C   MPICHのもっとも簡単なサンプル	2010.09.30.
C                                       BY Y.SAKAKIBARA
C
C
! ISO_FORTRAN_ENV: Fortran2003で追加されたモジュールで環境変数(named constants)
!                  にコードからアクセスする
!    named constant:
!       CHARACTER_STORAGE_SIZE
!       ERROR_UNIT
!       FILE_STORAGE_SIZE
!       INPUT_UNIT
!       IOSTAT_END
!       IOSTAT_EOR
!       NUMERIC_STORAGE_SIZE
!       OUTPUT_UNIT
!
!  intrinsic 設定されており、ONLY:以下のリストがローカル名で参照される
!        (local name) => (mod-name)の形をとる
      USE,INTRINSIC :: ISO_FORTRAN_ENV,ONLY:STDIN => INPUT_UNIT,
     1               STDOUT => OUTPUT_UNIT
      IMPLICIT     NONE
      INTEGER(4),PARAMETER :: UNIT_IN=15,
     1                        UNIT_OUT=16
      SAVE
!
      END MODULE   M_MOD1

test12.exeは、複数のプロセスを起動し、ランクが0のプロセスが入力ファイルから1行のテキストを読み込み、 プロセスIDと起動プロセス数をファイル出力し、読み込んだテキストをファイル出力する。

リスト5、6に示すコードの、メイクファイルをリスト7に示す。
コンパイル・リンクはコマンドプロンプトから、
\>mk test12
を実行する。クリーンアップは、同じく
\>mk test12 clean
を実行する。ここで、"mk"は、nmake.exeのバッチコマンドで前述と同じである。
実行可能モジュールtest12.exeを実行するとき、以下の実行形態を選択できる。各実行形態の詳細はリスト7を参照されたい。

\>mk test12 runmpiexecを使わない、singleプロセス実行
\>mk test12 run0サーバーマシン上で、4プロセス並列実行
\>mk test12 run1サーバーマシン上で、singleプロセス実行
\>mk test12 run2host指定、singleプロセス実行
\>mk test12 run3host指定、2マシン指定、各2プロセス並列実行
\>mk test12 run4マシンファイル指定、4プロセス並列実行

リスト7のメイクファイルで、test12.exeの実行のまえに、前回の出力ファイルを削除(del log.txt)を行い、その後実行し、 結果のlog.txtを画面出力(type log.txt)して、結果を確認している。

リスト7:test12.forのメイクファイル(test12.mak)

#
#  ivf 13.1.1.171 (2013 Nov.12,On i7-920, Win7)
#
#  mpich2(32bit版)による並列計算
#

TAR=test12
INC=
MOD=m_mod1
MPI=d:\Systools\2013\MS-HPC_2012\

FOR=ifort
LINK=ifort

FOR_OPT1=/Od
FOR_OPT2=/include:$(MPI)\Inc
FOR_OPT3=
FOR_OPT=$(FOR_OPT1) $(FOR_OPT2) $(FOR_OPT3)

LIBS=	$(MPI)\lib\i386\msmpifmc.lib $(MPI)\lib\i386\msmpi.lib

LNK_OPT=$(LIBS) /link /out:$(TAR).exe

OBJ=	$(TAR).obj

OBJ1=	

OBJ2=	$(MOD).obj

ALL:		$(MOD).mod $(TAR).exe

$(MOD).mod:	$*.for $(INC)
		$(FOR) /c $(FOR_OPT) $*.for

$(TAR).exe:	$(OBJ) $(OBJ1) $(OBJ2) $(INC) $(TAR).mak
		$(LINK) $(FOR_OPT) $(OBJ) $(OBJ1) $(OBJ2) $(LNK_OPT)

$(TAR).obj:	$*.for $(INC)
		$(FOR) /c $(FOR_OPT) $*.for
.for.obj:
		$(FOR) /c $(FOR_OPT) $*.for
.f.obj:
		$(FOR) /c $(FOR_OPT) $*.f

clean:
	del *.obj
	del $(TAR).exe
	del $(MOD).mod
	del *.lib
	del *.exp

run:		# OK
	del log.txt
	$(TAR) input.txt log.txt
	type log.txt
run0:		# OK
	del log.txt
	$(MPI)\bin\mpiexec -n 4 $(TAR) input.txt log.txt
	type log.txt
run1:		# OK
	del log.txt
	$(MPI)\bin\mpiexec -n 1 $(TAR) input.txt log.txt
	type log.txt
# require:  smpd -port 8677
run2:		# OK
	del log.txt
	$(MPI)\bin\mpiexec -hosts 1 i7_920 4 $(TAR) input.txt log.txt
	type log.txt

run3:		# OK
	del log.txt
	$(MPI)\bin\mpiexec -hosts 2 i7_920 2 note_sx2 2 \
	      $(TAR) input.txt log.txt
	type log.txt
run4:		# OK
	del log.txt
	$(MPI)\bin\mpiexec -n 4 -machinefile mfile.txt \
	      $(TAR) input.txt log.txt
	type log.txt

先頭に戻る

実行環境の設定

単独マシンで実行する、リスト7のrun、run0、run1では環境を設定することなく、コンパイル直後にコンパイルしたマシン上で そのまま実行させることができる。

一方、クラスター環境でコードをサーバー側から起動する前に、次のようにクライアント側の環境をあらかじめ設定しておく必要がある。

リスト7で、run2、run3、run4を起動させるとき、マシン名を直接またはマシンファイル(mfile.txt)を通して、 プロセスを起動するマシンを指定している。マシン名を名前解決とクラスタ並列計算のためのデーモンsmpd.exe(MS-MPIに 付属する。mpiexec.exeと同じ\Binフォルダにある)を、予め起動しておく必要がある。smpd.exeの ヘルプ画面および起動画面をリスト8に示した。ポート番号は8677を使っている(らしい)。 この辺りのマニュアルが見当たらず、エラーメッセージなどから推察した。

2010年当時のMPICH2では、デーモンsmpd.exeの起動停止はオプションスイッチ(-start, -stop)をつけることによりできた。MS-MPIでは ヘルプ画面を見ると、これらスイッチがなくなっている。

リスト8: smpd.exeデーモンのヘルプと起動

D:\Systools\2013\MS-HPC_2012\Bin>smpd /?
smpd options:
 -help
 -port  or -p 
 -debug [flags] or -d [flags] (flags are optional)
        flags are the sum of: 1 , 2 

"smpd -d" will start the smpd in debug mode.

D:\Systools\2013\MS-HPC_2012\Bin>smpd -port 8677

マシンファイルのサンプルを、リスト9に示す。先頭の"#"はコメント行、1行にマシン名を1つ記述し、 複数のマシンを利用するときは、その行数分を記述する。以前のMPICH2では、マシン毎に起動するプロセス数 を、"マシン名:n"のように指定することができた。しかし、MS-MPIではマシン名のみで、起動プロセス数を指定 するとエラーが発生する。

各マシンでどれだけのプロセスが生成されるのかは、現時点では判明していない。トータルのプロセス数は mpiexecの引数で指定することができるが、マシンファイルを使う場合には指定できない。マシンに割り振るプロセス数 を指定したいときには、run3のような記述で、mpiexecに引数を渡す方法しかないのかもしれぬ。

リスト9:マシンファイルの定義

#  machinefile for mpich
#
#                         created by Y.Sakakibara
#                         date:  2010.09.30.
#                modified date:  2013.11.15.
#
#   host名:利用するプロセッサコア数(整数)
#
#192.168.0.4:2
#192.168.0.3:2
#ok
i7_920
note_sx2
#bad
#i7_920:2
#note_sx2:2

なお、テスト環境のクラスタ構成(Windows 7マシン2台)を図6に示す。サーバー・マシン(マシン名:i7_920、CPU:core i7)と、 クライアント・マシン(マシン名:note_sx2、CPU:core i5)を、同一ドメイン"workgroup"に繋いでいる。なお、note_sx2は 無線LAN経由で、ブリッジを経由し、有線LANのハブと接続している。

i7_920は、IntelのCore i7 CPUを搭載し、4コア8スレッドのプロセスを、note_sx2は、Intelの Core i5 CPUを搭載し、2コア4スレッドのプロセスを起動できる。

図6:クラスタ・マシン群のネットワーク構成

たまたま自宅のマシン環境で、note_sx2を無線LANを使っていたので、そのまま無線LANで構築した。有線LANの方が 計算速度が速いと思われる。またHub、router経由で外部WAN(インターネット)に接続するが、この部分は並列計算 とは無関係で、サーバー側マシンi7_920とクライアント側のnote_sx2がethernet経由で TCP/IPで接続されていればよい。なお図中のIPアドレスは同じドメインに属している。

先頭に戻る

コードの実行

実行結果は、run, run0, run1は、単独マシン上で予想通りの結果が得られている。 run2は、同じく単独マシン上で4つのプロセスを起動し、正常終了している。

run3は、i7_920上で2つ、note_sx2上で2つ、合計4つのプロセスが起動し、正常終了している。 run4も、結果としてrun3と同じく、各マシンで2つのプロセスが起動し、正常終了している。 このときの、タスクマネージャによるCPUの使用率を図7および図8に示す。 i7_920マシンでは5つのスレッドの中の4つが同じピーク高さを示しており、これが並列計算に 利用されたプロセスと考えられる。一方note_sx2マシンではピーク高さがほぼ同じ2つのスレッド が見られ、並列計算に利用されたプロセスと考えられる。

これらタスクマネージャによる図では、並列計算が瞬間的に終了してしまい、本当に並列計算を実行 しているか判別がつきにくい。

図7:タスクマネージャによる確認(i7_920)

図8:タスクマネージャによる確認(note_sx2)

そこでもう少し計算負荷を上げたテストコードで試すことにした。

先頭に戻る

Fortranによる姫野ベンチマーク

独立行政法人 理化学研究所の姫野氏が、MPIコードを用いた数値計算ベンチマークコードを 姫野ベンチマーク3)として公開している。現在公開されているコードで、Fortran77の サイズM(256x128x128)のコード(現在のファイル名 himenoBMTxp_m.f)とほぼ同等の、2010年当時に ダウンロードしたFortranソースコードを用いて、並列計算を実行した。

コードの内容は三次元ポアッソン方程式を、ヤコビの反復法で解く、並列計算の評価のためのコードで、 ベンチマークのテスト結果も公開されている。

コードのコンパイル・リンク

Fortranソースコードの掲載(ファイル名はhimenoBMTxpr.fとしている)は省略する。 最適化コンパイルオプションは /Od (最適化無効)とし、コンパイルした。 コマンドプロンプト上で、
\>mk test13
でコンパイルし、実行可能なモジュールtest13.exeが生成する。そして
\>mk test13 run1
などターゲット指定で実行できる。リンクファイル(test13.mak)をリスト10に示す。 コンパイル時のオプションで "/define:M222"は、姫野氏のサイズMコードに相当する配列サイズを 選択するフラグである。

リスト10:姫野ベンチマークのメイクファイル(test13.mak)

#
#  ivf 11.1.060  (2010 Sep.21,IA32)
#  ivf 13.1.1.171 (2013 Nov.12,On i7-920, Win7)
#
#  mpich(32bit版)による並列計算
#

TAR=test13
TAR1=himenoBMTxpr
INC=param.h
MOD=
MPI=d:\Systools\2013\MS-HPC_2012\

FOR=ifort
LINK=ifort

FOR_OPT1=/Od
FOR_OPT2=/include:$(MPI)\Inc
#FOR_OPT3=/define:XS122		# メモリ,CPU数を選択
FOR_OPT3=/define:M222		# メモリ,CPU数を選択、Mモデル

FOR_OPT=$(FOR_OPT1) $(FOR_OPT2) $(FOR_OPT3)

LIBS=	$(MPI)\lib\i386\msmpifmc.lib $(MPI)\lib\i386\msmpi.lib

LNK_OPT=$(LIBS) /link /out:$(TAR).exe

OBJ=	$(TAR1).obj

OBJ1=	

OBJ2=	

ALL:		$(TAR).exe

$(TAR).exe:	$(OBJ) $(OBJ1) $(OBJ2) $(INC) $(TAR).mak
		$(LINK) $(FOR_OPT) $(OBJ) $(OBJ1) $(OBJ2) $(LNK_OPT)

$(TAR1).obj:	$*.f $(INC)
		$(FOR) /c $(FOR_OPT) $*.f
.for.obj:
		$(FOR) /c $(FOR_OPT) $*.for
.f.obj:
		$(FOR) /c $(FOR_OPT) $*.f

clean:
	del *.obj
	del $(TAR).exe
	del *.lib
	del *.exp

# smpd.exe -port 8677
# M 2 2 2のとき
run:	# error Invalid number of PE
	$(MPI)\bin\mpiexec -hosts 2 i7_920 2 note_sx2 2 $(TAR)

run1:	# OK
	$(MPI)\bin\mpiexec -n 8 $(TAR)

# M 2 2 2のとき
run2:	# OK
	$(MPI)\bin\mpiexec -n 8 -machinefile mfile.txt \
	      $(TAR)

# M 2 2 2のとき (2013.11.13) OK
run3:	# OK
	$(MPI)\bin\mpiexec -hosts 1 note_sx2 8 $(TAR)

run4:	# error Invalid number of PE
	$(MPI)\bin\mpiexec -n 12 -machinefile mfile.txt \
	      $(TAR)

先頭に戻る

コードの実行結果

実行のためのターゲットとして、次の5つをメイクファイルで用意した。

\>mk test13 runmpiexecを使い、2つのマシンでそれぞれ2プロセスを起動。 実行時エラー、"Invalid number of PE"でダウン。
\>mk test13 run1mpiexecを使い、サーバーマシンで8プロセスを起動。 実行できた。
\>mk test13 run2mpiexecを使い、マシンファイル指定で合計8プロセスを起動。 実行できた。各マシンとも4プロセスづつ起動
\>mk test13 run3mpiexecを使い、note_sx2マシンのみで8プロセスを起動。 実行できた。2コア4スレッドで、8プロセスを実行している。
\>mk test13 run4mpiexecを使い、2つのマシンで合計12プロセスを起動。 実行時エラー、"Invalid number of PE"でダウン。

このうち、run2およびrun4のマシンファイルは、リスト9と同じファイルを用いた。また 起動プロセス数の指定で、run2およびrun4で、2,4,12などを試したが、"Invalid number of PE"エラーで 計算しない。8を指定するrun3は実行できた。エラーの原因はよくわからない。

run1の実行中のタスクマネージャのCPU使用率を図9に示す。8プロセス(8スレッド)が起動している。

図9:test13.exe run1の実行中(i7_920)

同様に、run2(2つのマシンで合計8プロセス起動)のCPU使用率を図10図11に示す。

図10:test13.exe run2の実行中(i7_920)

図11:test13.exe run2の実行中(note_sx2)

各マシン毎に4つづつプロセスが自動的に(というか勝手に)分配されている。分配方法の指定は不明である(マニュアル等が見当たらず、インターネットなど十分に調べていないため)。

run2をコマンドプロンプト上で実行したときの出力メッセージを図12に示す。およそ541MFLOPSの性能であることが判る。 Core i7(2.67GHz)とCore i5(2.60GHz)のクラスタ構成で、無線LAN経由のEthernet環境で、最適化オプションなしでこの 程度の性能となった。

図12:test13.exe run2の出力(i7_920)

以上、クラスタ構成のマシン群を用いて、Windows環境下で、主にFortran言語を用いた 並列計算のさわりを紹介した。計算速度の向上のための、最適化コンパイル、ベクトル化、 OpenMPとの併用など課題は残されているが、手持ちのethernet環境でマシン群による並列計算が実行 出来ることが分かった。

先頭に戻る

その他のMPI

MS-MPI以外の、MPIコードをサポートする環境についてインターネットなどを調べた。その知見を以下紹介する。

Linux環境のMPICH

Linux環境で、MPICHが各種Linux Distribution用に無償配布されており、活発な開発が行われていて最新版を利用することができる。 Linuxを使っての動作テストは実施していないが、安価にクラスター並列計算を実行するとき、選択肢の一つであることに間違いない。 OSそのものが無償であり、MPICHもオープンソースで無償で利用可能であることはメリットが大きい。環境が整えばテストしたい。

Open_MPI

MPIに関してネット検索すると、Open_MPI(OpenMPではない)に関する情報が頻出する。Open_MPIの公式サイト http://www.open-mpi.org/のダウンロードページに、Windows版OpenMPI_v1.6.2-2?win64.exeなどが置いてある。 名前のとおりオープンソースであり、無償で利用できるらしい。今後機会があったらテストしてみたい。

ただし、サイト情報ではWindowsサポートはメンテする機関がなく、CygwinベースのOpenMPIを使えとリコメンドしている。

Intel Cluster Studio

Intel社のサポートするCluster Studioの利用が、Intel Fortranなどとの相性を考えると最もベストな選択なのであろう。Linux版とWindows版(HPC Server用)とがある。 しかし、ソフトは有償であり、個人ベースで購入するには高価である。お試し版がダウンロードできるので、いずれ時間があれば テストをしてみたい。

先頭に戻る

Literature Cited

関連ファイルのダウンロードは、こちら(未リンク)で取り扱っています。

先頭に戻る