At the very beginning of the topic, we saw that MPI_Win_create can use any buffer. However, MPI provides its own allocation function called MPI_Alloc_mem, which may be used in place of statically allocated buffers or otherwise dynamically allocated buffers (e.g. the C standard library's malloc). Although memory allocation for the window is antecedent to the creation of the window itself (with one exception, discussed below), since this step is optional and has many advanced alternatives, we have saved its discussion until last.

int MPI_Alloc_mem(MPI_Aint size, MPI_Info info, void *base)
size
size of memory segment to be allocated in bytes
info
handle to an MPI_Info object
base
address of the memory segment allocated (offset)

While there is not necessarily an advantage in using this function, there is no particular disadvantage in doing so either, since it may be implemented to call malloc directly. Additionally, the info argument may be used to provide (implementation-specific) directives that give additional control over memory allocation. It should go without saying that this is a form of optimization that should be considered later on rather than early on in the implementation of one's algorithm, but using MPI_Alloc_mem calls instead of malloc calls may simplify the process later on.

In MPI-3, memory allocation and window creation can now be paired together through the use of MPI_Win_allocate:

int MPI_Win_allocate(MPI_Aint size, int disp_unit, \
     MPI_Info info, MPI_Comm comm, void *base, MPI_Win *win)

The descriptions of the arguments for MPI_Win_allocate are the same as the corresponding arguments in MPI_Win_create and MPI_Alloc_mem. As we've seen in prior topics for MPI, it is generally good for behind-the-scenes performance gains when we can combine two MPI calls into a single MPI call. One benefit of using MPI_Win_allocate is that it can be used to allocate a window that is globally symmetric and has the same base address in all processes. This can help improve performance for a variety of reasons, including symmetry reducing the chance of one process waiting on another as well as reducing the amount of pointer arithmetic that needs to be done when performing RMA operations involving many processes.

Windows with dynamically attached memory

So far, we've seen that a window is typically attached to pre-allocated buffers, or allocated and attached at the time of window creation. Of course, there are many situations where one does not know how much memory is needed in the future. For this reason, MPI-3 introduced several routines that enable the creation and memory management of windows that can have dynamically attached memory.

int MPI_Win_create_dynamic(MPI_Info info, MPI_Comm comm, MPI_Win *win)

int MPI_Win_attach(MPI_Win win, void *base, MPI_Aint size)

int MPI_Win_detach(MPI_Win win, const void *base)

Clearly, a window created with MPI_Win_create_dynamic has no attached memory at the time of creation; to access memory in the window, MPI_Win_attach must first be called. Multiple non-overlapping regions may be attached to the same window. Due to some of the special properties associated with such a window, it is sometimes called a dynamic window, and MPI_Win_attach and MPI_Win_detach can only be called on such windows. The possibility of attaching multiple buffers and the ability to detach buffers gives them a great deal of flexibility. As with all forms of dynamic memory allocation, it is very important to make sure all buffers are correctly allocated before trying to use them (such as attaching them), and it is also important to free the buffers at the appropriate place in one's code to prevent memory leaks.

Freeing window memory

MPI_Free_mem should be paired with MPI_Alloc_mem in order to free dynamically allocated memory; if malloc was indirectly used to allocate the memory, then MPI_Free_mem will simply call free on the allocated memory segment.

int MPI_Free_mem(void *base)
 
©   Cornell University  |  Center for Advanced Computing  |  Copyright Statement  |  Inclusivity Statement