MPI_Send中的派生数据类型的分段错误

时间:2017-01-03 20:06:58

标签: c++ segmentation-fault mpi openmpi

在下面的代码中,如果MPI_Get_address(&member, &offset[0]);替换为offset[0] = 0;,则代码按预期工作,否则会在下面给出输出。据我所知,需要使用MPI_BOTTOM绝对内存地址,这就是使用MPI_Get_address()的原因。虽然struct MemberMPI_Get_address()没有问题,但struct Family无法使用它。有什么问题?

命令:

mpirun -n 2 ./out

输出:

Signal: Segmentation fault (11)
Signal code:  (128)
Failing at address: (nil)
mpirun noticed that process rank 0...

代码:

#include <mpi.h>

struct Member
{
    double height;
    MPI_Datatype mpi_dtype;
    Member() { make_layout(); }
    void make_layout()
    {
        int nblock = 1;
        int block_count[nblock] = {1};
        MPI_Aint offset[nblock];
        MPI_Get_address(&height, &offset[0]);
        MPI_Datatype block_type[nblock] = {MPI_DOUBLE};
        MPI_Type_create_struct(nblock, block_count, offset, block_type, &mpi_dtype);
        MPI_Type_commit(&mpi_dtype);
    }
};

struct Family
{
    Member member;
    MPI_Datatype mpi_dtype;
    Family() { make_layout(); }
    void make_layout()
    {
        int nblock = 1;
        int block_count[nblock] = {1};
        MPI_Aint offset[nblock]; 
        MPI_Get_address(&member, &offset[0]);
        //offset[0] = 0; <-- HERE!!!!!!!
        MPI_Datatype block_type[nblock] = {member.mpi_dtype};
        MPI_Type_create_struct(nblock, block_count, offset, block_type, &mpi_dtype);
        MPI_Type_commit(&mpi_dtype);
    }
};

int main()
{
    int rank;

    MPI_Init(NULL, NULL);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == 0)
    {
        Family f;
        MPI_Send(MPI_BOTTOM, 1, f.mpi_dtype, 1, 0, MPI_COMM_WORLD);
    }
    else if (rank == 1)
    {
        Family f;
        MPI_Recv(MPI_BOTTOM, 1, f.mpi_dtype, 0, 0, MPI_COMM_WORLD, NULL);
    }

    MPI_Finalize();

    return 0;
}

1 个答案:

答案 0 :(得分:0)

member.mpi_dtype已将Member::height的绝对地址作为其类型映射中的偏移量。在Family::make_layout()中,您指定offset[0]等于member的地址时,两个偏移量相加,这会导致非常错误的偏移量。因此,具有绝对地址的MPI数据类型不应用于构造其他数据类型。

在这种情况下绝对没有理由使用MPI_BOTTOM - 您的结构没有动态分配的字段,因此具有相对偏移的MPI数据类型就足够了。