TrioCFD 1.9.9_beta
TrioCFD documentation
Loading...
Searching...
No Matches
Execute_parallel.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 <LecFicDiffuse_JDD.h>
17#include <Execute_parallel.h>
18#include <Interprete_bloc.h>
19#include <TRUST_Error.h>
20#include <TRUSTArray.h>
21#include <PE_Groups.h>
22#include <Journal.h>
23#include <Param.h>
24
25Implemente_instanciable(Execute_parallel,"Execute_parallel",Interprete);
26// XD execute_parallel interprete execute_parallel BRACE This keyword allows to run several computations in parallel on
27// XD_CONT processors allocated to TRUST. The set of processors is split in N subsets and each subset will read and
28// XD_CONT execute a different data file. Error messages usualy written to stderr and stdout are redirected to .log
29// XD_CONT files (journaling must be activated).
30
32{
33 Cerr << "Execute_parallel::readOn() not coded" << finl;
34 exit();
35 return is;
36}
37
39{
40 Cerr << "Execute_parallel::printOn() not coded" << finl;
41 exit();
42 return os;
43}
44
45/*! @brief Creates a partition of the nproc processors for the computation in order to interpret N different data sets.
46 *
47 * The syntax of the data set is as follows:
48 * Execute_parallel {
49 * liste_cas N cas1 cas2 cas3 ...
50 * [ nb_procs N nproc1 nproc2 nproc3 ... ]
51 * }
52 * "cas1" is the name of the case (the file cas1.data is read from disk)
53 * nproc1 is the number of processors to use for that case
54 * By default, 1 processor is used for each case
55 * Cerr and Cout outputs are redirected to the journal of the master
56 * processor of each case.
57 *
58 */
60{
61 Cerr << "Execute_parallel::interpreter to run several cases:" << finl;
62
63 Noms liste_cas;
64 ArrOfInt nb_procs;
65
66 bool disable_journal = false;
67
68 Param param(que_suis_je());
69 param.ajouter("liste_cas", &liste_cas, Param::REQUIRED); // XD_ADD_P listchaine
70 // XD_CONT N datafile1 ... datafileN. datafileX the name of a TRUST data file without the .data extension.
71 param.ajouter("nb_procs", &nb_procs); // XD_ADD_P listentier
72 // XD_CONT nb_procs is the number of processors needed to run each data file. If not given, TRUST assumes that
73 // XD_CONT computations are sequential.
74 param.ajouter_flag("disable_journal", &disable_journal);
76 // If nb_procs was not given, assume it is 1
77 const int n_calculs = liste_cas.size();
78 if (nb_procs.size_array() == 0)
79 {
80 Cerr << "Nb_procs not given, we assume that calculations are sequential."
81 << finl;
82 nb_procs.resize_array(n_calculs);
83 nb_procs = 1;
84 }
85 // Verify array sizes
86 if (nb_procs.size_array() != n_calculs)
87 {
88 Cerr << "Error : nb_procs array must have " << n_calculs
89 << " values." << finl;
90 barrier();
91 exit();
92 }
93 if (n_calculs == 0)
94 return is;
95
96 // Verify the content:
97 if (min_array(nb_procs) < 1)
98 {
99 Cerr << "Error : processor numbers must be >= 1" << finl;
100 barrier();
101 exit();
102 }
103 int count = 0;
104 for (int i = 0; i < n_calculs; i++)
105 count += nb_procs[i];
106 if (count > nproc())
107 {
108 Cerr << "Error : computations require " << count << " processors." << finl;
109 Cerr << "but only " << nproc() << " processors has been asked." << finl;
110 barrier();
111 exit();
112 }
113
114 // Create the N processor groups
115 // (groups are destroyed when the VECT is destroyed)
116 VECT(OWN_PTR(Comm_Group)) groupes(n_calculs);
117 count = 0;
118 Nom log_courant("");
119 for (int i = 0; i < n_calculs; i++)
120 {
121 const int n = nb_procs[i];
122 Nom log("");
123 Nom log1(Objet_U::nom_du_cas());
124 log1+="_";
125 char s[20];
126 snprintf(s, 20, "%05d", (int)count);
127 log1+=s;
128 log1+=".log";
129 if (n==1)
130 {
131 log+=log1;
132 log+=" file";
133 }
134 else
135 {
136 Nom log2(Objet_U::nom_du_cas());
137 log2+="_";
138 char s2[20];
139 snprintf(s2, 20, "%05d", (int)(count+n-1));
140 log2+=s2;
141 log2+=".log";
142 log="log files from ";
143 log+=log1;
144 log+=" to ";
145 log+=log2;
146 }
147 Cerr << "Error and standard outputs are redirected into " << log << " for case " << liste_cas[i] << finl;
148 // Store in log_courant as it is reused later
149 if (Process::me()>=count && Process::me()<=count+n-1)
150 log_courant=log;
151
152 ArrOfInt tab(n);
153 for (int j = 0; j < n; j++)
154 tab[j] = count++;
155 PE_Groups::create_group(tab, groupes[i]);
156 }
157 // Throw an exception if a computation stops, so
158 // change the default Process behaviour (MPI_Abort)
160 Cerr << n_calculs << " cases are running..." << finl;
161 // Each processor enters its group and interprets the data set
162 Nom ancien_nom_du_cas(nom_du_cas());
163 const int old_journal_level = get_journal_level();
164 for (int i = 0; i < n_calculs; i++)
165 {
166 if (PE_Groups::enter_group(groupes[i].valeur()))
167 {
168 set_Cerr_to_journal(1);
169 if (disable_journal)
170 change_journal_level(0);
171 Nom nom_fichier(liste_cas[i]);
172 get_set_nom_du_cas() = nom_fichier;
173 Journal(1) << "Execute_parallel: Entering subgroup " << i
174 << " to run case " << nom_fichier << finl;
175
176 nom_fichier += ".data";
177 {
178 // Open the file (the LecFicDiffuse object is created inside
179 // the braces so it is destroyed before exiting the group)
180 LecFicDiffuse_JDD data_file(nom_fichier);
181 data_file.set_check_types(1);
182 // Create a new interpreter. At the end of reading the case,
183 // the objects will be destroyed.
184 Interprete_bloc interp;
185 // Use exceptions for computations that stop
186 int ok=1;
187 try
188 {
189 interp.interpreter_bloc(data_file,
190 Interprete_bloc::FIN /* we expect FIN at the end of the file */,
191 0 /* verifie_sans_interpreter=0 */);
192 }
193 catch (TRUST_Error& err)
194 {
195 if (err.get_pe()!=Process::me())
196 {
197 Cerr << err.get_pe() << " <> " << Process::me() << " in Execute_parallel::interpreter." << finl;
199 }
200 ok=0;
201 }
202 set_Cerr_to_journal(0);
203 if (ok)
204 Cerr << "Case " << liste_cas[i] << " has finished. See " << log_courant << finl;
205 else
206 Cerr << "!!! Case " << liste_cas[i] << " has failed. See " << log_courant << " !!!" << finl;
207 }
208 Journal(1) << "Execute_parallel: Exiting subgroup " << i << finl;
210 }
211 }
212 // return to the standard behaviour
214 change_journal_level(old_journal_level);
215 // Wait for all processors to finish executing their computation.
216 barrier();
217 get_set_nom_du_cas() = ancien_nom_du_cas;
218 Cerr << finl << "End of Execute_parallel::interpreter" << finl;
219 return is;
220}
: This class describes a group of processors on which
Definition Comm_Group.h:37
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
Interpreter allowing the simultaneous execution of several data files.
Entree & interpreter(Entree &) override
Creates a partition of the nproc processors for the computation in order to interpret N different dat...
Interprets a block of instructions in the data set.
Entree & interpreter_bloc(Entree &is, Bloc_Type bloc_type, int verifier_sans_interpreter)
Interprets a block of instructions read from input is.
Base class for "interpreter" objects.
Definition Interprete.h:38
This class implements the operators and virtual methods of the EFichier class as follows: The file to...
void set_check_types(bool flag) override
Calls get_entree_master().
class Nom: a character string for naming TRUST objects.
Definition Nom.h:31
An array of character strings (VECT(Nom)).
Definition Noms.h:26
friend class Entree
Definition Objet_U.h:71
const Nom & que_suis_je() const
Returns the string identifying the class.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Reads an Objet_U from an input stream. Virtual method to override.
Definition Objet_U.cpp:289
static const Nom & nom_du_cas()
Returns a constant reference to the case name. This method is static.
Definition Objet_U.cpp:145
static Nom & get_set_nom_du_cas()
Returns a non-constant reference to the case name (to allow modification). This method is static.
Definition Objet_U.cpp:154
virtual Sortie & printOn(Sortie &) const
Writes the object to an output stream. Virtual method to override.
Definition Objet_U.cpp:278
static int enter_group(const Comm_Group &group)
If the local processor belongs to the group, the current group for this processor becomes "group" and...
static void create_group(const ArrOfInt &liste_pe, OWN_PTR(Comm_Group) &group, int force_Comm_Group_NoParallel=0)
Creates a new processor group (can be called anywhere in the code).
Definition PE_Groups.cpp:55
static void exit_group()
Returns to the group that was active before the last successful enter_group() call (which returned 1)...
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
void ajouter_flag(const char *keyword, const bool *value)
Register a boolean flag whose mere presence switches it to true.
Definition Param.cpp:474
void ajouter(const char *keyword, const int *value, Param::Nature nat=Param::OPTIONAL)
Register an integer parameter.
Definition Param.cpp:364
@ REQUIRED
Definition Param.h:115
int lire_avec_accolades_depuis(Entree &is)
Parse the parameter block { ... } from is.
Definition Param.cpp:32
static Sortie & Journal(int message_level=0)
Returns a static Sortie object used as an event journal.
Definition Process.cpp:592
static int nproc()
Returns the number of processors in the current group. See Comm_Group::nproc() and PE_Groups::current...
Definition Process.cpp:102
static void barrier()
Synchronizes all processors in the current group (waits until all processors have reached the barrier...
Definition Process.cpp:133
static int exception_sur_exit
Definition Process.h:161
static int me()
Returns the rank of the local processor in the current communication group. See Comm_Group::rank() an...
Definition Process.cpp:122
static void exit(int exit_code=-1)
Exit routine for TRUST within a Kokkos region.
Definition Process.cpp:466
Base class for output streams.
Definition Sortie.h:52
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)
TRUST_Error class.
Definition TRUST_Error.h:25
const int & get_pe() const
Definition TRUST_Error.h:33