/*@ MPI_Group_rank - Returns the rank of this process in the given group Input Parameters: . group - group (handle) Output Parameters: . rank - rank of the calling process in group, or 'MPI_UNDEFINED' if the process is not a member (integer) .N SignalSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_GROUP .N MPI_ERR_ARG @*/ int MPI_Group_rank(MPI_Group group, int *rank) { int mpi_errno = MPI_SUCCESS; MPIR_Group *group_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GROUP_RANK); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GROUP_RANK); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_GROUP(group, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPIR_Group_get_ptr( group, group_ptr ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate group_ptr */ MPIR_Group_valid_ptr( group_ptr, mpi_errno ); /* If group_ptr is not value, it will be reset to null */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ *rank = group_ptr->rank; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GROUP_RANK); return mpi_errno; /* --BEGIN ERROR HANDLING-- */ fn_fail: { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE,FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_group_rank", "**mpi_group_rank %G %p", group, rank); } mpi_errno = MPIR_Err_return_comm( NULL, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Group_intersection - Produces a group as the intersection of two existing groups Input Parameters: + group1 - first group (handle) - group2 - second group (handle) Output Parameters: . newgroup - intersection group (handle) Notes: The output group contains those processes that are in both 'group1' and 'group2'. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_GROUP .N MPI_ERR_EXHAUSTED .seealso: MPI_Group_free @*/ int MPI_Group_intersection(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup) { int mpi_errno = MPI_SUCCESS; MPIR_Group *group_ptr1 = NULL; MPIR_Group *group_ptr2 = NULL; MPIR_Group *new_group_ptr; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GROUP_INTERSECTION); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GROUP_INTERSECTION); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_GROUP(group1, mpi_errno); MPIR_ERRTEST_GROUP(group2, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPIR_Group_get_ptr( group1, group_ptr1 ); MPIR_Group_get_ptr( group2, group_ptr2 ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate group_ptr */ MPIR_Group_valid_ptr( group_ptr1, mpi_errno ); MPIR_Group_valid_ptr( group_ptr2, mpi_errno ); /* If either group_ptr is not valid, it will be reset to null */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIR_Group_intersection_impl(group_ptr1, group_ptr2, &new_group_ptr); if (mpi_errno) goto fn_fail; MPIR_OBJ_PUBLISH_HANDLE(*newgroup, new_group_ptr->handle); /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GROUP_INTERSECTION); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_group_intersection", "**mpi_group_intersection %G %G %p", group1, group2, newgroup); } # endif mpi_errno = MPIR_Err_return_comm( NULL, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Group_translate_ranks - Translates the ranks of processes in one group to those in another group Input Parameters: + group1 - group1 (handle) . n - number of ranks in 'ranks1' and 'ranks2' arrays (integer) . ranks1 - array of zero or more valid ranks in 'group1' - group2 - group2 (handle) Output Parameters: . ranks2 - array of corresponding ranks in group2, 'MPI_UNDEFINED' when no correspondence exists. As a special case (see the MPI-2 errata), if the input rank is 'MPI_PROC_NULL', 'MPI_PROC_NULL' is given as the output rank. .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS @*/ int MPI_Group_translate_ranks(MPI_Group group1, int n, const int ranks1[], MPI_Group group2, int ranks2[]) { int mpi_errno = MPI_SUCCESS; MPIR_Group *group_ptr1 = NULL; MPIR_Group *group_ptr2 = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GROUP_TRANSLATE_RANKS); MPIR_ERRTEST_INITIALIZED_ORDIE(); /* The routines that setup the group data structures must be executed * within a mutex. As most of the group routines are not performance * critical, we simple run these routines within the SINGLE_CS */ MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GROUP_TRANSLATE_RANKS); /* Validate parameters, especially handles needing to be converted */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_GROUP(group1, mpi_errno); MPIR_ERRTEST_GROUP(group2, mpi_errno); } MPID_END_ERROR_CHECKS; } #endif /* Convert MPI object handles to object pointers */ MPIR_Group_get_ptr(group1, group_ptr1); MPIR_Group_get_ptr(group2, group_ptr2); /* Validate parameters and objects (post conversion) */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate group_ptr */ MPIR_Group_valid_ptr(group_ptr1, mpi_errno); MPIR_Group_valid_ptr(group_ptr2, mpi_errno); /* If either group_ptr is not valid, it will be reset to null */ MPIR_ERRTEST_ARGNEG(n, "n", mpi_errno); if (group_ptr1) { /* Check that the rank entries are valid */ int size1 = group_ptr1->size; int i; for (i = 0; i < n; i++) { if ((ranks1[i] < 0 && ranks1[i] != MPI_PROC_NULL) || ranks1[i] >= size1) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_RANK, "**rank", "**rank %d %d", ranks1[i], size1); goto fn_fail; } } } MPIR_ERRTEST_ARGNULL(ranks2, "ranks2", mpi_errno); } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIR_Group_translate_ranks_impl(group_ptr1, n, ranks1, group_ptr2, ranks2); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GROUP_TRANSLATE_RANKS); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; /* --BEGIN ERROR HANDLING-- */ fn_fail: { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_group_translate_ranks", "**mpi_group_translate_ranks %G %d %p %G %p", group1, n, ranks1, group2, ranks2); } mpi_errno = MPIR_Err_return_comm(NULL, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Comm_create_group - Creates a new communicator Input Parameters: + comm - communicator (handle) . group - group, which is a subset of the group of 'comm' (handle) - tag - safe tag unused by other communication Output Parameters: . newcomm - new communicator (handle) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_COMM .N MPI_ERR_GROUP .seealso: MPI_Comm_free @*/ int MPI_Comm_create_group(MPI_Comm comm, MPI_Group group, int tag, MPI_Comm * newcomm) { int mpi_errno = MPI_SUCCESS; MPIR_Comm *comm_ptr = NULL, *newcomm_ptr; MPIR_Group *group_ptr; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_COMM_CREATE_GROUP); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_COMM_CREATE_GROUP); /* Validate parameters, and convert MPI object handles to object pointers */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_COMM(comm, mpi_errno); } MPID_END_ERROR_CHECKS; MPIR_Comm_get_ptr( comm, comm_ptr ); MPID_BEGIN_ERROR_CHECKS; { /* Validate comm_ptr */ MPIR_Comm_valid_ptr( comm_ptr, mpi_errno, FALSE ); if (mpi_errno) goto fn_fail; /* If comm_ptr is not valid, it will be reset to null */ MPIR_ERRTEST_COMM_INTRA(comm_ptr, mpi_errno); /* only test for MPI_GROUP_NULL after attempting to convert the comm * so that any errhandlers on comm will (correctly) be invoked */ MPIR_ERRTEST_GROUP(group, mpi_errno); MPIR_ERRTEST_COMM_TAG(tag, mpi_errno); } MPID_END_ERROR_CHECKS; MPIR_Group_get_ptr( group, group_ptr ); MPID_BEGIN_ERROR_CHECKS; { /* Check the group ptr */ MPIR_Group_valid_ptr( group_ptr, mpi_errno ); if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # else { MPIR_Comm_get_ptr( comm, comm_ptr ); MPIR_Group_get_ptr( group, group_ptr ); } # endif /* ... body of routine ... */ mpi_errno = MPIR_Comm_create_group(comm_ptr, group_ptr, tag, &newcomm_ptr); if (mpi_errno) MPIR_ERR_POP(mpi_errno); if (newcomm_ptr) MPIR_OBJ_PUBLISH_HANDLE(*newcomm, newcomm_ptr->handle); else *newcomm = MPI_COMM_NULL; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_COMM_CREATE_GROUP); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ #ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_comm_create_group", "**mpi_comm_create_group %C %G %d %p", comm, group, tag, newcomm); } #endif mpi_errno = MPIR_Err_return_comm(comm_ptr, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Group_incl - Produces a group by reordering an existing group and taking only listed members Input Parameters: + group - group (handle) . n - number of elements in array 'ranks' (and size of newgroup) (integer) - ranks - ranks of processes in 'group' to appear in 'newgroup' (array of integers) Output Parameters: . newgroup - new group derived from above, in the order defined by 'ranks' (handle) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_GROUP .N MPI_ERR_ARG .N MPI_ERR_EXHAUSTED .N MPI_ERR_RANK .seealso: MPI_Group_free @*/ int MPI_Group_incl(MPI_Group group, int n, const int ranks[], MPI_Group * newgroup) { int mpi_errno = MPI_SUCCESS; MPIR_Group *group_ptr = NULL, *new_group_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GROUP_INCL); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GROUP_INCL); /* Validate parameters, especially handles needing to be converted */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_GROUP(group, mpi_errno); MPIR_ERRTEST_ARGNEG(n, "n", mpi_errno); } MPID_END_ERROR_CHECKS; } #endif /* Convert MPI object handles to object pointers */ MPIR_Group_get_ptr(group, group_ptr); /* Validate parameters and objects (post conversion) */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate group_ptr */ MPIR_Group_valid_ptr(group_ptr, mpi_errno); /* If group_ptr is not valid, it will be reset to null */ if (group_ptr) { mpi_errno = MPIR_Group_check_valid_ranks(group_ptr, ranks, n); } if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ if (n == 0) { *newgroup = MPI_GROUP_EMPTY; goto fn_exit; } mpi_errno = MPIR_Group_incl_impl(group_ptr, n, ranks, &new_group_ptr); if (mpi_errno) goto fn_fail; MPIR_OBJ_PUBLISH_HANDLE(*newgroup, new_group_ptr->handle); /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GROUP_INCL); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ #ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER, "**mpi_group_incl", "**mpi_group_incl %G %d %p %p", group, n, ranks, newgroup); } #endif mpi_errno = MPIR_Err_return_comm(NULL, __func__, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Group_compare - Compares two groups Input Parameters: + group1 - group1 (handle) - group2 - group2 (handle) Output Parameters: . result - integer which is 'MPI_IDENT' if the order and members of the two groups are the same, 'MPI_SIMILAR' if only the members are the same, and 'MPI_UNEQUAL' otherwise .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_GROUP .N MPI_ERR_ARG @*/ int MPI_Group_compare(MPI_Group group1, MPI_Group group2, int *result) { int mpi_errno = MPI_SUCCESS; MPIR_Group *group_ptr1 = NULL; MPIR_Group *group_ptr2 = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GROUP_COMPARE); MPIR_ERRTEST_INITIALIZED_ORDIE(); /* The routines that setup the group data structures must be executed within a mutex. As most of the group routines are not performance critical, we simple run these routines within the SINGLE_CS */ MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GROUP_COMPARE); /* Validate parameters, especially handles needing to be converted */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_ARGNULL( result, "result", mpi_errno ); MPIR_ERRTEST_GROUP(group1, mpi_errno); MPIR_ERRTEST_GROUP(group2, mpi_errno); } MPID_END_ERROR_CHECKS; } # endif /* Convert MPI object handles to object pointers */ MPIR_Group_get_ptr( group1, group_ptr1 ); MPIR_Group_get_ptr( group2, group_ptr2 ); /* Validate parameters and objects (post conversion) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate group_ptr */ MPIR_Group_valid_ptr( group_ptr1, mpi_errno ); MPIR_Group_valid_ptr( group_ptr2, mpi_errno ); /* If group_ptr is not valid, it will be reset to null */ if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPIR_Group_compare_impl(group_ptr1, group_ptr2, result); if (mpi_errno) MPIR_ERR_POP(mpi_errno); /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GROUP_COMPARE); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; /* --BEGIN ERROR HANDLING-- */ fn_fail: { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_group_compare", "**mpi_group_compare %G %G %p", group1, group2, result); } mpi_errno = MPIR_Err_return_comm( NULL, FCNAME, mpi_errno ); goto fn_exit; /* --END ERROR HANDLING-- */ }
/*@ MPI_Win_start - Start an RMA access epoch for MPI Input Parameters: + group - group of target processes (handle) . assert - Used to optimize this call; zero may be used as a default. See notes. (integer) - win - window object (handle) Notes: The 'assert' argument is used to indicate special conditions for the fence that an implementation may use to optimize the 'MPI_Win_start' operation. The value zero is always correct. Other assertion values may be or''ed together. Assertions tha are valid for 'MPI_Win_start' are\: . MPI_MODE_NOCHECK - the matching calls to 'MPI_WIN_POST' have already completed on all target processes when the call to 'MPI_WIN_START' is made. The nocheck option can be specified in a start call if and only if it is specified in each matching post call. This is similar to the optimization of ready-send that may save a handshake when the handshake is implicit in the code. (However, ready-send is matched by a regular receive, whereas both start and post must specify the nocheck option.) .N ThreadSafe .N Fortran .N Errors .N MPI_SUCCESS .N MPI_ERR_WIN .N MPI_ERR_OTHER @*/ int MPI_Win_start(MPI_Group group, int assert, MPI_Win win) { int mpi_errno = MPI_SUCCESS; MPIR_Win *win_ptr = NULL; MPIR_Group *group_ptr = NULL; MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_WIN_START); MPIR_ERRTEST_INITIALIZED_ORDIE(); MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); MPIR_FUNC_TERSE_RMA_ENTER(MPID_STATE_MPI_WIN_START); /* Validate parameters, especially handles needing to be converted */ #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { MPIR_ERRTEST_WIN(win, mpi_errno); MPIR_ERRTEST_GROUP(group, mpi_errno); } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* Get handles to MPI objects. */ MPIR_Win_get_ptr(win, win_ptr); MPIR_Group_get_ptr(group, group_ptr); #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { /* Validate win_ptr */ MPIR_Win_valid_ptr(win_ptr, mpi_errno); if (mpi_errno) goto fn_fail; MPIR_Group_valid_ptr(group_ptr, mpi_errno); /* TODO: Validate assert argument */ /* TODO: Validate window state */ if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ mpi_errno = MPID_Win_start(group_ptr, assert, win_ptr); if (mpi_errno != MPI_SUCCESS) goto fn_fail; /* ... end of body of routine ... */ fn_exit: MPIR_FUNC_TERSE_RMA_EXIT(MPID_STATE_MPI_WIN_START); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ #ifdef HAVE_ERROR_CHECKING { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_win_start", "**mpi_win_start %G %A %W", group, assert, win); } #endif mpi_errno = MPIR_Err_return_win(win_ptr, FCNAME, mpi_errno); goto fn_exit; /* --END ERROR HANDLING-- */ }