1

プログラムで複数の MPI_Send または MPI_Recv を呼び出そうとすると、ノードとルートで実行可能ファイルがハングします。つまり、2 番目の MPI_Send または MPI_Recv を実行しようとすると、通信がブロックされます。同時に、バイナリはマシンで 100% 実行されています。

OpenMPI 1.6.3 64 ビットを使用して Windows 7 64 ビットでこのコードを実行しようとすると、正常に実行されました。しかし、同じコードは Linux、つまり OpenMPI 1.6.3 -64 ビットの CentOS 6.3 x86_64 では機能しません。私がした問題は何ですか。

以下のコードを投稿する

#include <mpi.h>

int main(int argc, char** argv) {
MPI::Init();
int rank = MPI::COMM_WORLD.Get_rank();
int size = MPI::COMM_WORLD.Get_size();
char name[256] = { };
int len = 0;
MPI::Get_processor_name(name, len);

printf("Hi I'm %s:%d\n", name, rank);

if (rank == 0) 
{
    while (size >= 1) 
    {
        int val, stat = 1;
        MPI::Status status;
        MPI::COMM_WORLD.Recv(&val, 1, MPI::INT, 1, 0, status);
        int source = status.Get_source();
        printf("%s:%d received %d from %d\n", name, rank, val, source);

        MPI::COMM_WORLD.Send(&stat, 1, MPI::INT, 1, 2);
        printf("%s:%d sent status %d\n", name, rank, stat);

        size--;
    }
} else 
{
    int val = rank + 10;
    int stat = 0;
    printf("%s:%d sending %d...\n", name, rank, val);
    MPI::COMM_WORLD.Send(&val, 1, MPI::INT, 0, 0);
    printf("%s:%d sent %d\n", name, rank, val);

    MPI::Status status;
    MPI::COMM_WORLD.Recv(&stat, 1, MPI::INT, 0, 2, status);
    int source = status.Get_source();
    printf("%s:%d received status %d from %d\n", name, rank, stat, source);
}

size = MPI::COMM_WORLD.Get_size();
if (rank == 0) 
{
    while (size >= 1) 
    {
        int val, stat = 1;
        MPI::Status status;

        MPI::COMM_WORLD.Recv(&val, 1, MPI::INT, 1, 1, status);
        int source = status.Get_source();
        printf("%s:0 received %d from %d\n", name, val, source);

        size--;
    }

    printf("all workers checked in!\n");
} 
else
{
    int val = rank + 10 + 5;
    printf("%s:%d sending %d...\n", name, rank, val);
    MPI::COMM_WORLD.Send(&val, 1, MPI::INT, 0, 1);
    printf("%s:%d sent %d\n", name, rank, val);
}
MPI::Finalize();

return 0;

}

こんにちは Hristo、あなたが言ったようにソースを変更しました。コードは再び投稿されています

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

