Blame src/mpi/coll/scan/scan.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
Packit Service c5cf8c
/*
Packit Service c5cf8c
=== BEGIN_MPI_T_CVAR_INFO_BLOCK ===
Packit Service c5cf8c
Packit Service c5cf8c
cvars:
Packit Service c5cf8c
    - name        : MPIR_CVAR_SCAN_INTRA_ALGORITHM
Packit Service c5cf8c
      category    : COLLECTIVE
Packit Service c5cf8c
      type        : string
Packit Service c5cf8c
      default     : auto
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : |-
Packit Service c5cf8c
        Variable to select allgather algorithm
Packit Service c5cf8c
        auto               - Internal algorithm selection
Packit Service c5cf8c
        nb                 - Force nonblocking algorithm
Packit Service c5cf8c
        recursive_doubling - Force recursive doubling algorithm
Packit Service c5cf8c
Packit Service c5cf8c
    - name        : MPIR_CVAR_SCAN_DEVICE_COLLECTIVE
Packit Service c5cf8c
      category    : COLLECTIVE
Packit Service c5cf8c
      type        : boolean
Packit Service c5cf8c
      default     : true
Packit Service c5cf8c
      class       : device
Packit Service c5cf8c
      verbosity   : MPI_T_VERBOSITY_USER_BASIC
Packit Service c5cf8c
      scope       : MPI_T_SCOPE_ALL_EQ
Packit Service c5cf8c
      description : >-
Packit Service c5cf8c
        If set to true, MPI_Scan will allow the device to override the
Packit Service c5cf8c
        MPIR-level collective algorithms. The device still has the
Packit Service c5cf8c
        option to call the MPIR-level algorithms manually.
Packit Service c5cf8c
        If set to false, the device-level scan function will not be
Packit Service c5cf8c
        called.
Packit Service c5cf8c
Packit Service c5cf8c
=== END_MPI_T_CVAR_INFO_BLOCK ===
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
/* -- Begin Profiling Symbol Block for routine MPI_Scan */
Packit Service c5cf8c
#if defined(HAVE_PRAGMA_WEAK)
Packit Service c5cf8c
#pragma weak MPI_Scan = PMPI_Scan
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
Packit Service c5cf8c
#pragma _HP_SECONDARY_DEF PMPI_Scan  MPI_Scan
Packit Service c5cf8c
#elif defined(HAVE_PRAGMA_CRI_DUP)
Packit Service c5cf8c
#pragma _CRI duplicate MPI_Scan as PMPI_Scan
Packit Service c5cf8c
#elif defined(HAVE_WEAK_ATTRIBUTE)
Packit Service c5cf8c
int MPI_Scan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op,
Packit Service c5cf8c
             MPI_Comm comm)
Packit Service c5cf8c
    __attribute__ ((weak, alias("PMPI_Scan")));
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_Scan
Packit Service c5cf8c
#define MPI_Scan PMPI_Scan
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Scan_intra_auto
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Scan_intra_auto(const void *sendbuf, void *recvbuf, int count,
Packit Service c5cf8c
                         MPI_Datatype datatype, MPI_Op op, MPIR_Comm * comm_ptr,
Packit Service c5cf8c
                         MPIR_Errflag_t * errflag)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    /* In order to use the SMP-aware algorithm, the "op" can be
Packit Service c5cf8c
     * either commutative or non-commutative, but we require a
Packit Service c5cf8c
     * communicator in which all the nodes contain processes with
Packit Service c5cf8c
     * consecutive ranks. */
