LCOV - code coverage report
Current view: top level - src/dbm - dbm_mpi.c (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 89 106 84.0 %
Date: 2024-12-21 06:28:57 Functions: 20 26 76.9 %

          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      816458 : dbm_mpi_comm_t dbm_mpi_comm_f2c(const int fortran_comm) {
      67             : #if defined(__parallel)
      68      816458 :   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     2421486 : int dbm_mpi_comm_rank(const dbm_mpi_comm_t comm) {
      93             : #if defined(__parallel)
      94     2421486 :   int rank;
      95     2421486 :   CHECK(MPI_Comm_rank(comm, &rank));
      96     2421486 :   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     2421630 : int dbm_mpi_comm_size(const dbm_mpi_comm_t comm) {
     108             : #if defined(__parallel)
     109     2421630 :   int nranks;
     110     2421630 :   CHECK(MPI_Comm_size(comm, &nranks));
     111     2421630 :   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     1614324 : 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     1614324 :   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     1614324 : }
     171             : 
     172             : /*******************************************************************************
     173             :  * \brief Wrapper around MPI_Cart_rank.
     174             :  * \author Ole Schuett
     175             :  ******************************************************************************/
     176   105003511 : int dbm_mpi_cart_rank(const dbm_mpi_comm_t comm, const int coords[]) {
     177             : #if defined(__parallel)
     178   105003511 :   int rank;
     179   105003511 :   CHECK(MPI_Cart_rank(comm, coords, &rank));
     180   105003511 :   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     1614324 : dbm_mpi_comm_t dbm_mpi_cart_sub(const dbm_mpi_comm_t comm,
     193             :                                 const int remain_dims[]) {
     194             : #if defined(__parallel)
     195     1614324 :   dbm_mpi_comm_t newcomm;
     196     1614324 :   CHECK(MPI_Cart_sub(comm, remain_dims, &newcomm));
     197     1614324 :   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     1614324 : void dbm_mpi_comm_free(dbm_mpi_comm_t *comm) {
     210             : #if defined(__parallel)
     211     1614324 :   CHECK(MPI_Comm_free(comm));
     212             : #else
     213             :   (void)comm; // mark used
     214             : #endif
     215     1614324 : }
     216             : 
     217             : /*******************************************************************************
     218             :  * \brief Wrapper around MPI_Comm_compare.
     219             :  * \author Ole Schuett
     220             :  ******************************************************************************/
     221      404070 : bool dbm_mpi_comms_are_similar(const dbm_mpi_comm_t comm1,
     222             :                                const dbm_mpi_comm_t comm2) {
     223             : #if defined(__parallel)
     224      404070 :   int res;
     225      404070 :   CHECK(MPI_Comm_compare(comm1, comm2, &res));
     226      404070 :   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      807852 : void dbm_mpi_max_int(int *values, const int count, const dbm_mpi_comm_t comm) {
     239             : #if defined(__parallel)
     240      807852 :   void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(int));
     241      807852 :   CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_MAX, comm));
     242      807852 :   memcpy(values, recvbuf, count * sizeof(int));
     243      807852 :   dbm_mpi_free_mem(recvbuf);
     244             : #else
     245             :   (void)comm; // mark used
     246             :   (void)values;
     247             :   (void)count;
     248             : #endif
     249      807852 : }
     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      201963 : void dbm_mpi_sum_int(int *values, const int count, const dbm_mpi_comm_t comm) {
     274             : #if defined(__parallel)
     275      201963 :   void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(int));
     276      201963 :   CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT, MPI_SUM, comm));
     277      201963 :   memcpy(values, recvbuf, count * sizeof(int));
     278      201963 :   dbm_mpi_free_mem(recvbuf);
     279             : #else
     280             :   (void)comm; // mark used
     281             :   (void)values;
     282             :   (void)count;
     283             : #endif
     284      201963 : }
     285             : 
     286             : /*******************************************************************************
     287             :  * \brief Wrapper around MPI_Allreduce for op MPI_SUM and datatype MPI_INT64_T.
     288             :  * \author Ole Schuett
     289             :  ******************************************************************************/
     290      796907 : void dbm_mpi_sum_int64(int64_t *values, const int count,
     291             :                        const dbm_mpi_comm_t comm) {
     292             : #if defined(__parallel)
     293      796907 :   void *recvbuf = dbm_mpi_alloc_mem(count * sizeof(int64_t));
     294      796907 :   CHECK(MPI_Allreduce(values, recvbuf, count, MPI_INT64_T, MPI_SUM, comm));
     295      796907 :   memcpy(values, recvbuf, count * sizeof(int64_t));
     296      796907 :   dbm_mpi_free_mem(recvbuf);
     297             : #else
     298             :   (void)comm; // mark used
     299             :   (void)values;
     300             :   (void)count;
     301             : #endif
     302      796907 : }
     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       21800 : 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       21800 :   MPI_Status status;
     332       21800 :   CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_BYTE, dest, sendtag, recvbuf,
     333             :                      recvcount, MPI_BYTE, source, recvtag, comm, &status))
     334       21800 :   int count_received;
     335       21800 :   CHECK(MPI_Get_count(&status, MPI_BYTE, &count_received));
     336       21800 :   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       21800 : 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       21800 :   MPI_Status status;
     362       21800 :   CHECK(MPI_Sendrecv(sendbuf, sendcount, MPI_DOUBLE, dest, sendtag, recvbuf,
     363             :                      recvcount, MPI_DOUBLE, source, recvtag, comm, &status))
     364       21800 :   int count_received;
     365       21800 :   CHECK(MPI_Get_count(&status, MPI_DOUBLE, &count_received));
     366       21800 :   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      851596 : 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      851596 :   CHECK(MPI_Alltoall(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT,
     390      851596 :                      comm));
     391             : #else
     392             :   (void)comm; // mark used
     393             :   assert(sendcount == recvcount);
     394             :   memcpy(recvbuf, sendbuf, sendcount * sizeof(int));
     395             : #endif
     396      851596 : }
     397             : 
     398             : /*******************************************************************************
     399             :  * \brief Wrapper around MPI_Alltoallv for datatype MPI_BYTE.
     400             :  * \author Ole Schuett
     401             :  ******************************************************************************/
     402      425726 : 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      425726 :   CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_BYTE, recvbuf,
     408      425726 :                       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      425726 : }
     416             : 
     417             : /*******************************************************************************
     418             :  * \brief Wrapper around MPI_Alltoallv for datatype MPI_DOUBLE.
     419             :  * \author Ole Schuett
     420             :  ******************************************************************************/
     421      425870 : 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      425870 :   CHECK(MPI_Alltoallv(sendbuf, sendcounts, sdispls, MPI_DOUBLE, recvbuf,
     427      425870 :                       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      425870 : }
     435             : 
     436             : /*******************************************************************************
     437             :  * \brief Wrapper around MPI_Alloc_mem.
     438             :  * \author Hans Pabst
     439             :  ******************************************************************************/
     440     3046996 : void *dbm_mpi_alloc_mem(size_t size) {
     441     3046996 :   void *result = NULL;
     442             : #if defined(__parallel)
     443     3046996 :   CHECK(MPI_Alloc_mem((MPI_Aint)size, MPI_INFO_NULL, &result));
     444             : #else
     445             :   result = malloc(size);
     446             : #endif
     447     3046996 :   return result;
     448             : }
     449             : 
     450             : /*******************************************************************************
     451             :  * \brief Wrapper around MPI_Free_mem.
     452             :  * \author Hans Pabst
     453             :  ******************************************************************************/
     454     3046996 : void dbm_mpi_free_mem(void *mem) {
     455             : #if defined(__parallel)
     456     3046996 :   CHECK(MPI_Free_mem(mem));
     457             : #else
     458             :   free(mem);
     459             : #endif
     460     3046996 : }
     461             : 
     462             : // EOF

Generated by: LCOV version 1.15