Line data Source code
1 : /*----------------------------------------------------------------------------*/
2 : /* CP2K: A general program to perform molecular dynamics simulations */
3 : /* Copyright 2000-2026 CP2K developers group <https://cp2k.org> */
4 : /* */
5 : /* SPDX-License-Identifier: BSD-3-Clause */
6 : /*----------------------------------------------------------------------------*/
7 : #include "cp_mpi.h"
8 :
9 : #include <assert.h>
10 : #include <omp.h>
11 : #include <stdio.h>
12 : #include <stdlib.h>
13 : #include <string.h>
14 :
15 : #if defined(__parallel)
16 : static bool mpi_initialized_by_cp2k = false;
17 : static bool mpi_attached_by_cp2k = false;
18 :
19 : /*******************************************************************************
20 : * \brief Check given MPI status and upon failure abort with a nice message.
21 : * \author Ole Schuett
22 : ******************************************************************************/
23 : #define CHECK(CMD) \
24 : do { \
25 : const int error = (CMD); \
26 : if (MPI_SUCCESS != error) { \
27 : fprintf(stderr, "MPI error #%i in %s:%i\n", error, __FILE__, __LINE__); \
28 : MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); \
29 : } \
30 : } while (0)
31 :
32 : /*******************************************************************************
33 : * \brief Abort if an MPI lifecycle operation is called from a parallel region.
34 : ******************************************************************************/
35 4908520 : static void assert_outside_parallel(const char *routine_name) {
36 4908520 : if (omp_in_parallel()) {
37 0 : fprintf(stderr, "%s must be called outside an OpenMP parallel region.\n",
38 : routine_name);
39 0 : abort();
40 : }
41 4908520 : }
42 :
43 : /*******************************************************************************
44 : * \brief Return a human-readable MPI thread-support level.
45 : ******************************************************************************/
46 0 : static const char *thread_level_name(const int level) {
47 0 : switch (level) {
48 : case MPI_THREAD_SINGLE:
49 : return "MPI_THREAD_SINGLE";
50 0 : case MPI_THREAD_FUNNELED:
51 0 : return "MPI_THREAD_FUNNELED";
52 0 : case MPI_THREAD_SERIALIZED:
53 0 : return "MPI_THREAD_SERIALIZED";
54 0 : case MPI_THREAD_MULTIPLE:
55 0 : return "MPI_THREAD_MULTIPLE";
56 0 : default:
57 0 : return "unknown";
58 : }
59 : }
60 :
61 : /*******************************************************************************
62 : * \brief Abort unless MPI provides MPI_THREAD_MULTIPLE support.
63 : ******************************************************************************/
64 0 : static void require_thread_multiple(const int provided) {
65 0 : if (provided < MPI_THREAD_MULTIPLE) {
66 0 : fprintf(stderr, "CP2K requires MPI_THREAD_MULTIPLE, but MPI provides %s.\n",
67 : thread_level_name(provided));
68 0 : MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
69 0 : abort();
70 : }
71 0 : }
72 : #endif
73 :
74 : /*******************************************************************************
75 : * \brief Initialize MPI with MPI_THREAD_MULTIPLE or attach to an active MPI.
76 : * \author Ole Schuett
77 : ******************************************************************************/
78 2 : void cp_mpi_init(int *argc, char ***argv) {
79 : #if defined(__parallel)
80 0 : assert_outside_parallel("cp_mpi_init");
81 0 : if (mpi_attached_by_cp2k) {
82 0 : fprintf(stderr, "cp_mpi_init must only be called once per lifecycle.\n");
83 0 : abort();
84 : }
85 :
86 0 : int finalized, initialized, provided;
87 0 : CHECK(MPI_Finalized(&finalized));
88 0 : if (finalized) {
89 0 : fprintf(stderr, "cp_mpi_init cannot be called after MPI_Finalize.\n");
90 0 : abort();
91 : }
92 :
93 0 : CHECK(MPI_Initialized(&initialized));
94 0 : if (initialized) {
95 0 : CHECK(MPI_Query_thread(&provided));
96 : } else {
97 0 : CHECK(MPI_Init_thread(argc, argv, MPI_THREAD_MULTIPLE, &provided));
98 0 : mpi_initialized_by_cp2k = true;
99 : }
100 0 : require_thread_multiple(provided);
101 0 : mpi_attached_by_cp2k = true;
102 : #else
103 2 : (void)argc; // mark used
104 2 : (void)argv;
105 : #endif
106 2 : }
107 :
108 : /*******************************************************************************
109 : * \brief Detach from MPI and finalize it only if cp_mpi_init initialized it.
110 : * \author Ole Schuett
111 : ******************************************************************************/
112 2 : void cp_mpi_finalize(void) {
113 : #if defined(__parallel)
114 0 : assert_outside_parallel("cp_mpi_finalize");
115 0 : if (!mpi_attached_by_cp2k) {
116 0 : fprintf(stderr, "cp_mpi_finalize called without a matching cp_mpi_init.\n");
117 0 : abort();
118 : }
119 :
120 0 : int finalized;
121 0 : CHECK(MPI_Finalized(&finalized));
122 0 : if (finalized) {
123 0 : fprintf(stderr, "MPI was finalized before cp_mpi_finalize.\n");
124 0 : abort();
125 : }
126 0 : if (mpi_initialized_by_cp2k) {
127 0 : CHECK(MPI_Finalize());
128 0 : mpi_initialized_by_cp2k = false;
129 : }
130 0 : mpi_attached_by_cp2k = false;
131 : #endif
132 2 : }
133 :
134 : /*******************************************************************************
135 : * \brief Returns MPI_COMM_WORLD.
136 : * \author Ole Schuett
137 : ******************************************************************************/
138 10 : cp_mpi_comm_t cp_mpi_get_comm_world(void) {
139 : #if defined(__parallel)
140 10 : return MPI_COMM_WORLD;
141 : #else
142 0 : return -1;
143 : #endif
144 : }
145 :
146 : /*******************************************************************************
147 : * \brief Wrapper around MPI_Comm_f2c.
148 : * \author Ole Schuett
149 : ******************************************************************************/
150 1260426 : cp_mpi_comm_t cp_mpi_comm_f2c(const int fortran_comm) {
151 : #if defined(__parallel)
152 : // Attempt to support "no MPI" if __parallel is defined (0 -> MPI_COMM_NULL).
153 1260422 : return 0 != fortran_comm ? MPI_Comm_f2c(fortran_comm) : MPI_COMM_NULL;
154 : #else
155 4 : (void)fortran_comm; // mark used
156 4 : return -1;
157 : #endif
158 : }
159 :
160 : /*******************************************************************************
161 : * \brief Wrapper around MPI_Comm_c2f.
162 : * \author Ole Schuett
163 : ******************************************************************************/
164 2 : int cp_mpi_comm_c2f(const cp_mpi_comm_t comm) {
165 : #if defined(__parallel)
166 2 : return MPI_Comm_c2f(comm);
167 : #else
168 0 : (void)comm; // mark used
169 0 : return -1;
170 : #endif
171 : }
172 :
173 : /*******************************************************************************
174 : * \brief Wrapper around MPI_Comm_rank.
175 : * \author Ole Schuett
176 : ******************************************************************************/
177 3681392 : int cp_mpi_comm_rank(const cp_mpi_comm_t comm) {
178 : #if defined(__parallel)
179 3681392 : int rank = 0;
180 3681392 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
181 3681392 : CHECK(MPI_Comm_rank(comm, &rank));
182 : }
183 3681392 : return rank;
184 : #else
185 0 : (void)comm; // mark used
186 0 : return 0;
187 : #endif
188 : }
189 :
190 : /*******************************************************************************
191 : * \brief Wrapper around MPI_Comm_size.
192 : * \author Ole Schuett
193 : ******************************************************************************/
194 3681534 : int cp_mpi_comm_size(const cp_mpi_comm_t comm) {
195 : #if defined(__parallel)
196 3681534 : int nranks = 1;
197 3681534 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
198 3681534 : CHECK(MPI_Comm_size(comm, &nranks));
199 : }
200 3681534 : return nranks;
201 : #else
202 0 : (void)comm; // mark used
203 0 : return 1;
204 : #endif
205 : }
206 :
207 : /*******************************************************************************
208 : * \brief Wrapper around MPI_Barrier; a null communicator is a no-op.
209 : ******************************************************************************/
210 6 : void cp_mpi_barrier(const cp_mpi_comm_t comm) {
211 : #if defined(__parallel)
212 6 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
213 6 : CHECK(MPI_Barrier(comm));
214 : }
215 : #else
216 0 : (void)comm; // mark used
217 : #endif
218 6 : }
219 :
220 : /*******************************************************************************
221 : * \brief Wrapper around MPI_Dims_create.
222 : * \author Ole Schuett
223 : ******************************************************************************/
224 0 : void cp_mpi_dims_create(const int nnodes, const int ndims, int dims[]) {
225 : #if defined(__parallel)
226 0 : CHECK(MPI_Dims_create(nnodes, ndims, dims));
227 : #else
228 0 : dims[0] = nnodes;
229 0 : for (int i = 1; i < ndims; i++) {
230 0 : dims[i] = 1;
231 : }
232 : #endif
233 0 : }
234 :
235 : /*******************************************************************************
236 : * \brief Wrapper around MPI_Cart_create.
237 : * \author Ole Schuett
238 : ******************************************************************************/
239 0 : cp_mpi_comm_t cp_mpi_cart_create(const cp_mpi_comm_t comm_old, const int ndims,
240 : const int dims[], const int periods[],
241 : const int reorder) {
242 : #if defined(__parallel)
243 0 : assert_outside_parallel("cp_mpi_cart_create");
244 0 : cp_mpi_comm_t comm_cart;
245 0 : CHECK(MPI_Cart_create(comm_old, ndims, dims, periods, reorder, &comm_cart));
246 0 : return comm_cart;
247 : #else
248 0 : (void)comm_old; // mark used
249 0 : (void)ndims;
250 0 : (void)dims;
251 0 : (void)periods;
252 0 : (void)reorder;
253 0 : return -1;
254 : #endif
255 : }
256 :
257 : /*******************************************************************************
258 : * \brief Wrapper around MPI_Cart_get.
259 : * \author Ole Schuett
260 : ******************************************************************************/
261 2454260 : void cp_mpi_cart_get(const cp_mpi_comm_t comm, int maxdims, int dims[],
262 : int periods[], int coords[]) {
263 : #if defined(__parallel)
264 2454260 : CHECK(MPI_Cart_get(comm, maxdims, dims, periods, coords));
265 : #else
266 0 : (void)comm; // mark used
267 0 : for (int i = 0; i < maxdims; i++) {
268 0 : dims[i] = 1;
269 0 : periods[i] = 1;
270 0 : coords[i] = 0;
271 : }
272 : #endif
273 2454260 : }
274 :
275 : /*******************************************************************************
276 : * \brief Wrapper around MPI_Cart_rank.
277 : * \author Ole Schuett
278 : ******************************************************************************/
279 119458824 : int cp_mpi_cart_rank(const cp_mpi_comm_t comm, const int coords[]) {
280 : #if defined(__parallel)
281 119458824 : int rank;
282 119458824 : CHECK(MPI_Cart_rank(comm, coords, &rank));
283 119458824 : return rank;
284 : #else
285 0 : (void)comm; // mark used
286 0 : (void)coords;
287 0 : return 0;
288 : #endif
289 : }
290 :
291 : /*******************************************************************************
292 : * \brief Wrapper around MPI_Cart_sub.
293 : * \author Ole Schuett
294 : ******************************************************************************/
295 2454260 : cp_mpi_comm_t cp_mpi_cart_sub(const cp_mpi_comm_t comm,
296 : const int remain_dims[]) {
297 : #if defined(__parallel)
298 2454260 : assert_outside_parallel("cp_mpi_cart_sub");
299 2454260 : cp_mpi_comm_t newcomm;
300 2454260 : CHECK(MPI_Cart_sub(comm, remain_dims, &newcomm));
301 2454260 : return newcomm;
302 : #else
303 0 : (void)comm; // mark used
304 0 : (void)remain_dims;
305 0 : return -1;
306 : #endif
307 : }
308 :
309 : /*******************************************************************************
310 : * \brief Wrapper around MPI_Comm_free.
311 : * \author Ole Schuett
312 : ******************************************************************************/
313 2454260 : void cp_mpi_comm_free(cp_mpi_comm_t *comm) {
314 : #if defined(__parallel)
315 2454260 : assert_outside_parallel("cp_mpi_comm_free");
316 2454260 : CHECK(MPI_Comm_free(comm));
317 : #else
318 0 : (void)comm; // mark used
319 : #endif
320 2454260 : }
321 :
322 : /*******************************************************************************
323 : * \brief Wrapper around MPI_Comm_compare.
324 : * \author Ole Schuett
325 : ******************************************************************************/
326 700188 : bool cp_mpi_comms_are_similar(const cp_mpi_comm_t comm1,
327 : const cp_mpi_comm_t comm2) {
328 : #if defined(__parallel)
329 700188 : int res;
330 700188 : CHECK(MPI_Comm_compare(comm1, comm2, &res));
331 700188 : return res == MPI_IDENT || res == MPI_CONGRUENT || res == MPI_SIMILAR;
332 : #else
333 0 : (void)comm1; // mark used
334 0 : (void)comm2;
335 0 : return true;
336 : #endif
337 : }
338 :
339 : /*******************************************************************************
340 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_INT.
341 : * \author Ole Schuett
342 : ******************************************************************************/
343 1400088 : void cp_mpi_max_int(int *values, const int count, const cp_mpi_comm_t comm) {
344 : #if defined(__parallel)
345 1400088 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
346 1400088 : int value = 0;
347 1400088 : void *recvbuf =
348 1400088 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
349 1400088 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_MAX, comm));
350 1400088 : memcpy(values, recvbuf, count * sizeof(int));
351 1400088 : if (1 < count) {
352 0 : cp_mpi_free_mem(recvbuf);
353 : }
354 : }
355 : #else
356 0 : (void)comm; // mark used
357 0 : (void)values;
358 0 : (void)count;
359 : #endif
360 1400088 : }
361 :
362 : /*******************************************************************************
363 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_UINT64_T.
364 : * \author Ole Schuett
365 : ******************************************************************************/
366 32308 : void cp_mpi_max_uint64(uint64_t *values, const int count,
367 : const cp_mpi_comm_t comm) {
368 : #if defined(__parallel)
369 32302 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
370 32302 : uint64_t value = 0;
371 32302 : void *recvbuf =
372 32302 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(uint64_t)) : &value);
373 32302 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_UINT64_T, MPI_MAX, comm));
374 32302 : memcpy(values, recvbuf, count * sizeof(uint64_t));
375 32302 : if (1 < count) {
376 0 : cp_mpi_free_mem(recvbuf);
377 : }
378 : }
379 : #else
380 6 : (void)comm; // mark used
381 6 : (void)values;
382 6 : (void)count;
383 : #endif
384 32308 : }
385 :
386 : /*******************************************************************************
387 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_DOUBLE.
388 : * \author Ole Schuett
389 : ******************************************************************************/
390 48 : void cp_mpi_max_double(double *values, const int count,
391 : const cp_mpi_comm_t comm) {
392 : #if defined(__parallel)
393 48 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
394 48 : double value = 0;
395 48 : void *recvbuf =
396 48 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
397 48 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_MAX, comm));
398 48 : memcpy(values, recvbuf, count * sizeof(double));
399 48 : if (1 < count) {
400 0 : cp_mpi_free_mem(recvbuf);
401 : }
402 : }
403 : #else
404 0 : (void)comm; // mark used
405 0 : (void)values;
406 0 : (void)count;
407 : #endif
408 48 : }
409 :
410 : /*******************************************************************************
411 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT.
412 : * \author Ole Schuett
413 : ******************************************************************************/
414 350022 : void cp_mpi_sum_int(int *values, const int count, const cp_mpi_comm_t comm) {
415 : #if defined(__parallel)
416 350022 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
417 350022 : int value = 0;
418 350022 : void *recvbuf =
419 350022 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
420 350022 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_SUM, comm));
421 350022 : memcpy(values, recvbuf, count * sizeof(int));
422 350022 : if (1 < count) {
423 347363 : cp_mpi_free_mem(recvbuf);
424 : }
425 : }
426 : #else
427 0 : (void)comm; // mark used
428 0 : (void)values;
429 0 : (void)count;
430 : #endif
431 350022 : }
432 :
433 : /*******************************************************************************
434 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_LONG.
435 : * \author Hans Pabst
436 : ******************************************************************************/
437 4439200 : void cp_mpi_sum_long(long *values, const int count, const cp_mpi_comm_t comm) {
438 : #if defined(__parallel)
439 4438400 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
440 4438400 : long value = 0;
441 4438400 : void *recvbuf =
442 4438400 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(long)) : &value);
443 4438400 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_LONG, MPI_SUM, comm));
444 4438400 : memcpy(values, recvbuf, count * sizeof(long));
445 4438400 : if (1 < count) {
446 0 : cp_mpi_free_mem(recvbuf);
447 : }
448 : }
449 : #else
450 800 : (void)comm; // mark used
451 800 : (void)values;
452 800 : (void)count;
453 : #endif
454 4439200 : }
455 :
456 : /*******************************************************************************
457 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
458 : * \author Ole Schuett
459 : ******************************************************************************/
460 710400 : void cp_mpi_sum_int64(int64_t *values, const int count,
461 : const cp_mpi_comm_t comm) {
462 : #if defined(__parallel)
463 710400 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
464 710400 : int64_t value = 0;
465 710400 : void *recvbuf =
466 710400 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(int64_t)) : &value);
467 710400 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT64_T, MPI_SUM, comm));
468 710400 : memcpy(values, recvbuf, count * sizeof(int64_t));
469 710400 : if (1 < count) {
470 0 : cp_mpi_free_mem(recvbuf);
471 : }
472 : }
473 : #else
474 0 : (void)comm; // mark used
475 0 : (void)values;
476 0 : (void)count;
477 : #endif
478 710400 : }
479 :
480 : /*******************************************************************************
481 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_DOUBLE.
482 : * \author Ole Schuett
483 : ******************************************************************************/
484 190 : void cp_mpi_sum_double(double *values, const int count,
485 : const cp_mpi_comm_t comm) {
486 : #if defined(__parallel)
487 190 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
488 190 : double value = 0;
489 190 : void *recvbuf =
490 190 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
491 190 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_SUM, comm));
492 190 : memcpy(values, recvbuf, count * sizeof(double));
493 190 : if (1 < count) {
494 0 : cp_mpi_free_mem(recvbuf);
495 : }
496 : }
497 : #else
498 0 : (void)comm; // mark used
499 0 : (void)values;
500 0 : (void)count;
501 : #endif
502 190 : }
503 :
504 : /*******************************************************************************
505 : * \brief Wrapper around MPI_Sendrecv for datatype MPI_BYTE.
506 : * \author Ole Schuett
507 : ******************************************************************************/
508 33758 : int cp_mpi_sendrecv_byte(const void *sendbuf, const int sendcount,
509 : const int dest, const int sendtag, void *recvbuf,
510 : const int recvcount, const int source,
511 : const int recvtag, const cp_mpi_comm_t comm) {
512 : #if defined(__parallel)
513 33758 : MPI_Status status;
514 33758 : CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_BYTE, dest, sendtag, recvbuf,
515 : recvcount, MPI_BYTE, source, recvtag, comm, &status));
516 33758 : int count_received = 0;
517 33758 : CHECK(MPI_Get_count(&status, MPI_BYTE, &count_received));
518 33758 : return count_received;
519 : #else
520 0 : (void)sendbuf; // mark used
521 0 : (void)sendcount;
522 0 : (void)dest;
523 0 : (void)sendtag;
524 0 : (void)recvbuf;
525 0 : (void)recvcount;
526 0 : (void)source;
527 0 : (void)recvtag;
528 0 : (void)comm;
529 0 : fprintf(stderr, "Error: cp_mpi_sendrecv_byte not available without MPI\n");
530 0 : abort();
531 : #endif
532 : }
533 :
534 : /*******************************************************************************
535 : * \brief Wrapper around MPI_Sendrecv for datatype MPI_DOUBLE.
536 : * \author Ole Schuett
537 : ******************************************************************************/
538 33758 : int cp_mpi_sendrecv_double(const double *sendbuf, const int sendcount,
539 : const int dest, const int sendtag, double *recvbuf,
540 : const int recvcount, const int source,
541 : const int recvtag, const cp_mpi_comm_t comm) {
542 : #if defined(__parallel)
543 33758 : MPI_Status status;
544 33758 : CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_DOUBLE, dest, sendtag, recvbuf,
545 : recvcount, MPI_DOUBLE, source, recvtag, comm, &status));
546 33758 : int count_received;
547 33758 : CHECK(MPI_Get_count(&status, MPI_DOUBLE, &count_received));
548 33758 : return count_received;
549 : #else
550 0 : (void)sendbuf; // mark used
551 0 : (void)sendcount;
552 0 : (void)dest;
553 0 : (void)sendtag;
554 0 : (void)recvbuf;
555 0 : (void)recvcount;
556 0 : (void)source;
557 0 : (void)recvtag;
558 0 : (void)comm;
559 0 : fprintf(stderr, "Error: cp_mpi_sendrecv_double not available without MPI\n");
560 0 : abort();
561 : #endif
562 : }
563 :
564 : /*******************************************************************************
565 : * \brief Wrapper around MPI_Alltoall for datatype MPI_INT.
566 : * \author Ole Schuett
567 : ******************************************************************************/
568 733946 : void cp_mpi_alltoall_int(const int *sendbuf, const int sendcount, int *recvbuf,
569 : const int recvcount, const cp_mpi_comm_t comm) {
570 : #if defined(__parallel)
571 733946 : CHECK(MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT,
572 : comm));
573 : #else
574 0 : (void)comm; // mark used
575 0 : assert(sendcount == recvcount);
576 0 : memcpy(recvbuf, sendbuf, sendcount * sizeof(int));
577 : #endif
578 733946 : }
579 :
580 : /*******************************************************************************
581 : * \brief Wrapper around MPI_Alltoallv for datatype MPI_BYTE.
582 : * \author Ole Schuett
583 : ******************************************************************************/
584 733802 : void cp_mpi_alltoallv_byte(const void *sendbuf, const int *sendcounts,
585 : const int *sdispls, void *recvbuf,
586 : const int *recvcounts, const int *rdispls,
587 : const cp_mpi_comm_t comm) {
588 : #if defined(__parallel)
589 733802 : CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_BYTE, recvbuf,
590 : recvcounts, rdispls, MPI_BYTE, comm));
591 : #else
592 0 : (void)comm; // mark used
593 0 : assert(sendcounts[0] == recvcounts[0]);
594 0 : assert(sdispls[0] == 0 && rdispls[0] == 0);
595 0 : memcpy(recvbuf, sendbuf, sendcounts[0]);
596 : #endif
597 733802 : }
598 :
599 : /*******************************************************************************
600 : * \brief Wrapper around MPI_Alltoallv for datatype MPI_DOUBLE.
601 : * \author Ole Schuett
602 : ******************************************************************************/
603 733946 : void cp_mpi_alltoallv_double(const double *sendbuf, const int *sendcounts,
604 : const int *sdispls, double *recvbuf,
605 : const int *recvcounts, const int *rdispls,
606 : const cp_mpi_comm_t comm) {
607 : #if defined(__parallel)
608 733946 : CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_DOUBLE, recvbuf,
609 : recvcounts, rdispls, MPI_DOUBLE, comm));
610 : #else
611 0 : (void)comm; // mark used
612 0 : assert(sendcounts[0] == recvcounts[0]);
613 0 : assert(sdispls[0] == 0 && rdispls[0] == 0);
614 0 : memcpy(recvbuf, sendbuf, sendcounts[0] * sizeof(double));
615 : #endif
616 733946 : }
617 :
618 : /*******************************************************************************
619 : * \brief Wrapper around MPI_Alloc_mem.
620 : * \author Hans Pabst
621 : ******************************************************************************/
622 3181585 : void *cp_mpi_alloc_mem(size_t size) {
623 3181585 : void *result = NULL;
624 : #if DBM_ALLOC_MPI && defined(__parallel)
625 : CHECK(MPI_Alloc_mem((MPI_Aint)size, MPI_INFO_NULL, &result));
626 : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
627 : result = omp_alloc(size, omp_null_allocator);
628 : #else
629 3181585 : result = malloc(size);
630 : #endif
631 3181585 : return result;
632 : }
633 :
634 : /*******************************************************************************
635 : * \brief Wrapper around MPI_Free_mem.
636 : * \author Hans Pabst
637 : ******************************************************************************/
638 3181585 : void cp_mpi_free_mem(void *mem) {
639 : #if DBM_ALLOC_MPI && defined(__parallel)
640 : CHECK(MPI_Free_mem(mem));
641 : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
642 : omp_free(mem, omp_null_allocator);
643 : #else
644 3181585 : free(mem);
645 : #endif
646 3181585 : }
647 :
648 : // EOF
|