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