71 #define MAX(a,b) ((a) >= (b) ? (a) : (b))
75 MPI_Comm newComm,
int new_tag_offset);
76 static void xt_exchanger_neigh_alltoall_delete(
Xt_exchanger exchanger);
77 static void xt_exchanger_neigh_alltoall_s_exchange(
Xt_exchanger exchanger,
78 const void * src_data,
80 static void xt_exchanger_neigh_alltoall_a_exchange(
Xt_exchanger exchanger,
81 const void * src_data,
85 xt_exchanger_neigh_alltoall_get_msg_ranks(
Xt_exchanger exchanger,
87 int *restrict *ranks);
90 xt_exchanger_neigh_alltoall_get_MPI_Datatype(
Xt_exchanger exchanger,
96 .
copy = xt_exchanger_neigh_alltoall_copy,
97 .delete = xt_exchanger_neigh_alltoall_delete,
98 .s_exchange = xt_exchanger_neigh_alltoall_s_exchange,
99 .a_exchange = xt_exchanger_neigh_alltoall_a_exchange,
100 .get_msg_ranks = xt_exchanger_neigh_alltoall_get_msg_ranks,
101 .get_MPI_Datatype = xt_exchanger_neigh_alltoall_get_MPI_Datatype,
104 typedef struct Xt_exchanger_neigh_alltoall_ * Xt_exchanger_neigh_alltoall;
106 struct Xt_exchanger_neigh_alltoall_ {
116 MPI_Datatype * datatypes;
119 static Xt_exchanger_neigh_alltoall
120 xt_exchanger_neigh_alltoall_alloc(
size_t nsend,
size_t nrecv)
122 size_t nmsg = nsend + nrecv;
123 size_t max_msgs =
MAX(nsend, nrecv);
124 Xt_exchanger_neigh_alltoall exchanger =
xmalloc(1 *
sizeof(*exchanger));
125 exchanger->ranks =
xmalloc(nmsg *
sizeof(*(exchanger->ranks)));
126 exchanger->datatypes =
xmalloc(nmsg *
sizeof(*(exchanger->datatypes)));
127 exchanger->one_counts =
xmalloc(max_msgs *
sizeof(*(exchanger->one_counts)));
128 exchanger->displs =
xmalloc(max_msgs *
sizeof(*(exchanger->displs)));
129 exchanger->vtable = &exchanger_neigh_alltoall_vtable;
130 for (
size_t i = 0; i < max_msgs; ++i) {
131 exchanger->one_counts[i] = 1;
132 exchanger->displs[i] = 0;
137 static void copy_from_redist_msgs(
size_t n,
140 MPI_Datatype *restrict datatypes,
143 for (
size_t i = 0; i < n; ++i) {
144 ranks[i] = msgs[i].rank;
145 xt_mpi_call(MPI_Type_dup(msgs[i].datatype, datatypes + i), comm);
161 xt_mpi_call(MPI_Comm_test_inter(comm, &flag), comm);
163 Xt_abort(comm,
"ERROR(xt_exchanger_neigh_alltoall_new): "
164 "inter-communicator's are not defined for virtual topologies",
167 assert((nsend >= 0) & (nrecv >= 0));
168 Xt_exchanger_neigh_alltoall exchanger
169 = xt_exchanger_neigh_alltoall_alloc((
size_t)nsend, (
size_t)nrecv);
170 exchanger->tag_offset = tag_offset;
171 exchanger->nmsg[
SEND] = nsend;
172 copy_from_redist_msgs((
size_t)nsend, send_msgs, exchanger->ranks,
173 exchanger->datatypes, comm);
174 exchanger->nmsg[
RECV] = nrecv;
175 copy_from_redist_msgs((
size_t)nrecv, recv_msgs, exchanger->ranks + nsend,
176 exchanger->datatypes + nsend, comm);
180 MPI_Dist_graph_create_adjacent(
181 comm, nrecv, exchanger->ranks + nsend, MPI_UNWEIGHTED, nsend,
182 exchanger->ranks, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder,
183 &(exchanger->comm)), comm);
189 xt_exchanger_neigh_alltoall_copy(
Xt_exchanger exchanger,
190 MPI_Comm new_comm,
int new_tag_offset)
192 Xt_exchanger_neigh_alltoall exchanger_na =
193 (Xt_exchanger_neigh_alltoall)exchanger;
194 size_t nsend = (size_t)(exchanger_na->nmsg[
SEND]),
195 nrecv = (size_t)(exchanger_na->nmsg[
RECV]),
196 nmsg = nsend + nrecv;
198 Xt_exchanger_neigh_alltoall
199 exchanger_copy = xt_exchanger_neigh_alltoall_alloc(nsend, nrecv);
201 exchanger_copy->nmsg[
SEND] = (int)nsend;
202 exchanger_copy->nmsg[
RECV] = (int)nrecv;
203 exchanger_copy->tag_offset = new_tag_offset;
204 exchanger_copy->comm = new_comm;
205 memcpy(exchanger_copy->ranks, exchanger_na->ranks,
206 nmsg *
sizeof(*(exchanger_copy->ranks)));
207 for (
size_t i = 0; i < nmsg; ++i)
208 xt_mpi_call(MPI_Type_dup(exchanger_na->datatypes[i],
209 exchanger_copy->datatypes + i), new_comm);
214 static void xt_exchanger_neigh_alltoall_delete(
Xt_exchanger exchanger) {
216 Xt_exchanger_neigh_alltoall exchanger_na =
217 (Xt_exchanger_neigh_alltoall)exchanger;
219 size_t nmsg = (size_t)exchanger_na->nmsg[
SEND]
220 + (
size_t)exchanger_na->nmsg[
RECV];
223 free(exchanger_na->ranks);
224 free(exchanger_na->one_counts);
225 free(exchanger_na->displs);
226 for (
size_t i = 0; i < nmsg; ++i) {
227 MPI_Datatype *dt = exchanger_na->datatypes + i;
228 if (*dt != MPI_DATATYPE_NULL)
231 free(exchanger_na->datatypes);
232 xt_mpi_call(MPI_Comm_free(&(exchanger_na->comm)), Xt_default_comm);
236 static void xt_exchanger_neigh_alltoall_s_exchange(
Xt_exchanger exchanger,
237 const void * src_data,
240 Xt_exchanger_neigh_alltoall exchanger_na =
241 (Xt_exchanger_neigh_alltoall)exchanger;
244 MPI_Neighbor_alltoallw(src_data, exchanger_na->one_counts,
245 exchanger_na->displs, exchanger_na->datatypes,
246 dst_data, exchanger_na->one_counts,
247 exchanger_na->displs, exchanger_na->datatypes +
248 (
size_t)(exchanger_na->nmsg[
SEND]),
253 static void xt_exchanger_neigh_alltoall_a_exchange(
Xt_exchanger exchanger,
254 const void * src_data,
258 Xt_exchanger_neigh_alltoall exchanger_na =
259 (Xt_exchanger_neigh_alltoall)exchanger;
261 MPI_Request tmp_request;
264 MPI_Ineighbor_alltoallw(src_data, exchanger_na->one_counts,
265 exchanger_na->displs, exchanger_na->datatypes,
266 dst_data, exchanger_na->one_counts,
267 exchanger_na->displs, exchanger_na->datatypes +
268 (
size_t)(exchanger_na->nmsg[
SEND]),
269 exchanger_na->comm, &tmp_request),
276 xt_exchanger_neigh_alltoall_get_MPI_Datatype(
Xt_exchanger exchanger,
280 Xt_exchanger_neigh_alltoall exchanger_na =
281 (Xt_exchanger_neigh_alltoall)exchanger;
282 size_t nsend = (size_t)exchanger_na->nmsg[
SEND],
283 nmsg = (
size_t)exchanger_na->nmsg[direction],
284 ofs = direction ==
SEND ? 0 : nsend;
285 int *restrict ranks = exchanger_na->ranks + ofs;
286 MPI_Datatype datatype_copy = MPI_DATATYPE_NULL;
287 for (
size_t i = 0; i < nmsg; ++i) {
288 if (ranks[i] == rank) {
289 xt_mpi_call(MPI_Type_dup(exchanger_na->datatypes[i+ofs], &datatype_copy),
294 return datatype_copy;
298 xt_exchanger_neigh_alltoall_get_msg_ranks(
Xt_exchanger exchanger,
300 int *restrict *ranks)
302 Xt_exchanger_neigh_alltoall exchanger_na =
303 (Xt_exchanger_neigh_alltoall)exchanger;
304 size_t nsend = (size_t)exchanger_na->nmsg[
SEND],
305 nmsg = (
size_t)exchanger_na->nmsg[direction],
306 ofs = direction ==
SEND ? 0 : nsend;
307 *ranks =
xmalloc(nmsg *
sizeof(**ranks));
308 memcpy(*ranks, exchanger_na->ranks + ofs, nmsg *
sizeof(**ranks));
321 (void)nsend; (void)nrecv; (void)send_msgs; (void)recv_msgs; (void)tag_offset;
322 Xt_abort(comm,
"ERROR(xt_exchanger_neigh_alltoall_new): "
323 "exchanger_neigh_alltoall requires MPI version 3.0 or higher",
add versions of standard API functions not returning on error
Xt_exchanger(* copy)(Xt_exchanger, MPI_Comm, int)
exchanging of data based on information provided by redist's
Xt_exchanger xt_exchanger_neigh_alltoall_new(int nsend, int nrecv, const struct Xt_redist_msg *send_msgs, const struct Xt_redist_msg *recv_msgs, MPI_Comm comm, int tag_offset)
#define xt_mpi_call(call, comm)
redistribution of data, non-public declarations
Xt_request xt_request_msgs_new(int n, const MPI_Request requests[n], MPI_Comm comm)
exchange map declarations