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-2017 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) 2007      Cisco Systems, Inc.  All rights reserved.
14  * Copyright (c) 2012-2017 Los Alamos National Security, LLC.  All rights
15  *                         reserved.
16  * Copyright (c) 2014-2015 Research Organization for Information Science
17  *                         and Technology (RIST). All rights reserved.
18  * Copyright (c) 2017      IBM Corporation.  All rights reserved.
19  * $COPYRIGHT$
20  *
21  * Additional copyrights may follow
22  *
23  * $HEADER$
24  */
25 
26 #include "ompi_config.h"
27 #include <stdio.h>
28 
29 #include "ompi/mpi/c/bindings.h"
30 #include "ompi/runtime/params.h"
31 #include "ompi/communicator/communicator.h"
32 #include "ompi/errhandler/errhandler.h"
33 #include "ompi/datatype/ompi_datatype.h"
34 #include "ompi/memchecker.h"
35 #include "ompi/mca/topo/topo.h"
36 #include "ompi/mca/topo/base/base.h"
37 
38 #if OMPI_BUILD_MPI_PROFILING
39 #if OPAL_HAVE_WEAK_SYMBOLS
40 #pragma weak MPI_Ineighbor_alltoallw = PMPI_Ineighbor_alltoallw
41 #endif
42 #define MPI_Ineighbor_alltoallw PMPI_Ineighbor_alltoallw
43 #endif
44 
45 static const char FUNC_NAME[] = "MPI_Ineighbor_alltoallw";
46 
47 
MPI_Ineighbor_alltoallw(const void * sendbuf,const int sendcounts[],const MPI_Aint sdispls[],const MPI_Datatype sendtypes[],void * recvbuf,const int recvcounts[],const MPI_Aint rdispls[],const MPI_Datatype recvtypes[],MPI_Comm comm,MPI_Request * request)48 int MPI_Ineighbor_alltoallw(const void *sendbuf, const int sendcounts[], const MPI_Aint sdispls[],
49                             const MPI_Datatype sendtypes[], void *recvbuf, const int recvcounts[],
50                             const MPI_Aint rdispls[], const MPI_Datatype recvtypes[], MPI_Comm comm,
51                             MPI_Request *request)
52 {
53     int i, err;
54     int indegree, outdegree;
55 
56     MEMCHECKER(
57         ptrdiff_t recv_ext;
58         ptrdiff_t send_ext;
59 
60         memchecker_comm(comm);
61 
62         err = mca_topo_base_neighbor_count (comm, &indegree, &outdegree);
63         if (MPI_SUCCESS == err) {
64             if (MPI_IN_PLACE != sendbuf) {
65                 for ( i = 0; i < outdegree; i++ ) {
66                     memchecker_datatype(sendtypes[i]);
67 
68                     ompi_datatype_type_extent(sendtypes[i], &send_ext);
69 
70                     memchecker_call(&opal_memchecker_base_isdefined,
71                                     (char *)(sendbuf)+sdispls[i]*send_ext,
72                                     sendcounts[i], sendtypes[i]);
73                 }
74             }
75             for ( i = 0; i < indegree; i++ ) {
76                 memchecker_datatype(recvtypes[i]);
77 
78                 ompi_datatype_type_extent(recvtypes[i], &recv_ext);
79 
80                 memchecker_call(&opal_memchecker_base_isaddressable,
81                                 (char *)(recvbuf)+sdispls[i]*recv_ext,
82                                 recvcounts[i], recvtypes[i]);
83             }
84         }
85     );
86 
87     if (MPI_PARAM_CHECK) {
88 
89         /* Unrooted operation -- same checks for all ranks */
90 
91         err = MPI_SUCCESS;
92         OMPI_ERR_INIT_FINALIZE(FUNC_NAME);
93         if (ompi_comm_invalid(comm) || OMPI_COMM_IS_INTER(comm)) {
94             return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_COMM,
95                                           FUNC_NAME);
96         } else if (! OMPI_COMM_IS_TOPO(comm)) {
97             return OMPI_ERRHANDLER_INVOKE(MPI_COMM_WORLD, MPI_ERR_TOPOLOGY,
98                                           FUNC_NAME);
99         }
100 
101         if ((NULL == sendcounts) || (NULL == sdispls) || (NULL == sendtypes) ||
102             (NULL == recvcounts) || (NULL == rdispls) || (NULL == recvtypes) ||
103             MPI_IN_PLACE == sendbuf || MPI_IN_PLACE == recvbuf) {
104             return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
105         }
106 
107         err = mca_topo_base_neighbor_count (comm, &indegree, &outdegree);
108         OMPI_ERRHANDLER_CHECK(err, comm, err, FUNC_NAME);
109         for (i = 0; i < outdegree; ++i) {
110             OMPI_CHECK_DATATYPE_FOR_SEND(err, sendtypes[i], sendcounts[i]);
111             OMPI_ERRHANDLER_CHECK(err, comm, err, FUNC_NAME);
112         }
113         for (i = 0; i < indegree; ++i) {
114             OMPI_CHECK_DATATYPE_FOR_RECV(err, recvtypes[i], recvcounts[i]);
115             OMPI_ERRHANDLER_CHECK(err, comm, err, FUNC_NAME);
116         }
117 
118         if( OMPI_COMM_IS_CART(comm) ) {
119             const mca_topo_base_comm_cart_2_2_0_t *cart = comm->c_topo->mtc.cart;
120             if( 0 > cart->ndims ) {
121                 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
122             }
123         }
124         else if( OMPI_COMM_IS_GRAPH(comm) ) {
125             int degree;
126             mca_topo_base_graph_neighbors_count(comm, ompi_comm_rank(comm), &degree);
127             if( 0 > degree ) {
128                 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
129             }
130         }
131         else if( OMPI_COMM_IS_DIST_GRAPH(comm) ) {
132             const mca_topo_base_comm_dist_graph_2_2_0_t *dist_graph = comm->c_topo->mtc.dist_graph;
133             indegree  = dist_graph->indegree;
134             outdegree = dist_graph->outdegree;
135             if( indegree <  0 || outdegree <  0 ) {
136                 return OMPI_ERRHANDLER_INVOKE(comm, MPI_ERR_ARG, FUNC_NAME);
137             }
138         }
139     }
140 
141     OPAL_CR_ENTER_LIBRARY();
142 
143     /* Invoke the coll component to perform the back-end operation */
144     err = comm->c_coll->coll_ineighbor_alltoallw(sendbuf, sendcounts, sdispls, sendtypes,
145                                                 recvbuf, recvcounts, rdispls, recvtypes, comm, request,
146                                                 comm->c_coll->coll_ineighbor_alltoallw_module);
147     OMPI_ERRHANDLER_RETURN(err, comm, err, FUNC_NAME);
148 }
149 
150