64 MPI_Comm newComm,
int new_tag_offset);
67 const void * src_data,
70 Xt_exchanger exchanger,
const void * src_data,
void * dst_data,
75 int *restrict *ranks);
95 #if SIZEOF_MPI_DATATYPE == 2 * SIZEOF_INT
96 # define MSG_DIR(msg) ((enum xt_msg_direction)((msg).data.padding))
97 # define type data.padding
100 # define MSG_DIR(msg) ((msg).type)
117 size_t header_size =
sizeof (*exchanger),
118 body_size =
sizeof (
struct mix_msg) * nmsg;
119 exchanger =
xmalloc(header_size + body_size);
120 exchanger->
n = (int)nmsg;
136 assert((nsend >= 0) & (nrecv >= 0));
137 size_t nmsg = (size_t)nsend + (
size_t)nrecv;
140 exchanger->
comm = comm;
144 &(msgs[0].
data),
sizeof (msgs[0]), comm);
145 for (
size_t i = 0; i < (size_t)nsend; ++i)
148 &(msgs[nsend].
data),
sizeof (msgs[0]), comm);
149 for (
size_t i = 0; i < (size_t)nrecv; ++i)
150 msgs[i + (
size_t)nsend].type =
RECV;
154 for (
size_t i = 1; i < nmsg; ++i) {
158 struct mix_msg temp = msgs[i-1];
170 MPI_Comm new_comm,
int new_tag_offset)
174 size_t nmsg = (size_t)exchanger_msr->
n;
177 exchanger_copy->
comm = new_comm;
178 exchanger_copy->tag_offset = new_tag_offset;
179 struct mix_msg *restrict new_msgs = exchanger_copy->msgs,
180 *restrict orig_msgs = exchanger_msr->
msgs;
182 &new_msgs->data, sizeof (*new_msgs),
184 for (
size_t i = 0; i < nmsg; ++i)
185 new_msgs[i].
type = orig_msgs[i].
type;
196 size_t nmsg = (size_t)exchanger_msr->
n;
197 struct mix_msg *restrict msgs = exchanger_msr->
msgs;
205 const void * src_data,
211 if (exchanger_msr->
n > 0) {
212 size_t nmsg = (size_t)exchanger_msr->
n;
214 struct mix_msg *restrict msgs = exchanger_msr->
msgs;
217 MPI_Request *requests
219 ? req_buf :
xmalloc(nmsg *
sizeof (*requests));
220 for (
size_t i = 0; i < nmsg; ++i) {
221 typedef int (*ifp)(
void *buf,
int count, MPI_Datatype datatype,
int dest,
222 int tag,
MPI_Comm comm, MPI_Request *request);
223 ifp op =
MSG_DIR(msgs[i]) ==
SEND ? (ifp)MPI_Isend : (ifp)MPI_Irecv;
228 comm, requests+i), comm);
230 xt_mpi_call(MPI_Waitall((
int)nmsg, requests, MPI_STATUSES_IGNORE), comm);
231 if (requests != req_buf)
237 Xt_exchanger exchanger,
const void * src_data,
void * dst_data,
245 if (exchanger_msr->
n > 0) {
246 size_t nmsg = (size_t)exchanger_msr->
n;
248 struct mix_msg *restrict msgs = exchanger_msr->
msgs;
251 MPI_Request *tmp_requests
253 ? req_buf :
xmalloc(nmsg *
sizeof (*tmp_requests));
254 for (
size_t i = 0; i < nmsg; ++i) {
255 typedef int (*ifp)(
void *buf,
int count, MPI_Datatype datatype,
int dest,
256 int tag,
MPI_Comm comm, MPI_Request *request);
257 ifp op =
MSG_DIR(msgs[i]) ==
SEND ? (ifp)MPI_Isend : (ifp)MPI_Irecv;
262 comm, tmp_requests+i), comm);
265 if (tmp_requests != req_buf)
275 int *restrict *ranks)
279 size_t nmsg = 0, nmsg_all = (size_t)exchanger_msr->
n;
280 const struct mix_msg *restrict msgs = exchanger_msr->
msgs;
281 for (
size_t i = 0; i < nmsg_all; ++i)
282 nmsg +=
MSG_DIR(msgs[i]) == direction;
283 int *restrict ranks_ = *ranks =
xmalloc(nmsg *
sizeof (*ranks_));
284 for (
size_t i = 0, j = (
size_t)-1; i < nmsg_all; ++i)
285 if (
MSG_DIR(msgs[i]) == direction)
286 ranks_[++j] = msgs[i].data.rank;
297 size_t nmsg = (size_t)exchanger_msr->
n;
298 struct mix_msg *restrict msgs = exchanger_msr->
msgs;
299 MPI_Datatype datatype_copy = MPI_DATATYPE_NULL;
300 for (
size_t i = 0; i < nmsg; ++i)
301 if (
MSG_DIR(msgs[i]) == direction && msgs[i].data.rank == rank) {
303 exchanger_msr->
comm);
306 return datatype_copy;
add versions of standard API functions not returning on error
const struct xt_exchanger_vtable * vtable
struct Xt_redist_msg data
Xt_exchanger(* copy)(Xt_exchanger, MPI_Comm, int)
void xt_exchanger_internal_optimize(size_t n, void *msgs, size_t msg_type_size, MPI_Comm comm)
exchanging of data based on information provided by redist's
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)
static MPI_Datatype xt_exchanger_mix_isend_irecv_get_MPI_Datatype(Xt_exchanger exchanger, int rank, enum xt_msg_direction direction)
struct Xt_exchanger_mix_isend_irecv_ * Xt_exchanger_mix_isend_irecv
static Xt_exchanger_mix_isend_irecv xt_exchanger_mix_isend_irecv_alloc(size_t nmsg)
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 const struct xt_exchanger_vtable exchanger_mix_isend_irecv_vtable
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)
#define xt_mpi_call(call, comm)
@ xt_mpi_tag_exchange_msg
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)
void xt_redist_msgs_strided_destruct(size_t n, struct Xt_redist_msg *msgs, MPI_Comm comm, size_t ofs_stride)
redistribution of data, non-public declarations
Xt_request xt_request_msgs_new(int n, const MPI_Request requests[n], MPI_Comm comm)