Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MpiParallelSuperMng.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* MpiParallelSuperMng.cc (C) 2000-2024 */
9/* */
10/* Gestionnaire de parallélisme utilisant MPI. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ApplicationInfo.h"
15#include "arcane/utils/NullThreadMng.h"
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/ValueConvert.h"
19#include "arcane/utils/NotImplementedException.h"
20#include "arcane/utils/ArgumentException.h"
21#include "arcane/utils/FatalErrorException.h"
22#include "arcane/utils/CommandLineArguments.h"
23
24#include "arcane/parallel/IStat.h"
25
26#include "arcane/parallel/mpi/MpiAdapter.h"
27#include "arcane/parallel/mpi/MpiParallelMng.h"
28#include "arcane/parallel/mpi/MpiParallelDispatch.h"
29#include "arcane/parallel/mpi/MpiErrorHandler.h"
30
31#include "arcane/FactoryService.h"
32#include "arcane/IApplication.h"
33#include "arcane/ParallelSuperMngDispatcher.h"
34
35#include "arcane/impl/SequentialParallelSuperMng.h"
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40namespace Arcane
41{
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
50{
51 public:
52
54 ~MpiParallelSuperMng() override;
55
56 void initialize() override;
57 void build() override;
58
59 IApplication* application() const override { return m_application; }
60 IThreadMng* threadMng() const override { return m_thread_mng; }
61 bool isParallel() const override { return m_is_parallel; }
62 Int32 commRank() const override { return m_rank; }
63 Int32 commSize() const override { return m_nb_rank; }
64 Int32 traceRank() const override { return m_rank; }
65 void* getMPICommunicator() override { return &m_mpi_main_communicator; }
67 Ref<IParallelMng> internalCreateWorldParallelMng(Int32 local_rank) override;
68 void tryAbort() override;
69 bool isMasterIO() const override { return commRank()==0; }
70 Integer masterIORank() const override { return 0; }
71 Integer nbLocalSubDomain() override { return m_nb_local_sub_domain; }
72 void barrier() override;
73
74 public:
75
76 static void initMPI(IApplication* app);
77
78 public:
79
81 IThreadMng* m_thread_mng;
82 Parallel::IStat* m_stat;
84 Int32 m_rank;
85 Int32 m_nb_rank;
89 MpiErrorHandler m_error_handler;
90 MpiAdapter* m_adapter;
91 MpiDatatypeList* m_datatype_list;
92
93 private:
94
95 // Handler d'erreur
96 static void _ErrorHandler(MPI_Comm *, int *, ...);
97};
98
99/*---------------------------------------------------------------------------*/
100/*---------------------------------------------------------------------------*/
101
102MpiParallelSuperMng::
103MpiParallelSuperMng(const ServiceBuildInfo& sbi)
104: m_application(sbi.application())
105, m_thread_mng(nullptr)
106, m_stat(nullptr)
107, m_is_parallel(false)
108, m_rank(0)
109, m_nb_rank(0)
110, m_nb_local_sub_domain(1)
111, m_mpi_main_communicator(MPI_COMM_NULL)
112, m_main_communicator(MPI_COMM_NULL)
113, m_adapter(nullptr)
114, m_datatype_list(nullptr)
115{
116 m_thread_mng = new NullThreadMng();
118}
119
120/*---------------------------------------------------------------------------*/
121/*---------------------------------------------------------------------------*/
122
123MpiParallelSuperMng::
124~MpiParallelSuperMng()
125{
126 _finalize();
127
128 try{
129 delete m_datatype_list;
130 if (m_adapter)
131 m_adapter->destroy();
132 delete m_stat;
133 delete m_thread_mng;
134 }
135 catch(const Exception& ex){
136 m_application->traceMng()->error() << ex;
137 }
138
139 MPI_Barrier(m_mpi_main_communicator);
140 m_error_handler.removeHandler();
141
142 MPI_Comm_free(&m_mpi_main_communicator);
143 m_mpi_main_communicator = MPI_COMM_NULL;
144
146}
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
155
156/*---------------------------------------------------------------------------*/
157/*---------------------------------------------------------------------------*/
158
159void MpiParallelSuperMng::
160initMPI(IApplication* app)
161{
162 int* argc = nullptr;
163 char*** argv = nullptr;
164
165 Request::setNullRequest(Request(0,nullptr,MPI_REQUEST_NULL));
166 Communicator::setNullCommunicator(Communicator(MPI_COMM_NULL));
167
168 const CommandLineArguments& app_args = app->applicationInfo().commandLineArguments();
169 argc = app_args.commandLineArgc();
170 argv = app_args.commandLineArgv();
171
172 // TODO:
173 // Pouvoir utiliser un autre communicateur que MPI_COMM_WORLD
175 int thread_provided = 0;
177
178#ifndef ARCANE_USE_MPC
179 // MPC (v 2.4.1) ne connait pas cette fonction
181#else
183#endif
184
186 int my_rank = 0;
187 // Affiche un message mais seulement un seul processeur.
189 if (my_rank==0)
190 app->traceMng()->info() << "WARNING: MPI thread level provided!=wanted ("
191 << thread_provided << "!=" << thread_wanted << ")";
192 }
193}
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
197
198void MpiParallelSuperMng::
199_ErrorHandler(MPI_Comm* comm, int* error_code, ...)
200{
201 ARCANE_UNUSED(comm);
202
203 char error_buf[MPI_MAX_ERROR_STRING+1];
204 int error_len = 0;
205 int e = *error_code;
206 // int MPI_Error_string(int errorcode, char *string, int *resultlen);
207 MPI_Error_string(e,error_buf,&error_len);
208 error_buf[error_len] = '\0';
209 error_buf[MPI_MAX_ERROR_STRING] = '\0';
210
211 // int MPI_Error_class(int errorcode, int *errorclass);
212
213 ARCANE_FATAL("Error in MPI call code={0} msg={1}",*error_code,error_buf);
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
220build()
221{
223
224 // TODO: Regarder s'il faut faire une réduction sur tous les temps.
225 Real start_time = platform::getRealTime();
226 initMPI(m_application);
227 Real end_time = platform::getRealTime();
228
231 int rank, size;
234
235#ifndef ARCANE_USE_MPC
236 m_error_handler.registerHandler(m_main_communicator);
237#endif
238
239 if (rank==0){
240 tm->info() << "MPI has non blocking collective";
241 tm->info() << "MPI: sizeof(MPI_Count)=" << sizeof(MPI_Count);
242 tm->info() << "MPI: is GPU Aware?=" << arcaneIsAcceleratorAwareMPI();
243 tm->info() << "MPI: init_time (seconds)=" << (end_time-start_time);
244 }
245
246 m_rank = rank;
247 m_nb_rank = size;
248 m_is_parallel = true;
249 auto astat = m_stat->toArccoreStat();
250 m_datatype_list = new MpiDatatypeList(false);
251 m_adapter = new MpiAdapter(tm,astat,m_main_communicator,nullptr);
252 auto c = createBuiltInDispatcher<Byte>(tm,nullptr,m_adapter,m_datatype_list);
253 auto i32 = createBuiltInDispatcher<Int32>(tm,nullptr,m_adapter,m_datatype_list);
254 auto i64 = createBuiltInDispatcher<Int64>(tm,nullptr,m_adapter,m_datatype_list);
255 auto r = createBuiltInDispatcher<Real>(tm,nullptr,m_adapter,m_datatype_list);
256 _setDispatchers(c,i32,i64,r);
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
263internalCreateWorldParallelMng(Int32 local_rank)
264{
266 tm->debug()<<"[MpiParallelSuperMng::internalCreateWorldParallelMng]";
267 if (local_rank!=0)
268 ARCANE_THROW(ArgumentException,"local_rank has to be '0'");
269
272
273 int rank = -1;
274 int nb_rank = -1;
275 MPI_Comm_rank(comm,&rank);
276 MPI_Comm_size(comm,&nb_rank);
277
278 bool is_parallel = nb_rank > 1;
279
281 bi.is_parallel = is_parallel;
282 bi.stat = m_stat;
283 bi.trace_mng = tm;
284 bi.timer_mng = nullptr;
285 bi.thread_mng = m_thread_mng;
286 bi.mpi_lock = nullptr;
287
288 tm->debug()<<"[MpiParallelSuperMng::internalCreateWorldParallelMng] pm->build()";
290 pm->build();
291 return pm;
292}
293
294/*---------------------------------------------------------------------------*/
295/*---------------------------------------------------------------------------*/
296
298tryAbort()
299{
300 m_application->traceMng()->info() << "MpiParallelSuperMng: rank " << m_rank << " calling MPI_Abort";
301 m_application->traceMng()->flush();
303}
304
305/*---------------------------------------------------------------------------*/
306/*---------------------------------------------------------------------------*/
307
313
314/*---------------------------------------------------------------------------*/
315/*---------------------------------------------------------------------------*/
323{
324 public:
327 {
328 }
329
331 {
333 }
334
335 void build() override
336 {
337 MpiParallelSuperMng::initMPI(application());
339 }
340};
341
342/*---------------------------------------------------------------------------*/
343/*---------------------------------------------------------------------------*/
344
345ARCANE_REGISTER_SERVICE(MpiParallelSuperMng,
346 ServiceProperty("MpiParallelSuperMng",ST_Application),
347 ARCANE_SERVICE_INTERFACE(IParallelSuperMng));
348
349/*---------------------------------------------------------------------------*/
350/*---------------------------------------------------------------------------*/
351
352ARCANE_REGISTER_SERVICE(MpiSequentialParallelSuperMng,
353 ServiceProperty("MpiSequentialParallelSuperMng",ST_Application),
354 ARCANE_SERVICE_INTERFACE(IParallelSuperMng));
355
356/*---------------------------------------------------------------------------*/
357/*---------------------------------------------------------------------------*/
358
359} // End namespace Arcane
360
361/*---------------------------------------------------------------------------*/
362/*---------------------------------------------------------------------------*/
#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.
Arguments de la ligne de commande.
Interface de l'application.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual void build()=0
Construit l'instance.
Interface d'un gestionnaire de thread.
Definition IThreadMng.h:30
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Gère les MPI_Datatype associées aux types Arcane.
Interface des messages pour le type Type.
Superviseur du parallélisme utilisant MPI.
bool isParallel() const override
Retourne true si l'exécution est parallèle.
void initialize() override
Initialise l'instance.
Int32 m_rank
Rang MPI dans le communicateur global de ce processus.
Int32 m_nb_local_sub_domain
Nombre de sous-domaines locaux.
Int32 commSize() const override
Retourne le nombre total de process utilisés.
Integer nbLocalSubDomain() override
Nombre de sous-domaines à créér localement.
IThreadMng * threadMng() const override
Gestionnaire de thread.
Int32 commRank() const override
Retourne le numéro du process (compris entre 0 et nbProcess()-1)
Integer masterIORank() const override
Rang de l'instance gérant les entrées/sorties (pour laquelle isMasterIO() est vrai)
void barrier() override
Gestionnaire de parallèlisme pour l'ensemble des ressources allouées.
MP::Communicator m_main_communicator
Communicateur MPI.
MPI_Comm m_mpi_main_communicator
Communicateur MPI.
Ref< IParallelMng > internalCreateWorldParallelMng(Int32 local_rank) override
Créé un gestionnaire de parallélisme pour l'ensemble des coeurs alloués.
Int32 traceRank() const override
Rang de cette instance pour les traces.
bool isMasterIO() const override
true si l'instance est un gestionnaire maître des entrées/sorties.
IApplication * application() const override
Retourne le gestionnaire principal.
Int32 m_nb_rank
Nombre de processus MPI dans le communicateur global.
void tryAbort() override
Tente de faire un abort.
void build() override
Construit les membres l'instance.
void * getMPICommunicator() override
Adresse du communicateur MPI associé à ce gestionnaire.
Parallel::Communicator communicator() const override
Communicateur MPI associé à ce gestionnaire.
IApplication * m_application
Gestionnaire principal.
Superviseur en mode MPI avec un seul process alloué pour se comporter comme en séqentiel mais avec un...
void build() override
Construction de niveau build du service.
Gestionnaire de thread en mode mono-thread.
Redirige la gestion des messages des sous-domaines suivant le type de l'argument.
Statistiques sur le parallélisme.
Superviseur du parallélisme en mode séquentiel.
void build() override
Construction de niveau build du service.
IApplication * application() const override
Retourne le gestionnaire principal.
Structure contenant les informations pour créer un service.
Exception lorsqu'un argument est invalide.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Communicateur pour l'échange de message.
void destroy()
Détruit l'instance. Elle ne doit plus être utilisée par la suite.
Requête d'un message.
Definition Request.h:77
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
IStat * createDefaultStat()
Créé une instance par défaut.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
ARCANE_MPI_EXPORT void arcaneInitializeMPI(int *argc, char ***argv, int wanted_thread_level)
Definition ArcaneMpi.cc:202
ARCANE_MPI_EXPORT bool arcaneIsAcceleratorAwareMPI()
Indique si le runtime actuel de MPI a le support des accélérateurs.
Definition ArcaneMpi.cc:75
@ ST_Application
Le service s'utilise au niveau de l'application.
ARCANE_MPI_EXPORT void arcaneFinalizeMPI()
Definition ArcaneMpi.cc:208
Infos pour construire un MpiParallelMng.