Arcane  v4.1.2.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.
double getMemoryUsed()
Mémoire utilisée em octets.
Real getRealTime()
Temps Real utilisé en secondes.
String getCurrentDateTime()
Date et l'heure courante sous la forme ISO 8601.
Int64 getCPUTime()
Temps CPU utilisé en microsecondes.
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.