0

通常、MPI_Bcast を呼び出すときは、ルートを決定する必要があります。しかし今、誰がメッセージをブロードキャストするかを気にしないアプリケーションがあります。これは、メッセージをブロードキャストするノードがランダムであることを意味しますが、メッセージがブロードキャストされると、グローバル変数は一貫している必要があります。私の理解では、MPI_Bcast は集合関数であるため、すべてのノードが呼び出す必要がありますが、順序が異なる場合があります。つまり、誰が最初に MPI_Bcast に到着し、誰がメッセージを他の人にブロードキャストするかということです。次のコードを 3 つのノードで実行しました。ノード 1 (rank==1) が最初に MPI_Bcast に到達すると、local_count 値 (1) が他のノードに送信され、すべてのノードが同じ local_count で global_count を更新すると思います。私の予想される結果の 1 つは (出力順序は関係ありません)
ノード 0、グローバル カウントは 1
ノード 1、グローバル カウントは 1 です。
ノード 2、グローバル カウントは 1

ただし、実際の結果は常に (出力順序は関係ありません):
ノード 1、グローバル カウントは 1
ノード 0、グローバル カウントは 0
ノード 2、グローバル カウントは 2

この結果は、MPI_Bcast を使用しないコードとまったく同じです。MPI_Bcast または私のコードの理解に何か問題がありますか。ありがとう。

#include <mpi.h>
#include <stdio.h>

int main(int argc, char *argv[])
{   

    int rank, size;
    int local_count, global_count;
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    global_count = 0;
    local_count = rank;

    MPI_Bcast(&local_count, 1, MPI_INT, rank, MPI_COMM_WORLD);
    global_count += local_count;

    printf("node %d, global count is: %d\n", rank, global_count);
    MPI_Finalize();
}

コードは単純化されたケースです。私のアプリケーションでは、MPI_Bcast の前にいくつかの計算があり、誰が最初に計算を終了するかわかりません。ノードが MPI_Bcast ポイントに来るたびに、ノードは自身の計算結果ローカル変数をブロードキャストする必要があり、すべてのノードはグローバル変数を更新します。したがって、すべてのノードがメッセージをブロードキャストする必要がありますが、順序はわかりません。このアイデアをどのように実装しますか?

4

3 に答える 3

2

の正しい使い方は、すべてのプロセスが同じルートMPI_BCastで関数を呼び出すことです。ブロードキャスターが誰であるかを気にしなくても、ブロードキャスターをリッスンするには、すべてのプロセスが同じランクで関数を呼び出す必要があります。コードでは、各プロセスは独自のランクで呼び出しており、すべてが互いに異なります。MPI_BCast

標準ドキュメントは見ていませんが、MPI_BCast異なるランクで呼び出すことで未定義の動作を引き起こす可能性があります。

于 2012-07-06T04:38:10.023 に答える
2

通常、あなたが書いたものはデッドロックにつながります。典型的なMPI_Bcastケースでは、ランクを持つプロセスは、rootそのデータをコミュニケーター内の他のすべてのプロセスに送信します。rootそれらの受信プロセスで同じランクを指定して、誰を「リッスン」するかを知る必要があります。通常、総操作時間を短縮するために階層ブロードキャストが使用されるため、これは単純化しすぎた説明ですが、3 つのプロセスを使用すると、この階層実装は非常に単純な線形のものになります。あなたの場合、ランクのプロセスは、プロセスと0の両方に同じメッセージを送信しようとします。同時に、プロセスはそのメッセージを受信しませんが、代わりにそのメッセージをプロセスおよびプロセスに送信しようとします。プロセス121022も と に送信しようとし0ます1。最終的に、すべてのプロセスは、他のプロセスが受信しようとしないメッセージを送信します。これは災害のほぼ確実なレシピです。

プログラムがハングしないのはなぜですか? 送信されるメッセージは非常に小さく、1 つのMPI_INT要素のみであり、プロセスの数も少ないため、これらの送信はすべてのプロセスで MPI ライブラリによって内部的にバッファリングされます。送信先に到達することはありませんが、内部で行われた呼び出しは行われMPI_Bcastません。ブロックすると、操作がまだ進行中ですが、コードは実行制御を取り戻します。標準では、MPI ライブラリは何もバッファリングする必要がないため、これは未定義の動作です。実装によってはバッファリングする場合とそうでない場合があります。

local_countすべてのプロセスのすべての変数の合計を計算しようとしている場合は、 を使用してMPI_Allreduceください。これを置き換えます:

global_count = 0;
local_count = rank;

MPI_Bcast(&local_count, 1, MPI_INT, rank, MPI_COMM_WORLD);
global_count += local_count;

これとともに:

local_count = rank;
MPI_Allreduce(&local_count, &global_count, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
于 2012-07-06T14:30:33.070 に答える
0

openmpiドキュメントから

"MPI_Bcast broadcasts a message from the process with rank root to all processes of the group, itself included. It is called by all members of group using the same arguments for comm, root. On return, the contents of root’s communication buffer has been copied to all processes. "

ランクから呼び出す可能性があります!=ルートはいくつかの問題を引き起こす可能性があります

より安全な方法は、独自のブロードキャスト関数をハードコーディングして呼び出すことです。

基本的にはforループとmpi_sendコマンドであり、自分自身を実装するのはそれほど難しいことではありません。

于 2012-07-06T05:04:19.873 に答える