MPIの実行結果を1つのファイルに出力したい

MPIを用いた場合、通常は各プロセスごとに出力ファイルが生成されます。しかしMPI-IOを用いて出力先を指定することで、各プロセスの出力を1つのファイルにまとめることができます。

基本的な利用方法

MPI-IOはMPIプログラミングを行うことを前提としています。MPIの基本的な利用方法やコマンドについてはこちらをご覧ください。
以下にfortranで書かれたプログラムを紹介します。こちらを参考に説明します。
 

ファイルへの出力(書き込み)

各プロセスごとにプロセスID(rank)を取得し、output.datの任意の位置に出力するプログラムです。
たとえば自身のプロセスIDが4の場合、output.datの16-19バイト目(INTEGER換算で5番目)に自身のプロセスIDを書き込みます。

 

プログラムのハイライト部分(8行目-11行目)が、MPI-IOプログラムになります。また7行目は直接MPI-IOに関係があるわけではないですが、9行目でコマンドに引数として渡す変数を設定している部分になりますので、必要な処理になります。
 
2行目、6行目-7行目、13行目はMPIでの処理を行うためのプログラムです。こちらについてはMPI利用方法(VCC)のページで解説を行っていますのでそちらを参考にしてください。
 
以下で8行目-11行目のコマンドについて詳しく説明していきます。
 

mpi_file_open

mpi_file_open(comm, filename, amode, info, fh, ierr)

MPI-IOでの入出力先のファイルをオープンするためのコマンドです。
MPI-IOを行う場合は最初にcallする必要があります。

引数
comm コミュニケータを指定します。通常はMPI全プロセスをあらわす「MPI_COMM_WORLD」を指定することが多いです。
filename 入出力先のファイル名を指定します。
amode アクセスモードの設定をします。「|」をはさむことで複数同時に指定することが可能です。代表的なものをいくつか紹介します。
mpi_mode_rdonly:読み込みのみ可能
mpi_mode_wronly:書き込みのみ可能
mpi_mode_rdwr :読み書き両方可能
mpi_mode_create:filenameで指定した名前のファイルがない場合、自動で作成
mpi_mode_excl :filenameで指定した名前のファイルがすでに存在する場合、エラーを返す
これ以外にも様々なモードが存在します。
info 入出力先のファイル情報を設定できますが、基本的には何も渡さない「mpi_info_null」で問題ありません。
fh ファイルハンドルです。これ以降filenameで指定したファイルは、fhで指定したファイルハンドルで指定することになります。
ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます。

 

mpi_file_set_view

mpi_file_set_view(fh, disp, etype, ftype, datarep, info, ierr)

各プロセスのファイルへの入出力開始地点(ポインタ)を指定するコマンドです。
ここでうまくポインタの指定ができていないと、出力結果に変に空白ができてしまったり、上書きが発生してしまったりします。

引数
fh ファイルハンドルです。MPI_File_openで設定したファイルハンドルを指定します。
disp ポインタのオフセット距離をバイト数で指定します。たとえばここで4を引数として渡した場合、5バイト目にポインタがセットされます。CHARACTER型は1文字1バイトのデータ型なので、この場合はファイルの先頭から4文字分のスペースが空いていることになります。またINTEGER型で考えると、通常は1つ4バイトのデータ型なのでINTEGER1つ分のスペースが空いていることになります。
etype ファイルの基本単位を設定します。書き込む際のデータ型もしくはmpi_byteを指定します。
ftype ファイルのひとまとまりの単位を設定します。各プロセスが複数回にわたって規則的に入出力を行う際などに利用するもので、決まった型だけでなくユーザーが独自に作ったものを設定することも可能です。各プロセスが入出力を1回しか行わない場合はetypeと同じものを設定しておきます。
datarep データの表現方法を指定します。基本的にはバイナリ表現を表す「native」で問題ありません。
※必ず小文字で指定してください。
info 入出力先のファイル情報を設定できますが、基本的には何も渡さない「mpi_info_null」で問題ありません。
ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます

mpi_file_write

mpi_file_write(fh, buf, count, datatype, status, ierr)

実際にファイルに出力するためのコマンドです。
MPI_File_openでオープンしたファイルにMPI_File_set_viewで指定されたポインタから書き込み始めます。

引数
fh ファイルハンドルです。MPI_File_openで設定したファイルハンドルを指定します。
buf 実際に書き込む内容を設定します。
count 書き込むデータの数(文字数ではない)を設定します。詳しくはdatatypeの欄で説明します。
datatype 書き込むデータの型です。ここで設定したデータ型を、countで設定した数だけ出力します。
たとえばcharacter型で「hello」と書き込む場合はcountに5を、datatypeにmpi_characterを設定します。
またinteger型で「100」と書き込む場合はcountに1を、datatypeにmpi_integerを設定します。
これはcharacterが1つで1文字を表すデータ型であるのに対し、integerは1つで-2147483648~2147483647の範囲の整数を表すデータ型だからです。
status 入出力先のファイルの通信に関する設定を行えますが、基本的には何も渡さない「mpi_status_ignore」で問題ありません。
ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます

mpi_file_close

MPI_File_close(fh, ierr)

MPI-IOでの入出力先のファイルをクローズするためのコマンドです。
MPI-IOを行う場合は一連の処理の最後にcallする必要があります。

fh ファイルハンドルです。MPI_File_openで設定したファイルハンドルを指定します。
ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます


 

ファイルからの入力(読み込み)

上記で作成したoutput.datからデータを読み込み、printで画面に表示するプログラムです。

 

プログラムのハイライト部分(8行目-11行目)が、MPI-IOプログラムになりますが、出力用のプログラムからmpi_file_writeがmpi_file_readに変わったのみでほぼ変化がありません。以下で新たに使用しているmpi_file_readについて解説します。
 

mpi_file_read

mpi_file_read(fh, buf, count, datatype, status, ierr)

ファイルから読み込むためのコマンドです。
MPI_File_openでオープンしたファイルのMPI_File_set_viewで指定されたポインタからデータを読み込みます。

引数
fh ファイルハンドルです。MPI_File_openで設定したファイルハンドルを指定します。
buf 読み込んだデータが格納されます。
count 読み込むデータの数を設定します。writeのときと同様に文字数ではないという点に注意してください。
datatype 読み込むデータの型です。ここで設定した型で、countで設定した数だけ読み込みます。
status 入出力先のファイルの通信に関する設定を行えますが、基本的には何も渡さない「mpi_status_ignore」で問題ありません。
ierr 正常終了時に0が格納されます。エラー時はそれ以外の値が格納されます


 

通常のコマンドを用いた読み込み

MPI-IOを用いて出力されたファイルは通常のreadコマンドでも読み込むことができます。mpi_file_readコマンドは本来、各プロセスにファイルの別々の箇所を読み込ませ、それぞれに並列作業を行わせるためのコマンドですので、MPI-IOによる出力結果をただ読み込むだけならば通常のreadコマンドを用いてデータの読み込みを行います。
上記同様output.datからデータを読み込み、printで画面に出力するプログラムです。

 

ご覧のとおりMPI化を行っていないシリアル実行のプログラムですので、コンパイルやスクリプトでのジョブ投入の記述に誤ってMPI用のコマンドを使わないように注意してください。
 

C言語の場合

上記と同じプログラムをC言語で記述したものも参考までに掲載します。関数はfortran版とほぼ同じですので、説明は省略します。

ファイルへの出力(書き込み)


ファイルからの入力(読み込み)


通常の関数を用いた読み込み