Arcane  v3.16.4.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
ModuleMaster.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/* ModuleMaster.cc (C) 2000-2025 */
9/* */
10/* Module maître. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/utils/Iterator.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/Array.h"
19#include "arcane/utils/Enumerator.h"
20#include "arcane/utils/Collection.h"
21#include "arcane/utils/IOnlineDebuggerService.h"
22
23#include "arcane/core/ModuleMaster.h"
24#include "arcane/core/EntryPoint.h"
25#include "arcane/core/CaseOptionsMain.h"
26#include "arcane/core/ITimeHistoryMng.h"
27#include "arcane/core/IVariableMng.h"
28#include "arcane/core/ISubDomain.h"
29#include "arcane/core/IApplication.h"
30#include "arcane/core/IModuleMng.h"
31#include "arcane/core/ITimeLoopMng.h"
32#include "arcane/core/IParallelMng.h"
33#include "arcane/core/ICaseMng.h"
34#include "arcane/core/IModuleMng.h"
35#include "arcane/core/ModuleBuildInfo.h"
36#include "arcane/core/ITimeLoopService.h"
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41namespace Arcane
42{
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47extern "C++" ARCANE_CORE_EXPORT IModuleMaster*
48arcaneCreateModuleMaster(ISubDomain* sd)
49{
50 ModuleBuildInfo mbi(sd,sd->defaultMeshHandle(),"ArcaneMasterInternal");
51 ModuleMaster* m = new ModuleMaster(mbi);
52 return m;
53}
54
55/*---------------------------------------------------------------------------*/
56/*---------------------------------------------------------------------------*/
57
58ModuleMaster::
59ModuleMaster(const ModuleBuildInfo& mb)
61, CommonVariables(this)
62{
64
65 addEntryPoint(this,"ArcaneTimeLoopBegin",
68 addEntryPoint(this,"ArcaneTimeLoopEnd",
71 addEntryPoint(this,"ArcaneMasterStartInit",
74 addEntryPoint(this,"ArcaneMasterInit",
77 addEntryPoint(this,"ArcaneMasterContinueInit",
81 addEntryPoint(this,"ArcaneMasterLoopExit",
82 &ModuleMaster::_masterLoopExit,
83 IEntryPoint::WExit,
85 addEntryPoint(this,"ArcaneMasterLoopMeshChanged",
86 &ModuleMaster::_masterMeshChanged,
89 addEntryPoint(this,"ArcaneMasterLoopRestore",
90 &ModuleMaster::_masterRestore,
93}
94
95/*---------------------------------------------------------------------------*/
96/*---------------------------------------------------------------------------*/
97
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
109{
111 m_global_time = 0.0;
114 m_global_cpu_time = 0.0;
118
119 // Met a jour les options du jeu de données qui dépendent d'une table de marche.
120 ICaseMng* com = subDomain()->caseMng();
121 com->updateOptions(0.0,0.0,0);
122
123 _masterStartInit();
124}
125
126/*---------------------------------------------------------------------------*/
127/*---------------------------------------------------------------------------*/
128
131{
132}
133
134/*---------------------------------------------------------------------------*/
135/*---------------------------------------------------------------------------*/
136
139{
140 // En reprise, l'initialisation est considérée comme ayant lieu avant
141 // la prochaine itération, donc avec les anciennes valeurs du pas de temps
142 // et du temps de la simulation.
143
144 ICaseMng* com = subDomain()->caseMng();
145 Int32 opt_iteration = m_global_iteration() - 1;
146 info() << "Initialization to restore the functions of the input data: "
147 << " time=" << m_global_old_time()
148 << " dt=" << m_global_old_deltat()
149 << " iteration=" << opt_iteration;
151
152 _masterContinueInit();
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
163
164/*---------------------------------------------------------------------------*/
165/*---------------------------------------------------------------------------*/
166
169{
172
173 info()<<" ";
174 info(0) << "***"
175 << " ITERATION " << Trace::Width(8) << m_global_iteration()
176 << " TIME " << Trace::Width(digit) << Trace::Precision(precision,m_global_time(),true)
177 << " LOOP " << Trace::Width(8) << m_nb_loop
178 << " DELTAT " << Trace::Width(digit) << Trace::Precision(precision,m_global_deltat(),true)
179 << " ***";
180}
181
182/*---------------------------------------------------------------------------*/
183/*---------------------------------------------------------------------------*/
184
185
188{
189 // Première boucle, initialise le temps et affiche les infos
190 // sur la consommation
191 if (m_is_first_loop){
192 info() << "Information on consumption (unit:second): Con(R=...,I=...,C=...)";
193 info() << " R -> consumption in real time (clock) since the beginning of the computation";
194 info() << " I -> real time (clock) spent during the last iteration";
195 info() << " C -> consumption in CPU time since the beginning of the computation";
196 info() << "Information on memory consumption (unit: Mo): Mem=(X,m=X1:R1,M=X2:R2,avg=Z)";
197 info() << " X -> memory consumption of the process";
198 info() << " X1 -> memory consumption of the least memory hungry process and R1 is its rank";
199 info() << " X2 -> memory consumption of the most memory hungry process and R2 is its rank";
200 info() << " Z -> average memory consumption of all process";
201 }
202
203 ++m_nb_loop;
204
205 // Met a jour les options du jeu de données qui dépendent d'une table de marche.
206 ICaseMng* com = subDomain()->caseMng();
208
209 Real mem_used = platform::getMemoryUsed();
210
212
214
215 // Infos pour les courbes
216 m_thm_mem_used = mem_used;
217
218 // Ajoute le deltat au temps courant
219 //info() << "[ModuleMaster::timeLoopBegin] Add deltat to the current time";
221
222 m_thm_global_time = m_global_time();
223 //thm->addValue(m_global_time.name(),m_global_time());
224
225 //info() << "[ModuleMaster::timeLoopBegin] breakpoint_requested?";
227
228 // Il faut absolument que cette valeur soit la même pour tous les sous-domaines
229 Real cpu_time = (Real)platform::getCPUTime();
230 Real elapsed_time = platform::getRealTime();
231 {
232 Real values[3];
233 ArrayView<Real> vals(3,values);
234 values[0] = cpu_time;
235 values[1] = elapsed_time;
236 values[2] = (hyoda)?hyoda->loopbreak(subDomain()):0.0;
238 cpu_time = values[0];
239 elapsed_time = values[1];
240 if (hyoda && values[2]>0.0)
241 hyoda->hook(subDomain(),values[2]);
242 }
243 if (m_is_first_loop){
244 m_old_cpu_time = cpu_time;
245 m_old_elapsed_time = elapsed_time;
246 }
247 Real diff_cpu = (cpu_time - m_old_cpu_time) / CLOCKS_PER_SEC;
248 Real diff_elapsed = (elapsed_time - m_old_elapsed_time);
249 m_global_old_cpu_time = diff_cpu;
250 m_global_old_elapsed_time = diff_elapsed;
253
254 m_thm_diff_cpu = diff_cpu;
255 m_thm_global_cpu_time = m_global_cpu_time();
256 m_thm_diff_elapsed = diff_elapsed;
257 m_thm_global_elapsed_time = m_global_elapsed_time();
258
259 m_old_cpu_time = cpu_time;
260 m_old_elapsed_time = elapsed_time;
261
263
264 Real mem_sum = 0.0;
265 Real mem_min = 0.0;
266 Real mem_max = 0.0;
267 Int32 mem_min_rank = 0;
268 Int32 mem_max_rank = 0;
269 pm->computeMinMaxSum(mem_used,mem_min,mem_max,mem_sum,mem_min_rank,mem_max_rank);
270 // Tronque à la milli-seconde
271 Int64 i_elapsed = (Int64)(m_global_elapsed_time() * 1000.0);
272 Int64 i_diff_elapsed = (Int64)(diff_elapsed * 1000.0);
273 Int64 i_cpu = (Int64)(m_global_cpu_time() * 1000.0);
274 info(1) << "Date: " << platform::getCurrentDateTime()
275 << " Conso=(R=" << (((Real)i_elapsed) / 1000.0)
276 << ",I=" << (((Real)i_diff_elapsed) / 1000.0)
277 << ",C=" << ((Real)i_cpu / 1000.0)
278 << ") Mem=(" << (Int64)(mem_used/1e6)
279 << ",m=" << (Int64)(mem_min/1e6)
280 << ":" << mem_min_rank
281 << ",M=" << (Int64)(mem_max/1e6)
282 << ":" << mem_max_rank
283 << ",avg=" << (Int64)(mem_sum/1e6) / pm->commSize()
284 << ")";
285
286 _masterBeginLoop();
287 m_is_first_loop = false;
288 m_has_thm_dump_at_iteration = false;
289}
290
291/*---------------------------------------------------------------------------*/
292/*---------------------------------------------------------------------------*/
293
296{
297 _masterEndLoop();
298
299 // Effectue les sorties courbes
300 // Comme il est possible de désactiver les sorties courbes
301 // à une itération donnée, il faut faire les sorties en fin d'itération
302 // et non pas au début pour permettre aux autres modules d'activer ou non
303 // les sorties. Il est aussi possible pour un code utilisateur d'appeler
304 // explicitement cette méthode pour qu'il fasse les sorties quand il le
305 // souhaite au cours de l'itération.
307
308 // Incrémente le compteur d'itération
310
311 if (subDomain()->timeLoopMng()->finalTimeReached()){
312 info() <<"===============================================================";
313 info() <<"====== END OF COMPUTATION REACHED... =======================";
314 info() <<"===============================================================";
315 }
316}
317
318/*---------------------------------------------------------------------------*/
319/*---------------------------------------------------------------------------*/
320
323{
324 if (m_has_thm_dump_at_iteration)
325 return;
326
327 // Si cette méthode est appelée à la fin de l'itération, alors les
328 // temps cpu (m_thm_diff_cpu) et elapsed (m_thm_global_elapsed_time)
329 // ne sont pas bon car ils ont été calculés en début d'itération et donc
330 // ils ne sont pas bon. On les recalcule donc en prenant soin
331 // de ne pas mettre à jour les variables m_global* pour éviter toute
332 // incohérence car ces valeurs ne sont pas synchronisées entre tous
333 // les sous-domaines (et de plus cette méthode n'est pas toujours
334 // appelée)
335
336 Real cpu_time = (Real)platform::getCPUTime();
337 Real elapsed_time = platform::getRealTime();
338 Real diff_cpu = (cpu_time - m_old_cpu_time) / 1000000.0;
339 Real diff_elapsed = (elapsed_time - m_old_elapsed_time);
340 Real mem_used = platform::getMemoryUsed();
341 Real global_cpu_time = diff_cpu + m_global_cpu_time();
342 Real global_elapsed_time = diff_elapsed + m_global_elapsed_time();
343
345 thm->addValue("TotalMemory",mem_used);
346 thm->addValue("CpuTime",diff_cpu);
347 thm->addValue("GlobalCpuTime",global_cpu_time);
348 thm->addValue("ElapsedTime",diff_elapsed);
349 thm->addValue("GlobalElapsedTime",global_elapsed_time);
350 thm->addValue(m_global_time.name(),m_thm_global_time);
351 m_has_thm_dump_at_iteration = true;
352
353 Int64 i_elapsed = (Int64)(global_elapsed_time * 1000.0);
354 Int64 i_diff_elapsed = (Int64)(diff_elapsed * 1000.0);
355 Int64 i_cpu = (Int64)(global_cpu_time * 1000.0);
356
357 info(4) << "EndIter: Date: " << platform::getCurrentDateTime()
358 << " Conso=(R=" << (((Real)i_elapsed) / 1000.0)
359 << ",I=" << (((Real)i_diff_elapsed) / 1000.0)
360 << ",C=" << ((Real)i_cpu / 1000.0)
361 << ") Mem=(" << (Int64)(mem_used/1e6)
362 << ")";
363}
364
365/*---------------------------------------------------------------------------*/
366/*---------------------------------------------------------------------------*/
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
380void ModuleMaster::
381_masterBeginLoop()
382{
383 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
385 service->onTimeLoopBeginLoop();
386 }
387}
388
389/*---------------------------------------------------------------------------*/
390/*---------------------------------------------------------------------------*/
391
392void ModuleMaster::
393_masterEndLoop()
394{
395 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
396 ITimeLoopService* service = m_timeloop_services[i];
397 service->onTimeLoopEndLoop();
398 }
399}
400
401/*---------------------------------------------------------------------------*/
402/*---------------------------------------------------------------------------*/
403
404void ModuleMaster::
405_masterStartInit()
406{
407 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
408 ITimeLoopService* service = m_timeloop_services[i];
409 service->onTimeLoopStartInit();
410 }
411}
412
413/*---------------------------------------------------------------------------*/
414/*---------------------------------------------------------------------------*/
415
416void ModuleMaster::
417_masterContinueInit()
418{
419 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
420 ITimeLoopService* service = m_timeloop_services[i];
421 service->onTimeLoopContinueInit();
422 }
423}
424
425/*---------------------------------------------------------------------------*/
426/*---------------------------------------------------------------------------*/
427
428void ModuleMaster::
429_masterLoopExit()
430{
431 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
432 ITimeLoopService* service = m_timeloop_services[i];
433 service->onTimeLoopExit();
434 }
435}
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
439
440void ModuleMaster::
441_masterMeshChanged()
442{
443 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
444 ITimeLoopService* service = m_timeloop_services[i];
445 service->onTimeLoopMeshChanged();
446 }
447}
448
449/*---------------------------------------------------------------------------*/
450/*---------------------------------------------------------------------------*/
451
452void ModuleMaster::
453_masterRestore()
454{
455 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
456 ITimeLoopService* service = m_timeloop_services[i];
457 service->onTimeLoopRestore();
458 }
459}
460
461/*---------------------------------------------------------------------------*/
462/*---------------------------------------------------------------------------*/
463
464}
465
466/*---------------------------------------------------------------------------*/
467/*---------------------------------------------------------------------------*/
ISubDomain * subDomain() const override
Sous-domaine associé au module.
AbstractModule(const ModuleBuildInfo &)
Constructeur à partir d'un ModuleBuildInfo.
IParallelMng * parallelMng() const override
Gestionnaire du parallélisme par échange de message.
Vue modifiable d'un tableau d'un type T.
VariableScalarInt32 m_global_iteration
Itération courante.
VariableScalarReal m_global_elapsed_time
Temps horloge utilisé (en seconde)
VariableScalarReal m_global_cpu_time
Temps CPU utilisé (en seconde)
VariableScalarReal m_global_old_deltat
Delta T au temps précédent le temps global.
VariableScalarReal m_global_old_elapsed_time
Temps précédent horloge utilisé (en seconde)
VariableScalarReal m_global_time
Temps actuel.
CommonVariables(IModule *c)
Construit les références des variables communes pour le module c.
VariableScalarReal m_global_old_cpu_time
Temps précédent CPU utilisé (en seconde)
VariableScalarReal m_global_old_time
Temps précédent le temps actuel.
VariableScalarReal m_global_deltat
Delta T global.
Informations sur le type flottant.
Definition Limits.h:48
Interface du gestionnaire de cas.
Definition ICaseMng.h:56
virtual void updateOptions(Real current_time, Real current_deltat, Integer current_iteration)=0
Met à jour les options basée sur une table de marche en temps.
static const char *const WComputeLoop
appelé pendant la boucle de calcul
Definition IEntryPoint.h:42
static const char *const WStartInit
appelé pendant l'initialisation d'un nouveau cas
Definition IEntryPoint.h:50
static const char *const WRestore
appelé pour restaurer les variables lors d'un retour arrière
Definition IEntryPoint.h:52
@ PAutoLoadEnd
Chargé automatiquement à la fin. Cela signifie qu'un module possédant un point d'entrée avec cette pr...
Definition IEntryPoint.h:80
@ PAutoLoadBegin
Chargé automatiquement au début. Cela signifie qu'un module possédant un point d'entrée avec cette pr...
Definition IEntryPoint.h:73
static const char *const WOnMeshChanged
appelé après un changement de maillage
Definition IEntryPoint.h:54
static const char *const WContinueInit
appelé pendant l'initialisation d'une reprise
Definition IEntryPoint.h:48
static const char *const WInit
appelé pendant l'initialisation
Definition IEntryPoint.h:46
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual void computeMinMaxSum(char val, char &min_val, char &max_val, char &sum_val, Int32 &min_rank, Int32 &max_rank)=0
Calcule en une opération la somme, le min, le max d'une valeur.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual char reduce(eReduceType rt, char v)=0
Effectue la réduction de type rt sur le réel v et retourne la valeur.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual ITimeHistoryMng * timeHistoryMng()=0
Retourne le gestionnaire d'historique.
virtual ICaseMng * caseMng()=0
Retourne le gestionnaire du jeu de données.
virtual IParallelMng * allReplicaParallelMng() const =0
Retourne le gestionnaire de parallélisme pour tous les réplicats.
Classe gérant un historique de valeurs.
virtual void addValue(const String &name, Real value, bool end_time=true, bool is_local=false)=0
Ajoute la valeur value à l'historique name.
Interface d'un service opérant lors de la boucle en temps.
Informations pour construire un module.
ISubDomain * subDomain() const
Accès au sous-domaine associé
void masterInit()
Point d'entrée auto-chargé en début d'initialisation.
void masterStartInit()
Point d'entrée auto-chargé en début d'initialisation d'un nouveau cas.
CaseOptionsMain * m_case_options_main
Instance des options du module.
bool m_is_first_loop
Indique si on est dans la première itération de l'exécution.
Real m_old_cpu_time
Valeur du temps CPU à la dernière itération.
void dumpStandardCurves() override
Sort les courbes classiques (CPUTime, ElapsedTime, ...)
Real m_old_elapsed_time
Valeur du temps horloge à la dernière itération.
virtual void timeStepInformation()
Affichage surchargeable des informations du pas de temps.
void timeLoopEnd()
Point d'entrée auto-chargé en fin d'itération de la boucle de calcul.
void timeLoopBegin()
Point d'entrée auto-chargé en début d'itération de la boucle de calcul.
void addTimeLoopService(ITimeLoopService *tls) override
Ajoute le service de boucle en temps.
UniqueArray< ITimeLoopService * > m_timeloop_services
Liste des services de boucle en temps.
virtual void timeIncrementation()
Incrémentation du pas de temps surchargeable.
Integer m_nb_loop
Nombre de boucles de calcul effectuées.
~ModuleMaster() override
Destructeur.
void masterContinueInit()
Point d'entrée auto-chargé en début de reprise d'un nouveau cas.
TraceMessage info() const
Flot pour un message d'information.
Formattage des réels avec une précision donnée.
Formattage du flot en longueur.
@ ReduceMax
Maximum des valeurs.
ARCCORE_BASE_EXPORT Int64 getCPUTime()
Temps CPU utilisé en microsecondes.
ARCCORE_BASE_EXPORT String getCurrentDateTime()
Date et l'heure courante sous la forme ISO 8601.
ARCCORE_BASE_EXPORT double getMemoryUsed()
Mémoire utilisée em octets.
ARCCORE_BASE_EXPORT Real getRealTime()
Temps Real utilisé en secondes.
IOnlineDebuggerService * getOnlineDebuggerService()
Service utilisé pour obtenir la mise en place d'une architecture en ligne de debug.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
double Real
Type représentant un réel.
void addEntryPoint(ModuleType *module, const char *name, void(ModuleType::*func)(), const String &where=IEntryPoint::WComputeLoop, int property=IEntryPoint::PNone)
Routine template permettant de référencer un point d'entrée dans un module.
Definition EntryPoint.h:166
std::int32_t Int32
Type entier signé sur 32 bits.