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-2018 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) 2010 University of Houston. All rights reserved.
14 * Copyright (c) 2012 Cisco Systems, Inc. All rights reserved.
15 * Copyright (c) 2012-2016 Los Alamos National Security, LLC. All rights
16 * reserved.
17 * Copyright (c) 2015-2017 Research Organization for Information Science
18 * and Technology (RIST). All rights reserved.
19 * Copyright (c) 2017 IBM Corporation. All rights reserved.
20 * $COPYRIGHT$
21 *
22 * Additional copyrights may follow
23 *
24 * $HEADER$
25 */
26
27 #include "ompi_config.h"
28 #include <stdio.h>
29
30 #include "ompi/mpi/c/bindings.h"
31 #include "ompi/runtime/params.h"
32 #include "ompi/communicator/communicator.h"
33 #include "ompi/errhandler/errhandler.h"
34 #include "ompi/datatype/ompi_datatype.h"
35 #include "ompi/mca/topo/base/base.h"
36 #include "ompi/memchecker.h"
37 #include "ompi/mca/topo/topo.h"
38 #include "ompi/mca/topo/base/base.h"
39 #include "ompi/runtime/ompi_spc.h"
40
41 #if OMPI_BUILD_MPI_PROFILING
42 #if OPAL_HAVE_WEAK_SYMBOLS
43 #pragma weak MPI_Neighbor_allgatherv = PMPI_Neighbor_allgatherv
44 #endif
45 #define MPI_Neighbor_allgatherv PMPI_Neighbor_allgatherv
46 #endif
47
48 static const char FUNC_NAME[] = "MPI_Neighbor_allgatherv";
49
50
MPI_Neighbor_allgatherv(const void * sendbuf,int sendcount,MPI_Datatype sendtype,void * recvbuf,const int recvcounts[],const int displs[],MPI_Datatype recvtype,MPI_Comm comm)51 int MPI_Neighbor_allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype,
52 void *recvbuf, const int recvcounts[], const int displs[],
53 MPI_Datatype recvtype, MPI_Comm comm)
54 {
55 int in_size, out_size, err;
56
57 SPC_RECORD(OMPI_SPC_NEIGHBOR_ALLGATHERV, 1);
58
59 MEMCHECKER(
60 int rank;
61 ptrdiff_t ext;
62
63 rank = ompi_comm_rank(comm);
64 mca_topo_base_neighbor_count (comm, &in_size, &out_size);
65 ompi_datatype_type_extent(recvtype, &ext);
66
67 memchecker_datatype(recvtype);
68 memchecker_comm (comm);
69 /* check whether the receive buffer is addressable. */
70 for (int i = 0; i < in_size; ++i) {
71 memchecker_call(&opal_memchecker_base_isaddressable,
72 (char *)(recvbuf)+displs[i]*ext,
73 recvcounts[i], recvtype);
74 }
75
76 /* check whether the actual send buffer is defined. */
77 if (MPI_IN_PLACE != sendbuf) {
78 memchecker_datatype(sendtype);
79 memchecker_call(&opal_memchecker_base_isdefined, sendbuf, sendcount, sendtype);
80 }
81 );
82
83 if (MPI_PARAM_CHECK) {
84
85 /* Unrooted operation -- same checks for all ranks on both
86 intracommunicators and intercommunicators */
87
88 err = MPI_SUCCESS;
89 OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
90 if (ompi_comm_invalid(comm) || OMPI_COMM_IS_INTER(comm)) {
91 return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM,
92 FUNC_NAME);
93 } else if (! OMPI_COMM_IS_TOPO(comm)) {
94 return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_TOPOLOGY,
95 FUNC_NAME);
96 } else if (MPI_IN_PLACE == sendbuf || MPI_IN_PLACE == recvbuf) {
97 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
98 } else if (MPI_DATATYPE_NULL == recvtype) {
99 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_TYPE, FUNC_NAME);
100 }
101
102 OMPI_CHECK_DATATYPE_FOR_SEND(err, sendtype, sendcount);
103 OMPI_ERRHANDLER_CHECK(err, comm, err, FUNC_NAME);
104
105 /* We always define the remote group to be the same as the local
106 group in the case of an intracommunicator, so it's safe to
107 get the size of the remote group here for both intra- and
108 intercommunicators */
109
110 mca_topo_base_neighbor_count (comm, &in_size, &out_size);
111 for (int i = 0; i < in_size; ++i) {
112 if (recvcounts[i] < 0) {
113 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_COUNT, FUNC_NAME);
114 }
115 }
116
117 if (NULL == displs) {
118 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_BUFFER, FUNC_NAME);
119 }
120
121 if( OMPI_COMM_IS_CART(comm) ) {
122 const mca_topo_base_comm_cart_2_2_0_t *cart = comm->c_topo->mtc.cart;
123 if( 0 > cart->ndims ) {
124 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
125 }
126 }
127 else if( OMPI_COMM_IS_GRAPH(comm) ) {
128 int degree;
129 mca_topo_base_graph_neighbors_count(comm, ompi_comm_rank(comm), °ree);
130 if( 0 > degree ) {
131 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
132 }
133 }
134 else if( OMPI_COMM_IS_DIST_GRAPH(comm) ) {
135 const mca_topo_base_comm_dist_graph_2_2_0_t *dist_graph = comm->c_topo->mtc.dist_graph;
136 int indegree = dist_graph->indegree;
137 int outdegree = dist_graph->outdegree;
138 if( indegree < 0 || outdegree < 0 ) {
139 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
140 }
141 }
142 }
143
144 OPAL_CR_ENTER_LIBRARY();
145
146 /* Invoke the coll component to perform the back-end operation */
147 err = comm->c_coll->coll_neighbor_allgatherv(sendbuf, sendcount, sendtype,
148 recvbuf, recvcounts, displs,
149 recvtype, comm, comm->c_coll->coll_neighbor_allgatherv_module);
150 OMPI_ERRHANDLER_RETURN(err, comm, err, FUNC_NAME);
151 }
152