Blame src/mpi/group/group_translate_ranks.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
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
/* -- Begin Profiling Symbol Block for routine MPI_Group_translate_ranks */
Packit Service c5cf8c
#if defined(HAVE_PRAGMA_WEAK)
Packit Service c5cf8c
#pragma weak MPI_Group_translate_ranks = PMPI_Group_translate_ranks
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
Packit Service c5cf8c
#pragma _HP_SECONDARY_DEF PMPI_Group_translate_ranks  MPI_Group_translate_ranks
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_CRI_DUP)
Packit Service c5cf8c
#pragma _CRI duplicate MPI_Group_translate_ranks as PMPI_Group_translate_ranks
Packit Service c5cf8c
#elif defined(HAVE_WEAK_ATTRIBUTE)
Packit Service c5cf8c
int MPI_Group_translate_ranks(MPI_Group group1, int n, const int ranks1[], MPI_Group group2,
Packit Service c5cf8c
                              int ranks2[])
Packit Service c5cf8c
    __attribute__ ((weak, alias("PMPI_Group_translate_ranks")));
Packit Service c5cf8c
#endif
Packit Service c5cf8c
/* -- End Profiling Symbol Block */
Packit Service c5cf8c
Packit Service c5cf8c
/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
Packit Service c5cf8c
   the MPI routines */
