One-sided

C | Fortran-2008 | Fortran-90

MPI_Win_create_dynamic

Definition

MPI_Win_create_dynamic creates a window through which other MPI processes will be able to interact one-sidedly. Unlike other window creation routines however, MPI_Win_create_dynamic does not assign a memory region to the window during creation. Instead, memory regions can be attached to, or detached from, the window during runtime. RMA interactions with a window created with MPI_Win_create_dynamic have one specificity; the target displacement must be the actual address of the memory region on the target. In other terms, the address must have been received from the target beforehand. MPI_Win_create_dynamic is a collective operation; it must be called by all MPI processes in the intra-communicator. Other variants of MPI_Win_create_dynamic are MPI_Win_create, MPI_Win_allocate and MPI_Win_allocate_shared.

Copy

Feedback

int MPI_Win_create_dynamic(MPI_Info info,
                           MPI_Comm communicator,
                           MPI_Win* window);

Parameters

info

The info argument provides optimisation hints to the runtime about the expected usage pattern of the window.

  • no_locks: if set to true, then the implementation may assume that passive target synchronisation (that is, MPI_Win_lock, MPI_Win_lock_all) will not be used on the given window. This implies that this window is not used for 3-party communication, and RMA can be implemented with no (less) asynchronous agent activity at this process.
  • accumulate_ordering: controls the ordering of accumulate operations at the target. The default value is rar,raw,war,waw.
  • accumulate_ops: if set to same_op, the implementation will assume that all concurrent accumulate calls to the same target address will use the same operation. If set to same_op_no_op, then the implementation will assume that all concurrent accumulate calls to the same target address will use the same operation or MPI_NO_OP. This can eliminate the need to protect access for certain operation types where the hardware can guarantee atomicity. The default is same_op_no_op.
  • same_size: if set to true, then the implementation may assume that the argument size is identical on all processes, and that all processes have provided this info key with the same value.
  • same_disp_unit: if set to true, then the implementation may assume that the argument displacement_unit is identical on all processes, and that all processes have provided this info key with the same value.
communicator

The intra-communicator containing all MPI processes involved in RMA communications. The various processes in the corresponding group may specify completely different target windows, in location, size, displacement units and info arguments. As long as all the get, put and accumulate accesses to a particular process fit their specific target window this should pose no problem. The same area in memory may appear in multiple windows, each associated with a different window object. However, concurrent communications to distinct, overlapping windows may lead to undefined results.

window

A pointer on the variable in which store the window created.

Return value

The error code returned during the window creation:

Example

Copy

Feedback

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

/**
 * @brief Illustrate how to create a window dynamically.
 * @details This application consits of 2 MPI processes. They create a window
 * dynamically, then MPI process 0 attaches a region to its window and send its
 * address to MPI process 1. Finally, MPI process 1 uses that address as part of
 * an MPI_Put to write data into MPI process 0 window, which prints its value at
 * the end.
 **/
int main(int argc, char* argv[])
{
    MPI_Init(&argc, &argv);

    // Check that only 2 MPI processes are spawn
    int comm_size;
    MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
    if(comm_size != 2)
    {
        printf("This application is meant to be run with 2 MPI processes, not %d.\n", comm_size);
        MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
    }

    // Get my rank
    int my_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    // Create the window
    MPI_Win window;
    MPI_Win_create_dynamic(MPI_INFO_NULL, MPI_COMM_WORLD, &window);
    MPI_Win_fence(0, window);
    printf("[MPI process %d] Window created dynamically.\n", my_rank);

    int window_buffer;
    if(my_rank == 0)
    {
        // Allocate and attach the memory region to the window on that target MPI process
        MPI_Win_attach(window, &window_buffer, sizeof(int));
        printf("[MPI Process 0] Memory region attached.\n");

        // Get the address of that window and send it to MPI process 1
        MPI_Aint window_buffer_address;
        MPI_Get_address(&window_buffer, &window_buffer_address);
        MPI_Send(&window_buffer_address, 1, MPI_AINT, 1, 0, MPI_COMM_WORLD);
        printf("[MPI process 0] I send the local address of my memory region to MPI process 1.\n");
    }
    else
    {
        // Get the local address of the memory region attached to that window
        MPI_Aint remote_window_buffer_address;
        MPI_Recv(&remote_window_buffer_address, 1, MPI_AINT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        printf("[MPI process 1] Local address of the memory region attached to the window on MPI process 1 received. I can now use that in MPI_Put.\n");

        // Put the data into into that window
        int value = 12345;
        MPI_Put(&value, 1, MPI_INT, 0, remote_window_buffer_address, 1, MPI_INT, window);
        printf("[MPI Process 1] I put value %d in MPI Process 0 window.\n", value);
    }

    // Destroy the window
    MPI_Win_fence(0, window);
    if(my_rank == 0)
    {
        printf("[MPI process 0] Value in my window: %d.\n", window_buffer);
        MPI_Win_detach(window, &window_buffer);
        printf("[MPI process 0] Memory region detached.\n");
    }
    MPI_Win_free(&window);
    printf("[MPI process 0] Window destroyed.\n");

    MPI_Finalize();

    return EXIT_SUCCESS;
}