MPI_Probe()挂起

时间:2015-02-03 11:00:15

标签: c mpi

我需要使用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;
}

1 个答案:

答案 0 :(得分:0)

我发现代码无法正常工作,因为我正在错误地使用MPI_Bcast()。使用MPI_Bcast()时不使用MPI_Recv()。每个进程只使用MPI_Bcast(),因此root与每个人“共享”缓冲区。

我也找到了比我更好地解释这个问题的答案 - 我以前在某种程度上错过了它们:


正确代码

#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;
}