Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_xmap_dist_dir_common.c
Go to the documentation of this file.
1 
15 /*
16  * Keywords:
17  * Maintainer: Jörg Behrens <behrens@dkrz.de>
18  * Moritz Hanke <hanke@dkrz.de>
19  * Thomas Jahns <jahns@dkrz.de>
20  * URL: https://doc.redmine.dkrz.de/yaxt/html/
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions are
24  * met:
25  *
26  * Redistributions of source code must retain the above copyright notice,
27  * this list of conditions and the following disclaimer.
28  *
29  * Redistributions in binary form must reproduce the above copyright
30  * notice, this list of conditions and the following disclaimer in the
31  * documentation and/or other materials provided with the distribution.
32  *
33  * Neither the name of the DKRZ GmbH nor the names of its contributors
34  * may be used to endorse or promote products derived from this software
35  * without specific prior written permission.
36  *
37  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
38  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
39  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
40  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
41  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
45  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
46  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49 #ifdef HAVE_CONFIG_H
50 #include <config.h>
51 #endif
52 
53 #include <string.h>
54 
55 #include "core/ppm_xfuncs.h"
56 #include "xt/xt_idxstripes.h"
57 #include "xt/xt_mpi.h"
58 #include "xt/xt_xmap_dist_dir.h"
60 #include "xt_arithmetic_util.h"
62 #include "ensure_array_size.h"
63 #include "xt_idxstripes_internal.h"
64 
66  size_t num_entries
67  = dist_dir->num_entries > 0
68  ? (size_t)dist_dir->num_entries : (size_t)0;
69  struct Xt_com_list *entries = dist_dir->entries;
70  for (size_t i = 0; i < num_entries; ++i)
71  xt_idxlist_delete(entries[i].list);
72  free(dist_dir);
73 }
74 
116  struct Xt_stripe **stripes_,
117  size_t *stripes_array_size,
118  int dist_dir_rank)
119 {
120  Xt_int global_interval = bucket_params->global_interval;
121  Xt_int local_interval = bucket_params->local_interval;
122  Xt_int local_index_range_lbound = bucket_params->local_index_range_lbound;
123  Xt_int local_index_range_ubound = bucket_params->local_index_range_ubound;
124  int num_stripes = 0;
125 
126  /* find first index in bucket of dist_dir_rank
127  <= local_index_range_lbound */
128  Xt_int start = (Xt_int)(0 + dist_dir_rank * local_interval);
129  {
130  long long start_correction
131  = (long long)local_index_range_lbound - (long long)start;
132  Xt_int corr_steps
133  = (Xt_int)((start_correction
134  - (llsign_mask(start_correction)
135  & (long long)(global_interval - 1)))
136  / (long long)global_interval);
137  start = (Xt_int)(start + corr_steps * global_interval);
138  }
139  /* next find last stripe in bucket of dist_dir_rank
140  * <= local_index_range_ubound */
141  Xt_int end
142  = (Xt_int)(start
143  + (((long long)local_index_range_ubound - (long long)start)
144  / global_interval) * global_interval);
145  Xt_int use_start_stripe
146  = (Xt_int)(start + local_interval > local_index_range_lbound);
147  num_stripes = (int)(((long long)end - (long long)start)/global_interval)
148  + (int)use_start_stripe;
149  start = (Xt_int)(start
150  + ((Xt_int)((Xt_uint)use_start_stripe - (Xt_uint)1)
151  & global_interval));
152  if (!num_stripes)
153  return NULL;
154 
155  struct Xt_stripe *restrict stripes = *stripes_;
156  ENSURE_ARRAY_SIZE(stripes, *stripes_array_size, (size_t)num_stripes);
157 
158  for (int j = 0; j < num_stripes; ++j) {
159 
160  stripes[j].start = (Xt_int)(start + j * global_interval);
161  stripes[j].stride = 1;
162  stripes[j].nstrides = (int)local_interval;
163  }
164 
165  *stripes_ = stripes;
166  return xt_idxstripes_prealloc_new(stripes, num_stripes);
167 }
168 
169 struct Xt_xmdd_txstat
171  void *restrict send_buffer,
172  size_t send_size_asize, size_t send_size_entry,
173  int tag, MPI_Comm comm, int rank_lim,
174  MPI_Request *restrict requests,
175  const int (*send_size)[send_size_asize])
176 {
177  size_t offset = 0;
178  size_t reqOfs = 0;
179 
180  // pack the intersections into the send buffer
181  for (size_t rank = 0; rank < (size_t)rank_lim; ++rank)
182  if (send_size[rank][send_size_entry] > 0) {
183  xt_mpi_call(MPI_Isend((char *)send_buffer + offset,
184  send_size[rank][send_size_entry],
185  MPI_PACKED, (int)rank, tag,
186  comm, requests + reqOfs),
187  comm);
188  ++reqOfs;
189  offset += (size_t)send_size[rank][send_size_entry];
190  }
191  return (struct Xt_xmdd_txstat){ .bytes = offset, .num_msg = reqOfs };
192 }
193 
194 size_t
195 xt_xmap_dist_dir_match_src_dst(const struct dist_dir *src_dist_dir,
196  const struct dist_dir *dst_dist_dir,
197  struct isect **src_dst_intersections)
198 {
199  struct isect (*src_dst_intersections_)
200  = (*src_dst_intersections)
201  = xmalloc((size_t)src_dist_dir->num_entries
202  * (size_t)dst_dist_dir->num_entries
203  * sizeof(**src_dst_intersections));
204  size_t isect_fill = 0;
205  const struct Xt_com_list *restrict entries_src = src_dist_dir->entries,
206  *restrict entries_dst = dst_dist_dir->entries;
207  size_t num_entries_src = (size_t)src_dist_dir->num_entries,
208  num_entries_dst = (size_t)dst_dist_dir->num_entries;
209  for (size_t i = 0; i < num_entries_src; ++i)
210  for (size_t j = 0; j < num_entries_dst; ++j)
211  {
212  Xt_idxlist intersection
213  = xt_idxlist_get_intersection(entries_src[i].list, entries_dst[j].list);
214  if (xt_idxlist_get_num_indices(intersection) > 0) {
215  src_dst_intersections_[isect_fill]
216  = (struct isect){
217  .rank = { [xt_xmdd_direction_src]=entries_src[i].rank,
218  [xt_xmdd_direction_dst]=entries_dst[j].rank},
219  .idxlist = intersection };
220  ++isect_fill;
221  } else
222  xt_idxlist_delete(intersection);
223  }
224  *src_dst_intersections
225  = xrealloc(src_dst_intersections_,
226  isect_fill * sizeof (*src_dst_intersections_));
227  return isect_fill;
228 }
229 
230 
231 int
233  enum xt_xmdd_direction target,
234  size_t num_intersections,
235  const struct isect *restrict src_dst_intersections,
236  bool isect_idxlist_delete,
237  void *buffer, int buf_size, int *position, MPI_Comm comm)
238 {
239  int prev_send_rank = -1;
240  int num_send_indices_requests = 0;
241  size_t origin = 1 - target;
242  for (size_t i = 0; i < num_intersections; ++i)
243  {
244  /* see if this generates a new request? */
245  int send_rank = src_dst_intersections[i].rank[target];
246  num_send_indices_requests += send_rank != prev_send_rank;
247  prev_send_rank = send_rank;
248 
249  // pack rank
250  xt_mpi_call(MPI_Pack((void *)(src_dst_intersections[i].rank + origin),
251  1, MPI_INT, buffer, buf_size, position,
252  comm), comm);
253  // pack intersection
254  xt_idxlist_pack(src_dst_intersections[i].idxlist, buffer,
255  buf_size, position, comm);
256 
257  if (isect_idxlist_delete)
258  xt_idxlist_delete(src_dst_intersections[i].idxlist);
259  }
260  return num_send_indices_requests;
261 }
262 
263 
264 static int
265 stripe_cmp(const void *a, const void *b)
266 {
267  typedef const struct Xt_stripe *csx;
268  return (((csx)a)->start > ((csx)b)->start)
269  - (((csx)b)->start > ((csx)a)->start);
270 }
271 
272 /*
273  * @param dist_dir_results contains the intersections of this ranks
274  * dst or src idxlist with other ranks in bucket-sized chunks, the
275  * chunks belonging to the same communication partner are merged
276  * in-place here, i.e. on return (*dist_dir_results)->num_entries is
277  * less than or equal to the previous count and *dist_dir_results
278  * might point somewhere else
279  */
280 void
281 xt_xmap_dist_dir_same_rank_merge(struct dist_dir **dist_dir_results) {
282 
283  struct Xt_com_list *restrict entries = (*dist_dir_results)->entries;
284  size_t num_isect_agg = 0;
285 
286  size_t i = 0, num_shards = (size_t)(*dist_dir_results)->num_entries;
287  while (i < num_shards) {
288  int rank = entries[i].rank;
289  size_t j = i;
290  /* find all entries matching the currently considered rank */
291  do
292  ++j;
293  while (j < num_shards && entries[j].rank == rank);
294 
295  struct Xt_stripe *restrict stripes = NULL;
296  size_t num_stripes = 0;
297  for (; i < j; ++i) {
298  struct Xt_stripe *stripes_of_intersection;
299  int num_stripes_of_intersection;
300  xt_idxlist_get_index_stripes(entries[i].list,
301  &stripes_of_intersection,
302  &num_stripes_of_intersection);
303  xt_idxlist_delete(entries[i].list);
304  if (stripes) {
305  stripes = xrealloc(stripes,
306  (num_stripes + (size_t)num_stripes_of_intersection)
307  * sizeof (*stripes));
308  memcpy(stripes + num_stripes, stripes_of_intersection,
309  (size_t)num_stripes_of_intersection * sizeof (*stripes));
310  free(stripes_of_intersection);
311  } else
312  stripes = stripes_of_intersection;
313  num_stripes += (size_t)num_stripes_of_intersection;
314  }
315  qsort(stripes, num_stripes, sizeof (*stripes), stripe_cmp);
316  entries[num_isect_agg].list = xt_idxstripes_new(stripes, (int)num_stripes);
317  free(stripes);
318  entries[num_isect_agg].rank = rank;
319  ++num_isect_agg;
320  }
321  (*dist_dir_results)->num_entries = (int)num_isect_agg;
322  *dist_dir_results = xrealloc(*dist_dir_results, sizeof (struct dist_dir)
323  + (size_t)num_isect_agg
324  * sizeof(struct Xt_com_list));
325 }
326 
327 
328 int
329 xt_xmdd_cmp_isect_src_rank(const void *a_, const void *b_)
330 {
331  const struct isect *a = a_, *b = b_;
332  /* this is safe vs. overflow because ranks are in [0..MAX_INT) */
333  return a->rank[xt_xmdd_direction_src] - b->rank[xt_xmdd_direction_src];
334 }
335 
336 int
337 xt_xmdd_cmp_isect_dst_rank(const void *a_, const void *b_)
338 {
339  const struct isect *a = a_, *b = b_;
340  /* this is safe vs. overflow because ranks are in [0..MAX_INT) */
341  return a->rank[xt_xmdd_direction_dst] - b->rank[xt_xmdd_direction_dst];
342 }
343 
344 int
345 xt_com_list_rank_cmp(const void *a_, const void *b_)
346 {
347  const struct Xt_com_list *a = a_, *b = b_;
348  /* this is overflow-safe because rank's are non-negative ints */
349  return a->rank - b->rank;
350 }
351 
352 
354  MPI_Comm comm)
355 {
356  int is_inter;
357  xt_mpi_call(MPI_Comm_test_inter(comm, &is_inter), comm);
358  Xt_xmap xmap;
359  if (!is_inter)
360  xmap = xt_xmap_dist_dir_intracomm_new(src_idxlist, dst_idxlist, comm);
361  else {
362  MPI_Comm merge_comm, local_intra_comm;
363  MPI_Group local_group;
364  xt_mpi_call(MPI_Comm_group(comm, &local_group), comm);
365  xt_mpi_call(MPI_Intercomm_merge(comm, 0, &merge_comm), comm);
366  xt_mpi_call(MPI_Comm_create(merge_comm, local_group, &local_intra_comm),
367  comm);
368  xt_mpi_call(MPI_Group_free(&local_group), comm);
369  xt_mpi_call(MPI_Comm_free(&merge_comm), comm);
370  xt_mpi_comm_mark_exclusive(local_intra_comm);
371 
372  xmap = xt_xmap_dist_dir_intercomm_new(src_idxlist, dst_idxlist,
373  comm, local_intra_comm);
374 
375  xt_mpi_call(MPI_Comm_free(&local_intra_comm), local_intra_comm);
376  }
377  return xmap;
378 }
379 
380 
381 /*
382  * Local Variables:
383  * c-basic-offset: 2
384  * coding: utf-8
385  * indent-tabs-mode: nil
386  * show-trailing-whitespace: t
387  * require-trailing-newline: t
388  * End:
389  */
int xt_idxlist_get_num_indices(Xt_idxlist idxlist)
Definition: xt_idxlist.c:97
Uitlity functions for creation of distributed directories.
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_)
Xt_idxlist xt_idxstripes_prealloc_new(const struct Xt_stripe *stripes, int num_stripes)
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
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])
void xt_mpi_comm_mark_exclusive(MPI_Comm comm)
Definition: xt_mpi.c:918
void xt_idxlist_delete(Xt_idxlist idxlist)
Definition: xt_idxlist.c:73
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
Xt_xmap xt_xmap_dist_dir_new(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
void xt_idxlist_get_index_stripes(Xt_idxlist idxlist, struct Xt_stripe **stripes, int *num_stripes)
Definition: xt_idxlist.c:117
#define xrealloc(ptr, size)
Definition: ppm_xfuncs.h:67
Xt_xmap xt_xmap_dist_dir_intercomm_new(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm inter_comm, MPI_Comm intra_comm)
void xt_xmap_dist_dir_same_rank_merge(struct dist_dir **dist_dir_results)
XT_INT Xt_int
Definition: xt_core.h:68
Xt_idxlist idxlist
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_)
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
unsigned XT_INT Xt_uint
Definition: xt_core.h:70
static int stripe_cmp(const void *a, const void *b)
Xt_xmap xt_xmap_dist_dir_intracomm_new(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
struct Xt_com_list entries[]
Xt_int start
Definition: xt_stripe.h:55
static long long llsign_mask(long long x)
#define xt_mpi_call(call, comm)
Definition: xt_mpi.h:68
Xt_idxlist xt_idxstripes_new(struct Xt_stripe const *stripes, int num_stripes)
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
Xt_idxlist xt_idxlist_get_intersection(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst)