※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

MPIプログラミングを実際にC言語で実装してみた

そもそもMPIとは??
  • Message Passing Interfaceの略。並列計算をする際、それぞれのプロセスがお互いに通信をするためのAPI。ソケットプログラムの段階から、この機能を実装するのは大変であるため、ライブラリとして提供されている。もちろん、MPIはインターフェースの名称であり、その実装は様々。今回はMPICH1で実装してみた。他にはLAMとかいろいろあるみたい。MPICH2はもあるらしく、これはMPICH1の機能プラスアルファみたいな感じみたい。追加された機能は、いろいろあるみたいだけど、知ってるところだと、走らせるプロセス数を実行時に決定できるとかなんとか。とにかく、そのようなライブラリでして、今回はごく簡単なプログラムでそのライブラリを実装してみよーっと思ったわけです。

どんなプログラムを書いたか?
  • ごくごく簡単なプログラムだが、ランダム生成されたM×N行列と、長さNの列ベクトルの積をMPIを活用して解くプログラム。コマンドは以下のようにする。
~$ ~/mpirun -np 4 -machinefile ./mf ./mpi_matrix 10 12
これは、プロセス数が4で、カレントディレクトにあるmfってmachinefileを読み込み、実行可能プログラム mpi_matrixを、10と12という引数を持たせて実行する、とゆー意味。
この場合、10が行の数、12が列の数、となる。

実際に使ったprimitiveとその意味
  • MPI_Init(int *argc, char ***argv)
    • 初期化。まずこいつを呼ぶ。コマンドから引数を読み取るのは、こいつを呼んでからあとのほうがよい。ルートプロセスは自分でコマンド入れてるから、ちゃんと変数にコマンドから値が入るだろうけど、他のプロセスにはそれじゃ入らん。それで少しハマった。よく考えれば当たり前だけど。
  • MPI_Comm_size(MPI_Comm comm, int *size)
    • 指定するコミュニケ-タ(プロセスがお互いに通信できるグループのこと?デフォルトだとMPI_COMM_WORLD。今回はこれしか使ってない)における、総プロセス数を知ることができる。
  • MPI_Comm_rank(MPI_Comm comm, int *rank)
    • そのコミュニケータにおける自分のランクを知ることができる。
  • MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvbuf, MPI_Datatype recvtype, int root, MPI_Comm comm)
    • 配列のデータを各プロセスにばらまく。この関数では、それぞれのプロセスに決まった量のデータした撒けない。
  • MPI_Scatterv(void *sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype, void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, MPI_Comm comm)
    • Scatterの拡張版。各プロセスに対して異なるデータ数を送ることができる。そのために、sendcountsやdisplsとかゆーint型の配列を自分で作る必要あり。
  • MPI_Gatherv(void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype, int root, MPI_Comm comm)
    • Scattervの逆バージョン。
  • MPI_Finalize()
    • MPIの終了時に必ず読む関数。
  • MPI_Send()とかMPI_Recv()は、基本的な関数だけど、今回は使ってません。

やってみた感想
簡単なプログラムだけど、やると意外に時間がかかってしまった。。。反省点は、やっぱりいきなりMPIを実装するのではなく、Sequentialなものを書いてから、そこで用意した関数をバリバリ適用していくってのがラクだな、と思った。昔から気になっていた、MPIだけど、今回実装してみてなんとなく雰囲気が分かりよかった。本場のMPIプログラミングはことはだいぶ複雑なんだろうけど

-