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