最近、MPI を使用してシミュレーション プログラムを並列化し、高速化しました。私が採用した方法は、非常に時間がかかるが並列化が容易な 1 つの関数を書き直すことでした。
非 MPI プログラムの単純化されたモデルは次のとおりです。
int main( int argc, char* argv[] ){
// some declaration here
Some_OBJ.Serial_Function_1();
Some_OBJ.Serial_Function_2();
Some_OBJ.Serial_Function_3();
return 0;
}
私のMPIバージョンは、
#include "mpi.h"
int main( int argc, char* argv[] ){
// some declaration here
MPI_Init( NULL, NULL );
Some_OBJ.Serial_Function_1();
Some_OBJ.Parallel_Function_2(); // I rewrite this function to replace Some_OBJ.Serial_Function_2();
Some_OBJ.Serial_Function_3();
MPI_Finalize();
return 0;
}
非 MPI コードを mpi_simulation などの新しいフォルダーにコピーし、mpi 関数を追加して、メイン ファイルを . 動作しますが、非常に不便です。OBJ.Serial_Function_1() などの一部の関数を更新する場合、定数を変更するだけでも、注意してコードをコピーする必要があります。これらのバージョンのプログラムには、まだ若干の違いがあります。それらを順守するのに疲れました。
そのため、MPI プログラムを MPI 以外のバージョンに依存させる方法があるかどうか、私は迷っています。そうすれば、私のリビジョンをそれらの両方に安全かつ便利に簡単に適用できます。
ありがとう。
更新私はついにharaldklの提案を採用しました。この方法は、次のように、MPI インターフェイスを使用するすべての関数を囲むマクロを定義することです。
#ifdef USE_MPI
void Some_OBJ::Parallel_Function_2(){
// ...
}
#endif
MPI を自動的に初期化するために、MPI_plugin というシングルトンを定義します。
#ifdef USE_MPI
class MPI_plugin{
private:
static MPI_plugin auto_MPI;
MPI_plugin(){
MPI_Init( NULL, NULL );
}
public:
~MPI_plugin(){
MPI_Finalize();
}
};
MPI_plugin::MPI_plugin auto_MPI;
#endif
MPI バージョンをコンパイルするときに、main.cpp に MPI_plugin.h を含めることで、main.cpp に MPI_Init() と MPI_Finalize() を追加する必要がなくなります。最後のステップは、メイクファイルに PHONY ターゲット「mpi」を追加することです。
CPP := mpic++
OTHER_FLAGS := -DUSE_MPI
.PHONY: mpi
mpi: ${MPI_TARGET}
...
同じ問題を抱えている方の参考になれば幸いです。