【问题标题】:Segmentation fault in MPI_Send for derived data types派生数据类型的 MPI_Send 中的分段错误
【发布时间】:2017-05-18 00:23:27
【问题描述】:

在下面的代码中,如果将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;
}

【问题讨论】:

  • C++ 不是 C,您的代码肯定不是 C。
  • 既然您已经非常熟悉 C++,您是否考虑过改用 C++ 接口 MPI::Get_address(void*)
  • @JohnBollinger c++ 绑定没有贬值吗? (link)。
  • 不推荐使用 C++ 绑定,是的,但是如果您使用的是 MPI 2,那么它们仍然存在,并且可以使用。这是否是一个好主意取决于您的项目的性质。
  • @JohnBollinger,C++ 绑定已删除,不再是标准的一部分,因为它们没有比 C 绑定带来真正的优势。它们绝对不能用在新开发的代码中。

标签: c++ segmentation-fault mpi openmpi


【解决方案1】:

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

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

【讨论】:

  • 实际上在我的代码中,我几乎在每个结构中都有 STL 对象。这就是我使用绝对地址的原因。我听从了你的建议here
  • 也许我没有明确说明此类数据类型不应进一步组合成其他派生数据类型。
  • 在发送/接收操作中,我想对由动态分配的字段组成的数据类型进行分组以加快速度。我想制作另一种数据类型来对这些动态数据类型进行分组。这是不可能的,因为我正在从由动态对象组成的其他数据类型中创建数据类型?
猜你喜欢
  • 2015-05-20
  • 1970-01-01
  • 1970-01-01
  • 2014-01-25
  • 2017-02-06
  • 1970-01-01
  • 2012-10-24
  • 2016-07-11
  • 2013-04-28
相关资源
最近更新 更多