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