MPI send struct with a vector property in C++

前端 未结 3 1111
南笙
南笙 2021-01-06 03:08

I want to send a struct that has a vector property.

typedef struct {
    int id;
    vector neighbors;
} Node;

I know i have to

3条回答
  •  青春惊慌失措
    2021-01-06 03:53

    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, 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) {
        //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;
    }
    

    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 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);
    
        ...
    }
    

    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);
        //my logic
    
    }
    

    Now it works as expected.

提交回复
热议问题