Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_exchanger_mix_isend_irecv.c
Go to the documentation of this file.
1 
12 /*
13  * Keywords:
14  * Maintainer: Jörg Behrens <behrens@dkrz.de>
15  * Moritz Hanke <hanke@dkrz.de>
16  * Thomas Jahns <jahns@dkrz.de>
17  * URL: https://doc.redmine.dkrz.de/yaxt/html/
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions are
21  * met:
22  *
23  * Redistributions of source code must retain the above copyright notice,
24  * this list of conditions and the following disclaimer.
25  *
26  * Redistributions in binary form must reproduce the above copyright
27  * notice, this list of conditions and the following disclaimer in the
28  * documentation and/or other materials provided with the distribution.
29  *
30  * Neither the name of the DKRZ GmbH nor the names of its contributors
31  * may be used to endorse or promote products derived from this software
32  * without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
35  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
38  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  */
46 #ifdef HAVE_CONFIG_H
47 #include <config.h>
48 #endif
49 
50 #include <assert.h>
51 #include <mpi.h>
52 
53 #include "core/core.h"
54 #include "core/ppm_xfuncs.h"
55 #include "xt/xt_mpi.h"
56 #include "xt_mpi_internal.h"
57 #include "xt_redist_internal.h"
58 #include "xt_exchanger.h"
60 
61 static Xt_exchanger
63  MPI_Comm newComm, int new_tag_offset);
66  const void * src_data,
67  void * dst_data);
68 static int
70  enum xt_msg_direction direction,
71  int **ranks);
72 
73 static MPI_Datatype
75  int rank,
76  enum xt_msg_direction direction);
77 
84 };
85 
87 
88 struct mix_msg {
91 };
92 
94 
95  const struct xt_exchanger_vtable * vtable;
96 
97  int n, tag_offset;
99  struct mix_msg msgs[];
100 };
101 
102 static Xt_exchanger_mix_isend_irecv
104 {
105  Xt_exchanger_mix_isend_irecv exchanger;
106  size_t header_size = sizeof (*exchanger),
107  body_size = sizeof (struct mix_msg) * nmsg;
108  exchanger = xmalloc(header_size + body_size);
109  exchanger->n = (int)nmsg;
111  return exchanger;
112 }
113 
115 xt_exchanger_mix_isend_irecv_new(int nsend, int nrecv,
116  struct Xt_redist_msg * send_msgs,
117  struct Xt_redist_msg * recv_msgs,
118  MPI_Comm comm, int tag_offset) {
119 
120  assert((nsend >= 0) & (nrecv >= 0));
121  size_t nmsg = (size_t)nsend + (size_t)nrecv;
122  Xt_exchanger_mix_isend_irecv exchanger
124  exchanger->comm = comm, exchanger->tag_offset = tag_offset;
125  struct mix_msg *restrict msgs = exchanger->msgs;
126  xt_redist_msgs_strided_copy((size_t)nsend, send_msgs, sizeof (send_msgs[0]),
127  &(msgs[0].data), sizeof (msgs[0]), comm);
128  for (size_t i = 0; i < (size_t)nsend; ++i)
129  msgs[i].type = SEND;
130  xt_redist_msgs_strided_copy((size_t)nrecv, recv_msgs, sizeof (recv_msgs[0]),
131  &(msgs[nsend].data), sizeof (msgs[0]), comm);
132  for (size_t i = 0; i < (size_t)nrecv; ++i)
133  msgs[i + (size_t)nsend].type = RECV;
134 
135  xt_exchanger_internal_optimize(nmsg, msgs, sizeof(*msgs), comm);
136 
137  for (size_t i = 1; i < nmsg; ++i) {
138 
139  if ((msgs[i-1].data.rank == msgs[i].data.rank) && (msgs[i].type == SEND)) {
140 
141  struct mix_msg temp = msgs[i-1];
142  msgs[i-1] = msgs[i];
143  msgs[i] = temp;
144  i++;
145  }
146  }
147 
148  return (Xt_exchanger)exchanger;
149 }
150 
151 static Xt_exchanger
153  MPI_Comm new_comm, int new_tag_offset)
154 {
155  Xt_exchanger_mix_isend_irecv exchanger_msr =
156  (Xt_exchanger_mix_isend_irecv)exchanger;
157  size_t nmsg = (size_t)exchanger_msr->n;
158  Xt_exchanger_mix_isend_irecv exchanger_copy
160  exchanger_copy->comm = new_comm;
161  exchanger_copy->tag_offset = new_tag_offset;
162  struct mix_msg *restrict new_msgs = exchanger_copy->msgs,
163  *restrict orig_msgs = exchanger_msr->msgs;
164  xt_redist_msgs_strided_copy(nmsg, &orig_msgs->data, sizeof (*orig_msgs),
165  &new_msgs->data, sizeof (*new_msgs),
166  new_comm);
167  for (size_t i = 0; i < nmsg; ++i)
168  new_msgs[i].type = orig_msgs[i].type;
169  return (Xt_exchanger)exchanger_copy;
170 }
171 
172 
174 
175  Xt_exchanger_mix_isend_irecv exchanger_msr =
176  (Xt_exchanger_mix_isend_irecv)exchanger;
177 
178  size_t nmsg = (size_t)exchanger_msr->n;
179  struct mix_msg *restrict msgs = exchanger_msr->msgs;
180 
181  xt_redist_msgs_strided_destruct(nmsg, &msgs[0].data, exchanger_msr->comm,
182  sizeof (*msgs));
183  free(exchanger_msr);
184 }
185 
187  const void * src_data,
188  void * dst_data) {
189 
190  Xt_exchanger_mix_isend_irecv exchanger_msr =
191  (Xt_exchanger_mix_isend_irecv)exchanger;
192 
193  if (exchanger_msr->n > 0) {
194  size_t nmsg = (size_t)exchanger_msr->n;
195  MPI_Comm comm = exchanger_msr->comm;
196  struct mix_msg *restrict msgs = exchanger_msr->msgs;
197  int tag_offset = exchanger_msr->tag_offset;
198  MPI_Request *requests = xmalloc(nmsg * sizeof (*requests));
199  for (size_t i = 0; i < nmsg; ++i) {
200  typedef int (*ifp)(void *buf, int count, MPI_Datatype datatype, int dest,
201  int tag, MPI_Comm comm, MPI_Request *request);
202  ifp op = msgs[i].type == SEND ? (ifp)MPI_Isend : (ifp)MPI_Irecv;
203  void *data = msgs[i].type == SEND ? (void *)src_data : dst_data;
204  xt_mpi_call(op(data, 1, msgs[i].data.datatype,
205  msgs[i].data.rank,
206  tag_offset + xt_mpi_tag_exchange_msg,
207  comm, requests+i), comm);
208  }
209  xt_mpi_call(MPI_Waitall((int)nmsg, requests, MPI_STATUSES_IGNORE), comm);
210  free(requests);
211  }
212 }
213 
214 static int
216  enum xt_msg_direction direction,
217  int **ranks)
218 {
219  Xt_exchanger_mix_isend_irecv exchanger_msr =
220  (Xt_exchanger_mix_isend_irecv)exchanger;
221  size_t nmsg = 0, nmsg_all = (size_t)exchanger_msr->n;
222  const struct mix_msg *restrict msgs = exchanger_msr->msgs;
223  for (size_t i = 0; i < nmsg_all; ++i)
224  nmsg += msgs[i].type == direction;
225  int *restrict ranks_ = *ranks = xmalloc(nmsg * sizeof (*ranks_));
226  for (size_t i = 0, j = (size_t)-1; i < nmsg_all; ++i)
227  if (msgs[i].type == direction)
228  ranks_[++j] = msgs[i].data.rank;
229  return (int)nmsg;
230 }
231 
232 static MPI_Datatype
234  int rank,
235  enum xt_msg_direction direction)
236 {
237  Xt_exchanger_mix_isend_irecv exchanger_msr =
238  (Xt_exchanger_mix_isend_irecv)exchanger;
239  size_t nmsg = (size_t)exchanger_msr->n;
240  struct mix_msg *restrict msgs = exchanger_msr->msgs;
241  MPI_Datatype datatype_copy = MPI_DATATYPE_NULL;
242  for (size_t i = 0; i < nmsg; ++i)
243  if (msgs[i].type == direction && msgs[i].data.rank == rank) {
244  xt_mpi_call(MPI_Type_dup(msgs[i].data.datatype, &datatype_copy),
245  exchanger_msr->comm);
246  break;
247  }
248  return datatype_copy;
249 }
250 
251 /*
252  * Local Variables:
253  * c-basic-offset: 2
254  * coding: utf-8
255  * indent-tabs-mode: nil
256  * show-trailing-whitespace: t
257  * require-trailing-newline: t
258  * End:
259  */
enum xt_msg_direction type
xt_msg_direction
redistribution of data, non-public declarations
Xt_exchanger xt_exchanger_mix_isend_irecv_new(int nsend, int nrecv, struct Xt_redist_msg *send_msgs, struct Xt_redist_msg *recv_msgs, MPI_Comm comm, int tag_offset)
add versions of standard API functions not returning on error
static const struct xt_exchanger_vtable exchanger_mix_isend_irecv_vtable
static int xt_exchanger_mix_isend_irecv_get_msg_ranks(Xt_exchanger exchanger, enum xt_msg_direction direction, int **ranks)
static Xt_exchanger_mix_isend_irecv xt_exchanger_mix_isend_irecv_alloc(size_t nmsg)
Xt_exchanger(* copy)(Xt_exchanger, MPI_Comm, int)
Definition: xt_exchanger.h:65
static Xt_exchanger xt_exchanger_mix_isend_irecv_copy(Xt_exchanger exchanger, MPI_Comm newComm, int new_tag_offset)
static void xt_exchanger_mix_isend_irecv_delete(Xt_exchanger exchanger)
const struct xt_exchanger_vtable * vtable
struct Xt_redist_msg data
MPI_Datatype datatype
void xt_exchanger_internal_optimize(size_t n, void *msgs, size_t msg_type_size, MPI_Comm comm)
Definition: xt_exchanger.c:87
void xt_redist_msgs_strided_destruct(size_t n, struct Xt_redist_msg *msgs, MPI_Comm comm, size_t ofs_stride)
Definition: xt_redist.c:124
static MPI_Datatype xt_exchanger_mix_isend_irecv_get_MPI_Datatype(Xt_exchanger exchanger, int rank, enum xt_msg_direction direction)
struct Xt_exchanger_mix_isend_irecv_ * Xt_exchanger_mix_isend_irecv
exchanging of data based on information provided by redist&#39;s
#define xt_mpi_call(call, comm)
Definition: xt_mpi.h:68
void xt_redist_msgs_strided_copy(size_t n, struct Xt_redist_msg *restrict src, size_t src_stride, struct Xt_redist_msg *restrict dst, size_t dst_stride, MPI_Comm comm)
Definition: xt_redist.c:105
static void xt_exchanger_mix_isend_irecv_s_exchange(Xt_exchanger exchanger, const void *src_data, void *dst_data)
#define xmalloc(size)
Definition: ppm_xfuncs.h:66
int MPI_Comm
Definition: core.h:64
utility routines for MPI