YAC 3.7.0
Yet Another Coupler
Loading...
Searching...
No Matches
yac_mpi.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#include <assert.h>
10#include <inttypes.h>
11#include <limits.h>
12#include <stdbool.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16
17#include <mpi.h>
18#include "yac_mpi_internal.h"
19#include "geometry.h"
20#include "ensure_array_size.h"
21#include "ppm/core.h"
22
25static int init_count = 0;
26static int yaxt_init_count = 0;
27
28static size_t * comm_buffer = NULL;
29static size_t comm_buffer_array_size = 0;
30static int comm_buffer_in_use = 0;
31
33
34 int mpi_initialized;
35 MPI_Initialized(&mpi_initialized);
36
37 return mpi_initialized;
38}
39
40void yac_yaxt_init(MPI_Comm comm) {
41
44 "ERROR(yac_yaxt_init): MPI has not yet been initialised");
45
48 "ERROR(yac_yaxt_init): YAXT was initialised by YAC. \n"
49 "In case there are multiple instances of YAC in parallel, the user has "
50 "to initialise YAXT such that it is available on all processes that "
51 "use YAC.")
52
53 if ((yaxt_init_count == 0) && (!xt_initialized() || xt_finalized())) {
54 xt_initialize(comm);
56 }
58}
59
60void yac_yaxt_init_f2c(MPI_Fint comm) {
61
62 yac_yaxt_init(MPI_Comm_f2c(comm));
63}
64
65static void yac_yaxt_cleanup() {
66
68 xt_finalize();
70 }
72}
73
74#define XSTR(s) STR(s)
75#define STR(s) #s
76
78
80 sizeof(size_t) == sizeof(YAC_MPI_SIZE_T_TYPE),
81 "ERROR(yac_mpi_init_core): "
82 "could not determine MPI data type for size_t "
83 "(sizeof(size_t): %zu; sizeof(%s): %zu)",
84 sizeof(size_t), XSTR(YAC_MPI_SIZE_T_TYPE),
85 sizeof(YAC_MPI_SIZE_T_TYPE))
86
87 if ((init_count == 0) && (!yac_mpi_is_initialised())) {
88 MPI_Init(NULL, NULL);
90 }
91
92 init_count++;
93}
94
96
97 if (init_count == 1) {
99 !comm_buffer_in_use, "ERROR(yac_mpi_finalize): comm_buffer still in use")
100 free(comm_buffer);
101 comm_buffer = NULL;
103 }
104 init_count--;
106}
107
109
112 yac_mpi_call(MPI_Finalize(), MPI_COMM_WORLD);
113}
114
115// GCOVR_EXCL_START
116//taken from http://beige.ucs.indiana.edu/I590/node85.html
117void yac_mpi_error(int error_code, MPI_Comm comm) {
118 int rank;
119 MPI_Comm_rank(comm, &rank);
120
121 char error_string[MPI_MAX_ERROR_STRING];
122 int length_of_error_string, error_class;
123
124 MPI_Error_class(error_code, &error_class);
125 MPI_Error_string(error_class, error_string, &length_of_error_string);
126 fprintf(stderr, "%3d: %s\n", rank, error_string);
127 MPI_Abort(comm, error_code);
128}
129// GCOVR_EXCL_STOP
130
132 void const * send_buffer, size_t const * sendcounts, size_t const * sdispls,
133 void * recv_buffer, size_t const * recvcounts, size_t const * rdispls,
134 size_t dt_size, MPI_Datatype dt, MPI_Comm comm, char const * caller, int line) {
135
136#define USE_P2P_ALLTOALLV
137#ifdef USE_P2P_ALLTOALLV
138 int comm_rank, comm_size;
139 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
140 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
141
142 int req_count = 0;
143 for (int i = 0; i < comm_size; ++i)
144 req_count += (sendcounts[i] > 0) + (recvcounts[i] > 0);
145 MPI_Request * req = xmalloc((size_t)req_count * sizeof(*req));
146
147 req_count = 0;
148 for (int j = 0, lb = comm_rank, ub = comm_size; j < 2;
149 ++j, lb = 0, ub = comm_rank) {
150 for (int i = lb; i < ub; ++i) {
151 if (sendcounts[i] > 0) {
153 sendcounts[i] <= INT_MAX,
154 "ERROR(%s(%d)::yac_alltoallv_p2p): "
155 "sendcounts[%d] = %zu exceeds INT_MAX (%d)",
156 caller, line, i, sendcounts[i], (int)INT_MAX)
158 MPI_Isend(
159 (void const *)((unsigned char *)send_buffer +
160 dt_size * sdispls[i]),
161 (int)(sendcounts[i]), dt, i, 0,
162 comm, req + req_count), comm);
163 ++req_count;
164 }
165 if (recvcounts[i] > 0) {
167 recvcounts[i] <= INT_MAX,
168 "ERROR(%s(%d)::yac_alltoallv_p2p): "
169 "recvcounts[%d] = %zu exceeds INT_MAX (%d)",
170 caller, line, i, recvcounts[i], (int)INT_MAX)
172 MPI_Irecv(
173 (void *)((unsigned char *)recv_buffer +
174 dt_size * rdispls[i]),
175 (int)(recvcounts[i]), dt, i, 0,
176 comm, req + req_count), comm);
177 ++req_count;
178 }
179 }
180 }
181 yac_mpi_call(MPI_Waitall(req_count, req, MPI_STATUSES_IGNORE), comm);
182 free(req);
183#else // USE_P2P_ALLTOALLV
184 int comm_size;
185 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
186 int * int_buffer = xmalloc(4 * comm_size * sizeof(*int_buffer));
187 int * int_sendcounts = int_buffer + 0 * comm_size;
188 int * int_sdispls = int_buffer + 1 * comm_size;
189 int * int_recvcounts = int_buffer + 2 * comm_size;
190 int * int_rdispls = int_buffer + 3 * comm_size;
191 for (int i = 0; i < comm_size; ++i) {
193 sendcounts[i] <= INT_MAX,
194 "ERROR(%s(%d)::yac_alltoallv_p2p): "
195 "sendcounts[%d] = %zu exceeds INT_MAX (%d)",
196 caller, line, i, sendcounts[i], (int)INT_MAX)
198 sdispls[i] <= INT_MAX,
199 "ERROR(%s(%d)::yac_alltoallv_p2p): "
200 "sdispls[%d] = %zu exceeds INT_MAX (%d)",
201 caller, line, i, sdispls[i], (int)INT_MAX)
203 recvcounts[i] <= INT_MAX,
204 "ERROR(%s(%d)::yac_alltoallv_p2p): "
205 "recvcounts[%d] = %zu exceeds INT_MAX (%d)",
206 caller, line, i, recvcounts[i], (int)INT_MAX)
208 rdispls[i] <= INT_MAX,
209 "ERROR(%s(%d)::yac_alltoallv_p2p): "
210 "rdispls[%d] = %zu exceeds INT_MAX (%d)",
211 caller, line, i, rdispls[i], (int)INT_MAX)
212 int_sendcounts[i] = (int)(sendcounts[i]);
213 int_sdispls[i] = (int)(sdispls[i]);
214 int_recvcounts[i] = (int)(recvcounts[i]);
215 int_rdispls[i] = (int)(rdispls[i]);
216 }
218 MPI_Alltoallv(send_buffer, int_sendcounts, int_sdispls, dt,
219 recv_buffer, int_recvcounts, int_rdispls, dt, comm), comm);
220 free(int_buffer);
221#endif // USE_P2P_ALLTOALLV
222}
223
224#define YAC_ALLTOALL_P2P_TYPE(NAME, TYPE, TYPE_SIZE, MPI_TYPE) \
225 void yac_alltoallv_ ## NAME ## _p2p( \
226 TYPE const * send_buffer, size_t const * sendcounts, size_t const * sdispls, \
227 TYPE * recv_buffer, size_t const * recvcounts, size_t const * rdispls, \
228 MPI_Comm comm, char const * caller, int line) { \
229 yac_alltoallv_p2p( \
230 (void const *)send_buffer, sendcounts, sdispls, \
231 (void *)recv_buffer, recvcounts, rdispls, \
232 TYPE_SIZE, MPI_TYPE, comm, caller, line); \
233 }
234
235YAC_ALLTOALL_P2P_TYPE(int, int, sizeof(int), MPI_INT)
237YAC_ALLTOALL_P2P_TYPE(uint64, uint64_t, sizeof(uint64_t), MPI_UINT64_T)
238YAC_ALLTOALL_P2P_TYPE(packed, void, 1, MPI_PACKED)
239YAC_ALLTOALL_P2P_TYPE(dble, double, sizeof(double), MPI_DOUBLE)
240YAC_ALLTOALL_P2P_TYPE(size_t, size_t, sizeof(size_t), YAC_MPI_SIZE_T)
241
243 void const * send_buffer, int const * sendcounts, int const * sdispls,
244 void * recv_buffer, int const * recvcounts, int const * rdispls,
245 size_t dt_size, MPI_Datatype dt, struct yac_group_comm group_comm) {
246
247 MPI_Comm comm = group_comm.comm;
248 int comm_rank;
249 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
250 int rank = comm_rank - group_comm.start;
251
252 int req_count = 0;
253 for (int i = 0; i < group_comm.size; ++i)
254 req_count += (sendcounts[i] > 0) + (recvcounts[i] > 0);
255 MPI_Request * req = xmalloc((size_t)req_count * sizeof(*req));
256
257 req_count = 0;
258 for (int j = 0, lb = rank, ub = group_comm.size; j < 2;
259 ++j, lb = 0, ub = rank) {
260 for (int i = lb; i < ub; ++i) {
261 if (sendcounts[i] > 0) {
262
264 MPI_Isend(
265 (void const *)((unsigned char *)send_buffer +
266 dt_size * (size_t)(sdispls[i])),
267 sendcounts[i], dt, i + group_comm.start, 0,
268 comm, req + req_count), comm);
269 ++req_count;
270 }
271 if (recvcounts[i] > 0) {
273 MPI_Irecv(
274 (void *)((unsigned char *)recv_buffer +
275 dt_size * (size_t)(rdispls[i])),
276 recvcounts[i], dt, i + group_comm.start, 0,
277 comm, req + req_count), comm);
278 ++req_count;
279 }
280 }
281 }
282 yac_mpi_call(MPI_Waitall(req_count, req, MPI_STATUSES_IGNORE), comm);
283 free(req);
284}
285
286static int nearest_power_of_two(int x) {
287 int power = 1;
288
289 while(power < x) power *= 2;
290
291 return power / 2;
292}
293
294// based on https://doi.org/10.1016/j.parco.2017.08.004
296 double * buffer, int count, struct yac_group_comm group_comm) {
297
298 int comm_rank;
299 yac_mpi_call(MPI_Comm_rank(group_comm.comm, &comm_rank), group_comm.comm);
300
301 int rank = comm_rank - group_comm.start;
302 int pof2 = nearest_power_of_two(group_comm.size);
303 int rem = group_comm.size - pof2;
304 int my_rank;
305 double * recv_buffer = xmalloc((size_t)count * sizeof(*recv_buffer));
306
307 if (rank < 2 * rem) {
308
309 if (rank & 1) {
311 MPI_Recv(
312 (void*)recv_buffer, count, MPI_DOUBLE, rank - 1 + group_comm.start, 0,
313 group_comm.comm, MPI_STATUS_IGNORE), group_comm.comm);
314 for (int i = 0; i < count; ++i) buffer[i] += recv_buffer[i];
315 my_rank = rank / 2;
316 } else {
318 MPI_Send(
319 (void const *)buffer, count, MPI_DOUBLE, rank + 1 + group_comm.start,
320 0, group_comm.comm), group_comm.comm);
321 my_rank = -1;
322 }
323 } else {
324 my_rank = rank - rem;
325 }
326 if (my_rank != -1) {
327 int mask = 1;
328 while (mask < pof2) {
329 int newdst = my_rank ^ mask;
330 int dst;
331 if (newdst < rem) dst = newdst * 2 + 1;
332 else dst = newdst + rem;
334 MPI_Sendrecv(
335 (void const*)buffer, count, MPI_DOUBLE, dst + group_comm.start, 0,
336 (void*)recv_buffer, count, MPI_DOUBLE, dst + group_comm.start, 0,
337 group_comm.comm, MPI_STATUS_IGNORE),
338 group_comm.comm);
339 for (int i = 0; i < count; ++i) buffer[i] += recv_buffer[i];
340 mask <<= 1;
341 }
342 }
343 free(recv_buffer);
344 if (rank < 2 * rem) {
345 if (rank & 1) {
347 MPI_Send(
348 (void const*)buffer, count, MPI_DOUBLE, rank - 1 + group_comm.start,
349 0, group_comm.comm), group_comm.comm);
350 } else {
352 MPI_Recv(
353 (void*)buffer, count, MPI_DOUBLE, rank + 1 + group_comm.start, 0,
354 group_comm.comm, MPI_STATUS_IGNORE), group_comm.comm);
355 }
356 }
357}
358
359static int log2_(int x) {
360 if (x <= 1) return 0;
361 int l2 = 0;
362 while (x >>= 1) ++l2;
363 return l2;
364}
365
366// based on https://doi.org/10.1109/71.642949
368 const size_t * sendbuf, size_t * recvbuf, int count,
369 struct yac_group_comm group_comm) {
370
371 int comm_rank;
372 yac_mpi_call(MPI_Comm_rank(group_comm.comm, &comm_rank), group_comm.comm);
373 int rank = comm_rank - group_comm.start;
374
375 size_t * temp = xmalloc((size_t)group_comm.size * (size_t)count * sizeof(*temp));
376
377 int lg2 = log2_(group_comm.size);
378 memcpy(temp, sendbuf, (size_t)count * sizeof(*temp));
379 int nblk = 1;
380 int curr_len = count;
381
382 for (int r = 0; r < lg2; ++r) {
383 int dst = (rank - nblk + group_comm.size) % group_comm.size;
384 int src = (rank + nblk) % group_comm.size;
386 MPI_Sendrecv(
387 (void const*)temp, curr_len, YAC_MPI_SIZE_T, dst + group_comm.start, 0,
388 (void *)(temp + (size_t)curr_len), curr_len, YAC_MPI_SIZE_T,
389 src + group_comm.start, 0, group_comm.comm, MPI_STATUS_IGNORE),
390 group_comm.comm);
391 nblk *= 2;
392 curr_len *= 2;
393 }
394 int rest = count * group_comm.size - curr_len;
395 int dst = (rank - nblk + group_comm.size) % group_comm.size;
396 int src = (rank + nblk) % group_comm.size;
398 MPI_Sendrecv(
399 (void const*)temp, rest, YAC_MPI_SIZE_T, dst + group_comm.start, 0,
400 (void*)(temp + (size_t)curr_len), rest, YAC_MPI_SIZE_T,
401 src + group_comm.start, 0, group_comm.comm, MPI_STATUS_IGNORE),
402 group_comm.comm);
403 memcpy(recvbuf + (size_t)count * (size_t)rank,
404 temp, (size_t)count * (size_t)(group_comm.size - rank) * sizeof(*temp));
405 memcpy(recvbuf, temp + (size_t)count * (size_t)(group_comm.size - rank),
406 (size_t)count * (size_t)rank * sizeof(*temp));
407
408 free(temp);
409}
410
412 void * buffer, int count, MPI_Datatype datatype, int root,
413 struct yac_group_comm group_comm) {
414
415 int comm_rank;
416 yac_mpi_call(MPI_Comm_rank(group_comm.comm, &comm_rank), group_comm.comm);
417 int rank = comm_rank - group_comm.start;
418
419 // if root is not part of the group
420 if ((root < group_comm.start) ||
421 (root >= group_comm.start + group_comm.size)) {
422
423 if (comm_rank == root) {
425 MPI_Send(
426 (void const*)buffer, count, datatype, group_comm.start, 0,
427 group_comm.comm), group_comm.comm);
428 return;
429 } else if (comm_rank == group_comm.start) {
431 MPI_Recv(
432 buffer, count, datatype, root, 0, group_comm.comm,
433 MPI_STATUS_IGNORE), group_comm.comm);
434 }
435 root = 0;
436 } else {
437 root -= group_comm.start;
438 }
439
440 // if not root, receive data
441 if (rank != root) {
442
443 int temp_rank = (group_comm.size + rank - root) % group_comm.size;
444 int bit = 1;
445
446 while (bit <= temp_rank) bit <<= 1;
447 bit >>= 1;
448
449 int src_rank =
450 (((temp_rank ^ bit) + root) % group_comm.size) + group_comm.start;
451
453 MPI_Recv(buffer, count, datatype, src_rank, 0, group_comm.comm,
454 MPI_STATUS_IGNORE), group_comm.comm);
455 }
456
457 // relative rank in respect to root
458 int temp_rank = (group_comm.size + rank - root) % group_comm.size;
459 int bit = 1, send_rank;
460
461 while(bit <= temp_rank) bit <<= 1;
462
463 while ((send_rank = temp_rank | bit) < group_comm.size) {
464
465 bit <<= 1;
466
467 send_rank = ((send_rank + root) % group_comm.size) + group_comm.start;
468
470 MPI_Send(
471 (void const*)buffer, count, datatype, send_rank, 0, group_comm.comm),
472 group_comm.comm);
473 }
474}
475
477
478 struct yac_group_comm group_comm;
479 group_comm.start = 0;
480 yac_mpi_call(MPI_Comm_size(comm, &(group_comm.size)), comm);
481 yac_mpi_call(MPI_Comm_dup(comm, &(group_comm.comm)), comm);
482
483 return group_comm;
484}
485
486void yac_group_comm_delete(struct yac_group_comm group_comm) {
487
488 yac_mpi_call(MPI_Comm_free(&(group_comm.comm)), group_comm.comm);
489}
490
492 return yac_group_comm_get_global_rank(group_comm) - group_comm.start;
493}
494
496 return group_comm.size;
497}
498
500 int comm_rank;
501 yac_mpi_call(MPI_Comm_rank(group_comm.comm, &comm_rank), group_comm.comm);
502 return comm_rank;
503}
504
506 int comm_size;
507 yac_mpi_call(MPI_Comm_size(group_comm.comm, &comm_size), group_comm.comm);
508 return comm_size;
509}
510
512 struct yac_group_comm group_comm, int split_rank,
513 struct yac_group_comm * local_group_comm,
514 struct yac_group_comm * remote_group_comm) {
515
516 int comm_rank;
517 MPI_Comm comm = group_comm.comm;
518 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
519
521 (split_rank >= 0) && (split_rank < group_comm.size),
522 "ERROR(yac_group_comm_split): invalid split rank")
523
524 int start[2] = {group_comm.start, group_comm.start + split_rank};
525 int size[2] = {split_rank, group_comm.size - split_rank};
526 int local_idx = (comm_rank - group_comm.start) >= split_rank;
527
528 local_group_comm->start = start[local_idx];
529 local_group_comm->size = size[local_idx];
530 local_group_comm->comm = comm;
531 remote_group_comm->start = start[local_idx^1];
532 remote_group_comm->size = size[local_idx^1];
533 remote_group_comm->comm = comm;
534}
535
537
538 struct bounding_circle dummy;
539 MPI_Datatype bnd_circle_dt;
540 int array_of_blocklengths[] = {3, 1, 1};
541 const MPI_Aint array_of_displacements[] =
542 {(MPI_Aint)(intptr_t)(const void *)&(dummy.base_vector[0]) -
543 (MPI_Aint)(intptr_t)(const void *)&dummy,
544 (MPI_Aint)(intptr_t)(const void *)&(dummy.inc_angle.sin) -
545 (MPI_Aint)(intptr_t)(const void *)&dummy,
546 (MPI_Aint)(intptr_t)(const void *)&(dummy.inc_angle.cos) -
547 (MPI_Aint)(intptr_t)(const void *)&dummy};
548 const MPI_Datatype array_of_types[] =
549 {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE};
551 MPI_Type_create_struct(3, array_of_blocklengths, array_of_displacements,
552 array_of_types, &bnd_circle_dt), comm);
553 return yac_create_resized(bnd_circle_dt, sizeof(dummy), comm);
554}
555
557 MPI_Datatype dt, size_t new_size, MPI_Comm comm) {
558
559 MPI_Datatype resized_dt;
560
561#define OPENMPI_WORKAROUND
562#ifdef OPENMPI_WORKAROUND
563 MPI_Aint lb, extent;
564 MPI_Type_get_extent(dt, &lb, &extent);
566 MPI_Type_create_resized(dt, lb, (MPI_Aint)new_size, &resized_dt), comm);
567#else
569 MPI_Type_create_resized(dt, 0, (MPI_Aint)new_size, &resized_dt), comm);
570#endif
571#undef OPENMPI_WORKAROUND
572 yac_mpi_call(MPI_Type_free(&dt), comm);
573 yac_mpi_call(MPI_Type_commit(&resized_dt), comm);
574 return resized_dt;
575}
576
578 int count, size_t const * sendcounts, size_t * recvcounts,
579 size_t * sdispls, size_t * rdispls, MPI_Comm comm) {
580
581 int comm_size;
582 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
583
584 // exchange the number of requested points
586 MPI_Alltoall(
587 (void const*)sendcounts, count, YAC_MPI_SIZE_T,
588 (void*)recvcounts, count, YAC_MPI_SIZE_T, comm), comm);
589
590 // sdispls are offset by one position, this is intentional because this is
591 // usefull for packing of data
592 sdispls[0] = 0;
593 size_t iter_count = (size_t)(count * comm_size);
594 for (size_t i = 0, saccu = 0, raccu = 0; i < iter_count; ++i) {
595 sdispls[i+1] = saccu;
596 rdispls[i] = raccu;
597 saccu += sendcounts[i];
598 raccu += recvcounts[i];
599 }
600}
601
603 int count, size_t ** sendcounts, size_t ** recvcounts,
604 size_t ** sdispls, size_t ** rdispls, MPI_Comm comm) {
605
606 int comm_size;
607 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
608
609 size_t * comm_buffer_;
610 if (!comm_buffer_in_use) {
613 4 * (size_t)count * (size_t)comm_size + 1);
614 comm_buffer_ = comm_buffer;
616 } else {
617 comm_buffer_ =
618 xmalloc(
619 (4 * (size_t)count * (size_t)comm_size + 1) * sizeof(*comm_buffer_));
620 }
621
622 size_t offset = (size_t)count * (size_t)comm_size;
623 *sendcounts = comm_buffer_ + 0 * offset;
624 *recvcounts = comm_buffer_ + 1 * offset;
625 *rdispls = comm_buffer_ + 2 * offset;
626 *sdispls = comm_buffer_ + 3 * offset; // sdispls is bigger by one element,
627 // which is usefull when packing data
628 // for alltoallv operation
629 memset(
630 comm_buffer_, 0, (size_t)count * (size_t)comm_size * sizeof(*comm_buffer_));
631}
632
634 size_t * sendcounts, size_t * recvcounts,
635 size_t * sdispls, size_t * rdispls) {
636
637 UNUSED(recvcounts);
638 UNUSED(sdispls);
639 UNUSED(rdispls);
640
641 if (sendcounts != comm_buffer) free(sendcounts);
642 else comm_buffer_in_use = 0;
643}
644
645/*
646 * Local Variables:
647 * c-basic-offset: 2
648 * coding: utf-8
649 * indent-tabs-mode: nil
650 * show-trailing-whitespace: t
651 * require-trailing-newline: t
652 * End:
653 */
#define UNUSED(x)
Definition core.h:73
#define ENSURE_ARRAY_SIZE(arrayp, curr_array_size, req_size)
Definition __init__.py:1
#define xmalloc(size)
Definition ppm_xfuncs.h:66
struct sin_cos_angle inc_angle
angle between the middle point and the boundary of the spherical cap
Definition geometry.h:61
double base_vector[3]
Definition geometry.h:59
double sin
Definition geometry.h:41
double cos
Definition geometry.h:41
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
#define YAC_ASSERT(exp, msg)
Definition yac_assert.h:16
#define XSTR(s)
Definition yac_mpi.c:74
static int mpi_initialised_by_yac
Definition yac_mpi.c:23
#define YAC_ALLTOALL_P2P_TYPE(NAME, TYPE, TYPE_SIZE, MPI_TYPE)
Definition yac_mpi.c:224
void yac_mpi_finalize()
Definition yac_mpi.c:108
void yac_mpi_cleanup()
Definition yac_mpi.c:95
void yac_alltoallv_p2p_group(void const *send_buffer, int const *sendcounts, int const *sdispls, void *recv_buffer, int const *recvcounts, int const *rdispls, size_t dt_size, MPI_Datatype dt, struct yac_group_comm group_comm)
Definition yac_mpi.c:242
int yac_group_comm_get_global_rank(struct yac_group_comm group_comm)
Definition yac_mpi.c:499
void yac_generate_alltoallv_args(int count, size_t const *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls, MPI_Comm comm)
Definition yac_mpi.c:577
static int yaxt_initialised_by_yac
Definition yac_mpi.c:24
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:633
int yac_group_comm_get_rank(struct yac_group_comm group_comm)
Definition yac_mpi.c:491
int yac_mpi_is_initialised()
Definition yac_mpi.c:32
static int init_count
Definition yac_mpi.c:25
void yac_group_comm_split(struct yac_group_comm group_comm, int split_rank, struct yac_group_comm *local_group_comm, struct yac_group_comm *remote_group_comm)
Definition yac_mpi.c:511
MPI_Datatype yac_get_bounding_circle_mpi_datatype(MPI_Comm comm)
Definition yac_mpi.c:536
static size_t * comm_buffer
Definition yac_mpi.c:28
int yac_group_comm_get_global_size(struct yac_group_comm group_comm)
Definition yac_mpi.c:505
void yac_yaxt_init(MPI_Comm comm)
Definition yac_mpi.c:40
struct yac_group_comm yac_group_comm_new(MPI_Comm comm)
Definition yac_mpi.c:476
void yac_mpi_error(int error_code, MPI_Comm comm)
Definition yac_mpi.c:117
static size_t comm_buffer_array_size
Definition yac_mpi.c:29
static int yaxt_init_count
Definition yac_mpi.c:26
void yac_allreduce_sum_dble(double *buffer, int count, struct yac_group_comm group_comm)
Definition yac_mpi.c:295
void yac_yaxt_init_f2c(MPI_Fint comm)
Definition yac_mpi.c:60
void yac_get_comm_buffers(int count, size_t **sendcounts, size_t **recvcounts, size_t **sdispls, size_t **rdispls, MPI_Comm comm)
Definition yac_mpi.c:602
static int log2_(int x)
Definition yac_mpi.c:359
int yac_group_comm_get_size(struct yac_group_comm group_comm)
Definition yac_mpi.c:495
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
Definition yac_mpi.c:556
void yac_bcast_group(void *buffer, int count, MPI_Datatype datatype, int root, struct yac_group_comm group_comm)
Definition yac_mpi.c:411
void yac_allgather_size_t(const size_t *sendbuf, size_t *recvbuf, int count, struct yac_group_comm group_comm)
Definition yac_mpi.c:367
static int nearest_power_of_two(int x)
Definition yac_mpi.c:286
static int comm_buffer_in_use
Definition yac_mpi.c:30
static void yac_yaxt_cleanup()
Definition yac_mpi.c:65
void yac_group_comm_delete(struct yac_group_comm group_comm)
Definition yac_mpi.c:486
void yac_mpi_init()
Definition yac_mpi.c:77
void yac_alltoallv_p2p(void const *send_buffer, size_t const *sendcounts, size_t const *sdispls, void *recv_buffer, size_t const *recvcounts, size_t const *rdispls, size_t dt_size, MPI_Datatype dt, MPI_Comm comm, char const *caller, int line)
Definition yac_mpi.c:131
#define yac_mpi_call(call, comm)
#define YAC_MPI_SIZE_T_TYPE
#define YAC_MPI_SIZE_T
Xt_int yac_int
Definition yac_types.h:15
#define yac_int_dt
Definition yac_types.h:16