Packit Service c5cf8c
Packit Service c5cf8c
    if (MPII_Comm_is_node_consecutive(comm_ptr)) {
Packit Service c5cf8c
        mpi_errno = MPIR_Scan_intra_smp(sendbuf, recvbuf, count, datatype, op, comm_ptr, errflag);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        mpi_errno =
Packit Service c5cf8c
            MPIR_Scan_intra_recursive_doubling(sendbuf, recvbuf, count, datatype, op, comm_ptr,
Packit Service c5cf8c
                                               errflag);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    if (*errflag != MPIR_ERR_NONE)
Packit Service c5cf8c
        MPIR_ERR_SET(mpi_errno, *errflag, "**coll_fail");
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Scan_impl
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Scan_impl(const void *sendbuf, void *recvbuf, int count,
Packit Service c5cf8c
                   MPI_Datatype datatype, MPI_Op op, MPIR_Comm * comm_ptr, MPIR_Errflag_t * errflag)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    switch (MPIR_Scan_intra_algo_choice) {
Packit Service c5cf8c
        case MPIR_SCAN_INTRA_ALGO_RECURSIVE_DOUBLING:
Packit Service c5cf8c
            mpi_errno =
Packit Service c5cf8c
                MPIR_Scan_intra_recursive_doubling(sendbuf, recvbuf, count, datatype, op, comm_ptr,
Packit Service c5cf8c
                                                   errflag);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPIR_SCAN_INTRA_ALGO_NB:
Packit Service c5cf8c
            mpi_errno =
Packit Service c5cf8c
                MPIR_Scan_allcomm_nb(sendbuf, recvbuf, count, datatype, op, comm_ptr, errflag);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case MPIR_SCAN_INTRA_ALGO_AUTO:
Packit Service c5cf8c
            MPL_FALLTHROUGH;
Packit Service c5cf8c
        default:
Packit Service c5cf8c
            mpi_errno =
Packit Service c5cf8c
                MPIR_Scan_intra_auto(sendbuf, recvbuf, count, datatype, op, comm_ptr, errflag);
Packit Service c5cf8c
            break;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        MPIR_ERR_POP(mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
  fn_exit:
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
Packit Service c5cf8c
  fn_fail:
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPIR_Scan
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
int MPIR_Scan(const void *sendbuf, void *recvbuf, int count,
Packit Service c5cf8c
              MPI_Datatype datatype, MPI_Op op, MPIR_Comm * comm_ptr, MPIR_Errflag_t * errflag)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
Packit Service c5cf8c
    if (MPIR_CVAR_SCAN_DEVICE_COLLECTIVE && MPIR_CVAR_DEVICE_COLLECTIVES) {
Packit Service c5cf8c
        mpi_errno = MPID_Scan(sendbuf, recvbuf, count, datatype, op, comm_ptr, errflag);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        mpi_errno = MPIR_Scan_impl(sendbuf, recvbuf, count, datatype, op, comm_ptr, errflag);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    return mpi_errno;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
#undef FUNCNAME
Packit Service c5cf8c
#define FUNCNAME MPI_Scan
Packit Service c5cf8c
#undef FCNAME
Packit Service c5cf8c
#define FCNAME MPL_QUOTE(FUNCNAME)
Packit Service c5cf8c
/*@
Packit Service c5cf8c
Packit Service c5cf8c
MPI_Scan - Computes the scan (partial reductions) of data on a collection of
Packit Service c5cf8c
           processes
Packit Service c5cf8c
Packit Service c5cf8c
Input Parameters:
Packit Service c5cf8c
+ sendbuf - starting address of send buffer (choice)
Packit Service c5cf8c
. count - number of elements in input buffer (integer)
Packit Service c5cf8c
. datatype - data type of elements of input buffer (handle)
Packit Service c5cf8c
. op - operation (handle)
Packit Service c5cf8c
- comm - communicator (handle)
Packit Service c5cf8c
Packit Service c5cf8c
Output Parameters:
Packit Service c5cf8c
. recvbuf - starting address of receive buffer (choice)
Packit Service c5cf8c
Packit Service c5cf8c
.N ThreadSafe
Packit Service c5cf8c
Packit Service c5cf8c
.N Fortran
Packit Service c5cf8c
Packit Service c5cf8c
.N collops
Packit Service c5cf8c
Packit Service c5cf8c
.N Errors
Packit Service c5cf8c
.N MPI_SUCCESS
Packit Service c5cf8c
.N MPI_ERR_COMM
Packit Service c5cf8c
.N MPI_ERR_COUNT
Packit Service c5cf8c
.N MPI_ERR_TYPE
Packit Service c5cf8c
.N MPI_ERR_BUFFER
Packit Service c5cf8c
.N MPI_ERR_BUFFER_ALIAS
Packit Service c5cf8c
@*/
Packit Service c5cf8c
int MPI_Scan(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
Packit Service c5cf8c
             MPI_Op op, MPI_Comm comm)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int mpi_errno = MPI_SUCCESS;
Packit Service c5cf8c
    MPIR_Comm *comm_ptr = NULL;
Packit Service c5cf8c
    MPIR_Errflag_t errflag = MPIR_ERR_NONE;
Packit Service c5cf8c
    MPIR_FUNC_TERSE_STATE_DECL(MPID_STATE_MPI_SCAN);
Packit Service c5cf8c
Packit Service c5cf8c
    MPIR_ERRTEST_INITIALIZED_ORDIE();
Packit Service c5cf8c
Packit Service c5cf8c
    MPID_THREAD_CS_ENTER(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX);
Packit Service c5cf8c
    MPIR_FUNC_TERSE_COLL_ENTER(MPID_STATE_MPI_SCAN);
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_COMM(comm, 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
    /* Convert MPI object handles to object pointers */
Packit Service c5cf8c
    MPIR_Comm_get_ptr(comm, comm_ptr);
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
            MPIR_Datatype *datatype_ptr = NULL;
Packit Service c5cf8c
            MPIR_Op *op_ptr = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
            MPIR_Comm_valid_ptr(comm_ptr, mpi_errno, FALSE);
Packit Service c5cf8c
            if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                goto fn_fail;
Packit Service c5cf8c
Packit Service c5cf8c
            MPIR_ERRTEST_COMM_INTRA(comm_ptr, mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_COUNT(count, mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_DATATYPE(datatype, "datatype", mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_OP(op, mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
            if (HANDLE_GET_KIND(datatype) != HANDLE_KIND_BUILTIN) {
Packit Service c5cf8c
                MPIR_Datatype_get_ptr(datatype, datatype_ptr);
Packit Service c5cf8c
                MPIR_Datatype_valid_ptr(datatype_ptr, mpi_errno);
Packit Service c5cf8c
                if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                    goto fn_fail;
Packit Service c5cf8c
                MPIR_Datatype_committed_ptr(datatype_ptr, mpi_errno);
Packit Service c5cf8c
                if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                    goto fn_fail;
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            /* in_place option allowed. no error check */
Packit Service c5cf8c
            MPIR_ERRTEST_USERBUFFER(sendbuf, count, datatype, mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_RECVBUF_INPLACE(recvbuf, count, mpi_errno);
Packit Service c5cf8c
            MPIR_ERRTEST_USERBUFFER(recvbuf, count, datatype, mpi_errno);
Packit Service c5cf8c
Packit Service c5cf8c
            if (HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN) {
Packit Service c5cf8c
                MPIR_Op_get_ptr(op, op_ptr);
Packit Service c5cf8c
                MPIR_Op_valid_ptr(op_ptr, mpi_errno);
Packit Service c5cf8c
            }
Packit Service c5cf8c
            if (HANDLE_GET_KIND(op) == HANDLE_KIND_BUILTIN) {
Packit Service c5cf8c
                mpi_errno = (*MPIR_OP_HDL_TO_DTYPE_FN(op)) (datatype);
Packit Service c5cf8c
            }
Packit Service c5cf8c
            if (mpi_errno != MPI_SUCCESS)
Packit Service c5cf8c
                goto fn_fail;
Packit Service c5cf8c
Packit Service c5cf8c
            if (sendbuf != MPI_IN_PLACE && count != 0)
Packit Service c5cf8c
                MPIR_ERRTEST_ALIAS_COLL(sendbuf, recvbuf, 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_Scan(sendbuf, recvbuf, count, datatype, op, comm_ptr, &errflag);
Packit Service c5cf8c
    if (mpi_errno)
Packit Service c5cf8c
        goto fn_fail;
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_COLL_EXIT(MPID_STATE_MPI_SCAN);
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
  fn_fail:
Packit Service c5cf8c
    /* --BEGIN ERROR HANDLING-- */
Packit Service c5cf8c
#ifdef HAVE_ERROR_CHECKING
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_scan", "**mpi_scan %p %p %d %D %O %C", sendbuf, recvbuf,
Packit Service c5cf8c
                                 count, datatype, op, comm);
Packit Service c5cf8c
    }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    mpi_errno = MPIR_Err_return_comm(comm_ptr, FCNAME, mpi_errno);
Packit Service c5cf8c
    goto fn_exit;
Packit Service c5cf8c
    /* --END ERROR HANDLING-- */
Packit Service c5cf8c
}