Line data Source code
1 : /*----------------------------------------------------------------------------*/
2 : /* CP2K: A general program to perform molecular dynamics simulations */
3 : /* Copyright 2000-2024 CP2K developers group <https://cp2k.org> */
4 : /* */
5 : /* SPDX-License-Identifier: BSD-3-Clause */
6 : /*----------------------------------------------------------------------------*/
7 :
8 : #include <assert.h>
9 : #include <stdio.h>
10 : #include <stdlib.h>
11 : #include <string.h>
12 :
13 : #include "dbm_mpi.h"
14 :
15 : #if defined(__parallel)
16 : /*******************************************************************************
17 : * \brief Check given MPI status and upon failure abort with a nice message.
18 : * \author Ole Schuett
19 : ******************************************************************************/
20 : #define CHECK(status) \
21 : if (status != MPI_SUCCESS) { \
22 : fprintf(stderr, "MPI error in %s:%i\n", __FILE__, __LINE__); \
23 : MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE); \
24 : }
25 : #endif
26 :
27 : /*******************************************************************************
28 : * \brief Wrapper around MPI_Init.
29 : * \author Ole Schuett
30 : ******************************************************************************/
31 0 : void dbm_mpi_init(int *argc, char ***argv) {
32 : #if defined(__parallel)
33 0 : CHECK(MPI_Init(argc, argv));
34 : #else
35 : (void)argc; // mark used
36 : (void)argv;
37 : #endif
38 0 : }
39 :
40 : /*******************************************************************************
41 : * \brief Wrapper around MPI_Finalize.
42 : * \author Ole Schuett
43 : ******************************************************************************/
44 0 : void dbm_mpi_finalize() {
45 : #if defined(__parallel)
46 0 : CHECK(MPI_Finalize());
47 : #endif
48 0 : }
49 :
50 : /*******************************************************************************
51 : * \brief Returns MPI_COMM_WORLD.
52 : * \author Ole Schuett
53 : ******************************************************************************/
54 0 : dbm_mpi_comm_t dbm_mpi_get_comm_world() {
55 : #if defined(__parallel)
56 0 : return MPI_COMM_WORLD;
57 : #else
58 : return -1;
59 : #endif
60 : }
61 :
62 : /*******************************************************************************
63 : * \brief Wrapper around MPI_Comm_f2c.
64 : * \author Ole Schuett
65 : ******************************************************************************/
66 676802 : dbm_mpi_comm_t dbm_mpi_comm_f2c(const int fortran_comm) {
67 : #if defined(__parallel)
68 676802 : return MPI_Comm_f2c(fortran_comm);
69 : #else
70 : (void)fortran_comm; // mark used
71 : return -1;
72 : #endif
73 : }
74 :
75 : /*******************************************************************************
76 : * \brief Wrapper around MPI_Comm_c2f.
77 : * \author Ole Schuett
78 : ******************************************************************************/
79 0 : int dbm_mpi_comm_c2f(const dbm_mpi_comm_t comm) {
80 : #if defined(__parallel)
81 0 : return MPI_Comm_c2f(comm);
82 : #else
83 : (void)comm; // mark used
84 : return -1;
85 : #endif
86 : }
87 :
88 : /*******************************************************************************
89 : * \brief Wrapper around MPI_Comm_rank.
90 : * \author Ole Schuett
91 : ******************************************************************************/
92 2004756 : int dbm_mpi_comm_rank(const dbm_mpi_comm_t comm) {
93 : #if defined(__parallel)
94 2004756 : int rank;
95 2004756 : CHECK(MPI_Comm_rank(comm, &rank));
96 2004756 : return rank;
97 : #else
98 : (void)comm; // mark used
99 : return 0;
100 : #endif
101 : }
102 :
103 : /*******************************************************************************
104 : * \brief Wrapper around MPI_Comm_size.
105 : * \author Ole Schuett
106 : ******************************************************************************/
107 2004900 : int dbm_mpi_comm_size(const dbm_mpi_comm_t comm) {
108 : #if defined(__parallel)
109 2004900 : int nranks;
110 2004900 : CHECK(MPI_Comm_size(comm, &nranks));
111 2004900 : return nranks;
112 : #else
113 : (void)comm; // mark used
114 : return 1;
115 : #endif
116 : }
117 :
118 : /*******************************************************************************
119 : * \brief Wrapper around MPI_Dims_create.
120 : * \author Ole Schuett
121 : ******************************************************************************/
122 0 : void dbm_mpi_dims_create(const int nnodes, const int ndims, int dims[]) {
123 : #if defined(__parallel)
124 0 : CHECK(MPI_Dims_create(nnodes, ndims, dims));
125 : #else
126 : dims[0] = nnodes;
127 : for (int i = 1; i < ndims; i++) {
128 : dims[i] = 1;
129 : }
130 : #endif
131 0 : }
132 :
133 : /*******************************************************************************
134 : * \brief Wrapper around MPI_Cart_create.
135 : * \author Ole Schuett
136 : ******************************************************************************/
137 0 : dbm_mpi_comm_t dbm_mpi_cart_create(const dbm_mpi_comm_t comm_old,
138 : const int ndims, const int dims[],
139 : const int periods[], const int reorder) {
140 : #if defined(__parallel)
141 0 : dbm_mpi_comm_t comm_cart;
142 0 : CHECK(MPI_Cart_create(comm_old, ndims, dims, periods, reorder, &comm_cart));
143 0 : return comm_cart;
144 : #else
145 : (void)comm_old; // mark used
146 : (void)ndims;
147 : (void)dims;
148 : (void)periods;
149 : (void)reorder;
150 : return -1;
151 : #endif
152 : }
153 :
154 : /*******************************************************************************
155 : * \brief Wrapper around MPI_Cart_get.
156 : * \author Ole Schuett
157 : ******************************************************************************/
158 1336504 : void dbm_mpi_cart_get(const dbm_mpi_comm_t comm, int maxdims, int dims[],
159 : int periods[], int coords[]) {
160 : #if defined(__parallel)
161 1336504 : CHECK(MPI_Cart_get(comm, maxdims, dims, periods, coords));
162 : #else
163 : (void)comm; // mark used
164 : for (int i = 0; i < maxdims; i++) {
165 : dims[i] = 1;
166 : periods[i] = 1;
167 : coords[i] = 0;
168 : }
169 : #endif
170 1336504 : }
171 :
172 : /*******************************************************************************
173 : * \brief Wrapper around MPI_Cart_rank.
174 : * \author Ole Schuett
175 : ******************************************************************************/
176 105759419 : int dbm_mpi_cart_rank(const dbm_mpi_comm_t comm, const int coords[]) {
177 : #if defined(__parallel)
178 105759419 : int rank;
179 105759419 : CHECK(MPI_Cart_rank(comm, coords, &rank));
180 105759419 : return rank;
181 : #else
182 : (void)comm; // mark used
183 : (void)coords;
184 : return 0;
185 : #endif
186 : }
187 :
188 : /*******************************************************************************
189 : * \brief Wrapper around MPI_Cart_sub.
190 : * \author Ole Schuett
191 : ******************************************************************************/
192 1336504 : dbm_mpi_comm_t dbm_mpi_cart_sub(const dbm_mpi_comm_t comm,
193 : const int remain_dims[]) {
194 : #if defined(__parallel)
195 1336504 : dbm_mpi_comm_t newcomm;
196 1336504 : CHECK(MPI_Cart_sub(comm, remain_dims, &newcomm));
197 1336504 : return newcomm;
198 : #else
199 : (void)comm; // mark used
200 : (void)remain_dims;
201 : return -1;
202 : #endif
203 : }
204 :
205 : /*******************************************************************************
206 : * \brief Wrapper around MPI_Comm_free.
207 : * \author Ole Schuett
208 : ******************************************************************************/
209 1336504 : void dbm_mpi_comm_free(dbm_mpi_comm_t *comm) {
210 : #if defined(__parallel)
211 1336504 : CHECK(MPI_Comm_free(comm));
212 : #else
213 : (void)comm; // mark used
214 : #endif
215 1336504 : }
216 :
217 : /*******************************************************************************
218 : * \brief Wrapper around MPI_Comm_compare.
219 : * \author Ole Schuett
220 : ******************************************************************************/
221 314082 : bool dbm_mpi_comms_are_similar(const dbm_mpi_comm_t comm1,
222 : const dbm_mpi_comm_t comm2) {
223 : #if defined(__parallel)
224 314082 : int res;
225 314082 : CHECK(MPI_Comm_compare(comm1, comm2, &res));
226 314082 : return res == MPI_IDENT || res == MPI_CONGRUENT || res == MPI_SIMILAR;
227 : #else
228 : (void)comm1; // mark used
229 : (void)comm2;
230 : return true;
231 : #endif
232 : }
233 :
234 : /*******************************************************************************
235 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_INT.
236 : * \author Ole Schuett
237 : ******************************************************************************/
238 627876 : void dbm_mpi_max_int(int *values, const int count, const dbm_mpi_comm_t comm) {
239 : #if defined(__parallel)
240 627876 : void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(int));
241 627876 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_MAX, comm));
242 627876 : memcpy(values, recvbuf, count * sizeof(int));
243 627876 : dbm_mpi_free_mem(recvbuf);
244 : #else
245 : (void)comm; // mark used
246 : (void)values;
247 : (void)count;
248 : #endif
249 627876 : }
250 :
251 : /*******************************************************************************
252 : * \brief Wrapper around MPI_Allreduce for op MPI_MAX and datatype MPI_DOUBLE.
253 : * \author Ole Schuett
254 : ******************************************************************************/
255 48 : void dbm_mpi_max_double(double *values, const int count,
256 : const dbm_mpi_comm_t comm) {
257 : #if defined(__parallel)
258 48 : void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(double));
259 48 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_MAX, comm));
260 48 : memcpy(values, recvbuf, count * sizeof(double));
261 48 : dbm_mpi_free_mem(recvbuf);
262 : #else
263 : (void)comm; // mark used
264 : (void)values;
265 : (void)count;
266 : #endif
267 48 : }
268 :
269 : /*******************************************************************************
270 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT.
271 : * \author Ole Schuett
272 : ******************************************************************************/
273 156969 : void dbm_mpi_sum_int(int *values, const int count, const dbm_mpi_comm_t comm) {
274 : #if defined(__parallel)
275 156969 : void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(int));
276 156969 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_SUM, comm));
277 156969 : memcpy(values, recvbuf, count * sizeof(int));
278 156969 : dbm_mpi_free_mem(recvbuf);
279 : #else
280 : (void)comm; // mark used
281 : (void)values;
282 : (void)count;
283 : #endif
284 156969 : }
285 :
286 : /*******************************************************************************
287 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
288 : * \author Ole Schuett
289 : ******************************************************************************/
290 704169 : void dbm_mpi_sum_int64(int64_t *values, const int count,
291 : const dbm_mpi_comm_t comm) {
292 : #if defined(__parallel)
293 704169 : void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(int64_t));
294 704169 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT64_T, MPI_SUM, comm));
295 704169 : memcpy(values, recvbuf, count * sizeof(int64_t));
296 704169 : dbm_mpi_free_mem(recvbuf);
297 : #else
298 : (void)comm; // mark used
299 : (void)values;
300 : (void)count;
301 : #endif
302 704169 : }
303 :
304 : /*******************************************************************************
305 : * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_DOUBLE.
306 : * \author Ole Schuett
307 : ******************************************************************************/
308 190 : void dbm_mpi_sum_double(double *values, const int count,
309 : const dbm_mpi_comm_t comm) {
310 : #if defined(__parallel)
311 190 : void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(double));
312 190 : CHECK(MPI_Allreduce(values, recvbuf, count, MPI_DOUBLE, MPI_SUM, comm));
313 190 : memcpy(values, recvbuf, count * sizeof(double));
314 190 : dbm_mpi_free_mem(recvbuf);
315 : #else
316 : (void)comm; // mark used
317 : (void)values;
318 : (void)count;
319 : #endif
320 190 : }
321 :
322 : /*******************************************************************************
323 : * \brief Wrapper around MPI_Sendrecv for datatype MPI_BYTE.
324 : * \author Ole Schuett
325 : ******************************************************************************/
326 6660 : int dbm_mpi_sendrecv_byte(const void *sendbuf, const int sendcount,
327 : const int dest, const int sendtag, void *recvbuf,
328 : const int recvcount, const int source,
329 : const int recvtag, const dbm_mpi_comm_t comm) {
330 : #if defined(__parallel)
331 6660 : MPI_Status status;
332 6660 : CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_BYTE, dest, sendtag, recvbuf,
333 : recvcount, MPI_BYTE, source, recvtag, comm, &status))
334 6660 : int count_received;
335 6660 : CHECK(MPI_Get_count(&status, MPI_BYTE, &count_received));
336 6660 : return count_received;
337 : #else
338 : (void)sendbuf; // mark used
339 : (void)sendcount;
340 : (void)dest;
341 : (void)sendtag;
342 : (void)recvbuf;
343 : (void)recvcount;
344 : (void)source;
345 : (void)recvtag;
346 : (void)comm;
347 : fprintf(stderr, "Error: dbm_mpi_sendrecv_byte not available without MPI\n");
348 : abort();
349 : #endif
350 : }
351 :
352 : /*******************************************************************************
353 : * \brief Wrapper around MPI_Sendrecv for datatype MPI_DOUBLE.
354 : * \author Ole Schuett
355 : ******************************************************************************/
356 6660 : int dbm_mpi_sendrecv_double(const double *sendbuf, const int sendcount,
357 : const int dest, const int sendtag, double *recvbuf,
358 : const int recvcount, const int source,
359 : const int recvtag, const dbm_mpi_comm_t comm) {
360 : #if defined(__parallel)
361 6660 : MPI_Status status;
362 6660 : CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_DOUBLE, dest, sendtag, recvbuf,
363 : recvcount, MPI_DOUBLE, source, recvtag, comm, &status))
364 6660 : int count_received;
365 6660 : CHECK(MPI_Get_count(&status, MPI_DOUBLE, &count_received));
366 6660 : return count_received;
367 : #else
368 : (void)sendbuf; // mark used
369 : (void)sendcount;
370 : (void)dest;
371 : (void)sendtag;
372 : (void)recvbuf;
373 : (void)recvcount;
374 : (void)source;
375 : (void)recvtag;
376 : (void)comm;
377 : fprintf(stderr, "Error: dbm_mpi_sendrecv_double not available without MPI\n");
378 : abort();
379 : #endif
380 : }
381 :
382 : /*******************************************************************************
383 : * \brief Wrapper around MPI_Alltoall for datatype MPI_INT.
384 : * \author Ole Schuett
385 : ******************************************************************************/
386 641340 : void dbm_mpi_alltoall_int(const int *sendbuf, const int sendcount, int *recvbuf,
387 : const int recvcount, const dbm_mpi_comm_t comm) {
388 : #if defined(__parallel)
389 641340 : CHECK(MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT,
390 641340 : comm));
391 : #else
392 : (void)comm; // mark used
393 : assert(sendcount == recvcount);
394 : memcpy(recvbuf, sendbuf, sendcount * sizeof(int));
395 : #endif
396 641340 : }
397 :
398 : /*******************************************************************************
399 : * \brief Wrapper around MPI_Alltoallv for datatype MPI_BYTE.
400 : * \author Ole Schuett
401 : ******************************************************************************/
402 320598 : void dbm_mpi_alltoallv_byte(const void *sendbuf, const int *sendcounts,
403 : const int *sdispls, void *recvbuf,
404 : const int *recvcounts, const int *rdispls,
405 : const dbm_mpi_comm_t comm) {
406 : #if defined(__parallel)
407 320598 : CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_BYTE, recvbuf,
408 320598 : recvcounts, rdispls, MPI_BYTE, comm));
409 : #else
410 : (void)comm; // mark used
411 : assert(sendcounts[0] == recvcounts[0]);
412 : assert(sdispls[0] == 0 && rdispls[0] == 0);
413 : memcpy(recvbuf, sendbuf, sendcounts[0]);
414 : #endif
415 320598 : }
416 :
417 : /*******************************************************************************
418 : * \brief Wrapper around MPI_Alltoallv for datatype MPI_DOUBLE.
419 : * \author Ole Schuett
420 : ******************************************************************************/
421 320742 : void dbm_mpi_alltoallv_double(const double *sendbuf, const int *sendcounts,
422 : const int *sdispls, double *recvbuf,
423 : const int *recvcounts, const int *rdispls,
424 : const dbm_mpi_comm_t comm) {
425 : #if defined(__parallel)
426 320742 : CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_DOUBLE, recvbuf,
427 320742 : recvcounts, rdispls, MPI_DOUBLE, comm));
428 : #else
429 : (void)comm; // mark used
430 : assert(sendcounts[0] == recvcounts[0]);
431 : assert(sdispls[0] == 0 && rdispls[0] == 0);
432 : memcpy(recvbuf, sendbuf, sendcounts[0] * sizeof(double));
433 : #endif
434 320742 : }
435 :
436 : /*******************************************************************************
437 : * \brief Wrapper around MPI_Alloc_mem.
438 : * \author Hans Pabst
439 : ******************************************************************************/
440 2443765 : void *dbm_mpi_alloc_mem(size_t size) {
441 2443765 : void *result = NULL;
442 : #if defined(__parallel)
443 2443765 : CHECK(MPI_Alloc_mem((MPI_Aint)size, MPI_INFO_NULL, &result));
444 : #else
445 : result = malloc(size);
446 : #endif
447 2443765 : return result;
448 : }
449 :
450 : /*******************************************************************************
451 : * \brief Wrapper around MPI_Free_mem.
452 : * \author Hans Pabst
453 : ******************************************************************************/
454 2443765 : void dbm_mpi_free_mem(void *mem) {
455 : #if defined(__parallel)
456 2443765 : CHECK(MPI_Free_mem(mem));
457 : #else
458 : free(mem);
459 : #endif
460 2443765 : }
461 :
462 : // EOF
|