Arcane  v3.16.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ModuleMaster.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 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-2015 */
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/ModuleMaster.h"
24#include "arcane/EntryPoint.h"
25#include "arcane/CaseOptionsMain.h"
26#include "arcane/ITimeHistoryMng.h"
27#include "arcane/IVariableMng.h"
28#include "arcane/ISubDomain.h"
29#include "arcane/IApplication.h"
30#include "arcane/IModuleMng.h"
31#include "arcane/ITimeLoopMng.h"
32#include "arcane/IParallelMng.h"
33#include "arcane/ICaseMng.h"
34#include "arcane/IModuleMng.h"
35#include "arcane/ModuleBuildInfo.h"
36#include "arcane/ITimeLoopService.h"
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41ARCANE_BEGIN_NAMESPACE
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
46extern "C++" ARCANE_CORE_EXPORT IModuleMaster*
47arcaneCreateModuleMaster(ISubDomain* sd)
48{
49 ModuleBuildInfo mbi(sd,sd->defaultMeshHandle(),"ArcaneMasterInternal");
50 ModuleMaster* m = new ModuleMaster(mbi);
51 return m;
52}
53
54/*---------------------------------------------------------------------------*/
55/*---------------------------------------------------------------------------*/
56
57ModuleMaster::
58ModuleMaster(const ModuleBuildInfo& mb)
60, CommonVariables(this)
62, m_nb_loop(0)
63, m_old_cpu_time(0.0)
65, m_is_first_loop(true)
66, m_thm_mem_used(0.0)
67, m_thm_diff_cpu(0.0)
68, m_thm_global_cpu_time(0.0)
69, m_thm_diff_elapsed(0.0)
70, m_thm_global_elapsed_time(0.0)
71, m_thm_global_time(0.0)
72, m_has_thm_dump_at_iteration(false)
73{
75
76 addEntryPoint(this,"ArcaneTimeLoopBegin",
79 addEntryPoint(this,"ArcaneTimeLoopEnd",
82 addEntryPoint(this,"ArcaneMasterStartInit",
85 addEntryPoint(this,"ArcaneMasterInit",
88 addEntryPoint(this,"ArcaneMasterContinueInit",
92 addEntryPoint(this,"ArcaneMasterLoopExit",
93 &ModuleMaster::_masterLoopExit,
94 IEntryPoint::WExit,
96 addEntryPoint(this,"ArcaneMasterLoopMeshChanged",
97 &ModuleMaster::_masterMeshChanged,
100 addEntryPoint(this,"ArcaneMasterLoopRestore",
101 &ModuleMaster::_masterRestore,
104}
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
114
115/*---------------------------------------------------------------------------*/
116/*---------------------------------------------------------------------------*/
117
120{
122 m_global_time = 0.0;
125 m_global_cpu_time = 0.0;
129
130 // Met a jour les options du jeu de données qui dépendent d'une table de marche.
131 ICaseMng* com = subDomain()->caseMng();
132 com->updateOptions(0.0,0.0,0);
133
134 _masterStartInit();
135}
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
142{
143}
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
150{
151 // En reprise, l'initialisation est considérée comme ayant lieu avant
152 // la prochaine itération, donc avec les anciennes valeurs du pas de temps
153 // et du temps de la simulation.
154
155 ICaseMng* com = subDomain()->caseMng();
156 Int32 opt_iteration = m_global_iteration() - 1;
157 info() << "Initialization to restore the functions of the input data: "
158 << " time=" << m_global_old_time()
159 << " dt=" << m_global_old_deltat()
160 << " iteration=" << opt_iteration;
162
163 _masterContinueInit();
164}
165
166/*---------------------------------------------------------------------------*/
167/*---------------------------------------------------------------------------*/
168
174
175/*---------------------------------------------------------------------------*/
176/*---------------------------------------------------------------------------*/
177
180{
183
184 info()<<" ";
185 info(0) << "***"
186 << " ITERATION " << Trace::Width(8) << m_global_iteration()
187 << " TIME " << Trace::Width(digit) << Trace::Precision(precision,m_global_time(),true)
188 << " LOOP " << Trace::Width(8) << m_nb_loop
189 << " DELTAT " << Trace::Width(digit) << Trace::Precision(precision,m_global_deltat(),true)
190 << " ***";
191}
192
193/*---------------------------------------------------------------------------*/
194/*---------------------------------------------------------------------------*/
195
196
199{
200 // Première boucle, initialise le temps et affiche les infos
201 // sur la consommation
202 if (m_is_first_loop){
203 info() << "Information on consumption (unit:second): Con(R=...,I=...,C=...)";
204 info() << " R -> consumption in real time (clock) since the beginning of the computation";
205 info() << " I -> real time (clock) spent during the last iteration";
206 info() << " C -> consumption in CPU time since the beginning of the computation";
207 info() << "Information on memory consumption (unit: Mo): Mem=(X,m=X1:R1,M=X2:R2,avg=Z)";
208 info() << " X -> memory consumption of the process";
209 info() << " X1 -> memory consumption of the least memory hungry process and R1 is its rank";
210 info() << " X2 -> memory consumption of the most memory hungry process and R2 is its rank";
211 info() << " Z -> average memory consumption of all process";
212 }
213
214 ++m_nb_loop;
215
216 // Met a jour les options du jeu de données qui dépendent d'une table de marche.
217 ICaseMng* com = subDomain()->caseMng();
219
220 Real mem_used = platform::getMemoryUsed();
221
223
225
226 // Infos pour les courbes
227 m_thm_mem_used = mem_used;
228
229 // Ajoute le deltat au temps courant
230 //info() << "[ModuleMaster::timeLoopBegin] Add deltat to the current time";
232
233 m_thm_global_time = m_global_time();
234 //thm->addValue(m_global_time.name(),m_global_time());
235
236 //info() << "[ModuleMaster::timeLoopBegin] breakpoint_requested?";
238
239 // Il faut absolument que cette valeur soit la même pour tous les sous-domaines
240 Real cpu_time = (Real)platform::getCPUTime();
241 Real elapsed_time = platform::getRealTime();
242 {
243 Real values[3];
244 ArrayView<Real> vals(3,values);
245 values[0] = cpu_time;
246 values[1] = elapsed_time;
247 values[2] = (hyoda)?hyoda->loopbreak(subDomain()):0.0;
249 cpu_time = values[0];
250 elapsed_time = values[1];
251 if (hyoda && values[2]>0.0)
252 hyoda->hook(subDomain(),values[2]);
253 }
254 if (m_is_first_loop){
255 m_old_cpu_time = cpu_time;
256 m_old_elapsed_time = elapsed_time;
257 }
258 Real diff_cpu = (cpu_time - m_old_cpu_time) / CLOCKS_PER_SEC;
259 Real diff_elapsed = (elapsed_time - m_old_elapsed_time);
260 m_global_old_cpu_time = diff_cpu;
261 m_global_old_elapsed_time = diff_elapsed;
264
265 m_thm_diff_cpu = diff_cpu;
266 m_thm_global_cpu_time = m_global_cpu_time();
267 m_thm_diff_elapsed = diff_elapsed;
268 m_thm_global_elapsed_time = m_global_elapsed_time();
269
270 m_old_cpu_time = cpu_time;
271 m_old_elapsed_time = elapsed_time;
272
274
275 Real mem_sum = 0.0;
276 Real mem_min = 0.0;
277 Real mem_max = 0.0;
278 Int32 mem_min_rank = 0;
279 Int32 mem_max_rank = 0;
280 pm->computeMinMaxSum(mem_used,mem_min,mem_max,mem_sum,mem_min_rank,mem_max_rank);
281 // Tronque à la milli-seconde
282 Int64 i_elapsed = (Int64)(m_global_elapsed_time() * 1000.0);
283 Int64 i_diff_elapsed = (Int64)(diff_elapsed * 1000.0);
284 Int64 i_cpu = (Int64)(m_global_cpu_time() * 1000.0);
285 info(1) << "Date: " << platform::getCurrentDateTime()
286 << " Conso=(R=" << (((Real)i_elapsed) / 1000.0)
287 << ",I=" << (((Real)i_diff_elapsed) / 1000.0)
288 << ",C=" << ((Real)i_cpu / 1000.0)
289 << ") Mem=(" << (Int64)(mem_used/1e6)
290 << ",m=" << (Int64)(mem_min/1e6)
291 << ":" << mem_min_rank
292 << ",M=" << (Int64)(mem_max/1e6)
293 << ":" << mem_max_rank
294 << ",avg=" << (Int64)(mem_sum/1e6) / pm->commSize()
295 << ")";
296
297 _masterBeginLoop();
298 m_is_first_loop = false;
299 m_has_thm_dump_at_iteration = false;
300}
301
302/*---------------------------------------------------------------------------*/
303/*---------------------------------------------------------------------------*/
304
307{
308 _masterEndLoop();
309
310 // Effectue les sorties courbes
311 // Comme il est possible de désactiver les sorties courbes
312 // à une itération donnée, il faut faire les sorties en fin d'itération
313 // et non pas au début pour permettre aux autres modules d'activer ou non
314 // les sorties. Il est aussi possible pour un code utilisateur d'appeler
315 // explicitement cette méthode pour qu'il fasse les sorties quand il le
316 // souhaite au cours de l'itération.
318
319 // Incrémente le compteur d'itération
321
322 if (subDomain()->timeLoopMng()->finalTimeReached()){
323 info() <<"===============================================================";
324 info() <<"====== END OF COMPUTATION REACHED... =======================";
325 info() <<"===============================================================";
326 }
327}
328
329/*---------------------------------------------------------------------------*/
330/*---------------------------------------------------------------------------*/
331
334{
335 if (m_has_thm_dump_at_iteration)
336 return;
337
338 // Si cette méthode est appelée à la fin de l'itération, alors les
339 // temps cpu (m_thm_diff_cpu) et elapsed (m_thm_global_elapsed_time)
340 // ne sont pas bon car ils ont été calculés en début d'itération et donc
341 // ils ne sont pas bon. On les recalcule donc en prenant soin
342 // de ne pas mettre à jour les variables m_global* pour éviter toute
343 // incohérence car ces valeurs ne sont pas synchronisées entre tous
344 // les sous-domaines (et de plus cette méthode n'est pas toujours
345 // appelée)
346
347 Real cpu_time = (Real)platform::getCPUTime();
348 Real elapsed_time = platform::getRealTime();
349 Real diff_cpu = (cpu_time - m_old_cpu_time) / 1000000.0;
350 Real diff_elapsed = (elapsed_time - m_old_elapsed_time);
351 Real mem_used = platform::getMemoryUsed();
352 Real global_cpu_time = diff_cpu + m_global_cpu_time();
353 Real global_elapsed_time = diff_elapsed + m_global_elapsed_time();
354
356 thm->addValue("TotalMemory",mem_used);
357 thm->addValue("CpuTime",diff_cpu);
358 thm->addValue("GlobalCpuTime",global_cpu_time);
359 thm->addValue("ElapsedTime",diff_elapsed);
360 thm->addValue("GlobalElapsedTime",global_elapsed_time);
361 thm->addValue(m_global_time.name(),m_thm_global_time);
362 m_has_thm_dump_at_iteration = true;
363
364 Int64 i_elapsed = (Int64)(global_elapsed_time * 1000.0);
365 Int64 i_diff_elapsed = (Int64)(diff_elapsed * 1000.0);
366 Int64 i_cpu = (Int64)(global_cpu_time * 1000.0);
367
368 info(4) << "EndIter: Date: " << platform::getCurrentDateTime()
369 << " Conso=(R=" << (((Real)i_elapsed) / 1000.0)
370 << ",I=" << (((Real)i_diff_elapsed) / 1000.0)
371 << ",C=" << ((Real)i_cpu / 1000.0)
372 << ") Mem=(" << (Int64)(mem_used/1e6)
373 << ")";
374}
375
376/*---------------------------------------------------------------------------*/
377/*---------------------------------------------------------------------------*/
378
379/*---------------------------------------------------------------------------*/
380/*---------------------------------------------------------------------------*/
381
387
388/*---------------------------------------------------------------------------*/
389/*---------------------------------------------------------------------------*/
390
391void ModuleMaster::
392_masterBeginLoop()
393{
394 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
396 service->onTimeLoopBeginLoop();
397 }
398}
399
400/*---------------------------------------------------------------------------*/
401/*---------------------------------------------------------------------------*/
402
403void ModuleMaster::
404_masterEndLoop()
405{
406 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
407 ITimeLoopService* service = m_timeloop_services[i];
408 service->onTimeLoopEndLoop();
409 }
410}
411
412/*---------------------------------------------------------------------------*/
413/*---------------------------------------------------------------------------*/
414
415void ModuleMaster::
416_masterStartInit()
417{
418 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
419 ITimeLoopService* service = m_timeloop_services[i];
420 service->onTimeLoopStartInit();
421 }
422}
423
424/*---------------------------------------------------------------------------*/
425/*---------------------------------------------------------------------------*/
426
427void ModuleMaster::
428_masterContinueInit()
429{
430 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
431 ITimeLoopService* service = m_timeloop_services[i];
432 service->onTimeLoopContinueInit();
433 }
434}
435
436/*---------------------------------------------------------------------------*/
437/*---------------------------------------------------------------------------*/
438
439void ModuleMaster::
440_masterLoopExit()
441{
442 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
443 ITimeLoopService* service = m_timeloop_services[i];
444 service->onTimeLoopExit();
445 }
446}
447
448/*---------------------------------------------------------------------------*/
449/*---------------------------------------------------------------------------*/
450
451void ModuleMaster::
452_masterMeshChanged()
453{
454 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
455 ITimeLoopService* service = m_timeloop_services[i];
456 service->onTimeLoopMeshChanged();
457 }
458}
459
460/*---------------------------------------------------------------------------*/
461/*---------------------------------------------------------------------------*/
462
463void ModuleMaster::
464_masterRestore()
465{
466 for( Integer i=0, is=m_timeloop_services.size(); i<is; ++i ){
467 ITimeLoopService* service = m_timeloop_services[i];
468 service->onTimeLoopRestore();
469 }
470}
471
472/*---------------------------------------------------------------------------*/
473/*---------------------------------------------------------------------------*/
474
475ARCANE_END_NAMESPACE
476
477/*---------------------------------------------------------------------------*/
478/*---------------------------------------------------------------------------*/
479
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 d'un service de debugger hybrid.
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.
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.
virtual ~ModuleMaster()
Destructeur.
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 derniere itération.
Real m_old_elapsed_time
Valeur du temps horloge à la derniere 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.
virtual void addTimeLoopService(ITimeLoopService *tls)
Ajoute le service de boucle en temps.
virtual void dumpStandardCurves()
Sort les courbes classiques (CPUTime, ElapsedTime, ...)
UniqueArray< ITimeLoopService * > m_timeloop_services
Liste des serviecs 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.
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.
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.