1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3 * (C) 2012 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
5 */
6
7 #include "mpiimpl.h"
8 #include "topo.h"
9
10 /* -- Begin Profiling Symbol Block for routine MPIX_Ineighbor_alltoallw */
11 #if defined(HAVE_PRAGMA_WEAK)
12 #pragma weak MPIX_Ineighbor_alltoallw = PMPIX_Ineighbor_alltoallw
13 #elif defined(HAVE_PRAGMA_HP_SEC_DEF)
14 #pragma _HP_SECONDARY_DEF PMPIX_Ineighbor_alltoallw MPIX_Ineighbor_alltoallw
15 #elif defined(HAVE_PRAGMA_CRI_DUP)
16 #pragma _CRI duplicate MPIX_Ineighbor_alltoallw as PMPIX_Ineighbor_alltoallw
17 #endif
18 /* -- End Profiling Symbol Block */
19
20 /* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
21 the MPI routines */
22 #ifndef MPICH_MPI_FROM_PMPI
23 #undef MPIX_Ineighbor_alltoallw
24 #define MPIX_Ineighbor_alltoallw PMPIX_Ineighbor_alltoallw
25
26 /* any non-MPI functions go here, especially non-static ones */
27
28 #undef FUNCNAME
29 #define FUNCNAME MPIR_Ineighbor_alltoallw_default
30 #undef FCNAME
31 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIR_Ineighbor_alltoallw_default(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[],MPID_Comm * comm_ptr,MPID_Sched_t s)32 int MPIR_Ineighbor_alltoallw_default(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[], MPID_Comm *comm_ptr, MPID_Sched_t s)
33 {
34 int mpi_errno = MPI_SUCCESS;
35 int indegree, outdegree, weighted;
36 int k,l;
37 int *srcs, *dsts;
38 MPIU_CHKLMEM_DECL(2);
39
40 mpi_errno = MPIR_Topo_canon_nhb_count(comm_ptr, &indegree, &outdegree, &weighted);
41 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
42 MPIU_CHKLMEM_MALLOC(srcs, int *, indegree*sizeof(int), mpi_errno, "srcs");
43 MPIU_CHKLMEM_MALLOC(dsts, int *, outdegree*sizeof(int), mpi_errno, "dsts");
44 mpi_errno = MPIR_Topo_canon_nhb(comm_ptr,
45 indegree, srcs, MPI_UNWEIGHTED,
46 outdegree, dsts, MPI_UNWEIGHTED);
47 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
48
49 for (k = 0; k < outdegree; ++k) {
50 char *sb;
51 MPID_Ensure_Aint_fits_in_pointer(MPI_VOID_PTR_CAST_TO_MPI_AINT sendbuf + sdispls[k]);
52
53 sb = ((char *)sendbuf) + sdispls[k];
54 mpi_errno = MPID_Sched_send(sb, sendcounts[k], sendtypes[k], dsts[k], comm_ptr, s);
55 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
56 }
57
58 for (l = 0; l < indegree; ++l) {
59 char *rb;
60 MPID_Ensure_Aint_fits_in_pointer(MPI_VOID_PTR_CAST_TO_MPI_AINT recvbuf + rdispls[l]);
61
62 rb = ((char *)recvbuf) + rdispls[l];
63 mpi_errno = MPID_Sched_recv(rb, recvcounts[l], recvtypes[l], srcs[l], comm_ptr, s);
64 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
65 }
66
67 MPID_SCHED_BARRIER(s);
68
69 fn_exit:
70 MPIU_CHKLMEM_FREEALL();
71 return mpi_errno;
72 fn_fail:
73 goto fn_exit;
74 }
75
76 #undef FUNCNAME
77 #define FUNCNAME MPIR_Ineighbor_alltoallw_impl
78 #undef FCNAME
79 #define FCNAME MPIU_QUOTE(FUNCNAME)
MPIR_Ineighbor_alltoallw_impl(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[],MPID_Comm * comm_ptr,MPI_Request * request)80 int MPIR_Ineighbor_alltoallw_impl(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[], MPID_Comm *comm_ptr, MPI_Request *request)
81 {
82 int mpi_errno = MPI_SUCCESS;
83 int tag = -1;
84 MPID_Request *reqp = NULL;
85 MPID_Sched_t s = MPID_SCHED_NULL;
86
87 *request = MPI_REQUEST_NULL;
88
89 mpi_errno = MPID_Sched_next_tag(comm_ptr, &tag);
90 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
91 mpi_errno = MPID_Sched_create(&s);
92 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
93 MPIU_Assert(comm_ptr->coll_fns != NULL);
94 MPIU_Assert(comm_ptr->coll_fns->Ineighbor_alltoallw != NULL);
95 mpi_errno = comm_ptr->coll_fns->Ineighbor_alltoallw(sendbuf, sendcounts, sdispls, sendtypes,
96 recvbuf, recvcounts, rdispls, recvtypes,
97 comm_ptr, s);
98 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
99
100 mpi_errno = MPID_Sched_start(&s, comm_ptr, tag, &reqp);
101 if (reqp)
102 *request = reqp->handle;
103 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
104
105 fn_exit:
106 return mpi_errno;
107 fn_fail:
108 goto fn_exit;
109 }
110
111 #endif /* MPICH_MPI_FROM_PMPI */
112
113 #undef FUNCNAME
114 #define FUNCNAME MPIX_Ineighbor_alltoallw
115 #undef FCNAME
116 #define FCNAME MPIU_QUOTE(FUNCNAME)
117 /*@
118 MPIX_Ineighbor_alltoallw - Nonblocking version of MPIX_Neighbor_alltoallw.
119
120 Input Parameters:
121 + sendbuf - starting address of the send buffer (choice)
122 . sendcounts - non-negative integer array (of length outdegree) specifying the number of elements to send to each neighbor
123 . sdispls - integer array (of length outdegree). Entry j specifies the displacement in bytes (relative to sendbuf) from which to take the outgoing data destined for neighbor j (array of integers)
124 . sendtypes - array of datatypes (of length outdegree). Entry j specifies the type of data to send to neighbor j (array of handles)
125 . recvcounts - non-negative integer array (of length indegree) specifying the number of elements that are received from each neighbor
126 . rdispls - integer array (of length indegree). Entry i specifies the displacement in bytes (relative to recvbuf) at which to place the incoming data from neighbor i (array of integers).
127 . recvtypes - array of datatypes (of length indegree). Entry i specifies the type of data received from neighbor i (array of handles).
128 - comm - communicator with topology structure (handle)
129
130 Output Parameters:
131 + recvbuf - starting address of the receive buffer (choice)
132 - request - communication request (handle)
133
134 .N ThreadSafe
135
136 .N Fortran
137
138 .N Errors
139 @*/
MPIX_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)140 int MPIX_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)
141 {
142 int mpi_errno = MPI_SUCCESS;
143 MPID_Comm *comm_ptr = NULL;
144 MPID_MPI_STATE_DECL(MPID_STATE_MPIX_INEIGHBOR_ALLTOALLW);
145
146 MPIU_THREAD_CS_ENTER(ALLFUNC,);
147 MPID_MPI_FUNC_ENTER(MPID_STATE_MPIX_INEIGHBOR_ALLTOALLW);
148
149 /* Validate parameters, especially handles needing to be converted */
150 # ifdef HAVE_ERROR_CHECKING
151 {
152 MPID_BEGIN_ERROR_CHECKS
153 {
154 MPIR_ERRTEST_COMM(comm, mpi_errno);
155
156 /* TODO more checks may be appropriate */
157 if (mpi_errno != MPI_SUCCESS) goto fn_fail;
158 }
159 MPID_END_ERROR_CHECKS
160 }
161 # endif /* HAVE_ERROR_CHECKING */
162
163 /* Convert MPI object handles to object pointers */
164 MPID_Comm_get_ptr(comm, comm_ptr);
165
166 /* Validate parameters and objects (post conversion) */
167 # ifdef HAVE_ERROR_CHECKING
168 {
169 MPID_BEGIN_ERROR_CHECKS
170 {
171 MPID_Comm_valid_ptr(comm_ptr, mpi_errno);
172 MPIR_ERRTEST_ARGNULL(request, "request", mpi_errno);
173 /* TODO more checks may be appropriate (counts, in_place, buffer aliasing, etc) */
174 if (mpi_errno != MPI_SUCCESS) goto fn_fail;
175 }
176 MPID_END_ERROR_CHECKS
177 }
178 # endif /* HAVE_ERROR_CHECKING */
179
180 /* ... body of routine ... */
181
182 mpi_errno = MPIR_Ineighbor_alltoallw_impl(sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes, comm_ptr, request);
183 if (mpi_errno) MPIU_ERR_POP(mpi_errno);
184
185 /* ... end of body of routine ... */
186
187 fn_exit:
188 MPID_MPI_FUNC_EXIT(MPID_STATE_MPIX_INEIGHBOR_ALLTOALLW);
189 MPIU_THREAD_CS_EXIT(ALLFUNC,);
190 return mpi_errno;
191
192 fn_fail:
193 /* --BEGIN ERROR HANDLING-- */
194 # ifdef HAVE_ERROR_CHECKING
195 {
196 mpi_errno = MPIR_Err_create_code(
197 mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER,
198 "**mpix_ineighbor_alltoallw", "**mpix_ineighbor_alltoallw %p %p %p %p %p %p %p %p %C %p", sendbuf, sendcounts, sdispls, sendtypes, recvbuf, recvcounts, rdispls, recvtypes, comm, request);
199 }
200 # endif
201 mpi_errno = MPIR_Err_return_comm(NULL, FCNAME, mpi_errno);
202 goto fn_exit;
203 /* --END ERROR HANDLING-- */
204 }
205