如何使用MPI_Datatype和MPI_Type_struct发送向量结构的结构

时间:2017-11-20 11:01:12

标签: c++ struct mpi

我正在尝试发送一个结构:

struct statpSwitch {
  int isActive;
  vector<statvRM> vRM;
};

包含另一个结构的向量:

struct statvRM {
  int isActive;
  int x, y;
};

使用MPI_DatatypeMPI_Type_struct。以下是代码:

int main(int argc, char** argv)
{

  MPI_Init(&argc, &argv);

  // Get ranks and cluster size
  int size = 0, rank = 0, len = 0;
  char hostname[MPI_MAX_PROCESSOR_NAME];
  MPI_Comm mpiComm;

  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  statpSwitch pSwitch[1], pSwitch_recv[1];

  if (rank != 0) {
    statvRM vRM;
    vRM.isActive = 5;
    pSwitch[0].vRM.push_back(vRM);
    pSwitch[0].vRM.push_back(vRM);
    pSwitch[0].vRM.push_back(vRM);
    pSwitch[0].vRM[1].isActive = 69;
    pSwitch[0].isActive = 15;
  }

  MPI_Datatype A_type, B_type;
  MPI_Type_contiguous(3, MPI_INT, &A_type);

  int counts[2];
  MPI_Aint displacements[2];
  MPI_Datatype datatypes[2];

  counts[0] = 1;
  displacements[0] = 0;
  datatypes[0] = MPI_INT;

  counts[1] = 1;
  MPI_Aint extent;
  MPI_Type_extent(MPI_INT, &extent);
  displacements[1] = pSwitch[0].vRM.size() * extent;
  datatypes[1] = A_type;

  MPI_Type_struct(2, counts, displacements, datatypes, &B_type);
  MPI_Type_commit(&B_type);

  // The 1D type is no longer needed
  MPI_Type_free(&A_type);

  if (rank != 0) {
    std::cout << "sending..." << std::flush << std::endl;
    MPI_Send(pSwitch, 1, B_type, 0, 123, MPI_COMM_WORLD);
    std::cout << pSwitch[0].isActive << " " << pSwitch[0].vRM.at(1).isActive <<  std::endl;
  } else {
    MPI_Status status;
    MPI_Recv(pSwitch_recv, 1, B_type, 1, 123, MPI_COMM_WORLD, &status);
    cout << "received" << std::flush << endl;
    std::cout << pSwitch_recv[0].isActive << endl;
    cout << pSwitch_recv[0].vRM.at(1).isActive <<  std::endl;
  }
}

但是MPI在MPI_Recv期间崩溃了。作为参考,使用std::array而不是std:vector时完全相同的代码正在按预期工作:

struct statvRM {
  int isActive;
  int x, y;
};

struct statpSwitch {
  int isActive;
  array<statvRM,3> vRM;
};

int main(int argc, char** argv)
{

  MPI_Init(&argc, &argv);

  // Get ranks and cluster size
  int size = 0, rank = 0, len = 0;
  char hostname[MPI_MAX_PROCESSOR_NAME];
  MPI_Comm mpiComm;

  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);

  statpSwitch pSwitch[1], pSwitch_recv[1];

  if (rank != 0) {
    statvRM vRM;
    vRM.isActive = 5;
    pSwitch[0].vRM[1].isActive = 69;
    pSwitch[0].isActive = 15;
  }

  MPI_Datatype A_type, B_type;
  MPI_Type_contiguous(3, MPI_INT, &A_type);

  int counts[2];
  MPI_Aint displacements[2];
  MPI_Datatype datatypes[2];

  counts[0] = 1;
  displacements[0] = 0;
  datatypes[0] = MPI_INT;

  counts[1] = 1;
  MPI_Aint extent;
  MPI_Type_extent(MPI_INT, &extent);
  displacements[1] = 3 * extent;
  datatypes[1] = A_type;

  MPI_Type_struct(2, counts, displacements, datatypes, &B_type);
  MPI_Type_commit(&B_type);

  // The 1D type is no longer needed
  MPI_Type_free(&A_type);

  if (rank != 0) {
    std::cout << "sending..." << std::flush << std::endl;
    MPI_Send(pSwitch, 1, B_type, 0, 123, MPI_COMM_WORLD);
    std::cout << pSwitch[0].isActive << " " << pSwitch[0].vRM.at(1).isActive <<  std::endl;
  } else {
    MPI_Status status;
    MPI_Recv(pSwitch_recv, 1, B_type, 1, 123, MPI_COMM_WORLD, &status);
    cout << "received" << std::flush << endl;
    std::cout << pSwitch_recv[0].isActive << endl;
    cout << pSwitch_recv[0].vRM.at(1).isActive <<  std::endl;
  }
}    

0 个答案:

没有答案