Miscellaneous

C | Fortran-2008 | Fortran-90

MPI_Cancel

Definition

MPI_Cancel marks a pending non-blocking operation (send or receive) for cancellation and immediately returns. The underlying communication may or may not have already taken place by the time MPI_Cancel was issued. If the call to MPI_Cancel took place before the underlying communication actually happened; the communication is successfully cancelled and no message is sent or received. In the case of a buffered send such as MPI_Ibsend, the corresponding send buffer is automatically freed, and in the case of a receive such as MPI_Irecv, the reception buffer is not altered. However, if the call to MPI_Cancel happened after the underlying communication already took place, the message was already sent or received. Either way, the call to MPI_Cancel is local therefore the non-blocking operation must still be passed to MPI_Wait (or its derivatives), MPI_Test (or its derivatives) or MPI_Request_free. Refer to MPI_Test_cancelled to determine whether a non-blocking operation effectively completed or was cancelled by MPI_Cancel.

Copy

Feedback

int MPI_Cancel(MPI_Request* request);

Parameters

request

The request to mark for cancellation.

Return value

The error code returned from the cancellation.

Example

Copy

Feedback

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

/**
 * @brief Illustrates how to cancel a request.
 * @details This program is meant to be run with 2 processes: a sender and a
 * receiver. The sender issues a non-blocking send to communicate the value
 * 12345 to the receiver, and cancels it with MPI_Cancel. Both processes
 * display what they sent / received depending on whether the MPI_Cancel
 * happened before or after the message could be exchanged.
 **/
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:
        {
            int buffer_sent = 12345;
            MPI_Request request;
            MPI_Isend(&buffer_sent, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request);
            
            // Cancel that request
            MPI_Cancel(&request);

            // The request is marked for cancellation, but the MPI_Cancel operation is local therefore the MPI_Wait is still needed
            MPI_Status status;
            MPI_Wait(&request, &status);

            // Check whether the underlying communication had already taken place
            int flag;
            MPI_Test_cancelled(&status, &flag);

            if(flag)
            {
                // Successful cancellation
                printf("MPI process %d: the cancellation happened before I could send the message, therefore nothing was sent.\n", my_rank);
            }
            else
            {
                // Successful communication
                printf("MPI process %d: the cancellation happened after I sent the message containing value %d.\n", my_rank, buffer_sent);
            }
            break;
        }
        case RECEIVER:
        {
            MPI_Status status;
            int received = 0;
            MPI_Recv(&received, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);

            // Check whether the underlying communication had already taken place
            int flag;
            MPI_Test_cancelled(&status, &flag);

            if(flag)
            {
                // Successful cancellation
                printf("MPI process %d: the cancellation happened before I sent the message, therefore I received nothing and my buffer still contains its original value of %d.\n", my_rank, received);
            }
            else
            {
                // Successful communication
                printf("MPI process %d: the cancellation happened after MPI process %d sent the message, therefore I received value %d as normal.\n", my_rank, SENDER, received);
            }

            break;
        }
    }

    MPI_Finalize();

    return EXIT_SUCCESS;
}