C++ 派生数据类型的MPI_发送中的分段错误

C++ 派生数据类型的MPI_发送中的分段错误,c++,segmentation-fault,mpi,openmpi,C++,Segmentation Fault,Mpi,Openmpi,在下面的代码中,如果MPI_Get_地址(&member,&offset[0])替换为偏移量[0]=0代码按预期工作,否则会给出以下输出。据我所知,在使用MPI\u时,需要底部绝对内存地址,这就是使用MPI\u Get\u address()的原因。虽然structMember对MPI\u Get\u address()没有问题,但struct系列无法使用它。有什么问题 命令: mpirun -n 2 ./out Signal: Segmentation fault (11) Signal c

在下面的代码中,如果
MPI_Get_地址(&member,&offset[0])替换为
偏移量[0]=0代码按预期工作,否则会给出以下输出。据我所知,在使用
MPI\u时,需要底部
绝对内存地址,这就是使用
MPI\u Get\u address()
的原因。虽然struct
Member
MPI\u Get\u address()
没有问题,但struct
系列
无法使用它。有什么问题

命令:

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;
}
输出:

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;
}
代码:

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;
}
#包括
结构成员
{
双高;
MPI_数据类型MPI_数据类型;
成员(){make_layout();}
void make_布局()
{
int nblock=1;
int block_count[nblock]={1};
MPI_Aint offset[nblock];
MPI_Get_地址(&高度和偏移量[0]);
MPI_数据类型block_类型[nblock]={MPI_DOUBLE};
MPI类型创建结构(nblock、block计数、偏移、block类型和MPI数据类型);
MPI\u类型\u提交(&MPI\u数据类型);
}
};
结构族
{
成员;
MPI_数据类型MPI_数据类型;
族(){make_layout();}
void make_布局()
{
int nblock=1;
int block_count[nblock]={1};
MPI_Aint offset[nblock];
MPI_Get_地址(&成员和偏移量[0]);

//偏移量[0]=0;
成员。mpi\u数据类型
已在其类型映射中将
成员::高度
的绝对地址作为偏移量携带。在
族::make_layout()
中,指定
偏移量[0]
等于
成员的地址
,两个偏移量相加,这会导致非常错误的偏移量。因此,具有绝对地址的MPI数据类型不应用于构造其他数据类型


绝对没有理由使用<代码> MPIIOUTHOL/<代码> -在您的结构中没有动态分配的字段,因此具有相对偏移量的MPI数据类型应该足够了。

C++不是C,并且您的代码绝对不是C。因为您确实进入C++,您考虑过使用C++接口<代码> MPI::GETHEA吗?DRADE(空洞*)< /C++ >?@ JundBulner-ER不是C++绑定折旧吗?C++绑定被禁止,但是如果你使用MPI 2,它们仍然存在,并且可以使用。这是否是一个好主意取决于项目的性质。@ JunBulnor,C++绑定被删除,不再是标准的一部分,因为它们在C绑定上没有真正的优势。它们不能简单地用于新的绑定。开发的代码。实际上,在我的代码中,几乎每个结构中都有STL对象。这就是我使用绝对地址的原因。我遵循了你的建议。也许我还没有明确说明这些数据类型不应该进一步组合到其他派生数据类型中。在发送/接收操作中,我希望将由动态allo组成的数据类型分组用于加速的指定字段。我想创建另一个数据类型来对这些动态数据类型进行分组。这是不可能的,因为我正在从由动态对象组成的其他数据类型创建数据类型?