69#if __GNUC__ >= 11 && __GNUC__ <= 13 && defined MPICH
70#pragma GCC diagnostic push
71#pragma GCC diagnostic ignored "-Wstringop-overread"
72#pragma GCC diagnostic ignored "-Wstringop-overflow"
77 MPI_Comm newComm,
int new_tag_offset);
85xt_exchanger_mix_isend_irecv_s_exchange_omp(
Xt_exchanger exchanger,
91 Xt_exchanger exchanger,
const void * src_data,
void * dst_data,
95xt_exchanger_mix_isend_irecv_a_exchange_omp(
96 Xt_exchanger exchanger,
const void * src_data,
void * dst_data,
105 int *restrict *ranks);
125xt_exchanger_mix_isend_irecv_auto_omp_vtable = {
128 .s_exchange = xt_exchanger_mix_isend_irecv_s_exchange_omp,
129 .a_exchange = xt_exchanger_mix_isend_irecv_a_exchange_omp,
139#define MSG_DIR(msg) ((msg).rank < 0)
156 size_t header_size =
sizeof (*exchanger),
158 exchanger =
xmalloc(header_size + body_size);
159 exchanger->
n = (int)nmsg;
163 exchanger->
vtable = &xt_exchanger_mix_isend_irecv_auto_omp_vtable;
173 int r_ = r & INT_MAX;
174 return r_ + (r_ <= comm_rank ? comm_size : 0);
177#define XT_SORTFUNC_DECL static
178#define SORT_TYPE struct Xt_redist_msg
179#define SORT_TYPE_SUFFIX redist_msg_mix
180#define SORT_TYPE_CMP_LT(u,v,i,j) \
181 (adjusted_rank((u).rank, comm_rank, comm_size) \
182 < adjusted_rank((v).rank, comm_rank, comm_size))
183#define SORT_TYPE_CMP_LE(u,v,i,j) \
184 (adjusted_rank((u).rank, comm_rank, comm_size) \
185 <= adjusted_rank((v).rank, comm_rank, comm_size))
186#define SORT_TYPE_CMP_EQ(u,v,i,j) \
187 (((u).rank & INT_MAX) == ((v).rank & INT_MAX))
188#define XT_SORT_EXTRA_ARGS_DECL , int comm_rank, int comm_size
189#define XT_SORT_EXTRA_ARGS_PASS , comm_rank, comm_size
190#define XT_SORT_VECSWAP_EXTRA_ARGS_DECL
191#define XT_SORT_VECSWAP_EXTRA_ARGS_PASS
208 assert((nsend >= 0) & (nrecv >= 0));
209 size_t nmsg = (size_t)nsend + (
size_t)nrecv;
212 exchanger->
comm = comm;
217 msgs,
sizeof (msgs[0]), comm, dt_dup);
219 msgs+nsend,
sizeof (msgs[0]), comm,
221 for (
size_t i = 0; i < (size_t)nrecv; ++i)
222 msgs[i + (
size_t)nsend].rank |= ~INT_MAX;
225 int comm_size, comm_rank, is_inter;
226 xt_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
227 xt_mpi_call(MPI_Comm_test_inter(comm, &is_inter), comm);
228 int (*get_comm_size)(
MPI_Comm,
int *)
229 = is_inter ? MPI_Comm_remote_size : MPI_Comm_size;
230 xt_mpi_call(get_comm_size(comm, &comm_size), comm);
231 xt_quicksort_redist_msg_mix(msgs, nmsg, comm_rank, comm_size);
234 for (
size_t i = 1; i < nmsg; ++i) {
236 if ((msgs[i-1].
rank & INT_MAX) == (msgs[i].
rank & INT_MAX)
251 MPI_Comm new_comm,
int new_tag_offset)
255 size_t nmsg = (size_t)exchanger_msr->
n;
259 exchanger_copy->
comm = new_comm;
263 *restrict orig_msgs = exchanger_msr->
msgs;
265 new_msgs,
sizeof (*new_msgs),
277 size_t nmsg = (size_t)exchanger_msr->
n;
288 const void *src_data,
void *dst_data,
289 MPI_Request *requests,
292 for (
size_t i = 0; i < nmsg; ++i) {
293 typedef int (*ifp)(
void *buf,
int count, MPI_Datatype
datatype,
int dest,
294 int tag,
MPI_Comm comm, MPI_Request *request);
295 ifp op =
MSG_DIR(msgs[i]) ==
SEND ? (ifp)MPI_Isend : (ifp)MPI_Irecv;
297 ? (
void *)(intptr_t)src_data : dst_data;
300 comm, requests+i), comm);
306 const void * src_data,
312 if (exchanger_msr->
n > 0) {
313 size_t nmsg = (size_t)exchanger_msr->
n;
315 MPI_Request *requests
317 ? req_buf :
xmalloc(nmsg *
sizeof (*requests));
319 src_data, dst_data, requests,
321 xt_mpi_call(MPI_Waitall((
int)nmsg, requests, MPI_STATUSES_IGNORE),
322 exchanger_msr->
comm);
323 if (requests != req_buf)
329 Xt_exchanger exchanger,
const void * src_data,
void * dst_data,
335 if (exchanger_msr->
n > 0) {
336 size_t nmsg = (size_t)exchanger_msr->
n;
341 MPI_Request *requests_
344 src_data, dst_data, requests_,
353xt_exchanger_mix_isend_irecv_a_exchange_mt(
Xt_exchanger exchanger,
354 const void * src_data,
358 MPI_Request *requests
362 size_t num_threads = (size_t)omp_get_num_threads(),
363 tid = (size_t)omp_get_thread_num();
364 size_t nmsg = (size_t)exchanger_msr->
n,
365 start = (nmsg * tid) / num_threads,
366 nmsg_ = (nmsg * (tid+1)) / num_threads - start;
368 src_data, dst_data, requests+start,
373xt_exchanger_mix_isend_irecv_a_exchange_omp(
Xt_exchanger exchanger,
374 const void *src_data,
381 xt_exchanger_mix_isend_irecv_a_exchange_mt(exchanger, src_data, dst_data,
387xt_exchanger_mix_isend_irecv_s_exchange_mt(
Xt_exchanger exchanger,
388 const void * src_data,
392 MPI_Request *requests
396 size_t num_threads = (size_t)omp_get_num_threads(),
397 tid = (size_t)omp_get_thread_num();
398 size_t nmsg = (size_t)exchanger_msr->
n,
399 start = (nmsg * tid) / num_threads,
400 nmsg_ = (nmsg * (tid+1)) / num_threads - start;
402 src_data, dst_data, requests+start,
404 xt_mpi_call(MPI_Waitall((
int)nmsg_, requests+start,
405 MPI_STATUSES_IGNORE), exchanger_msr->
comm);
409xt_exchanger_mix_isend_irecv_s_exchange_omp(
Xt_exchanger exchanger,
410 const void * src_data,
416 xt_exchanger_mix_isend_irecv_s_exchange_mt(exchanger, src_data, dst_data,
437 int *restrict *ranks)
441 size_t nmsg = 0, nmsg_all = (size_t)exchanger_msr->
n;
443 for (
size_t i = 0; i < nmsg_all; ++i)
444 nmsg +=
MSG_DIR(msgs[i]) == direction;
445 int *restrict ranks_ = *ranks;
447 ranks_ = *ranks =
xmalloc(nmsg *
sizeof (*ranks_));
448 for (
size_t i = 0, j = (
size_t)-1; i < nmsg_all; ++i)
449 if (
MSG_DIR(msgs[i]) == direction)
450 ranks_[++j] = msgs[i].rank & INT_MAX;
462 size_t nmsg = (size_t)exchanger_msr->
n;
464 MPI_Datatype datatype_copy = MPI_DATATYPE_NULL;
465 if (direction ==
RECV)
rank |= ~INT_MAX;
466 for (
size_t i = 0; i < nmsg; ++i)
470 exchanger_msr->
comm);
472 datatype_copy = msgs[i].datatype;
475 return datatype_copy;
add versions of standard API functions not returning on error
const struct xt_exchanger_vtable * vtable
struct Xt_redist_msg msgs[]
Xt_exchanger(* copy)(Xt_exchanger, MPI_Comm, int)
int MPI_Type_dup(MPI_Datatype oldtype, MPI_Datatype *newtype)
struct Xt_config_ xt_default_config
void xt_config_set_redist_mthread_mode(Xt_config config, int mode)
int xt_config_get_redist_mthread_mode(Xt_config config)
implementation of configuration object
exchanging of data based on information provided by redist's
struct Xt_exchanger_omp_share_ * Xt_exchanger_omp_share
static int adjusted_rank(int r, int comm_rank, int comm_size)
static Xt_exchanger_mix_isend_irecv xt_exchanger_mix_isend_irecv_alloc(size_t nmsg, Xt_config config)
Xt_exchanger xt_exchanger_mix_isend_irecv_new(int nsend, int nrecv, const struct Xt_redist_msg *send_msgs, const struct Xt_redist_msg *recv_msgs, MPI_Comm comm, int tag_offset, Xt_config config)
static MPI_Datatype xt_exchanger_mix_isend_irecv_get_MPI_Datatype(Xt_exchanger exchanger, int rank, enum xt_msg_direction direction, bool do_dup)
struct Xt_exchanger_mix_isend_irecv_ * Xt_exchanger_mix_isend_irecv
static void xt_exchanger_mix_isend_irecv_a_exchange(Xt_exchanger exchanger, const void *src_data, void *dst_data, Xt_request *request)
static void xt_exchanger_mix_isend_irecv_delete(Xt_exchanger exchanger)
static int xt_exchanger_mix_isend_irecv_get_msg_ranks(Xt_exchanger exchanger, enum xt_msg_direction direction, int *restrict *ranks)
static void xt_exchanger_mix_isend_irecv_s_exchange(Xt_exchanger exchanger, const void *src_data, void *dst_data)
static Xt_exchanger xt_exchanger_mix_isend_irecv_copy(Xt_exchanger exchanger, MPI_Comm newComm, int new_tag_offset)
static void redist_msgs_to_req(size_t nmsg, const struct Xt_redist_msg *restrict msgs, const void *src_data, void *dst_data, MPI_Request *requests, MPI_Comm comm, int tag_offset)
static Xt_exchanger_omp_share xt_exchanger_mix_isend_irecv_create_omp_share(Xt_exchanger exchanger)
const struct xt_exchanger_vtable xt_exchanger_mix_isend_irecv_vtable
#define xt_mpi_call(call, comm)
@ xt_mpi_tag_exchange_msg
macros to create quicksort implementations
redistribution of data, non-public declarations
PPM_DSO_INTERNAL void xt_redist_msgs_strided_copy(size_t n, const struct Xt_redist_msg *restrict src, size_t src_stride, struct Xt_redist_msg *restrict dst, size_t dst_stride, MPI_Comm comm, bool dt_dup)
PPM_DSO_INTERNAL void xt_redist_msgs_strided_destruct(size_t n, struct Xt_redist_msg *msgs, MPI_Comm comm, size_t ofs_stride)
struct Xt_request_ * Xt_request
MPI_Request * xt_request_msgs_get_req_ptr(Xt_request request)
Xt_request xt_request_msgs_alloc(int n, MPI_Comm comm, Xt_config config)
internal interfaces for xt_request_msgs