I didn't like the idea of importing a library just to do this simple thing. So here is what i did:
I thought that there is no reason to have the MPI know anything about the underlying structure of the object. So i could just manually convert it to a buffer array and since the receiver knows that is expecting a Node struct, can recreate the object on the other side. So initially i defined an MPI_Contiguous
datatype and send it:
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);
This is a more general solution and worked.
But since the struct contains an int
and a vector<int>
, i decided to create an int buffer with the first element as the node.id
and the reset as the node.neighbors
. And on the other side using MPI_Iprobe
(or synchronous MPI_Probe
) and MPI_Get_count
i can recreate the Node struct. Here is the code:
int *seriealizeNode(Node node) {
int *s = new int[node.neighbors.size() + 1];
s[0] = node.id;
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;
node.id = buffer[0];
for (int i = 1; i < size; ++i) {
node.neighbors.push_back(buffer[i]);
}
return node;
}
I think that there must be a more efficient/faster way for converting the Node to int[] and vice versa. I would like if someone could offer some tips.
Then on the senders side:
while (some_condition){
...
if (request != MPI_REQUEST_NULL) {
MPI_Wait(&request, &status);
free(send_buffer);
}
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);
...
}
And on the receivers side:
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);
}
Now it works as expected.
vector::data()
gives you access to raw pointer with contiguously stored elements – ftynse