【发布时间】:2017-05-18 00:23:27
【问题描述】:
在下面的代码中,如果将MPI_Get_address(&member, &offset[0]); 替换为offset[0] = 0;,则代码按预期工作,否则将给出以下输出。据我所知,使用MPI_BOTTOM 需要绝对内存地址,这就是使用MPI_Get_address() 的原因。虽然 struct Member 对 MPI_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