79 const void **src_data,
void **dst_data);
83 const void *src_data,
void *dst_data);
146 Xt_redist *redists,
unsigned num_redists,
148 MPI_Datatype (*get_MPI_datatype)(
Xt_redist,
int))
150 size_t num_ranks[num_redists], rank_pos[num_redists];
151 int *restrict ranks[num_redists];
152 bool ranks_left =
false;
154 for (
size_t j = 0; j < num_redists; ++j) {
157 (
int **)(ranks + j));
160 ranks_left |= (num_ranks[j] > 0);
164 size_t num_messages = ranks_left
170 MPI_Datatype *restrict dt
171 =
xmalloc(num_messages * num_redists *
sizeof (*dt));
172 p =
xmalloc(num_messages *
sizeof (*p));
173 for (
size_t i = 0; i < num_messages; ++i) {
174 int min_rank = INT_MAX;
175 for (
size_t j = 0; j < num_redists; ++j)
176 if (rank_pos[j] < num_ranks[j] && ranks[j][rank_pos[j]] < min_rank)
177 min_rank = ranks[j][rank_pos[j]];
179 MPI_Datatype *dts_rank = dt + (size_t)num_redists * i;
180 for (
size_t j = 0; j < num_redists; ++j)
182 (rank_pos[j] < num_ranks[j] && ranks[j][rank_pos[j]] == min_rank)
183 ? get_MPI_datatype(redists[j], min_rank) : MPI_DATATYPE_NULL;
185 p[i].rank = min_rank;
186 p[i].component_dt = dts_rank;
187 for (
size_t j = 0; j < num_redists; ++j)
189 += (rank_pos[j] < num_ranks[j] && ranks[j][rank_pos[j]] == min_rank);
192 for (
size_t j = 0; j < num_redists; ++j)
195 *nmsgs = (unsigned)num_messages;
202 unsigned num_redists)
205 size_t num_displ = cache_size * num_redists;
207 for (
size_t i = 0; i < ntx; ++i) msgs[i].
datatype = MPI_DATATYPE_NULL;
209 =
xmalloc(2 * num_displ *
sizeof (*q));
211 for (
size_t i = 0; i < 2 * num_displ; i += num_redists)
218 size_t cache_size,
size_t ntx,
MPI_Comm comm)
220 for (
size_t i = 0; i < cache_size; ++i)
233 Xt_redist_collection redist_coll =
xmalloc(
sizeof (*redist_coll));
236 unsigned num_redists_ = num_redists >= 0 ? (unsigned)num_redists : 0;
238 redist_coll->
ndst = 0;
239 redist_coll->
nsrc = 0;
243 Xt_abort(comm,
"ERROR: invalid cache size in xt_redist_collection_new",
257 (
size_t)redist_coll->
nsrc + (
size_t)redist_coll->
ndst,
266 unsigned num_messages,
unsigned num_redists,
267 const MPI_Aint displacements[num_redists],
271 int block_lengths[num_redists];
273 for (
size_t i = 0; i < num_redists; ++i)
274 block_lengths[i] = 1;
275 for (
size_t i = 0; i < num_messages; ++i) {
276 if (redist_msgs[i].
datatype != MPI_DATATYPE_NULL)
278 redist_msgs[i].datatype
281 redist_msgs[i].rank = msgs[i].
rank;
287 MPI_Aint displacements[num_redists],
291 MPI_Aint base_addr, offset;
292 xt_mpi_call(MPI_Get_address((
void *)data[0], &base_addr), comm);
293 displacements[0] = 0;
294 for (
size_t i = 1; i < num_redists; ++i) {
295 xt_mpi_call(MPI_Get_address((
void *)data[i], &offset), comm);
296 displacements[i] = offset - base_addr;
303 const MPI_Aint src_displacements[num_redists],
304 const MPI_Aint dst_displacements[num_redists],
305 const MPI_Aint (*cached_src_displacements)[num_redists],
306 const MPI_Aint (*cached_dst_displacements)[num_redists],
309 for (
size_t i = 0; i < cache_size &&
310 cached_src_displacements[i][0] == (MPI_Aint)0 &&
311 cached_dst_displacements[i][0] == (MPI_Aint)0; ++i) {
312 bool mismatch =
false;
313 for (
size_t j = 0; j < num_redists; ++j)
314 mismatch |= (src_displacements[j] != cached_src_displacements[i][j]) ||
315 (dst_displacements[j] != cached_dst_displacements[i][j]);
316 if (!mismatch)
return i;
325 unsigned num_redists,
329 MPI_Aint displacements[2][num_redists];
330 compute_displ(src_data, num_redists, displacements[0], comm);
331 compute_displ((
const void *
const *)dst_data, num_redists, displacements[1], comm);
343 if (cache_index == cache_size)
345 cache_index = cache->
token;
347 displacements[0], cache->
msgs, comm);
349 displacements[1], cache->
msgs +
350 (
size_t)num_send_messages, comm);
352 displacements[0], sizeof (displacements[0]));
354 displacements[1], sizeof (displacements[1]));
361 (
int)num_recv_messages,
363 (
size_t)num_send_messages,
366 cache->
token = (cache->
token + 1) % cache_size;
373 size_t nmsg = (size_t)num_send_messages + (
size_t)num_recv_messages;
375 for (
size_t i = 0; i < nmsg; ++i)
379 displacements[0], p, comm);
381 displacements[1], p + num_send_messages, comm);
385 (
int)num_recv_messages,
386 p, p + (
size_t)num_send_messages,
395 static inline Xt_redist_collection
398 return (Xt_redist_collection)redist;
403 const void **src_data,
void **dst_data) {
405 Xt_redist_collection redist_coll =
xrc(redist);
408 Xt_abort(redist_coll->
comm,
"ERROR: wrong number of arrays in " 409 "redist_collection_s_exchange", __FILE__, __LINE__);
418 &(redist_coll->
cache),
436 *p_msgs_copy = nmsgs > 0 ?
xmalloc(nmsgs *
sizeof (*msgs_copy)) : NULL;
437 MPI_Datatype *restrict dt_copy
438 = nmsgs * num_redists > 0
439 ?
xmalloc(nmsgs * num_redists *
sizeof (*dt_copy)) : NULL;
440 for (
size_t i = 0; i < nmsgs; ++i)
442 msgs_copy[i].rank = msgs_orig[i].rank;
443 msgs_copy[i].component_dt = dt_copy + i * num_redists;
444 for (
size_t j = 0; j < num_redists; ++j)
447 dt_copy + i * num_redists + j), comm);
449 dt_copy[i * num_redists + j] = MPI_DATATYPE_NULL;
456 Xt_redist_collection redist_coll =
xrc(redist),
457 redist_copy =
xmalloc(
sizeof (*redist_copy));
458 redist_copy->vtable = redist_coll->
vtable;
460 redist_copy->num_redists = num_redists;
462 MPI_Comm copy_comm = redist_copy->comm
465 unsigned nsrc = redist_coll->
nsrc;
466 redist_copy->nsrc = nsrc;
469 unsigned ndst = redist_coll->
ndst;
470 redist_copy->ndst = ndst;
474 redist_copy->cache_size = cache_size;
475 init_cache(&redist_copy->cache, cache_size, (
size_t)ndst + nsrc, num_redists);
481 unsigned nmsgs,
unsigned num_redists,
485 size_t ndt = (size_t)nmsgs * num_redists;
487 for (
size_t i = 0; i < ndt; ++i)
488 if (all_component_dt[i] != MPI_DATATYPE_NULL)
489 xt_mpi_call(MPI_Type_free(all_component_dt + i), comm);
498 Xt_redist_collection redist_coll =
xrc(redist);
509 (
size_t)redist_coll->
nsrc + (
size_t)redist_coll->
ndst,
520 Xt_redist_collection redist_coll =
xrc(redist);
522 Xt_abort(redist_coll->
comm,
"ERROR: get_send_MPI_Datatype is not" 523 " supported for this xt_redist type (Xt_redist_collection)",
526 return MPI_DATATYPE_NULL;
532 Xt_redist_collection redist_coll =
xrc(redist);
534 Xt_abort(redist_coll->
comm,
"ERROR: get_recv_MPI_Datatype is not" 535 " supported for this xt_redist type (Xt_redist_collection)",
538 return MPI_DATATYPE_NULL;
543 const void *src_data,
void *dst_data)
546 Xt_redist_collection redist_coll =
xrc(redist);
550 Xt_abort(redist_coll->
comm,
"ERROR: s_exchange1 is not implemented for" 551 " this xt_redist type (Xt_redist_collection)", __FILE__, __LINE__);
559 Xt_redist_collection redist_coll =
xrc(redist);
562 if (direction ==
SEND) {
563 nmsg = redist_coll->
ndst;
566 nmsg = redist_coll->
nsrc;
569 int *restrict ranks_ = *ranks =
xmalloc(nmsg *
sizeof (*ranks_));
570 for (
size_t i = 0; i < nmsg; ++i)
571 ranks_[i] = msg[i].
rank;
579 Xt_redist_collection redist_coll =
xrc(redist);
581 return redist_coll->
comm;
struct exchanger_cache cache
void xt_exchanger_s_exchange(Xt_exchanger exchanger, const void *src_data, void *dst_data)
static void redist_collection_s_exchange1(Xt_redist redist, const void *src_data, void *dst_data)
void xt_redist_check_comms(Xt_redist *redists, int num_redists, MPI_Comm comm)
redistribution of data, non-public declarations
Xt_redist(* copy)(Xt_redist)
static Xt_redist redist_collection_copy(Xt_redist redist)
add versions of standard API functions not returning on error
static void create_all_dt_for_dir(struct redist_collection_msg *msgs, unsigned num_messages, unsigned num_redists, const MPI_Aint displacements[num_redists], struct Xt_redist_msg redist_msgs[num_messages], MPI_Comm comm)
MPI_Datatype xt_redist_get_send_MPI_Datatype(Xt_redist redist, int rank)
struct Xt_redist_msg * msgs
MPI_Datatype xt_redist_get_recv_MPI_Datatype(Xt_redist redist, int rank)
struct redist_collection_msg * send_msgs
static void free_redist_collection_msgs(struct redist_collection_msg *msgs, unsigned nmsgs, unsigned num_redists, MPI_Comm comm)
MPI_Datatype xt_create_compound_datatype(size_t num_redists, const MPI_Aint displacements[num_redists], const MPI_Datatype datatypes[num_redists], const int block_lengths[num_redists], MPI_Comm comm)
Xt_redist xt_redist_collection_new(Xt_redist *redists, int num_redists, int cache_size, MPI_Comm comm)
static void xt_redist_msgs_free(size_t n, struct Xt_redist_msg *msgs, MPI_Comm comm)
static Xt_redist_collection xrc(void *redist)
static MPI_Datatype redist_collection_get_send_MPI_Datatype(Xt_redist redist, int rank)
#define xcalloc(nmemb, size)
static MPI_Datatype redist_collection_get_recv_MPI_Datatype(Xt_redist redist, int rank)
Xt_exchanger(* xt_exchanger_default_constructor)(int nsend, int nrecv, struct Xt_redist_msg *send_msgs, struct Xt_redist_msg *recv_msgs, MPI_Comm comm, int tag_offset)
void xt_exchanger_delete(Xt_exchanger exchanger)
static void compute_displ(const void *const *data, unsigned num_redists, MPI_Aint displacements[num_redists], MPI_Comm comm)
static size_t lookup_cache_index(unsigned num_redists, const MPI_Aint src_displacements[num_redists], const MPI_Aint dst_displacements[num_redists], const MPI_Aint(*cached_src_displacements)[num_redists], const MPI_Aint(*cached_dst_displacements)[num_redists], size_t cache_size)
static void redist_collection_delete(Xt_redist redist)
struct Xt_redist_collection_ * Xt_redist_collection
static void copy_component_dt(struct redist_collection_msg **msgs, unsigned *nmsgs, Xt_redist *redists, unsigned num_redists, enum xt_msg_direction direction, MPI_Datatype(*get_MPI_datatype)(Xt_redist, int))
const struct xt_redist_vtable * vtable
MPI_Aint * src_displacements
static void destruct_cache(struct exchanger_cache *cache, size_t cache_size, size_t ntx, MPI_Comm comm)
MPI_Datatype * component_dt
static void redist_collection_s_exchange(Xt_redist redist, int num_src_arrays, const void **src_data, void **dst_data)
static MPI_Comm redist_collection_get_MPI_Comm(Xt_redist redist)
MPI_Comm xt_mpi_comm_smart_dup(MPI_Comm comm, int *tag_offset)
static int redist_collection_get_msg_ranks(Xt_redist redist, enum xt_msg_direction direction, int **ranks)
void xt_mpi_comm_smart_dedup(MPI_Comm *comm, int tag_offset)
int xt_redist_get_msg_ranks(Xt_redist redist, enum xt_msg_direction direction, int **ranks)
exchanging of data based on information provided by redist's
#define xt_mpi_call(call, comm)
static Xt_exchanger get_exchanger(const void *const *src_data, void *const *dst_data, struct redist_collection_msg *send_msgs, unsigned num_send_messages, struct redist_collection_msg *recv_msgs, unsigned num_recv_messages, unsigned num_redists, struct exchanger_cache *cache, size_t cache_size, MPI_Comm comm, int tag_offset)
MPI_Aint * dst_displacements
struct redist_collection_msg * recv_msgs
static void init_cache(struct exchanger_cache *cache, size_t cache_size, size_t ntx, unsigned num_redists)
static void copy_msgs(size_t num_redists, unsigned nmsgs, const struct redist_collection_msg *restrict msgs_orig, struct redist_collection_msg **p_msgs_copy, MPI_Comm comm)
void(* xt_sort_int)(int *a, size_t n)
size_t xt_ranks_uniq_count(size_t num_rank_sets, size_t *restrict num_ranks, const int *ranks[num_rank_sets])
Xt_exchanger * exchangers
static const struct xt_redist_vtable redist_collection_vtable