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 2615460 : template <typename T> Data(T*p,int s): pointer(p), size(s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
73 : /// Init from reference
74 13135340 : 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 83422 : 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 2389647 : template <typename T> explicit Data(std::vector<T>&v) {
85 2389818 : Data d(v.data(),v.size()); pointer=d.pointer; size=d.size; type=d.type;
86 2389647 : }
87 : /// Init from reference to PLMD::Matrix
88 17 : template <typename T> explicit Data(Matrix<T>&m ) {
89 17 : 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 0 : else { pointer=NULL; size=0; }
91 17 : }
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 19900 : template <typename T> explicit ConstData(const T*p,int s): pointer(p), size(s), nbytes(sizeof(T)), type(getMPIType<T>()) {}
106 5164 : 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 732 : template <typename T> explicit ConstData(const std::vector<T>&v) {
112 732 : ConstData d(v.data(),v.size()); pointer=d.pointer; size=d.size; type=d.type;
113 732 : }
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 : /// Wrapper class for MPI_Status
125 : class Status {
126 : int Get_count(MPI_Datatype)const;
127 : public:
128 : MPI_Status s;
129 : template <class T>
130 7588 : int Get_count()const {return Get_count(getMPIType<T>());}
131 : };
132 : /// Special status used when status should be ignored.
133 : /// E.g. `Recv(a,0,1,Communicator::StatusIgnore);`
134 : /// Notice that this is the default for Recv, so this is equivalent to
135 : /// `Recv(a,0,1);`
136 : static Status StatusIgnore;
137 : /// Wrapper class for MPI_Request
138 : class Request {
139 : public:
140 : MPI_Request r;
141 : void wait(Status&s=StatusIgnore);
142 : };
143 : /// Default constructor
144 : Communicator();
145 : /// Copy constructor.
146 : /// It effectively "clones" the communicator, providing a new one acting on the same group
147 : Communicator(const Communicator&);
148 : /// Assignment operator.
149 : /// It effectively "clones" the communicator, providing a new one acting on the same group
150 : Communicator& operator=(const Communicator&);
151 : /// Destructor
152 : virtual ~Communicator();
153 : /// Obtain the rank of the present process
154 : int Get_rank()const;
155 : /// Obtain the number of processes
156 : int Get_size()const;
157 : /// Set from a real MPI communicator.
158 : /// \param comm MPI communicator
159 : void Set_comm(MPI_Comm comm);
160 : /// Reference to MPI communicator
161 : MPI_Comm & Get_comm();
162 : /// Set from a pointer to a real MPI communicator (C).
163 : /// \param comm Pointer to a C MPI communicator
164 : void Set_comm(const TypesafePtr & comm);
165 : /// Set from a pointer to a real MPI communicator (FORTRAN).
166 : /// \param comm Pointer to a FORTRAN MPI communicator (INTEGER)
167 : void Set_fcomm(const TypesafePtr & comm);
168 : /// Wrapper to MPI_Abort.
169 : /// \param code Error code
170 : void Abort(int code);
171 : /// Wrapper to MPI_Barrier
172 : void Barrier()const;
173 : /// Tests if MPI library is initialized
174 : static bool initialized();
175 : /// Wrapper for MPI_Allreduce with MPI_SUM (data struct)
176 : void Sum(Data);
177 : /// Wrapper for MPI_Allreduce with MPI_SUM (pointer)
178 88206 : template <class T> void Sum(T*buf,int count) {Sum(Data(buf,count));}
179 : /// Wrapper for MPI_Allreduce with MPI_SUM (reference)
180 4195556 : template <class T> void Sum(T&buf) {Sum(Data(buf));}
181 : /// Wrapper for MPI_Allreduce with MPI_PROD (data struct)
182 : void Prod(Data);
183 : /// Wrapper for MPI_Allreduce with MPI_PROD (pointer)
184 : template <class T> void Prod(T*buf,int count) {Prod(Data(buf,count));}
185 : /// Wrapper for MPI_Allreduce with MPI_PROD (reference)
186 : template <class T> void Prod(T&buf) {Prod(Data(buf));}
187 : /// Wrapper for MPI_Allreduce with MPI_MAX (data struct)
188 : void Max(Data);
189 : /// Wrapper for MPI_Allreduce with MPI_MAX (pointer)
190 : template <class T> void Max(T*buf,int count) {Max(Data(buf,count));}
191 : /// Wrapper for MPI_Allreduce with MPI_MAX (reference)
192 152 : template <class T> void Max(T&buf) {Max(Data(buf));}
193 : /// Wrapper for MPI_Allreduce with MPI_MIN (data struct)
194 : void Min(Data);
195 : /// Wrapper for MPI_Allreduce with MPI_MIN (pointer)
196 : template <class T> void Min(T*buf,int count) {Min(Data(buf,count));}
197 : /// Wrapper for MPI_Allreduce with MPI_MIN (reference)
198 0 : template <class T> void Min(T&buf) {Min(Data(buf));}
199 :
200 : /// Wrapper for MPI_Bcast (data struct)
201 : void Bcast(Data,int);
202 : /// Wrapper for MPI_Bcast (pointer)
203 : template <class T> void Bcast(T*buf,int count,int root) {Bcast(Data(buf,count),root);}
204 : /// Wrapper for MPI_Bcast (reference)
205 4797673 : template <class T> void Bcast(T&buf,int root) {Bcast(Data(buf),root);}
206 :
207 : /// Wrapper for MPI_Isend (data struct)
208 : Request Isend(ConstData,int,int);
209 : /// Wrapper for MPI_Isend (pointer)
210 15176 : template <class T> Request Isend(const T*buf,int count,int source,int tag) {return Isend(ConstData(buf,count),source,tag);}
211 : /// Wrapper for MPI_Isend (reference)
212 114 : template <class T> Request Isend(const T&buf,int source,int tag) {return Isend(ConstData(buf),source,tag);}
213 :
214 : /// Wrapper for MPI_Allgatherv (data struct)
215 : void Allgatherv(ConstData in,Data out,const int*,const int*);
216 : /// Wrapper for MPI_Allgatherv (pointer)
217 18907 : template <class T,class S> void Allgatherv(const T*sendbuf,int sendcount,S*recvbuf,const int*recvcounts,const int*displs) {
218 18907 : Allgatherv(ConstData(sendbuf,sendcount),Data(recvbuf,0),recvcounts,displs);
219 18907 : }
220 : /// Wrapper for MPI_Allgatherv (reference)
221 152 : template <class T,class S> void Allgatherv(const T&sendbuf,S&recvbuf,const int*recvcounts,const int*displs) {
222 152 : Allgatherv(ConstData(sendbuf),Data(recvbuf),recvcounts,displs);
223 152 : }
224 :
225 : /// Wrapper for MPI_Allgather (data struct)
226 : void Allgather(ConstData in,Data out);
227 : /// Wrapper for MPI_Allgatherv (pointer)
228 204 : template <class T,class S> void Allgather(const T*sendbuf,int sendcount,S*recvbuf,int recvcount) {
229 408 : Allgather(ConstData(sendbuf,sendcount),Data(recvbuf,recvcount*Get_size()));
230 204 : }
231 : /// Wrapper for MPI_Allgatherv (reference)
232 5630 : template <class T,class S> void Allgather(const T&sendbuf,S&recvbuf) {
233 10680 : Allgather(ConstData(sendbuf),Data(recvbuf));
234 5630 : }
235 :
236 : /// Wrapper for MPI_Recv (data struct)
237 : void Recv(Data,int,int,Status&s=StatusIgnore);
238 : /// Wrapper for MPI_Recv (pointer)
239 15176 : template <class T> void Recv(T*buf,int count,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf,count),source,tag,s);}
240 : /// Wrapper for MPI_Recv (reference)
241 114 : template <class T> void Recv(T&buf,int source,int tag,Status&s=StatusIgnore) {Recv(Data(buf),source,tag,s);}
242 :
243 : /// Wrapper to MPI_Comm_split
244 : void Split(int,int,Communicator&)const;
245 : };
246 :
247 : }
248 :
249 : #endif
|