Packit Service c5cf8c
#ifndef MPICH_MPI_FROM_PMPI
Packit Service c5cf8c
#undef MPI_Group_translate_ranks
Packit Service c5cf8c
#define MPI_Group_translate_ranks PMPI_Group_translate_ranks
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Group_translate_ranks_impl
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Group_translate_ranks_impl(MPIR_Group * gp1, int n, const int ranks1[],
Packit Service c5cf8c
                                    MPIR_Group * gp2, int ranks2[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    int i, g2_idx, l1_pid, l2_pid;
Packit Service c5cf8c
Packit Service c5cf8c
    MPL_DBG_MSG_S(MPIR_DBG_OTHER, VERBOSE, "gp2->is_local_dense_monotonic=%s",
Packit Service c5cf8c
                  (gp2->is_local_dense_monotonic ? "TRUE" : "FALSE"));
Packit Service c5cf8c
Packit Service c5cf8c
    /* Initialize the output ranks */
Packit Service c5cf8c
    for (i = 0; i < n; i++)
Packit Service c5cf8c
        ranks2[i] = MPI_UNDEFINED;
Packit Service c5cf8c
Packit Service c5cf8c
    if (gp2->size > 0 && gp2->is_local_dense_monotonic) {
Packit Service c5cf8c
        /* g2 probably == group_of(MPI_COMM_WORLD); use fast, constant-time lookup */
Packit Service c5cf8c
        int lpid_offset = gp2->lrank_to_lpid[0].lpid;
Packit Service c5cf8c
Packit Service c5cf8c
        MPIR_Assert(lpid_offset >= 0);
Packit Service c5cf8c
        for (i = 0; i < n; ++i) {
Packit Service c5cf8c
            int g1_lpid;
Packit Service c5cf8c
Packit Service c5cf8c
            if (ranks1[i] == MPI_PROC_NULL) {
Packit Service c5cf8c
                ranks2[i] = MPI_PROC_NULL;
Packit Service c5cf8c
                continue;
Packit Service c5cf8c
            }
Packit Service c5cf8c
            /* "adjusted" lpid from g1 */
Packit Service c5cf8c
            g1_lpid = gp1->lrank_to_lpid[ranks1[i]].lpid - lpid_offset;
Packit Service c5cf8c
            if ((g1_lpid >= 0) && (g1_lpid < gp2->size)) {
Packit Service c5cf8c
                ranks2[i] = g1_lpid;
Packit Service c5cf8c
            }
Packit Service c5cf8c
            /* else leave UNDEFINED */
Packit Service c5cf8c
        }
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        /* general, slow path; lookup time is dependent on the user-provided rank values! */
Packit Service c5cf8c
        g2_idx = gp2->idx_of_first_lpid;
Packit Service c5cf8c
        if (g2_idx < 0) {
Packit Service c5cf8c
            MPII_Group_setup_lpid_list(gp2);
Packit Service c5cf8c
            g2_idx = gp2->idx_of_first_lpid;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        if (g2_idx >= 0) {
Packit Service c5cf8c
            /* g2_idx can be < 0 if the g2 group is empty */
Packit Service c5cf8c
            l2_pid = gp2->lrank_to_lpid[g2_idx].lpid;
Packit Service c5cf8c
            for (i = 0; i < n; i++) {
Packit Service c5cf8c
                if (ranks1[i] == MPI_PROC_NULL) {
Packit Service c5cf8c
                    ranks2[i] = MPI_PROC_NULL;
Packit Service c5cf8c
                    continue;
Packit Service c5cf8c
                }
Packit Service c5cf8c
                l1_pid = gp1->lrank_to_lpid[ranks1[i]].lpid;
Packit Service c5cf8c
                /* Search for this l1_pid in group2.  Use the following
Packit Service c5cf8c
                 * optimization: start from the last position in the lpid list
Packit Service c5cf8c
                 * if possible.  A more sophisticated version could use a
Packit Service c5cf8c
                 * tree based or even hashed search to speed the translation. */
Packit Service c5cf8c
                if (l1_pid < l2_pid || g2_idx < 0) {
Packit Service c5cf8c
                    /* Start over from the beginning */
Packit Service c5cf8c
                    g2_idx = gp2->idx_of_first_lpid;
Packit Service c5cf8c
                    l2_pid = gp2->lrank_to_lpid[g2_idx].lpid;
Packit Service c5cf8c
                }
Packit Service c5cf8c
                while (g2_idx >= 0 && l1_pid > l2_pid) {
Packit Service c5cf8c
                    g2_idx = gp2->lrank_to_lpid[g2_idx].next_lpid;
Packit Service c5cf8c
                    if (g2_idx >= 0)
Packit Service c5cf8c
                        l2_pid = gp2->lrank_to_lpid[g2_idx].lpid;
Packit Service c5cf8c
                    else
Packit Service c5cf8c
                        l2_pid = -1;
Packit Service c5cf8c
                }
Packit Service c5cf8c
                if (l1_pid == l2_pid)
Packit Service c5cf8c
                    ranks2[i] = g2_idx;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPI_Group_translate_ranks
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
/*@
Packit Service c5cf8c
 MPI_Group_translate_ranks - Translates the ranks of processes in one group to
Packit Service c5cf8c
                             those in another group
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
+ group1 - group1 (handle)
Packit Service c5cf8c
. n - number of ranks in  'ranks1' and 'ranks2'  arrays (integer)
Packit Service c5cf8c
. ranks1 - array of zero or more valid ranks in 'group1'
Packit Service c5cf8c
- group2 - group2 (handle)
Packit Service c5cf8c
Packit Service c5cf8c
Output Parameters:
Packit Service c5cf8c
. ranks2 - array of corresponding ranks in group2,  'MPI_UNDEFINED'  when no
Packit Service c5cf8c
  correspondence exists.
Packit Service c5cf8c
Packit Service c5cf8c
  As a special case (see the MPI-2 errata), if the input rank is
Packit Service c5cf8c
  'MPI_PROC_NULL', 'MPI_PROC_NULL' is given as the output rank.
Packit Service c5cf8c
Packit Service c5cf8c
.N ThreadSafe
Packit Service c5cf8c
Packit Service c5cf8c
.N Fortran
Packit Service c5cf8c
Packit Service c5cf8c
.N Errors
Packit Service c5cf8c
.N MPI_SUCCESS
Packit Service c5cf8c
@*/
Packit Service c5cf8c
int MPI_Group_translate_ranks(MPI_Group group1, int n, const int ranks1[],
Packit Service c5cf8c
                              MPI_Group group2, int ranks2[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    MPIR_Group *group_ptr1 = NULL;
Packit Service c5cf8c
    MPIR_Group *group_ptr2 = NULL;
Packit Service c5cf8c
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_GROUP_TRANSLATE_RANKS);
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_ERRTEST_INITIALIZED_ORDIE();
Packit Service c5cf8c
Packit Service c5cf8c
    /* The routines that setup the group data structures must be executed
Packit Service c5cf8c
     * within a mutex.  As most of the group routines are not performance
Packit Service c5cf8c
     * critical, we simple run these routines within the SINGLE_CS */
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPIR_FUNC_TERSE_ENTER(MPID_STATE_MPI_GROUP_TRANSLATE_RANKS);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Validate parameters, especially handles needing to be converted */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        MPID_BEGIN_ERROR_CHECKS;
Packit Service c5cf8c
        {
Packit Service c5cf8c
            MPIR_ERRTEST_GROUP(group1, mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_GROUP(group2, mpi_errno);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPID_END_ERROR_CHECKS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
    /* Convert MPI object handles to object pointers */
Packit Service c5cf8c
    MPIR_Group_get_ptr(group1, group_ptr1);
Packit Service c5cf8c
    MPIR_Group_get_ptr(group2, group_ptr2);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Validate parameters and objects (post conversion) */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
Packit Service c5cf8c
    {
Packit Service c5cf8c
        MPID_BEGIN_ERROR_CHECKS;
Packit Service c5cf8c
        {
Packit Service c5cf8c
            /* Validate group_ptr */
Packit Service c5cf8c
            MPIR_Group_valid_ptr(group_ptr1, mpi_errno);
Packit Service c5cf8c
            MPIR_Group_valid_ptr(group_ptr2, mpi_errno);
Packit Service c5cf8c
            /* If either group_ptr is not valid, it will be reset to null */
Packit Service c5cf8c
Packit Service c5cf8c
            MPIR_ERRTEST_ARGNEG(n, "n", mpi_errno);
Packit Service c5cf8c
            if (group_ptr1) {
Packit Service c5cf8c
                /* Check that the rank entries are valid */
Packit Service c5cf8c
                int size1 = group_ptr1->size;
Packit Service c5cf8c
                int i;
Packit Service c5cf8c
                for (i = 0; i < n; i++) {
Packit Service c5cf8c
                    if ((ranks1[i] < 0 && ranks1[i] != MPI_PROC_NULL) || ranks1[i] >= size1) {
Packit Service c5cf8c
                        mpi_errno = MPIR_Err_create_code(MPI_SUCCESS,
Packit Service c5cf8c
                                                         MPIR_ERR_RECOVERABLE, FCNAME, __LINE__,
Packit Service c5cf8c
                                                         MPI_ERR_RANK,
Packit Service c5cf8c
                                                         "**rank", "**rank %d %d",
Packit Service c5cf8c
                                                         ranks1[i], size1);
Packit Service c5cf8c
                        goto fn_fail;
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
            MPIR_ERRTEST_ARGNULL(ranks2, "ranks2", mpi_errno);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPID_END_ERROR_CHECKS;
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif /* HAVE_ERROR_CHECKING */
Packit Service c5cf8c
Packit Service c5cf8c
    /* ... body of routine ...  */
Packit Service c5cf8c
Packit Service c5cf8c
    mpi_errno = MPIR_Group_translate_ranks_impl(group_ptr1, n, ranks1, group_ptr2, ranks2);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
    /* ... end of body of routine ... */
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    MPIR_FUNC_TERSE_EXIT(MPID_STATE_MPI_GROUP_TRANSLATE_RANKS);
Packit Service c5cf8c
    MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
Packit Service c5cf8c
    /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
Packit Service c5cf8c
                                 "**mpi_group_translate_ranks",
Packit Service c5cf8c
                                 "**mpi_group_translate_ranks %G %d %p %G %p", group1, n, ranks1,
Packit Service c5cf8c
                                 group2, ranks2);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    mpi_errno = MPIR_Err_return_comm(NULL, FCNAME, mpi_errno);
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
    /* --END ERROR HANDLING-- */
Packit Service c5cf8c
}