Мне не понравилась идея импортировать библиотеку, чтобы сделать это просто. Итак, вот что я сделал:
Я думал, что нет никакой причины, чтобы MPI знал что-либо о базовой структуре объекта. Поэтому я мог бы просто вручную преобразовать его в буферный массив, и поскольку приемник знает, что ожидает структуру узла, можно воссоздать объект с другой стороны.Таким образом, изначально я определил MPI_Contiguous
тип данных и отправить его:
int size = (int) ((node.second.neighbors.size() + 1) * sizeof(int *));
MPI_Datatype datatype;
MPI_Type_contiguous(size, MPI_BYTE, &datatype);
MPI_Type_commit(&datatype);
MPI_Isend(&buffer, 1, datatype, proc_rank, TAG_DATA, MPI_COMM_WORLD, &request);
Это более общее решение и работал.
Но поскольку структура содержит int
и vector<int>
, я решил создать ИНТ буфер с первым элементом в качестве node.id
и сброса в качестве node.neighbors
. А с другой стороны, используя MPI_Iprobe
(или синхронно MPI_Probe
) и MPI_Get_count
, я могу воссоздать структуру узла. Вот код:
int *seriealizeNode(Node node) {
//allocate buffer array
int *s = new int[node.neighbors.size() + 1];
//set the first element = Node.id
s[0] = node.id;
//set the rest elements to be the vector elements
for (int i = 0; i < node.neighbors.size(); ++i) {
s[i + 1] = node.neighbors[i];
}
return s;
}
Node deseriealizeNode(int buffer[], int size) {
Node node;
//get the Node.id
node.id = buffer[0];
//get the vector elements
for (int i = 1; i < size; ++i) {
node.neighbors.push_back(buffer[i]);
}
return node;
}
Я думаю, что должно быть более эффективным/быстрым способом для преобразования узла в INT [], и наоборот. Я бы хотел, чтобы кто-то мог предложить несколько советов.
Тогда на стороне отправители:
while (some_condition){
...
//if there is a pending request wait for it to finish and then free the buffer
if (request != MPI_REQUEST_NULL) {
MPI_Wait(&request, &status);
free(send_buffer);
}
// now send the node data
send_buffer = seriealizeNode(node.second);
int buffer_size = (int) (node.second.neighbors.size() + 1);
MPI_Isend(send_buffer, buffer_size, MPI_INT, proc, TAG_DATA, MPI_COMM_WORLD, &request);
...
}
А на стороне приемников:
int count = 0;
MPI_Iprobe(MPI_ANY_SOURCE, TAG_DATA, MPI_COMM_WORLD, &flag, &status);
if (flag) {
MPI_Get_count(&status, MPI_INT, &count);
int *s = new int[count];
MPI_Recv(s, count, MPI_INT, MPI_ANY_SOURCE, TAG_DATA, MPI_COMM_WORLD, &status);
Node node = deseriealizeNode(s, count);
free(s);
//my logic
}
Теперь он работает, как ожидалось.
'vector :: data()' дает вам доступ к необработанному указателю со смежно сохраненными элементами. – ftynse