Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
SharedMemoryParallelSuperMng.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/* SharedMemoryParallelSuperMng.cc (C) 2000-2026 */
9/* */
10/* Message manager using only shared memory. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/parallel/thread/SharedMemoryParallelSuperMng.h"
15
16#include "arcane/utils/ApplicationInfo.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/NotImplementedException.h"
19#include "arcane/utils/FatalErrorException.h"
20#include "arcane/utils/ArgumentException.h"
21#include "arcane/utils/ValueConvert.h"
22#include "arcane/utils/IThreadMng.h"
23#include "arcane/utils/TraceClassConfig.h"
24#include "arcane/utils/ITraceMng.h"
25#include "arcane/utils/IThreadImplementation.h"
26#include "arcane/utils/Mutex.h"
27
28#include "arcane/parallel/IStat.h"
29
30#include "arcane/parallel/thread/SharedMemoryParallelMng.h"
31#include "arcane/parallel/thread/SharedMemoryParallelDispatch.h"
32#include "arcane/parallel/thread/SharedMemoryMessageQueue.h"
33#include "arcane/parallel/thread/internal/SharedMemoryThreadMng.h"
34#include "arcane/parallel/thread/internal/SharedMemoryMachineShMemWinBaseInternalCreator.h"
35
36#include "arcane/core/FactoryService.h"
37#include "arcane/core/IApplication.h"
38#include "arcane/core/ParallelSuperMngDispatcher.h"
39#include "arcane/core/ApplicationBuildInfo.h"
40#include "arcane/core/AbstractService.h"
41#include "arcane/core/ServiceBuilder.h"
42
43#include "arcane/core/IMainFactory.h"
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
49{
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
57class SharedMemoryParallelMngContainer
59{
60 public:
61
62 SharedMemoryParallelMngContainer(IApplication* app, Int32 nb_local_rank,
63 MP::Communicator mpi_comm,
65 ~SharedMemoryParallelMngContainer() override;
66
67 public:
68
69 void build();
70 Ref<IParallelMng> _createParallelMng(Int32 local_rank, ITraceMng* tm) override;
71
72 public:
73
75 Int32 m_nb_local_rank;
76 SharedMemoryThreadMng* m_thread_mng;
77 ISharedMemoryMessageQueue* m_message_queue = nullptr;
78 Mutex* m_internal_create_mutex = nullptr;
79 IThreadBarrier* m_thread_barrier = nullptr;
80 SharedMemoryAllDispatcher* m_all_dispatchers = nullptr;
81 IParallelMngContainerFactory* m_sub_factory_builder = nullptr;
82 SharedMemoryMachineShMemWinBaseInternalCreator* m_window_creator = nullptr;
83
84 private:
85
86 MP::Communicator m_communicator;
87};
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
91
92SharedMemoryParallelMngContainer::
93SharedMemoryParallelMngContainer(IApplication* app, Int32 nb_local_rank,
94 MP::Communicator mpi_comm,
96: m_application(app)
97, m_nb_local_rank(nb_local_rank)
98, m_thread_mng(new SharedMemoryThreadMng())
99, m_sub_factory_builder(factory)
100, m_communicator(mpi_comm)
101{
102}
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
107SharedMemoryParallelMngContainer::
108~SharedMemoryParallelMngContainer()
109{
110 if (m_thread_barrier)
111 m_thread_barrier->destroy();
112 delete m_message_queue;
113 delete m_thread_mng;
114 delete m_all_dispatchers;
115 delete m_internal_create_mutex;
116 delete m_window_creator;
117}
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
122void SharedMemoryParallelMngContainer::
123build()
124{
125 m_message_queue = new SharedMemoryMessageQueue();
126 m_message_queue->init(m_nb_local_rank);
127
128 m_thread_barrier = platform::getThreadImplementationService()->createBarrier();
129 m_thread_barrier->init(m_nb_local_rank);
130
131 m_all_dispatchers = new SharedMemoryAllDispatcher();
132 m_all_dispatchers->resize(m_nb_local_rank);
133
134 m_internal_create_mutex = new Mutex();
135
136 m_window_creator = new SharedMemoryMachineShMemWinBaseInternalCreator(m_nb_local_rank, m_thread_barrier);
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
143_createParallelMng(Int32 local_rank, ITraceMng* tm)
144{
145 if (local_rank < 0 || local_rank >= m_nb_local_rank)
146 ARCANE_THROW(ArgumentException, "Bad value '{0}' for local_rank (max={1})",
147 local_rank, m_nb_local_rank);
148
149 // This method is not reentrant.
150 Mutex::ScopedLock sl(m_internal_create_mutex);
151
152 IParallelSuperMng* sm = m_application->sequentialParallelSuperMng();
154 build_info.rank = local_rank;
155 build_info.nb_rank = m_nb_local_rank;
156 build_info.trace_mng = tm;
157 build_info.thread_mng = m_thread_mng;
158 build_info.sequential_parallel_mng = sm->internalCreateWorldParallelMng(0);
159 build_info.world_parallel_mng = nullptr;
160 build_info.message_queue = m_message_queue;
161 build_info.thread_barrier = m_thread_barrier;
162 build_info.all_dispatchers = m_all_dispatchers;
163 build_info.sub_builder_factory = m_sub_factory_builder;
164 build_info.container = makeRef<IParallelMngContainer>(this);
165 build_info.window_creator = m_window_creator;
166 // Only rank 0 positions the eventual communicator, otherwise all PEs
167 // will end up with the same MPI rank
168 if (local_rank == 0)
169 build_info.communicator = m_communicator;
170
171 IParallelMng* pm = new SharedMemoryParallelMng(build_info);
172 pm->build();
173
174 return makeRef(pm);
175}
176
177/*---------------------------------------------------------------------------*/
178/*---------------------------------------------------------------------------*/
179
180class SharedMemoryParallelMngContainerFactory
181: public AbstractService
183{
184 public:
185
186 SharedMemoryParallelMngContainerFactory(const ServiceBuildInfo& sbi)
187 : AbstractService(sbi)
188 , m_application(sbi.application())
189 {}
190
191 public:
192
193 Ref<IParallelMngContainer> _createParallelMngBuilder(Int32 nb_rank, MP::Communicator comm, MP::Communicator machine_comm) override
194 {
195 ARCANE_UNUSED(machine_comm);
196 auto x = new SharedMemoryParallelMngContainer(m_application, nb_rank, comm, this);
197 x->build();
199 }
200
201 private:
202
203 IApplication* m_application;
204};
205
206/*---------------------------------------------------------------------------*/
207/*---------------------------------------------------------------------------*/
208
210 ServiceProperty("SharedMemoryParallelMngContainerFactory", ST_Application),
212
213/*---------------------------------------------------------------------------*/
214/*---------------------------------------------------------------------------*/
215
216SharedMemoryParallelSuperMng::
217SharedMemoryParallelSuperMng(const ServiceBuildInfo& sbi)
219{
220}
221
222/*---------------------------------------------------------------------------*/
223/*---------------------------------------------------------------------------*/
224
225SharedMemoryParallelSuperMng::
226SharedMemoryParallelSuperMng(const ServiceBuildInfo& sbi, MP::Communicator comm,
227 bool has_mpi_init)
228: m_application(sbi.application())
229, m_stat(nullptr)
230, m_is_parallel(false)
231, m_communicator(comm)
232{
234 m_has_mpi_init = has_mpi_init;
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
239
240SharedMemoryParallelSuperMng::
241~SharedMemoryParallelSuperMng()
242{
243 delete m_stat;
244}
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
253
254/*---------------------------------------------------------------------------*/
255/*---------------------------------------------------------------------------*/
256
258build()
259{
260 if (!arcaneHasThread())
261 ARCANE_FATAL("Can not create SharedMemoryParallelSuperMng because threads are disabled");
262
263 // If initialized with MPI, null requests and the null communicator
264 // have already been positioned.
265 if (!m_has_mpi_init) {
266 Request::setNullRequest(Request(0, nullptr, 0));
267 Parallel::Communicator::setNullCommunicator(Parallel::Communicator((void*)nullptr));
268 }
269
270 m_is_parallel = true;
271 Int32 n = m_application->applicationBuildInfo().nbSharedMemorySubDomain();
272 if (n == 0)
273 ARCANE_FATAL("Number of shared memory sub-domains is not defined");
274
275 ITraceMng* app_tm = m_application->traceMng();
276 app_tm->info() << "SharedMemoryParallelSuperMng: nb_local_sub_domain=" << n;
277 app_tm->info() << "SharedMemoryParallelSuperMng: mpi_communicator=" << getMPICommunicator();
279 String service_name = "SharedMemoryParallelMngContainerFactory";
280 m_builder_factory = sb.createReference(service_name);
281 Ref<IParallelMngContainer> x = m_builder_factory->_createParallelMngBuilder(n, communicator(), communicator());
282 m_main_builder = x;
283 m_container = dynamic_cast<SharedMemoryParallelMngContainer*>(x.get());
284 ARCANE_CHECK_POINTER(m_container);
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
292{
293 Int32 max_rank = nbLocalSubDomain();
294 if (local_rank < 0 || local_rank >= max_rank)
295 ARCANE_THROW(ArgumentException, "Bad value '{0}' for local_rank (max={1})",
296 local_rank, max_rank);
297
298 ITraceMng* tm = nullptr;
299 ITraceMng* app_tm = m_application->traceMng();
300 if (local_rank == 0) {
301 // The first created subdomain uses the default traceMng().
302 tm = app_tm;
303 }
304 else {
305 tm = m_application->createAndInitializeTraceMng(app_tm, String::fromNumber(local_rank));
306 }
307
308 Ref<IParallelMng> pm = m_container->_createParallelMng(local_rank, tm);
309 return pm;
310}
311
312/*---------------------------------------------------------------------------*/
313/*---------------------------------------------------------------------------*/
314
316tryAbort()
317{
318 m_application->traceMng()->flush();
319 ::abort();
320}
321
322/*---------------------------------------------------------------------------*/
323/*---------------------------------------------------------------------------*/
324
326broadcast(ByteArrayView send_buf, Int32 process_id)
327{
328 ARCANE_UNUSED(send_buf);
329 ARCANE_UNUSED(process_id);
330}
331
332/*---------------------------------------------------------------------------*/
333/*---------------------------------------------------------------------------*/
334
336broadcast(Int32ArrayView send_buf, Int32 process_id)
337{
338 ARCANE_UNUSED(send_buf);
339 ARCANE_UNUSED(process_id);
340}
341
342/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
346broadcast(Int64ArrayView send_buf, Int32 process_id)
347{
348 ARCANE_UNUSED(send_buf);
349 ARCANE_UNUSED(process_id);
350}
351
352/*---------------------------------------------------------------------------*/
353/*---------------------------------------------------------------------------*/
354
356broadcast(RealArrayView send_buf, Int32 process_id)
357{
358 ARCANE_UNUSED(send_buf);
359 ARCANE_UNUSED(process_id);
360}
361
362/*---------------------------------------------------------------------------*/
363/*---------------------------------------------------------------------------*/
364
366threadMng() const
367{
368 return m_container->m_thread_mng;
369}
370
371/*---------------------------------------------------------------------------*/
372/*---------------------------------------------------------------------------*/
373
376{
377 return m_container->m_nb_local_rank;
378}
379
380/*---------------------------------------------------------------------------*/
381/*---------------------------------------------------------------------------*/
382
384 ServiceProperty("SharedMemoryParallelSuperMng", ST_Application),
386
387// Old name
389 ServiceProperty("ThreadParallelSuperMng", ST_Application),
391
392/*---------------------------------------------------------------------------*/
393/*---------------------------------------------------------------------------*/
394
395} // End namespace Arcane::MessagePassing
396
397/*---------------------------------------------------------------------------*/
398/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
AbstractService(const ServiceBuildInfo &)
Constructor from a ServiceBuildInfo.
Application interface.
Interface for an 'IParallelMng' container factory.
Interface of the parallelism manager for a subdomain.
virtual void build()=0
Constructs the instance.
Abstract class of the parallelism supervisor.
virtual Ref< IParallelMng > internalCreateWorldParallelMng(Int32 local_rank)=0
Creates a parallelism manager for all allocated cores.
virtual void destroy()=0
Destroys the barrier.
virtual void init(Integer nb_thread)=0
Initializes the barrier for nb_thread.
Interface of a thread manager.
Definition IThreadMng.h:32
virtual TraceMessage info()=0
Stream for an information message.
Communicator for message exchange.
Container for shared memory message manager information.
Ref< IParallelMng > _createParallelMng(Int32 local_rank, ITraceMng *tm) override
Creates the IParallelMng for the local rank local_rank.
Ref< IParallelMng > internalCreateWorldParallelMng(Int32 local_rank) override
Creates a parallelism manager for all allocated cores.
void build() override
Constructs the instance members.
void broadcast(ByteArrayView send_buf, Int32 rank) override
Sends an array of values to all processes This operation synchronizes the value array send_buf across...
void * getMPICommunicator() override
Address of the MPI communicator associated with this manager.
Parallel::Communicator communicator() const override
MPI communicator associated with this manager.
Int32 nbLocalSubDomain() override
Number of subdomains to create locally.
InstanceType * get() const
Associated instance or nullptr if none.
Reference to an instance.
IApplication * application() const
Access to the associated IApplication.
Structure containing the information to create a service.
Utility class for instantiating a service of a given interface.
Ref< InterfaceType > createReference(const String &name, eServiceBuilderProperties properties=SB_None)
Creates an instance implementing the InterfaceType interface.
Service creation properties.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
Declarations of types and methods used by message exchange mechanisms.
IStat * createDefaultStat()
Creates a default instance.
IThreadImplementation * getThreadImplementationService()
Service used to manage threads.
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:451
bool arcaneHasThread()
True if arcane is compiled with thread support AND they are active.
Definition Misc.cc:88
ArrayView< Byte > ByteArrayView
C equivalent of a 1D array of characters.
Definition UtilsTypes.h:447
@ ST_Application
The service is used at the application level.
ArrayView< Int32 > Int32ArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:453
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
ArrayView< Real > RealArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:459
std::int32_t Int32
Signed integer type of 32 bits.