Persistent

Sending

C | Fortran-2008 | Fortran-90

MPI_Rsend_init

Definition

MPI_Rsend_init prepares a request handle for ready sending using persistent communications. The handle request is inactive upon creation because no actual ready send is issued until the request handle is passed to MPI_Start, at which point it becomes active. An MPI_Rsend_init followed with an MPI_Start is equivalent to MPI_Irsend: the ready send is issued, but completion must still be explicitly checked. Therefore, a wait such as MPI_Wait or a test such as MPI_Test is required before the buffers passed to MPI_Rsend_init can be safely reused. Once the request handle of a persistent communication has been waited upon, or successfully tested, it becomes inactive and can be passed again to MPI_Start to issue that same ready send again. This is how persistent communications save time; they decrease the overhead about argument processing since the list of arguments passed is already known. Using an MPI_Rsend_init does not require the corresponding receive on the receiver MPI process to be done via persistent communications, and vice-versa. Other persistent communications are: MPI_Recv_init, MPI_Send_init, MPI_Bsend_init and MPI_Ssend_init.

Copy

Feedback

int MPI_Rsend_init(const void* buffer,
                   int count,
                   MPI_Datatype datatype,
                   int recipient,
                   int tag,
                   MPI_Comm communicator,
                   MPI_Request* request);

Parameters

buffer

The buffer to send.

count

The number of elements to send.

datatype

The type of one buffer element.

recipient

The rank of the recipient MPI process.

tag

The tag to assign to the message.

communicator

The communicator in which the ready send takes place.

request

The request handle representing the ready send used in persistent communications.

Return value

The error code returned from the ready send.

Example

Copy

Feedback

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>

/**
 * @brief Sends a message as soon as possible in a blocking synchronous fashion.
 * @details This program is meant to be run with 2 processes: a sender and a
 * receiver.
 **/
int main(int argc, char* argv[])
{
    MPI_Init(&argc, &argv);

    // Get the number of processes and check only 2 processes are used
    int size;
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    if(size != 2)
    {
        printf("This application is meant to be run with 2 processes.\n");
        MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
    }

    // Get my rank and do the corresponding job
    enum role_ranks { SENDER, RECEIVER };
    int my_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    switch(my_rank)
    {
        case SENDER:
        {
            // Prepare the ready send
            int buffer_sent;
            MPI_Request request;
            MPI_Rsend_init(&buffer_sent, 1, MPI_INT, RECEIVER, 0, MPI_COMM_WORLD, &request);

            for(int i = 0; i < 3; i++)
            {
                printf("MPI process %d hits the barrier to wait for the matching MPI_Recv to be posted.\n", my_rank);
                MPI_Barrier(MPI_COMM_WORLD);
                printf("The barrier unlocked, which means the MPI_Recv is already posted so the ready send can be issued.\n");
                
                printf("MPI process %d sends value %d for message %d.\n", my_rank, buffer_sent, i);
                // Launch the ready send
                MPI_Start(&request);
                // Wait for the ready send to complete
                MPI_Wait(&request, MPI_STATUS_IGNORE);
            }
            break;
        }
        case RECEIVER:
        {
            int received;
            MPI_Request request;
            for(int i = 0; i < 3; i++)
            {
                MPI_Irecv(&received, 1, MPI_INT, SENDER, 0, MPI_COMM_WORLD, &request);

                printf("MPI process %d issued the MPI_Irecv, moved on and hit the barrier.\n", my_rank);
                MPI_Barrier(MPI_COMM_WORLD);

                // Wait for the underlying MPI_Recv to complete.
                MPI_Wait(&request, MPI_STATUS_IGNORE);
                printf("MPI process %d receives value %d for message %d.\n", my_rank, received, i);
            }
            break;
        }
    }

    MPI_Finalize();

    return EXIT_SUCCESS;
}