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"
41#include "arcane/core/FactoryService.h"
42#include "arcane/core/AbstractService.h"
43#include "arcane/core/IApplication.h"
44#include "arcane/core/ParallelSuperMngDispatcher.h"
45#include "arcane/core/ApplicationBuildInfo.h"
46#include "arcane/core/ServiceBuilder.h"
48#include "arcane/core/IMainFactory.h"
63class HybridParallelMngContainer
70 ~HybridParallelMngContainer()
override;
86 Int32 m_local_nb_rank = -1;
90 Mutex* m_internal_create_mutex =
nullptr;
97 void _setMPICommunicator();
103HybridParallelMngContainer::
110, m_mpi_lock(mpi_lock)
111, m_local_nb_rank(nb_local_rank)
113, m_sub_builder_factory(factory)
114, m_mpi_communicator(mpi_comm)
116 _setMPICommunicator();
122HybridParallelMngContainer::
123~HybridParallelMngContainer()
127 delete m_message_queue;
129 delete m_all_dispatchers;
130 delete m_parallel_mng_list;
131 delete m_internal_create_mutex;
137void HybridParallelMngContainer::
140 m_internal_create_mutex =
new Mutex();
142 m_all_dispatchers =
new MpiThreadAllDispatcher();
143 m_all_dispatchers->resize(m_local_nb_rank);
145 m_parallel_mng_list->resize(m_local_nb_rank);
146 m_parallel_mng_list->fill(
nullptr);
148 m_message_queue =
new SharedMemoryMessageQueue();
149 m_message_queue->init(m_local_nb_rank);
152 m_thread_barrier->
init(m_local_nb_rank);
158void HybridParallelMngContainer::
163 if (comm==MPI_COMM_NULL)
164 ARCANE_THROW(ArgumentException,
"Null MPI Communicator");
182 if (local_rank<0 || local_rank>=m_local_nb_rank)
184 local_rank,m_local_nb_rank);
190 bool is_parallel = nb_process > 1;
194 bi.is_parallel = is_parallel;
198 bi.is_mpi_comm_owned =
false;
199 bi.mpi_lock = m_mpi_lock;
202 tm->
info() <<
"MPI implementation need serialized threads : using locks";
208 mpi_pm->adapter()->enableDebugRequest(
false);
211 build_info.local_rank = local_rank;
212 build_info.local_nb_rank = m_local_nb_rank;
213 build_info.mpi_parallel_mng = mpi_pm;
214 build_info.trace_mng = tm;
216 build_info.message_queue = m_message_queue;
217 build_info.thread_barrier = m_thread_barrier;
218 build_info.parallel_mng_list = m_parallel_mng_list;
219 build_info.all_dispatchers = m_all_dispatchers;
220 build_info.sub_builder_factory = m_sub_builder_factory;
226 (*m_parallel_mng_list)[local_rank] = pm;
237class HybridParallelMngContainerFactory
246 _createParallelMngBuilder(
Int32 nb_rank,MP::Communicator mpi_communicator)
override
249 this,m_stat,m_mpi_lock);
275class HybridParallelSuperMng
276:
public ParallelSuperMngDispatcher
281 ~HybridParallelSuperMng()
override;
284 void build()
override;
293 MP::Communicator
communicator()
const override {
return m_communicator; }
313 MPI_Comm m_mpi_communicator;
314 MP::Communicator m_communicator;
315 Int32 m_local_nb_rank = A_NULL_RANK;
325HybridParallelSuperMng::
327: m_application(sbi.application())
330, m_mpi_communicator(MPI_COMM_NULL)
331, m_local_nb_rank(A_NULL_RANK)
333, m_mpi_adapter(nullptr)
334, m_datatype_list(nullptr)
342HybridParallelSuperMng::
343~HybridParallelSuperMng()
345 m_error_handler.removeHandler();
347 delete m_datatype_list;
352 MPI_Barrier(m_mpi_communicator);
353 MPI_Comm_free(&m_mpi_communicator);
354 m_mpi_communicator = MPI_COMM_NULL;
373 ARCANE_FATAL(
"Can not create HybridParallelSuperMng because threads are disabled");
375 Request::setNullRequest(
Request(0,
nullptr,MPI_REQUEST_NULL));
376 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
380 char*** argv =
nullptr;
384 argc = cmd_line_args.commandLineArgc();
385 argv = cmd_line_args.commandLineArgv();
387 bool need_serialize =
false;
398 int thread_wanted = MPI_THREAD_MULTIPLE;
399 int thread_provided = 0;
404 MPI_Query_thread(&thread_provided);
406 if (thread_provided < MPI_THREAD_MULTIPLE) {
407 if (thread_provided>=MPI_THREAD_SERIALIZED)
408 need_serialize =
true;
413 MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
415 ARCANE_FATAL(
"MPI thread level provided!=wanted ({0}!={1})",
416 thread_provided,thread_wanted);
426 MPI_Comm_dup(MPI_COMM_WORLD,&m_mpi_communicator);
428 MPI_Comm_rank(m_mpi_communicator,&rank);
429 MPI_Comm_size(m_mpi_communicator,&size);
435 m_error_handler.registerHandler(m_mpi_communicator);
439 ARCANE_FATAL(
"Number of shared memory sub-domains is not defined");
444 tm->
info() <<
"MPI has non blocking collective";
445 tm->
info() <<
"MPI: sizeof(MPI_Count)=" <<
sizeof(MPI_Count);
447 tm->
info() <<
"MPI: init_time (seconds)=" << (end_time-start_time);
457 auto* adapter =
new MpiAdapter(tm,m_stat->toArccoreStat(),m_communicator,
nullptr);
458 m_mpi_adapter = adapter;
459 auto c = createBuiltInDispatcher<Byte>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
460 auto i32 = createBuiltInDispatcher<Int32>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
461 auto i64 = createBuiltInDispatcher<Int64>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
462 auto r = createBuiltInDispatcher<Real>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
463 _setDispatchers(c,i32,i64,r);
466 String service_name =
"HybridParallelMngContainerFactory";
470 true_builder->m_stat = m_stat;
471 true_builder->m_mpi_lock = m_mpi_lock;
485 if (local_rank<0 || local_rank>=m_local_nb_rank)
488 Int32 current_global_rank = local_rank + m_local_nb_rank *
commRank();
490 app_tm->
info() <<
"Create SharedMemoryParallelMng rank=" << current_global_rank;
498 tm =
m_application->createAndInitializeTraceMng(app_tm,String::fromNumber(current_global_rank));
512 MPI_Abort(m_communicator,2);
521 MPI_Barrier(m_communicator);
547class MpiSharedMemoryParallelSuperMng
548:
public SharedMemoryParallelSuperMng
554 Request::setNullRequest(
Request(0,
nullptr,MPI_REQUEST_NULL));
555 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
558 ~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.
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.