This section presents several examples of how to use MPI Sessions to create MPI Groups and MPI Communicators.
Example
Example illustrating creation of an MPI communicator using the Sessions Model.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
static MPI_Session lib_shandle = MPI_SESSION_NULL;
static MPI_Comm lib_comm = MPI_COMM_NULL;
int library_foo_init(void)
{
int rc, flag, valuelen;
int ret = 0;
const char pset_name[] = "mpi://WORLD";
const char mt_key[] = "thread_level";
const char mt_value[] = "MPI_THREAD_MULTIPLE";
char out_value[100]; /* large enough */
MPI_Group wgroup = MPI_GROUP_NULL;
MPI_Info sinfo = MPI_INFO_NULL;
MPI_Info tinfo = MPI_INFO_NULL;
MPI_Info_create(&sinfo);
MPI_Info_set(sinfo, mt_key, mt_value);
rc = MPI_Session_init(sinfo, MPI_ERRORS_RETURN,
&lib_shandle);
if (rc != MPI_SUCCESS) {
ret = -1;
goto fn_exit;
}
/*
* check we got thread support level foo library needs
*/
rc = MPI_Session_get_info(lib_shandle, &tinfo);
if (rc != MPI_SUCCESS) {
ret = -1;
goto fn_exit;
}
valuelen = sizeof(out_value);
MPI_Info_get_string(tinfo, mt_key, &valuelen,
out_value, &flag);
if (0 == flag) {
printf("Could not find key %s\n", mt_key);
ret = -1;
goto fn_exit;
}
if (strcmp(out_value, mt_value)) {
printf("Did not get thread multiple support, got %s\n",
out_value);
ret = -1;
goto fn_exit;
}
/*
* create a group from the WORLD process set
*/
rc = MPI_Group_from_session_pset(lib_shandle,
pset_name,
&wgroup);
if (rc != MPI_SUCCESS) {
ret = -1;
goto fn_exit;
}
/*
* get a communicator
*/
rc = MPI_Comm_create_from_group(wgroup,
"org.mpi-forum.mpi-v4_0.example-ex11_10",
MPI_INFO_NULL,
MPI_ERRORS_RETURN,
&lib_comm);
if (rc != MPI_SUCCESS) {
ret = -1;
goto fn_exit;
}
/*
* release unused resources
*/
fn_exit:
if (wgroup != MPI_GROUP_NULL) {
MPI_Group_free(&wgroup);
}
if (sinfo != MPI_INFO_NULL) {
MPI_Info_free(&sinfo);
}
if (tinfo != MPI_INFO_NULL) {
MPI_Info_free(&tinfo);
}
if (ret != 0) {
MPI_Session_finalize(&lib_shandle);
}
return ret;
}
Example Sessions Model Examples shows how the predefined "mpi://WORLD" process set can be used to first create a local MPI group and then subsequently to create an MPI communicator from this group.
Example
This example illustrates the use of Process Set query functions
to select a Process Set to use for MPI Group creation.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int main(int argc, char *argv[])
{
int i, n_psets, psetlen, rc, ret;
int valuelen;
int flag = 0;
char *pset_name = NULL;
char *info_val = NULL;
MPI_Session shandle = MPI_SESSION_NULL;
MPI_Info sinfo = MPI_INFO_NULL;
MPI_Group pgroup = MPI_GROUP_NULL;
if (argc < 2) {
fprintf(stderr, "A process set name fragment is required\n");
return EXIT_FAILURE;
}
rc = MPI_Session_init(MPI_INFO_NULL, MPI_ERRORS_RETURN, &shandle);
if (rc != MPI_SUCCESS) {
fprintf(stderr, "Could not initialize session, bailing out\n");
return EXIT_FAILURE;
}
MPI_Session_get_num_psets(shandle, MPI_INFO_NULL, &n_psets);
for (i=0, pset_name=NULL; i<n_psets; i++) {
psetlen = 0;
MPI_Session_get_nth_pset(shandle, MPI_INFO_NULL, i,
&psetlen, NULL);
pset_name = (char *)malloc(sizeof(char) * psetlen);
MPI_Session_get_nth_pset(shandle, MPI_INFO_NULL, i,
&psetlen, pset_name);
if (strstr(pset_name, argv[1]) != NULL) break;
free(pset_name);
pset_name = NULL;
}
if (pset_name == NULL) {
fprintf(stderr, "Unable to find matching process set\n");
return EXIT_FAILURE;
}
/*
* get instance of an info object for this Session
*/
MPI_Session_get_pset_info(shandle, pset_name, &sinfo);
valuelen = 0;
MPI_Info_get_string(sinfo, "mpi_size", &valuelen, NULL, &flag);
if (flag) {
info_val = (char *)malloc(valuelen);
MPI_Info_get_string(sinfo, "mpi_size", &valuelen, info_val, &flag);
free(info_val);
}
/*
* create a group from the process set
*/
rc = MPI_Group_from_session_pset(shandle, pset_name,
&pgroup);
ret = (rc == MPI_SUCCESS) ? 0 : EXIT_FAILURE;
free(pset_name);
if (pgroup != MPI_GROUP_NULL) {
MPI_Group_free(&pgroup);
}
MPI_Info_free(&sinfo);
MPI_Session_finalize(&shandle);
fprintf(stderr, "Test completed ret = %d\n", ret);
return ret;
}
Example Sessions Model Examples illustrates several aspects of the Sessions Model. First, the default error handler can be specified when instantiating a Session instance. Second, there must be at least two process sets associated with a Session. Third, the example illustrates use of the Sessions info object and the one required key: mpi_size.
Example
A Fortran 2008 example illustrating how to obtain information about available process sets, create an MPI Group
from a process set, and subsequently create an MPI Communicator.
PROGRAM MAIN
USE mpi_f08
IMPLICIT NONE
INTEGER :: pset_len, ierror, n_psets
CHARACTER(LEN=:), ALLOCATABLE :: pset_name
TYPE(MPI_Session) :: shandle
TYPE(MPI_Group) :: pgroup
TYPE(MPI_Comm) :: pcomm
CALL MPI_Session_init(MPI_INFO_NULL, MPI_ERRORS_RETURN, &
shandle, ierror)
IF (ierror .NE. MPI_SUCCESS) THEN
WRITE(*,*) "MPI_Session_init failed"
ERROR STOP
END IF
CALL MPI_Session_get_num_psets(shandle, MPI_INFO_NULL, n_psets)
IF (n_psets .LT. 2) THEN
WRITE(*,*) "MPI_Session_get_num_psets didn't return at least 2 psets"
ERROR STOP
END IF
!
! Just get the second pset's length and name
! Note that index values are zero-based, even in Fortran
!
pset_len = 0
CALL MPI_Session_get_nth_pset(shandle, MPI_INFO_NULL, 1, &
pset_len, pset_name)
ALLOCATE(CHARACTER(LEN=pset_len)::pset_name)
CALL MPI_Session_get_nth_pset(shandle, MPI_INFO_NULL, 1, &
pset_len, pset_name)
!
! create a group from the pset
!
CALL MPI_Group_from_session_pset(shandle, pset_name, pgroup)
!
! free the buffer used for the pset name
!
DEALLOCATE(pset_name)
!
! create a MPI communicator from the group
!
CALL MPI_Comm_create_from_group(pgroup, "session_example", &
MPI_INFO_NULL, &
MPI_ERRORS_RETURN, &
pcomm)
CALL MPI_Barrier(pcomm, ierror)
IF (ierror .NE. MPI_SUCCESS) THEN
WRITE(*,*) "Barrier call on communicator failed"
ERROR STOP
END IF
CALL MPI_Comm_free(pcomm)
CALL MPI_Group_free(pgroup)
CALL MPI_Session_finalize(shandle, ierror)
END PROGRAM MAIN
Note in this example that the call to MPI_SESSION_FINALIZE may block in order to ensure that the calling MPI process has completed its involvement in the preceding MPI_BARRIER operation. If MPI_COMM_DISCONNECT had been used instead of MPI_COMM_FREE, the example would have blocked in MPI_COMM_DISCONNECT rather than MPI_SESSION_FINALIZE.