Arcane  v4.1.1.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-2025 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-2025 */
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 "arccore/message_passing_mpi/internal/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/*---------------------------------------------------------------------------*/
48class MpiParallelSuperMng
49: public ParallelSuperMngDispatcher
50{
51 public:
52
53 explicit MpiParallelSuperMng(const ServiceBuildInfo& sbi);
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; }
68 void tryAbort() override;
69 bool isMasterIO() const override { return commRank()==0; }
70 Integer masterIORank() const override { return 0; }
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;
88 MP::Communicator m_main_communicator;
89 MP::Communicator m_machine_communicator;
90 MpiErrorHandler m_error_handler;
91 MpiAdapter* m_adapter;
92 MpiDatatypeList* m_datatype_list;
93
94 private:
95
96 // Handler d'erreur
97 static void _ErrorHandler(MPI_Comm *, int *, ...);
98};
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102
103MpiParallelSuperMng::
104MpiParallelSuperMng(const ServiceBuildInfo& sbi)
105: m_application(sbi.application())
106, m_thread_mng(nullptr)
107, m_stat(nullptr)
108, m_is_parallel(false)
109, m_rank(0)
110, m_nb_rank(0)
111, m_nb_local_sub_domain(1)
112, m_mpi_main_communicator(MPI_COMM_NULL)
113, m_main_communicator(MPI_COMM_NULL)
114, m_machine_communicator(MPI_COMM_NULL)
115, m_adapter(nullptr)
116, m_datatype_list(nullptr)
117{
118 m_thread_mng = new NullThreadMng();
120}
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
124
125MpiParallelSuperMng::
126~MpiParallelSuperMng()
127{
128 _finalize();
129
130 try{
131 delete m_datatype_list;
132 if (m_adapter)
133 m_adapter->destroy();
134 delete m_stat;
135 delete m_thread_mng;
136 }
137 catch(const Exception& ex){
138 m_application->traceMng()->error() << ex;
139 }
140
141 MPI_Barrier(m_mpi_main_communicator);
142 m_error_handler.removeHandler();
143
144 MPI_Comm_free(&m_mpi_main_communicator);
145 m_mpi_main_communicator = MPI_COMM_NULL;
146
147 MPI_Comm_free(static_cast<MPI_Comm*>(m_machine_communicator.communicatorAddress()));
148
150}
151
152/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
154
159
160/*---------------------------------------------------------------------------*/
161/*---------------------------------------------------------------------------*/
162
163void MpiParallelSuperMng::
164initMPI(IApplication* app)
165{
166 int* argc = nullptr;
167 char*** argv = nullptr;
168
169 Request::setNullRequest(Request(0,nullptr,MPI_REQUEST_NULL));
170 Communicator::setNullCommunicator(Communicator(MPI_COMM_NULL));
171
173 argc = app_args.commandLineArgc();
174 argv = app_args.commandLineArgv();
175
176 // TODO:
177 // Pouvoir utiliser un autre communicateur que MPI_COMM_WORLD
178 int thread_wanted = MPI_THREAD_SERIALIZED;
179 int thread_provided = 0;
180 arcaneInitializeMPI(argc,argv,thread_wanted);
181
182#ifndef ARCANE_USE_MPC
183 // MPC (v 2.4.1) ne connait pas cette fonction
184 MPI_Query_thread(&thread_provided);
185#else
186 thread_provided = MPI_THREAD_MULTIPLE;
187#endif
188
189 if (thread_provided < thread_wanted) {
190 int my_rank = 0;
191 // Affiche un message mais seulement un seul processeur.
192 MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
193 if (my_rank==0)
194 app->traceMng()->info() << "WARNING: MPI thread level provided!=wanted ("
195 << thread_provided << "!=" << thread_wanted << ")";
196 }
197}
198
199/*---------------------------------------------------------------------------*/
200/*---------------------------------------------------------------------------*/
201
202void MpiParallelSuperMng::
203_ErrorHandler(MPI_Comm* comm, int* error_code, ...)
204{
205 ARCANE_UNUSED(comm);
206
207 char error_buf[MPI_MAX_ERROR_STRING+1];
208 int error_len = 0;
209 int e = *error_code;
210 // int MPI_Error_string(int errorcode, char *string, int *resultlen);
211 MPI_Error_string(e,error_buf,&error_len);
212 error_buf[error_len] = '\0';
213 error_buf[MPI_MAX_ERROR_STRING] = '\0';
214
215 // int MPI_Error_class(int errorcode, int *errorclass);
216
217 ARCANE_FATAL("Error in MPI call code={0} msg={1}",*error_code,error_buf);
218}
219
220/*---------------------------------------------------------------------------*/
221/*---------------------------------------------------------------------------*/
222
224build()
225{
226 ITraceMng* tm = m_application->traceMng();
227
228 // TODO: Regarder s'il faut faire une réduction sur tous les temps.
229 Real start_time = platform::getRealTime();
230 initMPI(m_application);
231 Real end_time = platform::getRealTime();
232
233 MPI_Comm_dup(MPI_COMM_WORLD,&m_mpi_main_communicator);
235 int rank, size;
236 MPI_Comm_rank(m_mpi_main_communicator,&rank);
237 MPI_Comm_size(m_mpi_main_communicator,&size);
238
239 MPI_Comm mpi_machine_communicator = MPI_COMM_NULL;
240 MPI_Comm_split_type(MPI_COMM_WORLD, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &mpi_machine_communicator);
241
242 m_machine_communicator = MP::Communicator(mpi_machine_communicator);
243
244#ifndef ARCANE_USE_MPC
245 m_error_handler.registerHandler(m_main_communicator);
246#endif
247
248 if (rank==0){
249 tm->info() << "MPI has non blocking collective";
250 tm->info() << "MPI: sizeof(MPI_Count)=" << sizeof(MPI_Count);
251 tm->info() << "MPI: is GPU Aware?=" << arcaneIsAcceleratorAwareMPI();
252 tm->info() << "MPI: init_time (seconds)=" << (end_time-start_time);
253 }
254
255 m_rank = rank;
256 m_nb_rank = size;
257 m_is_parallel = true;
258 auto astat = m_stat->toArccoreStat();
259 m_datatype_list = new MpiDatatypeList(false);
260 m_adapter = new MpiAdapter(tm,astat,m_main_communicator,nullptr);
261 auto c = createBuiltInDispatcher<Byte>(tm,nullptr,m_adapter,m_datatype_list);
262 auto i32 = createBuiltInDispatcher<Int32>(tm,nullptr,m_adapter,m_datatype_list);
263 auto i64 = createBuiltInDispatcher<Int64>(tm,nullptr,m_adapter,m_datatype_list);
264 auto r = createBuiltInDispatcher<Real>(tm,nullptr,m_adapter,m_datatype_list);
265 _setDispatchers(c,i32,i64,r);
266}
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
273{
274 ITraceMng* tm = m_application->traceMng();
275 tm->debug()<<"[MpiParallelSuperMng::internalCreateWorldParallelMng]";
276 if (local_rank!=0)
277 ARCANE_THROW(ArgumentException,"local_rank has to be '0'");
278
279 MPI_Comm comm = MPI_COMM_NULL;
280 MPI_Comm_dup(m_main_communicator,&comm);
281
282 MPI_Comm machine_comm = MPI_COMM_NULL;
283 MPI_Comm_dup(m_machine_communicator, &machine_comm);
284
285 int rank = -1;
286 int nb_rank = -1;
287 MPI_Comm_rank(comm,&rank);
288 MPI_Comm_size(comm,&nb_rank);
289
290 bool is_parallel = nb_rank > 1;
291
292 MpiParallelMngBuildInfo bi(comm, machine_comm);
293 bi.is_parallel = is_parallel;
294 bi.stat = m_stat;
295 bi.trace_mng = tm;
296 bi.timer_mng = nullptr;
297 bi.thread_mng = m_thread_mng;
298 bi.mpi_lock = nullptr;
299
300 tm->debug()<<"[MpiParallelSuperMng::internalCreateWorldParallelMng] pm->build()";
302 pm->build();
303 return pm;
304}
305
306/*---------------------------------------------------------------------------*/
307/*---------------------------------------------------------------------------*/
308
310tryAbort()
311{
312 m_application->traceMng()->info() << "MpiParallelSuperMng: rank " << m_rank << " calling MPI_Abort";
313 m_application->traceMng()->flush();
314 MPI_Abort(m_main_communicator,2);
315}
316
317/*---------------------------------------------------------------------------*/
318/*---------------------------------------------------------------------------*/
319
321barrier()
322{
323 MPI_Barrier(m_main_communicator);
324}
325
326/*---------------------------------------------------------------------------*/
327/*---------------------------------------------------------------------------*/
333class MpiSequentialParallelSuperMng
334: public SequentialParallelSuperMng
335{
336 public:
337 explicit MpiSequentialParallelSuperMng(const ServiceBuildInfo& sbi)
338 : SequentialParallelSuperMng(sbi,Parallel::Communicator(MPI_COMM_WORLD))
339 {
340 }
341
342 ~MpiSequentialParallelSuperMng() override
343 {
345 }
346
347 void build() override
348 {
349 MpiParallelSuperMng::initMPI(application());
351 }
352};
353
354/*---------------------------------------------------------------------------*/
355/*---------------------------------------------------------------------------*/
356
357ARCANE_REGISTER_SERVICE(MpiParallelSuperMng,
358 ServiceProperty("MpiParallelSuperMng",ST_Application),
359 ARCANE_SERVICE_INTERFACE(IParallelSuperMng));
360
361/*---------------------------------------------------------------------------*/
362/*---------------------------------------------------------------------------*/
363
364ARCANE_REGISTER_SERVICE(MpiSequentialParallelSuperMng,
365 ServiceProperty("MpiSequentialParallelSuperMng",ST_Application),
366 ARCANE_SERVICE_INTERFACE(IParallelSuperMng));
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
371} // End namespace Arcane
372
373/*---------------------------------------------------------------------------*/
374/*---------------------------------------------------------------------------*/
#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.
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 ApplicationInfo & applicationInfo() const =0
Informations sur l'exécutable.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
Interface d'un gestionnaire de thread.
Definition IThreadMng.h:30
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
virtual TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium)=0
Flot pour un message de debug.
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
Gère les MPI_Datatype associées aux types Arcane.
Interface des messages pour le type Type.
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)
MP::Communicator m_machine_communicator
Communicateur MPI Machine.
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.
void build() override
Construction de niveau build du service.
Gestionnaire de thread en mode mono-thread.
Statistiques sur le parallélisme.
Référence à une instance.
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.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
IStat * createDefaultStat()
Créé une instance par défaut.
ARCCORE_BASE_EXPORT Real getRealTime()
Temps Real utilisé en secondes.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Ref< TrueType > createRef(Args &&... args)
Créé une instance de type TrueType avec les arguments Args et retourne une référence dessus.
ARCANE_MPI_EXPORT void arcaneInitializeMPI(int *argc, char ***argv, int wanted_thread_level)
Definition ArcaneMpi.cc:209
ARCANE_MPI_EXPORT bool arcaneIsAcceleratorAwareMPI()
Indique si le runtime actuel de MPI a le support des accélérateurs.
Definition ArcaneMpi.cc:82
Int32 Integer
Type représentant un entier.
@ ST_Application
Le service s'utilise au niveau de l'application.
double Real
Type représentant un réel.
ARCANE_MPI_EXPORT void arcaneFinalizeMPI()
Definition ArcaneMpi.cc:215
std::int32_t Int32
Type entier signé sur 32 bits.
Infos pour construire un MpiParallelMng.