Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
HyodaArc.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 * Hyoda.cc (C) 2000-2012 *
9 * *
10 * Service de debugger hybrid. *
11 *****************************************************************************/
12#include "arcane/IMesh.h"
13#include "arcane/IApplication.h"
14#include "arcane/IParallelMng.h"
15#include "arcane/utils/ValueConvert.h"
16#include "arcane/FactoryService.h"
17#include "arcane/ServiceFinder2.h"
18#include "arcane/SharedVariable.h"
19#include "arcane/CommonVariables.h"
20#include "arcane/utils/ScopedPtr.h"
21#include "arcane/AbstractService.h"
23#include "arcane/utils/PlatformUtils.h"
24#include "arcane/utils/IOnlineDebuggerService.h"
25#include "arcane/ITransferValuesParallelOperation.h"
26#include "arcane/ServiceBuilder.h"
27
28#include "arcane/hyoda/HyodaArc.h"
29#include "arcane/hyoda/HyodaTcp.h"
30#include "arcane/hyoda/HyodaIceT.h"
31#include "arcane/hyoda/HyodaMatrix.h"
32#include "arcane/hyoda/HyodaPapi.h"
33
34#include <unistd.h>
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39ARCANE_BEGIN_NAMESPACE
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44
45
46/******************************************************************************
47 * Hyoda SERVICE
48 *****************************************************************************/
49ARCANE_REGISTER_APPLICATION_FACTORY(Hyoda, IOnlineDebuggerService, Hyoda);
50
51# define SWAP(n) (((n)<<24)|(((n)&0xff00)<<8)|(((n)>>8)&0xff00)|((n)>>24))
52
53/******************************************************************************
54 * Hyoda Constructor
55 *****************************************************************************/
56Hyoda::Hyoda(const ServiceBuildInfo& sbi): AbstractService(sbi),
57 m_break_at_startup(false),
58 m_configured(false),
59 m_init_configured(false),
60 m_gdbserver_rank(0),
61 m_qhyoda_hooked(0.),
62//#warning Hardcoded values must be sync'ed with QHyodaJob::QHyodaJob's ones
63 m_qhyoda_adrs(0x100007Ful),
64// L'adresse IP est settée par QHyoda, par défault 127.0.0.1
65 m_qhyoda_port(3889),
66// Le numéro du port est settée par QHyoda, par défaut 3889
67 m_qhyoda_pyld(8*1024),
68// Le payload à utiliser
69 m_qhyoda_width_height(0x04000300ul),
70 m_target_cell_uid(0),
71 m_data(NULL),
72 m_ice_mesh(NULL),
73 m_ice_matrix(NULL),
74 m_tcp(NULL),
75 m_variables_names(NULL),
76 m_application(sbi.application()),
77 m_papi(new HyodaPapi(this, sbi.application(),traceMng())),
78 m_matrix_render(false){
79 debug()<<"Hooking Hyoda";
80 if ((m_data=(hyoda_shared_data*)malloc(sizeof(hyoda_shared_data)))==NULL)
81 throw Arcane::FatalErrorException(A_FUNCINFO,"Could not allocate data space for hook");
82 m_data->global_iteration=0;
83 m_data->global_time=0.;
84 m_data->global_deltat=0.;
85 m_data->global_cpu_time=0.;
86 m_data->global_mesh_nb_cells=0;
87 m_data->target_cell_uid=m_target_cell_uid;
88 m_data->target_cell_rank=0;
89 m_data->target_cell_nb_nodes=0;
90 for(int i=0;i<HYODA_CELL_NB_NODES_MAX;++i)
91 m_data->coords[i][0]=m_data->coords[i][1]=m_data->coords[i][2]=0.;
92
93 // On test si l'on souhaite s'accrocher au démarrage
94 if (!platform::getEnvironmentVariable("ARCANE_HYODA").null()) m_break_at_startup=true;
95 if (!platform::getEnvironmentVariable("ARCANE_HYODA_MATRIX_RENDER").null()) m_matrix_render=true;
96
97 if (m_break_at_startup) debug()<<"\33[7m[Hyoda] m_break_at_startup == Single shot!\33[m";
98
99 // On récupère le host depuis lequel est lancé Hyoda
100 String hyoda_host;
101 if (!(hyoda_host=platform::getEnvironmentVariable("ARCANE_HYODA_HOST")).null()){
102 debug()<<"\33[7m[Hyoda] hyoda_host="<<hyoda_host<<"\33[m";
103 }
104
105 // On récupère l'adresse du host depuis lequel est lancé Hyoda
106 String hyoda_adrs;
107 if (!(hyoda_adrs=platform::getEnvironmentVariable("ARCANE_HYODA_ADRS")).null()){
108 UInt32 adrs=0;
109 if (!builtInGetValue(adrs,hyoda_adrs)){
110 //Attention: QHostAddress::toIPv4Address() = if the address is 127.0.0.1, the returned value is 2130706433 (i.e. 0x7f000001).
111 // Alors que l'on souhaite 0x100007Ful => il faut donc swaper!
112 m_qhyoda_adrs=SWAP(adrs);
113 debug()<<"\33[7m[Hyoda] hyoda_adrs="<<m_qhyoda_adrs<<"\33[m";
114 }
115 }
116
117 // Et son numéro de port
118 String hyoda_port;
119 if (!(hyoda_port=platform::getEnvironmentVariable("ARCANE_HYODA_PORT")).null()){
120 Integer port=0;
121 if (!builtInGetValue(port,hyoda_port)){
122 m_qhyoda_port=port;
123 debug()<<"\33[7m[Hyoda] hyoda_port="<<m_qhyoda_port<<"\33[m";
124 }
125 }
126}
127
128
129
130/******************************************************************************
131 * Hyoda Destructor
132 *****************************************************************************/
133Hyoda::~Hyoda(){
134 debug()<<"\33[7m[Hyoda::~ Hyoda]\33[m";
135 free(m_data);
136 delete m_papi;
137}
138
139
140
141/******************************************************************************
142 * Fonction de test pour savoir si j'ai la maille visée
143 * Maillage initiale: UIDs + partitionnement => LIDs dont les ghosts
144 * Le slider est bien sur le maillage initial, donc les UIDs et on cherche à quels LIDs
145 * ils correspondent alors que les ghosts ont été incorporés
146 *****************************************************************************/
147LocalIdType Hyoda::targetCellIdToLocalId(ISubDomain *sd, UniqueIdType target_cell_uid){
148 UniqueArray<UniqueIdType> uid(1);
149 Int32UniqueArray lid(1);
150
151 uid[0]=target_cell_uid;
152 debug()<<"[Hyoda::targetCellIdToLocalId] uid="<<target_cell_uid;
153 sd->defaultMesh()->itemFamily(IK_Cell)->itemsUniqueIdToLocalId(lid.view(),uid.constView(),false);
154 debug()<<"[Hyoda::targetCellIdToLocalId] lid="<<lid[0];
155
156 if (lid[0]!=NULL_ITEM_ID){ // Si on a un candidat: c'est une maille propre ou fantôme
157 if (!sd->defaultMesh()->cellFamily()->itemsInternal()[lid[0]]->isOwn())
158 return NULL_ITEM_ID; // Si c'est fantôme, c'est pas à nous
159 return lid[0]; // Sinon, on la tient!
160 }
161 return NULL_ITEM_ID;
162}
163
164
165
166/******************************************************************************
167 * Fonction de configuration pour mettre tout le monde d'accord sur les variables:
168 * m_gdbserver_rank
169 * m_data->*
170 *****************************************************************************/
171void Hyoda::broadcast_configuration(ISubDomain *sd, UniqueIdType target_cell_uid){
172 debug()<<"[Hyoda::broadcast_configuration] target_cell_uid="<<target_cell_uid;
173 m_configured=true;
174
175 if (!sd->parallelMng()->isParallel()){
176 // En séquentiel, il faut au moins mettre le nombre de mailles à jour
177 m_data->global_mesh_nb_cells=sd->defaultMesh()->ownCells().size();
178 // En séquentiel, il faut au moins mettre le nombre noeuds de la maille visée (uid=lid)
179 m_data->target_cell_nb_nodes=sd->defaultMesh()->cellFamily()->itemsInternal()[target_cell_uid]->nbNode();
180 // Si on est en mode séquentiel, il y a rien d'autre à faire
181 return;
182 }
183
184 // Transformation unique => local
185 LocalIdType target_cell_lid=targetCellIdToLocalId(sd, target_cell_uid);
186 UniqueArray<Integer> gather(4*sd->parallelMng()->commSize());
187 UniqueArray<Integer> all;
188 // En mode parallèle, nous remplissons la structure data pour la partager
189 if (m_break_at_startup==false)
190 all.add(m_qhyoda_hooked>0.?3883:0); // Où gdbserver est accroché
191 else
192 all.add(sd->parallelMng()->commRank()==0?3883:0); // Où gdbserver est accroché
193 all.add(target_cell_lid); // Le résultat de la transformation id to 'local'
194 all.add(target_cell_lid!=NULL_ITEM_ID // Le nombre de noeuds de la maille considérée
195 ?sd->defaultMesh()->cellFamily()->itemsInternal()[target_cell_lid]->nbNode():0);
196 all.add(sd->defaultMesh()->ownCells().size()); // Le nombre de own cells par sous-domaine
197 // On s'échange le tout /////////////////////////////////////////////
198 debug()<<"[Hyoda::broadcast_where_gdbserver_is_hooked] Gathering, all="<<all<<"...";
199 sd->parallelMng()->allGather(all,gather);
201 m_gdbserver_rank=-1;
202 m_data->target_cell_rank=-1;
203 m_data->target_cell_nb_nodes=-1;
204 m_data->global_mesh_nb_cells=0;
205 for(int iRnk=4*sd->parallelMng()->commSize();iRnk>0;iRnk-=4){
206 if (gather[iRnk-4]==3883){
207 if (m_gdbserver_rank!=-1)
208 throw FatalErrorException("[Hyoda::broadcast_where_gdbserver_is_hooked] more than one m_gdbserver_rank");
209 m_gdbserver_rank=(iRnk/4)-1;
210 debug()<<"[Hyoda::broadcast_where_gdbserver_is_hooked] m_gdbserver_rank="<<m_gdbserver_rank;
211 }
212 if (gather[iRnk-3]!=NULL_ITEM_ID){
213 if (m_data->target_cell_rank!=-1)
214 throw FatalErrorException("[Hyoda::broadcast_where_gdbserver_is_hooked] more than one m_data->target_cell_rank");
215 m_data->target_cell_rank=(iRnk/4)-1;
216 debug() << "\33[7m[Hyoda::broadcast_where_gdbserver_is_hooked] m_data->target_cell_rank="
217 << m_data->target_cell_rank
218 << "\33[m";
219 }
220 if (gather[iRnk-2]!=0){
221 if (m_data->target_cell_nb_nodes!=-1)
222 throw FatalErrorException("[Hyoda::broadcast_where_gdbserver_is_hooked] more than one m_data->target_cell_nb_nodes");
223 m_data->target_cell_nb_nodes=gather[iRnk-2];
224 debug()<<"[Hyoda::broadcast_where_gdbserver_is_hooked] m_data->target_cell_nb_nodes="<<m_data->target_cell_nb_nodes;
225 }
226 if (gather[iRnk-1]!=0) m_data->global_mesh_nb_cells+=gather[iRnk-1];
227 }
228 if (m_data->target_cell_rank>=sd->parallelMng()->commSize())
229 throw FatalErrorException("[Hyoda::broadcast_where_gdbserver_is_hooked] ERROR with m_data->target_cell_rank (>commSize)");
230}
231
232
233/******************************************************************************
234 * Vérifie si un sous-domaine demande un breakpoint ou une tâche particulière
235 * On doit être rapide car c'est ce que l'on fait en mode standard
236 * C'est le premier breapoint sur lequel gdb va s'arréter
237 * Loopbreak pour positionner des points d'arrêt lors de la boucle en temps
238 *****************************************************************************
239 * Attention à l'ordre dans lequel nous allons returner
240 *****************************************************************************/
241Real Hyoda::
242loopbreak(ISubDomain* sd)
243{
244 ARCANE_UNUSED(sd);
245 // Si l'un voit la target cell uid bouger,
246 // il faut informer les autres via le biais du reduce qui sera fait
247 if (m_target_cell_uid!=m_data->target_cell_uid)
248 return HYODA_HOOK_CONFIGURE;
249 // Si on a l'IHM de up dès le début, on s'arréte systématiquement!
250 if (m_break_at_startup)
251 return HYODA_HOOK_BREAK;
252 // Est-ce que mon m_qhyoda_hooked été set'à par gdb?
253 if (m_qhyoda_hooked>0.)
254 return HYODA_HOOK_BREAK;
255 return 0.0;
256}
257
258/******************************************************************************
259 * Softbreak pour positionner des points d'arrêt en différents endroits du code
260 *****************************************************************************/
261Real Hyoda::softbreak(ISubDomain* sd, const char *fileName,const char *prettyFunction, int lineNumber){
262 // Tant que l'IHM n'est pas accrochée, on fait rien
263 if (m_qhyoda_hooked==0.) return 0.;
264 debug() << "[Hyoda::softbreak] Was @ " << ((fileName)?fileName:"(NoFileNameInfo)")<< ":" << lineNumber;
265 debug() << "[Hyoda::softbreak] Was @ " << ((prettyFunction)?prettyFunction:"(NoFunctionInfo)");
266 //usleep(100);
267 return 0.;
268}
269
270
271/******************************************************************************
272 * Point d'entrée du debugger
273 * C'est le deuxième breapoint sur lequel gdb va s'arréter pour rafraîchir
274 *****************************************************************************/
275void Hyoda::hook(ISubDomain* sd, Real tasks){
276 m_papi->stop();
277
278 // On attend au moins d'avoir fait une itération
279 //if (sd->commonVariables().globalIteration()<2) return;
280
281 // Si la maille affichée dans la QHyodaToolCell est à rafraîchir,
282 // on le demande && m_break_at_startup==false
283 if (m_target_cell_uid!=m_data->target_cell_uid) tasks=HYODA_HOOK_CONFIGURE;
284
285 // Dans le cas parallèle
286 if (tasks==HYODA_HOOK_CONFIGURE && sd->parallelMng()->isParallel()){
287 debug()<<"[Hyoda::hook] New requested cell #"<<m_target_cell_uid;
288 UniqueArray<UniqueIdType> send_buf(1,m_target_cell_uid);
289 sd->parallelMng()->broadcast(send_buf.view(),m_gdbserver_rank);
290 debug() << "[Hyoda::hook] broadcasted cell " << send_buf.at(0)
291 << ", m_data->global_mesh_nb_cells=" << m_data->global_mesh_nb_cells;
292 if (send_buf.at(0)>m_data->global_mesh_nb_cells)
293 throw FatalErrorException("[Hyoda::hook] ERROR with broadcasted cell");
294 // Et on met à jour la bonne cell ID dans la structure vue du debugger
295 m_data->target_cell_uid=m_target_cell_uid=send_buf.at(0);
296 // Et on annonce qu'il faut se reconfigurer
297 m_configured=false;
298 }
299
300 // Dans le cas séquentiel (pas sûr d'être utile)
301 if (tasks==HYODA_HOOK_CONFIGURE && (!sd->parallelMng()->isParallel())){
302 debug()<<"[Hyoda::hook (seq)] New cell sent from server "<<m_target_cell_uid;
303 if (m_target_cell_uid>m_data->global_mesh_nb_cells)
304 throw FatalErrorException("[Hyoda::hook] ERROR with broadcasted cell");
305 // Et on met à jour la bonne cell ID dans la structure vue du debugger
306 m_data->target_cell_uid=m_target_cell_uid;
307 // Et on annonce qu'il faut se reconfigurer
308 m_configured=false;
309 }
310
311 // S'il y a des configurations à faire, on les déclenche
312 if (!m_configured) broadcast_configuration(sd, m_target_cell_uid);
313
314 // Configuration à ne faire qu'une seule fois, après celle ci dessus pour que m_gdbserver_rank soit à jour
315 if (!m_init_configured){
316 m_init_configured=true;
317 UniqueArray<Integer> wxh_to_broadcast(0);
318 wxh_to_broadcast.add(m_qhyoda_width_height);
319 debug()<<"[Hyoda::hook] broadcasting wxh...";
320 sd->parallelMng()->broadcast(wxh_to_broadcast.view(), m_gdbserver_rank);
321 unsigned int width = (wxh_to_broadcast[0]>>16)&0xFFFFul;
322 unsigned int height = (wxh_to_broadcast[0])&0xFFFFul;
323 debug() << "[Hyoda::hook] Let's configure: m_qhyoda_width_height="
324 << wxh_to_broadcast[0] << ", " << width << "x" << height;
325 debug()<<"\33[7m[Hyoda::hook] Initializing HyodaTcp\33[m";
326 // Seul le proc 0 se connecte réellement
327 m_tcp = new HyodaTcp(this, sd, traceMng(),
328 m_qhyoda_adrs, m_qhyoda_port,
329 m_qhyoda_pyld, m_break_at_startup);
330 debug()<<"\33[7m[Hyoda::hook] Initializing MESH HyodaIceT\33[m";
331 m_ice_mesh=new HyodaIceT(this, sd, traceMng(), width, height, m_tcp);
332 debug()<<"\33[7m[Hyoda::hook] Initializing MATRIX HyodaIceT\33[m";
333 m_ice_matrix=new HyodaMatrix(this, sd, traceMng(), width, height, m_tcp);
334 m_papi->initialize(sd,m_tcp);
335 }
336
337 m_ice_mesh->render();
338 if (m_matrix_render) m_ice_matrix->render();
339
340 debug()<<"[Hyoda::hook] now fetch_and_fill_data_to_be_dumped";
341 fetch_and_fill_data_to_be_dumped(sd,m_target_cell_uid);
342
343 debug()<<"[Hyoda::hook] dump";
344 m_papi->dump();
345 debug()<<"[Hyoda::hook] done";
346 m_papi->start();
347}
348
349
350// ****************************************************************************
351// * ijval
352// ****************************************************************************
353void Hyoda::ijval(int cpu,int n, int *i, int *j, double *val){
354 debug()<<"\33[7m[HyodaArc::ijval] cpu="<<cpu<<", n="<<n<<"\33[m";
355 m_ice_matrix->setIJVal(cpu,n,i,j,val);
356}
357
358
359/*---------------------------------------------------------------------------*/
360/*---------------------------------------------------------------------------*/
361
362ARCANE_END_NAMESPACE
363
364/*---------------------------------------------------------------------------*/
365/*---------------------------------------------------------------------------*/
366
Fichier de configuration d'Arcane.
#define ARCANE_REGISTER_APPLICATION_FACTORY(aclass, ainterface, aname)
Enregistre un service de fabrique pour la classe aclass.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Exception lorsqu'une erreur fatale est survenue.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
Int32 LocalIdType
Type des entiers utilisés pour stocker les identifiants locaux des entités.
Int32 Integer
Type représentant un entier.
std::uint32_t UInt32
Type entier non signé sur 32 bits.