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
71 ~HybridParallelMngContainer()
override;
87 Int32 m_local_nb_rank = -1;
91 Mutex* m_internal_create_mutex =
nullptr;
100 void _setMPICommunicator();
106HybridParallelMngContainer::
113, m_mpi_lock(mpi_lock)
114, m_local_nb_rank(nb_local_rank)
116, m_sub_builder_factory(factory)
117, m_mpi_communicator(mpi_comm)
119 _setMPICommunicator();
125HybridParallelMngContainer::
126~HybridParallelMngContainer()
130 delete m_message_queue;
132 delete m_all_dispatchers;
133 delete m_parallel_mng_list;
134 delete m_internal_create_mutex;
135 delete m_window_creator;
141void HybridParallelMngContainer::
144 m_internal_create_mutex =
new Mutex();
146 m_all_dispatchers =
new MpiThreadAllDispatcher();
147 m_all_dispatchers->resize(m_local_nb_rank);
149 m_parallel_mng_list->resize(m_local_nb_rank);
150 m_parallel_mng_list->fill(
nullptr);
152 m_message_queue =
new SharedMemoryMessageQueue();
153 m_message_queue->init(m_local_nb_rank);
156 m_thread_barrier->
init(m_local_nb_rank);
158 m_window_creator =
new HybridMachineMemoryWindowBaseInternalCreator(m_local_nb_rank, m_thread_barrier);
164void HybridParallelMngContainer::
169 if (comm==MPI_COMM_NULL)
170 ARCANE_THROW(ArgumentException,
"Null MPI Communicator");
188 if (local_rank<0 || local_rank>=m_local_nb_rank)
190 local_rank,m_local_nb_rank);
196 bool is_parallel = nb_process > 1;
200 bi.is_parallel = is_parallel;
204 bi.is_mpi_comm_owned =
false;
205 bi.mpi_lock = m_mpi_lock;
208 tm->
info() <<
"MPI implementation need serialized threads : using locks";
214 mpi_pm->adapter()->enableDebugRequest(
false);
217 build_info.local_rank = local_rank;
218 build_info.local_nb_rank = m_local_nb_rank;
219 build_info.mpi_parallel_mng = mpi_pm;
220 build_info.trace_mng = tm;
222 build_info.message_queue = m_message_queue;
223 build_info.thread_barrier = m_thread_barrier;
224 build_info.parallel_mng_list = m_parallel_mng_list;
225 build_info.all_dispatchers = m_all_dispatchers;
226 build_info.sub_builder_factory = m_sub_builder_factory;
228 build_info.window_creator = m_window_creator;
233 (*m_parallel_mng_list)[local_rank] = pm;
244class HybridParallelMngContainerFactory
253 _createParallelMngBuilder(
Int32 nb_rank,MP::Communicator mpi_communicator)
override
256 this,m_stat,m_mpi_lock);
282class HybridParallelSuperMng
283:
public ParallelSuperMngDispatcher
288 ~HybridParallelSuperMng()
override;
291 void build()
override;
300 MP::Communicator
communicator()
const override {
return m_communicator; }
320 MPI_Comm m_mpi_communicator;
321 MP::Communicator m_communicator;
322 Int32 m_local_nb_rank = A_NULL_RANK;
332HybridParallelSuperMng::
334: m_application(sbi.application())
337, m_mpi_communicator(MPI_COMM_NULL)
338, m_local_nb_rank(A_NULL_RANK)
340, m_mpi_adapter(nullptr)
341, m_datatype_list(nullptr)
349HybridParallelSuperMng::
350~HybridParallelSuperMng()
352 m_error_handler.removeHandler();
354 delete m_datatype_list;
359 MPI_Barrier(m_mpi_communicator);
360 MPI_Comm_free(&m_mpi_communicator);
361 m_mpi_communicator = MPI_COMM_NULL;
380 ARCANE_FATAL(
"Can not create HybridParallelSuperMng because threads are disabled");
382 Request::setNullRequest(
Request(0,
nullptr,MPI_REQUEST_NULL));
383 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
387 char*** argv =
nullptr;
391 argc = cmd_line_args.commandLineArgc();
392 argv = cmd_line_args.commandLineArgv();
394 bool need_serialize =
false;
405 int thread_wanted = MPI_THREAD_MULTIPLE;
406 int thread_provided = 0;
411 MPI_Query_thread(&thread_provided);
413 if (thread_provided < MPI_THREAD_MULTIPLE) {
414 if (thread_provided>=MPI_THREAD_SERIALIZED)
415 need_serialize =
true;
420 MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
422 ARCANE_FATAL(
"MPI thread level provided!=wanted ({0}!={1})",
423 thread_provided,thread_wanted);
433 MPI_Comm_dup(MPI_COMM_WORLD,&m_mpi_communicator);
435 MPI_Comm_rank(m_mpi_communicator,&rank);
436 MPI_Comm_size(m_mpi_communicator,&size);
442 m_error_handler.registerHandler(m_mpi_communicator);
446 ARCANE_FATAL(
"Number of shared memory sub-domains is not defined");
451 tm->
info() <<
"MPI has non blocking collective";
452 tm->
info() <<
"MPI: sizeof(MPI_Count)=" <<
sizeof(MPI_Count);
454 tm->
info() <<
"MPI: init_time (seconds)=" << (end_time-start_time);
464 auto* adapter =
new MpiAdapter(tm,m_stat->toArccoreStat(),m_communicator,
nullptr);
465 m_mpi_adapter = adapter;
466 auto c = createBuiltInDispatcher<Byte>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
467 auto i32 = createBuiltInDispatcher<Int32>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
468 auto i64 = createBuiltInDispatcher<Int64>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
469 auto r = createBuiltInDispatcher<Real>(tm,
nullptr,m_mpi_adapter,m_datatype_list);
470 _setDispatchers(c,i32,i64,r);
473 String service_name =
"HybridParallelMngContainerFactory";
477 true_builder->m_stat = m_stat;
478 true_builder->m_mpi_lock = m_mpi_lock;
492 if (local_rank<0 || local_rank>=m_local_nb_rank)
495 Int32 current_global_rank = local_rank + m_local_nb_rank *
commRank();
497 app_tm->
info() <<
"Create SharedMemoryParallelMng rank=" << current_global_rank;
505 tm =
m_application->createAndInitializeTraceMng(app_tm,String::fromNumber(current_global_rank));
519 MPI_Abort(m_communicator,2);
528 MPI_Barrier(m_communicator);
554class MpiSharedMemoryParallelSuperMng
555:
public SharedMemoryParallelSuperMng
561 Request::setNullRequest(
Request(0,
nullptr,MPI_REQUEST_NULL));
562 Communicator::setNullCommunicator(
Communicator(MPI_COMM_NULL));
565 ~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.