allReduceTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2012-2015 OpenFOAM Foundation
9  Copyright (C) 2019-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "allReduce.H"
30 #include "profilingPstream.H"
31 
32 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
33 
34 template<class Type, class BinaryOp>
35 void Foam::allReduce
36 (
37  Type& Value,
38  int MPICount,
39  MPI_Datatype MPIType,
40  MPI_Op MPIOp,
41  const BinaryOp& bop,
42  const int tag,
43  const label communicator
44 )
45 {
46  if (!UPstream::parRun())
47  {
48  return;
49  }
50 
51  profilingPstream::beginTiming();
52 
53  if (UPstream::nProcs(communicator) <= UPstream::nProcsSimpleSum)
54  {
55  if (UPstream::master(communicator))
56  {
57  for
58  (
59  int slave=UPstream::firstSlave();
60  slave<=UPstream::lastSlave(communicator);
61  slave++
62  )
63  {
64  Type value;
65 
66  if
67  (
68  MPI_Recv
69  (
70  &value,
71  MPICount,
72  MPIType,
73  slave, //UPstream::procID(slave),
74  tag,
76  MPI_STATUS_IGNORE
77  )
78  )
79  {
81  << "MPI_Recv failed"
83  }
84 
85  Value = bop(Value, value);
86  }
87  }
88  else
89  {
90  if
91  (
92  MPI_Send
93  (
94  &Value,
95  MPICount,
96  MPIType,
97  UPstream::masterNo(),//UPstream::procID(masterNo()),
98  tag,
100  )
101  )
102  {
104  << "MPI_Send failed"
106  }
107  }
108 
109 
110  if (UPstream::master(communicator))
111  {
112  for
113  (
114  int slave=UPstream::firstSlave();
115  slave<=UPstream::lastSlave(communicator);
116  slave++
117  )
118  {
119  if
120  (
121  MPI_Send
122  (
123  &Value,
124  MPICount,
125  MPIType,
126  slave, //UPstream::procID(slave),
127  tag,
129  )
130  )
131  {
133  << "MPI_Send failed"
135  }
136  }
137  }
138  else
139  {
140  if
141  (
142  MPI_Recv
143  (
144  &Value,
145  MPICount,
146  MPIType,
147  UPstream::masterNo(),//UPstream::procID(masterNo()),
148  tag,
149  PstreamGlobals::MPICommunicators_[communicator],
150  MPI_STATUS_IGNORE
151  )
152  )
153  {
155  << "MPI_Recv failed"
157  }
158  }
159  }
160  else
161  {
162  Type sum;
163  MPI_Allreduce
164  (
165  &Value,
166  &sum,
167  MPICount,
168  MPIType,
169  MPIOp,
171  );
172  Value = sum;
173  }
174 
175  profilingPstream::addReduceTime();
176 }
177 
178 
179 template<class Type>
180 void Foam::iallReduce
181 (
182  void* recvBuf,
183  int MPICount,
184  MPI_Datatype MPIType,
185  MPI_Op MPIOp,
186  const label communicator,
187  label& requestID
188 )
189 {
190  if (!UPstream::parRun())
191  {
192  return;
193  }
194 
195  if (UPstream::warnComm != -1 && communicator != UPstream::warnComm)
196  {
197  Pout<< "** non-blocking reducing:"
198  << UList<Type>(static_cast<Type*>(recvBuf), MPICount)
199  << " with comm:" << communicator
200  << " warnComm:" << UPstream::warnComm << endl;
201  error::printStack(Pout);
202  }
203 
204  profilingPstream::beginTiming();
205 
206 #if defined(MPI_VERSION) && (MPI_VERSION >= 3)
207  MPI_Request request;
208  if
209  (
210  MPI_Iallreduce
211  (
212  MPI_IN_PLACE,
213  recvBuf,
214  MPICount,
215  MPIType,
216  MPIOp,
217  PstreamGlobals::MPICommunicators_[communicator],
218  &request
219  )
220  )
221  {
223  << "MPI_Iallreduce failed for "
224  << UList<Type>(static_cast<Type*>(recvBuf), MPICount)
226  }
227 
229  {
231  PstreamGlobals::outstandingRequests_[requestID] = request;
232  }
233  else
234  {
235  requestID = PstreamGlobals::outstandingRequests_.size();
236  PstreamGlobals::outstandingRequests_.append(request);
237  }
238 
239  if (UPstream::debug)
240  {
241  Pout<< "UPstream::allocateRequest for non-blocking reduce"
242  << " : request:" << requestID << endl;
243  }
244 #else
245  // Non-blocking not yet implemented in mpi
246  if
247  (
248  MPI_Allreduce
249  (
250  MPI_IN_PLACE,
251  recvBuf,
252  MPICount,
253  MPIType,
254  MPIOp,
256  )
257  )
258  {
260  << "MPI_Allreduce failed for "
261  << UList<Type>(static_cast<Type*>(recvBuf), MPICount)
263  }
264  requestID = -1;
265 #endif
266 
267  profilingPstream::addReduceTime();
268 }
269 
270 
271 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::PstreamGlobals::freedRequests_
DynamicList< label > freedRequests_
Definition: PstreamGlobals.C:33
Foam::PstreamGlobals::outstandingRequests_
DynamicList< MPI_Request > outstandingRequests_
Outstanding non-blocking operations.
Definition: PstreamGlobals.C:32
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::iallReduce
void iallReduce(void *Value, int count, MPI_Datatype MPIType, MPI_Op op, const label communicator, label &requestID)
Definition: allReduceTemplates.C:181
Foam::Pout
prefixOSstream Pout
An Ostream wrapper for parallel output to std::cout.
Foam::PstreamGlobals::MPICommunicators_
DynamicList< MPI_Comm > MPICommunicators_
Definition: PstreamGlobals.C:39
Foam::allReduce
void allReduce(Type &Value, int count, MPI_Datatype MPIType, MPI_Op op, const BinaryOp &bop, const int tag, const label communicator)
Definition: allReduceTemplates.C:36
Foam::FatalError
error FatalError
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
allReduce.H
Various functions to wrap MPI_Allreduce.
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::UList< Type >
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::DynamicList::remove
T remove()
Remove and return the last element. Fatal on an empty list.
Definition: DynamicListI.H:651
profilingPstream.H