Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_xmap_intersection.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 <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <assert.h>
54 #include <limits.h>
55 
56 #include <mpi.h>
57 
58 #include "xt/xt_idxlist.h"
59 #include "xt/xt_idxvec.h"
60 #include "xt/xt_xmap.h"
61 #include "xt_xmap_internal.h"
62 #include "xt/xt_mpi.h"
63 #include "xt_mpi_internal.h"
64 #include "core/core.h"
65 #include "core/ppm_xfuncs.h"
67 #include "ensure_array_size.h"
68 #include "xt_arithmetic_util.h"
69 
73 static void
75 static void
80 static void xmap_intersection_delete(Xt_xmap xmap);
83 static int const *
85 static int
87 static const struct Xt_pos_ext *
89 static int
94 
95 
96 static const struct Xt_xmap_iter_vtable
101  .get_num_transfer_pos = xmap_intersection_iterator_get_num_transfer_pos,
102  .get_transfer_pos_ext = xmap_intersection_iterator_get_transfer_pos_ext,
103  .get_num_transfer_pos_ext
106 
108 
110 
111  const struct Xt_xmap_iter_vtable * vtable;
112 
113  struct exchange_data * msg;
115 };
116 
117 static inline Xt_xmap_iter_intersection
118 xmii(void *iter)
119 {
120  return (Xt_xmap_iter_intersection)iter;
121 }
122 
123 
126  .get_num_destinations = xmap_intersection_get_num_destinations,
127  .get_num_sources = xmap_intersection_get_num_sources,
128  .get_destination_ranks = xmap_intersection_get_destination_ranks,
129  .get_source_ranks = xmap_intersection_get_source_ranks,
130  .get_out_iterator = xmap_intersection_get_out_iterator,
131  .get_in_iterator = xmap_intersection_get_in_iterator,
132  .copy = xmap_intersection_copy,
133  .delete = xmap_intersection_delete,
134  .get_max_src_pos = xmap_intersection_get_max_src_pos,
135  .get_max_dst_pos = xmap_intersection_get_max_dst_pos};
136 
138  // list of relative positions in memory to send or receive
141  int num_transfer_pos, num_transfer_pos_ext;
142  int rank;
143 };
144 
146 
147  const struct Xt_xmap_vtable * vtable;
148 
149  struct exchange_data *in_msg, *out_msg;
150  int n_in, n_out;
151 
152  // we need the max position in order to enable quick range-checks
153  // for xmap-users like redist
154  int max_src_pos; // max possible pos over all src transfer_pos (always >= 0)
155  int max_dst_pos; // same for dst
156  int tag_offset; /* add to make tags on same communicator non-overlapping */
157 
159 };
160 
162 
163 static inline Xt_xmap_intersection
164 xmi(void *xmap)
165 {
166  return (Xt_xmap_intersection)xmap;
167 }
168 
170 
171  Xt_xmap_intersection xmap_intersection = xmi(xmap);
172 
173  return xmap_intersection->comm;
174 }
175 
177 
178  Xt_xmap_intersection xmap_intersection = xmi(xmap);
179 
180  // the number of destinations equals the number of source messages
181  return xmap_intersection->n_out;
182 }
183 
185 
186  Xt_xmap_intersection xmap_intersection = xmi(xmap);
187 
188  // the number of sources equals the number of destination messages
189  return xmap_intersection->n_in;
190 }
191 
192 static void xmap_intersection_get_destination_ranks(Xt_xmap xmap, int * ranks) {
193 
194  Xt_xmap_intersection xmap_intersection = xmi(xmap);
195 
196  for (int i = 0; i < xmap_intersection->n_out; ++i)
197  ranks[i] = xmap_intersection->out_msg[i].rank;
198 }
199 
200 static void xmap_intersection_get_source_ranks(Xt_xmap xmap, int * ranks) {
201 
202  Xt_xmap_intersection xmap_intersection = xmi(xmap);
203 
204  for (int i = 0; i < xmap_intersection->n_in; ++i)
205  ranks[i] = xmap_intersection->in_msg[i].rank;
206 }
207 
208 enum {
209  bitsPerCoverageElement = sizeof (unsigned long) * CHAR_BIT,
210 };
211 
212 struct pos_run {
213  size_t len;
214  int start, direction;
215 };
216 
217 /* how many pos values have monotonically either positively or
218  * negatively consecutive values */
219 static inline struct pos_run
220 get_pos_run_len(size_t num_pos, const int *restrict pos)
221 {
222  size_t i = 0, j = 1;
223  int direction = 0;
224  int start = pos[0];
225  if (j < num_pos) {
226  direction = isign_mask(pos[1] - pos[0]);
227  while (j < num_pos
228  && pos[j] == start + (~direction & (int)(j - i)) + (direction & -(int)(j - i)))
229  ++j;
230  direction = direction & ((j == 1) - 1);
231  }
232  return (struct pos_run){ .start = start, .len = j, .direction = direction };
233 }
234 
235 
236 /* compute number of position extents that would be required
237  to represent transfer positions array */
238 static size_t
239 count_transfer_pos_ext(size_t intersection_size,
240  const int *restrict intersection_pos)
241 {
242  size_t i = 0, num_transfer_pos_ext = 0;
243  while (i < intersection_size) {
244  i += get_pos_run_len(intersection_size - i, intersection_pos + i).len;
245  ++num_transfer_pos_ext;
246  }
247  return num_transfer_pos_ext;
248 }
249 
250 /* compute list positions for recv direction */
251 static int
252 generate_dir_transfer_pos_dst(int num_intersections,
253  const struct Xt_com_list
254  intersections[num_intersections],
255  Xt_idxlist mypart_idxlist,
256  int *resCount,
257  struct exchange_data **resSets,
258  Xt_int ** indices_to_remove,
259  int *num_indices_to_remove_per_intersection)
260 {
261  struct exchange_data *restrict resSets_
262  = *resSets = xmalloc((size_t)num_intersections * sizeof(**resSets));
263 
264  int mypart_num_indices = xt_idxlist_get_num_indices(mypart_idxlist);
265  size_t coverage_size = (size_t)mypart_num_indices;
266  coverage_size = (coverage_size + bitsPerCoverageElement - 1)
268  unsigned long *restrict coverage = xcalloc(coverage_size, sizeof(*coverage));
269  /* set uncovered top-most bits to ease later comparison */
270  if (mypart_num_indices%bitsPerCoverageElement)
271  coverage[coverage_size-1]
272  = ~((1UL << (mypart_num_indices%bitsPerCoverageElement)) - 1UL);
273 
274  int new_num_intersections = 0;
275  size_t total_num_indices_to_remove = 0;
276  size_t curr_indices_to_remove_size = 0;
277  Xt_int *restrict indices_to_remove_ = *indices_to_remove;
278  int *restrict intersection_pos = NULL;
279 
280  for (int i = 0; i < num_intersections; ++i) {
281 
282  const Xt_int *restrict intersection_idxvec
283  = xt_idxlist_get_indices_const(intersections[i].list);
284  int max_intersection_size
285  = xt_idxlist_get_num_indices(intersections[i].list);
286  intersection_pos
287  = xrealloc(intersection_pos,
288  (size_t)max_intersection_size * sizeof(*intersection_pos));
289 
291  mypart_idxlist, intersection_idxvec, max_intersection_size,
292  intersection_pos, 1);
293  assert(retval == 0);
294 
295  // we have to enforce single_match_only not only within a single
296  // intersection, but also between all intersections
297 
298  int intersection_size = 0;
299  int num_indices_to_remove_isect = 0;
300 
301  /* at most intersection_size many indices need to be removed */
302  ENSURE_ARRAY_SIZE(indices_to_remove_, curr_indices_to_remove_size,
303  total_num_indices_to_remove
304  + (size_t)max_intersection_size);
305 
306  for (int j = 0; j < max_intersection_size; ++j) {
307 
308  int pos = intersection_pos[j];
309  /* the predicate effectively conditionalizes adding of either
310  * the position to intersection_pos
311  * if the current value was NOT already in another intersection
312  * or
313  * the index to indices_to_remove_
314  * if the current value was already in another intersection
315  */
316  unsigned long mask = 1UL << (pos % bitsPerCoverageElement);
317  int predicate = (coverage[pos/bitsPerCoverageElement] & mask) != 0UL;
318  intersection_pos[intersection_size] = pos;
319  indices_to_remove_[total_num_indices_to_remove
320  + (size_t)num_indices_to_remove_isect]
321  = intersection_idxvec[j];
322  intersection_size += predicate ^ 1;
323  num_indices_to_remove_isect += predicate;
324  coverage[pos/bitsPerCoverageElement] |= mask;
325  }
326 
327  total_num_indices_to_remove += (size_t)num_indices_to_remove_isect;
328  num_indices_to_remove_per_intersection[i] = num_indices_to_remove_isect;
329 
330  if (intersection_size > 0) {
331  resSets_[new_num_intersections].transfer_pos = intersection_pos;
332  resSets_[new_num_intersections].num_transfer_pos = intersection_size;
333  resSets_[new_num_intersections].transfer_pos_ext_cache = NULL;
334  resSets_[new_num_intersections].num_transfer_pos_ext
335  = (int)count_transfer_pos_ext((size_t)intersection_size,
336  intersection_pos);
337  resSets_[new_num_intersections].rank = intersections[i].rank;
338  new_num_intersections++;
339  intersection_pos = NULL;
340  }
341  }
342  free(intersection_pos);
343 
344  *indices_to_remove = xrealloc(indices_to_remove_,
345  (size_t)total_num_indices_to_remove
346  * sizeof (**indices_to_remove));
347  *resCount = new_num_intersections;
348  if (num_intersections != new_num_intersections)
349  *resSets = xrealloc(resSets_,
350  (size_t)new_num_intersections * sizeof(**resSets));
351 
352  // check resulting bit map
353  unsigned long all_bits_set = ~0UL;
354  for (size_t i = 0; i < coverage_size; ++i)
355  all_bits_set &= coverage[i];
356 
357  free(coverage);
358  return all_bits_set == ~0UL;
359 }
360 
361 /* compute list positions for send direction */
362 static void
363 generate_dir_transfer_pos_src(int num_intersections,
364  const struct Xt_com_list
365  intersections[num_intersections],
366  Xt_idxlist mypart_idxlist,
367  int *resCount,
368  struct exchange_data **resSets,
369  Xt_int * indices_to_remove,
370  int * num_indices_to_remove_per_intersection)
371 {
372 
373  struct exchange_data *restrict resSets_ = *resSets
374  = xmalloc((size_t)num_intersections * sizeof(**resSets));
375 
376  int new_num_intersections = 0;
377  int offset = 0;
378 
379  Xt_int * new_intersection_idxvec = NULL;
380  size_t curr_new_intersection_idxvec_size = 0;
381  int *restrict intersection_pos = NULL;
382 
383  for (int i = 0; i < num_intersections; ++i) {
384 
385  const Xt_int *restrict intersection_idxvec
386  = xt_idxlist_get_indices_const(intersections[i].list);
387  int intersection_size
388  = xt_idxlist_get_num_indices(intersections[i].list);
389  intersection_pos = xrealloc(intersection_pos,
390  (size_t)intersection_size
391  * sizeof(*intersection_pos));
392 
393  int num_indices_to_remove = num_indices_to_remove_per_intersection[i];
394  if (num_indices_to_remove > 0) {
395 
397  new_intersection_idxvec, curr_new_intersection_idxvec_size,
398  intersection_size - num_indices_to_remove + 1);
399  int new_intersection_size = 0;
400 
401  for (int j = 0; j < intersection_size; ++j) {
402 
403  int discard = 0;
404 
405  Xt_int idx = intersection_idxvec[j];
406  /* could be improved with BLOOM-filter if
407  * num_indices_to_remove was sufficiently large */
408  for (int k = 0; k < num_indices_to_remove; ++k)
409  discard |= (idx == indices_to_remove[offset + k]);
410 
411  new_intersection_idxvec[new_intersection_size] = idx;
412  new_intersection_size += !discard;
413  }
414 
415  intersection_idxvec = new_intersection_idxvec;
416  intersection_size = new_intersection_size;
417  offset = offset + num_indices_to_remove;
418  }
419 
420  int retval;
422  mypart_idxlist, intersection_idxvec, intersection_size,
423  intersection_pos, 0);
424  assert(retval == 0);
425 
426  if (intersection_size > 0) {
427  resSets_[new_num_intersections].transfer_pos = intersection_pos;
428  resSets_[new_num_intersections].num_transfer_pos = intersection_size;
429  resSets_[new_num_intersections].transfer_pos_ext_cache = NULL;
430  resSets_[new_num_intersections].num_transfer_pos_ext
431  = (int)count_transfer_pos_ext((size_t)intersection_size,
432  intersection_pos);
433  resSets_[new_num_intersections].rank = intersections[i].rank;
434  new_num_intersections++;
435  intersection_pos = NULL;
436  }
437  }
438 
439  free(new_intersection_idxvec);
440  free(intersection_pos);
441 
442  *resCount = new_num_intersections;
443  if (num_intersections != new_num_intersections)
444  *resSets = xrealloc(resSets_,
445  (size_t)new_num_intersections * sizeof(**resSets));
446 }
447 
448 static void
449 exchange_points_to_remove(int num_src_intersections,
450  const struct Xt_com_list
451  src_com[num_src_intersections],
452  int num_dst_intersections,
453  const struct Xt_com_list
454  dst_com[num_dst_intersections],
455  Xt_int ** src_indices_to_remove,
456  int *restrict num_src_indices_to_remove_per_intersection,
457  Xt_int * dst_indices_to_remove,
458  int *restrict num_dst_indices_to_remove_per_intersection,
459  int tag_offset,
460  MPI_Comm comm) {
461 
462  MPI_Request * requests
463  = xmalloc((size_t)(num_src_intersections + 2 * num_dst_intersections) *
464  sizeof(*requests));
465  MPI_Request *restrict recv_requests = requests,
466  *restrict send_header_requests = requests + num_src_intersections,
467  *restrict send_data_requests = send_header_requests + num_dst_intersections;
468 
469  // set up receives for indices that need to be removed from the send messages
470  for (int i = 0; i < num_src_intersections; ++i)
471  xt_mpi_call(MPI_Irecv(
472  num_src_indices_to_remove_per_intersection + i, 1, MPI_INT,
473  src_com[i].rank,
475  comm, recv_requests+i), comm);
476 
477  // send indices that need to be removed on the target side due to duplicated
478  // receives
479  int offset = 0;
480  unsigned num_nonempty_dst_intersections = 0;
481  for (int i = 0; i < num_dst_intersections; ++i) {
482  xt_mpi_call(MPI_Isend(
483  num_dst_indices_to_remove_per_intersection + i, 1, MPI_INT,
484  dst_com[i].rank,
486  comm, send_header_requests + i), comm);
487 
488  if (num_dst_indices_to_remove_per_intersection[i] > 0) {
489 
490  xt_mpi_call(MPI_Isend(
491  dst_indices_to_remove + offset,
492  num_dst_indices_to_remove_per_intersection[i], Xt_int_dt,
493  dst_com[i].rank,
495  comm, send_data_requests + num_nonempty_dst_intersections),
496  comm);
497  offset += num_dst_indices_to_remove_per_intersection[i];
498  ++num_nonempty_dst_intersections;
499  }
500  }
501 
502  // wait for the receiving of headers to complete
503  xt_mpi_call(MPI_Waitall(num_src_intersections + num_dst_intersections,
504  recv_requests, MPI_STATUSES_IGNORE), comm);
505 
506  size_t total_num_src_indices_to_recv = 0;
507 
508  for (int i = 0; i < num_src_intersections; ++i)
509  total_num_src_indices_to_recv
510  += (size_t)num_src_indices_to_remove_per_intersection[i];
511 
512  unsigned num_nonempty_src_intersections = 0;
513  if (total_num_src_indices_to_recv > 0) {
514 
515  *src_indices_to_remove = xmalloc(total_num_src_indices_to_recv
516  * sizeof(**src_indices_to_remove));
517 
518  // set up receive for indices that need to be removed
519  offset = 0;
520  for (int i = 0; i < num_src_intersections; ++i)
521  if (num_src_indices_to_remove_per_intersection[i] > 0) {
522  xt_mpi_call(MPI_Irecv(
523  (*src_indices_to_remove) + offset,
524  num_src_indices_to_remove_per_intersection[i],
525  Xt_int_dt, src_com[i].rank,
527  comm,
528  recv_requests + num_nonempty_src_intersections), comm);
529 
530  offset = offset
531  + num_src_indices_to_remove_per_intersection[i];
532  ++num_nonempty_src_intersections;
533  }
534 
535  } else {
536  *src_indices_to_remove = NULL;
537  }
538 
539  /* move data request handles for compact wait */
540  memcpy(recv_requests + num_nonempty_src_intersections, send_data_requests,
541  num_nonempty_dst_intersections * sizeof (recv_requests[0]));
542 
543  // wait until all communication is completed
544  xt_mpi_call(MPI_Waitall((int)num_nonempty_src_intersections
545  + (int)num_nonempty_dst_intersections,
546  requests, MPI_STATUSES_IGNORE), comm);
547 
548  free(requests);
549 }
550 
551 static int
553  int num_src_intersections,
554  const struct Xt_com_list src_com[num_src_intersections],
555  int num_dst_intersections,
556  const struct Xt_com_list dst_com[num_dst_intersections],
557  Xt_idxlist src_idxlist_local,
558  Xt_idxlist dst_idxlist_local,
559  MPI_Comm comm) {
560 
561  int * num_src_indices_to_remove_per_intersection =
562  xmalloc((size_t)num_src_intersections
563  * sizeof(*num_src_indices_to_remove_per_intersection));
564  int * num_dst_indices_to_remove_per_intersection =
565  xmalloc((size_t)num_dst_intersections
566  * sizeof(*num_dst_indices_to_remove_per_intersection));
567  Xt_int * src_indices_to_remove = NULL, * dst_indices_to_remove = NULL;
568 
569  int all_dst_covered = generate_dir_transfer_pos_dst(
570  num_dst_intersections, dst_com, dst_idxlist_local,
571  &(xmap->n_in), &(xmap->in_msg), &dst_indices_to_remove,
572  num_dst_indices_to_remove_per_intersection);
573 
574  // exchange the points that need to be removed
576  num_src_intersections, src_com, num_dst_intersections, dst_com,
577  &src_indices_to_remove, num_src_indices_to_remove_per_intersection,
578  dst_indices_to_remove, num_dst_indices_to_remove_per_intersection,
579  xmap->tag_offset, comm);
580 
581  free(dst_indices_to_remove);
582  free(num_dst_indices_to_remove_per_intersection);
583 
585  num_src_intersections, src_com, src_idxlist_local,
586  &(xmap->n_out), &(xmap->out_msg),
587  src_indices_to_remove, num_src_indices_to_remove_per_intersection);
588 
589  free(src_indices_to_remove);
590  free(num_src_indices_to_remove_per_intersection);
591  return all_dst_covered;
592 }
593 
594 Xt_xmap
595 xt_xmap_intersection_new(int num_src_intersections,
596  const struct Xt_com_list
597  src_com[num_src_intersections],
598  int num_dst_intersections,
599  const struct Xt_com_list
600  dst_com[num_dst_intersections],
601  Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist,
602  MPI_Comm comm) {
603 
604  Xt_xmap_intersection xmap = xmalloc(sizeof (*xmap));
605 
607 
608  xmap->comm = comm = xt_mpi_comm_smart_dup(comm, &xmap->tag_offset);
609 
610  // generate exchange lists
611  if (!generate_transfer_pos(xmap,
612  num_src_intersections, src_com,
613  num_dst_intersections, dst_com,
614  src_idxlist, dst_idxlist, comm)) {
615 
616  int num_dst_indices = xt_idxlist_get_num_indices(dst_idxlist);
617  const Xt_int *dst_indices = xt_idxlist_get_indices_const(dst_idxlist);
618  int * found_index_mask = xcalloc((size_t)num_dst_indices,
619  sizeof(*found_index_mask));
620  int * index_positions = xmalloc((size_t)num_dst_indices
621  * sizeof(*index_positions));
622 
623  for (size_t i = 0; i < (size_t)num_dst_intersections; ++i) {
624  xt_idxlist_get_positions_of_indices(dst_com[i].list, dst_indices,
625  num_dst_indices, index_positions, 0);
626  for (size_t j = 0; j < (size_t)num_dst_indices; ++j)
627  found_index_mask[j] |= index_positions[j] != -1;
628  }
629 
630  int first_missing_pos = 0;
631  while ((first_missing_pos < (num_dst_indices - 1)) &&
632  (found_index_mask[first_missing_pos])) ++first_missing_pos;
633 
634  Xt_int missing_index;
635  xt_idxlist_get_index_at_position(dst_idxlist, first_missing_pos,
636  &missing_index);
637 
638  char error_message[1024];
639  sprintf(error_message, "ERROR: destination intersections do not match "
640  "with destination index list (first missing index %lld "
641  "at position %d)", (long long)missing_index, first_missing_pos);
642  Xt_abort(comm, error_message, __FILE__, __LINE__);
643  }
644 
645  // we could also calculate the (more precise) max pos using only xmap data
646  // but using this simple estimate we are still okay for usage checks
647  xmap->max_src_pos = xt_idxlist_get_num_indices(src_idxlist);
648  xmap->max_dst_pos = xt_idxlist_get_num_indices(dst_idxlist);
649 
650  return (Xt_xmap)xmap;
651 }
652 
654  return xmi(xmap)->max_src_pos;
655 }
656 
658  return xmi(xmap)->max_dst_pos;
659 }
660 
661 
662 static void
663 xmap_intersection_msg_copy(size_t nmsg, struct exchange_data *restrict msg,
664  int *nmsg_copy, struct exchange_data **msg_copy) {
665  *nmsg_copy = (int)nmsg;
666  struct exchange_data *restrict msg_copy_
667  = *msg_copy = xmalloc(sizeof (*msg_copy_) * nmsg);
668  for (size_t i = 0; i < nmsg; ++i) {
669  size_t num_transfer_pos
670  = (size_t)(msg_copy_[i].num_transfer_pos = msg[i].num_transfer_pos);
671  msg_copy_[i].num_transfer_pos_ext = msg[i].num_transfer_pos_ext;
672  msg_copy_[i].rank = msg[i].rank;
673  msg_copy_[i].transfer_pos_ext_cache = NULL;
674  size_t size_transfer_pos
675  = num_transfer_pos * sizeof (*(msg[i].transfer_pos));
676  msg_copy_[i].transfer_pos = xmalloc(size_transfer_pos);
677  memcpy(msg_copy_[i].transfer_pos, msg[i].transfer_pos, size_transfer_pos);
678  }
679 }
680 
681 static Xt_xmap
683 {
684  Xt_xmap_intersection xmap_intersection = xmi(xmap),
685  xmap_intersection_new = xmalloc(sizeof (*xmap_intersection_new));
686  xmap_intersection_new->vtable = xmap_intersection->vtable;
687  size_t n_in = (size_t)(xmap_intersection_new->n_in = xmap_intersection->n_in),
688  n_out = (size_t)(xmap_intersection_new->n_out = xmap_intersection->n_out);
689  xmap_intersection_new->max_src_pos = xmap_intersection->max_src_pos;
690  xmap_intersection_new->max_dst_pos = xmap_intersection->max_dst_pos;
691  xmap_intersection_msg_copy(n_in, xmap_intersection->in_msg,
692  &xmap_intersection_new->n_in,
693  &xmap_intersection_new->in_msg);
694  xmap_intersection_msg_copy(n_out, xmap_intersection->out_msg,
695  &xmap_intersection_new->n_out,
696  &xmap_intersection_new->out_msg);
697  xmap_intersection_new->comm
698  = xt_mpi_comm_smart_dup(xmap_intersection->comm,
699  &xmap_intersection_new->tag_offset);
700  return (Xt_xmap)xmap_intersection_new;
701 }
702 
703 
704 static void
706  for (int i = 0; i < nmsg; ++i)
707  {
708  free(msg[i].transfer_pos_ext_cache);
709  free(msg[i].transfer_pos);
710  }
711  free(msg);
712 }
713 
715 
716  Xt_xmap_intersection xmap_intersection = xmi(xmap);
717 
718  xmap_intersection_msg_delete(xmap_intersection->n_in,
719  xmap_intersection->in_msg);
720  xmap_intersection_msg_delete(xmap_intersection->n_out,
721  xmap_intersection->out_msg);
722  xt_mpi_comm_smart_dedup(&xmap_intersection->comm,
723  xmap_intersection->tag_offset);
724  free(xmap_intersection);
725 }
726 
728 
729  Xt_xmap_intersection xmap_intersection = xmi(xmap);
730 
731  if (xmap_intersection->n_in == 0)
732  return NULL;
733 
734  Xt_xmap_iter_intersection iter = xmalloc(sizeof (*iter));
735 
737  iter->msg = xmap_intersection->in_msg;
738  iter->msgs_left = xmap_intersection->n_in - 1;
739 
740  return (Xt_xmap_iter)iter;
741 }
742 
744 
745  Xt_xmap_intersection xmap_intersection = xmi(xmap);
746 
747  if (xmap_intersection->n_out == 0)
748  return NULL;
749 
750  Xt_xmap_iter_intersection iter = xmalloc(sizeof (*iter));
751 
753  iter->msg = xmap_intersection->out_msg;
754  iter->msgs_left = xmap_intersection->n_out - 1;
755 
756  return (Xt_xmap_iter)iter;
757 }
758 
760 
761  Xt_xmap_iter_intersection iter_intersection = xmii(iter);
762 
763  if (iter_intersection == NULL || iter_intersection->msgs_left == 0)
764  return 0;
765 
766  iter_intersection->msg++;
767  iter_intersection->msgs_left--;
768 
769  return 1;
770 }
771 
773 
774  assert(iter != NULL);
775  return xmii(iter)->msg->rank;
776 }
777 
778 static int const *
780 
781  assert(iter != NULL);
782  return xmii(iter)->msg->transfer_pos;
783 }
784 
785 static const struct Xt_pos_ext *
787 
788  assert(iter != NULL);
789  if (!xmii(iter)->msg->transfer_pos_ext_cache)
790  {
791  size_t i = 0, n = (size_t)xmii(iter)->msg->num_transfer_pos,
792  num_transfer_pos_ext = 0;
793  const int *restrict transfer_pos = xmii(iter)->msg->transfer_pos;
794  struct Xt_pos_ext *restrict transfer_pos_ext
795  = xmalloc((size_t)xmii(iter)->msg->num_transfer_pos_ext
796  * sizeof (transfer_pos_ext[0]));
797  while (i < n)
798  {
799  struct pos_run rn = get_pos_run_len(n - i, transfer_pos + i);
800  transfer_pos_ext[num_transfer_pos_ext]
801  = (struct Xt_pos_ext){ .start = rn.start,
802  .size = (rn.direction*2 + 1) * (int)rn.len };
803  ++num_transfer_pos_ext;
804  i += rn.len;
805  }
806  assert(xmii(iter)->msg->num_transfer_pos_ext == (int)num_transfer_pos_ext);
807  xmii(iter)->msg->transfer_pos_ext_cache = transfer_pos_ext;
808  }
809  return xmii(iter)->msg->transfer_pos_ext_cache;
810 }
811 
812 static int
814  assert(iter != NULL);
815  return xmii(iter)->msg->num_transfer_pos_ext;
816 }
817 
818 static int
820 
821  assert(iter != NULL);
822  return xmii(iter)->msg->num_transfer_pos;
823 }
824 
826 
827  free(iter);
828 }
829 
830 /*
831  * Local Variables:
832  * c-basic-offset: 2
833  * coding: utf-8
834  * indent-tabs-mode: nil
835  * show-trailing-whitespace: t
836  * require-trailing-newline: t
837  * End:
838  */
static int generate_dir_transfer_pos_dst(int num_intersections, const struct Xt_com_list intersections[num_intersections], Xt_idxlist mypart_idxlist, int *resCount, struct exchange_data **resSets, Xt_int **indices_to_remove, int *num_indices_to_remove_per_intersection)
static int xmap_intersection_get_max_src_pos(Xt_xmap xmap)
int xt_idxlist_get_num_indices(Xt_idxlist idxlist)
Definition: xt_idxlist.c:97
static void xmap_intersection_get_destination_ranks(Xt_xmap xmap, int *ranks)
static const struct Xt_xmap_iter_vtable xmap_iterator_intersection_vtable
struct exchange_data * in_msg
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)
int(* next)(Xt_xmap_iter iter)
static void xmap_intersection_get_source_ranks(Xt_xmap xmap, int *ranks)
add versions of standard API functions not returning on error
static int xmap_intersection_iterator_next(Xt_xmap_iter iter)
static int generate_transfer_pos(struct Xt_xmap_intersection_ *xmap, 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_local, Xt_idxlist dst_idxlist_local, MPI_Comm comm)
static Xt_xmap xmap_intersection_copy(Xt_xmap xmap)
contains declaration for the exchange map data structure
static Xt_xmap_iter xmap_intersection_get_in_iterator(Xt_xmap xmap)
static void xmap_intersection_iterator_delete(Xt_xmap_iter iter)
static void exchange_points_to_remove(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_int **src_indices_to_remove, int *restrict num_src_indices_to_remove_per_intersection, Xt_int *dst_indices_to_remove, int *restrict num_dst_indices_to_remove_per_intersection, int tag_offset, MPI_Comm comm)
struct exchange_data * msg
static struct pos_run get_pos_run_len(size_t num_pos, const int *restrict pos)
int xt_idxlist_get_positions_of_indices(Xt_idxlist idxlist, const Xt_int *indices, int num_indices, int *positions, int single_match_only)
Definition: xt_idxlist.c:192
#define xrealloc(ptr, size)
Definition: ppm_xfuncs.h:67
static size_t count_transfer_pos_ext(size_t intersection_size, const int *restrict intersection_pos)
exchange map declarations
int xt_idxlist_get_index_at_position(Xt_idxlist idxlist, int position, Xt_int *index)
Definition: xt_idxlist.c:147
MPI_Comm(* get_communicator)(Xt_xmap)
static Xt_xmap_intersection xmi(void *xmap)
static int const * xmap_intersection_iterator_get_transfer_pos(Xt_xmap_iter iter)
XT_INT Xt_int
Definition: xt_core.h:68
#define xcalloc(nmemb, size)
Definition: ppm_xfuncs.h:64
static int isign_mask(int x)
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
static void xmap_intersection_msg_copy(size_t nmsg, struct exchange_data *restrict msg, int *nmsg_copy, struct exchange_data **msg_copy)
static void generate_dir_transfer_pos_src(int num_intersections, const struct Xt_com_list intersections[num_intersections], Xt_idxlist mypart_idxlist, int *resCount, struct exchange_data **resSets, Xt_int *indices_to_remove, int *num_indices_to_remove_per_intersection)
static const struct Xt_pos_ext * xmap_intersection_iterator_get_transfer_pos_ext(Xt_xmap_iter iter)
static void xmap_intersection_msg_delete(int nmsg, struct exchange_data *msg)
static int xmap_intersection_iterator_get_num_transfer_pos_ext(Xt_xmap_iter iter)
#define Xt_int_dt
Definition: xt_core.h:69
static int xmap_intersection_iterator_get_num_transfer_pos(Xt_xmap_iter iter)
struct Xt_xmap_intersection_ * Xt_xmap_intersection
static int xmap_intersection_get_num_destinations(Xt_xmap xmap)
MPI_Comm xt_mpi_comm_smart_dup(MPI_Comm comm, int *tag_offset)
Definition: xt_mpi.c:850
struct Xt_pos_ext * transfer_pos_ext_cache
static int xmap_intersection_iterator_get_rank(Xt_xmap_iter iter)
void xt_mpi_comm_smart_dedup(MPI_Comm *comm, int tag_offset)
Definition: xt_mpi.c:901
struct Xt_xmap_iter_intersection_ * Xt_xmap_iter_intersection
static int xmap_intersection_get_max_dst_pos(Xt_xmap xmap)
struct exchange_data * out_msg
#define xt_mpi_call(call, comm)
Definition: xt_mpi.h:68
static Xt_xmap_iter_intersection xmii(void *iter)
index list declaration
const struct Xt_xmap_vtable * vtable
const Xt_int * xt_idxlist_get_indices_const(Xt_idxlist idxlist)
Definition: xt_idxlist.c:107
const struct Xt_xmap_iter_vtable * vtable
static const struct Xt_xmap_vtable xmap_intersection_vtable
static void xmap_intersection_delete(Xt_xmap xmap)
#define xmalloc(size)
Definition: ppm_xfuncs.h:66
int MPI_Comm
Definition: core.h:64
utility routines for MPI
static Xt_xmap_iter xmap_intersection_get_out_iterator(Xt_xmap xmap)
static MPI_Comm xmap_intersection_get_communicator(Xt_xmap xmap)
static int xmap_intersection_get_num_sources(Xt_xmap xmap)