エラー条件が満たされたときに、特定の MPI ランクでプログラムがエラー メッセージを生成することがあります。ただし、この条件は一部の (すべてではない) ランクでのみ満たされる可能性があります。エラー状態に遭遇した最初のランクからメッセージを出力し、他のランクから同様のメッセージを破棄したい。
私が単純に(メッセージを捨てずに)これをした場合、例えば
if (error) cout << "Error on rank " << rank << endl;
画面上でランダムに並べられた出力が表示されます。
ブロックに入る最初のプロセスの標準出力をロックしたいのですが、if(error)
すべてのプロセスがそのブロックに入るわけではないという事実によって複雑になります。これは、MPI_Barrier() 集合が完了しないことを意味します。すべての出力を 1 つのプロセッサのみに送信することは、実際には解決策ではありません。これは、エラー メッセージが生成されるコード内のすべての場所で同期が必要になり、プログラムの速度が低下するためです。メッセージを出力するためだけにアイドル プロセッサを別に設定することも魅力的ではないようです (これはコミュニティ コードのためです)。ランクごとに 1 つのファイルに書き込むことも、少なくともランクが多数ある場合はオプションではありません。
MPIにアトミックメカニズムがあるかどうか疑問に思っていました(MPI3にあると読みました)。これにより、たとえば一方的な通信を介して、1つのプロセッサのメモリのフラグをアトミックに更新し、エラーメッセージの出力のみを続行できます。フラグはまだ設定されていません。
残念ながら、これは標準的なトリックでは簡単に達成できません... そうですか?
アップデート:
やり方がわかったと思います。Wesley の答えは近いものでしたが、ほとんどの MPI 実装で利用可能な標準の MPI2 RMA で行うこともできます。ソリューションの鍵は、MPICH2 ディストリビューション (test/mpi/rma/fetchandadd.c) にも含まれている Using MPI2 book のアトミックな例にあります。
変数 (ランク 0 に存在する) をロックしてアトミックにインクリメントする方法は次のとおりです。
if (error)
{
int one = 1;
int flag;
MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, 0, win);
MPI_Accumulate(&one, 1, MPI_INT, 0, 1, MPI_INT, MPI_SUM, win);
MPI_Get(&flag, 1, MPI_INT, 0, 0, 1, MPI_INT, win);
MPI_Win_unlock(0, win);
if (flag ==1) cout << "Error on rank " << rank << endl;
}
そして初期化中のどこか:
int error_flag = 0;
MPI_Win_create(&error_flag, sizeof(int), sizeof(int), MPI_INFO_NULL, mpi_comm, &win);
...そして終了する前に
MPI_Win_free(&win);