Yet Another eXchange Tool  DO_NOT_EDIT_HERE
xt_redist_p2p.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 <assert.h>
53 
54 #include <mpi.h>
55 
56 #include "xt/xt_mpi.h"
57 #include "xt_mpi_internal.h"
58 #include "xt/xt_redist_p2p.h"
59 #include "xt_redist_internal.h"
61 #include "xt/xt_xmap.h"
62 #include "xt/xt_idxlist.h"
63 #include "core/ppm_xfuncs.h"
64 #include "core/core.h"
65 
66 #include "xt_arithmetic_util.h"
67 
68 static MPI_Datatype
69 generate_datatype(const int *transfer_pos, int num_transfer_pos,
70  const int *offsets, MPI_Datatype base_datatype, MPI_Comm comm)
71 {
72 
73  MPI_Datatype type;
74 
75  int const * displ;
76  int * tmp_displ = NULL;
77 
78  if (offsets != NULL) {
79 
80  tmp_displ = xmalloc((size_t)num_transfer_pos * sizeof(int));
81 
82  for (int i = 0; i < num_transfer_pos; ++i)
83  tmp_displ[i] = offsets[transfer_pos[i]];
84 
85  displ = tmp_displ;
86 
87  } else
88  displ = transfer_pos;
89 
90  type = xt_mpi_generate_datatype(displ, num_transfer_pos, base_datatype, comm);
91 
92  free(tmp_displ);
93 
94  return type;
95 }
96 
97 static void
98 generate_msg_infos(int num_msgs, Xt_xmap_iter iter, const int *offsets,
99  MPI_Datatype base_datatype, struct Xt_redist_msg ** msgs,
100  MPI_Comm comm) {
101 
102  if (num_msgs <= 0) {
103  *msgs = NULL;
104  return;
105  }
106 
107  struct Xt_redist_msg *restrict curr_msg
108  = *msgs = xmalloc((size_t)num_msgs * sizeof(**msgs));
109 
110  do {
111 
112  const int *curr_transfer_pos = xt_xmap_iterator_get_transfer_pos(iter);
113  int curr_num_transfer_pos = xt_xmap_iterator_get_num_transfer_pos(iter);
114 
115  curr_msg->datatype
116  = generate_datatype(curr_transfer_pos, curr_num_transfer_pos,
117  offsets, base_datatype, comm);
118  curr_msg->rank = xt_xmap_iterator_get_rank(iter);
119 
120  curr_msg++;
121 
122  } while (xt_xmap_iterator_next(iter));
123 }
124 
125 Xt_redist xt_redist_p2p_off_new(Xt_xmap xmap, const int *src_offsets,
126  const int *dst_offsets, MPI_Datatype datatype) {
127 
128  int nsend, nrecv;
129  struct Xt_redist_msg * send_msgs = NULL;
130  struct Xt_redist_msg * recv_msgs = NULL;
131  MPI_Comm comm;
132  int tag_offset;
133 
134  comm = xt_mpi_comm_smart_dup(xt_xmap_get_communicator(xmap), &tag_offset);
135 
136  nrecv = xt_xmap_get_num_sources(xmap);
137  Xt_xmap_iter dst_iter = xt_xmap_get_in_iterator(xmap);
138  generate_msg_infos(nrecv, dst_iter, dst_offsets, datatype, &recv_msgs,
139  comm);
140  if (dst_iter) xt_xmap_iterator_delete(dst_iter);
141 
142  nsend = xt_xmap_get_num_destinations(xmap);
143  Xt_xmap_iter src_iter = xt_xmap_get_out_iterator(xmap);
144  generate_msg_infos(nsend, src_iter, src_offsets, datatype, &send_msgs,
145  comm);
146  if (src_iter) xt_xmap_iterator_delete(src_iter);
147 
148  Xt_redist result
149  = xt_redist_single_array_base_new(nsend, nrecv, send_msgs, recv_msgs, comm);
150  xt_mpi_comm_smart_dedup(&comm, tag_offset);
151  return result;
152 }
153 
154 /* ====================================================================== */
155 
156 struct ext_disp
157 {
158  int disp, ext_idx;
159 };
160 
161 static inline struct ext_disp
162 pos2disp(int pos, int num_ext, const struct Xt_offset_ext extents[],
163  const int psum_ext_size[])
164 {
165  int j = 0;
166  /* FIXME: use bsearch if linear search is too slow, i.e. num_ext >> 1000 */
167  /* what extent covers the pos'th position? */
168  while (j < num_ext && pos >= psum_ext_size[j + 1])
169  ++j;
170  int disp = extents[j].start + (pos - psum_ext_size[j]) * extents[j].stride;
171  return (struct ext_disp){ .disp = disp, .ext_idx = j };
172 }
173 
174 static inline struct ext_disp
175 pos2disp2(int pos, int num_ext, const struct Xt_offset_ext extents[],
176  const int psum_ext_size[], int start_ext)
177 {
178  int j = start_ext;
179  if (pos < psum_ext_size[j + 1] && pos >= psum_ext_size[j])
180  ;
181  else if (pos < psum_ext_size[j + 1])
182  {
183  j = 0;
184  while (j < start_ext && pos >= psum_ext_size[j + 1])
185  ++j;
186  }
187  else
188  while (j < num_ext && pos >= psum_ext_size[j + 1])
189  ++j;
190  int disp = extents[j].start + (pos - psum_ext_size[j]) * extents[j].stride;
191  return (struct ext_disp){ .disp = disp, .ext_idx = j };
192 }
193 
194 static MPI_Datatype
195 generate_ext_datatype(int num_transfer_pos_ext,
196  const struct Xt_pos_ext transfer_pos_ext[],
197  int num_ext, const struct Xt_offset_ext extents[],
198  const int psum_ext_size[],
199  MPI_Datatype base_datatype, MPI_Comm comm)
200 {
201  if (num_transfer_pos_ext > 0)
202  {
203  size_t size_dt_stripes = 8, num_dt_stripes = 0;
204  struct Xt_offset_ext *dt_stripes
205  = xmalloc(size_dt_stripes * sizeof (*dt_stripes));
206  int i = 0,
207  search_start_ext
208  = pos2disp(transfer_pos_ext[0].start,
209  num_ext, extents, psum_ext_size).ext_idx;
210  do
211  {
212  struct Xt_pos_ext current_pos_ext = transfer_pos_ext[i];
213  if (num_dt_stripes >= size_dt_stripes)
214  {
215  more_stripes:
216  size_dt_stripes *= 2;
217  dt_stripes = xrealloc(dt_stripes,
218  size_dt_stripes * sizeof (*dt_stripes));
219  }
220  do {
221  /* find extent containing start position of current range */
222  struct ext_disp pos = pos2disp2(current_pos_ext.start,
223  num_ext, extents, psum_ext_size,
224  search_start_ext);
225  search_start_ext = pos.ext_idx;
226  struct Xt_offset_ext base_ext = extents[pos.ext_idx],
227  derived_ext;
228  int preceding = psum_ext_size[pos.ext_idx];
229  derived_ext.start
230  = base_ext.start + ((current_pos_ext.start - preceding)
231  * base_ext.stride);
232  int isign_mask_current_pos_ext_size = isign_mask(current_pos_ext.size);
233  /* find number of positions in containing extent,
234  * which precede current_pos_ext.start
235  * if (current_pos_ext.size < 0)
236  * or follow current_pos_ext.start
237  * if (current_pos_ext.size > 0) */
238  derived_ext.size = imin(abs(current_pos_ext.size),
239  (~isign_mask_current_pos_ext_size
240  & (base_ext.size
241  - (current_pos_ext.start - preceding)))
242  | (isign_mask_current_pos_ext_size
243  & (current_pos_ext.start - preceding + 1)));
244  derived_ext.stride
245  = (~isign_mask_current_pos_ext_size & base_ext.stride)
246  | (isign_mask_current_pos_ext_size & -base_ext.stride);
247  dt_stripes[num_dt_stripes++] = derived_ext;
248  current_pos_ext.size
249  += (~isign_mask_current_pos_ext_size & -derived_ext.size)
250  | (isign_mask_current_pos_ext_size & derived_ext.size);
251  current_pos_ext.start += derived_ext.size;
252  } while ((abs(current_pos_ext.size) > 0)
253  & (num_dt_stripes < size_dt_stripes));
254  /* current_pos_ext hasn't been mapped completely, get more
255  * stripe memory */
256  if (abs(current_pos_ext.size) > 0)
257  goto more_stripes;
258  /* only advance current_pos_ext after it has been mapped completely */
259  } while (++i < num_transfer_pos_ext);
260  MPI_Datatype type
261  = xt_mpi_generate_datatype_stripe(dt_stripes, (int)num_dt_stripes,
262  base_datatype, comm);
263  free(dt_stripes);
264  return type;
265  }
266  else
267  return MPI_DATATYPE_NULL;
268 }
269 
270 static void
272  int num_ext,
273  const struct Xt_offset_ext extents[],
274  MPI_Datatype base_datatype,
275  struct Xt_redist_msg **msgs,
276  MPI_Comm comm)
277 {
278  if (num_msgs <= 0) {
279  *msgs = NULL;
280  return;
281  }
282 
283  struct Xt_redist_msg *curr_msg =
284  *msgs = xmalloc((size_t)num_msgs * sizeof(**msgs));
285 
286  /* partial sums of ext sizes */
287  int *psum_ext_size
288  = xmalloc(((size_t)num_ext + 1) * sizeof (psum_ext_size[0]));
289  psum_ext_size[0] = 0;
290  for (size_t i = 0; i < (size_t)num_ext; ++i)
291  psum_ext_size[i + 1] = psum_ext_size[i] + extents[i].size;
292 
293  do {
294 
295  const struct Xt_pos_ext *curr_transfer_pos_ext
297  int curr_num_transfer_pos_ext
299 
300  curr_msg->datatype
301  = generate_ext_datatype(curr_num_transfer_pos_ext, curr_transfer_pos_ext,
302  num_ext, extents, psum_ext_size,
303  base_datatype, comm);
304  curr_msg->rank = xt_xmap_iterator_get_rank(iter);
305 
306  curr_msg++;
307 
308  } while (xt_xmap_iterator_next(iter));
309  free(psum_ext_size);
310 }
311 
313  int num_src_ext,
314  const struct Xt_offset_ext src_extents[],
315  int num_dst_ext,
316  const struct Xt_offset_ext dst_extents[],
317  MPI_Datatype datatype)
318 {
319  struct Xt_redist_msg * send_msgs = NULL;
320  struct Xt_redist_msg * recv_msgs = NULL;
321  MPI_Comm comm;
322  int tag_offset;
323 
324  comm = xt_mpi_comm_smart_dup(xt_xmap_get_communicator(xmap), &tag_offset);
325 
326  int nrecv = xt_xmap_get_num_sources(xmap);
327  Xt_xmap_iter dst_iter = xt_xmap_get_in_iterator(xmap);
328  generate_ext_msg_infos(nrecv, dst_iter, num_dst_ext, dst_extents,
329  datatype, &recv_msgs, comm);
330  if (dst_iter) xt_xmap_iterator_delete(dst_iter);
331 
332  int nsend = xt_xmap_get_num_destinations(xmap);
333  Xt_xmap_iter src_iter = xt_xmap_get_out_iterator(xmap);
334  generate_ext_msg_infos(nsend, src_iter, num_src_ext, src_extents,
335  datatype, &send_msgs, comm);
336  if (src_iter) xt_xmap_iterator_delete(src_iter);
337 
338  Xt_redist result
339  = xt_redist_single_array_base_new(nsend, nrecv, send_msgs, recv_msgs, comm);
340  xt_mpi_comm_smart_dedup(&comm, tag_offset);
341  return result;
342 }
343 
344 /* ====================================================================== */
345 
346 static inline void
347 aux_gen_simple_block_offsets(int block_offsets[], const int block_sizes[],
348  size_t num_blocks) {
349 
350  if (num_blocks > 0) {
351  block_offsets[0] = 0;
352  for (size_t i = 1; i < num_blocks; ++i)
353  block_offsets[i] = block_offsets[i-1] + block_sizes[i-1];
354  }
355 }
356 
357 static MPI_Datatype
358 generate_block_datatype(const int *transfer_pos, int num_transfer_pos,
359  const int *block_offsets, const int *block_sizes,
360  MPI_Datatype base_datatype, MPI_Comm comm) {
361 
362  assert(block_sizes != NULL);
363 
364  int *bdispl_vec
365  = xmalloc(2 * (size_t)num_transfer_pos * sizeof(*bdispl_vec)),
366  *blen_vec = bdispl_vec + num_transfer_pos;
367  assert(block_offsets);
368 
369  for (int i = 0; i < num_transfer_pos; ++i) {
370  int j = transfer_pos[i];
371  bdispl_vec[i] = block_offsets[j];
372  blen_vec[i] = block_sizes[j];
373  }
374 
375  MPI_Datatype type
376  = xt_mpi_generate_datatype_block(bdispl_vec, blen_vec,
377  num_transfer_pos, base_datatype, comm);
378 
379  free(bdispl_vec);
380 
381  return type;
382 }
383 
384 #if defined (__PGIC__) && (__PGIC__ == 15 && __PGIC_MINOR__ == 4)
385 #pragma routine novector
386 #endif
387 static void
389  const int *block_offsets,
390  const int *block_sizes, int **aux_offsets,
391  size_t num_blocks,
392  MPI_Datatype base_datatype,
393  struct Xt_redist_msg **msgs, MPI_Comm comm) {
394 
395  if (num_msgs > 0) {
396 
397  const int *block_offsets_;
398  if (block_offsets)
399  block_offsets_ = block_offsets;
400  else {
401  block_offsets_ = *aux_offsets
402  = xrealloc(*aux_offsets, num_blocks * sizeof(*block_offsets_));
403  aux_gen_simple_block_offsets(*aux_offsets, block_sizes, num_blocks);
404  }
405 
406  struct Xt_redist_msg *curr_msg
407  = *msgs = xmalloc((size_t)num_msgs * sizeof(**msgs));
408 
409  do {
410  const int *curr_transfer_pos = xt_xmap_iterator_get_transfer_pos(iter);
411  int curr_num_transfer_pos = xt_xmap_iterator_get_num_transfer_pos(iter);
412  curr_msg->datatype
413  = generate_block_datatype(curr_transfer_pos, curr_num_transfer_pos,
414  block_offsets_, block_sizes, base_datatype,
415  comm);
416  curr_msg->rank = xt_xmap_iterator_get_rank(iter);
417 
418  curr_msg++;
419  } while (xt_xmap_iterator_next(iter));
420 
421  } else
422  *msgs = NULL;
423 }
424 
425 Xt_redist
427  const int *src_block_offsets,
428  const int *src_block_sizes,
429  int src_block_num,
430  const int *dst_block_offsets,
431  const int *dst_block_sizes,
432  int dst_block_num,
433  MPI_Datatype datatype) {
434 
435  struct Xt_redist_msg * send_msgs = NULL;
436  struct Xt_redist_msg * recv_msgs = NULL;
437 
438  if (!src_block_sizes)
439  die("xt_redist_p2p_blocks_off_new: undefined src_block_sizes");
440  if (!dst_block_sizes)
441  die("xt_redist_p2p_blocks_off_new: undefined dst_block_sizes");
442 
443  int tag_offset;
444  MPI_Comm comm
445  = xt_mpi_comm_smart_dup(xt_xmap_get_communicator(xmap), &tag_offset);
446 
447 
448  int nsend = xt_xmap_get_num_destinations(xmap),
449  nrecv = xt_xmap_get_num_sources(xmap);
450 
451  int *aux_offsets = NULL;
452 
453  Xt_xmap_iter dst_iter = xt_xmap_get_in_iterator(xmap),
454  src_iter = xt_xmap_get_out_iterator(xmap);
455 
456  // dst part:
457  int max_dst_pos = xt_xmap_get_max_dst_pos(xmap);
458  if (dst_block_num < max_dst_pos)
459  die("xt_redist_p2p_blocks_off_new: dst_block_num too small");
460  generate_block_msg_infos(nrecv, dst_iter, dst_block_offsets, dst_block_sizes,
461  &aux_offsets, (size_t)dst_block_num,
462  datatype, &recv_msgs, comm);
463  if (dst_iter) xt_xmap_iterator_delete(dst_iter);
464 
465  // src part:
466  int max_src_pos = xt_xmap_get_max_src_pos(xmap);
467  if (src_block_num < max_src_pos)
468  die("xt_redist_p2p_blocks_off_new: src_block_num too small");
469  generate_block_msg_infos(nsend, src_iter, src_block_offsets, src_block_sizes,
470  &aux_offsets, (size_t)src_block_num,
471  datatype, &send_msgs, comm);
472  free(aux_offsets);
473 
474  if (src_iter) xt_xmap_iterator_delete(src_iter);
475 
476  Xt_redist result
477  = xt_redist_single_array_base_new(nsend, nrecv, send_msgs, recv_msgs, comm);
478  xt_mpi_comm_smart_dedup(&comm, tag_offset);
479  return result;
480 }
481 
483  const int *src_block_sizes,
484  int src_block_num,
485  const int *dst_block_sizes,
486  int dst_block_num,
487  MPI_Datatype datatype) {
488 
489  return xt_redist_p2p_blocks_off_new(xmap,
490  NULL, src_block_sizes, src_block_num,
491  NULL, dst_block_sizes, dst_block_num,
492  datatype);
493 
494 }
495 
496 
498 
499  return xt_redist_p2p_off_new(xmap, NULL, NULL, datatype);
500 }
501 
502 /*
503  * Local Variables:
504  * c-basic-offset: 2
505  * coding: utf-8
506  * indent-tabs-mode: nil
507  * show-trailing-whitespace: t
508  * require-trailing-newline: t
509  * End:
510  */
Xt_xmap_iter xt_xmap_get_out_iterator(Xt_xmap xmap)
Definition: xt_xmap.c:95
int size
Definition: xt_core.h:93
int xt_xmap_get_num_sources(Xt_xmap xmap)
Definition: xt_xmap.c:65
#define die(msg)
Definition: core.h:131
redistribution of data, non-public declarations
static int imin(int a, int b)
add versions of standard API functions not returning on error
const struct Xt_pos_ext * xt_xmap_iterator_get_transfer_pos_ext(Xt_xmap_iter iter)
Definition: xt_xmap.c:121
int xt_xmap_get_max_dst_pos(Xt_xmap xmap)
Definition: xt_xmap.c:138
int xt_xmap_iterator_get_num_transfer_pos(Xt_xmap_iter iter)
Definition: xt_xmap.c:115
int xt_xmap_iterator_get_num_transfer_pos_ext(Xt_xmap_iter iter)
Definition: xt_xmap.c:125
void xt_xmap_iterator_delete(Xt_xmap_iter iter)
Definition: xt_xmap.c:129
static void aux_gen_simple_block_offsets(int block_offsets[], const int block_sizes[], size_t num_blocks)
Xt_redist xt_redist_p2p_new(Xt_xmap xmap, MPI_Datatype datatype)
static struct ext_disp pos2disp2(int pos, int num_ext, const struct Xt_offset_ext extents[], const int psum_ext_size[], int start_ext)
#define xrealloc(ptr, size)
Definition: ppm_xfuncs.h:67
exchange map declarations
Xt_redist xt_redist_p2p_off_new(Xt_xmap xmap, const int *src_offsets, const int *dst_offsets, MPI_Datatype datatype)
int xt_xmap_iterator_get_rank(Xt_xmap_iter iter)
Definition: xt_xmap.c:105
static void generate_msg_infos(int num_msgs, Xt_xmap_iter iter, const int *offsets, MPI_Datatype base_datatype, struct Xt_redist_msg **msgs, MPI_Comm comm)
Definition: xt_redist_p2p.c:98
static int isign_mask(int x)
static MPI_Datatype generate_ext_datatype(int num_transfer_pos_ext, const struct Xt_pos_ext transfer_pos_ext[], int num_ext, const struct Xt_offset_ext extents[], const int psum_ext_size[], MPI_Datatype base_datatype, MPI_Comm comm)
Xt_redist xt_redist_single_array_base_new(int nsend, int nrecv, struct Xt_redist_msg *send_msgs, struct Xt_redist_msg *recv_msgs, MPI_Comm comm)
Xt_redist xt_redist_p2p_blocks_off_new(Xt_xmap xmap, const int *src_block_offsets, const int *src_block_sizes, int src_block_num, const int *dst_block_offsets, const int *dst_block_sizes, int dst_block_num, MPI_Datatype datatype)
static MPI_Datatype generate_block_datatype(const int *transfer_pos, int num_transfer_pos, const int *block_offsets, const int *block_sizes, MPI_Datatype base_datatype, MPI_Comm comm)
int xt_xmap_get_num_destinations(Xt_xmap xmap)
Definition: xt_xmap.c:60
MPI_Datatype datatype
static MPI_Datatype generate_datatype(const int *transfer_pos, int num_transfer_pos, const int *offsets, MPI_Datatype base_datatype, MPI_Comm comm)
Definition: xt_redist_p2p.c:69
Xt_xmap_iter xt_xmap_get_in_iterator(Xt_xmap xmap)
Definition: xt_xmap.c:90
static void generate_ext_msg_infos(int num_msgs, Xt_xmap_iter iter, int num_ext, const struct Xt_offset_ext extents[], MPI_Datatype base_datatype, struct Xt_redist_msg **msgs, MPI_Comm comm)
MPI_Datatype xt_mpi_generate_datatype_stripe(const struct Xt_offset_ext *v, int count, MPI_Datatype old_type, MPI_Comm comm)
MPI_Datatype xt_mpi_generate_datatype(int const *displacements, int count, MPI_Datatype old_type, MPI_Comm comm)
Definition: xt_mpi.c:263
static void generate_block_msg_infos(int num_msgs, Xt_xmap_iter iter, const int *block_offsets, const int *block_sizes, int **aux_offsets, size_t num_blocks, MPI_Datatype base_datatype, struct Xt_redist_msg **msgs, MPI_Comm comm)
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
int const * xt_xmap_iterator_get_transfer_pos(Xt_xmap_iter iter)
Definition: xt_xmap.c:110
Xt_redist xt_redist_p2p_blocks_new(Xt_xmap xmap, const int *src_block_sizes, int src_block_num, const int *dst_block_sizes, int dst_block_num, MPI_Datatype datatype)
index list declaration
static struct ext_disp pos2disp(int pos, int num_ext, const struct Xt_offset_ext extents[], const int psum_ext_size[])
MPI_Comm xt_xmap_get_communicator(Xt_xmap xmap)
Definition: xt_xmap.c:55
Xt_redist xt_redist_p2p_ext_new(Xt_xmap xmap, int num_src_ext, const struct Xt_offset_ext src_extents[], int num_dst_ext, const struct Xt_offset_ext dst_extents[], MPI_Datatype datatype)
int start
Definition: xt_core.h:93
int xt_xmap_iterator_next(Xt_xmap_iter iter)
Definition: xt_xmap.c:100
MPI_Datatype xt_mpi_generate_datatype_block(const int *displacements, const int *blocklengths, int count, MPI_Datatype old_type, MPI_Comm comm)
Definition: xt_mpi.c:229
int xt_xmap_get_max_src_pos(Xt_xmap xmap)
Definition: xt_xmap.c:134
#define xmalloc(size)
Definition: ppm_xfuncs.h:66
int MPI_Comm
Definition: core.h:64
utility routines for MPI