Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_xmap_dist_dir.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 <stdbool.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <assert.h>
55 #include <limits.h>
56 
57 #include <mpi.h>
58 
59 #include "xt/xt_idxlist.h"
61 #include "xt/xt_idxvec.h"
62 #include "xt/xt_idxstripes.h"
63 #include "xt/xt_idxempty.h"
64 #include "xt/xt_xmap.h"
65 #include "xt/xt_xmap_dist_dir.h"
66 #include "xt/xt_mpi.h"
67 #include "xt_mpi_internal.h"
68 #include "core/core.h"
69 #include "core/ppm_xfuncs.h"
71 #include "xt_idxlist_internal.h"
72 #include "instr.h"
74 
75 static inline Xt_int
77  bool *stripify, MPI_Comm comm, int comm_size)
78 {
79  unsigned long long local_vals[2], global_sums[2];
80 
81  unsigned num_indices_src = (unsigned)xt_idxlist_get_num_indices(src);
82  local_vals[0] = num_indices_src;
83  local_vals[1] = (num_indices_src >= CHEAP_VECTOR_SIZE)
85 
86  xt_mpi_call(MPI_Allreduce(local_vals, global_sums, 2,
87  MPI_UNSIGNED_LONG_LONG, MPI_SUM, comm), comm);
88 
89  *stripify = global_sums[1] > 0;
90  return (Xt_int)(((global_sums[0] + (unsigned)comm_size - 1)
91  / (unsigned)comm_size) * (unsigned)comm_size);
92 }
93 
95 
96  int num_a = xt_idxlist_get_num_indices(a),
97  num_b = xt_idxlist_get_num_indices(b);
98  Xt_int min_index_a = num_a ? xt_idxlist_get_min_index(a) : XT_INT_MAX,
99  min_index_b = num_b ? xt_idxlist_get_min_index(b) : XT_INT_MAX,
100  min_index = (Xt_int)MIN(min_index_a, min_index_b);
101  return min_index;
102 }
103 
105 
106  int num_a = xt_idxlist_get_num_indices(a),
107  num_b = xt_idxlist_get_num_indices(b);
108  Xt_int max_index_a = num_a ? xt_idxlist_get_max_index(a) : XT_INT_MIN,
109  max_index_b = num_b ? xt_idxlist_get_max_index(b) : XT_INT_MIN,
110  max_index = MAX(max_index_a, max_index_b);
111  return max_index;
112 }
113 
114 static struct bucket_params
115 get_bucket_params(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist,
116  bool *stripify, MPI_Comm comm, int comm_size)
117 {
119  = get_dist_dir_global_interval_size(src_idxlist, dst_idxlist, stripify,
120  comm, comm_size);
121  /* guard vs. comm_size being larger than number of indices */
122  Xt_int local_interval = MAX((Xt_int)1, (Xt_int)(global_interval / comm_size));
124  = get_min_idxlist_index(src_idxlist, dst_idxlist);
126  = get_max_idxlist_index(src_idxlist, dst_idxlist);
127  return (struct bucket_params){
128  .global_interval = global_interval,
129  .local_interval = local_interval,
130  .local_index_range_lbound = local_index_range_lbound,
131  .local_index_range_ubound = local_index_range_ubound,
132  };
133 }
134 
135 enum {
141 };
142 
143 static inline void
144 rank_no_send(size_t rank, int (*restrict send_size)[SEND_SIZE_ASIZE])
145 {
146  send_size[rank][SEND_SIZE_SRC] = 0;
147  send_size[rank][SEND_NUM_SRC] = 0;
148  send_size[rank][SEND_SIZE_DST] = 0;
149  send_size[rank][SEND_NUM_DST] = 0;
150 }
151 
152 static int
154  Xt_idxlist src_idxlist,
155  Xt_idxlist dst_idxlist,
156  int (*send_size)[SEND_SIZE_ASIZE],
157  void **send_buffer_,
158  MPI_Comm comm, int comm_size) {
159 
160 
161  int num_msg = 0;
164  if (local_index_range_lbound <= local_index_range_ubound) {
165  int send_buffer_size = 0;
166  Xt_idxlist *restrict send_list_dst
167  = xmalloc(2 * (size_t)comm_size * sizeof(*send_list_dst)),
168  *restrict send_list_src = send_list_dst + (size_t)comm_size;
169  struct Xt_stripe *stripes = NULL;
170  size_t stripes_array_size = 0;
171  Xt_int global_interval = bucket_params->global_interval;
172  Xt_int local_interval = bucket_params->local_interval;
173  size_t first_overlapping_bucket = 0;
174  /* is it impossible for early buckets to overlap our lists? */
175  if (local_index_range_lbound >= 0
176  && (local_index_range_ubound < global_interval)) {
177  first_overlapping_bucket
178  = (size_t)(local_index_range_lbound / local_interval);
179  for (size_t i = 0; i < first_overlapping_bucket; ++i)
180  rank_no_send(i, send_size);
181  }
182  /* is it impossible for later ranks to overlap our lists? */
183  size_t start_of_non_overlapping_bucket_suffix
184  = (size_t)(((long long)local_index_range_ubound + local_interval - 1)
185  / local_interval) + 1;
186  if (local_index_range_lbound < 0
187  || start_of_non_overlapping_bucket_suffix > (size_t)comm_size)
188  start_of_non_overlapping_bucket_suffix = (size_t)comm_size;
189  size_t i = first_overlapping_bucket;
190  size_t num_src_msg = 0, num_dst_msg = 0;
191  for (; i < (size_t)start_of_non_overlapping_bucket_suffix; ++i) {
192  Xt_idxlist bucket
193  = xt_xmap_dist_dir_get_bucket(bucket_params,
194  &stripes, &stripes_array_size, (int)i);
195  if (bucket) {
196  Xt_idxlist send4src = xt_idxlist_get_intersection(src_idxlist, bucket);
197  if (xt_idxlist_get_num_indices(send4src) > 0) {
198  send_list_src[num_src_msg] = send4src;
199  send_size[i][SEND_SIZE_SRC]
200  = (int)xt_idxlist_get_pack_size(send4src, comm);
201  send_size[i][SEND_NUM_SRC] = 1;
202  ++num_src_msg;
203  } else {
204  send_size[i][SEND_SIZE_SRC] = 0;
205  send_size[i][SEND_NUM_SRC] = 0;
206  xt_idxlist_delete(send4src);
207  }
208 
209  Xt_idxlist send4dst = xt_idxlist_get_intersection(bucket, dst_idxlist);
210  xt_idxlist_delete(bucket);
211  if (xt_idxlist_get_num_indices(send4dst) > 0) {
212  send_list_dst[num_dst_msg] = send4dst;
213  send_size[i][SEND_SIZE_DST]
214  = (int)xt_idxlist_get_pack_size(send4dst, comm);
215  send_size[i][SEND_NUM_DST] = 1;
216  ++num_dst_msg;
217  } else {
218  send_size[i][SEND_SIZE_DST] = 0;
219  send_size[i][SEND_NUM_DST] = 0;
220  xt_idxlist_delete(send4dst);
221  }
222  } else
223  rank_no_send(i, send_size);
224 
225  send_buffer_size
226  += send_size[i][SEND_SIZE_SRC] + send_size[i][SEND_SIZE_DST];
227  }
228  for (; i < (size_t)comm_size; ++i)
229  rank_no_send(i, send_size);
230 
231  void *send_buffer
232  = *send_buffer_ = xrealloc(stripes, (size_t)send_buffer_size);
233 
234  int position = 0;
235  for (i = 0; i < num_src_msg; ++i) {
236  xt_idxlist_pack(send_list_src[i], send_buffer, send_buffer_size,
237  &position, comm);
238  xt_idxlist_delete(send_list_src[i]);
239  }
240 
241  for (i = 0; i < num_dst_msg; ++i) {
242  xt_idxlist_pack(send_list_dst[i], send_buffer, send_buffer_size,
243  &position, comm);
244  xt_idxlist_delete(send_list_dst[i]);
245  }
246  free(send_list_dst);
247  num_msg = (int)(num_src_msg + num_dst_msg);
248  } else
249  memset(send_size, 0, (size_t)comm_size * sizeof (*send_size));
250  return num_msg;
251 }
252 
253 static void
255  int recv_count, void * recv_buffer, int tag,
256  MPI_Comm comm) {
257 
258  // initialize distributed directories
259  int total_recv_size = 0;
260 
261  for (int i = 0; i < recv_count; ++i)
262  {
263  MPI_Status status;
264 
265  xt_mpi_call(MPI_Recv(recv_buffer, recv_size, MPI_PACKED, MPI_ANY_SOURCE,
266  tag, comm, &status), comm);
267 
268  int received_count;
269  xt_mpi_call(MPI_Get_count(&status, MPI_PACKED, &received_count), comm);
270 
271  int position = 0;
272 
273  dist_dir->entries[i].rank = status.MPI_SOURCE;
274  dist_dir->entries[i].list =
275  xt_idxlist_unpack(recv_buffer, received_count, &position, comm);
276 
277  total_recv_size += received_count;
278  }
279 
280  if (total_recv_size != recv_size)
281  Xt_abort(comm, "ERROR: recv_intersections received wrong number of bytes",
282  __FILE__, __LINE__);
283  dist_dir->num_entries = recv_count;
284 }
285 
286 static void send_intersections(void *send_buffer,
287  const int (*send_size)[SEND_SIZE_ASIZE],
288  MPI_Request *dir_init_send_requests,
289  int tag_offset, MPI_Comm comm, int comm_size) {
290  int src_tag = tag_offset + xt_mpi_tag_xmap_dist_dir_src_send;
291  struct Xt_xmdd_txstat txstat
293  SEND_SIZE_ASIZE, SEND_SIZE_SRC,
294  src_tag, comm, comm_size,
295  dir_init_send_requests,
296  send_size);
297  int dst_tag = tag_offset + xt_mpi_tag_xmap_dist_dir_dst_send;
298  xt_xmap_dist_dir_send_intersections((unsigned char *)send_buffer
299  + txstat.bytes,
300  SEND_SIZE_ASIZE, SEND_SIZE_DST,
301  dst_tag, comm, comm_size,
302  dir_init_send_requests + txstat.num_msg,
303  send_size);
304 }
305 
306 static void
308  struct dist_dir **src_dist_dir,
309  struct dist_dir **dst_dist_dir,
310  int tag_offset, MPI_Comm comm) {
311 
312  *src_dist_dir = xmalloc(sizeof (struct dist_dir)
313  + (sizeof (struct Xt_com_list)
314  * (size_t)recv_size[SEND_NUM_SRC]));
315  *dst_dist_dir = xmalloc(sizeof (struct dist_dir)
316  + (sizeof (struct Xt_com_list)
317  * (size_t)recv_size[SEND_NUM_DST]));
318 
319  void * recv_buffer = xmalloc((size_t)MAX(recv_size[SEND_SIZE_SRC],
320  recv_size[SEND_SIZE_DST]));
321 
322  recv_and_unpack_intersection(*src_dist_dir, recv_size[SEND_SIZE_SRC],
323  recv_size[SEND_NUM_SRC], recv_buffer,
325  comm);
326  recv_and_unpack_intersection(*dst_dist_dir, recv_size[SEND_SIZE_DST],
327  recv_size[SEND_NUM_DST], recv_buffer,
329  comm);
330 
331  free(recv_buffer);
332 }
333 
334 
335 static int
336 send_size_from_intersections(size_t num_intersections,
337  const struct isect *restrict src_dst_intersections,
338  MPI_Comm comm, int comm_size,
339  int (*restrict send_size)[SEND_SIZE_ASIZE])
340 {
341  size_t total_send_size = 0;
342  for (int i = 0; i < comm_size; ++i)
343  send_size[i][SEND_SIZE_SRC] = 0, send_size[i][SEND_SIZE_DST] = 0,
344  send_size[i][SEND_NUM_SRC] = 0, send_size[i][SEND_NUM_DST] = 0;
345 
346  int rank_pack_size;
347  xt_mpi_call(MPI_Pack_size(1, MPI_INT, comm, &rank_pack_size), comm);
348 
349  for (size_t i = 0; i < num_intersections; ++i)
350  {
351  int msg_size = rank_pack_size
352  + (int)xt_idxlist_get_pack_size(src_dst_intersections[i].idxlist,
353  comm);
354  size_t src_rank
355  = (size_t)src_dst_intersections[i].rank[xt_xmdd_direction_src],
356  dst_rank = (size_t)src_dst_intersections[i].rank[xt_xmdd_direction_dst];
357  send_size[src_rank][SEND_SIZE_SRC] += msg_size;
358  ++(send_size[src_rank][SEND_NUM_SRC]);
359  send_size[dst_rank][SEND_SIZE_DST] += msg_size;
360  ++(send_size[dst_rank][SEND_NUM_DST]);
361  total_send_size += 2*(size_t)msg_size;
362  }
363  assert(total_send_size <= INT_MAX);
364  return (int)total_send_size;
365 }
366 
367 
368 static int
369 pack_src_dst_dist_dirs(size_t num_intersections,
370  struct isect *restrict src_dst_intersections,
371  int (*send_size)[SEND_SIZE_ASIZE],
372  void **send_buffer_,
373  MPI_Comm comm, int comm_size) {
374 
375  int total_send_size
376  = send_size_from_intersections(num_intersections,
377  src_dst_intersections,
378  comm, comm_size, send_size);
379 
380  void *send_buffer = (*send_buffer_) = xmalloc((size_t)total_send_size);
381  int position = 0;
382  qsort(src_dst_intersections, num_intersections,
383  sizeof (src_dst_intersections[0]), xt_xmdd_cmp_isect_src_rank);
384  int num_send_indices_requests
386  xt_xmdd_direction_src, num_intersections, src_dst_intersections, false,
387  send_buffer, total_send_size, &position, comm);
388 
389  qsort(src_dst_intersections, num_intersections,
390  sizeof (src_dst_intersections[0]), xt_xmdd_cmp_isect_dst_rank);
391  num_send_indices_requests
393  xt_xmdd_direction_dst, num_intersections, src_dst_intersections, true,
394  send_buffer, total_send_size, &position, comm);
395  return num_send_indices_requests;
396 }
397 
408 static void
410  int recv_size[num_sizes],
411  int (*send_size)[num_sizes],
412  MPI_Comm comm) {
413 
414 #if MPI_VERSION > 2 || ( MPI_VERSION == 2 && MPI_SUBVERSION >= 2)
415  xt_mpi_call(MPI_Reduce_scatter_block((int *)send_size, (int *)recv_size,
416  num_sizes, MPI_INT, MPI_SUM,
417  comm), comm);
418 #else
419  int comm_size;
420  xt_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
421 
422  int *recv_count = xmalloc((size_t)comm_size * sizeof(*recv_count));
423  for (int i = 0; i < comm_size; ++i) recv_count[i] = num_sizes;
424 
425  xt_mpi_call(MPI_Reduce_scatter(send_size, recv_size, recv_count, MPI_INT,
426  MPI_SUM, comm), comm);
427 
428  free(recv_count);
429 #endif
430 }
431 
432 static void generate_distributed_directories(struct dist_dir **src_dist_dir,
433  struct dist_dir **dst_dist_dir,
434  bool *stripify,
435  Xt_idxlist src_idxlist,
436  Xt_idxlist dst_idxlist,
437  int tag_offset,
438  MPI_Comm comm, int comm_size) {
439 
440  struct bucket_params bucket_params
441  = get_bucket_params(src_idxlist, dst_idxlist, stripify, comm, comm_size);
442 
443  void *send_buffer = NULL;
444 
445  int (*send_size)[SEND_SIZE_ASIZE]
446  = xmalloc((size_t)comm_size * sizeof(*send_size));
447 
448  int num_msg
449  = compute_and_pack_bucket_intersections(&bucket_params,
450  src_idxlist, dst_idxlist,
451  send_size, &send_buffer,
452  comm, comm_size);
453 
454  int recv_size[SEND_SIZE_ASIZE]; // for src and dst
455 
456  /* get packed intersection sizes to be sent from other ranks */
457  xt_xmap_dist_dir_reduce_scatter_sizes(SEND_SIZE_ASIZE, recv_size, send_size, comm);
458 
459  MPI_Request *dir_init_send_requests
460  = xmalloc((size_t)num_msg * sizeof(*dir_init_send_requests));
461  send_intersections(send_buffer, (const int (*)[SEND_SIZE_ASIZE])send_size,
462  dir_init_send_requests, tag_offset, comm, comm_size);
463 
464  free(send_size);
465 
466  recv_and_unpack_intersections(recv_size, src_dist_dir, dst_dist_dir,
467  tag_offset, comm);
468 
469  // wait for the sends to be completed
470  xt_mpi_call(MPI_Waitall(num_msg, dir_init_send_requests,
471  MPI_STATUSES_IGNORE), comm);
472  free(dir_init_send_requests);
473  free(send_buffer);
474 }
475 
476 static void
478  void *restrict recv_buffer, int tag,
479  MPI_Comm comm)
480 {
481 
482  // initiate distributed directories
483  int num_entries = 0;
484  while (recv_size > 0) {
485 
486  MPI_Status status;
487 
488  xt_mpi_call(MPI_Recv(recv_buffer, recv_size, MPI_PACKED,
489  MPI_ANY_SOURCE, tag, comm, &status), comm);
490 
491  int received_count;
492  xt_mpi_call(MPI_Get_count(&status, MPI_PACKED, &received_count), comm);
493 
494  recv_size -= received_count;
495 
496  int position = 0;
497 
498  while (received_count > position) {
499 
500  xt_mpi_call(MPI_Unpack(recv_buffer, received_count, &position,
501  &dist_dir->entries[num_entries].rank,
502  1, MPI_INT, comm), comm);
503 
504  dist_dir->entries[num_entries].list =
505  xt_idxlist_unpack(recv_buffer, received_count, &position, comm);
506 
507  ++num_entries;
508  }
509  }
510  qsort(dist_dir->entries, (size_t)num_entries, sizeof(*dist_dir->entries),
512 
513  if (0 != recv_size)
514  Xt_abort(comm, "ERROR: recv_and_unpack_dist_dir_result"
515  " received wrong number of bytes", __FILE__, __LINE__);
516 
517  dist_dir->num_entries = num_entries;
518 
519 }
520 
521 
522 static void
524  struct dist_dir **src_intersections,
525  struct dist_dir **dst_intersections,
526  int *num_send_indices_requests,
527  MPI_Request *send_indices_requests,
528  int tag_offset,
529  MPI_Comm comm) {
530 
531  struct dist_dir *src_dist_dir_results
532  = xmalloc(sizeof (struct dist_dir)
533  + (sizeof (struct Xt_com_list)
534  * (size_t)recv_size[SEND_NUM_SRC])),
535  *dst_dist_dir_results
536  = xmalloc(sizeof (struct dist_dir)
537  + (sizeof (struct Xt_com_list)
538  * (size_t)recv_size[SEND_NUM_DST]));
539 
540  void *recv_buffer = xmalloc((size_t)MAX(recv_size[SEND_SIZE_SRC],
541  recv_size[SEND_SIZE_DST]));
542 
543  recv_and_unpack_dist_dir_result(src_dist_dir_results,
544  recv_size[SEND_SIZE_SRC],
545  recv_buffer, tag_offset
547  assert(src_dist_dir_results->num_entries
548  == recv_size[SEND_NUM_SRC]);
549 
550  enum { ops_completed_auto_size = 16 };
551  int ops_completed_auto[ops_completed_auto_size];
552  int *ops_completed
553  = *num_send_indices_requests > ops_completed_auto_size
554  ? xmalloc((size_t)*num_send_indices_requests * sizeof (*ops_completed))
555  : ops_completed_auto;
556  bool all_sends_done
557  = xt_mpi_test_some(num_send_indices_requests, send_indices_requests,
558  ops_completed, comm);
559 
560  recv_and_unpack_dist_dir_result(dst_dist_dir_results,
561  recv_size[SEND_SIZE_DST],
562  recv_buffer, tag_offset
564  assert(dst_dist_dir_results->num_entries
565  == recv_size[SEND_NUM_DST]);
566 
567  if (!all_sends_done)
568  all_sends_done
569  = xt_mpi_test_some(num_send_indices_requests, send_indices_requests,
570  ops_completed, comm);
571  free(recv_buffer);
572 
573  xt_xmap_dist_dir_same_rank_merge(&src_dist_dir_results);
574  *src_intersections = src_dist_dir_results;
575 
576  if (!all_sends_done)
577  all_sends_done
578  = xt_mpi_test_some(num_send_indices_requests, send_indices_requests,
579  ops_completed, comm);
580 
581  xt_xmap_dist_dir_same_rank_merge(&dst_dist_dir_results);
582  *dst_intersections = dst_dist_dir_results;
583  if (ops_completed != ops_completed_auto) free(ops_completed);
584 }
585 
586 static void exchange_idxlists(struct dist_dir **src_intersections,
587  struct dist_dir **dst_intersections,
588  bool *stripify,
589  Xt_idxlist src_idxlist,
590  Xt_idxlist dst_idxlist,
591  int tag_offset,
592  MPI_Comm comm) {
593 
594  int comm_size;
595 
596  xt_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
597 
598  struct dist_dir *src_dist_dir, *dst_dist_dir;
599 
600  generate_distributed_directories(&src_dist_dir, &dst_dist_dir, stripify,
601  src_idxlist, dst_idxlist,
602  tag_offset, comm, comm_size);
603 
604  void * send_buffer;
605 
606  int recv_size[SEND_SIZE_ASIZE], (*send_size)[SEND_SIZE_ASIZE]
607  = xmalloc((size_t)comm_size * sizeof(*send_size));
608 
609  /* match the source and destination entries in the local distributed
610  * directories... */
611  struct isect *src_dst_intersections;
612  size_t num_intersections
613  = xt_xmap_dist_dir_match_src_dst(src_dist_dir, dst_dist_dir,
614  &src_dst_intersections);
615  xt_xmdd_free_dist_dir(src_dist_dir);
616  xt_xmdd_free_dist_dir(dst_dist_dir);
617  /* ... and pack the results into a sendable format */
618  int num_send_indices_requests
619  = pack_src_dst_dist_dirs(num_intersections, src_dst_intersections,
620  send_size, &send_buffer, comm, comm_size);
621  free(src_dst_intersections);
622 
623  // get the data size the local process will receive from other processes
625  send_size, comm);
626 
627  MPI_Request *send_indices_requests
628  = xmalloc((size_t)num_send_indices_requests
629  * sizeof(*send_indices_requests));
630 
631  send_intersections(send_buffer, (const int (*)[SEND_SIZE_ASIZE])send_size,
632  send_indices_requests, tag_offset, comm, comm_size);
633 
635  src_intersections, dst_intersections,
636  &num_send_indices_requests,
637  send_indices_requests,
638  tag_offset, comm);
639 
640  xt_mpi_call(MPI_Waitall(num_send_indices_requests, send_indices_requests,
641  MPI_STATUSES_IGNORE), comm);
642 
643  free(send_buffer);
644  free(send_size);
645  free(send_indices_requests);
646 }
647 
648 Xt_xmap
650  MPI_Comm comm)
651 {
652  INSTR_DEF(this_instr,"xt_xmap_all2all_new")
653  INSTR_START(this_instr);
654 
655  int tag_offset;
656  MPI_Comm newcomm = xt_mpi_comm_smart_dup(comm, &tag_offset);
657 
658  struct dist_dir *src_intersections, *dst_intersections;
659 
660  bool stripify;
661  exchange_idxlists(&src_intersections, &dst_intersections, &stripify,
662  src_idxlist, dst_idxlist, tag_offset, newcomm);
663 
664  Xt_xmap (*xmap_new)(int num_src_intersections,
665  const struct Xt_com_list *src_com,
666  int num_dst_intersections,
667  const struct Xt_com_list *dst_com,
668  Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist,
669  MPI_Comm comm)
671 
672  Xt_xmap xmap
673  = xmap_new(src_intersections->num_entries, src_intersections->entries,
674  dst_intersections->num_entries, dst_intersections->entries,
675  src_idxlist, dst_idxlist, newcomm);
676 
677  xt_mpi_comm_smart_dedup(&newcomm, tag_offset);
678 
679  xt_xmdd_free_dist_dir(src_intersections);
680  xt_xmdd_free_dist_dir(dst_intersections);
681  INSTR_STOP(this_instr);
682  return xmap;
683 }
684 
685 /*
686  * Local Variables:
687  * c-basic-offset: 2
688  * coding: utf-8
689  * indent-tabs-mode: nil
690  * show-trailing-whitespace: t
691  * require-trailing-newline: t
692  * End:
693  */
Xt_idxlist xt_idxlist_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
int xt_idxlist_get_num_indices(Xt_idxlist idxlist)
Definition: xt_idxlist.c:97
#define XT_INT_MAX
Definition: xt_core.h:73
static Xt_int get_min_idxlist_index(Xt_idxlist a, Xt_idxlist b)
struct Xt_xmap_ * Xt_xmap
Definition: xt_core.h:81
Uitlity functions for creation of distributed directories.
Xt_xmap xt_xmap_dist_dir_intracomm_new(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
#define INSTR_START(T)
Definition: instr.h:68
int xt_com_list_rank_cmp(const void *a_, const void *b_)
int xt_xmdd_cmp_isect_dst_rank(const void *a_, const void *b_)
size_t xt_xmap_dist_dir_match_src_dst(const struct dist_dir *src_dist_dir, const struct dist_dir *dst_dist_dir, struct isect **src_dst_intersections)
add versions of standard API functions not returning on error
static void xt_xmap_dist_dir_reduce_scatter_sizes(int num_sizes, int recv_size[num_sizes], int(*send_size)[num_sizes], MPI_Comm comm)
wrapper for MPI_Reduce_scatter_block if available or MPI_Reduce_scatter if not
static void recv_and_unpack_intersections(int recv_size[SEND_SIZE_ASIZE], struct dist_dir **src_dist_dir, struct dist_dir **dst_dist_dir, int tag_offset, MPI_Comm comm)
struct Xt_xmdd_txstat xt_xmap_dist_dir_send_intersections(void *restrict send_buffer, size_t send_size_asize, size_t send_size_entry, int tag, MPI_Comm comm, int rank_lim, MPI_Request *restrict requests, const int(*send_size)[send_size_asize])
bool xt_mpi_test_some(int *restrict num_req, MPI_Request *restrict req, int *restrict ops_completed, MPI_Comm comm)
Definition: xt_mpi.c:929
void xt_idxlist_delete(Xt_idxlist idxlist)
Definition: xt_idxlist.c:73
static void exchange_idxlists(struct dist_dir **src_intersections, struct dist_dir **dst_intersections, bool *stripify, Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, int tag_offset, MPI_Comm comm)
#define MIN(a, b)
Definition: xt_idxstripes.c:75
Xt_idxlist xt_xmap_dist_dir_get_bucket(const struct bucket_params *bucket_params, struct Xt_stripe **stripes_, size_t *stripes_array_size, int dist_dir_rank)
generates the buckets of the distributed directory
static Xt_int get_dist_dir_global_interval_size(Xt_idxlist src, Xt_idxlist dst, bool *stripify, MPI_Comm comm, int comm_size)
Xt_xmap xt_xmap_intersection_new(int num_src_intersections, const struct Xt_com_list src_com[num_src_intersections], int num_dst_intersections, const struct Xt_com_list dst_com[num_dst_intersections], Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
Xt_int xt_idxlist_get_min_index(Xt_idxlist idxlist)
Definition: xt_idxlist.c:296
#define xrealloc(ptr, size)
Definition: ppm_xfuncs.h:67
static void recv_and_unpack_dist_dir_result(struct dist_dir *dist_dir, int recv_size, void *restrict recv_buffer, int tag, MPI_Comm comm)
exchange map declarations
void xt_xmap_dist_dir_same_rank_merge(struct dist_dir **dist_dir_results)
static int compute_and_pack_bucket_intersections(struct bucket_params *bucket_params, Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, int(*send_size)[SEND_SIZE_ASIZE], void **send_buffer_, MPI_Comm comm, int comm_size)
XT_INT Xt_int
Definition: xt_core.h:68
static int pack_src_dst_dist_dirs(size_t num_intersections, struct isect *restrict src_dst_intersections, int(*send_size)[SEND_SIZE_ASIZE], void **send_buffer_, MPI_Comm comm, int comm_size)
static void send_intersections(void *send_buffer, const int(*send_size)[SEND_SIZE_ASIZE], MPI_Request *dir_init_send_requests, int tag_offset, MPI_Comm comm, int comm_size)
Provide non-public declarations common to all index lists.
int xt_xmap_dist_dir_pack_intersections(enum xt_xmdd_direction target, size_t num_intersections, const struct isect *restrict src_dst_intersections, bool isect_idxlist_delete, void *buffer, int buf_size, int *position, MPI_Comm comm)
void xt_xmdd_free_dist_dir(struct dist_dir *dist_dir)
int xt_xmdd_cmp_isect_src_rank(const void *a_, const void *b_)
Xt_int xt_idxlist_get_max_index(Xt_idxlist idxlist)
Definition: xt_idxlist.c:301
static struct bucket_params get_bucket_params(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, bool *stripify, MPI_Comm comm, int comm_size)
Xt_xmap xt_xmap_intersection_ext_new(int num_src_intersections, const struct Xt_com_list src_com[num_src_intersections], int num_dst_intersections, const struct Xt_com_list dst_com[num_dst_intersections], Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
#define INSTR_DEF(T, S)
Definition: instr.h:66
static Xt_int get_max_idxlist_index(Xt_idxlist a, Xt_idxlist b)
static int send_size_from_intersections(size_t num_intersections, const struct isect *restrict src_dst_intersections, MPI_Comm comm, int comm_size, int(*restrict send_size)[SEND_SIZE_ASIZE])
static void recv_and_unpack_intersection(struct dist_dir *dist_dir, int recv_size, int recv_count, void *recv_buffer, int tag, MPI_Comm comm)
struct Xt_com_list entries[]
MPI_Comm xt_mpi_comm_smart_dup(MPI_Comm comm, int *tag_offset)
Definition: xt_mpi.c:850
void xt_mpi_comm_smart_dedup(MPI_Comm *comm, int tag_offset)
Definition: xt_mpi.c:901
size_t xt_idxlist_get_pack_size(Xt_idxlist idxlist, MPI_Comm comm)
Definition: xt_idxlist.c:78
#define xt_mpi_call(call, comm)
Definition: xt_mpi.h:68
#define INSTR_STOP(T)
Definition: instr.h:69
index list declaration
#define XT_INT_MIN
Definition: xt_core.h:74
static void generate_distributed_directories(struct dist_dir **src_dist_dir, struct dist_dir **dst_dist_dir, bool *stripify, Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, int tag_offset, MPI_Comm comm, int comm_size)
void xt_idxlist_pack(Xt_idxlist idxlist, void *buffer, int buffer_size, int *position, MPI_Comm comm)
Definition: xt_idxlist.c:84
#define xmalloc(size)
Definition: ppm_xfuncs.h:66
int MPI_Comm
Definition: core.h:64
utility routines for MPI
static void recv_and_unpack_dist_dir_results(int recv_size[SEND_SIZE_ASIZE], struct dist_dir **src_intersections, struct dist_dir **dst_intersections, int *num_send_indices_requests, MPI_Request *send_indices_requests, int tag_offset, MPI_Comm comm)
static void rank_no_send(size_t rank, int(*restrict send_size)[SEND_SIZE_ASIZE])
#define MAX(a, b)
Definition: xt_idxstripes.c:76
Xt_idxlist xt_idxlist_get_intersection(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst)