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 <cstdlib>
25 :
26 : using namespace std;
27 :
28 : namespace PLMD {
29 :
30 9742 : Communicator::Communicator()
31 : #ifdef __PLUMED_HAS_MPI
32 9742 : : communicator(MPI_COMM_SELF)
33 : #endif
34 : {
35 9742 : }
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 5904626 : int Communicator::Get_rank()const {
51 5904626 : int r=0;
52 : #ifdef __PLUMED_HAS_MPI
53 5904626 : if(initialized()) MPI_Comm_rank(communicator,&r);
54 : #endif
55 5904626 : return r;
56 : }
57 :
58 0 : Communicator& Communicator::Get_world() {
59 0 : static Communicator c;
60 : #ifdef __PLUMED_HAS_MPI
61 0 : if(initialized()) c.communicator=MPI_COMM_WORLD;
62 : #endif
63 0 : return c;
64 : }
65 :
66 :
67 2161827 : int Communicator::Get_size()const {
68 2161827 : int s=1;
69 : #ifdef __PLUMED_HAS_MPI
70 2161827 : if(initialized()) MPI_Comm_size(communicator,&s);
71 : #endif
72 2161827 : return s;
73 : }
74 :
75 1617 : void Communicator::Set_comm(MPI_Comm c) {
76 : #ifdef __PLUMED_HAS_MPI
77 1617 : if(initialized()) {
78 1317 : if(communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator);
79 1317 : if(c!=MPI_COMM_SELF) MPI_Comm_dup(c,&communicator);
80 : }
81 : #else
82 : (void) c;
83 : #endif
84 1617 : }
85 :
86 25853 : Communicator::~Communicator() {
87 : #ifdef __PLUMED_HAS_MPI
88 9742 : if(initialized() && communicator!=MPI_COMM_SELF && communicator!=MPI_COMM_WORLD) MPI_Comm_free(&communicator);
89 : #endif
90 16111 : }
91 :
92 982 : void Communicator::Set_comm(void*val) {
93 : #ifdef __PLUMED_HAS_MPI
94 982 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
95 982 : if(val) Set_comm(*(MPI_Comm*)val);
96 : #else
97 : (void) val;
98 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
99 : #endif
100 982 : }
101 :
102 0 : void Communicator::Set_fcomm(void*val) {
103 : #ifdef __PLUMED_HAS_MPI
104 0 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
105 0 : if(val) {
106 0 : MPI_Comm comm=MPI_Comm_f2c(*(MPI_Fint*)val);
107 0 : Set_comm(comm);
108 : }
109 : #else
110 : (void) val;
111 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
112 : #endif
113 0 : }
114 :
115 0 : void Communicator::Abort(int errorcode) {
116 : #ifdef __PLUMED_HAS_MPI
117 0 : if(initialized()) {
118 0 : MPI_Abort(communicator,errorcode);
119 : }
120 0 : std::exit(errorcode);
121 : #else
122 : std::exit(errorcode);
123 : #endif
124 : }
125 :
126 3952467 : void Communicator::Bcast(Data data,int root) {
127 : #if defined(__PLUMED_HAS_MPI)
128 3952467 : if(initialized()) MPI_Bcast(data.pointer,data.size,data.type,root,communicator);
129 : #else
130 : (void) data;
131 : (void) root;
132 : #endif
133 3952467 : }
134 :
135 3911050 : void Communicator::Sum(Data data) {
136 : #if defined(__PLUMED_HAS_MPI)
137 3911050 : if(initialized()) MPI_Allreduce(MPI_IN_PLACE,data.pointer,data.size,data.type,MPI_SUM,communicator);
138 : #else
139 : (void) data;
140 : #endif
141 3911050 : }
142 :
143 14656 : Communicator::Request Communicator::Isend(ConstData data,int source,int tag) {
144 : Request req;
145 : #ifdef __PLUMED_HAS_MPI
146 14656 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
147 14656 : void*s=const_cast<void*>((const void*)data.pointer);
148 14656 : MPI_Isend(s,data.size,data.type,source,tag,communicator,&req.r);
149 : #else
150 : (void) data;
151 : (void) source;
152 : (void) tag;
153 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
154 : #endif
155 14656 : return req;
156 : }
157 :
158 2270 : void Communicator::Allgatherv(ConstData in,Data out,const int*recvcounts,const int*displs) {
159 : #if defined(__PLUMED_HAS_MPI)
160 2270 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
161 2270 : void*s=const_cast<void*>((const void*)in.pointer);
162 2270 : void*r=const_cast<void*>((const void*)out.pointer);
163 : int*rc=const_cast<int*>(recvcounts);
164 : int*di=const_cast<int*>(displs);
165 2270 : if(s==NULL)s=MPI_IN_PLACE;
166 2270 : MPI_Allgatherv(s,in.size,in.type,r,rc,di,out.type,communicator);
167 : #else
168 : (void) in;
169 : (void) out;
170 : (void) recvcounts;
171 : (void) displs;
172 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
173 : #endif
174 2270 : }
175 :
176 515 : void Communicator::Allgather(ConstData in,Data out) {
177 : #if defined(__PLUMED_HAS_MPI)
178 515 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
179 515 : void*s=const_cast<void*>((const void*)in.pointer);
180 515 : void*r=const_cast<void*>((const void*)out.pointer);
181 515 : if(s==NULL)s=MPI_IN_PLACE;
182 515 : MPI_Allgather(s,in.size,in.type,r,out.size/Get_size(),out.type,communicator);
183 : #else
184 : (void) in;
185 : (void) out;
186 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
187 : #endif
188 515 : }
189 :
190 14656 : void Communicator::Recv(Data data,int source,int tag,Status&status) {
191 : #ifdef __PLUMED_HAS_MPI
192 14656 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
193 14656 : if(&status==&StatusIgnore) MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,MPI_STATUS_IGNORE);
194 7281 : else MPI_Recv(data.pointer,data.size,data.type,source,tag,communicator,&status.s);
195 : #else
196 : (void) data;
197 : (void) source;
198 : (void) tag;
199 : (void) status;
200 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
201 : #endif
202 14656 : }
203 :
204 :
205 :
206 :
207 :
208 3908218 : void Communicator::Barrier()const {
209 : #ifdef __PLUMED_HAS_MPI
210 3908218 : if(initialized()) MPI_Barrier(communicator);
211 : #endif
212 3908218 : }
213 :
214 1146 : MPI_Comm & Communicator::Get_comm() {
215 1146 : return communicator;
216 : }
217 :
218 19905217 : bool Communicator::initialized() {
219 19905217 : int flag=false;
220 : #if defined(__PLUMED_HAS_MPI)
221 19905217 : MPI_Initialized(&flag);
222 : #endif
223 19905217 : if(flag) return true;
224 11518055 : else return false;
225 : }
226 :
227 14320 : void Communicator::Request::wait(Status&s) {
228 : #ifdef __PLUMED_HAS_MPI
229 14320 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
230 14320 : if(&s==&StatusIgnore) MPI_Wait(&r,MPI_STATUS_IGNORE);
231 1 : else MPI_Wait(&r,&s.s);
232 : #else
233 : (void) s;
234 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
235 : #endif
236 14320 : }
237 :
238 : #ifdef __PLUMED_HAS_MPI
239 0 : template<> MPI_Datatype Communicator::getMPIType<float>() { return MPI_FLOAT;}
240 3959999 : template<> MPI_Datatype Communicator::getMPIType<double>() { return MPI_DOUBLE;}
241 30980 : template<> MPI_Datatype Communicator::getMPIType<int>() { return MPI_INT;}
242 174 : template<> MPI_Datatype Communicator::getMPIType<char>() { return MPI_CHAR;}
243 10237 : template<> MPI_Datatype Communicator::getMPIType<unsigned>() { return MPI_UNSIGNED;}
244 3904290 : template<> MPI_Datatype Communicator::getMPIType<long unsigned>() { return MPI_UNSIGNED_LONG;}
245 : #else
246 : template<> MPI_Datatype Communicator::getMPIType<float>() { return MPI_Datatype();}
247 : template<> MPI_Datatype Communicator::getMPIType<double>() { return MPI_Datatype();}
248 : template<> MPI_Datatype Communicator::getMPIType<int>() { return MPI_Datatype();}
249 : template<> MPI_Datatype Communicator::getMPIType<char>() { return MPI_Datatype();}
250 : template<> MPI_Datatype Communicator::getMPIType<unsigned>() { return MPI_Datatype();}
251 : template<> MPI_Datatype Communicator::getMPIType<long unsigned>() { return MPI_Datatype();}
252 : #endif
253 :
254 :
255 310 : void Communicator::Split(int color,int key,Communicator&pc)const {
256 : #ifdef __PLUMED_HAS_MPI
257 310 : MPI_Comm_split(communicator,color,key,&pc.communicator);
258 : #else
259 : (void) color;
260 : (void) key;
261 : (void) pc;
262 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
263 : #endif
264 310 : }
265 :
266 7281 : int Communicator::Status::Get_count(MPI_Datatype type)const {
267 : int i;
268 : #ifdef __PLUMED_HAS_MPI
269 7281 : plumed_massert(initialized(),"you are trying to use an MPI function, but MPI is not initialized");
270 7281 : MPI_Get_count(const_cast<MPI_Status*>(&s),type,&i);
271 : #else
272 : i=0;
273 : plumed_merror("you are trying to use an MPI function, but PLUMED has been compiled without MPI support");
274 : #endif
275 7281 : return i;
276 : }
277 :
278 4839 : }
279 :
|