Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
MpiParallelDispatch.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* MpiParallelDispatch.cc (C) 2000-2025 */
9/* */
10/* Parallelism manager using MPI. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/Array.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/String.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/Real2.h"
21#include "arcane/utils/Real3.h"
22#include "arcane/utils/Real2x2.h"
23#include "arcane/utils/Real3x3.h"
24#include "arcane/utils/HPReal.h"
25#include "arcane/utils/APReal.h"
26
27#include "arcane/core/IParallelMng.h"
28
29#include "arcane/parallel/mpi/MpiDatatype.h"
30#include "arcane/parallel/mpi/MpiParallelDispatch.h"
31
33
34#include "arccore/message_passing_mpi/internal/MpiTypeDispatcherImpl.h"
35#include "arccore/message_passing_mpi/internal/MpiAdapter.h"
36#include "arccore/message_passing_mpi/internal/MpiLock.h"
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane
42{
43
44namespace MP = ::Arccore::MessagePassing;
45
46/*---------------------------------------------------------------------------*/
47/*---------------------------------------------------------------------------*/
48
49template <class Type> MpiParallelDispatchT<Type>::
50MpiParallelDispatchT(ITraceMng* tm, IMessagePassingMng* parallel_mng, MpiAdapter* adapter, MpiDatatype* datatype)
51: TraceAccessor(tm)
52, m_mp_dispatcher(new MP::Mpi::MpiTypeDispatcher<Type>(parallel_mng, adapter, datatype))
53, m_min_max_sum_datatype(MPI_DATATYPE_NULL)
54, m_min_max_sum_operator(MPI_OP_NULL)
55{
56 _initialize();
57}
58
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62template <class Type> MpiParallelDispatchT<Type>::
63~MpiParallelDispatchT()
64{
65 finalize();
66 delete m_mp_dispatcher;
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72template <class Type> void MpiParallelDispatchT<Type>::
73finalize()
74{
75 if (m_min_max_sum_datatype != MPI_DATATYPE_NULL) {
76 MPI_Type_free(&m_min_max_sum_datatype);
77 m_min_max_sum_datatype = MPI_DATATYPE_NULL;
78 }
79 if (m_min_max_sum_operator != MPI_OP_NULL) {
80 MPI_Op_free(&m_min_max_sum_operator);
81 m_min_max_sum_operator = MPI_OP_NULL;
82 }
83}
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88template <class Type> void MpiParallelDispatchT<Type>::
89_initialize()
90{
91 MinMaxSumInfo mmsi;
92
93 int blen[2];
94 MPI_Aint indices[2];
95 MPI_Datatype oldtypes[2];
96
97 blen[0] = 2;
98 indices[0] = 0;
99 oldtypes[0] = MpiBuiltIn::datatype(Integer());
100
101 blen[1] = 3;
102 indices[1] = (char*)&mmsi.m_min_value - (char*)&mmsi;
103 oldtypes[1] = _mpiDatatype();
104
105 MPI_Type_create_struct(2, blen, indices, oldtypes, &m_min_max_sum_datatype);
106 MPI_Type_commit(&m_min_max_sum_datatype);
107
108 MPI_Op_create(_MinMaxSumOperator, 1, &m_min_max_sum_operator);
109}
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
114template <class Type> void ARCANE_MPIOP_CALL MpiParallelDispatchT<Type>::
115_MinMaxSumOperator(void* a, void* b, int* len, MPI_Datatype* type)
116{
117 ARCANE_UNUSED(type);
118
119 Integer n = *len;
120 MinMaxSumInfo* va = static_cast<MinMaxSumInfo*>(a);
121 MinMaxSumInfo* vb = static_cast<MinMaxSumInfo*>(b);
122 for (Integer i = 0; i < n; ++i) {
123 MinMaxSumInfo& ma = va[i];
124 MinMaxSumInfo& mb = vb[i];
125 // It must be certain that in case of equal values
126 // the returned rank is the same for everyone
127 if (ma.m_min_value == mb.m_min_value) {
128 mb.m_min_rank = math::min(mb.m_min_rank, ma.m_min_rank);
129 }
130 else if (ma.m_min_value < mb.m_min_value) {
131 mb.m_min_value = ma.m_min_value;
132 mb.m_min_rank = ma.m_min_rank;
133 }
134 if (mb.m_max_value == ma.m_max_value) {
135 mb.m_max_rank = math::min(mb.m_max_rank, ma.m_max_rank);
136 }
137 else if (mb.m_max_value < ma.m_max_value) {
138 mb.m_max_value = ma.m_max_value;
139 mb.m_max_rank = ma.m_max_rank;
140 }
141 mb.m_sum_value = (Type)(ma.m_sum_value + mb.m_sum_value);
142 }
143}
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
148template <class Type> void MpiParallelDispatchT<Type>::
149computeMinMaxSumNoInit(Type& min_val, Type& max_val, Type& sum_val,
150 Int32& min_rank, Int32& max_rank)
151{
152 MinMaxSumInfo mmsi;
153 mmsi.m_min_rank = min_rank;
154 mmsi.m_max_rank = max_rank;
155 mmsi.m_min_value = min_val;
156 mmsi.m_max_value = max_val;
157 mmsi.m_sum_value = sum_val;
158 MinMaxSumInfo mmsi_ret;
159 _adapter()->allReduce(&mmsi, &mmsi_ret, 1, m_min_max_sum_datatype,
160 m_min_max_sum_operator);
161 min_val = mmsi_ret.m_min_value;
162 max_val = mmsi_ret.m_max_value;
163 sum_val = mmsi_ret.m_sum_value;
164 min_rank = mmsi_ret.m_min_rank;
165 max_rank = mmsi_ret.m_max_rank;
166}
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
171template <class Type> void MpiParallelDispatchT<Type>::
172computeMinMaxSum(Type val, Type& min_val, Type& max_val, Type& sum_val,
173 Int32& min_rank, Int32& max_rank)
174{
175 min_rank = _adapter()->commRank();
176 max_rank = _adapter()->commRank();
177 min_val = val;
178 max_val = val;
179 sum_val = val;
180 computeMinMaxSumNoInit(min_val, max_val, sum_val, min_rank, max_rank);
181}
182
183/*---------------------------------------------------------------------------*/
184/*---------------------------------------------------------------------------*/
185
186template <class Type> void MpiParallelDispatchT<Type>::
187computeMinMaxSum(ConstArrayView<Type> values,
188 ArrayView<Type> min_values,
189 ArrayView<Type> max_values,
190 ArrayView<Type> sum_values,
191 ArrayView<Int32> min_ranks,
192 ArrayView<Int32> max_ranks)
193{
194 const Integer n = values.size();
195 UniqueArray<MinMaxSumInfo> mmsi(n);
196 const Integer comm_rank = m_mp_dispatcher->adapter()->commRank();
197 for (Integer i = 0; i < n; ++i) {
198 mmsi[i].m_min_rank = comm_rank;
199 mmsi[i].m_max_rank = comm_rank;
200 mmsi[i].m_min_value = values[i];
201 mmsi[i].m_max_value = values[i];
202 mmsi[i].m_sum_value = values[i];
203 }
204 UniqueArray<MinMaxSumInfo> mmsi_ret(n);
205 _adapter()->allReduce(mmsi.data(), mmsi_ret.data(), n, m_min_max_sum_datatype,
206 m_min_max_sum_operator);
207 for (Integer i = 0; i < n; ++i) {
208 min_values[i] = mmsi_ret[i].m_min_value;
209 max_values[i] = mmsi_ret[i].m_max_value;
210 sum_values[i] = mmsi_ret[i].m_sum_value;
211 min_ranks[i] = mmsi_ret[i].m_min_rank;
212 max_ranks[i] = mmsi_ret[i].m_max_rank;
213 }
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219template <class Type> void MpiParallelDispatchT<Type>::
220sendRecv(ConstArrayView<Type> send_buffer, ArrayView<Type> recv_buffer, Int32 rank)
221{
222 MPI_Datatype type = _mpiDatatype();
223 _adapter()->directSendRecv(send_buffer.data(), send_buffer.size(),
224 recv_buffer.data(), recv_buffer.size(),
225 rank, sizeof(Type), type);
226}
227
228/*---------------------------------------------------------------------------*/
229/*---------------------------------------------------------------------------*/
230
231template <class Type> Type MpiParallelDispatchT<Type>::
232scan(eReduceType op, Type send_buf)
233{
234 MPI_Datatype type = _mpiDatatype();
235 Type recv_buf = send_buf;
236 _adapter()->scan(&send_buf, &recv_buf, 1, type, _mpiReduceOperator(op));
237 return recv_buf;
238}
239
240/*---------------------------------------------------------------------------*/
241/*---------------------------------------------------------------------------*/
242
243template <class Type> void MpiParallelDispatchT<Type>::
244scan(eReduceType op, ArrayView<Type> send_buf)
245{
246 MPI_Datatype type = _mpiDatatype();
247 Integer s = send_buf.size();
248 UniqueArray<Type> recv_buf(s);
249 _adapter()->scan(send_buf.data(), recv_buf.data(), s, type, _mpiReduceOperator(op));
250 send_buf.copy(recv_buf);
251}
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
256template <class Type> MPI_Datatype MpiParallelDispatchT<Type>::
257_mpiDatatype()
258{
259 return m_mp_dispatcher->datatype()->datatype();
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265template <class Type> MPI_Op MpiParallelDispatchT<Type>::
266_mpiReduceOperator(eReduceType rt)
267{
268 return m_mp_dispatcher->datatype()->reduceOperator(rt);
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
274template <class Type> MpiAdapter* MpiParallelDispatchT<Type>::
275_adapter()
276{
277 return m_mp_dispatcher->adapter();
278}
279
280/*---------------------------------------------------------------------------*/
281/*---------------------------------------------------------------------------*/
282
283template <class Type> MpiDatatype* MpiParallelDispatchT<Type>::
284datatype() const
285{
286 return m_mp_dispatcher->datatype();
287}
288
289template <class Type> ITypeDispatcher<Type>* MpiParallelDispatchT<Type>::
290toArccoreDispatcher()
291{
292 return m_mp_dispatcher;
293}
294
295/*---------------------------------------------------------------------------*/
296/*---------------------------------------------------------------------------*/
297
298template class MpiParallelDispatchT<char>;
299template class MpiParallelDispatchT<signed char>;
300template class MpiParallelDispatchT<unsigned char>;
301template class MpiParallelDispatchT<short>;
302template class MpiParallelDispatchT<unsigned short>;
303template class MpiParallelDispatchT<int>;
304template class MpiParallelDispatchT<unsigned int>;
305template class MpiParallelDispatchT<long>;
306template class MpiParallelDispatchT<unsigned long>;
307template class MpiParallelDispatchT<long long>;
308template class MpiParallelDispatchT<unsigned long long>;
309template class MpiParallelDispatchT<float>;
310template class MpiParallelDispatchT<double>;
311template class MpiParallelDispatchT<long double>;
312template class MpiParallelDispatchT<APReal>;
313template class MpiParallelDispatchT<Real2>;
314template class MpiParallelDispatchT<Real3>;
315template class MpiParallelDispatchT<Real2x2>;
316template class MpiParallelDispatchT<Real3x3>;
317template class MpiParallelDispatchT<HPReal>;
318
319/*---------------------------------------------------------------------------*/
320/*---------------------------------------------------------------------------*/
321
322} // namespace Arcane
323
324/*---------------------------------------------------------------------------*/
325/*---------------------------------------------------------------------------*/
326
327namespace Arcane::MessagePassing::Mpi
328{
329using namespace Arcane;
330template class MpiTypeDispatcher<APReal>;
331template class MpiTypeDispatcher<Real2>;
332template class MpiTypeDispatcher<Real3>;
333template class MpiTypeDispatcher<Real2x2>;
334template class MpiTypeDispatcher<Real3x3>;
335template class MpiTypeDispatcher<HPReal>;
336} // namespace Arcane::MessagePassing::Mpi
337
338/*---------------------------------------------------------------------------*/
339/*---------------------------------------------------------------------------*/
Brief list of message exchange functions.
Interface of the message passing manager.
Message interface for type Type.
Integer len(const char *s)
Returns the length of the string s.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
Namespace containing the types and declarations that manage the message-passing parallelism mechanism...
Type
Type of JSON value.
Definition rapidjson.h:730