Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
Otf2LibWrapper.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/* Otf2LibWrapper.cc (C) 2000-2022 */
9/* */
10/* Classe qui encapsule les fonctions utiles de la lib Otf2. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/std/Otf2LibWrapper.h"
15
16#include "arcane/utils/Collection.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/FatalErrorException.h"
19
20#include "arcane/IDirectory.h"
21#include "arcane/IParallelMng.h"
22#include "arcane/ITimeLoopMng.h"
23#include "arcane/IEntryPoint.h"
24#include "arcane/IApplication.h"
25
26#include "arccore/message_passing_mpi/MessagePassingMpiGlobal.h"
27#include "arccore/message_passing_mpi/MessagePassingMpiEnum.h"
28#include "arccore/base/PlatformUtils.h"
29
30#include <otf2/OTF2_MPI_Collectives.h>
31#include <numeric>
32#include <filesystem>
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37using namespace Arccore::MessagePassing::Mpi;
38
39namespace Arcane
40{
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
46
47/*---------------------------------------------------------------------------*/
48/*---------------------------------------------------------------------------*/
52: m_sub_domain(sub_domain)
53{
54 m_flush_callbacks.otf2_pre_flush = _preFlush;
55 m_flush_callbacks.otf2_post_flush = _postFlush;
56}
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
63{
64 // Fermeture de l'archive
65 if (m_archive)
66 OTF2_Archive_Close(m_archive);
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
74{
75 // Alias sur le comm MPI
76 MPI_Comm* mpi_comm((MPI_Comm*)m_sub_domain->parallelMng()->getMPICommunicator());
77 if (!mpi_comm)
78 ARCANE_FATAL("Impossible d'initialiser la librairie Otf2 sans communicateur MPI");
79
80 // Initialisation du tableau des participants aux comm (i.e. les sub-domain id quoi...)
81 m_comm_members.resize(m_sub_domain->nbSubDomain());
82 std::iota(m_comm_members.begin(), m_comm_members.end(), 0);
83
84 // Verification de l'eventuelle existance des fichiers et suppression le cas echeant
85 String dir_name(m_sub_domain->listingDirectory().path() + "/" + archive_name);
86 String otf2_name(dir_name + ".otf2");
87 String def_name(dir_name + ".def");
88 if (m_sub_domain->parallelMng()->isMasterIO() && std::filesystem::exists(dir_name.localstr())) {
89 std::filesystem::remove_all(dir_name.localstr());
90 std::filesystem::remove_all(otf2_name.localstr());
91 std::filesystem::remove_all(def_name.localstr());
92 }
93 // Synchro avant d'ouvrir
94 MPI_Barrier(*mpi_comm);
95
96 // Sauvegarde du temps de debut pour recaler les enregistrements de chaque rang MPI
98
99 // Ouverture de l'archive
100 m_archive = OTF2_Archive_Open(m_sub_domain->listingDirectory().path().localstr(),
102 1024 * 1024 /* event chunk size */,
103 4 * 1024 * 1024 /* def chunk size */,
105 if (!m_archive)
106 ARCANE_FATAL("Impossible de creer l'archive OTF2");
107
108 // Attachement des callbacks
109 OTF2_Archive_SetFlushCallbacks(m_archive, &m_flush_callbacks, NULL);
111 ARCANE_FATAL("Probleme lors du positionnement des callbacks MPI pour la librairie OTF2");
112
113 // Init des fichiers d'event (pas encore crees)
114 OTF2_Archive_OpenEvtFiles(m_archive);
115
116 // Init du event writer
117 m_evt_writer = OTF2_Archive_GetEvtWriter(m_archive, m_sub_domain->subDomainId());
118
119 // Creation des ids pour les definitions de l'archive
121
122 // DBG test du contenu du set
123 /*
124 m_sub_domain->traceMng()->info() << "===== EntryPointIdSet =====";
125 for (auto i : m_id.m_ep_id_set)
126 m_sub_domain->traceMng()->info() << "{" << i.m_name << ", " << i.m_id << "}";
127 */
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
134finalize()
135{
136 // Alias sur la comm
137 MPI_Comm* mpi_comm((MPI_Comm*)m_sub_domain->parallelMng()->getMPICommunicator());
138
139 // Sauvegarde du temps de fin pour recaler les enregistrements de chaque rang MPI
141
142 // Fermeture de ce qui est lie aux events
143 OTF2_Archive_CloseEvtWriter(m_archive, m_evt_writer);
145
146 // Temporaire pour recuperer les timings globaux
148
149 // Echanges pour avoir la fenetre temporelle globale
150 // Plus petit temps pour le debut
151 /*
152 MPI_Reduce(&m_epoch_start, &sync_epoch, 1, OTF2_MPI_UINT64_T, MPI_MIN,
153 m_sub_domain->parallelMng()->masterIORank(), *mpi_comm);
154 std::swap(m_epoch_start, sync_epoch);
155 */
156 // Plus grand temps pour la fin
158 m_sub_domain->parallelMng()->masterIORank(), *mpi_comm);
159 std::swap(epoch_end, sync_epoch);
160
161 // On finit de creer les definitions pour l'archive
162 //_buildOtf2ClockAndStringDefinition(m_epoch_start, epoch_end);
167 _buildOtf2GroupAndCommDefinition(); // L'ecriture effective se passe dans cette methode
168
169 // Synchro avant de fermer
170 MPI_Barrier(*mpi_comm);
171
172 // Fermeture du fichier archive
173 OTF2_Archive_Close(m_archive);
174 m_archive = nullptr;
175}
176
177/*---------------------------------------------------------------------------*/
178/*---------------------------------------------------------------------------*/
183{
184 ++m_evt_nb;
185 return m_evt_writer;
186}
187
188/*---------------------------------------------------------------------------*/
189/*---------------------------------------------------------------------------*/
192getEntryPointId(const String& ep_name) const
193{
194 auto id(m_id.m_ep_id_set.find(ep_name));
195 if (id == m_id.m_ep_id_set.end())
196 ARCANE_FATAL(String("Impossible de trouver le point d'entree ") + ep_name);
197 return id->m_id;
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
204getMpiRank() const
205{
206 return m_sub_domain->subDomainId();
207}
208
209/*---------------------------------------------------------------------------*/
210/*---------------------------------------------------------------------------*/
213getMpiNbRank() const
214{
215 return m_sub_domain->nbSubDomain();
216}
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
223{
224 return m_id.m_app_name;
225}
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
231getSynchronizeId() const
232{
233 return m_id.m_sync_id;
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
240getTime()
241{
242 // We use MPI_Wtime to get timestamps for our events but need to convert the seconds to an integral value.
243 // We use a nano second resolution.
244 double t(MPI_Wtime() * 1e9);
246}
247
248/*---------------------------------------------------------------------------*/
249/*---------------------------------------------------------------------------*/
250
255 [[maybe_unused]] bool final)
256{
257 // The pre flush callback is triggered right before a buffer flush.
258 // It needs to return either OTF2_FLUSH to flush the recorded data to a file
259 // or OTF2_NO_FLUSH to suppress flushing data to a file
260 return OTF2_FLUSH;
261}
262
263/*---------------------------------------------------------------------------*/
264/*---------------------------------------------------------------------------*/
265
269 [[maybe_unused]] OTF2_LocationRef location)
270{
271 // The post flush callback is triggered right after a memory buffer flush.
272 // It has to return a current timestamp which is recorded to mark the time spend in a buffer flush
273 return getTime();
274}
275
276/*---------------------------------------------------------------------------*/
277/*---------------------------------------------------------------------------*/
283{
284 // Les ids des noms des operations MPI sont cables sur la valeur de l'enum
285 // Leur description est decale d'autant
286 // On compteur pour incrementer les identifiants
287 u_int32_t offset(static_cast<uint32_t>(eMpiName::NameOffset));
288 m_id.m_desc_offset = offset;
289
290 // On continu avec le reste, j'ai pas trouve d'idee geniale pour avoir un indice intelligent ...
291 offset *= 2;
292 // Chaine vide : 2 x eMpiName::NameOffset
293 m_id.m_empty_id = offset++;
294 // Nom du thread CPU mappe sur le process MPI : 2 x eMpiName::NameOffset + 1
295 m_id.m_thread_id = offset++;
296 // Nom de la machine : 2 x eMpiName::NameOffset + 2
297 m_id.m_hostname_id = offset++;
298 // Classe de la machine... pas inspire... : 2 x eMpiName::NameOffset + 3
299 m_id.m_class_id = offset++;
300 // MPI Communicator : 2 x eMpiName::NameOffset + 4
301 m_id.m_comm_world_id = offset++;
302 // MPI : 2 x eMpiName::NameOffset + 5
303 m_id.m_mpi_id = offset++;
304 // Comm id : 2 x eMpiName::NameOffset + 6
305 m_id.m_comm_id = offset++;
306 // Win id : 2 x eMpiName::NameOffset + 7
307 m_id.m_win_id = offset++;
308 // MPI_COMM_SELF : 2 x eMpiName::NameOffset + 8
309 m_id.m_comm_self_id = offset++;
310 // Entry Point : 2 x eMpiName::NameOffset + 9
311 m_id.m_ep_id = offset++;
312 // Synchronize : 2 x eMpiName::NameOffset + 10
313 m_id.m_sync_id = offset++;
314 // Application name : 2 x eMpiName::NameOffset + 11
315 m_id.m_app_name = offset++;
316 // On continu avec les noms des rangs MPI : a partir de 2 x eMpiName::NameOffset + 12
317 m_id.m_rank_offset = offset;
318 offset += m_sub_domain->nbSubDomain();
319
320 // On termine avec les points d'entree : a partir de 2 x eMpiName::NameOffset + 12 + nbSubDomain()
321 for (auto i : m_sub_domain->timeLoopMng()->usedTimeLoopEntryPoints()) {
322 // On ajoute la reference du point d'entree dans la table
323 // NOTE: L'identifiant utilisé doit être identique à celui dans
324 // Otf2MessagePassingProfilingService
325 m_id.m_ep_id_set.emplace(EntryPointId(i->fullName(), offset));
326 // On incremente pour tout le monde
327 offset++;
328 }
329}
330
331/*---------------------------------------------------------------------------*/
332/*---------------------------------------------------------------------------*/
338{
339 /*
340 * Seul le sous-domaine responsable des IOs va remplir cette structure OTF2
341 * (parcequ'on ne sait pas trop ce qu'il y a la dessous, mais surement trop de char*)
342 * et pour etre raccord sur les identifiants associes au nom des pts d'entree, on
343 * communique le debut des ids des pts d'entree.
344 */
345
346 // Seul le sous-domaine responsable ecrit l'archive otf2
347 if (!m_sub_domain->parallelMng()->isMasterIO())
348 return;
349
350 // Recuperation de l'ecrivain
351 m_global_def_writer = OTF2_Archive_GetGlobalDefWriter(m_archive);
352
353 // Definition des proprietes temporelles
354 // Un nouvel argument est disponible à partir de la version 3.0. Il s'agit du dernier argument
355 // * @param realtimeTimestamp A realtime timestamp of the `globalOffset` timestamp
356 // * in nanoseconds since 1970-01-01T00:00 UTC. Use
357 // * @eref{OTF2_UNDEFINED_TIMESTAMP} if no such
358 // * timestamp exists. Since version 3.0.
359 OTF2_GlobalDefWriter_WriteClockProperties(m_global_def_writer, 1000000000,
361#if OTF2_VERSION_MAJOR >= 3
363#endif
364 );
365
366 // Definition de toutes les noms que l'on verra apparaitre dans les outils capables de lire l'archive otf2
367 // On commence par les noms des operations MPI
368 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
369 static_cast<uint32_t>(eMpiName::Bcast), MpiInfo(eMpiName::Bcast).name().localstr());
370 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
371 static_cast<uint32_t>(eMpiName::Gather), MpiInfo(eMpiName::Gather).name().localstr());
372 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
373 static_cast<uint32_t>(eMpiName::Gatherv), MpiInfo(eMpiName::Gatherv).name().localstr());
374 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
375 static_cast<uint32_t>(eMpiName::Allgather), MpiInfo(eMpiName::Allgather).name().localstr());
376 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
377 static_cast<uint32_t>(eMpiName::Allgatherv), MpiInfo(eMpiName::Allgatherv).name().localstr());
378 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
379 static_cast<uint32_t>(eMpiName::Scatterv), MpiInfo(eMpiName::Scatterv).name().localstr());
380 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
381 static_cast<uint32_t>(eMpiName::Alltoall), MpiInfo(eMpiName::Alltoall).name().localstr());
382 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
383 static_cast<uint32_t>(eMpiName::Alltoallv), MpiInfo(eMpiName::Alltoallv).name().localstr());
384 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
385 static_cast<uint32_t>(eMpiName::Barrier), MpiInfo(eMpiName::Barrier).name().localstr());
386 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
387 static_cast<uint32_t>(eMpiName::Reduce), MpiInfo(eMpiName::Reduce).name().localstr());
388 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
389 static_cast<uint32_t>(eMpiName::Allreduce), MpiInfo(eMpiName::Allreduce).name().localstr());
390 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
391 static_cast<uint32_t>(eMpiName::Scan), MpiInfo(eMpiName::Scan).name().localstr());
392 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
393 static_cast<uint32_t>(eMpiName::Sendrecv), MpiInfo(eMpiName::Sendrecv).name().localstr());
394 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
395 static_cast<uint32_t>(eMpiName::Isend), MpiInfo(eMpiName::Isend).name().localstr());
396 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
397 static_cast<uint32_t>(eMpiName::Send), MpiInfo(eMpiName::Send).name().localstr());
398 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
399 static_cast<uint32_t>(eMpiName::Irecv), MpiInfo(eMpiName::Irecv).name().localstr());
400 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
401 static_cast<uint32_t>(eMpiName::Recv), MpiInfo(eMpiName::Recv).name().localstr());
402 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
403 static_cast<uint32_t>(eMpiName::Test), MpiInfo(eMpiName::Test).name().localstr());
404 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
405 static_cast<uint32_t>(eMpiName::Probe), MpiInfo(eMpiName::Probe).name().localstr());
406 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
407 static_cast<uint32_t>(eMpiName::Get_count), MpiInfo(eMpiName::Get_count).name().localstr());
408 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
409 static_cast<uint32_t>(eMpiName::Wait), MpiInfo(eMpiName::Wait).name().localstr());
410 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
411 static_cast<uint32_t>(eMpiName::Waitall), MpiInfo(eMpiName::Waitall).name().localstr());
412 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
413 static_cast<uint32_t>(eMpiName::Testsome), MpiInfo(eMpiName::Testsome).name().localstr());
414 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
415 static_cast<uint32_t>(eMpiName::Waitsome), MpiInfo(eMpiName::Waitsome).name().localstr());
416 // On compteur pour incrementer les identifiants
417 u_int32_t offset(static_cast<uint32_t>(eMpiName::NameOffset));
418
419 // On continu avec les descriptions de ces operations. On utilise la valeur du decalage du nb de champ de l'enum
420 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
421 static_cast<uint32_t>(eMpiName::Bcast) + offset, MpiInfo(eMpiName::Bcast).description().localstr());
422 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
423 static_cast<uint32_t>(eMpiName::Gather) + offset, MpiInfo(eMpiName::Gather).description().localstr());
424 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
425 static_cast<uint32_t>(eMpiName::Gatherv) + offset, MpiInfo(eMpiName::Gatherv).description().localstr());
426 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
427 static_cast<uint32_t>(eMpiName::Allgather) + offset, MpiInfo(eMpiName::Allgather).description().localstr());
428 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
429 static_cast<uint32_t>(eMpiName::Allgatherv) + offset, MpiInfo(eMpiName::Allgatherv).description().localstr());
430 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
431 static_cast<uint32_t>(eMpiName::Scatterv) + offset, MpiInfo(eMpiName::Scatterv).description().localstr());
432 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
433 static_cast<uint32_t>(eMpiName::Alltoall) + offset, MpiInfo(eMpiName::Alltoall).description().localstr());
434 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
435 static_cast<uint32_t>(eMpiName::Alltoallv) + offset, MpiInfo(eMpiName::Alltoallv).description().localstr());
436 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
437 static_cast<uint32_t>(eMpiName::Barrier) + offset, MpiInfo(eMpiName::Barrier).description().localstr());
438 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
439 static_cast<uint32_t>(eMpiName::Reduce) + offset, MpiInfo(eMpiName::Reduce).description().localstr());
440 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
441 static_cast<uint32_t>(eMpiName::Allreduce) + offset, MpiInfo(eMpiName::Allreduce).description().localstr());
442 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
443 static_cast<uint32_t>(eMpiName::Scan) + offset, MpiInfo(eMpiName::Scan).description().localstr());
444 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
445 static_cast<uint32_t>(eMpiName::Sendrecv) + offset, MpiInfo(eMpiName::Sendrecv).description().localstr());
446 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
447 static_cast<uint32_t>(eMpiName::Isend) + offset, MpiInfo(eMpiName::Isend).description().localstr());
448 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
449 static_cast<uint32_t>(eMpiName::Send) + offset, MpiInfo(eMpiName::Send).description().localstr());
450 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
451 static_cast<uint32_t>(eMpiName::Irecv) + offset, MpiInfo(eMpiName::Irecv).description().localstr());
452 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
453 static_cast<uint32_t>(eMpiName::Recv) + offset, MpiInfo(eMpiName::Recv).description().localstr());
454 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
455 static_cast<uint32_t>(eMpiName::Test) + offset, MpiInfo(eMpiName::Test).description().localstr());
456 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
457 static_cast<uint32_t>(eMpiName::Probe) + offset, MpiInfo(eMpiName::Probe).description().localstr());
458 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
459 static_cast<uint32_t>(eMpiName::Get_count) + offset, MpiInfo(eMpiName::Get_count).description().localstr());
460 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
461 static_cast<uint32_t>(eMpiName::Wait) + offset, MpiInfo(eMpiName::Wait).description().localstr());
462 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
463 static_cast<uint32_t>(eMpiName::Waitall) + offset, MpiInfo(eMpiName::Waitall).description().localstr());
464 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
465 static_cast<uint32_t>(eMpiName::Testsome) + offset, MpiInfo(eMpiName::Testsome).description().localstr());
466 OTF2_GlobalDefWriter_WriteString(m_global_def_writer,
467 static_cast<uint32_t>(eMpiName::Waitsome) + offset, MpiInfo(eMpiName::Waitsome).description().localstr());
468
469 // On continu avec le reste, j'ai pas trouve d'idee geniale pour avoir un indice intelligent ...
470 offset *= 2;
471 // Chaine vide : 2 x eMpiName::NameOffset
472 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "");
473 // Nom du thread CPU mappe sur le process MPI : 2 x eMpiName::NameOffset + 1
474 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "Master Thread");
475 // Nom de la machine : 2 x eMpiName::NameOffset + 2
476 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, Arccore::Platform::getHostName().localstr());
477 // Classe de la machine... pas inspire... : 2 x eMpiName::NameOffset + 3
478 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "Compute node");
479 // MPI Communicator : 2 x eMpiName::NameOffset + 4
480 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "MPI_COMM_WORLD");
481 // MPI : 2 x eMpiName::NameOffset + 5
482 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "MPI");
483
484 // Comm id: 2 x eMpiName::NameOffset + 6
485 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "Comm ${id}");
486 // + 7
487 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "Win ${id}");
488 // + 8
489 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "MPI_COMM_SELF");
490
491 // Entry Point : 2 x eMpiName::NameOffset + 9
492 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "Entry Point");
493 // Synchronize : 2 x eMpiName::NameOffset + 10
494 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, "Synchronize");
495 // Application name : 2 x eMpiName::NameOffset + 11
496 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, m_sub_domain->application()->applicationName().localstr());
497 // On continu avec les noms des rangs MPI
498 for (Int32 i(0); i < m_sub_domain->nbSubDomain(); ++i) {
499 String mpi_rank_name(std::string("MPI Rank ") + std::to_string(i));
500 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, mpi_rank_name.localstr());
501 }
502 // On termine avec les points d'entree
503 for (auto i : m_sub_domain->timeLoopMng()->usedTimeLoopEntryPoints())
504 // On cree la definition otf2 pour le responsable des IOs
505 OTF2_GlobalDefWriter_WriteString(m_global_def_writer, offset++, i->fullName().localstr());
506}
507
508/*---------------------------------------------------------------------------*/
509/*---------------------------------------------------------------------------*/
514{
515 // Seul le sous-domaine responsable ecrit l'archive otf2
516 if (!m_sub_domain->parallelMng()->isMasterIO())
517 return;
518
521 attr_val.stringRef = m_id.m_comm_id;
524
525 attr_val.stringRef = m_id.m_win_id;
528
529 // Definition du systeme
530 OTF2_GlobalDefWriter_WriteSystemTreeNode(m_global_def_writer, 0 /* id */, m_id.m_hostname_id, m_id.m_class_id,
532}
533
534/*---------------------------------------------------------------------------*/
535/*---------------------------------------------------------------------------*/
539{
540 // On a besoin de connaitre le nb d'evenement par sous-domaine
542 UniqueArray<Integer> send_buffer(1, static_cast<Integer >(m_evt_nb));
543 m_sub_domain->parallelMng()->gather(send_buffer, recv_buffer, m_sub_domain->parallelMng()->masterIORank());
544
545 // Seul le sous-domaine responsable ecrit l'archive otf2
546 if (!m_sub_domain->parallelMng()->isMasterIO())
547 return;
548
549 // Location group pour tous les ranks MPI
550 for (Int32 i(0); i < m_sub_domain->nbSubDomain(); ++i) {
551 OTF2_GlobalDefWriter_WriteLocationGroup(m_global_def_writer, i /* id */,
552 m_id.m_rank_offset + i /* name */,
554 0 /* system tree */
555#if OTF2_VERSION_MAJOR >= 3
557#endif
558 );
559 }
560 for (Int32 i(0); i < m_sub_domain->nbSubDomain(); ++i) {
561 OTF2_GlobalDefWriter_WriteLocation(m_global_def_writer, i /* id */, m_id.m_thread_id /* name */,
562 OTF2_LOCATION_TYPE_CPU_THREAD, recv_buffer.at(i) /* # events */,
563 i /* location group */);
564 }
565}
566
567/*---------------------------------------------------------------------------*/
568/*---------------------------------------------------------------------------*/
573{
574 // Seul le sous-domaine responsable ecrit l'archive otf2
575 if (!m_sub_domain->parallelMng()->isMasterIO())
576 return;
577
578 // Definition des regions
579 // broadcast
580 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Bcast),
581 static_cast<uint32_t>(eMpiName::Bcast), static_cast<uint32_t>(eMpiName::Bcast),
582 static_cast<uint32_t>(eMpiName::Bcast) + m_id.m_desc_offset,
586 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
587 // gather
588 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Gather),
589 static_cast<uint32_t>(eMpiName::Gather), static_cast<uint32_t>(eMpiName::Gather),
590 static_cast<uint32_t>(eMpiName::Gather) + m_id.m_desc_offset,
594 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
595 // gather variable
596 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Gatherv),
597 static_cast<uint32_t>(eMpiName::Gatherv), static_cast<uint32_t>(eMpiName::Gatherv),
598 static_cast<uint32_t>(eMpiName::Gatherv) + m_id.m_desc_offset,
602 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
603 // all gather
604 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Allgather),
605 static_cast<uint32_t>(eMpiName::Allgather), static_cast<uint32_t>(eMpiName::Allgather),
606 static_cast<uint32_t>(eMpiName::Allgather) + m_id.m_desc_offset,
610 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
611 // all gather variable
612 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Allgatherv),
613 static_cast<uint32_t>(eMpiName::Allgatherv), static_cast<uint32_t>(eMpiName::Allgatherv),
614 static_cast<uint32_t>(eMpiName::Allgatherv) + m_id.m_desc_offset,
618 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
619 // scatter variable
620 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Scatterv),
621 static_cast<uint32_t>(eMpiName::Scatterv), static_cast<uint32_t>(eMpiName::Scatterv),
622 static_cast<uint32_t>(eMpiName::Scatterv) + m_id.m_desc_offset,
626 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
627 // all to all
628 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Alltoall),
629 static_cast<uint32_t>(eMpiName::Alltoall), static_cast<uint32_t>(eMpiName::Alltoall),
630 static_cast<uint32_t>(eMpiName::Alltoall) + m_id.m_desc_offset,
634 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
635 // all to all variable
636 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Alltoallv),
637 static_cast<uint32_t>(eMpiName::Alltoallv), static_cast<uint32_t>(eMpiName::Alltoallv),
638 static_cast<uint32_t>(eMpiName::Alltoallv) + m_id.m_desc_offset,
642 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
643 // barrier
644 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Barrier),
645 static_cast<uint32_t>(eMpiName::Barrier), static_cast<uint32_t>(eMpiName::Barrier),
646 static_cast<uint32_t>(eMpiName::Barrier) + m_id.m_desc_offset,
650 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
651 // reduce
652 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Reduce),
653 static_cast<uint32_t>(eMpiName::Reduce), static_cast<uint32_t>(eMpiName::Reduce),
654 static_cast<uint32_t>(eMpiName::Reduce) + m_id.m_desc_offset,
658 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
659 // all reduce
660 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Allreduce),
661 static_cast<uint32_t>(eMpiName::Allreduce), static_cast<uint32_t>(eMpiName::Allreduce),
662 static_cast<uint32_t>(eMpiName::Allreduce) + m_id.m_desc_offset,
666 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
667 // scan
668 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Scan),
669 static_cast<uint32_t>(eMpiName::Scan), static_cast<uint32_t>(eMpiName::Scan),
670 static_cast<uint32_t>(eMpiName::Scan) + m_id.m_desc_offset,
674 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
675 // sendrecv
676 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Sendrecv),
677 static_cast<uint32_t>(eMpiName::Sendrecv), static_cast<uint32_t>(eMpiName::Sendrecv),
678 static_cast<uint32_t>(eMpiName::Sendrecv) + m_id.m_desc_offset,
682 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
683 // non blocking send
684 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Isend),
685 static_cast<uint32_t>(eMpiName::Isend), static_cast<uint32_t>(eMpiName::Isend),
686 static_cast<uint32_t>(eMpiName::Isend) + m_id.m_desc_offset,
690 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
691 // blocking send
692 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Send),
693 static_cast<uint32_t>(eMpiName::Send), static_cast<uint32_t>(eMpiName::Send),
694 static_cast<uint32_t>(eMpiName::Send) + m_id.m_desc_offset,
698 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
699 // non blocking recv
700 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Irecv),
701 static_cast<uint32_t>(eMpiName::Irecv), static_cast<uint32_t>(eMpiName::Irecv),
702 static_cast<uint32_t>(eMpiName::Irecv) + m_id.m_desc_offset,
706 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
707 // blocking recv
708 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Recv),
709 static_cast<uint32_t>(eMpiName::Recv), static_cast<uint32_t>(eMpiName::Recv),
710 static_cast<uint32_t>(eMpiName::Recv) + m_id.m_desc_offset,
714 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
715 // test
716 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Test),
717 static_cast<uint32_t>(eMpiName::Test), static_cast<uint32_t>(eMpiName::Test),
718 static_cast<uint32_t>(eMpiName::Test) + m_id.m_desc_offset,
722 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
723 // probe
724 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Probe),
725 static_cast<uint32_t>(eMpiName::Probe), static_cast<uint32_t>(eMpiName::Probe),
726 static_cast<uint32_t>(eMpiName::Probe) + m_id.m_desc_offset,
730 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
731 // get count
732 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Get_count),
733 static_cast<uint32_t>(eMpiName::Get_count), static_cast<uint32_t>(eMpiName::Get_count),
734 static_cast<uint32_t>(eMpiName::Get_count) + m_id.m_desc_offset,
738 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
739 // wait
740 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Wait),
741 static_cast<uint32_t>(eMpiName::Wait), static_cast<uint32_t>(eMpiName::Wait),
742 static_cast<uint32_t>(eMpiName::Wait) + m_id.m_desc_offset,
746 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
747 // wait all
748 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Waitall),
749 static_cast<uint32_t>(eMpiName::Waitall), static_cast<uint32_t>(eMpiName::Waitall),
750 static_cast<uint32_t>(eMpiName::Waitall) + m_id.m_desc_offset,
754 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
755 // test some
756 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Testsome),
757 static_cast<uint32_t>(eMpiName::Testsome), static_cast<uint32_t>(eMpiName::Testsome),
758 static_cast<uint32_t>(eMpiName::Testsome) + m_id.m_desc_offset,
762 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
763 // wait some
764 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(eMpiName::Waitsome),
765 static_cast<uint32_t>(eMpiName::Waitsome), static_cast<uint32_t>(eMpiName::Waitsome),
766 static_cast<uint32_t>(eMpiName::Waitsome) + m_id.m_desc_offset,
770 m_id.m_mpi_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
771 // Pour les points d'entree
772 for (const auto& i : m_id.m_ep_id_set) {
773 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, static_cast<uint32_t>(i.m_id),
774 static_cast<uint32_t>(i.m_id), static_cast<uint32_t>(i.m_id),
775 static_cast<uint32_t>(i.m_id),
779 m_id.m_ep_id, 0, 0); // 0,0 pour les numeros de lignes des src...
780 }
781 // synchronize
782 OTF2_GlobalDefWriter_WriteRegion(m_global_def_writer, m_id.m_sync_id,
783 m_id.m_sync_id, m_id.m_sync_id, m_id.m_sync_id,
787 m_id.m_sync_id, 0, 0); // 0,0 pour les numeros de lignes du src MPI.c ...
788}
789
790/*---------------------------------------------------------------------------*/
791/*---------------------------------------------------------------------------*/
797{
798 // Seul le sous-domaine responsable ecrit l'archive otf2
799 if (!m_sub_domain->parallelMng()->isMasterIO())
800 return;
801
802 // Definitions des sous groupes de communication (nous n'en avons pas donc ce sont les memes)
803 OTF2_GlobalDefWriter_WriteGroup(m_global_def_writer, 0 /* id */, m_id.m_empty_id /* name */,
805 m_sub_domain->nbSubDomain(), m_comm_members.data());
806
807 OTF2_GlobalDefWriter_WriteGroup(m_global_def_writer, 1 /* id */, m_id.m_empty_id /* name */,
809 OTF2_GROUP_FLAG_NONE, m_sub_domain->nbSubDomain(), m_comm_members.data());
810
811 OTF2_GlobalDefWriter_WriteGroup(m_global_def_writer, 2 /* id */, m_id.m_empty_id /* name */,
814
815 // Definition du communicateur associe au groupe des comm
816 OTF2_GlobalDefWriter_WriteComm(m_global_def_writer, 0 /* id */, m_id.m_comm_world_id, 1 /* group */,
817 OTF2_UNDEFINED_COMM /* parent */
818#if OTF2_VERSION_MAJOR >= 3
819 ,0
820#endif
821 );
822
823 OTF2_GlobalDefWriter_WriteComm(m_global_def_writer, 1 /* id */, m_id.m_comm_self_id, 2 /* group */,
824 OTF2_UNDEFINED_COMM /* parent */
825#if OTF2_VERSION_MAJOR >= 3
826 ,0
827#endif
828 );
829
830 // Fermeture de la definition de l'archive pour enfin ecrire tout ca
831 OTF2_Archive_CloseGlobalDefWriter(m_archive, m_global_def_writer);
832}
833
834/*---------------------------------------------------------------------------*/
835/*---------------------------------------------------------------------------*/
836
837} // namespace Arcane
838
839/*---------------------------------------------------------------------------*/
840/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual Int32 subDomainId() const =0
Numéro du sous-domaine associé à ce gestionnaire.
virtual IApplication * application()=0
Application.
virtual IParallelMng * parallelMng()=0
Retourne le gestionnaire de parallélisme.
virtual const IDirectory & listingDirectory() const =0
Répertoire de base des listings (logs, info exécution).
virtual ITimeLoopMng * timeLoopMng()=0
Retourne le gestionnaire de la boucle en temps.
virtual Int32 nbSubDomain() const =0
Nombre total de sous-domaines.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Otf2LibWrapper(ISubDomain *sub_domain)
Constructeur.
~Otf2LibWrapper()
Destructeur.
void _buildOtf2ClockAndStringDefinition(uint64_t global_start_time, uint64_t global_end_time)
static uint64_t s_epoch_start
Static member.
void init(const String &archive_name)
Methode d'initialisation. Permet de definir le chemin ou va se trouver l'archive ainsi que son nom.
void _buildOtf2ParadigmAndSystemDefinition()
uint32_t getApplicationNameId() const
Helper sur le nom de l'application.
OTF2_EvtWriter * getEventWriter()
int getMpiNbRank() const
Helper sur le nombre de rank MPI.
void _buildOtf2LocationDefinition()
Methode interne pour ecrire la definition du systeme associee a l'archive otf2.
static OTF2_TimeStamp getTime()
Méthode interne statique pour recuperer le timestamp.
void finalize()
Methode a appeler pour finaliser la creation de l'archive (i.e. on ne veut plus enregistrer plus d'ev...
static OTF2_TimeStamp _postFlush(void *user_data, OTF2_FileType file_type, OTF2_LocationRef location)
Méthode interne statique pour positionner la callback a appeler apres l'evenement a enregistrer.
static OTF2_FlushType _preFlush(void *user_data, OTF2_FileType file_type, OTF2_LocationRef location, void *caller_data, bool final)
Méthode interne statique pour positionner la callback a appeler avant l'evenement a enregistrer.
int getMpiRank() const
Helper sur le numero de rank MPI.
uint32_t getEntryPointId(const String &ep_name) const
Helper pour l'id d'un point d'entree via son nom.
uint32_t getSynchronizeId() const
Helper sur la chaine de charactere "syncrhonize".
Structure informative liee aux enumerationx pour les operations MPI. Donne le nom associe a l'enum ai...
Chaîne de caractères unicode.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
ARCCORE_BASE_EXPORT String getHostName()
Nom de la machine sur lequel tourne le processus.