Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2020 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 : #include "Communicator.h"
23 : #include "Exception.h"
24 : #include <cstdlib>
25 :
26 : using namespace std;
27 :
28 : namespace PLMD {
29 :
30 11212 : Communicator::Communicator()
31 : #ifdef __PLUMED_HAS_MPI
32 11212 : : communicator(MPI_COMM_SELF)
33 : #endif
34 : {
35 11212 : }
36 :
37 0 : Communicator::Communicator(const Communicator&pc) {
38 0 : Set_comm(pc.communicator);
39 0 : }
40 :
41 : Communicator::Status Communicator::StatusIgnore;
42 :
43 0 : Communicator& Communicator::operator=(const Communicator&pc) {
44 0 : if (this != &pc) {
45 0 : Set_comm(pc.communicator);
46 : }
47 0 : return *this;
48 : }
49 :
50 6055384 : int Communicator::Get_rank()const {
51 6055384 : int r=0;
52 : #ifdef __PLUMED_HAS_MPI
53 6055384 : if(initialized()) MPI_Comm_rank(communicator,&r);
54 : #endif
55 6055384 : return r;
56 : }
57 :
58 2228748 : int Communicator::Get_size()const {
59 2228748 : int s=1;
60 : #ifdef __PLUMED_HAS_MPI
61 2228748 : if(initialized()) MPI_Comm_size(communicator,&s);
62 : #endif
63 2228748 : return s;
64 : }
65 :
66 1850 : void Communicator::Set_comm(MPI_Comm c) {
67 : #ifdef __PLUMED_HAS_MPI
68 1850 : if(initialized()) {
69 1517 : if(communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator);
70 1517 : if(c!=MPI_COMM_SELF) MPI_Comm_dup(c,&communicator);
71 : }
72 : #else
73 : (void) c;
74 : #endif
75 1850 : }
76 :
77 29762 : Communicator::~Communicator() {
78 : #ifdef __PLUMED_HAS_MPI
79 11212 : if(initialized() && communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator);
80 : #endif
81 18550 : }
82 :
83 1142 : void Communicator::Set_comm(void*val) {
84 : #ifdef __PLUMED_HAS_MPI
85 1142 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
86 1142 : if(val) Set_comm(*(MPI_Comm*)val);
87 : #else
88 : (void) val;
89 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
90 : #endif
91 1142 : }
92 :
93 0 : void Communicator::Set_fcomm(void*val) {
94 : #ifdef __PLUMED_HAS_MPI
95 0 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
96 0 : if(val) {
97 0 : MPI_Comm comm=MPI_Comm_f2c(*(MPI_Fint*)val);
98 0 : Set_comm(comm);
99 : }
100 : #else
101 : (void) val;
102 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
103 : #endif
104 0 : }
105 :
106 0 : void Communicator::Abort(int errorcode) {
107 : #ifdef __PLUMED_HAS_MPI
108 0 : if(initialized()) {
109 0 : MPI_Abort(communicator,errorcode);
110 : }
111 0 : std::exit(errorcode);
112 : #else
113 : std::exit(errorcode);
114 : #endif
115 : }
116 :
117 4103755 : void Communicator::Bcast(Data data,int root) {
118 : #if defined(__PLUMED_HAS_MPI)
119 4103755 : if(initialized()) MPI_Bcast(data.pointer,data.size,data.type,root,communicator);
120 : #else
121 : (void) data;
122 : (void) root;
123 : #endif
124 4103755 : }
125 :
126 3928007 : void Communicator::Sum(Data data) {
127 : #if defined(__PLUMED_HAS_MPI)
128 3928007 : if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_SUM,communicator);
129 : #else
130 : (void) data;
131 : #endif
132 3928007 : }
133 :
134 3 : void Communicator::Prod(Data data) {
135 : #if defined(__PLUMED_HAS_MPI)
136 3 : if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_PROD,communicator);
137 : #else
138 : (void) data;
139 : #endif
140 3 : }
141 :
142 3 : void Communicator::Max(Data data) {
143 : #if defined(__PLUMED_HAS_MPI)
144 3 : if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_MAX,communicator);
145 : #else
146 : (void) data;
147 : #endif
148 3 : }
149 :
150 3 : void Communicator::Min(Data data) {
151 : #if defined(__PLUMED_HAS_MPI)
152 3 : if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_MIN,communicator);
153 : #else
154 : (void) data;
155 : #endif
156 3 : }
157 :
158 15206 : Communicator::Request Communicator::Isend(ConstData data,int source,int tag) {
159 : Request req;
160 : #ifdef __PLUMED_HAS_MPI
161 15206 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
162 15206 : void*s=const_cast<void*>((const void*)data.pointer);
163 15206 : MPI_Isend(s,data.size,data.type,source,tag,communicator,&req.r);
164 : #else
165 : (void) data;
166 : (void) source;
167 : (void) tag;
168 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
169 : #endif
170 15206 : return req;
171 : }
172 :
173 2270 : void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const int*displs) {
174 : #if defined(__PLUMED_HAS_MPI)
175 2270 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
176 2270 : void*s=const_cast<void*>((const void*)in.pointer);
177 2270 : void*r=const_cast<void*>((const void*)out.pointer);
178 : int*rc=const_cast<int*>(recvcounts);
179 : int*di=const_cast<int*>(displs);
180 2270 : if(s==NULL)s=MPI_IN_PLACE;
181 2270 : MPI_Allgatherv(s,in.size,in.type,r,rc,di,out.type,communicator);
182 : #else
183 : (void) in;
184 : (void) out;
185 : (void) recvcounts;
186 : (void) displs;
187 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
188 : #endif
189 2270 : }
190 :
191 4835 : void Communicator::Allgather(ConstData in,Data out) {
192 : #if defined(__PLUMED_HAS_MPI)
193 4835 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
194 4835 : void*s=const_cast<void*>((const void*)in.pointer);
195 4835 : void*r=const_cast<void*>((const void*)out.pointer);
196 4835 : if(s==NULL)s=MPI_IN_PLACE;
197 4835 : MPI_Allgather(s,in.size,in.type,r,out.size/Get_size(),out.type,communicator);
198 : #else
199 : (void) in;
200 : (void) out;
201 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
202 : #endif
203 4835 : }
204 :
205 15206 : void Communicator::Recv(Data data,int source,int tag,Status&status) {
206 : #ifdef __PLUMED_HAS_MPI
207 15206 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
208 15206 : if(&status==&StatusIgnore) MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,MPI_STATUS_IGNORE);
209 7541 : else MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,&status.s);
210 : #else
211 : (void) data;
212 : (void) source;
213 : (void) tag;
214 : (void) status;
215 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
216 : #endif
217 15206 : }
218 :
219 :
220 :
221 :
222 :
223 4042645 : void Communicator::Barrier()const {
224 : #ifdef __PLUMED_HAS_MPI
225 4042645 : if(initialized()) MPI_Barrier(communicator);
226 : #endif
227 4042645 : }
228 :
229 1310 : MPI_Comm & Communicator::Get_comm() {
230 1310 : return communicator;
231 : }
232 :
233 20434059 : bool Communicator::initialized() {
234 : #if defined(__PLUMED_HAS_MPI)
235 20434059 : int flag=0;
236 20434059 : MPI_Initialized(&flag);
237 20434059 : if(flag) return true;
238 11787415 : else return false;
239 : #endif
240 : return false;
241 : }
242 :
243 14814 : void Communicator::Request::wait(Status&s) {
244 : #ifdef __PLUMED_HAS_MPI
245 14814 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
246 14814 : if(&s==&StatusIgnore) MPI_Wait(&r,MPI_STATUS_IGNORE);
247 1 : else MPI_Wait(&r,&s.s);
248 : #else
249 : (void) s;
250 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
251 : #endif
252 14814 : }
253 :
254 : #ifdef __PLUMED_HAS_MPI
255 0 : template<> MPI_Datatype Communicator::getMPIType<float>() { return MPI_FLOAT;}
256 4002900 : template<> MPI_Datatype Communicator::getMPIType<double>() { return MPI_DOUBLE;}
257 33177 : template<> MPI_Datatype Communicator::getMPIType<int>() { return MPI_INT;}
258 234 : template<> MPI_Datatype Communicator::getMPIType<char>() { return MPI_CHAR;}
259 9346 : template<> MPI_Datatype Communicator::getMPIType<unsigned>() { return MPI_UNSIGNED;}
260 4038277 : template<> MPI_Datatype Communicator::getMPIType<long unsigned>() { return MPI_UNSIGNED_LONG;}
261 : #else
262 : template<> MPI_Datatype Communicator::getMPIType<float>() { return MPI_Datatype();}
263 : template<> MPI_Datatype Communicator::getMPIType<double>() { return MPI_Datatype();}
264 : template<> MPI_Datatype Communicator::getMPIType<int>() { return MPI_Datatype();}
265 : template<> MPI_Datatype Communicator::getMPIType<char>() { return MPI_Datatype();}
266 : template<> MPI_Datatype Communicator::getMPIType<unsigned>() { return MPI_Datatype();}
267 : template<> MPI_Datatype Communicator::getMPIType<long unsigned>() { return MPI_Datatype();}
268 : #endif
269 :
270 :
271 366 : void Communicator::Split(int color,int key,Communicator&pc)const {
272 : #ifdef __PLUMED_HAS_MPI
273 366 : MPI_Comm_split(communicator,color,key,&pc.communicator);
274 : #else
275 : (void) color;
276 : (void) key;
277 : (void) pc;
278 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
279 : #endif
280 366 : }
281 :
282 7541 : int Communicator::Status::Get_count(MPI_Datatype type)const {
283 : int i;
284 : #ifdef __PLUMED_HAS_MPI
285 7541 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
286 7541 : MPI_Get_count(const_cast<MPI_Status*>(&s),type,&i);
287 : #else
288 : i=0;
289 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
290 : #endif
291 7541 : return i;
292 : }
293 :
294 5517 : }
295 :
|