Arcane  4.2.3.0
User documentation
Loading...
Searching...
No Matches
StandaloneMpiMessagePassingMng.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/* StandaloneMpiMessagePassingMng.cc (C) 2000-2026 */
9/* */
10/* MPI implementation of the message exchange manager. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/message_passing_mpi/StandaloneMpiMessagePassingMng.h"
15
16#include "arccore/message_passing/Dispatchers.h"
17#include "arccore/message_passing/Stat.h"
18#include "arccore/trace/ITraceMng.h"
19#include "arccore/base/ReferenceCounter.h"
20#include "arccore/base/BFloat16.h"
21#include "arccore/base/Float16.h"
22
23#include "arccore/message_passing_mpi/MpiDatatype.h"
24#include "arccore/message_passing_mpi/internal/MpiMessagePassingMng.h"
25#include "arccore/message_passing_mpi/internal/MpiAdapter.h"
26#include "arccore/message_passing_mpi/internal/MpiTypeDispatcher.h"
27#include "arccore/message_passing_mpi/internal/MpiControlDispatcher.h"
28#include "arccore/message_passing_mpi/internal/MpiSerializeDispatcher.h"
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
33namespace Arcane::MessagePassing::Mpi
34{
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39class ARCCORE_MESSAGEPASSINGMPI_EXPORT StandaloneMpiMessagePassingMng2
40: public MpiMessagePassingMng
41{
42 class Impl;
43 friend class StandaloneMpiMessagePassingMng;
44
45 private:
46
47 explicit StandaloneMpiMessagePassingMng2(Impl* p);
48
49 public:
50
51 ~StandaloneMpiMessagePassingMng2() override;
52
53 private:
54
55 //! Creates a manager associated with the communicator \a comm.
56 static MpiMessagePassingMng* create(MPI_Comm comm, bool clean_comm = false);
57
58 /*!
59 * \brief Creates a manager associated with the communicator \a comm.
60 *
61 * If \a clean_comm is true, MPI_Comm_free() is called on \a comm
62 * when the instance is destroyed.
63 */
64 static Ref<IMessagePassingMng> createRef(MPI_Comm comm, bool clean_comm = false);
65
66 static Ref<IMessagePassingMng> createAndInitializeMPI(int* argc, char** argv[], int wanted_thread_level);
67
68 private:
69
70 Impl* m_p = nullptr;
71
72 private:
73
74 static MpiMessagePassingMng* _create(Impl* p);
75};
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79
81{
82 public:
83
84 explicit Impl(MPI_Comm mpi_comm, bool clean_comm = false)
85 : m_communicator(mpi_comm)
86 , m_clean_comm(clean_comm)
87 {
88 _init();
89 }
90
91 explicit Impl(int* argc, char** argv[], int wanted_thread_level)
92 : m_communicator(MPI_COMM_WORLD)
93 {
94 int provided = 0;
95 int r = MPI_Init_thread(argc, argv, wanted_thread_level, &provided);
96 if (r != MPI_SUCCESS)
97 ARCCORE_FATAL("Error when calling MPI_Init_thread err={0}", r);
98 if (provided != wanted_thread_level) {
99 int rank = 0;
100 ::MPI_Comm_rank(m_communicator, &rank);
101 if (rank == 0)
102 std::cerr << "WARNING: MPI_Init_thread provided level (" << provided
103 << ") is not the wanted level (" << wanted_thread_level << ")\n";
104 }
105 m_do_finalize = true;
106 _init();
107 }
108
109 ~Impl()
110 {
111 try {
112 m_adapter->destroy();
113 }
114 catch (const Exception& ex) {
115 std::cerr << "ERROR: msg=" << ex << "\n";
116 }
117
118 delete m_dispatchers;
119 delete m_stat;
120
121 if (m_clean_comm)
122 MPI_Comm_free(&m_communicator);
123 if (m_do_finalize)
124 MPI_Finalize();
125 }
126
127 void _init()
128 {
129 m_trace_mng = Arccore::arccoreCreateDefaultTraceMng();
130 MPI_Comm mpi_comm = m_communicator;
131 ::MPI_Comm_rank(mpi_comm, &m_comm_rank);
132 ::MPI_Comm_size(mpi_comm, &m_comm_size);
133 m_stat = new Stat();
134 MpiLock* mpi_lock = nullptr;
135 m_adapter = new MpiAdapter(m_trace_mng.get(), m_stat, mpi_comm, mpi_lock);
136
137 m_dispatchers = new Dispatchers();
138 m_dispatchers->setDeleteDispatchers(true);
139 }
140
141 MpiMessagePassingMng::BuildInfo
142 buildInfo() const
143 {
144 return MpiMessagePassingMng::BuildInfo(m_comm_rank, m_comm_size, m_dispatchers, m_communicator);
145 }
146
147 public:
148
149 ReferenceCounter<ITraceMng> m_trace_mng;
150 IStat* m_stat = nullptr;
151 Dispatchers* m_dispatchers = nullptr;
152 MpiAdapter* m_adapter = nullptr;
153 int m_comm_rank = A_NULL_RANK;
154 int m_comm_size = A_NULL_RANK;
155 MPI_Comm m_communicator = MPI_COMM_NULL;
156 bool m_clean_comm = false;
157 bool m_do_finalize = false;
158};
159
160/*---------------------------------------------------------------------------*/
161/*---------------------------------------------------------------------------*/
162
163StandaloneMpiMessagePassingMng2::
164StandaloneMpiMessagePassingMng2(Impl* p)
165: MpiMessagePassingMng(p->buildInfo())
166, m_p(p)
167{
168 setTraceMng(p->m_trace_mng.get());
169}
170
171/*---------------------------------------------------------------------------*/
172/*---------------------------------------------------------------------------*/
173
174StandaloneMpiMessagePassingMng2::
175~StandaloneMpiMessagePassingMng2()
176{
177 delete m_p;
178}
179
180namespace
181{
182 template <typename DataType> void
183 _createAndSetCustomDispatcher(Dispatchers* dispatchers, IMessagePassingMng* mpm,
184 MpiAdapter* adapter, MpiDatatype* datatype)
185 {
186 auto* x = new MpiTypeDispatcher<DataType>(mpm, adapter, datatype);
187 x->setDestroyDatatype(true);
188 dispatchers->setDispatcher(x);
189 }
190
191 template <typename DataType> void
192 _createAndSetDispatcher(Dispatchers* dispatchers, IMessagePassingMng* mpm,
193 MpiAdapter* adapter)
194 {
195 MPI_Datatype mpi_dt = MpiBuiltIn::datatype(DataType());
196 auto dt = new MpiDatatype(mpi_dt);
197 _createAndSetCustomDispatcher<DataType>(dispatchers, mpm, adapter, dt);
198 }
199
200} // namespace
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
204
205MpiMessagePassingMng* StandaloneMpiMessagePassingMng2::
206_create(Impl* p)
207{
208 auto mpm = new StandaloneMpiMessagePassingMng2(p);
209 auto adapter = p->m_adapter;
210 auto dsp = p->m_dispatchers;
211
212 _createAndSetDispatcher<char>(dsp, mpm, adapter);
213 _createAndSetDispatcher<signed char>(dsp, mpm, adapter);
214 _createAndSetDispatcher<unsigned char>(dsp, mpm, adapter);
215 _createAndSetDispatcher<short>(dsp, mpm, adapter);
216 _createAndSetDispatcher<unsigned short>(dsp, mpm, adapter);
217 _createAndSetDispatcher<int>(dsp, mpm, adapter);
218 _createAndSetDispatcher<unsigned int>(dsp, mpm, adapter);
219 _createAndSetDispatcher<long>(dsp, mpm, adapter);
220 _createAndSetDispatcher<unsigned long>(dsp, mpm, adapter);
221 _createAndSetDispatcher<long long>(dsp, mpm, adapter);
222 _createAndSetDispatcher<unsigned long long>(dsp, mpm, adapter);
223 _createAndSetDispatcher<float>(dsp, mpm, adapter);
224 _createAndSetDispatcher<double>(dsp, mpm, adapter);
225 _createAndSetDispatcher<long double>(dsp, mpm, adapter);
226
227 dsp->setDispatcher(new MpiControlDispatcher(adapter, mpm));
228 dsp->setDispatcher(new MpiSerializeDispatcher(adapter, mpm));
229
230 MPI_Datatype uint8_datatype = MpiBuiltIn::datatype(uint8_t{});
231 {
232 // BFloat16
233 MPI_Datatype mpi_datatype;
234 MPI_Type_contiguous(2, uint8_datatype, &mpi_datatype);
235 MPI_Type_commit(&mpi_datatype);
236 auto* x = new MpiDatatype(mpi_datatype, false, new StdMpiReduceOperator<BFloat16>(true));
237 _createAndSetCustomDispatcher<BFloat16>(dsp, mpm, adapter, x);
238 }
239 {
240 // Float16
241 MPI_Datatype mpi_datatype;
242 MPI_Type_contiguous(2, uint8_datatype, &mpi_datatype);
243 MPI_Type_commit(&mpi_datatype);
244 auto* x = new MpiDatatype(mpi_datatype, false, new StdMpiReduceOperator<Float16>(true));
245 _createAndSetCustomDispatcher<Float16>(dsp, mpm, adapter, x);
246 }
247 return mpm;
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
253MpiMessagePassingMng* StandaloneMpiMessagePassingMng2::
254create(MPI_Comm mpi_comm, bool clean_comm)
255{
256 Impl* p = new Impl(mpi_comm, clean_comm);
257 return _create(p);
258}
259
260/*---------------------------------------------------------------------------*/
261/*---------------------------------------------------------------------------*/
262
263Ref<IMessagePassingMng> StandaloneMpiMessagePassingMng2::
264createRef(MPI_Comm mpi_comm, bool clean_comm)
265{
266 MpiMessagePassingMng* v = create(mpi_comm, clean_comm);
268}
269
270/*---------------------------------------------------------------------------*/
271/*---------------------------------------------------------------------------*/
272
273Ref<IMessagePassingMng> StandaloneMpiMessagePassingMng2::
274createAndInitializeMPI(int* argc, char** argv[], int wanted_thread_level)
275{
276 Impl* p = new Impl(argc, argv, wanted_thread_level);
277 MpiMessagePassingMng* v = _create(p);
279}
280
281/*---------------------------------------------------------------------------*/
282/*---------------------------------------------------------------------------*/
283
284/*---------------------------------------------------------------------------*/
285/*---------------------------------------------------------------------------*/
286
288create(MPI_Comm mpi_comm, bool clean_comm)
289{
290 return StandaloneMpiMessagePassingMng2::create(mpi_comm, clean_comm);
291}
292
293/*---------------------------------------------------------------------------*/
294/*---------------------------------------------------------------------------*/
295
297createRef(MPI_Comm mpi_comm, bool clean_comm)
298{
299 return StandaloneMpiMessagePassingMng2::createRef(mpi_comm, clean_comm);
300}
301
302/*---------------------------------------------------------------------------*/
303/*---------------------------------------------------------------------------*/
304
307{
308 return StandaloneMpiMessagePassingMng2::createRef(MPI_COMM_WORLD);
309}
310
311/*---------------------------------------------------------------------------*/
312/*---------------------------------------------------------------------------*/
313
315createAndInitializeMPI(int* argc, char** argv[], int wanted_thread_level)
316{
317 return StandaloneMpiMessagePassingMng2::createAndInitializeMPI(argc, argv, wanted_thread_level);
318}
319
320/*---------------------------------------------------------------------------*/
321/*---------------------------------------------------------------------------*/
322
323} // End namespace Arcane::MessagePassing::Mpi
324
325/*---------------------------------------------------------------------------*/
326/*---------------------------------------------------------------------------*/
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Interface of the dispatcher container.
Definition Dispatchers.h:35
Interface of the message passing manager.
static Ref< IMessagePassingMng > createAndInitializeMPI(int *argc, char **argv[], int wanted_thread_level)
Initialize MPI and creates a manager associated with the MPI_WORLD_COMM communicator.
static Ref< IMessagePassingMng > createRef(MPI_Comm comm, bool clean_comm=false)
Creates a manager associated with the communicator comm.
static Ref< IMessagePassingMng > createWorldRef()
Creates a manager associated with the MPI_WORLD_COMM communicator.
static IMessagePassingMng * create(MPI_Comm comm, bool clean_comm=false)
Creates a manager associated with the communicator comm.
Reference to an instance.
Encapsulation of a pointer with a reference counter.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.