私が理解しているのは、1 つのマスター プロセスが他のすべてのプロセスにメッセージを送信するということです。他のすべてのプロセスは、代わりにメッセージをマスター プロセスに送信します。障壁が機能するにはこれで十分でしょうか? そうでない場合、さらに何が必要ですか?
2 に答える
OpenMPI のバリアの実装を見てみましょう。他の実装はわずかに異なる場合がありますが、一般的な通信パターンは同じである必要があります。
最初に注意すべきことは、MPI のバリアにはセットアップ コストがないことです。呼び出しに到達したプロセスMPI_Barrier
は、グループの他のすべてのメンバーも を呼び出すまでブロックされMPI_Barrier
ます。MPI では、同じ呼び出しに到達する必要はなく、 への任意の呼び出しであることに注意してくださいMPI_Barrier
。したがって、グループ内のノードの総数はすでに各プロセスに知られているため、呼び出しを初期化するために追加の状態を配布する必要はありません。
それでは、いくつかのコードを見てみましょう。
/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2012 Oak Ridge National Labs. All rights reserved.
* [...]
*/
[...]
/*
* barrier_intra_lin
*
* Function: - barrier using O(N) algorithm
* Accepts: - same as MPI_Barrier()
* Returns: - MPI_SUCCESS or error code
*/
int
mca_coll_basic_barrier_intra_lin(struct ompi_communicator_t *comm,
mca_coll_base_module_t *module)
{
int i;
int err;
int size = ompi_comm_size(comm);
int rank = ompi_comm_rank(comm);
最初に、すべてのノード (ルート ノードであるランク 0 のノードを除く) が、バリアに到達したという通知をルート ノードに送信します。
/* All non-root send & receive zero-length message. */
if (rank > 0) {
err =
MCA_PML_CALL(send
(NULL, 0, MPI_BYTE, 0, MCA_COLL_BASE_TAG_BARRIER,
MCA_PML_BASE_SEND_STANDARD, comm));
if (MPI_SUCCESS != err) {
return err;
}
その後、ルートからの通知を待ってブロックします。
err =
MCA_PML_CALL(recv
(NULL, 0, MPI_BYTE, 0, MCA_COLL_BASE_TAG_BARRIER,
comm, MPI_STATUS_IGNORE));
if (MPI_SUCCESS != err) {
return err;
}
}
ルート ノードは、通信の反対側を実装します。まず、通知を受信するまでブロックしますn-1
(彼はすでにバリア呼び出しの内側にいるため、彼自身を除く、グループ内のすべてのノードから 1 つ)。
else {
for (i = 1; i < size; ++i) {
err = MCA_PML_CALL(recv(NULL, 0, MPI_BYTE, MPI_ANY_SOURCE,
MCA_COLL_BASE_TAG_BARRIER,
comm, MPI_STATUS_IGNORE));
if (MPI_SUCCESS != err) {
return err;
}
}
すべての通知が到着すると、すべてのノードが待機しているメッセージを送信して、全員がバリアに到達したことを通知し、その後、バリア呼び出し自体を終了します。
for (i = 1; i < size; ++i) {
err =
MCA_PML_CALL(send
(NULL, 0, MPI_BYTE, i,
MCA_COLL_BASE_TAG_BARRIER,
MCA_PML_BASE_SEND_STANDARD, comm));
if (MPI_SUCCESS != err) {
return err;
}
}
}
/* All done */
return MPI_SUCCESS;
}
したがって、通信パターンは、最初にn:1
すべてのノードからルートへ、次にルートからすべてのノードへと1:n
戻ります。ルート ノードがリクエストで過負荷になるのを避けるために、OpenMPI ではツリーベースの通信パターンを使用できますが、基本的な考え方は同じです。すべてのノードがバリアに入るときにルートに通知し、ルートは結果を集約し、バリアに入ると全員に通知します。続行する準備ができました。
いいえ、それだけでは十分ではありません。マスター プロセスが他のすべてのプロセスにメッセージを送信してバリアに到達したことを通知し、他のすべてのプロセスがバリアに到達したことを伝えると、マスター プロセスだけがすべてのプロセスがバリアに到達したことを認識します。このシナリオでは、マスターから他のプロセスへの別のメッセージが必要になります。
どのライブラリでも MPI バリアが実際に実装されていることについては主張しません。特に、概説されている一連のメッセージが実際に使用されていることを示唆しているわけではありません。理論的に不十分であるというだけです。