MPI_Probe() 挂起

MPI_Probe() hangs

我需要使用 MPI_Bcast() 在 MPI 中实现一个简单的代码。我想通过使用 MPI_Probe() 使其更有用,这样我就不必每次都手动将消息大小写入 MPI_Recv()。

我习惯使用 MPI_Send() 执行此操作,但使用 MPI_Bcast() 时程序会挂在 MPI_Probe() 上。你知道为什么吗?


我的代码

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

#define ARR_LEN 1

int main() {
    MPI_Init(NULL, NULL);

    typedef struct Values {
        int id;
        char * c;
    } Values;

    Values val1;
    val1.id = 5;
    val1.c = "Ahoj";

    MPI_Datatype valuesDatatypeTmp;

    int blockLengths[2] = {1, 3};

    MPI_Aint indices[2];

    MPI_Address( &val1.id, &indices[0] );
    MPI_Address( &val1.c, &indices[1] );
    
    indices[1] -= indices[0];
    indices[0] = 0;

    MPI_Datatype types[2] = {MPI_INT, MPI_CHAR};

    MPI_Type_create_struct( 2, blockLengths, indices, types, &valuesDatatypeTmp );

    MPI_Datatype valuesDatatype;
    MPI_Type_create_resized( valuesDatatypeTmp,
                                indices[0],
                                (MPI_Aint)sizeof(struct Values),
                                &valuesDatatype );

    MPI_Type_free( &valuesDatatypeTmp );
    MPI_Type_commit( &valuesDatatype );

    //-----------------------//
    //--- Message passing ---//
    //-----------------------//

    int world_size;
    MPI_Comm_size( MPI_COMM_WORLD, &world_size );

    int world_rank;
    MPI_Comm_rank( MPI_COMM_WORLD, &world_rank );

    MPI_Status status;
    Values * buf;

    Values val[ARR_LEN] = {val1};

    switch( world_rank ) {
    case 0:
        printf("Toto je proces cislo %d - root.\n", world_rank);
        MPI_Bcast( val, ARR_LEN, valuesDatatype, 0, MPI_COMM_WORLD );
        break;
    default:

        MPI_Probe( 0, 0, MPI_COMM_WORLD, &status );

        int status_size;
        MPI_Get_count( &status, valuesDatatype, &status_size );


        buf = (Values *) malloc( sizeof(struct Values) * status_size );

        MPI_Recv( buf, status_size, valuesDatatype, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE );

        printf( "Toto je proces cislo %d.\n", world_rank );
        
        for( int i = 0; i < ARR_LEN; i++ ) {
            printf("Prijata zprava je %d %s\n"\
                    "Delka zpravy byla %d\n",
                    buf[i].id,
                    buf[i].c,
                    status_size);
        }

        break;
    }

    MPI_Type_free( &valuesDatatype );
    MPI_Finalize();
    return 0;
}

我发现代码无法正常工作,因为我使用 MPI_Bcast() 不正确。使用 MPI_Bcast() 时不使用 MPI_Recv()。每个进程都只使用 MPI_Bcast(),所以根与每个人“共享”缓冲区。

我还找到了比我更好地解释这个问题的答案 - 我之前不知何故错过了它们:

  • Probe for MPI_Bcast or MPI_Send
  • Corresponding Receive Routine of MPI_Bcast

正确的代码

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

#define ARR_LEN 1

int main() {
    MPI_Init(NULL, NULL);

    typedef struct Values {
        int id;
        char * c;
    } Values;

    Values val1;
    val1.id = 5;
    val1.c = "Ahoj";

    MPI_Datatype valuesDatatypeTmp;

    int blockLengths[2] = {1, 3};

    MPI_Aint indices[2];

    MPI_Address( &val1.id, &indices[0] );
    MPI_Address( &val1.c, &indices[1] );
    indices[1] -= indices[0];
    indices[0] = 0;

    MPI_Datatype types[2] = {MPI_INT, MPI_CHAR};

    MPI_Type_create_struct( 2, blockLengths, indices, types, &valuesDatatypeTmp );

    MPI_Datatype valuesDatatype;
    MPI_Type_create_resized( valuesDatatypeTmp,
                                indices[0],
                                (MPI_Aint)sizeof(struct Values),
                                &valuesDatatype );

    MPI_Type_free( &valuesDatatypeTmp );
    MPI_Type_commit( &valuesDatatype );

    int world_size;
    MPI_Comm_size( MPI_COMM_WORLD, &world_size );

    int world_rank;
    MPI_Comm_rank( MPI_COMM_WORLD, &world_rank );

    MPI_Status status;
    Values * buf;

    Values val[ARR_LEN] = {val1};

    MPI_Bcast( val, ARR_LEN, valuesDatatype, 0, MPI_COMM_WORLD );

    printf( "This is the processnumber %d.\n", world_rank );
    
    for( int i = 0; i < ARR_LEN; i++ ) {
        printf("Message received: %d %s\n",
                val[i].id,
                val[i].c
                );
    }

    MPI_Type_free( &valuesDatatype );
    MPI_Finalize();
    return 0;
}