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 4901992 : static void assert_outside_parallel(const char *routine_name) {
36 4901992 : 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 4901992 : }
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 0 : cp_mpi_comm_t cp_mpi_get_comm_world(void) {
139 : #if defined(__parallel)
140 0 : 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 1258410 : 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 1258406 : 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 0 : int cp_mpi_comm_c2f(const cp_mpi_comm_t comm) {
165 : #if defined(__parallel)
166 0 : 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 3676494 : int cp_mpi_comm_rank(const cp_mpi_comm_t comm) {
178 : #if defined(__parallel)
179 3676494 : int rank = 0;
180 3676494 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
181 3676494 : CHECK(MPI_Comm_rank(comm, &rank));
182 : }
183 3676494 : 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 3676638 : int cp_mpi_comm_size(const cp_mpi_comm_t comm) {
195 : #if defined(__parallel)
196 3676638 : int nranks = 1;
197 3676638 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
198 3676638 : CHECK(MPI_Comm_size(comm, &nranks));
199 : }
200 3676638 : return nranks;
201 : #else
202 0 : (void)comm; // mark used
203 0 : return 1;
204 : #endif
205 : }
206 :
207 : /*******************************************************************************
208 : * \brief Wrapper around MPI_Dims_create.
209 : * \author Ole Schuett
210 : ******************************************************************************/
211 0 : void cp_mpi_dims_create(const int nnodes, const int ndims, int dims[]) {
212 : #if defined(__parallel)
213 0 : CHECK(MPI_Dims_create(nnodes, ndims, dims));
214 : #else
215 0 : dims[0] = nnodes;
216 0 : for (int i = 1; i < ndims; i++) {
217 0 : dims[i] = 1;
218 : }
219 : #endif
220 0 : }
221 :
222 : /*******************************************************************************
223 : * \brief Wrapper around MPI_Cart_create.
224 : * \author Ole Schuett
225 : ******************************************************************************/
226 0 : cp_mpi_comm_t cp_mpi_cart_create(const cp_mpi_comm_t comm_old, const int ndims,
227 : const int dims[], const int periods[],
228 : const int reorder) {
229 : #if defined(__parallel)
230 0 : assert_outside_parallel("cp_mpi_cart_create");
231 0 : cp_mpi_comm_t comm_cart;
232 0 : CHECK(MPI_Cart_create(comm_old, ndims, dims, periods, reorder, &comm_cart));
233 0 : return comm_cart;
234 : #else
235 0 : (void)comm_old; // mark used
236 0 : (void)ndims;
237 0 : (void)dims;
238 0 : (void)periods;
239 0 : (void)reorder;
240 0 : return -1;
241 : #endif
242 : }
243 :
244 : /*******************************************************************************
245 : * \brief Wrapper around MPI_Cart_get.
246 : * \author Ole Schuett
247 : ******************************************************************************/
248 2450996 : void cp_mpi_cart_get(const cp_mpi_comm_t comm, int maxdims, int dims[],
249 : int periods[], int coords[]) {
250 : #if defined(__parallel)
251 2450996 : CHECK(MPI_Cart_get(comm, maxdims, dims, periods, coords));
252 : #else
253 0 : (void)comm; // mark used
254 0 : for (int i = 0; i < maxdims; i++) {
255 0 : dims[i] = 1;
256 0 : periods[i] = 1;
257 0 : coords[i] = 0;
258 : }
259 : #endif
260 2450996 : }
261 :
262 : /*******************************************************************************
263 : * \brief Wrapper around MPI_Cart_rank.
264 : * \author Ole Schuett
265 : ******************************************************************************/
266 119420491 : int cp_mpi_cart_rank(const cp_mpi_comm_t comm, const int coords[]) {
267 : #if defined(__parallel)
268 119420491 : int rank;
269 119420491 : CHECK(MPI_Cart_rank(comm, coords, &rank));
270 119420491 : return rank;
271 : #else
272 0 : (void)comm; // mark used
273 0 : (void)coords;
274 0 : return 0;
275 : #endif
276 : }
277 :
278 : /*******************************************************************************
279 : * \brief Wrapper around MPI_Cart_sub.
280 : * \author Ole Schuett
281 : ******************************************************************************/
282 2450996 : cp_mpi_comm_t cp_mpi_cart_sub(const cp_mpi_comm_t comm,
283 : const int remain_dims[]) {
284 : #if defined(__parallel)
285 2450996 : assert_outside_parallel("cp_mpi_cart_sub");
286 2450996 : cp_mpi_comm_t newcomm;
287 2450996 : CHECK(MPI_Cart_sub(comm, remain_dims, &newcomm));
288 2450996 : return newcomm;
289 : #else
290 0 : (void)comm; // mark used
291 0 : (void)remain_dims;
292 0 : return -1;
293 : #endif
294 : }
295 :
296 : /*******************************************************************************
297 : * \brief Wrapper around MPI_Comm_free.
298 : * \author Ole Schuett
299 : ******************************************************************************/
300 2450996 : void cp_mpi_comm_free(cp_mpi_comm_t *comm) {
301 : #if defined(__parallel)
302 2450996 : assert_outside_parallel("cp_mpi_comm_free");
303 2450996 : CHECK(MPI_Comm_free(comm));
304 : #else
305 0 : (void)comm; // mark used
306 : #endif
307 2450996 : }
308 :
309 : /*******************************************************************************
310 : * \brief Wrapper around MPI_Comm_compare.
311 : * \author Ole Schuett
312 : ******************************************************************************/
313 698952 : bool cp_mpi_comms_are_similar(const cp_mpi_comm_t comm1,
314 : const cp_mpi_comm_t comm2) {
315 : #if defined(__parallel)
316 698952 : int res;
317 698952 : CHECK(MPI_Comm_compare(comm1, comm2, &res));
318 698952 : return res == MPI_IDENT || res == MPI_CONGRUENT || res == MPI_SIMILAR;
319 : #else
320 0 : (void)comm1; // mark used
321 0 : (void)comm2;
322 0 : return true;
323 : #endif
324 : }
325 :
326 : /*******************************************************************************
327 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_INT.
328 : * \author Ole Schuett
329 : ******************************************************************************/
330 1397616 : void cp_mpi_max_int(int *values, const int count, const cp_mpi_comm_t comm) {
331 : #if defined(__parallel)
332 1397616 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
333 1397616 : int value = 0;
334 1397616 : void *recvbuf =
335 1397616 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
336 1397616 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_MAX, comm));
337 1397616 : memcpy(values, recvbuf, count * sizeof(int));
338 1397616 : if (1 < count) {
339 0 : cp_mpi_free_mem(recvbuf);
340 : }
341 : }
342 : #else
343 0 : (void)comm; // mark used
344 0 : (void)values;
345 0 : (void)count;
346 : #endif
347 1397616 : }
348 :
349 : /*******************************************************************************
350 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_UINT64_T.
351 : * \author Ole Schuett
352 : ******************************************************************************/
353 31524 : void cp_mpi_max_uint64(uint64_t *values, const int count,
354 : const cp_mpi_comm_t comm) {
355 : #if defined(__parallel)
356 31518 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
357 31518 : uint64_t value = 0;
358 31518 : void *recvbuf =
359 31518 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(uint64_t)) : &value);
360 31518 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_UINT64_T, MPI_MAX, comm));
361 31518 : memcpy(values, recvbuf, count * sizeof(uint64_t));
362 31518 : if (1 < count) {
363 0 : cp_mpi_free_mem(recvbuf);
364 : }
365 : }
366 : #else
367 6 : (void)comm; // mark used
368 6 : (void)values;
369 6 : (void)count;
370 : #endif
371 31524 : }
372 :
373 : /*******************************************************************************
374 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_DOUBLE.
375 : * \author Ole Schuett
376 : ******************************************************************************/
377 48 : void cp_mpi_max_double(double *values, const int count,
378 : const cp_mpi_comm_t comm) {
379 : #if defined(__parallel)
380 48 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
381 48 : double value = 0;
382 48 : void *recvbuf =
383 48 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
384 48 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_MAX, comm));
385 48 : memcpy(values, recvbuf, count * sizeof(double));
386 48 : if (1 < count) {
387 0 : cp_mpi_free_mem(recvbuf);
388 : }
389 : }
390 : #else
391 0 : (void)comm; // mark used
392 0 : (void)values;
393 0 : (void)count;
394 : #endif
395 48 : }
396 :
397 : /*******************************************************************************
398 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT.
399 : * \author Ole Schuett
400 : ******************************************************************************/
401 349404 : void cp_mpi_sum_int(int *values, const int count, const cp_mpi_comm_t comm) {
402 : #if defined(__parallel)
403 349404 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
404 349404 : int value = 0;
405 349404 : void *recvbuf =
406 349404 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(int)) : &value);
407 349404 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_SUM, comm));
408 349404 : memcpy(values, recvbuf, count * sizeof(int));
409 349404 : if (1 < count) {
410 346757 : cp_mpi_free_mem(recvbuf);
411 : }
412 : }
413 : #else
414 0 : (void)comm; // mark used
415 0 : (void)values;
416 0 : (void)count;
417 : #endif
418 349404 : }
419 :
420 : /*******************************************************************************
421 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_LONG.
422 : * \author Hans Pabst
423 : ******************************************************************************/
424 4388000 : void cp_mpi_sum_long(long *values, const int count, const cp_mpi_comm_t comm) {
425 : #if defined(__parallel)
426 4387200 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
427 4387200 : long value = 0;
428 4387200 : void *recvbuf =
429 4387200 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(long)) : &value);
430 4387200 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_LONG, MPI_SUM, comm));
431 4387200 : memcpy(values, recvbuf, count * sizeof(long));
432 4387200 : if (1 < count) {
433 0 : cp_mpi_free_mem(recvbuf);
434 : }
435 : }
436 : #else
437 800 : (void)comm; // mark used
438 800 : (void)values;
439 800 : (void)count;
440 : #endif
441 4388000 : }
442 :
443 : /*******************************************************************************
444 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
445 : * \author Ole Schuett
446 : ******************************************************************************/
447 702208 : void cp_mpi_sum_int64(int64_t *values, const int count,
448 : const cp_mpi_comm_t comm) {
449 : #if defined(__parallel)
450 702208 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
451 702208 : int64_t value = 0;
452 702208 : void *recvbuf =
453 702208 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(int64_t)) : &value);
454 702208 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT64_T, MPI_SUM, comm));
455 702208 : memcpy(values, recvbuf, count * sizeof(int64_t));
456 702208 : if (1 < count) {
457 0 : cp_mpi_free_mem(recvbuf);
458 : }
459 : }
460 : #else
461 0 : (void)comm; // mark used
462 0 : (void)values;
463 0 : (void)count;
464 : #endif
465 702208 : }
466 :
467 : /*******************************************************************************
468 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_DOUBLE.
469 : * \author Ole Schuett
470 : ******************************************************************************/
471 190 : void cp_mpi_sum_double(double *values, const int count,
472 : const cp_mpi_comm_t comm) {
473 : #if defined(__parallel)
474 190 : if (MPI_COMM_NULL != comm) { // !MPI_Comm_compare
475 190 : double value = 0;
476 190 : void *recvbuf =
477 190 : (1 < count ? cp_mpi_alloc_mem(count * sizeof(double)) : &value);
478 190 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_SUM, comm));
479 190 : memcpy(values, recvbuf, count * sizeof(double));
480 190 : if (1 < count) {
481 0 : cp_mpi_free_mem(recvbuf);
482 : }
483 : }
484 : #else
485 0 : (void)comm; // mark used
486 0 : (void)values;
487 0 : (void)count;
488 : #endif
489 190 : }
490 :
491 : /*******************************************************************************
492 : * \brief Wrapper around MPI_Sendrecv for datatype MPI_BYTE.
493 : * \author Ole Schuett
494 : ******************************************************************************/
495 33686 : int cp_mpi_sendrecv_byte(const void *sendbuf, const int sendcount,
496 : const int dest, const int sendtag, void *recvbuf,
497 : const int recvcount, const int source,
498 : const int recvtag, const cp_mpi_comm_t comm) {
499 : #if defined(__parallel)
500 33686 : MPI_Status status;
501 33686 : CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_BYTE, dest, sendtag, recvbuf,
502 : recvcount, MPI_BYTE, source, recvtag, comm, &status));
503 33686 : int count_received = 0;
504 33686 : CHECK(MPI_Get_count(&status, MPI_BYTE, &count_received));
505 33686 : return count_received;
506 : #else
507 0 : (void)sendbuf; // mark used
508 0 : (void)sendcount;
509 0 : (void)dest;
510 0 : (void)sendtag;
511 0 : (void)recvbuf;
512 0 : (void)recvcount;
513 0 : (void)source;
514 0 : (void)recvtag;
515 0 : (void)comm;
516 0 : fprintf(stderr, "Error: cp_mpi_sendrecv_byte not available without MPI\n");
517 0 : abort();
518 : #endif
519 : }
520 :
521 : /*******************************************************************************
522 : * \brief Wrapper around MPI_Sendrecv for datatype MPI_DOUBLE.
523 : * \author Ole Schuett
524 : ******************************************************************************/
525 33686 : int cp_mpi_sendrecv_double(const double *sendbuf, const int sendcount,
526 : const int dest, const int sendtag, double *recvbuf,
527 : const int recvcount, const int source,
528 : const int recvtag, const cp_mpi_comm_t comm) {
529 : #if defined(__parallel)
530 33686 : MPI_Status status;
531 33686 : CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_DOUBLE, dest, sendtag, recvbuf,
532 : recvcount, MPI_DOUBLE, source, recvtag, comm, &status));
533 33686 : int count_received;
534 33686 : CHECK(MPI_Get_count(&status, MPI_DOUBLE, &count_received));
535 33686 : return count_received;
536 : #else
537 0 : (void)sendbuf; // mark used
538 0 : (void)sendcount;
539 0 : (void)dest;
540 0 : (void)sendtag;
541 0 : (void)recvbuf;
542 0 : (void)recvcount;
543 0 : (void)source;
544 0 : (void)recvtag;
545 0 : (void)comm;
546 0 : fprintf(stderr, "Error: cp_mpi_sendrecv_double not available without MPI\n");
547 0 : abort();
548 : #endif
549 : }
550 :
551 : /*******************************************************************************
552 : * \brief Wrapper around MPI_Alltoall for datatype MPI_INT.
553 : * \author Ole Schuett
554 : ******************************************************************************/
555 732638 : void cp_mpi_alltoall_int(const int *sendbuf, const int sendcount, int *recvbuf,
556 : const int recvcount, const cp_mpi_comm_t comm) {
557 : #if defined(__parallel)
558 732638 : CHECK(MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT,
559 : comm));
560 : #else
561 0 : (void)comm; // mark used
562 0 : assert(sendcount == recvcount);
563 0 : memcpy(recvbuf, sendbuf, sendcount * sizeof(int));
564 : #endif
565 732638 : }
566 :
567 : /*******************************************************************************
568 : * \brief Wrapper around MPI_Alltoallv for datatype MPI_BYTE.
569 : * \author Ole Schuett
570 : ******************************************************************************/
571 732494 : void cp_mpi_alltoallv_byte(const void *sendbuf, const int *sendcounts,
572 : const int *sdispls, void *recvbuf,
573 : const int *recvcounts, const int *rdispls,
574 : const cp_mpi_comm_t comm) {
575 : #if defined(__parallel)
576 732494 : CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_BYTE, recvbuf,
577 : recvcounts, rdispls, MPI_BYTE, comm));
578 : #else
579 0 : (void)comm; // mark used
580 0 : assert(sendcounts[0] == recvcounts[0]);
581 0 : assert(sdispls[0] == 0 && rdispls[0] == 0);
582 0 : memcpy(recvbuf, sendbuf, sendcounts[0]);
583 : #endif
584 732494 : }
585 :
586 : /*******************************************************************************
587 : * \brief Wrapper around MPI_Alltoallv for datatype MPI_DOUBLE.
588 : * \author Ole Schuett
589 : ******************************************************************************/
590 732638 : void cp_mpi_alltoallv_double(const double *sendbuf, const int *sendcounts,
591 : const int *sdispls, double *recvbuf,
592 : const int *recvcounts, const int *rdispls,
593 : const cp_mpi_comm_t comm) {
594 : #if defined(__parallel)
595 732638 : CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_DOUBLE, recvbuf,
596 : recvcounts, rdispls, MPI_DOUBLE, comm));
597 : #else
598 0 : (void)comm; // mark used
599 0 : assert(sendcounts[0] == recvcounts[0]);
600 0 : assert(sdispls[0] == 0 && rdispls[0] == 0);
601 0 : memcpy(recvbuf, sendbuf, sendcounts[0] * sizeof(double));
602 : #endif
603 732638 : }
604 :
605 : /*******************************************************************************
606 : * \brief Wrapper around MPI_Alloc_mem.
607 : * \author Hans Pabst
608 : ******************************************************************************/
609 3175963 : void *cp_mpi_alloc_mem(size_t size) {
610 3175963 : void *result = NULL;
611 : #if DBM_ALLOC_MPI && defined(__parallel)
612 : CHECK(MPI_Alloc_mem((MPI_Aint)size, MPI_INFO_NULL, &result));
613 : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
614 : result = omp_alloc(size, omp_null_allocator);
615 : #else
616 3175963 : result = malloc(size);
617 : #endif
618 3175963 : return result;
619 : }
620 :
621 : /*******************************************************************************
622 : * \brief Wrapper around MPI_Free_mem.
623 : * \author Hans Pabst
624 : ******************************************************************************/
625 3175963 : void cp_mpi_free_mem(void *mem) {
626 : #if DBM_ALLOC_MPI && defined(__parallel)
627 : CHECK(MPI_Free_mem(mem));
628 : #elif DBM_ALLOC_OPENMP && (201811 /*v5.0*/ <= _OPENMP)
629 : omp_free(mem, omp_null_allocator);
630 : #else
631 3175963 : free(mem);
632 : #endif
633 3175963 : }
634 :
635 : // EOF
|