TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
PE_Groups.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 <Comm_Group.h>
17#include <PE_Groups.h>
18#include <TRUST_Ref.h>
19
20// Les trois variables suivantes sauvegardent la pile des groupes
21// (voir Comm_Group::enter_group() Comm_Group::current_group() Comm_Group::exit_group() )
22// Le haut de la pile est toujours groupe_TRUST(), fourni a initialize()
23// groups[0] pointe sur groupe_trio.
24static OBS_PTR(Comm_Group) groups[100];
25static int ngroups = 0;
26static int max_ngroups = 100;
27const Comm_Group * PE_Groups::current_group_ = 0;
28// node group is an isolated variable from all the other groups as it is only used for IO purposes
29// and might be used throughout the code together with other groups
30static OBS_PTR(Comm_Group) node_group;
31static OBS_PTR(Comm_Group) node_master;
32// For the user that defines his own group ! not done in the main, see the My_Comm_Group class !
33static OBS_PTR(Comm_Group) user_defined_group;
34
35int PE_Groups::check_current_group()
36{
37 assert(ngroups > 0);
38 assert(current_group_ == &(groups[ngroups-1].valeur()));
39 return 1;
40}
41
42/*! @brief Creation d'un nouveau groupe de processeurs (utilisation possible n'importe ou dans le code)
43 *
44 * Il faut l'appeler simultanement sur tous les processeurs du groupe current_group()
45 * avec le meme tableau liste_pe. liste_pe est la liste des rangs dans le groupe
46 * courant des processeurs que l'on veut inclure dans le groupe. Le premier de la
47 * liste sera le maitre du groupe. La liste ne doit pas comporter de doublon et
48 * doit contenir au moins un processeur.
49 * La methode type et initialize l'objet group.
50 * Il faut ensuite appeler enter_group() et exit_group() (autant de fois qu'on veut)
51 *
52 */
53void PE_Groups::create_group(const ArrOfInt& liste_pe, OWN_PTR(Comm_Group) & group, int force_Comm_Group_NoParallel)
54{
55 if (liste_pe.size_array()==1 && force_Comm_Group_NoParallel)
56 {
57 // On cree un groupe non parallele si c'est possible et si c'est impose
58 group.typer("Comm_Group_NoParallel");
59 }
60 else
61 {
62 // On cree un groupe du meme type que le groupe_TRUST
63 group.typer(groups[0]->que_suis_je());
64 }
65 group->init_group(liste_pe);
66}
67
68/*! @brief Initialisation d'un nouveau groupe de processeurs deja instantie (utilisation possible n'importe ou dans le code)
69 *
70 * Il faut l'appeler simultanement sur tous les processeurs du groupe current_group()
71 * avec le meme tableau liste_pe. liste_pe est la liste des rangs dans le groupe
72 * courant des processeurs que l'on veut inclure dans le groupe. Le premier de la
73 * liste sera le maitre du groupe. La liste ne doit pas comporter de doublon et
74 * doit contenir au moins un processeur.
75 * La methode type et initialize l'objet group.
76 * Il faut ensuite appeler enter_group() et exit_group() (autant de fois qu'on veut)
77 *
78 */
79void PE_Groups::init_group(const ArrOfInt& liste_pe, OWN_PTR(Comm_Group) & group)
80{
81 assert(group);
82 group->init_group(liste_pe);
83}
84
85/*! @brief Si le processeur local appartient au groupe, le groupe courant pour ce processeur devient "group" et on renvoie 1, sinon on renvoie 0.
86 *
87 * Une reference au groupe actuel est sauvegardee et sera restauree quand on
88 * appellera exit_group().
89 * Cette methode doit etre appelee simultanement sur tous les processeurs
90 * du groupe "group".
91 * Attention: a chaque enter_group() doit correspondre un exit_group().
92 * Cependant, il n'est pas interdit d'entrer plusieurs fois de suite dans le
93 * meme groupe, ni d'entrer dans un groupe plus grand que le groupe actuel.
94 * Exemple : group1 et group2 forment une partition du groupe_TRUST()
95 *
96 * int sync_point(int x)
97 * {
98 * PE_Groups::enter_group(groupe_TRUST());
99 * int i = mp_sum(x);
100 * PE_Groups::exit_group();
101 * return i;
102 * }
103 * if (PE_Groups::enter_group(group1)) {
104 * s1 = mp_sum(x); // Somme sur le groupe 2
105 * // Point de synchro avec l'autre groupe:
106 * s_all = sync_point(x);
107 * } else if (PE_Groups::enter_group(group2)) {
108 * s2 = mp_sum(x);
109 * // Point de synchro avec l'autre groupe:
110 * s_all = sync_point(x);
111 * } else {
112 * Cerr << "Error: processor " << me() << " is not within a subgroup.";
113 * exit();
114 * }
115 * PE_Groups::exit_group(); // Sort du sous-groupe
116 *
117 */
119{
120 assert(&group != &current_group());
121 if (ngroups >= max_ngroups-1)
122 {
123 Cerr << "Comm_Group::enter_group : fatal, too many groups" << finl;
125 }
126 int my_rank_in_group = rank_translate(current_group().rank(), current_group(), group);
127 if (my_rank_in_group >= 0)
128 {
129 // Sauvegarde du pointeur sur le groupe actuel et changement du
130 // current_group() :
131 groups[ngroups] = group;
132 current_group_ = &group;
133 ngroups++;
134 // Attention, on a change de current_group() !
135
136 // On verifie que tous les processeurs du nouveau groupe sont la:
139
140 return 1;
141 }
142 else
143 {
144 return 0;
145 }
146}
147
148/*! @brief Retourne dans le groupe ou l'on etait avant le dernier enter_group() reussi (dont le resultat a ete 1).
149 *
150 * Cette methode doit etre appelee simultanement sur tous les processeurs
151 * du current_group() actif juste avant exit_group()).
152 *
153 */
155{
158
159 if (ngroups <= 1)
160 {
161 Cerr << "Comm_Group::exit_group() error : trying to exit from TRUST main group." << finl;
163 }
164 ngroups--;
165 current_group_ = &(groups[ngroups-1].valeur());
166}
167
168/*! @brief Calcule le rank dans le groupe courant du processeur de rang "rank" dans le "group".
169 *
170 * Il faut que 0 <= rank < group.nproc()
171 * Si le processeur en question n'appartient pas au groupe courant, renvoie -1.
172 *
173 */
174int PE_Groups::rank_translate(int rank, const Comm_Group& group,
175 const Comm_Group& dest_group)
176{
177 const int world_rank = group.world_ranks_[rank];
178 const int local_rank = dest_group.local_ranks_[world_rank];
179 return local_rank;
180}
181
182/*! @brief Renvoie une reference au groupe de tous les processeurs TRUST
183 *
184 */
186{
187 assert(ngroups > 0); // Initialized ?
188 return groups[0].valeur();
189}
190
191/*! @brief Renvoie une reference au groupe sur les noeuds
192 *
193 */
195{
196 assert(node_group);
197 return node_group.valeur();
198}
199
200/*! @brief Renvoie le groupe contenant le maitre de mon noeud
201 *
202 */
204{
205 assert(node_master);
206 return node_master.valeur();
207}
208
209/*! @brief Renvoie une reference au groupe sur defini par l'utilisateur
210 *
211 */
213{
214 assert(user_defined_group);
215 return user_defined_group.valeur();
216}
217
218/*! @brief Methode a appeler au debut de l'execution (MAIN.
219 *
220 * cpp) Elle initialise current_group() avec groupe_trio_u
221 *
222 */
223void PE_Groups::initialize(const Comm_Group& groupe_trio_u)
224{
225 assert(ngroups == 0);
226 ngroups = 1;
227 groups[0] = groupe_trio_u;
228 current_group_ = &groupe_trio_u;
229}
230
231/*! @brief Methode a appeler apres l'initialisation de trio_u_world et l'initialisation des compteurs statistiques de TRUST
232 */
234{
235 assert(!node_group);
236 node_group = ngrp;
237}
238
240{
241 assert(!user_defined_group);
242 user_defined_group = ngrp;
243}
244
246{
247 return bool(user_defined_group);
248}
249
250/*! @brief Methode a appeler apres l'initialisation de trio_u_world et de node_group et l'initialisation des compteurs statistiques de TRUST
251 */
253{
254 assert(!node_master);
255 node_master = ngrp;
256}
257
258/*! @brief Methode a appeler en fin d'execution, une fois qu'on est revenu dans le groupe_TRUST() et juste avant de detruire de Comm_Group
259 *
260 * principal.
261 *
262 */
264{
265 assert(ngroups == 1);
266 groups[0].reset();
267 ngroups = 0;
268 current_group_ = 0;
269 node_group.reset();
270 node_master.reset();
271 user_defined_group.reset();
272}
273
275{
276 return ngroups ;
277}
: Cette classe decrit un groupe de processeurs sur lesquels
Definition Comm_Group.h:40
static int check_enabled()
Definition Comm_Group.h:159
virtual void barrier(int tag) const =0
virtual void init_group(const ArrOfInt &pe_list)
Cette fonction doit etre appelee simultanement par tous les PEs du groupe current_group avec les meme...
static void initialize_user_defined_group(const Comm_Group &ngrp)
static int enter_group(const Comm_Group &group)
Si le processeur local appartient au groupe, le groupe courant pour ce processeur devient "group" et ...
static void create_group(const ArrOfInt &liste_pe, OWN_PTR(Comm_Group) &group, int force_Comm_Group_NoParallel=0)
Creation d'un nouveau groupe de processeurs (utilisation possible n'importe ou dans le code).
Definition PE_Groups.cpp:53
static void init_group(const ArrOfInt &liste_pe, OWN_PTR(Comm_Group) &group)
Initialisation d'un nouveau groupe de processeurs deja instantie (utilisation possible n'importe ou d...
Definition PE_Groups.cpp:79
static void initialize_node_master(const Comm_Group &ngrp)
Methode a appeler apres l'initialisation de trio_u_world et de node_group et l'initialisation des com...
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_node_master()
Renvoie le groupe contenant le maitre de mon noeud.
static void initialize(const Comm_Group &groupe_trio_u)
Methode a appeler au debut de l'execution (MAIN.
static void initialize_node(const Comm_Group &ngrp)
Methode a appeler apres l'initialisation de trio_u_world et l'initialisation des compteurs statistiqu...
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 int rank_translate(int rank, const Comm_Group &group, const Comm_Group &dest_group=current_group())
Calcule le rank dans le groupe courant du processeur de rang "rank" dans le "group".
static const Comm_Group & groupe_TRUST()
Renvoie une reference au groupe de tous les processeurs TRUST.
static void exit_group()
Retourne dans le groupe ou l'on etait avant le dernier enter_group() reussi (dont le resultat a ete 1...
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
_SIZE_ size_array() const