1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2005 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2008 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2009 Sun Microsystmes, Inc. All rights reserved.
14 * Copyright (c) 2011 Sandia National Laboratories. All rights reserved.
15 * Copyright (c) 2014-2015 Los Alamos National Security, LLC. All rights
16 * reserved.
17 * Copyright (c) 2015 Research Organization for Information Science
18 * and Technology (RIST). All rights reserved.
19 * $COPYRIGHT$
20 *
21 * Additional copyrights may follow
22 *
23 * $HEADER$
24 */
25 #include "ompi_config.h"
26 #include <stdio.h>
27 #include "ompi/mpi/c/bindings.h"
28 #include "ompi/runtime/params.h"
29 #include "ompi/communicator/communicator.h"
30 #include "ompi/errhandler/errhandler.h"
31 #include "ompi/win/win.h"
32 #include "ompi/mca/osc/osc.h"
33 #include "ompi/op/op.h"
34 #include "ompi/datatype/ompi_datatype.h"
35 #include "ompi/datatype/ompi_datatype_internal.h"
36 #include "ompi/memchecker.h"
37
38 #if OMPI_BUILD_MPI_PROFILING
39 #if OPAL_HAVE_WEAK_SYMBOLS
40 #pragma weak MPI_Raccumulate = PMPI_Raccumulate
41 #endif
42 #define MPI_Raccumulate PMPI_Raccumulate
43 #endif
44
45 static const char FUNC_NAME[] = "MPI_Raccumulate";
46
47 int MPI_Raccumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype,
48 int target_rank, MPI_Aint target_disp, int target_count,
49 MPI_Datatype target_datatype, MPI_Op op, MPI_Win win, MPI_Request *request)
50 {
51 int rc;
52 ompi_win_t *ompi_win = (ompi_win_t*) win;
53
54 MEMCHECKER(
55 memchecker_datatype(origin_datatype);
56 memchecker_datatype(target_datatype);
57 memchecker_call(&opal_memchecker_base_isdefined, origin_addr, origin_count, origin_datatype);
58 );
59
60 if (MPI_PARAM_CHECK) {
61 rc = OMPI_SUCCESS;
62
63 OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
64
65 if (ompi_win_invalid(win)) {
66 return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_WIN, FUNC_NAME);
67 } else if (origin_count < 0 || target_count < 0) {
68 rc = MPI_ERR_COUNT;
69 } else if (ompi_win_peer_invalid(win, target_rank) &&
70 (MPI_PROC_NULL != target_rank)) {
71 rc = MPI_ERR_RANK;
72 } else if (MPI_OP_NULL == op || MPI_NO_OP == op) {
73 rc = MPI_ERR_OP;
74 } else if (!ompi_op_is_intrinsic(op)) {
75 rc = MPI_ERR_OP;
76 } else if ( MPI_WIN_FLAVOR_DYNAMIC != win->w_flavor && target_disp < 0 ) {
77 rc = MPI_ERR_DISP;
78 } else {
79 OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, origin_datatype, origin_count);
80 if (OMPI_SUCCESS == rc) {
81 OMPI_CHECK_DATATYPE_FOR_ONE_SIDED(rc, target_datatype, target_count);
82 }
83 if (OMPI_SUCCESS == rc) {
84 /* While technically the standard probably requires that the
85 datatypes used with MPI_REPLACE conform to all the rules
86 for other reduction operators, we don't require such
87 behavior, as checking for it is expensive here and we don't
88 care in implementation.. */
89 if (op != &ompi_mpi_op_replace.op && op != &ompi_mpi_op_no_op.op) {
90 ompi_datatype_t *op_check_dt, *origin_check_dt;
91 char *msg;
92
93 /* RACCUMULATE, unlike REDUCE, can use with derived
94 datatypes with predefinied operations, with some
95 restrictions outlined in MPI-3:11.3.4. The derived
96 datatype must be composed entierly from one predefined
97 datatype (so you can do all the construction you want,
98 but at the bottom, you can only use one datatype, say,
99 MPI_INT). If the datatype at the target isn't
100 predefined, then make sure it's composed of only one
101 datatype, and check that datatype against
102 ompi_op_is_valid(). */
103 origin_check_dt = ompi_datatype_get_single_predefined_type_from_args(origin_datatype);
104 op_check_dt = ompi_datatype_get_single_predefined_type_from_args(target_datatype);
105
106 if( !((origin_check_dt == op_check_dt) & (NULL != op_check_dt)) ) {
107 OMPI_ERRHANDLER_RETURN(MPI_ERR_ARG, win, MPI_ERR_ARG, FUNC_NAME);
108 }
109
110 /* check to make sure primitive type is valid for
111 reduction. Should do this on the target, but
112 then can't get the errcode back for this
113 call */
114 if (!ompi_op_is_valid(op, op_check_dt, &msg, FUNC_NAME)) {
115 int ret = OMPI_ERRHANDLER_INVOKE(win, MPI_ERR_OP, msg);
116 free(msg);
117 return ret;
118 }
119 }
120 }
121 }
122 OMPI_ERRHANDLER_CHECK(rc, win, rc, FUNC_NAME);
123 }
124
125 if (MPI_PROC_NULL == target_rank) {
126 *request = &ompi_request_empty;
127 return MPI_SUCCESS;
128 }
129
130 OPAL_CR_ENTER_LIBRARY();
131
132 rc = ompi_win->w_osc_module->osc_raccumulate(origin_addr,
133 origin_count,
134 origin_datatype,
135 target_rank,
136 target_disp,
137 target_count,
138 target_datatype,
139 op, win, request);
140 OMPI_ERRHANDLER_RETURN(rc, win, rc, FUNC_NAME);
141 }