14#include "arcane/utils/ApplicationInfo.h"
15#include "arcane/utils/NullThreadMng.h"
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/ValueConvert.h"
20#include "arcane/utils/TraceClassConfig.h"
21#include "arcane/utils/ArgumentException.h"
22#include "arcane/utils/CommandLineArguments.h"
24#include "arcane/parallel/IStat.h"
26#include "arcane/parallel/mpi/MpiParallelMng.h"
27#include "arcane/parallel/mpi/MpiParallelDispatch.h"
28#include "arcane/parallel/mpi/MpiErrorHandler.h"
30#include "arccore/message_passing_mpi/internal/MpiAdapter.h"
31#include "arccore/message_passing_mpi/internal/MpiLock.h"
33#include "arcane/parallel/thread/SharedMemoryMessageQueue.h"
34#include "arcane/parallel/thread/SharedMemoryParallelMng.h"
35#include "arcane/parallel/thread/SharedMemoryParallelSuperMng.h"
36#include "arcane/parallel/thread/internal/SharedMemoryThreadMng.h"
38#include "arcane/parallel/mpithread/HybridParallelMng.h"
39#include "arcane/parallel/mpithread/HybridParallelDispatch.h"
40#include "arcane/parallel/mpithread/internal/HybridMachineShMemWinBaseInternalCreator.h"
42#include "arcane/core/FactoryService.h"
43#include "arcane/core/AbstractService.h"
44#include "arcane/core/IApplication.h"
45#include "arcane/core/ParallelSuperMngDispatcher.h"
46#include "arcane/core/ApplicationBuildInfo.h"
47#include "arcane/core/ServiceBuilder.h"
49#include "arcane/core/IMainFactory.h"
65class HybridParallelMngContainer
71 MP::Communicator mpi_comm, MP::Communicator mpi_machine_comm,
74 ~HybridParallelMngContainer()
override;
89 Int32 m_local_nb_rank = -1;
93 Mutex* m_internal_create_mutex =
nullptr;
106 void _setMPICommunicator();
112HybridParallelMngContainer::
114 MP::Communicator mpi_comm, MP::Communicator mpi_machine_comm,
120, m_mpi_lock(mpi_lock)
121, m_local_nb_rank(nb_local_rank)
123, m_sub_builder_factory(factory)
124, m_mpi_communicator(mpi_comm)
125, m_mpi_machine_communicator(mpi_machine_comm)
127 _setMPICommunicator();
133HybridParallelMngContainer::
134~HybridParallelMngContainer()
138 delete m_message_queue;
140 delete m_all_dispatchers;
141 delete m_parallel_mng_list;
142 delete m_internal_create_mutex;
143 delete m_window_creator;
149void HybridParallelMngContainer::
152 m_internal_create_mutex =
new Mutex();
154 m_all_dispatchers =
new MpiThreadAllDispatcher();
155 m_all_dispatchers->resize(m_local_nb_rank);
157 m_parallel_mng_list->resize(m_local_nb_rank);
158 m_parallel_mng_list->fill(
nullptr);
160 m_message_queue =
new SharedMemoryMessageQueue();
161 m_message_queue->init(m_local_nb_rank);
164 m_thread_barrier->
init(m_local_nb_rank);
166 m_window_creator =
new HybridMachineShMemWinBaseInternalCreator(m_local_nb_rank, m_thread_barrier);
172void HybridParallelMngContainer::
177 if (comm == MPI_COMM_NULL)
178 ARCANE_THROW(ArgumentException,
"Null MPI Communicator");
196 if (local_rank < 0 || local_rank >= m_local_nb_rank)
198 local_rank, m_local_nb_rank);
204 bool is_parallel = nb_process > 1;
208 bi.is_parallel = is_parallel;
212 bi.is_mpi_comm_owned =
false;
213 bi.mpi_lock = m_mpi_lock;
216 tm->
info() <<
"MPI implementation need serialized threads : using locks";
222 mpi_pm->adapter()->enableDebugRequest(
false);
225 build_info.local_rank = local_rank;
226 build_info.local_nb_rank = m_local_nb_rank;
227 build_info.mpi_parallel_mng = mpi_pm;
228 build_info.trace_mng = tm;
230 build_info.message_queue = m_message_queue;
231 build_info.thread_barrier = m_thread_barrier;
232 build_info.parallel_mng_list = m_parallel_mng_list;
233 build_info.all_dispatchers = m_all_dispatchers;
234 build_info.sub_builder_factory = m_sub_builder_factory;
236 build_info.window_creator = m_window_creator;
241 (*m_parallel_mng_list)[local_rank] = pm;
252class HybridParallelMngContainerFactory
266 _createParallelMngBuilder(
Int32 nb_rank, MP::Communicator mpi_communicator,
267 MP::Communicator mpi_machine_communicator)
override
270 mpi_machine_communicator,
271 this, m_stat, m_mpi_lock);
302class HybridParallelSuperMng
303:
public ParallelSuperMngDispatcher
308 ~HybridParallelSuperMng()
override;
311 void build()
override;
320 MP::Communicator
communicator()
const override {
return m_communicator; }
338 MPI_Comm m_mpi_communicator;
339 MP::Communicator m_communicator;
340 MP::Communicator m_machine_communicator;
341 Int32 m_local_nb_rank = A_NULL_RANK;
351HybridParallelSuperMng::
353: m_application(sbi.application())
356, m_mpi_communicator(MPI_COMM_NULL)
357, m_local_nb_rank(A_NULL_RANK)
359, m_mpi_adapter(nullptr)
360, m_datatype_list(nullptr)
368HybridParallelSuperMng::
369~HybridParallelSuperMng()
371 m_error_handler.removeHandler();
373 delete m_datatype_list;
378 MPI_Barrier(m_mpi_communicator);
379 MPI_Comm_free(&m_mpi_communicator);
380 m_mpi_communicator = MPI_COMM_NULL;
381 MPI_Comm_free(
static_cast<MPI_Comm*
>(m_machine_communicator.communicatorAddress()));
400 ARCANE_FATAL(
"Can not create HybridParallelSuperMng because threads are disabled");
402 Request::setNullRequest(
Request(0,
nullptr, MPI_REQUEST_NULL));
403 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
407 char*** argv =
nullptr;
411 argc = cmd_line_args.commandLineArgc();
412 argv = cmd_line_args.commandLineArgv();
414 bool need_serialize =
false;
425 int thread_wanted = MPI_THREAD_MULTIPLE;
426 int thread_provided = 0;
431 MPI_Query_thread(&thread_provided);
433 if (thread_provided < MPI_THREAD_MULTIPLE) {
434 if (thread_provided >= MPI_THREAD_SERIALIZED)
435 need_serialize =
true;
440 MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
442 ARCANE_FATAL(
"MPI thread level provided!=wanted ({0}!={1})",
443 thread_provided, thread_wanted);
453 MPI_Comm_dup(MPI_COMM_WORLD, &m_mpi_communicator);
455 MPI_Comm_rank(m_mpi_communicator, &rank);
456 MPI_Comm_size(m_mpi_communicator, &size);
461 MPI_Comm mpi_machine_communicator = MPI_COMM_NULL;
462 MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED,
m_mpi_comm_rank, MPI_INFO_NULL, &mpi_machine_communicator);
463 m_machine_communicator =
Communicator(mpi_machine_communicator);
467 m_error_handler.registerHandler(m_mpi_communicator);
471 ARCANE_FATAL(
"Number of shared memory sub-domains is not defined");
476 tm->
info() <<
"MPI has non blocking collective";
477 tm->
info() <<
"MPI: sizeof(MPI_Count)=" <<
sizeof(MPI_Count);
479 tm->
info() <<
"MPI: init_time (seconds)=" << (end_time - start_time);
489 auto* adapter =
new MpiAdapter(tm, m_stat->toArccoreStat(), m_communicator,
nullptr);
490 m_mpi_adapter = adapter;
491 auto c = createBuiltInDispatcher<Byte>(tm,
nullptr, m_mpi_adapter, m_datatype_list);
492 auto i32 = createBuiltInDispatcher<Int32>(tm,
nullptr, m_mpi_adapter, m_datatype_list);
493 auto i64 = createBuiltInDispatcher<Int64>(tm,
nullptr, m_mpi_adapter, m_datatype_list);
494 auto r = createBuiltInDispatcher<Real>(tm,
nullptr, m_mpi_adapter, m_datatype_list);
495 _setDispatchers(c, i32, i64, r);
498 String service_name =
"HybridParallelMngContainerFactory";
502 true_builder->m_stat = m_stat;
503 true_builder->m_mpi_lock = m_mpi_lock;
517 if (local_rank < 0 || local_rank >= m_local_nb_rank)
520 Int32 current_global_rank = local_rank + m_local_nb_rank *
commRank();
522 app_tm->
info() <<
"Create SharedMemoryParallelMng rank=" << current_global_rank;
525 if (local_rank == 0) {
530 tm =
m_application->createAndInitializeTraceMng(app_tm, String::fromNumber(current_global_rank));
544 MPI_Abort(m_communicator, 2);
553 MPI_Barrier(m_communicator);
580class MpiSharedMemoryParallelSuperMng
581:
public SharedMemoryParallelSuperMng
588 Request::setNullRequest(
Request(0,
nullptr, MPI_REQUEST_NULL));
589 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
592 ~MpiSharedMemoryParallelSuperMng()
override
#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.
const CommandLineArguments & commandLineArguments() const
Command line arguments.
Exception when an argument is invalid.
virtual const ApplicationBuildInfo & applicationBuildInfo() const =0
Instance build parameter information.
virtual ITraceMng * traceMng() const =0
Trace manager.
Interface for an 'IParallelMng' container factory.
Abstract class of the parallelism supervisor.
Interface of a barrier between threads.
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.
virtual TraceMessage info()=0
Stream for an information message.
Communicator for message exchange.
Container of information for the hybrid mode message manager.
Int32 m_mpi_comm_size
Number of processors.
IThreadMng * m_thread_mng
Statistics.
IApplication * m_application
Main manager.
Int32 m_mpi_comm_rank
Current processor number.
MPI_Comm m_mpi_communicator
MPI Communicator.
Ref< IParallelMng > _createParallelMng(Int32 local_rank, ITraceMng *tm) override
Creates the IParallelMng for the local rank local_rank.
MPI_Comm m_mpi_machine_communicator
MPI Communicator.
Thread-based parallelism manager.
void build() override
Constructs the instance.
Supervisor of parallelism using MPI and Threads.
void tryAbort() override
Attempts to abort.
Int32 commRank() const override
Returns the process number (between 0 and nbProcess()-1).
MP::Communicator communicator() const override
MPI communicator associated with this manager.
Int32 m_mpi_comm_rank
Statistics.
void build() override
Constructs the instance members.
void * getMPICommunicator() override
Address of the MPI communicator associated with this manager.
IThreadMng * threadMng() const override
Thread manager.
IApplication * application() const override
Returns the main manager.
void barrier() override
Parallelism manager for all allocated resources.
Ref< IParallelMng > internalCreateWorldParallelMng(Int32 local_rank) override
Creates a parallelism manager for all allocated cores.
Integer masterIORank() const override
Rank of the instance managing input/output (for which isMasterIO() is true).
void initialize() override
Initializes the instance.
Int32 m_mpi_comm_size
Number of processors.
Integer nbLocalSubDomain() override
Number of subdomains to create locally.
bool isMasterIO() const override
Returns true if the instance is a master I/O manager.
Int32 commSize() const override
Returns the total number of processes used.
bool isParallel() const override
Returns true if the execution is parallel.
Int32 traceRank() const override
Rank of this instance for traces.
IApplication * m_application
Main manager.
Interface of a message queue with threads.
Shared memory supervisor with MPI initialization.
void build() override
Constructs the instance members.
void destroy()
Destroys the instance. It should no longer be used afterward.
void build() override
Constructs the instance members.
Manages the MPI_Datatypes associated with Arcane types.
Message interface for the Type.
Parallelism manager using MPI.
void build() override
Constructs the instance.
void initialize() override
Initializes the parallelism manager.
Statistics on parallelism.
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.
Unicode character string.
1D data vector with value semantics (STL style).
#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.
ARCANE_MPI_EXPORT void arcaneInitializeMPI(int *argc, char ***argv, int wanted_thread_level)
bool arcaneHasThread()
True if arcane is compiled with thread support AND they are active.
ARCANE_MPI_EXPORT bool arcaneIsCudaAwareMPI()
Indicates if the current MPI runtime supports CUDA.
Int32 Integer
Type representing an integer.
@ ST_Application
The service is used at the application level.
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)
Calls the function function and calls std::terminate() if an exception occurs.
double Real
Type representing a real number.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
ARCANE_MPI_EXPORT void arcaneFinalizeMPI()
std::int32_t Int32
Signed integer type of 32 bits.
Info for constructing a HybridParallelMng.
Info to construct an MpiParallelMng.