【发布时间】:2017-02-25 10:14:30
【问题描述】:
为什么我使用mpirun -np 2 ./out 命令得到以下代码的以下错误?我在调整std::vector 的大小后调用了make_layout(),所以通常我不应该收到这个错误。如果我不调整大小,它会起作用。是什么原因?
main.cpp:
#include <iostream>
#include <vector>
#include "mpi.h"
MPI_Datatype MPI_CHILD;
struct Child
{
std::vector<int> age;
void make_layout();
};
void Child::make_layout()
{
int nblock = 1;
int age_size = age.size();
int block_count[nblock] = {age_size};
MPI_Datatype block_type[nblock] = {MPI_INT};
MPI_Aint offset[nblock] = {0};
MPI_Type_struct(nblock, block_count, offset, block_type, &MPI_CHILD);
MPI_Type_commit(&MPI_CHILD);
}
int main()
{
int rank, size;
MPI_Init(NULL, NULL);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
Child kid;
kid.age.resize(5);
kid.make_layout();
int datasize;
MPI_Type_size(MPI_CHILD, &datasize);
std::cout << datasize << std::endl; // output: 20 (5x4 seems OK).
if (rank == 0)
{
MPI_Send(&kid, 1, MPI_CHILD, 1, 0, MPI_COMM_WORLD);
}
if (rank == 1)
{
MPI_Recv(&kid, 1, MPI_CHILD, 0, 0, MPI_COMM_WORLD, NULL);
}
MPI_Finalize();
return 0;
}
错误信息:
*** Process received signal ***
Signal: Segmentation fault (11)
Signal code: Address not mapped (1)
Failing at address: 0x14ae7b8
[ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x113d0)[0x7fe1ad91c3d0]
[ 1] /lib/x86_64-linux-gnu/libc.so.6(cfree+0x22)[0x7fe1ad5c5a92]
[ 2] ./out[0x400de4]
[ 3] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fe1ad562830]
[ 4] ./out[0x400ec9]
*** End of error message ***
【问题讨论】:
-
这可能是我给过的最糟糕的与 MPI 相关的建议,但你可以重载一元
Child::operator&以返回age.data()。 -
int nblock = 1;应该是const int nblock = 1; -
@M.M 没有任何区别。
-
@HristoIliev 如果
age不是struct的第一个成员怎么办? -
那么
age.data()在构造的MPI数据类型中的偏移量应该是相对于结构的第一个成员的绝对地址。这适用于结构的所有其他成员。或者您可以简单地使用绝对地址作为偏移量,并在MPI_Send/MPI_Recv中指定MPI_BOTTOM作为缓冲区地址。
标签: c++ linux mpi c++14 openmpi