LCOV - code coverage report
Current view: top level - tools - Communicator.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 40 43 93.0 %
Date: 2024-10-18 14:00:25 Functions: 56 60 93.3 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2011-2023 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #ifndef __PLUMED_tools_Communicator_h
      23             : #define __PLUMED_tools_Communicator_h
      24             : #ifdef __PLUMED_HAS_MPI
      25             : #include <mpi.h>
      26             : #endif
      27             : #include <cstdlib>
      28             : #include "Exception.h"
      29             : #include "TypesafePtr.h"
      30             : #include <vector>
      31             : #include <string>
      32             : #include "Vector.h"
      33             : #include "Tensor.h"
      34             : #include "Matrix.h"
      35             : 
      36             : namespace PLMD {
      37             : 
      38             : #ifndef  __PLUMED_HAS_MPI
      39             : /// Surrogate of MPI_Comm when MPI library is not available
      40             : class MPI_Comm {};
      41             : /// Surrogate of MPI_Datatype when MPI library is not available
      42             : class MPI_Datatype {};
      43             : /// Surrogate of MPI_Status when MPI library is not available
      44             : class MPI_Status {};
      45             : /// Surrogate of MPI_Request when MPI library is not available
      46             : class MPI_Request {};
      47             : #endif
      48             : 
      49             : /// \ingroup TOOLBOX
      50             : /// Class containing wrappers to MPI.
      51             : /// All the MPI related stuff is relegated here.
      52             : class Communicator {
      53             : /// Communicator
      54             :   MPI_Comm communicator;
      55             : /// Function returning the MPI type.
      56             : /// You can use it to access to the MPI type of a C++ type, e.g.
      57             : /// `MPI_Datatype type=getMPIType<double>();`
      58             :   template <class T>
      59             :   static MPI_Datatype getMPIType();
      60             : /// Structure defining a buffer for MPI.
      61             : /// It contains info on the pointed data and its type and size. It is useful to
      62             : /// allow wrapper of MPI functions where the triplet (buffer,type,size)
      63             : /// is grouped into a single object. It can be built starting from
      64             : /// different kinds of data. To implement compatibility of MPI wrappers
      65             : /// with e.g. vectors, add constructors here.
      66             :   struct Data {
      67             :     void*pointer;
      68             :     int size;
      69             :     int nbytes=0;
      70             :     MPI_Datatype type;
      71             : /// Init from pointer and size
      72     2918535 :     template <typename T> Data(T*p,int s): pointer(p), size(s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      73             : /// Init from reference
      74    14584458 :     template <typename T> explicit Data(T&p): pointer(&p), size(1), nbytes(sizeof(T)), type(getMPIType<T>()) {}
      75             : /// Init from pointer to VectorGeneric
      76       11179 :     template <unsigned n> explicit Data(VectorGeneric<n> *p,int s): pointer(p), size(n*s), nbytes(sizeof(double)), type(getMPIType<double>()) {}
      77             : /// Init from reference to VectorGeneric
      78             :     template <unsigned n> explicit Data(VectorGeneric<n> &p): pointer(&p), size(n), nbytes(sizeof(double)), type(getMPIType<double>()) {}
      79             : /// Init from pointer to TensorGeneric
      80          16 :     template <unsigned n,unsigned m> explicit Data(TensorGeneric<n,m> *p,int s): pointer(p), size(n*m*s), nbytes(sizeof(double)), type(getMPIType<double>()) {}
      81             : /// Init from reference to TensorGeneric
      82       41550 :     template <unsigned n,unsigned m> explicit Data(TensorGeneric<n,m> &p): pointer(&p), size(n*m), nbytes(sizeof(double)), type(getMPIType<double>()) {}
      83             : /// Init from reference to std::vector
      84     2652079 :     template <typename T> explicit Data(std::vector<T>&v) {
      85     2652250 :       Data d(v.data(),v.size()); pointer=d.pointer; size=d.size; type=d.type;
      86     2652079 :     }
      87             : /// Init from reference to PLMD::Matrix
      88             :     template <typename T> explicit Data(Matrix<T>&m ) {
      89             :       if(m.nrows()*m.ncols()>0) { Data d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; }
      90             :       else { pointer=NULL; size=0; }
      91             :     }
      92             : /// Init from reference to std::string
      93          61 :     explicit Data(std::string&s) {
      94          61 :       if(s.size()>0) { Data d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; }
      95           0 :       else { pointer=NULL; size=0; }
      96          61 :     }
      97             :   };
      98             : /// Const version of Communicator::Data
      99             : /// See Communicator::Data documentation
     100             :   struct ConstData {
     101             :     const void*pointer;
     102             :     int size;
     103             :     int nbytes=0;
     104             :     MPI_Datatype type;
     105       24124 :     template <typename T> explicit ConstData(const T*p,int s): pointer(p), size(s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     106         952 :     template <typename T> explicit ConstData(const T&p): pointer(&p), size(1), nbytes(sizeof(T)), type(getMPIType<T>()) {}
     107             :     template <unsigned n> explicit ConstData(const VectorGeneric<n> *p,int s): pointer(p), size(n*s), nbytes(sizeof(double)), type(getMPIType<double>()) {}
     108             :     template <unsigned n> explicit ConstData(const VectorGeneric<n> &p): pointer(&p), size(n), nbytes(sizeof(double)), type(getMPIType<double>()) {}
     109             :     template <unsigned n,unsigned m> explicit ConstData(const TensorGeneric<n,m> *p,int s): pointer(p), size(n*m*s), nbytes(sizeof(double)), type(getMPIType<double>()) {}
     110             :     template <unsigned n,unsigned m> explicit ConstData(const TensorGeneric<n,m> &p): pointer(&p), size(n*m), nbytes(sizeof(double)), type(getMPIType<double>()) {}
     111        4956 :     template <typename T> explicit ConstData(const std::vector<T>&v) {
     112        4956 :       ConstData d(v.data(),v.size()); pointer=d.pointer; size=d.size; type=d.type;
     113        4956 :     }
     114             :     template <typename T> explicit ConstData(const Matrix<T>&m ) {
     115             :       if(m.nrows()*m.ncols()>0) { ConstData d(&m(0,0),m.nrows()*m.ncols()); pointer=d.pointer; size=d.size; type=d.type; }
     116             :       else { pointer=NULL; size=0; }
     117             :     }
     118          57 :     explicit ConstData(const std::string&s) {
     119          57 :       if(s.size()>0) { ConstData d(&s[0],s.size()); pointer=d.pointer; size=d.size; type=d.type; }
     120           0 :       else { pointer=NULL; size=0; }
     121          57 :     }
     122             :   };
     123             : public:
     124             :   ///Runtime acces to the __PLUMED_HAS_MPI definition
     125             :   static bool plumedHasMPI();
     126             : 
     127             : /// Wrapper class for MPI_Status
     128             :   class Status {
     129             :     int Get_count(MPI_Datatype)const;
     130             :   public:
     131             :     MPI_Status s;
     132             :     template <class T>
     133        7634 :     int Get_count()const {return Get_count(getMPIType<T>());}
     134             :   };
     135             : /// Special status used when status should be ignored.
     136             : /// E.g. `Recv(a,0,1,Communicator::StatusIgnore);`
     137             : /// Notice that this is the default for Recv, so this is equivalent to
     138             : /// `Recv(a,0,1);`
     139             :   static Status StatusIgnore;
     140             : /// Wrapper class for MPI_Request
     141             :   class Request {
     142             :   public:
     143             :     MPI_Request r;
     144             :     void wait(Status&s=StatusIgnore);
     145             :   };
     146             : /// Default constructor
     147             :   Communicator();
     148             : /// Copy constructor.
     149             : /// It effectively "clones" the communicator, providing a new one acting on the same group
     150             :   Communicator(const Communicator&);
     151             : /// Assignment operator.
     152             : /// It effectively "clones" the communicator, providing a new one acting on the same group
     153             :   Communicator& operator=(const Communicator&);
     154             : /// Destructor
     155             :   virtual ~Communicator();
     156             : /// Obtain the rank of the present process
     157             :   int Get_rank()const;
     158             : /// Obtain the number of processes
     159             :   int Get_size()const;
     160             : /// Set from a real MPI communicator.
     161             : /// \param comm MPI communicator
     162             :   void Set_comm(MPI_Comm comm);
     163             : /// Reference to MPI communicator
     164             :   MPI_Comm & Get_comm();
     165             : /// Set from a pointer to a real MPI communicator (C).
     166             : /// \param comm Pointer to a C MPI communicator
     167             :   void Set_comm(const TypesafePtr & comm);
     168             : /// Set from a pointer to a real MPI communicator (FORTRAN).
     169             : /// \param comm Pointer to a FORTRAN MPI communicator (INTEGER)
     170             :   void Set_fcomm(const TypesafePtr & comm);
     171             : /// Wrapper to MPI_Abort.
     172             : /// \param code Error code
     173             :   void Abort(int code);
     174             : /// Wrapper to MPI_Barrier
     175             :   void Barrier()const;
     176             : /// Tests if MPI library is initialized
     177             :   static bool initialized();
     178             : /// Wrapper for MPI_Allreduce with MPI_SUM (data struct)
     179             :   void Sum(Data);
     180             : /// Wrapper for MPI_Allreduce with MPI_SUM (pointer)
     181      108444 :   template <class T> void Sum(T*buf,int count) {Sum(Data(buf,count));}
     182             : /// Wrapper for MPI_Allreduce with MPI_SUM (reference)
     183     4422565 :   template <class T> void Sum(T&buf) {Sum(Data(buf));}
     184             : /// Wrapper for MPI_Allreduce with MPI_PROD (data struct)
     185             :   void Prod(Data);
     186             : /// Wrapper for MPI_Allreduce with MPI_PROD (pointer)
     187             :   template <class T> void Prod(T*buf,int count) {Prod(Data(buf,count));}
     188             : /// Wrapper for MPI_Allreduce with MPI_PROD (reference)
     189             :   template <class T> void Prod(T&buf) {Prod(Data(buf));}
     190             : /// Wrapper for MPI_Allreduce with MPI_MAX (data struct)
     191             :   void Max(Data);
     192             : /// Wrapper for MPI_Allreduce with MPI_MAX (pointer)
     193             :   template <class T> void Max(T*buf,int count) {Max(Data(buf,count));}
     194             : /// Wrapper for MPI_Allreduce with MPI_MAX (reference)
     195         152 :   template <class T> void Max(T&buf) {Max(Data(buf));}
     196             : /// Wrapper for MPI_Allreduce with MPI_MIN (data struct)
     197             :   void Min(Data);
     198             : /// Wrapper for MPI_Allreduce with MPI_MIN (pointer)
     199             :   template <class T> void Min(T*buf,int count) {Min(Data(buf,count));}
     200             : /// Wrapper for MPI_Allreduce with MPI_MIN (reference)
     201           0 :   template <class T> void Min(T&buf) {Min(Data(buf));}
     202             : 
     203             : /// Wrapper for MPI_Bcast (data struct)
     204             :   void Bcast(Data,int);
     205             : /// Wrapper for MPI_Bcast (pointer)
     206             :   template <class T> void Bcast(T*buf,int count,int root) {Bcast(Data(buf,count),root);}
     207             : /// Wrapper for MPI_Bcast (reference)
     208     5536690 :   template <class T> void Bcast(T&buf,int root) {Bcast(Data(buf),root);}
     209             : 
     210             : /// Wrapper for MPI_Isend (data struct)
     211             :   Request Isend(ConstData,int,int);
     212             : /// Wrapper for MPI_Isend (pointer)
     213       15268 :   template <class T> Request Isend(const T*buf,int count,int source,int tag) {return Isend(ConstData(buf,count),source,tag);}
     214             : /// Wrapper for MPI_Isend (reference)
     215         114 :   template <class T> Request Isend(const T&buf,int source,int tag) {return Isend(ConstData(buf),source,tag);}
     216             : 
     217             : /// Wrapper for MPI_Allgatherv (data struct)
     218             :   void Allgatherv(ConstData in,Data out,const int*,const int*);
     219             : /// Wrapper for MPI_Allgatherv (pointer)
     220       18907 :   template <class T,class S> void Allgatherv(const T*sendbuf,int sendcount,S*recvbuf,const int*recvcounts,const int*displs) {
     221       18907 :     Allgatherv(ConstData(sendbuf,sendcount),Data(recvbuf,0),recvcounts,displs);
     222       18907 :   }
     223             : /// Wrapper for MPI_Allgatherv (reference)
     224         152 :   template <class T,class S> void Allgatherv(const T&sendbuf,S&recvbuf,const int*recvcounts,const int*displs) {
     225         152 :     Allgatherv(ConstData(sendbuf),Data(recvbuf),recvcounts,displs);
     226         152 :   }
     227             : 
     228             : /// Wrapper for MPI_Allgather (data struct)
     229             :   void Allgather(ConstData in,Data out);
     230             : /// Wrapper for MPI_Allgatherv (pointer)
     231         204 :   template <class T,class S> void Allgather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount) {
     232         408 :     Allgather(ConstData(sendbuf,sendcount),Data(recvbuf,recvcount*Get_size()));
     233         204 :   }
     234             : /// Wrapper for MPI_Allgatherv (reference)
     235        5642 :   template <class T,class S> void Allgather(const T&sendbuf,S&recvbuf) {
     236        6480 :     Allgather(ConstData(sendbuf),Data(recvbuf));
     237        5642 :   }
     238             : 
     239             : /// Wrapper for MPI_Recv (data struct)
     240             :   void Recv(Data,int,int,Status&s=StatusIgnore);
     241             : /// Wrapper for MPI_Recv (pointer)
     242       15268 :   template <class T> void Recv(T*buf,int count,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf,count),source,tag,s);}
     243             : /// Wrapper for MPI_Recv (reference)
     244         114 :   template <class T> void Recv(T&buf,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf),source,tag,s);}
     245             : 
     246             : /// Wrapper to MPI_Comm_split
     247             :   void Split(int,int,Communicator&)const;
     248             : };
     249             : 
     250             : }
     251             : 
     252             : #endif

Generated by: LCOV version 1.16