int main(int argc, char** argv) 
{
    int iNumProcess = 0, iRank = 0, iNameLen = 0, n;
    char szNodeName[MPI_MAX_PROCESSOR_NAME] = {};
    MPI_Status stMPIStatus;

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &iNumProcess);
    MPI_Comm_rank(MPI_COMM_WORLD, &iRank);
    MPI_Get_processor_name(szNodeName, &iNameLen);

    printf("Hi I'm %s:%d\n", szNodeName, iRank);

    if (iRank == 0) 
    {
        int iNode = 1;
        while (iNumProcess > 1) 
        {
            int iVal = 0, iStat = 1;
            MPI_Recv(&iVal, 1, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &stMPIStatus);
            printf("%s:%d received %d\n", szNodeName, iRank, iVal);

            MPI_Send(&iStat, 1, MPI_INT, iNode, 1, MPI_COMM_WORLD);
            printf("%s:%d sent Status %d\n", szNodeName, iRank, iStat);

            MPI_Recv(&iVal, 1, MPI_INT, MPI_ANY_SOURCE, 2, MPI_COMM_WORLD, &stMPIStatus);
            printf("%s:%d received %d\n", szNodeName, iRank, iVal);

            iNumProcess--;
            iNode++;
        }

        printf("all workers checked in!\n");
    }
    else 
    {
        int iVal = iRank + 10;
        int iStat = 0;
        printf("%s:%d sending %d...\n", szNodeName, iRank, iVal);
        MPI_Send(&iVal, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
        printf("%s:%d sent %d\n", szNodeName, iRank, iVal);

        MPI_Recv(&iStat, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, &stMPIStatus);
        printf("%s:%d received status %d\n", szNodeName, iRank, iVal);

        iVal = 20;
        printf("%s:%d sending %d...\n", szNodeName, iRank, iVal);
        MPI_Send(&iVal, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
        printf("%s:%d sent %d\n", szNodeName, iRank, iVal);

    }

    MPI_Finalize();

    return 0;
}

私は次のように出力を得ました。つまり、送受信の送信後、ルートは無限に待機し、ノードは 100% の CPU 使用率で動作します。その出力は以下のとおりです

Hi I'm N1433:1
N1433:1 sending 11...
Hi I'm N1425:0
N1425:0 received 11
N1425:0 sent Status 1
N1433:1 sent 11
N1433:1 received status 11
N1433:1 sending 20...

ここで、N1433 と N1425 はマシン名です。助けてください

4

2 に答える 2

3

マスターのコードが間違っています。常に同じランク(ランク)からのメッセージを送信して待機しています1。したがって、プログラムはとして実行された場合にのみ正しく機能しmpiexec -np 2 ...ます。おそらくやりたかったMPI_ANY_SOURCEのは、送信元ランクとして使用し、その送信元ランクを送信操作の宛先として使用することです。while (size >= 1)ランク0はそれ自体と通信しておらず、通信数は。より1つ少ないと予想されるため、使用しないでsizeください。

if (rank == 0) 
{
    while (size > 1)
    //     ^^^^^^^^
    {
        int val, stat = 1;
        MPI::Status status;
        MPI::COMM_WORLD.Recv(&val, 1, MPI::INT, MPI_ANY_SOURCE, 0, status);
        // Use wildcard source here ------------^^^^^^^^^^^^^^
        int source = status.Get_source();
        printf("%s:%d received %d from %d\n", name, rank, val, source);

        MPI::COMM_WORLD.Send(&stat, 1, MPI::INT, source, 2);
        // Send back to the same process --------^^^^^^
        printf("%s:%d sent status %d\n", name, rank, stat);

        size--;
    }
} else

ワーカーでこのようなことをするのは無意味です。

MPI::Status status;
MPI::COMM_WORLD.Recv(&stat, 1, MPI::INT, 0, 2, status);
// Source rank is fixed here ------------^
int source = status.Get_source();
printf("%s:%d received status %d from %d\n", name, rank, stat, source);

受信操作でソースとしてランクをすでに指定0しているため、ランクからのメッセージのみを受信できます0status.Get_source()何らかの通信エラーが発生した場合を除いて、以外の値を返す方法はありません。0その場合、例外がによってスローされMPI::COMM_WORLD.Recv()ます。

コードの2番目のループについても同じことが言えます。

ちなみに、あなたは公式の標準C++バインディングであったものを使用しています。これらはMPI-2.2で非推奨になり、最新バージョンの標準(MPI-3.0)は、MPIフォーラムでサポートされなくなったため、完全に削除されました。代わりにCバインディングを使用するか、のようなサードパーティのC++インターフェイスに依存する必要がありますBoost.MPI

于 2012-11-16T08:01:16.130 に答える
1

OpenMPI の代わりに MPICH2 をインストールすると、正常に動作しました。クラスター マシンで OpenMPI 1.6.3 を使用する際に問題があると思います。

于 2012-12-19T04:47:13.770 に答える