Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
Otf2MessagePassingProfilingService.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* Otf2MessagePassingProfilingService.cc (C) 2000-2020 */
9/* */
10/* Performance information for "message passing" in Otf2 format */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/std/Otf2MessagePassingProfilingService.h"
15
16#include "arcane/utils/ITraceMng.h"
17
19#include "arcane/core/CommonVariables.h"
20#include "arcane/core/IMesh.h"
21#include "arcane/core/IItemFamily.h"
22#include "arcane/core/IVariableSynchronizer.h"
23#include "arcane/core/ITimeLoopMng.h"
24#include "arcane/core/IParallelMng.h"
25#include "arcane/core/IEntryPoint.h"
26
27#include "arcane/parallel/IStat.h"
28
29#include "arccore/message_passing/IMessagePassingMng.h"
30#include "arccore/message_passing/IDispatchers.h"
31#include "arccore/message_passing/IControlDispatcher.h"
32
33#include <algorithm>
34#include <string>
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
39namespace Arcane
40{
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
46 ServiceProperty("Otf2MessagePassingProfiling",ST_SubDomain),
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52Otf2MessagePassingProfilingService::
53Otf2MessagePassingProfilingService(const ServiceBuildInfo& sbi)
54: AbstractService(sbi)
55, m_sub_domain(sbi.subDomain())
56, m_otf2_wrapper(sbi.subDomain())
57, m_otf2_prof(&m_otf2_wrapper)
58, m_prof_backup(nullptr)
59, m_impl_name("Otf2MessagePassingProfiling")
60{
61}
62
63/*---------------------------------------------------------------------------*/
64/*---------------------------------------------------------------------------*/
65
66Otf2MessagePassingProfilingService::
67~Otf2MessagePassingProfilingService() noexcept
68{
69}
70
71/*---------------------------------------------------------------------------*/
72/*---------------------------------------------------------------------------*/
73
74void Otf2MessagePassingProfilingService::
75startProfiling()
76{
77 // DBG
78 //info() << "========== OTF2 PROFILING SERVICE ! ==========";
79
80 // Initialize the otf2 library
81 m_otf2_wrapper.init(m_sub_domain->application()->applicationName());
82
83 IMessagePassingMng* mp_mng = m_sub_domain->parallelMng()->messagePassingMng();
84 IControlDispatcher* cd = mp_mng->dispatchers()->controlDispatcher();
85 m_control_dispatcher = cd;
86
87 // Save the old MPI profiling service to reposition it
88 m_prof_backup = cd->profiler();
89
90 // Position the OTF2 decorator for MPI calls
91 cd->setProfiler(&m_otf2_prof);
92
93 // When starting profiling, we begin observing timeLoopMng events
94 // Entry point start event
95 m_observer.addObserver(this, &Otf2MessagePassingProfilingService::_updateFromBeginEntryPointEvt,
96 m_sub_domain->timeLoopMng()->observable(eTimeLoopEventType::BeginEntryPoint));
97
98 // Entry point end event
99 m_observer.addObserver(this, &Otf2MessagePassingProfilingService::_updateFromEndEntryPointEvt,
100 m_sub_domain->timeLoopMng()->observable(eTimeLoopEventType::EndEntryPoint));
101
102 // It is the same function for all synchronization events
103 auto sync_evt_handler = std::function<void(const Arcane::VariableSynchronizerEventArgs&)>(
104 std::bind(&Otf2MessagePassingProfilingService::_updateFromSynchronizeEvt, this, std::placeholders::_1));
105
106 // Synchronization event on cell variables
107 m_sub_domain->defaultMesh()->cellFamily()->allItemsSynchronizer()->onSynchronized().attach(m_observer_pool,
108 sync_evt_handler);
109 // Synchronization event on node variables
110 m_sub_domain->defaultMesh()->nodeFamily()->allItemsSynchronizer()->onSynchronized().attach(m_observer_pool,
111 sync_evt_handler);
112 // Synchronization event on edge variables
113 m_sub_domain->defaultMesh()->edgeFamily()->allItemsSynchronizer()->onSynchronized().attach(m_observer_pool,
114 sync_evt_handler);
115 // Synchronization event on face variables
116 m_sub_domain->defaultMesh()->faceFamily()->allItemsSynchronizer()->onSynchronized().attach(m_observer_pool,
117 sync_evt_handler);
118 // TODO: do it for material variables
119
120 // Start program profiling
121 OTF2_EvtWriter_ProgramBegin(m_otf2_wrapper.getEventWriter(), NULL, Otf2LibWrapper::getTime(),
122 m_otf2_wrapper.getApplicationNameId(), 0, NULL);
123}
124
125/*---------------------------------------------------------------------------*/
126/*---------------------------------------------------------------------------*/
127
128void Otf2MessagePassingProfilingService::
129stopProfiling()
130{
131 // Remove the OTF2 decorator from MPI calls
132 if (m_control_dispatcher)
133 m_control_dispatcher->setProfiler(m_prof_backup);
134
135 // Finish program profiling
136 OTF2_EvtWriter_ProgramEnd(m_otf2_wrapper.getEventWriter(), NULL, Otf2LibWrapper::getTime(), 0);
137 m_otf2_wrapper.finalize();
138
139 // Stop observations
140 m_observer.detachAll();
141}
142
143/*---------------------------------------------------------------------------*/
144/*---------------------------------------------------------------------------*/
145void Otf2MessagePassingProfilingService::
146printInfos(std::ostream& output)
147{
148 ARCANE_UNUSED(output);
149 // TODO: should we do something here?
150}
151
152/*---------------------------------------------------------------------------*/
153/*---------------------------------------------------------------------------*/
154String Otf2MessagePassingProfilingService::
155implName()
156{
157 return m_impl_name;
158}
159
160/*---------------------------------------------------------------------------*/
161/*---------------------------------------------------------------------------*/
162
163void Otf2MessagePassingProfilingService::
164_updateFromBeginEntryPointEvt()
165{
166 // Retrieve the entry point name
167 const String& ep_name(m_sub_domain->timeLoopMng()->currentEntryPoint()->fullName());
168
169 OTF2_EvtWriter_Enter(m_otf2_wrapper.getEventWriter(), NULL, Otf2LibWrapper::getTime(),
170 m_otf2_wrapper.getEntryPointId(ep_name));
171}
172
173/*---------------------------------------------------------------------------*/
174/*---------------------------------------------------------------------------*/
175
176void Otf2MessagePassingProfilingService::
177_updateFromEndEntryPointEvt()
178{
179 // Retrieve the entry point name
180 const String& ep_name(m_sub_domain->timeLoopMng()->currentEntryPoint()->fullName());
181
182 OTF2_EvtWriter_Leave(m_otf2_wrapper.getEventWriter(), NULL, Otf2LibWrapper::getTime(),
183 m_otf2_wrapper.getEntryPointId(ep_name));
184}
185
186/*---------------------------------------------------------------------------*/
187/*---------------------------------------------------------------------------*/
188
189void Otf2MessagePassingProfilingService::
190_updateFromSynchronizeEvt(const VariableSynchronizerEventArgs& arg)
191{
192 if (arg.state() == VariableSynchronizerEventArgs::State::BeginSynchronize)
193 OTF2_EvtWriter_Enter(m_otf2_wrapper.getEventWriter(), NULL, Otf2LibWrapper::getTime(),
194 m_otf2_wrapper.getSynchronizeId());
195 else
196 OTF2_EvtWriter_Leave(m_otf2_wrapper.getEventWriter(), NULL, Otf2LibWrapper::getTime(),
197 m_otf2_wrapper.getSynchronizeId());
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
203} // namespace Arcane
204
205/*---------------------------------------------------------------------------*/
206/*---------------------------------------------------------------------------*/
This file contains the various service factories and macros for registering services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro to declare an interface when registering a service.
Base class of a service.
Interface of a profiling service dedicated to "message passing".
Manage control streams for parallel messages.
Interface of the message passing manager.
static OTF2_TimeStamp getTime()
Internal static method to retrieve the timestamp.
Profiling service for "message passing" in JSON format.
Structure containing the information to create a service.
Service creation properties.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro for registering a service.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
@ ST_SubDomain
The service is used at the subdomain level.