|
Packit |
0848f5 |
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* (C) 2001 by Argonne National Laboratory.
|
|
Packit |
0848f5 |
* See COPYRIGHT in top-level directory.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#include "mpiimpl.h"
|
|
Packit |
0848f5 |
#include "group.h"
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#ifndef MPID_GROUP_PREALLOC
|
|
Packit |
0848f5 |
#define MPID_GROUP_PREALLOC 8
|
|
Packit |
0848f5 |
#endif
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Preallocated group objects */
|
|
Packit |
0848f5 |
MPID_Group MPID_Group_builtin[MPID_GROUP_N_BUILTIN] = { {0} };
|
|
Packit |
0848f5 |
MPID_Group MPID_Group_direct[MPID_GROUP_PREALLOC] = { {0} };
|
|
Packit |
0848f5 |
MPIU_Object_alloc_t MPID_Group_mem = { 0, 0, 0, 0, MPID_GROUP,
|
|
Packit |
0848f5 |
sizeof(MPID_Group), MPID_Group_direct,
|
|
Packit |
0848f5 |
MPID_GROUP_PREALLOC};
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPID_Group * const MPID_Group_empty = &MPID_Group_builtin[0];
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int MPIR_Group_init(void)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int mpi_errno = MPI_SUCCESS;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPIU_Assert(MPID_GROUP_N_BUILTIN == 1); /* update this func if this ever triggers */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPID_Group_builtin[0].handle = MPI_GROUP_EMPTY;
|
|
Packit |
0848f5 |
MPIU_Object_set_ref(&MPID_Group_builtin[0], 1);
|
|
Packit |
0848f5 |
MPID_Group_builtin[0].size = 0;
|
|
Packit |
0848f5 |
MPID_Group_builtin[0].rank = MPI_UNDEFINED;
|
|
Packit |
0848f5 |
MPID_Group_builtin[0].idx_of_first_lpid = -1;
|
|
Packit |
0848f5 |
MPID_Group_builtin[0].lrank_to_lpid = NULL;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* TODO hook for device here? */
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
int MPIR_Group_release(MPID_Group *group_ptr)
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int mpi_errno = MPI_SUCCESS;
|
|
Packit |
0848f5 |
int inuse;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPIR_Group_release_ref(group_ptr, &inuse);
|
|
Packit |
0848f5 |
if (!inuse) {
|
|
Packit |
0848f5 |
/* Only if refcount is 0 do we actually free. */
|
|
Packit |
0848f5 |
MPIU_Free(group_ptr->lrank_to_lpid);
|
|
Packit |
0848f5 |
MPIU_Handle_obj_free( &MPID_Group_mem, group_ptr );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Allocate a new group and the group lrank to lpid array. Does *not*
|
|
Packit |
0848f5 |
* initialize any arrays, but does set the reference count.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
#define FCNAME "MPIR_Group_create"
|
|
Packit |
0848f5 |
int MPIR_Group_create( int nproc, MPID_Group **new_group_ptr )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int mpi_errno = MPI_SUCCESS;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
*new_group_ptr = (MPID_Group *)MPIU_Handle_obj_alloc( &MPID_Group_mem );
|
|
Packit |
0848f5 |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit |
0848f5 |
if (!*new_group_ptr) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPIR_Group_create", __LINE__, MPI_ERR_OTHER, "**nomem", 0 );
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/* --END ERROR HANDLING-- */
|
|
Packit |
0848f5 |
MPIU_Object_set_ref( *new_group_ptr, 1 );
|
|
Packit |
0848f5 |
(*new_group_ptr)->lrank_to_lpid =
|
|
Packit |
0848f5 |
(MPID_Group_pmap_t *)MPIU_Malloc( nproc * sizeof(MPID_Group_pmap_t) );
|
|
Packit |
0848f5 |
/* --BEGIN ERROR HANDLING-- */
|
|
Packit |
0848f5 |
if (!(*new_group_ptr)->lrank_to_lpid) {
|
|
Packit |
0848f5 |
MPIU_Handle_obj_free( &MPID_Group_mem, *new_group_ptr );
|
|
Packit |
0848f5 |
*new_group_ptr = NULL;
|
|
Packit |
0848f5 |
MPIU_CHKMEM_SETERR(mpi_errno,nproc*sizeof(MPID_Group_pmap_t),
|
|
Packit |
0848f5 |
"newgroup->lrank_to_lpid");
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/* --END ERROR HANDLING-- */
|
|
Packit |
0848f5 |
(*new_group_ptr)->size = nproc;
|
|
Packit |
0848f5 |
/* Make sure that there is no question that the list of ranks sorted
|
|
Packit |
0848f5 |
by pids is marked as uninitialized */
|
|
Packit |
0848f5 |
(*new_group_ptr)->idx_of_first_lpid = -1;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
(*new_group_ptr)->is_local_dense_monotonic = FALSE;
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* return value is the first index in the list
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* This "sorts" an lpid array by lpid value, using a simple merge sort
|
|
Packit |
0848f5 |
* algorithm.
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* In actuality, it does not reorder the elements of maparray (these must remain
|
|
Packit |
0848f5 |
* in group rank order). Instead it builds the traversal order (in increasing
|
|
Packit |
0848f5 |
* lpid order) through the maparray given by the "next_lpid" fields.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
static int mergesort_lpidarray( MPID_Group_pmap_t maparray[], int n )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int idx1, idx2, first_idx, cur_idx, next_lpid, idx2_offset;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (n == 2) {
|
|
Packit |
0848f5 |
if (maparray[0].lpid > maparray[1].lpid) {
|
|
Packit |
0848f5 |
first_idx = 1;
|
|
Packit |
0848f5 |
maparray[0].next_lpid = -1;
|
|
Packit |
0848f5 |
maparray[1].next_lpid = 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
first_idx = 0;
|
|
Packit |
0848f5 |
maparray[0].next_lpid = 1;
|
|
Packit |
0848f5 |
maparray[1].next_lpid = -1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
return first_idx;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (n == 1) {
|
|
Packit |
0848f5 |
maparray[0].next_lpid = -1;
|
|
Packit |
0848f5 |
return 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (n == 0)
|
|
Packit |
0848f5 |
return -1;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Sort each half */
|
|
Packit |
0848f5 |
idx2_offset = n/2;
|
|
Packit |
0848f5 |
idx1 = mergesort_lpidarray( maparray, n/2 );
|
|
Packit |
0848f5 |
idx2 = mergesort_lpidarray( maparray + idx2_offset, n - n/2 ) + idx2_offset;
|
|
Packit |
0848f5 |
/* merge the results */
|
|
Packit |
0848f5 |
/* There are three lists:
|
|
Packit |
0848f5 |
first_idx - points to the HEAD of the sorted, merged list
|
|
Packit |
0848f5 |
cur_idx - points to the LAST element of the sorted, merged list
|
|
Packit |
0848f5 |
idx1 - points to the HEAD of one sorted list
|
|
Packit |
0848f5 |
idx2 - points to the HEAD of the other sorted list
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
We first identify the head element of the sorted list. We then
|
|
Packit |
0848f5 |
take elements from the remaining lists. When one list is empty,
|
|
Packit |
0848f5 |
we add the other list to the end of sorted list.
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
The last wrinkle is that the next_lpid fields in maparray[idx2]
|
|
Packit |
0848f5 |
are relative to n/2, not 0 (that is, a next_lpid of 1 is
|
|
Packit |
0848f5 |
really 1 + n/2, relative to the beginning of maparray).
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
/* Find the head element */
|
|
Packit |
0848f5 |
if (maparray[idx1].lpid > maparray[idx2].lpid) {
|
|
Packit |
0848f5 |
first_idx = idx2;
|
|
Packit |
0848f5 |
idx2 = maparray[idx2].next_lpid + idx2_offset;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
first_idx = idx1;
|
|
Packit |
0848f5 |
idx1 = maparray[idx1].next_lpid;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Merge the lists until one is empty */
|
|
Packit |
0848f5 |
cur_idx = first_idx;
|
|
Packit |
0848f5 |
while ( idx1 >= 0 && idx2 >= 0) {
|
|
Packit |
0848f5 |
if (maparray[idx1].lpid > maparray[idx2].lpid) {
|
|
Packit |
0848f5 |
next_lpid = maparray[idx2].next_lpid;
|
|
Packit |
0848f5 |
if (next_lpid >= 0) next_lpid += idx2_offset;
|
|
Packit |
0848f5 |
maparray[cur_idx].next_lpid = idx2;
|
|
Packit |
0848f5 |
cur_idx = idx2;
|
|
Packit |
0848f5 |
idx2 = next_lpid;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
next_lpid = maparray[idx1].next_lpid;
|
|
Packit |
0848f5 |
maparray[cur_idx].next_lpid = idx1;
|
|
Packit |
0848f5 |
cur_idx = idx1;
|
|
Packit |
0848f5 |
idx1 = next_lpid;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
/* Add whichever list remains */
|
|
Packit |
0848f5 |
if (idx1 >= 0) {
|
|
Packit |
0848f5 |
maparray[cur_idx].next_lpid = idx1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
maparray[cur_idx].next_lpid = idx2;
|
|
Packit |
0848f5 |
/* Convert the rest of these next_lpid values to be
|
|
Packit |
0848f5 |
relative to the beginning of maparray */
|
|
Packit |
0848f5 |
while (idx2 >= 0) {
|
|
Packit |
0848f5 |
next_lpid = maparray[idx2].next_lpid;
|
|
Packit |
0848f5 |
if (next_lpid >= 0) {
|
|
Packit |
0848f5 |
next_lpid += idx2_offset;
|
|
Packit |
0848f5 |
maparray[idx2].next_lpid = next_lpid;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
idx2 = next_lpid;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
return first_idx;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* Create a list of the lpids, in lpid order.
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* Called by group_compare, group_translate_ranks, group_union
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* In the case of a single master thread lock, the lock must
|
|
Packit |
0848f5 |
* be held on entry to this routine. This forces some of the routines
|
|
Packit |
0848f5 |
* noted above to hold the SINGLE_CS; which would otherwise not be required.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
void MPIR_Group_setup_lpid_list( MPID_Group *group_ptr )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
if (group_ptr->idx_of_first_lpid == -1) {
|
|
Packit |
0848f5 |
group_ptr->idx_of_first_lpid =
|
|
Packit |
0848f5 |
mergesort_lpidarray( group_ptr->lrank_to_lpid,
|
|
Packit |
0848f5 |
group_ptr->size );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
void MPIR_Group_setup_lpid_pairs( MPID_Group *group_ptr1,
|
|
Packit |
0848f5 |
MPID_Group *group_ptr2 )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
/* If the lpid list hasn't been created, do it now */
|
|
Packit |
0848f5 |
if (group_ptr1->idx_of_first_lpid < 0) {
|
|
Packit |
0848f5 |
MPIR_Group_setup_lpid_list( group_ptr1 );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (group_ptr2->idx_of_first_lpid < 0) {
|
|
Packit |
0848f5 |
MPIR_Group_setup_lpid_list( group_ptr2 );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#ifdef HAVE_ERROR_CHECKING
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* The following routines are needed only for error checking
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#undef FUNCNAME
|
|
Packit |
0848f5 |
#define FUNCNAME MPIR_Group_check_valid_ranks
|
|
Packit |
0848f5 |
#undef FCNAME
|
|
Packit |
0848f5 |
#define FCNAME "MPIR_Group_check_valid_ranks"
|
|
Packit |
0848f5 |
/*
|
|
Packit |
0848f5 |
* This routine is for error checking for a valid ranks array, used
|
|
Packit |
0848f5 |
* by Group_incl and Group_excl.
|
|
Packit |
0848f5 |
*
|
|
Packit |
0848f5 |
* Note that because this uses the flag field in the group, it
|
|
Packit |
0848f5 |
* must be used by only on thread at a time (per group). For the SINGLE_CS
|
|
Packit |
0848f5 |
* case, that means that the SINGLE_CS must be held on entry to this routine.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
int MPIR_Group_check_valid_ranks( MPID_Group *group_ptr, const int ranks[], int n )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int mpi_errno = MPI_SUCCESS, i;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
for (i=0; i<group_ptr->size; i++) {
|
|
Packit |
0848f5 |
group_ptr->lrank_to_lpid[i].flag = 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
for (i=0; i
|
|
Packit |
0848f5 |
if (ranks[i] < 0 ||
|
|
Packit |
0848f5 |
ranks[i] >= group_ptr->size) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_RANK,
|
|
Packit |
0848f5 |
"**rankarray", "**rankarray %d %d %d",
|
|
Packit |
0848f5 |
i, ranks[i], group_ptr->size-1 );
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (group_ptr->lrank_to_lpid[ranks[i]].flag) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_RANK,
|
|
Packit |
0848f5 |
"**rankdup", "**rankdup %d %d %d",
|
|
Packit |
0848f5 |
i, ranks[i],
|
|
Packit |
0848f5 |
group_ptr->lrank_to_lpid[ranks[i]].flag-1);
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
group_ptr->lrank_to_lpid[ranks[i]].flag = i+1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Service routine to check for valid range arguments. This routine makes use
|
|
Packit |
0848f5 |
of some of the internal fields in a group; in a multithreaded MPI program,
|
|
Packit |
0848f5 |
these must ensure that only one thread is accessing the group at a time.
|
|
Packit |
0848f5 |
In the SINGLE_CS model, this routine requires that the calling routine
|
|
Packit |
0848f5 |
be within the SINGLE_CS (the routines are group_range_incl and
|
|
Packit |
0848f5 |
group_range_excl) */
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#undef FUNCNAME
|
|
Packit |
0848f5 |
#define FUNCNAME MPIR_Group_check_valid_ranges
|
|
Packit |
0848f5 |
#undef FCNAME
|
|
Packit |
0848f5 |
#define FCNAME "MPIR_Group_check_valid_ranges"
|
|
Packit |
0848f5 |
int MPIR_Group_check_valid_ranges( MPID_Group *group_ptr,
|
|
Packit |
0848f5 |
int ranges[][3], int n )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int i, j, size, first, last, stride, mpi_errno = MPI_SUCCESS;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (n < 0) {
|
|
Packit |
0848f5 |
MPIR_ERR_SETANDSTMT2(mpi_errno,MPI_ERR_ARG,;,
|
|
Packit |
0848f5 |
"**argneg", "**argneg %s %d", "n", n );
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
size = group_ptr->size;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* First, clear the flag */
|
|
Packit |
0848f5 |
for (i=0; i
|
|
Packit |
0848f5 |
group_ptr->lrank_to_lpid[i].flag = 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
for (i=0; i
|
|
Packit |
0848f5 |
int act_last;
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
first = ranges[i][0]; last = ranges[i][1];
|
|
Packit |
0848f5 |
stride = ranges[i][2];
|
|
Packit |
0848f5 |
if (first < 0 || first >= size) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG,
|
|
Packit |
0848f5 |
"**rangestartinvalid",
|
|
Packit |
0848f5 |
"**rangestartinvalid %d %d %d",
|
|
Packit |
0848f5 |
i, first, size );
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (stride == 0) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG,
|
|
Packit |
0848f5 |
"**stridezero", 0 );
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* We must compute the actual last value, taking into account
|
|
Packit |
0848f5 |
the stride value. At this point, we know that the stride is
|
|
Packit |
0848f5 |
non-zero
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
act_last = first + stride * ((last - first) / stride);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (last < 0 || act_last >= size) {
|
|
Packit |
0848f5 |
/* Use last instead of act_last in the error message since
|
|
Packit |
0848f5 |
the last value is the one that the user provided */
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG,
|
|
Packit |
0848f5 |
"**rangeendinvalid",
|
|
Packit |
0848f5 |
"**rangeendinvalid %d %d %d",
|
|
Packit |
0848f5 |
i, last, size );
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if ( (stride > 0 && first > last) ||
|
|
Packit |
0848f5 |
(stride < 0 && first < last) ) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_ARG,
|
|
Packit |
0848f5 |
"**stride", "**stride %d %d %d",
|
|
Packit |
0848f5 |
first, last, stride );
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* range is valid. Mark flags */
|
|
Packit |
0848f5 |
if (stride > 0) {
|
|
Packit |
0848f5 |
for (j=first; j<=last; j+=stride) {
|
|
Packit |
0848f5 |
if (group_ptr->lrank_to_lpid[j].flag) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__,
|
|
Packit |
0848f5 |
MPI_ERR_ARG, "**rangedup", "**rangedup %d %d %d",
|
|
Packit |
0848f5 |
j, i, group_ptr->lrank_to_lpid[j].flag - 1);
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else
|
|
Packit |
0848f5 |
group_ptr->lrank_to_lpid[j].flag = 1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
for (j=first; j>=last; j+=stride) {
|
|
Packit |
0848f5 |
if (group_ptr->lrank_to_lpid[j].flag) {
|
|
Packit |
0848f5 |
mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__,
|
|
Packit |
0848f5 |
MPI_ERR_ARG, "**rangedup", "**rangedup %d %d %d",
|
|
Packit |
0848f5 |
j, i, group_ptr->lrank_to_lpid[j].flag - 1);
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else
|
|
Packit |
0848f5 |
/* Set to i + 1 so that we can remember where it was
|
|
Packit |
0848f5 |
first set */
|
|
Packit |
0848f5 |
group_ptr->lrank_to_lpid[j].flag = i + 1;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
if (mpi_errno) break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
/* Given a group and a comm, check that the group is a subset of the processes
|
|
Packit |
0848f5 |
defined by the comm.
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
We sort the lpids for the group and the comm. If the group has an
|
|
Packit |
0848f5 |
lpid that is not in the comm, then report an error.
|
|
Packit |
0848f5 |
*/
|
|
Packit |
0848f5 |
int MPIR_Group_check_subset( MPID_Group *group_ptr, MPID_Comm *comm_ptr )
|
|
Packit |
0848f5 |
{
|
|
Packit |
0848f5 |
int mpi_errno = MPI_SUCCESS;
|
|
Packit |
0848f5 |
int g1_idx, g2_idx, l1_pid, l2_pid, i;
|
|
Packit |
0848f5 |
MPID_Group_pmap_t *vmap=0;
|
|
Packit |
0848f5 |
int vsize = comm_ptr->comm_kind == MPID_INTERCOMM ? comm_ptr->local_size :
|
|
Packit |
0848f5 |
comm_ptr->remote_size;
|
|
Packit |
0848f5 |
MPIU_CHKLMEM_DECL(1);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPIU_Assert(group_ptr != NULL);
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPIU_CHKLMEM_MALLOC(vmap,MPID_Group_pmap_t*,
|
|
Packit |
0848f5 |
vsize*sizeof(MPID_Group_pmap_t),mpi_errno, "" );
|
|
Packit |
0848f5 |
/* Initialize the vmap */
|
|
Packit |
0848f5 |
for (i=0; i
|
|
Packit |
0848f5 |
MPID_Comm_get_lpid(comm_ptr, i, &vmap[i].lpid, FALSE);
|
|
Packit |
0848f5 |
vmap[i].next_lpid = 0;
|
|
Packit |
0848f5 |
vmap[i].flag = 0;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
MPIR_Group_setup_lpid_list( group_ptr );
|
|
Packit |
0848f5 |
g1_idx = group_ptr->idx_of_first_lpid;
|
|
Packit |
0848f5 |
g2_idx = mergesort_lpidarray( vmap, vsize );
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_FMT(COMM,VERBOSE,(MPIU_DBG_FDEST,
|
|
Packit |
0848f5 |
"initial indices: %d %d\n", g1_idx, g2_idx ));
|
|
Packit |
0848f5 |
while (g1_idx >= 0 && g2_idx >= 0) {
|
|
Packit |
0848f5 |
l1_pid = group_ptr->lrank_to_lpid[g1_idx].lpid;
|
|
Packit |
0848f5 |
l2_pid = vmap[g2_idx].lpid;
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_FMT(COMM,VERBOSE,(MPIU_DBG_FDEST,
|
|
Packit |
0848f5 |
"Lpids are %d, %d\n", l1_pid, l2_pid ));
|
|
Packit |
0848f5 |
if (l1_pid < l2_pid) {
|
|
Packit |
0848f5 |
/* If we have to advance g1, we didn't find a match, so
|
|
Packit |
0848f5 |
that's an error. */
|
|
Packit |
0848f5 |
break;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else if (l1_pid > l2_pid) {
|
|
Packit |
0848f5 |
g2_idx = vmap[g2_idx].next_lpid;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
else {
|
|
Packit |
0848f5 |
/* Equal */
|
|
Packit |
0848f5 |
g1_idx = group_ptr->lrank_to_lpid[g1_idx].next_lpid;
|
|
Packit |
0848f5 |
g2_idx = vmap[g2_idx].next_lpid;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
MPIU_DBG_MSG_FMT(COMM,VERBOSE,(MPIU_DBG_FDEST,
|
|
Packit |
0848f5 |
"g1 = %d, g2 = %d\n", g1_idx, g2_idx ));
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
if (g1_idx >= 0) {
|
|
Packit |
0848f5 |
MPIR_ERR_SET1(mpi_errno, MPI_ERR_GROUP,
|
|
Packit |
0848f5 |
"**groupnotincomm", "**groupnotincomm %d", g1_idx );
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
fn_fail:
|
|
Packit |
0848f5 |
MPIU_CHKLMEM_FREEALL();
|
|
Packit |
0848f5 |
return mpi_errno;
|
|
Packit |
0848f5 |
}
|
|
Packit |
0848f5 |
|
|
Packit |
0848f5 |
#endif /* HAVE_ERROR_CHECKING */
|