Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_redist_collection.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 <limits.h>
52 #include <stdbool.h>
53 #include <stdlib.h>
54 #include <string.h>
55 
56 #include <mpi.h>
57 
58 #include "core/core.h"
59 #include "core/ppm_xfuncs.h"
60 #include "xt/xt_mpi.h"
61 #include "xt/xt_sort.h"
62 #include "xt_mpi_internal.h"
64 #include "ensure_array_size.h"
65 #include "xt/xt_redist.h"
66 #include "xt_redist_internal.h"
67 #include "xt_exchanger.h"
68 
70 
71 static void
73 
74 static Xt_redist
76 
77 static void
78 redist_collection_s_exchange(Xt_redist redist, int num_src_arrays,
79  const void **src_data, void **dst_data);
80 
81 static void
83  const void *src_data, void *dst_data);
84 
85 static MPI_Datatype
87 
88 static MPI_Datatype
90 
91 static int
93  enum xt_msg_direction direction,
94  int **ranks);
95 
96 static MPI_Comm
98 
101  .delete = redist_collection_delete,
102  .s_exchange = redist_collection_s_exchange,
103  .s_exchange1 = redist_collection_s_exchange1,
104  .get_send_MPI_Datatype = redist_collection_get_send_MPI_Datatype,
105  .get_recv_MPI_Datatype = redist_collection_get_recv_MPI_Datatype,
106  .get_msg_ranks = redist_collection_get_msg_ranks,
107  .get_MPI_Comm = redist_collection_get_MPI_Comm
108 };
109 
111 
112  int rank;
113  MPI_Datatype *component_dt; // datatypes of the redists (size == num_redists)
114 };
115 
117 {
118  size_t token;
119  MPI_Aint *src_displacements, *dst_displacements;
121  struct Xt_redist_msg * msgs;
122 };
123 
125 
127 
128  const struct xt_redist_vtable *vtable;
129 
130  unsigned num_redists;
131 
132  struct exchanger_cache cache;
133 
134  unsigned ndst, nsrc;
137 
138  size_t cache_size;
139 
142 };
143 
144 static void copy_component_dt(struct redist_collection_msg **msgs,
145  unsigned *nmsgs,
146  Xt_redist *redists, unsigned num_redists,
147  enum xt_msg_direction direction,
148  MPI_Datatype (*get_MPI_datatype)(Xt_redist,int))
149 {
150  size_t num_ranks[num_redists], rank_pos[num_redists];
151  int *restrict ranks[num_redists];
152  bool ranks_left = false;
153  /* get lists of ranks to send/receive message to/from */
154  for (size_t j = 0; j < num_redists; ++j) {
155  num_ranks[j]
156  = (size_t)xt_redist_get_msg_ranks(redists[j], direction,
157  (int **)(ranks + j));
158  /* sort list */
159  xt_sort_int(ranks[j], num_ranks[j]);
160  ranks_left |= (num_ranks[j] > 0);
161  rank_pos[j] = 0;
162  }
163  /* count number of different ranks to send/receive message to/from */
164  size_t num_messages = ranks_left
165  ? xt_ranks_uniq_count(num_redists, num_ranks, (const int **)ranks)
166  : 0;
167  /* build messages */
168  struct redist_collection_msg *restrict p = NULL;
169  if (num_messages) {
170  MPI_Datatype *restrict dt
171  = xmalloc(num_messages * num_redists * sizeof (*dt));
172  p = xmalloc(num_messages * sizeof (*p));
173  for (size_t i = 0; i < num_messages; ++i) {
174  int min_rank = INT_MAX;
175  for (size_t j = 0; j < num_redists; ++j)
176  if (rank_pos[j] < num_ranks[j] && ranks[j][rank_pos[j]] < min_rank)
177  min_rank = ranks[j][rank_pos[j]];
178 
179  MPI_Datatype *dts_rank = dt + (size_t)num_redists * i;
180  for (size_t j = 0; j < num_redists; ++j)
181  dts_rank[j] =
182  (rank_pos[j] < num_ranks[j] && ranks[j][rank_pos[j]] == min_rank)
183  ? get_MPI_datatype(redists[j], min_rank) : MPI_DATATYPE_NULL;
184 
185  p[i].rank = min_rank;
186  p[i].component_dt = dts_rank;
187  for (size_t j = 0; j < num_redists; ++j)
188  rank_pos[j]
189  += (rank_pos[j] < num_ranks[j] && ranks[j][rank_pos[j]] == min_rank);
190  }
191  }
192  for (size_t j = 0; j < num_redists; ++j)
193  free(ranks[j]);
194  *msgs = p;
195  *nmsgs = (unsigned)num_messages;
196 }
197 
198 /* not yet used cache entries are marked with -1 as first displacement,
199  * which becomes 0 later on through use */
200 static inline void
201 init_cache(struct exchanger_cache *cache, size_t cache_size, size_t ntx,
202  unsigned num_redists)
203 {
204  cache->exchangers = xcalloc(cache_size, sizeof(*(cache->exchangers)));
205  size_t num_displ = cache_size * num_redists;
206  struct Xt_redist_msg *msgs = cache->msgs = xmalloc(ntx * sizeof (*msgs));
207  for (size_t i = 0; i < ntx; ++i) msgs[i].datatype = MPI_DATATYPE_NULL;
208  MPI_Aint *restrict q = cache->src_displacements
209  = xmalloc(2 * num_displ * sizeof (*q));
210  cache->dst_displacements = q + num_displ;
211  for (size_t i = 0; i < 2 * num_displ; i += num_redists)
212  q[i] = (MPI_Aint)-1;
213  cache->token = 0;
214 }
215 
216 static inline void
218  size_t cache_size, size_t ntx, MPI_Comm comm)
219 {
220  for (size_t i = 0; i < cache_size; ++i)
221  if (cache->exchangers[i] != NULL)
222  xt_exchanger_delete(cache->exchangers[i]);
223  free(cache->exchangers);
224 
225  xt_redist_msgs_free(ntx, cache->msgs, comm);
226  free(cache->src_displacements);
227 }
228 
229 
230 Xt_redist xt_redist_collection_new(Xt_redist * redists, int num_redists,
231  int cache_size, MPI_Comm comm) {
232 
233  Xt_redist_collection redist_coll = xmalloc(sizeof (*redist_coll));
234 
235  redist_coll->vtable = &redist_collection_vtable;
236  unsigned num_redists_ = num_redists >= 0 ? (unsigned)num_redists : 0;
237  redist_coll->num_redists = num_redists_;
238  redist_coll->ndst = 0;
239  redist_coll->nsrc = 0;
240  redist_coll->send_msgs = NULL;
241  redist_coll->recv_msgs = NULL;
242  if (cache_size < -1)
243  Xt_abort(comm, "ERROR: invalid cache size in xt_redist_collection_new",
244  __FILE__, __LINE__);
245  redist_coll->cache_size
246  = (cache_size == -1)?(DEFFAULT_DATATYPE_CACHE_SIZE):(size_t)cache_size;
247 
248  redist_coll->comm = xt_mpi_comm_smart_dup(comm, &redist_coll->tag_offset);
249 
250  xt_redist_check_comms(redists, num_redists, comm);
251 
252  copy_component_dt(&redist_coll->send_msgs, &redist_coll->nsrc, redists,
253  num_redists_, SEND, xt_redist_get_send_MPI_Datatype);
254  copy_component_dt(&redist_coll->recv_msgs, &redist_coll->ndst, redists,
255  num_redists_, RECV, xt_redist_get_recv_MPI_Datatype);
256  init_cache(&redist_coll->cache, redist_coll->cache_size,
257  (size_t)redist_coll->nsrc + (size_t)redist_coll->ndst,
258  num_redists_);
259 
260  return (Xt_redist)redist_coll;
261 }
262 
263 
264 static void
266  unsigned num_messages, unsigned num_redists,
267  const MPI_Aint displacements[num_redists],
268  struct Xt_redist_msg redist_msgs[num_messages],
269  MPI_Comm comm)
270 {
271  int block_lengths[num_redists];
272 
273  for (size_t i = 0; i < num_redists; ++i)
274  block_lengths[i] = 1;
275  for (size_t i = 0; i < num_messages; ++i) {
276  if (redist_msgs[i].datatype != MPI_DATATYPE_NULL)
277  xt_mpi_call(MPI_Type_free(&(redist_msgs[i].datatype)), comm);
278  redist_msgs[i].datatype
279  = xt_create_compound_datatype(num_redists, displacements,
280  msgs[i].component_dt, block_lengths, comm);
281  redist_msgs[i].rank = msgs[i].rank;
282  }
283 }
284 
285 static void
286 compute_displ(const void *const *data, unsigned num_redists,
287  MPI_Aint displacements[num_redists],
288  MPI_Comm comm)
289 {
290  if (num_redists) {
291  MPI_Aint base_addr, offset;
292  xt_mpi_call(MPI_Get_address((void *)data[0], &base_addr), comm);
293  displacements[0] = 0;
294  for (size_t i = 1; i < num_redists; ++i) {
295  xt_mpi_call(MPI_Get_address((void *)data[i], &offset), comm);
296  displacements[i] = offset - base_addr;
297  }
298  }
299 }
300 
301 static size_t
302 lookup_cache_index(unsigned num_redists,
303  const MPI_Aint src_displacements[num_redists],
304  const MPI_Aint dst_displacements[num_redists],
305  const MPI_Aint (*cached_src_displacements)[num_redists],
306  const MPI_Aint (*cached_dst_displacements)[num_redists],
307  size_t cache_size)
308 {
309  for (size_t i = 0; i < cache_size &&
310  cached_src_displacements[i][0] == (MPI_Aint)0 &&
311  cached_dst_displacements[i][0] == (MPI_Aint)0; ++i) {
312  bool mismatch = false;
313  for (size_t j = 0; j < num_redists; ++j)
314  mismatch |= (src_displacements[j] != cached_src_displacements[i][j]) ||
315  (dst_displacements[j] != cached_dst_displacements[i][j]);
316  if (!mismatch) return i;
317  }
318  return cache_size;
319 }
320 
321 static Xt_exchanger
322 get_exchanger(const void *const * src_data, void *const * dst_data,
323  struct redist_collection_msg * send_msgs, unsigned num_send_messages,
324  struct redist_collection_msg * recv_msgs, unsigned num_recv_messages,
325  unsigned num_redists,
326  struct exchanger_cache *cache, size_t cache_size,
327  MPI_Comm comm, int tag_offset)
328 {
329  MPI_Aint displacements[2][num_redists];
330  compute_displ(src_data, num_redists, displacements[0], comm);
331  compute_displ((const void *const *)dst_data, num_redists, displacements[1], comm);
332 
333  Xt_exchanger exchanger;
334 
335  if (cache_size > 0)
336  {
337  size_t cache_index
338  = lookup_cache_index(num_redists, displacements[0], displacements[1],
339  (const MPI_Aint (*)[num_redists])cache->src_displacements,
340  (const MPI_Aint (*)[num_redists])cache->dst_displacements,
341  cache_size);
342 
343  if (cache_index == cache_size)
344  {
345  cache_index = cache->token;
346  create_all_dt_for_dir(send_msgs, num_send_messages, num_redists,
347  displacements[0], cache->msgs, comm);
348  create_all_dt_for_dir(recv_msgs, num_recv_messages, num_redists,
349  displacements[1], cache->msgs +
350  (size_t)num_send_messages, comm);
351  memcpy(cache->src_displacements + cache_index * num_redists,
352  displacements[0], sizeof (displacements[0]));
353  memcpy(cache->dst_displacements + cache_index * num_redists,
354  displacements[1], sizeof (displacements[1]));
355 
356  if (cache->exchangers[cache_index] != NULL)
357  xt_exchanger_delete(cache->exchangers[cache_index]);
358 
359  exchanger = cache->exchangers[cache_index] =
360  xt_exchanger_default_constructor((int)num_send_messages,
361  (int)num_recv_messages,
362  cache->msgs, cache->msgs +
363  (size_t)num_send_messages,
364  comm, tag_offset);
365 
366  cache->token = (cache->token + 1) % cache_size;
367  }
368  else
369  exchanger = cache->exchangers[cache_index];
370  }
371  else
372  {
373  size_t nmsg = (size_t)num_send_messages + (size_t)num_recv_messages;
374  struct Xt_redist_msg *restrict p = xmalloc(nmsg * sizeof (*p));
375  for (size_t i = 0; i < nmsg; ++i)
376  p[i].datatype = MPI_DATATYPE_NULL;
377 
378  create_all_dt_for_dir(send_msgs, num_send_messages, num_redists,
379  displacements[0], p, comm);
380  create_all_dt_for_dir(recv_msgs, num_recv_messages, num_redists,
381  displacements[1], p + num_send_messages, comm);
382 
383  exchanger =
384  xt_exchanger_default_constructor((int)num_send_messages,
385  (int)num_recv_messages,
386  p, p + (size_t)num_send_messages,
387  comm, tag_offset);
388 
389  xt_redist_msgs_free(nmsg, p, comm);
390  }
391 
392  return exchanger;
393 }
394 
395 static inline Xt_redist_collection
396 xrc(void *redist)
397 {
398  return (Xt_redist_collection)redist;
399 }
400 
401 static void
403  const void **src_data, void **dst_data) {
404 
405  Xt_redist_collection redist_coll = xrc(redist);
406 
407  if (num_arrays != (int)redist_coll->num_redists)
408  Xt_abort(redist_coll->comm, "ERROR: wrong number of arrays in "
409  "redist_collection_s_exchange", __FILE__, __LINE__);
410 
411 
412  Xt_exchanger exchanger = get_exchanger(src_data, dst_data,
413  redist_coll->send_msgs,
414  redist_coll->nsrc,
415  redist_coll->recv_msgs,
416  redist_coll->ndst,
417  redist_coll->num_redists,
418  &(redist_coll->cache),
419  redist_coll->cache_size,
420  redist_coll->comm,
421  redist_coll->tag_offset);
422 
423  xt_exchanger_s_exchange(exchanger, src_data[0], dst_data[0]);
424 
425  if (redist_coll->cache_size == 0)
426  xt_exchanger_delete(exchanger);
427 }
428 
429 static void
430 copy_msgs(size_t num_redists, unsigned nmsgs,
431  const struct redist_collection_msg *restrict msgs_orig,
432  struct redist_collection_msg **p_msgs_copy,
433  MPI_Comm comm)
434 {
435  struct redist_collection_msg *restrict msgs_copy =
436  *p_msgs_copy = nmsgs > 0 ? xmalloc(nmsgs * sizeof (*msgs_copy)) : NULL;
437  MPI_Datatype *restrict dt_copy
438  = nmsgs * num_redists > 0
439  ? xmalloc(nmsgs * num_redists * sizeof (*dt_copy)) : NULL;
440  for (size_t i = 0; i < nmsgs; ++i)
441  {
442  msgs_copy[i].rank = msgs_orig[i].rank;
443  msgs_copy[i].component_dt = dt_copy + i * num_redists;
444  for (size_t j = 0; j < num_redists; ++j)
445  if (msgs_orig[i].component_dt[j] != MPI_DATATYPE_NULL)
446  xt_mpi_call(MPI_Type_dup(msgs_orig[i].component_dt[j],
447  dt_copy + i * num_redists + j), comm);
448  else
449  dt_copy[i * num_redists + j] = MPI_DATATYPE_NULL;
450  }
451 }
452 
453 static Xt_redist
455 {
456  Xt_redist_collection redist_coll = xrc(redist),
457  redist_copy = xmalloc(sizeof (*redist_copy));
458  redist_copy->vtable = redist_coll->vtable;
459  unsigned num_redists = redist_coll->num_redists;
460  redist_copy->num_redists = num_redists;
461 
462  MPI_Comm copy_comm = redist_copy->comm
463  = xt_mpi_comm_smart_dup(redist_coll->comm, &redist_copy->tag_offset);
464 
465  unsigned nsrc = redist_coll->nsrc;
466  redist_copy->nsrc = nsrc;
467  copy_msgs(num_redists, nsrc, redist_coll->send_msgs, &redist_copy->send_msgs,
468  copy_comm);
469  unsigned ndst = redist_coll->ndst;
470  redist_copy->ndst = ndst;
471  copy_msgs(num_redists, ndst, redist_coll->recv_msgs, &redist_copy->recv_msgs,
472  copy_comm);
473  size_t cache_size = redist_coll->cache_size;
474  redist_copy->cache_size = cache_size;
475  init_cache(&redist_copy->cache, cache_size, (size_t)ndst + nsrc, num_redists);
476  return (Xt_redist)redist_copy;
477 }
478 
479 static void
481  unsigned nmsgs, unsigned num_redists,
482  MPI_Comm comm) {
483 
484  if (nmsgs) {
485  size_t ndt = (size_t)nmsgs * num_redists;
486  MPI_Datatype *all_component_dt = msgs[0].component_dt;
487  for (size_t i = 0; i < ndt; ++i)
488  if (all_component_dt[i] != MPI_DATATYPE_NULL)
489  xt_mpi_call(MPI_Type_free(all_component_dt + i), comm);
490  free(msgs[0].component_dt);
491  }
492  free(msgs);
493 }
494 
495 static void
497 
498  Xt_redist_collection redist_coll = xrc(redist);
499 
500  free_redist_collection_msgs(redist_coll->send_msgs, redist_coll->nsrc,
501  redist_coll->num_redists,
502  redist_coll->comm);
503 
504  free_redist_collection_msgs(redist_coll->recv_msgs, redist_coll->ndst,
505  redist_coll->num_redists,
506  redist_coll->comm);
507 
508  destruct_cache(&redist_coll->cache, redist_coll->cache_size,
509  (size_t)redist_coll->nsrc + (size_t)redist_coll->ndst,
510  redist_coll->comm);
511 
512  xt_mpi_comm_smart_dedup(&(redist_coll->comm), redist_coll->tag_offset);
513 
514  free(redist_coll);
515 }
516 
517 static MPI_Datatype
519 {
520  Xt_redist_collection redist_coll = xrc(redist);
521 
522  Xt_abort(redist_coll->comm, "ERROR: get_send_MPI_Datatype is not"
523  " supported for this xt_redist type (Xt_redist_collection)",
524  __FILE__, __LINE__);
525 
526  return MPI_DATATYPE_NULL;
527 }
528 
529 static MPI_Datatype
531 
532  Xt_redist_collection redist_coll = xrc(redist);
533 
534  Xt_abort(redist_coll->comm, "ERROR: get_recv_MPI_Datatype is not"
535  " supported for this xt_redist type (Xt_redist_collection)",
536  __FILE__, __LINE__);
537 
538  return MPI_DATATYPE_NULL;
539 }
540 
541 static void
543  const void *src_data, void *dst_data)
544 {
545 
546  Xt_redist_collection redist_coll = xrc(redist);
547  if (redist_coll->num_redists == 1)
548  redist_collection_s_exchange(redist, 1, &src_data, &dst_data);
549  else
550  Xt_abort(redist_coll->comm, "ERROR: s_exchange1 is not implemented for"
551  " this xt_redist type (Xt_redist_collection)", __FILE__, __LINE__);
552 }
553 
554 static int
556  enum xt_msg_direction direction,
557  int **ranks)
558 {
559  Xt_redist_collection redist_coll = xrc(redist);
560  unsigned nmsg;
561  struct redist_collection_msg *restrict msg;
562  if (direction == SEND) {
563  nmsg = redist_coll->ndst;
564  msg = redist_coll->send_msgs;
565  } else {
566  nmsg = redist_coll->nsrc;
567  msg = redist_coll->recv_msgs;
568  }
569  int *restrict ranks_ = *ranks = xmalloc(nmsg * sizeof (*ranks_));
570  for (size_t i = 0; i < nmsg; ++i)
571  ranks_[i] = msg[i].rank;
572  return (int)nmsg;
573 }
574 
575 
576 static MPI_Comm
578 
579  Xt_redist_collection redist_coll = xrc(redist);
580 
581  return redist_coll->comm;
582 }
583 
584 /*
585  * Local Variables:
586  * c-basic-offset: 2
587  * coding: utf-8
588  * indent-tabs-mode: nil
589  * show-trailing-whitespace: t
590  * require-trailing-newline: t
591  * End:
592  */
struct exchanger_cache cache
void xt_exchanger_s_exchange(Xt_exchanger exchanger, const void *src_data, void *dst_data)
Definition: xt_exchanger.c:75
static void redist_collection_s_exchange1(Xt_redist redist, const void *src_data, void *dst_data)
xt_msg_direction
void xt_redist_check_comms(Xt_redist *redists, int num_redists, MPI_Comm comm)
Definition: xt_redist.c:137
redistribution of data, non-public declarations
Xt_redist(* copy)(Xt_redist)
static Xt_redist redist_collection_copy(Xt_redist redist)
add versions of standard API functions not returning on error
static void create_all_dt_for_dir(struct redist_collection_msg *msgs, unsigned num_messages, unsigned num_redists, const MPI_Aint displacements[num_redists], struct Xt_redist_msg redist_msgs[num_messages], MPI_Comm comm)
MPI_Datatype xt_redist_get_send_MPI_Datatype(Xt_redist redist, int rank)
Definition: xt_redist.c:82
struct Xt_redist_msg * msgs
MPI_Datatype xt_redist_get_recv_MPI_Datatype(Xt_redist redist, int rank)
Definition: xt_redist.c:87
struct redist_collection_msg * send_msgs
static void free_redist_collection_msgs(struct redist_collection_msg *msgs, unsigned nmsgs, unsigned num_redists, MPI_Comm comm)
MPI_Datatype xt_create_compound_datatype(size_t num_redists, const MPI_Aint displacements[num_redists], const MPI_Datatype datatypes[num_redists], const int block_lengths[num_redists], MPI_Comm comm)
Definition: xt_redist.c:181
Xt_redist xt_redist_collection_new(Xt_redist *redists, int num_redists, int cache_size, MPI_Comm comm)
static void xt_redist_msgs_free(size_t n, struct Xt_redist_msg *msgs, MPI_Comm comm)
static Xt_redist_collection xrc(void *redist)
static MPI_Datatype redist_collection_get_send_MPI_Datatype(Xt_redist redist, int rank)
#define xcalloc(nmemb, size)
Definition: ppm_xfuncs.h:64
static MPI_Datatype redist_collection_get_recv_MPI_Datatype(Xt_redist redist, int rank)
Xt_exchanger(* xt_exchanger_default_constructor)(int nsend, int nrecv, struct Xt_redist_msg *send_msgs, struct Xt_redist_msg *recv_msgs, MPI_Comm comm, int tag_offset)
Definition: xt_exchanger.c:59
void xt_exchanger_delete(Xt_exchanger exchanger)
Definition: xt_exchanger.c:70
static void compute_displ(const void *const *data, unsigned num_redists, MPI_Aint displacements[num_redists], MPI_Comm comm)
redistribution of data
static size_t lookup_cache_index(unsigned num_redists, const MPI_Aint src_displacements[num_redists], const MPI_Aint dst_displacements[num_redists], const MPI_Aint(*cached_src_displacements)[num_redists], const MPI_Aint(*cached_dst_displacements)[num_redists], size_t cache_size)
static void redist_collection_delete(Xt_redist redist)
#define XT_UNUSED(x)
Definition: core.h:84
struct Xt_redist_collection_ * Xt_redist_collection
MPI_Datatype datatype
static void copy_component_dt(struct redist_collection_msg **msgs, unsigned *nmsgs, Xt_redist *redists, unsigned num_redists, enum xt_msg_direction direction, MPI_Datatype(*get_MPI_datatype)(Xt_redist, int))
const struct xt_redist_vtable * vtable
MPI_Aint * src_displacements
static void destruct_cache(struct exchanger_cache *cache, size_t cache_size, size_t ntx, MPI_Comm comm)
static void redist_collection_s_exchange(Xt_redist redist, int num_src_arrays, const void **src_data, void **dst_data)
static MPI_Comm redist_collection_get_MPI_Comm(Xt_redist redist)
MPI_Comm xt_mpi_comm_smart_dup(MPI_Comm comm, int *tag_offset)
Definition: xt_mpi.c:850
static int redist_collection_get_msg_ranks(Xt_redist redist, enum xt_msg_direction direction, int **ranks)
void xt_mpi_comm_smart_dedup(MPI_Comm *comm, int tag_offset)
Definition: xt_mpi.c:901
int xt_redist_get_msg_ranks(Xt_redist redist, enum xt_msg_direction direction, int **ranks)
Definition: xt_redist.c:97
exchanging of data based on information provided by redist&#39;s
#define xt_mpi_call(call, comm)
Definition: xt_mpi.h:68
static Xt_exchanger get_exchanger(const void *const *src_data, void *const *dst_data, struct redist_collection_msg *send_msgs, unsigned num_send_messages, struct redist_collection_msg *recv_msgs, unsigned num_recv_messages, unsigned num_redists, struct exchanger_cache *cache, size_t cache_size, MPI_Comm comm, int tag_offset)
MPI_Aint * dst_displacements
struct redist_collection_msg * recv_msgs
static void init_cache(struct exchanger_cache *cache, size_t cache_size, size_t ntx, unsigned num_redists)
static void copy_msgs(size_t num_redists, unsigned nmsgs, const struct redist_collection_msg *restrict msgs_orig, struct redist_collection_msg **p_msgs_copy, MPI_Comm comm)
#define xmalloc(size)
Definition: ppm_xfuncs.h:66
void(* xt_sort_int)(int *a, size_t n)
Definition: xt_sort.c:53
size_t xt_ranks_uniq_count(size_t num_rank_sets, size_t *restrict num_ranks, const int *ranks[num_rank_sets])
Definition: xt_redist.c:152
Xt_exchanger * exchangers
int MPI_Comm
Definition: core.h:64
utility routines for MPI
static const struct xt_redist_vtable redist_collection_vtable