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