TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Process.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <Process.h>
17#include <Comm_Group.h>
18#include <PE_Groups.h>
19#include <communications.h>
20#include <Sortie_Nulle.h>
21#include <Journal.h>
22#include <SFichier.h>
23#include <Synonyme_info.h>
24#include <petsc_for_kernel.h>
25#include <comm_incl.h>
26#include <TRUST_Error.h>
27#include <Comm_Group_MPI.h>
28#include <unistd.h> // sleep() pour certaines machines
29#include <SChaine.h>
30#include <FichierHDFPar.h>
31#include <EChaineJDD.h>
32#include <DeviceMemory.h>
33#include <kokkos++.h>
34#include <fstream>
35
36// Chacun des fichiers Cerr, Cout et Journal(i)
37// peut etre redirige vers l'un des quatre fichiers suivants:
38// Instance de la Sortie nulle (equivalent de /dev/null)
39static Sortie_Nulle journal_zero_;
40// Instance de la Sortie pointant vers cerr
41static Sortie std_err_(cerr);
42// Instance de la Sortie pointant vers cout
43static Sortie std_out_(cout);
44// Instances du fichier Journal
45static SFichier journal_file_;
46
47static int journal_file_open_;
48static Nom journal_file_name_;
49// Niveau maximal des messages ecrits. La valeur initiale determine
50// si les messages ecrits avant l'initialisation du journal sont ecrits
51// ou pas.
52static int verbose_level_ = 0;
53static int disable_stop_ = 0;
54
55// Drapeau indiquant si les sorties cerr et cout doivent
56// etre redirigees vers le fichier journal
57static int cerr_to_journal_ = 0;
59int Process::multiple_files=5120; // Valeur modifiable avec la variable d'environnement TRUST_MultipleFiles
60bool Process::force_single_file(const int ranks, const Nom& filename)
61{
62 char* theValue = getenv("TRUST_MultipleFiles");
63 if (theValue != nullptr) multiple_files=atoi(theValue);
64 if (ranks>multiple_files)
65 {
66 if (Process::je_suis_maitre()) // Attention, necessaire, car appel possible tres tot dans main.cpp alors que Cerr par defini completement sur les processes
67 {
68 Cerr << "======================================================================================================" << finl;
69 Cerr << "Warning! Single file option is forced for " << filename << " above " << multiple_files << " MPI ranks." << finl;
70 Cerr << "for I/O performance reasons on cluster and inodes number limitation." << finl;
71 Cerr << "If you want to keep multiple files, add at the beginning of your data file to outpass the limitation:" << finl;
72 Cerr << "MultipleFiles " << ranks << finl;
73 Cerr << "=====================================================================================================" << finl;
74 }
75 return true;
76 }
77 else
78 return false;
79}
80
81/*! @brief renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0), 0 sinon.
82 *
83 * Voir Comm_Group::rank()
84 *
85 */
87{
88 const int r = PE_Groups::current_group().rank();
89 return r == 0;
90}
91
92/*! @brief renvoie 1 si on est sur le processeur maitre du noeud numa, 0 sinon.
93 *
94 */
96{
97 const int r = PE_Groups::get_node_group().rank();
98 return r == 0;
99}
100
101/*! @brief renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::current_group()
102 *
103 */
105{
106 const int n = PE_Groups::current_group().nproc();
107 return n;
108}
109
111{
112 return Process::nproc() > 1;
113}
114
116{
117 return Process::nproc() == 1;
118}
119
120/*! @brief renvoie mon rang dans le groupe de communication courant.
121 *
122 * Voir Comm_Group::rank() et PE_Groups::current_group()
123 *
124 */
126{
127 const int r = PE_Groups::current_group().rank();
128 return r;
129}
130
131/*! @brief Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a la barriere)
132 *
133 * Instruction a executer sur tous les processeurs du groupe.
134 *
135 */
140
141
142/*! @brief Calcule la somme de x sur tous les processeurs du groupe courant.
143 *
144 * @sa mp_max()
145 */
146double Process::mp_sum(double x)
147{
149 double y;
151 return y;
152}
153
154float Process::mp_sum(float x)
155{
157 float y;
159 return y;
160}
161
162/*! @brief Calcule la somme de x sur tous les processeurs du groupe courant.
163 *
164 * !!! Note that the sum of many int might result in a long !!!
165 *
166 * @sa mp_max()
167 */
168trustIdType Process::mp_sum(trustIdType x)
169{
171 trustIdType y;
173 return y;
174}
175
176template<typename _TYPE_>
177void mp_collective_op_arr(TRUSTArray<_TYPE_>& x, Comm_Group::Collective_Op op, int n)
178{
179 int sz = n==-1 ? x.size_array() : n;
180 assert_parallel<_TYPE_>(sz);
181 if (sz > 0)
182 {
183 _TYPE_ *data = x.addr();
184 _TYPE_ *tmp = new _TYPE_[sz];
186 grp.mp_collective_op(data, tmp, sz, op);
187 memcpy(data, tmp, sz * sizeof(_TYPE_));
188 delete[] tmp;
189 }
190}
191
192template<typename _TYPE_>
193void Process::mp_sum_for_each_item(TRUSTArray<_TYPE_>& x, int n) { mp_collective_op_arr(x, Comm_Group::COLL_SUM, n); }
194
195template<typename _TYPE_>
196void Process::mp_max_for_each_item(TRUSTArray<_TYPE_>& x, int n) { mp_collective_op_arr(x, Comm_Group::COLL_MAX, n); }
197
198template<typename _TYPE_>
199void Process::mp_min_for_each_item(TRUSTArray<_TYPE_>& x, int n) { mp_collective_op_arr(x, Comm_Group::COLL_MIN, n); }
200
201/*! @brief C++14 compatible mp_sum_for_each: combine multiple mp_sum calls into one collective operation
202 * Usage: mp_sum_for_each(a, b); mp_sum_for_each(a, b, c); mp_sum_for_each(a, b, c, d); mp_sum_for_each(a, b, c, d, e);
203 * All arguments must be of the same type (double or int) and are modified in place.
204 * Supports 2-5 parameters.
205 */
206template<typename T>
207void Process::mp_sum_for_each(T& arg1, T& arg2)
208{
209 T data[2] = {arg1, arg2};
210 T tmp[2];
212 grp.mp_collective_op(data, tmp, 2, Comm_Group::COLL_SUM);
213 arg1 = tmp[0];
214 arg2 = tmp[1];
215}
216
217template<typename T>
218void Process::mp_sum_for_each(T& arg1, T& arg2, T& arg3)
219{
220 T data[3] = {arg1, arg2, arg3};
221 T tmp[3];
223 grp.mp_collective_op(data, tmp, 3, Comm_Group::COLL_SUM);
224 arg1 = tmp[0];
225 arg2 = tmp[1];
226 arg3 = tmp[2];
227}
228
229template<typename T>
230void Process::mp_sum_for_each(T& arg1, T& arg2, T& arg3, T& arg4)
231{
232 T data[4] = {arg1, arg2, arg3, arg4};
233 T tmp[4];
235 grp.mp_collective_op(data, tmp, 4, Comm_Group::COLL_SUM);
236 arg1 = tmp[0];
237 arg2 = tmp[1];
238 arg3 = tmp[2];
239 arg4 = tmp[3];
240}
241
242/*! @brief C++14 compatible mp_max_for_each: combine multiple mp_max calls into one collective operation */
243template<typename T>
244void Process::mp_max_for_each(T& arg1, T& arg2)
245{
246 T data[2] = {arg1, arg2};
247 T tmp[2];
249 grp.mp_collective_op(data, tmp, 2, Comm_Group::COLL_MAX);
250 arg1 = tmp[0];
251 arg2 = tmp[1];
252}
253
254template<typename T>
255void Process::mp_max_for_each(T& arg1, T& arg2, T& arg3)
256{
257 T data[3] = {arg1, arg2, arg3};
258 T tmp[3];
260 grp.mp_collective_op(data, tmp, 3, Comm_Group::COLL_MAX);
261 arg1 = tmp[0];
262 arg2 = tmp[1];
263 arg3 = tmp[2];
264}
265
266template<typename T>
267void Process::mp_max_for_each(T& arg1, T& arg2, T& arg3, T& arg4)
268{
269 T data[4] = {arg1, arg2, arg3, arg4};
270 T tmp[4];
272 grp.mp_collective_op(data, tmp, 4, Comm_Group::COLL_MAX);
273 arg1 = tmp[0];
274 arg2 = tmp[1];
275 arg3 = tmp[2];
276 arg4 = tmp[3];
277}
278
279/*! @brief C++14 compatible mp_min_for_each: combine multiple mp_min calls into one collective operation */
280template<typename T>
281void Process::mp_min_for_each(T& arg1, T& arg2)
282{
283 T data[2] = {arg1, arg2};
284 T tmp[2];
286 grp.mp_collective_op(data, tmp, 2, Comm_Group::COLL_MIN);
287 arg1 = tmp[0];
288 arg2 = tmp[1];
289}
290
291template<typename T>
292void Process::mp_min_for_each(T& arg1, T& arg2, T& arg3)
293{
294 T data[3] = {arg1, arg2, arg3};
295 T tmp[3];
297 grp.mp_collective_op(data, tmp, 3, Comm_Group::COLL_MIN);
298 arg1 = tmp[0];
299 arg2 = tmp[1];
300 arg3 = tmp[2];
301}
302
303template<typename T>
304void Process::mp_min_for_each(T& arg1, T& arg2, T& arg3, T& arg4)
305{
306 T data[4] = {arg1, arg2, arg3, arg4};
307 T tmp[4];
309 grp.mp_collective_op(data, tmp, 4, Comm_Group::COLL_MIN);
310 arg1 = tmp[0];
311 arg2 = tmp[1];
312 arg3 = tmp[2];
313 arg4 = tmp[3];
314}
315
316// 5-parameter versions
317template<typename T>
318void Process::mp_sum_for_each(T& arg1, T& arg2, T& arg3, T& arg4, T& arg5)
319{
320 T data[5] = {arg1, arg2, arg3, arg4, arg5};
321 T tmp[5];
323 grp.mp_collective_op(data, tmp, 5, Comm_Group::COLL_SUM);
324 arg1 = tmp[0];
325 arg2 = tmp[1];
326 arg3 = tmp[2];
327 arg4 = tmp[3];
328 arg5 = tmp[4];
329}
330
331template<typename T>
332void Process::mp_max_for_each(T& arg1, T& arg2, T& arg3, T& arg4, T& arg5)
333{
334 T data[5] = {arg1, arg2, arg3, arg4, arg5};
335 T tmp[5];
337 grp.mp_collective_op(data, tmp, 5, Comm_Group::COLL_MAX);
338 arg1 = tmp[0];
339 arg2 = tmp[1];
340 arg3 = tmp[2];
341 arg4 = tmp[3];
342 arg5 = tmp[4];
343}
344
345template<typename T>
346void Process::mp_min_for_each(T& arg1, T& arg2, T& arg3, T& arg4, T& arg5)
347{
348 T data[5] = {arg1, arg2, arg3, arg4, arg5};
349 T tmp[5];
351 grp.mp_collective_op(data, tmp, 5, Comm_Group::COLL_MIN);
352 arg1 = tmp[0];
353 arg2 = tmp[1];
354 arg3 = tmp[2];
355 arg4 = tmp[3];
356 arg5 = tmp[4];
357}
358
359namespace
360{
361
362template <typename T>
363T mp_operations_commun_(T x, Comm_Group::Collective_Op op)
364{
366 T y;
367 grp.mp_collective_op(&x, &y, 1, op);
368 return y;
369}
370}
371
372/*! @brief renvoie le plus grand int i sur l'ensemble des processeurs du groupe courant.
373 *
374 */
375int Process::mp_max(int x) { return mp_operations_commun_(x,Comm_Group::COLL_MAX); }
376double Process::mp_max(double x) { return mp_operations_commun_(x,Comm_Group::COLL_MAX); }
377#if INT_is_64_ == 2
378trustIdType Process::mp_max(trustIdType x) { return mp_operations_commun_(x,Comm_Group::COLL_MAX); }
379#endif
380
381
382/*! @brief renvoie le plus petit int i sur l'ensemble des processeurs du groupe courant.
383 *
384 */
385int Process::mp_min(int x) { return mp_operations_commun_(x,Comm_Group::COLL_MIN); }
386double Process::mp_min(double x) { return mp_operations_commun_(x,Comm_Group::COLL_MIN); }
387#if INT_is_64_ == 2
388trustIdType Process::mp_min(trustIdType x) { return mp_operations_commun_(x,Comm_Group::COLL_MIN); }
389#endif
390
391/*! @brief Calul de la somme partielle de i sur les processeurs 0 a me()-1 (renvoie 0 sur le processeur 0).
392 *
393 * Voir Comm_Group::mppartial_sum()
394 *
395 */
396trustIdType Process::mppartial_sum(trustIdType x)
397{
399 trustIdType xx = x;
400 trustIdType y;
401
403 return y;
404}
405
406/*! @brief Calcule le 'et' logique de b sur tous les processeurs du groupe courant.
407 *
408 */
409bool Process::mp_and(bool b)
410{
412 int x = b ? 1 : 0;
413 int y;
415 return y == 1;
416}
417
418bool Process::mp_or(bool b)
419{
421 int x = b ? 1 : 0;
422 int y;
424 return y == 1;
425}
426
427
429{
430 if (v >= std::numeric_limits<int>::max())
431 Process::exit("Value too big - above 32b and can not be converted to int!!");
432 return static_cast<int>(v);
433}
434
435/*! @brief Routine de sortie de TRUST dans une region Kokkos
436 *
437 */
438/*
439KOKKOS_FUNCTION
440void Process::Kokkos_exit(const char* str)
441{
442#ifdef TRUST_USE_GPU
443 // ToDo Kokkos: try to exit more properly on device...
444 Kokkos::abort(str);
445 //Kokkos::finalize();
446#else
447 Process::exit(str);
448#endif
449}*/
450
451/*! @brief Routine de sortie de TRUST sur une erreur.
452 *
453 * Sauvegarde la memoire et de la hierarchie dans les fichiers "memoire.dump" et "hierarchie.dump"
454 */
455void Process::exit(int i)
456{
457 Nom message="=========================================\nTRUST has caused an error and will stop.\nUnexpected error during TRUST calculation.";
458 std::string jddLine = "\nError triggered at line " + std::to_string(EChaineJDD::file_cur_line_) + " in " + Objet_U::nom_du_cas().getString() + ".data";
459 message+=jddLine;
460 exit(message,i);
461}
462void Process::exit(const Nom& message ,int i)
463{
464 if (exception_sur_exit == 2)
465 {
466 ::exit(-1); // ND 11/01/23 utilisation d'un second ::exit(-1) dans TRUST car si pas droits d'ecriture appel recursif a Process::exit()
467 }
468
469 if(je_suis_maitre())
470 {
471 Cerr << message << finl;
472 Cerr.flush();
473 // Utile pour XData et la creation de syno.py
474 if (getenv("TRUST_USE_XDATA")!=nullptr)
475 {
476 SFichier hier("hierarchie.dump");
477 hier << "\n KEYWORDS\n";
479 hier << "\n SYNONYMS\n";
481 }
482 if (!get_disable_stop() && Process::je_suis_maitre())
483 {
484 Nom nomfic( Objet_U::nom_du_cas() );
485 nomfic += ".stop";
486 {
487 SFichier ficstop( nomfic );
488 ficstop <<message<<finl;
489 }
490 }
491 }
492 Journal() << message << finl;
493
495 {
496 // Lancement d'une exception (utilise par Execute_parallel)
497 throw TRUST_Error("Error in trust ",Process::me());
498 }
499 else
500 {
501 int abort=0;
502#ifdef MPI_
504 {
505 // user defined groups (if any !)
507 {
509 if (sub_type(Comm_Group_MPI,grp))
510 ref_cast_non_const(Comm_Group_MPI,grp).free_all(); // free comm + group
511 }
512
513 const MPI_Comm& mpi_comm=ref_cast(Comm_Group_MPI,PE_Groups::groupe_TRUST()).get_mpi_comm();
514 int tag = 666;
515 int buffer[1]= {1};
516 MPI_Request request;
517
518 // Envoi non bloquant vers me()+1
519 int to_pe = (me()==nproc()-1?0:me()+1);
520 MPI_Isend(buffer, 1, MPI_ENTIER, to_pe, tag, mpi_comm, &request);
521
522 // Reception non bloquante depuis me()-1
523 int from_pe = (me()==0?nproc()-1:me()-1);
524 MPI_Irecv(buffer, 1, MPI_ENTIER, from_pe, tag, mpi_comm, &request);
525
526 // Attente
527 sleep(1);
528
529 // Test si me() a recu de me()-1
530 int ok;
531 MPI_Status status;
532 MPI_Test(&request,&ok,&status);
533 if (!ok)
534 abort=1;
535 }
536#endif
537 if (abort)
538 {
539 if (!je_suis_maitre())
540 {
541 std_err_ << "!!! TRUST process number " << Process::me() << " exited unexpectedly ! See error message at the end of the file " << journal_file_name_ << " -> Aborting calculation..." << finl;
542 }
544 }
545 else
546 {
547#ifdef MPI_
548 // On MPI_Finalize si MPI_Initialized and not MPI_Finalized
549 int flag;
550 MPI_Initialized(&flag);
551 if (flag)
552 {
553 MPI_Finalized(&flag);
554 if (!flag)
555 MPI_Finalize();
556 }
557#endif
559 }
560 }
561 // Kokkos::finalize();
562 // On force exit();
563 if (i==0) i=-1;
564 ::exit(i); //Seul ::exit utilise dans le code jusqu'a 01/23. second ajoute car appel recursif a Process::exit si droits ecriture dossier etude manquants
565}
566
567/*! @brief Routine de sortie de Trio-U sur une erreur abort()
568 *
569 */
571{
572#ifdef NDEBUG
573 // En optimise on sort proprement.
574 exit();
575#else
576 // En debug, on sort brutal pour avoir des infos avec le debugger ?
577 ::abort(); //Seul ::abort() utilise dans le code
578#endif
579}
580
581/*! @brief Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
582 *
583 * Si message_level <= verbose_level_, on ecrit le message, sinon
584 * on l'envoie sur une Sortie_Nulle.
585 * Si le fichier journal est ouvert, on ecrit dans le fichier, sinon dans stderr.
586 *
587 */
588Sortie& Process::Journal(int message_level)
589{
590 if (message_level <= verbose_level_ && verbose_level_ > 0)
591 {
592 if (journal_file_open_)
593 return journal_file_;
594 else
595 return std_err_;
596 }
597 return journal_zero_;
598}
599
600// Renvoie la ram occupee par un processeur
602{
603#ifdef PETSCKSP_H
604 PetscLogDouble memoire;
605 PetscMemoryGetCurrentUsage(&memoire);
606 return memoire;
607#else
608 return 0;
609#endif
610}
611#include <sys/resource.h>
612double ru_maxrss()
613{
614 // Best to track OOM
615 struct rusage usage;
616 getrusage(RUSAGE_SELF, &usage);
617 // ru_maxrss is in kilobytes
618 long rss_kb = usage.ru_maxrss;
619 return static_cast<double>(rss_kb*1024);
620}
621
622#ifndef __APPLE__
623#include <malloc.h>
624
625/*
626struct mallinfo2 {
627 size_t hblkhd; // Space in mmapped regions (bytes)
628 size_t hblks; // Number of mmapped regions
629 size_t usmblks; // Always 0 (obsolete field)
630 size_t fsmblks; // Always 0 (obsolete field)
631 size_t uordblks; // Total allocated space (bytes)
632 size_t fordblks; // Total free space (bytes)
633 size_t keepcost; // Top-most, releasable space (bytes)
634};
635*/
636double heap_allocation()
637{
638 // Best to track memory leak
639#if defined(__GLIBC__) && __GLIBC_PREREQ(2, 33)
640 struct mallinfo2 info = mallinfo2();
641#else
642 struct mallinfo info = mallinfo();
643#endif
644 return (double)info.uordblks;
645}
646
647static double heap_allocated_old=0;
648
649#endif /* ndef __APPLE__ */
650
651void Process::imprimer_ram_totale(int all_process)
652{
653 double memoire;
654 //memoire = ram_processeur();
655 memoire = ru_maxrss();
656
657#ifndef __APPLE__
658 double heap_allocated = heap_allocation();
659#endif
660
661 if (memoire)
662 {
663 //Cout << "RAM provisoire: PETSc " << ram_processeur() << " ru_maxrss " << memoire << " mallinfo " << heap_allocated << finl;
664 int Mo=1024*1024;
665 if (all_process) Journal() << (int)(memoire/Mo) << " MBytes of RAM taken by the processor " << Process::me() << finl;
666 {
667 double max_memoire=Process::mp_max(memoire);
668 double total_memoire=Process::mp_sum(memoire);
669 Cout << (int)(total_memoire/Mo) << " MBytes of RAM taken by the calculation (max on a rank: "<<(int)(max_memoire/Mo)<<" MB)." << finl;
670#ifndef __APPLE__
671 Cout << "[RAM] Allocated heap on master rank: " << (int)(heap_allocated/Mo) << " Mbytes";
672 double delta = heap_allocated - heap_allocated_old;
673 if (delta!=0 && heap_allocated_old>0) Cout << " (" << (delta>0 ? "+" : "") << (long)delta << " bytes)";
674 Cout << finl;
675 heap_allocated_old = heap_allocated;
676#ifdef TRUST_USE_GPU
677 int Go = 1024 * Mo;
678 double allocated = mp_max((double)DeviceMemory::allocatedBytesOnDevice());
679 double total = static_cast<double>(DeviceMemory::deviceMemGetInfo(1));
680 Cout << 0.1*(int)(10*allocated/Go) << " GBytes of maximal RAM allocated on a GPU (" << int(100 * allocated / total) << "%)" << finl;
681#endif
682#endif /* ndef __APPLE__ */
683 }
684#ifdef TRUST_USE_ROCM /* Seulement sur adastra */
685 // sUnreclaim sur chaque process:
686 std::ifstream meminfo("/proc/meminfo");
687 std::string line;
688 size_t sunreclaim_kb = 0;
689 size_t mem_available_kb = 0;
690 size_t mem_total_kb = 0;
691 while (std::getline(meminfo, line))
692 {
693 if (line.substr(0, 9) == "MemTotal:")
694 {
695 size_t pos = line.find_first_of("0123456789");
696 mem_total_kb = std::stoull(line.substr(pos));
697 }
698 if (line.substr(0, 13) == "MemAvailable:")
699 {
700 size_t pos = line.find_first_of("0123456789");
701 mem_available_kb = std::stoull(line.substr(pos));
702 }
703 if (line.substr(0, 11) == "SUnreclaim:")
704 {
705 size_t pos = line.find_first_of("0123456789");
706 sunreclaim_kb = std::stoull(line.substr(pos));
707 break;
708 }
709 }
710 Process::Journal() << "[RAM] SUnreclaim: " << sunreclaim_kb/1024 << " MB MemAvailable: " << mem_available_kb/1024 << " MB MemTotal: " << mem_total_kb/1024 << " MB " << finl;
711#endif
712 }
713}
714
715/*! @brief Initialisation du journal
716 *
717 * @param (verbose_level) les messages de niveau <= verbose_level seront affiches, les autres seront mis a la poubelle.
718 * @param (file_name) si pointeur nul, tout le monde ecrit dans cerr, sinon c'est le nom du fichier (doit etre different sur chaque processeur)
719 * @param (append) indique si on ouvre le fichier en mode append ou pas.
720 */
721void init_journal_file(int verbose_level, const char * file_name, int append)
722{
723 end_journal(verbose_level);
724
725 if (verbose_level > 0)
726 {
727 if (file_name)
728 {
729 IOS_OPEN_MODE mode = ios::out;
730 if (append)
731 mode = ios::app;
732 if (!journal_file_.ouvrir(file_name, mode))
733 {
734 Cerr << "Fatal error in init_journal_file: cannot open journal file" << finl;
736 }
737
738 journal_file_open_ = 1;
739 journal_file_name_ = file_name;
740 }
741 }
742 verbose_level_ = verbose_level;
743}
744
745void end_journal(int verbose_level)
746{
747 // Attention: acrobatie pour que ca "plante proprement" si le destructeur
748 // ecrit dans le journal !
749 journal_file_.close();
750 journal_file_open_ = 0;
751}
752
753/*! @brief Renvoie l'objet Sortie sur lequel seront redirigees les objets ecrits dans Cerr.
754 *
755 * Cela peut etre std_err_ ou journal_file_
756 *
757 */
758Sortie& get_Cerr()
759{
760 if (journal_file_open_ && cerr_to_journal_)
761 return journal_file_;
762 else
763 {
764 // dans le cas ou on a pas initialise les groupes
765 // on ne peut pas tester si on est maitre
767 return std_err_;
768 // Seul le processeur maitre ecrit sur std_err_, les autres ecrivent sur journal_file_
770 return std_err_;
771 else if (verbose_level_)
772 return journal_file_;
773 else
774 return journal_zero_;
775 }
776}
777
778/*! @brief Si on est sur le maitre, on renvoie cout ou le fichier journal sinon journal_zero_.
779 *
780 * @sa cerr_to_journal_
781 *
782 */
783Sortie& get_Cout()
784{
786 {
787 if (journal_file_open_ && cerr_to_journal_)
788 return journal_file_;
789 else
790 return std_out_;
791 }
792 else
793 {
794 return journal_zero_;
795 }
796}
797
798/*! @brief change la destination de Cerr et Cout Si flag=0, c'est stderr et stdout, sinon, si le fichier
799 *
800 * journal est ouvert, c'est le journal, sinon c'est
801 * Sortie_Nulle
802 *
803 */
804void set_Cerr_to_journal(int flag)
805{
806 cerr_to_journal_ = flag;
807}
808
809int get_journal_level()
810{
811 return verbose_level_;
812}
813
814void change_journal_level(int level)
815{
816 verbose_level_ = level;
817}
818
819/*! @brief Returns the disable_stop_ flag (Disable or not the writing of the .
820 *
821 * stop file)
822 *
823 */
824int get_disable_stop()
825{
826 return disable_stop_;
827}
828
829/*! @brief Affects a new value to disable_stop_ flag (Disable or not the writing of the .
830 *
831 * stop file)
832 *
833 */
834void change_disable_stop(int new_stop)
835{
836 disable_stop_ = new_stop;
837}
838
839// Explicit template instantiations for mp_*_for_each_item
847
848// Explicit template instantiations for mp_*_for_each (C++14 overloads)
849// mp_sum_for_each
850template void Process::mp_sum_for_each<double>(double&, double&);
851template void Process::mp_sum_for_each<double>(double&, double&, double&);
852template void Process::mp_sum_for_each<double>(double&, double&, double&, double&);
853template void Process::mp_sum_for_each<double>(double&, double&, double&, double&, double&);
854template void Process::mp_sum_for_each<int>(int&, int&);
855template void Process::mp_sum_for_each<int>(int&, int&, int&);
856template void Process::mp_sum_for_each<int>(int&, int&, int&, int&);
857template void Process::mp_sum_for_each<int>(int&, int&, int&, int&, int&);
858// mp_max_for_each
859template void Process::mp_max_for_each<double>(double&, double&);
860template void Process::mp_max_for_each<double>(double&, double&, double&);
861template void Process::mp_max_for_each<double>(double&, double&, double&, double&);
862template void Process::mp_max_for_each<double>(double&, double&, double&, double&, double&);
863template void Process::mp_max_for_each<int>(int&, int&);
864template void Process::mp_max_for_each<int>(int&, int&, int&);
865template void Process::mp_max_for_each<int>(int&, int&, int&, int&);
866template void Process::mp_max_for_each<int>(int&, int&, int&, int&, int&);
867// mp_min_for_each
868template void Process::mp_min_for_each<double>(double&, double&);
869template void Process::mp_min_for_each<double>(double&, double&, double&);
870template void Process::mp_min_for_each<double>(double&, double&, double&, double&);
871template void Process::mp_min_for_each<double>(double&, double&, double&, double&, double&);
872template void Process::mp_min_for_each<int>(int&, int&);
873template void Process::mp_min_for_each<int>(int&, int&, int&);
874template void Process::mp_min_for_each<int>(int&, int&, int&, int&);
875template void Process::mp_min_for_each<int>(int&, int&, int&, int&, int&);
: Classe Comm_Group_MPI, derivee de la classe abstraite Comm_Group.
: Cette classe decrit un groupe de processeurs sur lesquels
Definition Comm_Group.h:40
@ COLL_PARTIAL_SUM
Definition Comm_Group.h:52
int nproc() const
Renvoie le nombre de processeurs dans le groupe *this.
Definition Comm_Group.h:190
int rank() const
Renvoie le rang du processeur local dans le groupe *this.
Definition Comm_Group.h:182
virtual void abort() const =0
virtual void mp_collective_op(const double *x, double *resu, int n, Collective_Op op) const =0
virtual void barrier(int tag) const =0
static int file_cur_line_
Definition EChaineJDD.h:45
class Nom Une chaine de caractere pour nommer les objets de TRUST
Definition Nom.h:31
const std::string & getString() const
Definition Nom.h:92
static const Nom & nom_du_cas()
Renvoie une reference constante vers le nom du cas.
Definition Objet_U.cpp:146
static const int & get_nb_groups()
static void finalize()
Methode a appeler en fin d'execution, une fois qu'on est revenu dans le groupe_TRUST() et juste avant...
static const Comm_Group & get_user_defined_group()
Renvoie une reference au groupe sur defini par l'utilisateur.
static const Comm_Group & get_node_group()
Renvoie une reference au groupe sur les noeuds.
static bool has_user_defined_group()
static const Comm_Group & current_group()
renvoie une reference au groupe de processeurs actif courant
Definition PE_Groups.h:65
static const Comm_Group & groupe_TRUST()
Renvoie une reference au groupe de tous les processeurs TRUST.
static void mp_max_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:196
static double mp_min(double)
Definition Process.cpp:386
static int check_int_overflow(trustIdType)
Definition Process.cpp:428
static void mp_sum_for_each(T &arg1, T &arg2)
C++14 compatible mp_sum_for_each: combine multiple mp_sum calls into one collective operation Usage: ...
Definition Process.cpp:207
static double ram_processeur()
Definition Process.cpp:601
static trustIdType mppartial_sum(trustIdType i)
Calul de la somme partielle de i sur les processeurs 0 a me()-1 (renvoie 0 sur le processeur 0).
Definition Process.cpp:396
static int multiple_files
Definition Process.h:164
static double mp_max(double)
Definition Process.cpp:376
static void mp_sum_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:193
static bool mp_or(bool)
Definition Process.cpp:418
static int node_master()
renvoie 1 si on est sur le processeur maitre du noeud numa, 0 sinon.
Definition Process.cpp:95
static bool is_parallel()
Definition Process.cpp:110
static Sortie & Journal(int message_level=0)
Renvoie un objet statique de type Sortie qui sert de journal d'evenements.
Definition Process.cpp:588
static void abort()
Routine de sortie de Trio-U sur une erreur abort().
Definition Process.cpp:570
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static void mp_max_for_each(T &arg1, T &arg2)
C++14 compatible mp_max_for_each: combine multiple mp_max calls into one collective operation.
Definition Process.cpp:244
static void imprimer_ram_totale(int all_process=0)
Definition Process.cpp:651
static void barrier()
Synchronise tous les processeurs du groupe courant (attend que tous les processeurs soient arrives a ...
Definition Process.cpp:136
static bool force_single_file(const int ranks, const Nom &filename)
Definition Process.cpp:60
static void mp_min_for_each(T &arg1, T &arg2)
C++14 compatible mp_min_for_each: combine multiple mp_min calls into one collective operation.
Definition Process.cpp:281
static int exception_sur_exit
Definition Process.h:163
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
static void mp_min_for_each_item(TRUSTArray< _TYPE_ > &x, int n=-1)
Definition Process.cpp:199
static bool is_sequential()
Definition Process.cpp:115
static bool mp_and(bool)
Calcule le 'et' logique de b sur tous les processeurs du groupe courant.
Definition Process.cpp:409
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
Classe derivee de Sortie qui ne sort les donnees nulle part (c'est une poubelle) Classe utilisee dans...
Classe de base des flux de sortie.
Definition Sortie.h:52
static Sortie & hierarchie(Sortie &)
Ecriture de toute la hierarchie du synonyme considere sur un flux de sortie.
Represents a an array of int/int64/double/... values.
Definition TRUSTArray.h:81
_SIZE_ size_array() const
_TYPE_ * addr()
classe TRUST_Error
Definition TRUST_Error.h:25
static Sortie & hierarchie(Sortie &)
Ecriture de toute la hierarchie du type considere sur un flix de sortie.
static size_t allocatedBytesOnDevice()
static size_t deviceMemGetInfo(bool)