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/HybridMachineMemoryWindowBaseInternalCreator.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"
64class HybridParallelMngContainer
69 MP::Communicator mpi_comm, MP::Communicator mpi_machine_comm,
72 ~HybridParallelMngContainer()
override;
88 Int32 m_local_nb_rank = -1;
92 Mutex* m_internal_create_mutex =
nullptr;
105 void _setMPICommunicator();
111HybridParallelMngContainer::
113 MP::Communicator mpi_comm, MP::Communicator mpi_machine_comm,
119, m_mpi_lock(mpi_lock)
120, m_local_nb_rank(nb_local_rank)
122, m_sub_builder_factory(factory)
123, m_mpi_communicator(mpi_comm)
124, m_mpi_machine_communicator(mpi_machine_comm)
126 _setMPICommunicator();
132HybridParallelMngContainer::
133~HybridParallelMngContainer()
137 delete m_message_queue;
139 delete m_all_dispatchers;
140 delete m_parallel_mng_list;
141 delete m_internal_create_mutex;
142 delete m_window_creator;
148void HybridParallelMngContainer::
151 m_internal_create_mutex =
new Mutex();
153 m_all_dispatchers =
new MpiThreadAllDispatcher();
154 m_all_dispatchers->resize(m_local_nb_rank);
156 m_parallel_mng_list->resize(m_local_nb_rank);
157 m_parallel_mng_list->fill(
nullptr);
159 m_message_queue =
new SharedMemoryMessageQueue();
160 m_message_queue->init(m_local_nb_rank);
163 m_thread_barrier->
init(m_local_nb_rank);
165 m_window_creator =
new HybridMachineMemoryWindowBaseInternalCreator(m_local_nb_rank, m_thread_barrier);
171void HybridParallelMngContainer::
176 if (comm==MPI_COMM_NULL)
177 ARCANE_THROW(ArgumentException,
"Null MPI Communicator");
195 if (local_rank<0 || local_rank>=m_local_nb_rank)
197 local_rank,m_local_nb_rank);
203 bool is_parallel = nb_process > 1;
207 bi.is_parallel = is_parallel;
211 bi.is_mpi_comm_owned =
false;
212 bi.mpi_lock = m_mpi_lock;
215 tm->
info() <<
"MPI implementation need serialized threads : using locks";
221 mpi_pm->adapter()->enableDebugRequest(
false);
224 build_info.local_rank = local_rank;
225 build_info.local_nb_rank = m_local_nb_rank;
226 build_info.mpi_parallel_mng = mpi_pm;
227 build_info.trace_mng = tm;
229 build_info.message_queue = m_message_queue;
230 build_info.thread_barrier = m_thread_barrier;
231 build_info.parallel_mng_list = m_parallel_mng_list;
232 build_info.all_dispatchers = m_all_dispatchers;
233 build_info.sub_builder_factory = m_sub_builder_factory;
235 build_info.window_creator = m_window_creator;
240 (*m_parallel_mng_list)[local_rank] = pm;
251class HybridParallelMngContainerFactory
260 _createParallelMngBuilder(
Int32 nb_rank, MP::Communicator mpi_communicator,
261 MP::Communicator mpi_machine_communicator)
override
264 mpi_machine_communicator,
265 this,m_stat,m_mpi_lock);
291class HybridParallelSuperMng
292:
public ParallelSuperMngDispatcher
297 ~HybridParallelSuperMng()
override;
300 void build()
override;
309 MP::Communicator
communicator()
const override {
return m_communicator; }
327 MPI_Comm m_mpi_communicator;
328 MP::Communicator m_communicator;
329 MP::Communicator m_machine_communicator;
330 Int32 m_local_nb_rank = A_NULL_RANK;
340HybridParallelSuperMng::
342: m_application(sbi.application())
345, m_mpi_communicator(MPI_COMM_NULL)
346, m_local_nb_rank(A_NULL_RANK)
348, m_mpi_adapter(nullptr)
349, m_datatype_list(nullptr)
357HybridParallelSuperMng::
358~HybridParallelSuperMng()
360 m_error_handler.removeHandler();
362 delete m_datatype_list;
367 MPI_Barrier(m_mpi_communicator);
368 MPI_Comm_free(&m_mpi_communicator);
369 m_mpi_communicator = MPI_COMM_NULL;
370 MPI_Comm_free(
static_cast<MPI_Comm*
>(m_machine_communicator.communicatorAddress()));
389 ARCANE_FATAL(
"Can not create HybridParallelSuperMng because threads are disabled");
391 Request::setNullRequest(
Request(0,
nullptr,MPI_REQUEST_NULL));
392 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
396 char*** argv =
nullptr;
400 argc = cmd_line_args.commandLineArgc();
401 argv = cmd_line_args.commandLineArgv();
403 bool need_serialize =
false;
414 int thread_wanted = MPI_THREAD_MULTIPLE;
415 int thread_provided = 0;
420 MPI_Query_thread(&thread_provided);
422 if (thread_provided < MPI_THREAD_MULTIPLE) {
423 if (thread_provided>=MPI_THREAD_SERIALIZED)
424 need_serialize =
true;
429 MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
431 ARCANE_FATAL(
"MPI thread level provided!=wanted ({0}!={1})",
432 thread_provided,thread_wanted);
442 MPI_Comm_dup(MPI_COMM_WORLD,&m_mpi_communicator);
444 MPI_Comm_rank(m_mpi_communicator,&rank);
445 MPI_Comm_size(m_mpi_communicator,&size);
450 MPI_Comm mpi_machine_communicator = MPI_COMM_NULL;
451 MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED,
m_mpi_comm_rank, MPI_INFO_NULL, &mpi_machine_communicator);
452 m_machine_communicator =
Communicator(mpi_machine_communicator);
456 m_error_handler.registerHandler(m_mpi_communicator);
460 ARCANE_FATAL(
"Number of shared memory sub-domains is not defined");
465 tm->
info() <<
"MPI has non blocking collective";
466 tm->
info() <<
"MPI: sizeof(MPI_Count)=" <<
sizeof(MPI_Count);
468 tm->
info() <<
"MPI: init_time (seconds)=" << (end_time-start_time);
478 auto* adapter =
new MpiAdapter(tm,m_stat->toArccoreStat(),m_communicator,
nullptr);
479 m_mpi_adapter = adapter;
480 auto c = createBuiltInDispatcher<Byte>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
481 auto i32 = createBuiltInDispatcher<Int32>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
482 auto i64 = createBuiltInDispatcher<Int64>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
483 auto r = createBuiltInDispatcher<Real>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
484 _setDispatchers(c,i32,i64,r);
487 String service_name =
"HybridParallelMngContainerFactory";
491 true_builder->m_stat = m_stat;
492 true_builder->m_mpi_lock = m_mpi_lock;
506 if (local_rank<0 || local_rank>=m_local_nb_rank)
509 Int32 current_global_rank = local_rank + m_local_nb_rank *
commRank();
511 app_tm->
info() <<
"Create SharedMemoryParallelMng rank=" << current_global_rank;
519 tm =
m_application->createAndInitializeTraceMng(app_tm,String::fromNumber(current_global_rank));
533 MPI_Abort(m_communicator,2);
542 MPI_Barrier(m_communicator);
568class MpiSharedMemoryParallelSuperMng
569:
public SharedMemoryParallelSuperMng
575 Request::setNullRequest(
Request(0,
nullptr,MPI_REQUEST_NULL));
576 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
579 ~MpiSharedMemoryParallelSuperMng()
override
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
AbstractService(const ServiceBuildInfo &)
Constructeur à partir d'un ServiceBuildInfo.
Informations sur une application.
const CommandLineArguments & commandLineArguments() const
Arguments de la ligne de commande.
Exception lorsqu'un argument est invalide.
Arguments de la ligne de commande.
Interface de l'application.
virtual const ApplicationBuildInfo & applicationBuildInfo() const =0
Informations sur les paramètres de construction de l'instance.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
Interface d'une fabrique de conteneur de 'IParallelMng'.
Classe abstraite du superviseur de parallélisme.
Interface d'une barrière entre threads.
virtual void destroy()=0
Détruit la barrière.
virtual void init(Integer nb_thread)=0
Initialise la barrière pour nb_thread.
Interface d'un gestionnaire de thread.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Communicateur pour l'échange de message.
Conteneur des informations du gestionnaire de message en mode hybride.
Int32 m_mpi_comm_size
Nombre de processeurs.
IThreadMng * m_thread_mng
Statistiques.
IApplication * m_application
Gestionnaire principal.
Int32 m_mpi_comm_rank
Numéro du processeur actuel.
MPI_Comm m_mpi_communicator
Communicateur MPI.
Ref< IParallelMng > _createParallelMng(Int32 local_rank, ITraceMng *tm) override
Créé le IParallelMng pour le rang local local_rank.
MPI_Comm m_mpi_machine_communicator
Communicateur MPI.
Gestionnaire du parallélisme utilisant les threads.
void build() override
Construit l'instance.
Superviseur du parallélisme utilisant MPI et Threads.
void tryAbort() override
Tente de faire un abort.
Int32 commRank() const override
Retourne le numéro du process (compris entre 0 et nbProcess()-1)
MP::Communicator communicator() const override
Communicateur MPI associé à ce gestionnaire.
Int32 m_mpi_comm_rank
Statistiques.
void build() override
Construit les membres l'instance.
void * getMPICommunicator() override
Adresse du communicateur MPI associé à ce gestionnaire.
IThreadMng * threadMng() const override
Gestionnaire de thread.
IApplication * application() const override
Retourne le gestionnaire principal.
void barrier() override
Gestionnaire de parallèlisme pour l'ensemble des ressources allouées.
Ref< IParallelMng > internalCreateWorldParallelMng(Int32 local_rank) override
Créé un gestionnaire de parallélisme pour l'ensemble des coeurs alloués.
Integer masterIORank() const override
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai)
void initialize() override
Initialise l'instance.
Int32 m_mpi_comm_size
Nombre de processeurs.
Integer nbLocalSubDomain() override
Nombre de sous-domaines à créér localement.
bool isMasterIO() const override
true si l'instance est un gestionnaire maître des entrées/sorties.
Int32 commSize() const override
Retourne le nombre total de process utilisés.
bool isParallel() const override
Retourne true si l'exécution est parallèle.
Int32 traceRank() const override
Rang de cette instance pour les traces.
IApplication * m_application
Gestionnaire principal.
Interface d'une file de messages avec les threads.
Superviseur en mémoire partagé avec initialisation MPI.
void build() override
Construit les membres l'instance.
void destroy()
Détruit l'instance. Elle ne doit plus être utilisée par la suite.
Verrou pour les appels MPI.
void build() override
Construit les membres l'instance.
Gère les MPI_Datatype associées aux types Arcane.
Interface des messages pour le type Type.
Gestionnaire du parallélisme utilisant MPI.
void build() override
Construit l'instance.
void initialize() override
Initialise le gestionnaire du parallélisme.
Statistiques sur le parallélisme.
Référence à une instance.
InstanceType * get() const
Instance associée ou nullptr si aucune.
IApplication * application() const
Accès à l'application IApplication associé.
Structure contenant les informations pour créer un service.
Classe utilitaire pour instantier un service d'une interface donnée.
Ref< InterfaceType > createReference(const String &name, eServiceBuilderProperties properties=SB_None)
Créé une instance implémentant l'interface InterfaceType.
Propriétés de création d'un service.
Chaîne de caractères unicode.
Vecteur 1D de données avec sémantique par valeur (style STL).
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
Déclarations des types et méthodes utilisés par les mécanismes d'échange de messages.
IStat * createDefaultStat()
Créé une instance par défaut.
ARCANE_MPI_EXPORT void arcaneInitializeMPI(int *argc, char ***argv, int wanted_thread_level)
bool arcaneHasThread()
Vrai si arcane est compilé avec le support des threads ET qu'ils sont actifs.
ARCANE_MPI_EXPORT bool arcaneIsCudaAwareMPI()
Indique si le runtime actuel de MPI a le support de CUDA.
Int32 Integer
Type représentant un entier.
@ ST_Application
Le service s'utilise au niveau de l'application.
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)
double Real
Type représentant un réel.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
ARCANE_MPI_EXPORT void arcaneFinalizeMPI()
std::int32_t Int32
Type entier signé sur 32 bits.
Infos pour construire un HybridParallelMng.
Infos pour construire un MpiParallelMng.