Здравствуйте, я пишу программу c++
, в которой я хочу, чтобы MPI взаимодействовал по производному типу данных. Но получатель не получает полную информацию, которую отправляет отправитель.
Вот как я создаю свой производный тип данных:
// dg_derived_datatype.cpp
#include <mpi.h>
#include "dg_derived_datatype.h"
namespace Hash{
MPI_Datatype Face_type;
};
void Construct_data_type(){
MPI_Face_type();
}
void MPI_Face_type(){
int num = 3;
// Number of elements in each block (array of integers)
int elem_blocklength[num]{2, 1, 5};
// Byte displacement of each block (array of integers).
MPI_Aint array_of_offsets[num];
MPI_Aint intex, charex;
MPI_Aint lb;
MPI_Type_get_extent(MPI_INT, &lb, &intex);
MPI_Type_get_extent(MPI_CHAR, &lb, &charex);
array_of_offsets[0] = (MPI_Aint) 0;
array_of_offsets[1] = array_of_offsets[0] + intex * 2;
array_of_offsets[2] = array_of_offsets[1] + charex;
MPI_Datatype array_of_types[num]{MPI_INT, MPI_CHAR, MPI_INT};
// create and MPI datatype
MPI_Type_create_struct(num, elem_blocklength, array_of_offsets, array_of_types, &Hash::Face_type);
MPI_Type_commit(&Hash::Face_type);
}
void Free_type(){
MPI_Type_free(&Hash::Face_type);
}
Здесь я получаю свой тип данных Hash::Face_type
и фиксирую его. Hash::Face_type
используется для передачи вектора моей структуры (face_pack
, 2 int + 1 char + 5 int).
// dg_derived_datatype.h
#ifndef DG_DERIVED_DATA_TYPE_H
#define DG_DERIVED_DATA_TYPE_H
#include <mpi.h>
struct face_pack{
int owners_key;
int facei;
char face_type;
int hlevel;
int porderx;
int pordery;
int key;
int rank;
};
namespace Hash{
extern MPI_Datatype Face_type;
};
void Construct_data_type();
void Free_type();
#endif
Затем в своей основной программе я делаю
// dg_main.cpp
#include <iostream>
#include <mpi.h>
#include "dg_derived_datatype.h"
#include <vector>
void Recv_face(int source, int tag, std::vector<face_pack>& recv_face);
int main(){
// Initialize MPI.
// some code here.
// I create a vector of struct: std::vector<face_pack> face_info,
// to store the info I want to let proccesors communicate.
Construct_data_type(); // construct my derived data type
MPI_Request request_pre1, request_pre2, request_next1, request_next2;
// send
if(num_next > 0){ // If fullfilled the current processor send info to the next processor (myrank + 1)
std::vector<face_pack> face_info;
// some code to construct face_info
// source my_rank, destination my_rank + 1
MPI_Isend(&face_info[0], num_n, Hash::Face_type, mpi::rank + 1, mpi::rank + 1, MPI_COMM_WORLD, &request_next2);
}
// recv
if(some critira){ // recv from the former processor (my_rank - 1)
std::vector<face_pack> recv_face;
Recv_face(mpi::rank - 1, mpi::rank, recv_face); // recv info from former processor
}
if(num_next > 0){
MPI_Status status;
MPI_Wait(&request_next2, &status);
}
Free_type();
// finialize MPI
}
void Recv_face(int source, int tag, std::vector<face_pack>& recv_face){
MPI_Status status1, status2;
MPI_Probe(source, tag, MPI_COMM_WORLD, &status1);
int count;
MPI_Get_count(&status1, Hash::Face_type, &count);
recv_face = std::vector<face_pack>(count);
MPI_Recv(&recv_face[0], count, Hash::Face_type, source, tag, MPI_COMM_WORLD, &status2);
}
Проблема в том, что получатель иногда получает неполную информацию.
Например, я распечатываю face_info
до его отправки:
// rank 2
owners_key3658 facei 0 face_type M neighbour 192 n_rank 0
owners_key3658 facei 1 face_type L neighbour 66070 n_rank 1
owners_key3658 facei 1 face_type L neighbour 76640 n_rank 1
owners_key3658 facei 2 face_type M neighbour 2631 n_rank 0
owners_key3658 facei 3 face_type L neighbour 4953 n_rank 1
...
owners_key49144 facei 1 face_type M neighbour 844354 n_rank 2
owners_key49144 facei 1 face_type M neighbour 913280 n_rank 2
owners_key49144 facei 2 face_type L neighbour 41619 n_rank 1
owners_key49144 facei 3 face_type M neighbour 57633 n_rank 2
Что правильно.
Но на стороне получателя я распечатываю полученное сообщение:
owners_key3658 facei 0 face_type M neighbour 192 n_rank 0
owners_key3658 facei 1 face_type L neighbour 66070 n_rank 1
owners_key3658 facei 1 face_type L neighbour 76640 n_rank 1
owners_key3658 facei 2 face_type M neighbour 2631 n_rank 0
owners_key3658 facei 3 face_type L neighbour 4953 n_rank 1
... // at the beginning it's fine, however, at the end it messed up
owners_key242560 facei 2 face_type ! neighbour 2 n_rank 2
owners_key217474 facei 2 face_type ! neighbour 2 n_rank 2
owners_key17394 facei 2 face_type ! neighbour 2 n_rank 2
owners_key216815 facei 2 face_type ! neighbour 2 n_rank 2
Конечно, он потерял информацию face_type
, которая является символом. И, насколько я знаю, std::vector
гарантирует непрерывную память здесь . Поэтому я не уверен, какая часть моего производного типа данных MPI неверна. Передача сообщений иногда работает, иногда нет.