| The Gaudi Framework v29r0 (ff2e7097)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

IntelProfilerAuditor.cpp
Go to the documentation of this file.
1 // ## Includes.
2 // * Standard libraries.
3 #include <algorithm>
4 #include <iomanip>
5 #include <memory>
6 #include <sstream>
7 #include <stack>
8 #include <string>
9 #include <utility>
10 #include <vector>
11
12 // * Gaudi libraries.
13 #include "GaudiKernel/Auditor.h"
14 #include "GaudiKernel/GaudiException.h"
15 #include "GaudiKernel/IAuditorSvc.h"
16 #include "GaudiKernel/IIncidentListener.h"
17 #include "GaudiKernel/IIncidentSvc.h"
18 #include "GaudiKernel/MsgStream.h"
19
20 // * Intel User API
21 #ifdef __GNUC__
22 #pragma GCC diagnostic ignored "-Wunused-function"
23 #endif
24 #include "ittnotify.h"
25
26 typedef std::map<std::string, __itt_event> TaskTypes;
27
28 // Gaudi profiling auditor. The auditor use Intel API for control profiling
29 // flow. We need to run profiling throw Intel Amplifier amplxe-cl command
30 // line tool.
31 class IntelProfilerAuditor : public extends<Auditor, IIncidentListener>
32 {
33 public:
34 // ## Public functions.
35 using extends::extends;
36 StatusCode initialize() override;
37 // Overridden functions.
38 void handle( const Incident& incident ) override;
39 using Auditor::before; // avoid hiding base-class methods
40 void before( StandardEventType type, INamedInterface* i ) override;
41 using Auditor::after; // avoid hiding base-class methods
42 void after( StandardEventType type, INamedInterface* i, const StatusCode& sc ) override;
43 // ## Private attributes.
44 private:
45 // Stack for store current component(algorithm) chain with useful
46 // information for the auditor.
47 struct stack_entity {
48 stack_entity( const std::string& name_, bool status_, const __itt_event event_ = 0,
49 const __itt_event parent_event_ = 0 )
50 : name( name_ ), status( status_ ), event( event_ ), parent_event( parent_event_ )
51 {
52 }
53 // Name of the component.
54 std::string name;
55 // Running status: on/off.
56 bool status;
57 // Task type holder.
58 __itt_event event;
59 // Parent task type.
60 __itt_event parent_event;
61 };
62
63 private:
64 Gaudi::Property<std::vector<std::string>> m_included{this, "IncludeAlgorithms", {}, "Names of included algorithms."};
65 Gaudi::Property<std::vector<std::string>> m_excluded{this, "ExcludeAlgorithms", {}, "Names of excluded algorithms."};
66 Gaudi::Property<int> m_nStartFromEvent{
67 this, "StartFromEventN", 1, "After what event we stop profiling. If 0 than we also profile finalization stage."};
68 Gaudi::Property<int> m_nStopAtEvent{
69 this, "StopAtEventN", 0,
70 "After what event we stop profiling. If 0 than we also profile finalization stage. Default = 0."};
71 Gaudi::Property<std::vector<std::string>> m_algs_for_tasktypes{
72 this,
73 "ComponentsForTaskTypes",
74 {},
75 "Algorithm name, for which intel amplifier task type will be created."
76 "By default all algorithms have a corresponding task type."};
77 Gaudi::Property<std::string> m_alg_delim{this, "TaskTypeNameDelimeter", " ",
78 "The String delimiter between sequences/algorithms names in "
79 "\"Task Type\" grouping at Amplifier. Default=\" \"."};
80 Gaudi::Property<bool> m_enable_frames{this, "EnableFrames", false,
81 "Enable frames (needed for detecting slow events). Default=false."};
82 Gaudi::Property<int> m_frames_rate{this, "FramesRate", 100,
83 "Frames rate. The recommended maximum rate for calling the Frame API is "
84 "1000 frames (events) per second. A higher rate may result in large product"
85 " memory consumption and slow finalization. "
86 "You need update \"slow-frames-threshold\" and \"fast-frames-threshold\" "
87 "parameters of amplxe-cl tool to separate slow, medium and fast events. "
88 "For use frames you need to switch on \"EnableFrames\". "
89 "Default=100"};
90
91 private:
92 // Events counter.
93 int m_nEvents = 0;
94 // Domain for event loop.
95 __itt_domain* domain = nullptr;
96 // True if profiler is started.
97 bool m_isStarted = false;
98 // Current stack of sequences/algorithms.
99 std::vector<stack_entity> m_stack;
100 // Mapping of task type name to Amplifier event .
101 TaskTypes m_tasktypes;
102
103 private:
104 // ## Private functions.
105 void start_profiling_component( const std::string& name );
106 void skip_profiling_component( const std::string& name );
107
108 void start();
109 void pause();
110 void resume();
111 void stop();
112
113 bool hasIncludes() const;
114 bool isIncluded( const std::string& name ) const;
115 bool isExcluded( const std::string& name ) const;
116 bool isRunning() const;
117
118 int stackLevel() const;
119 std::string stackIndent( bool newLevel = false ) const;
120 std::string taskTypeName( const std::string& component_name ) const;
121 };
122 // ## Implementation.
123 void IntelProfilerAuditor::start()
124 {
125 m_isStarted = true;
126 __itt_resume();
127 }
128
129 void IntelProfilerAuditor::start_profiling_component( const std::string& name )
130 {
131 if ( !m_isStarted ) return;
132 std::string typeName = taskTypeName( name );
133 __itt_event taskId = 0;
134 TaskTypes::const_iterator iter = m_tasktypes.find( typeName );
135 if ( iter != m_tasktypes.end() ) {
136 taskId = iter->second;
137 }
138
139 if ( !taskId && m_algs_for_tasktypes.empty() ) {
140 // Create event
141 taskId = __itt_event_create( typeName.c_str(), typeName.size() );
142 m_tasktypes.insert( TaskTypes::value_type( typeName, taskId ) );
143 }
144
145 stack_entity state = stack_entity( name, true, taskId );
146 stack_entity* parent = !m_stack.empty() ? &m_stack.back() : NULL;
147
148 if ( parent != NULL ) {
149 if ( parent->event ) {
150 state.parent_event = parent->event;
151 } else {
152 state.parent_event = parent->parent_event;
153 }
154 }
155
156 if ( taskId && state.parent_event ) {
157 debug() << stackIndent() << "Pause event " << state.parent_event << endmsg;
158 __itt_event_end( state.parent_event );
159 }
160 m_stack.push_back( state );
161
162 debug() << stackIndent() << "Start profiling component " << typeName << endmsg;
163
164 if ( taskId ) {
165 // Start event
166 debug() << stackIndent() << "Start event type " << state.event << " for " << typeName << endmsg;
167 __itt_event_start( state.event );
168 }
169
170 __itt_resume();
171 }
172
173 void IntelProfilerAuditor::resume()
174 {
175 if ( !m_isStarted ) return;
176 debug() << stackIndent() << "Resume" << endmsg;
177 __itt_resume();
178 }
179
180 void IntelProfilerAuditor::pause()
181 {
182 if ( !m_isStarted ) return;
183 debug() << stackIndent() << "Pause" << endmsg;
184 __itt_pause();
185 }
186
187 void IntelProfilerAuditor::skip_profiling_component( const std::string& name )
188 {
189 if ( !m_isStarted ) return;
190 m_stack.push_back( stack_entity( name, false ) );
191 debug() << stackIndent() << "Skip component " << name << endmsg;
192 }
193
194 void IntelProfilerAuditor::stop()
195 {
196 if ( !m_isStarted ) return;
197 m_isStarted = false;
198 __itt_pause();
199 }
200
201 bool IntelProfilerAuditor::hasIncludes() const { return !m_included.empty(); }
202
203 bool IntelProfilerAuditor::isIncluded( const std::string& name ) const
204 {
205 return std::find( m_included.begin(), m_included.end(), name ) != m_included.end();
206 }
207
208 bool IntelProfilerAuditor::isExcluded( const std::string& name ) const
209 {
210 return std::find( m_excluded.begin(), m_excluded.end(), name ) != m_excluded.end();
211 }
212
213 bool IntelProfilerAuditor::isRunning() const { return !m_stack.empty() && m_stack.back().status; }
214
215 int IntelProfilerAuditor::stackLevel() const { return m_stack.size(); }
216
217 std::string IntelProfilerAuditor::stackIndent( bool newLevel ) const
218 {
219 std::stringstream indent( std::stringstream::out );
220 indent << std::setw( stackLevel() * 2 + ( newLevel ? 2 : 0 ) ) << " ";
221 return indent.str();
222 }
223
224 std::string IntelProfilerAuditor::taskTypeName( const std::string& component_name ) const
225 {
226 std::string result;
227 std::string delim = "";
228 for ( const auto& value : m_stack ) {
229 result += delim + value.name;
230 delim = m_alg_delim;
231 }
232 return result + m_alg_delim + component_name;
233 }
234
235 StatusCode IntelProfilerAuditor::initialize()
236 {
237 info() << "Initialised" << endmsg;
238
239 IIncidentSvc* inSvc = NULL;
240 const StatusCode sc = serviceLocator()->service( "IncidentSvc", inSvc );
241 if ( sc.isFailure() ) return sc;
242 // Useful to start profiling only after some event, we don't need profile
243 // initialization stage. For that we need to count events with BeginEvent
244 // listener.
245 inSvc->addListener( this, IncidentType::BeginEvent );
246 // If the end event number don't setup we finish profiling at the end
247 // of loop. We don't need profiling finalization stage.
248 inSvc->addListener( this, IncidentType::EndProcessing );
249
250 std::string str_excluded, str_included, str_eventtypes;
251 for ( const auto& name : m_excluded ) {
252 str_excluded += " " + name;
253 }
254 for ( const auto& name : m_included ) {
255 str_included += " " + name;
256 }
257 for ( const auto& name : m_algs_for_tasktypes ) {
258 str_eventtypes += " " + name;
259 }
260
261 if ( !m_included.empty() ) {
262 info() << "Included algorithms (" << m_included.size() << "): " << str_included << endmsg;
263 }
264
265 if ( !m_excluded.empty() ) {
266 info() << "Excluded algorithms (" << m_excluded.size() << "): " << str_excluded << endmsg;
267 }
268
269 if ( !m_algs_for_tasktypes.empty() ) {
270 info() << "Event types (" << m_algs_for_tasktypes.size() << "): " << str_eventtypes << endmsg;
271 }
272
273 // Create a profiler domain for detection of slow events.
274 domain = __itt_domain_create( "Event loop" );
275 domain->flags = m_enable_frames;
276
277 return StatusCode::SUCCESS;
278 }
279
280 void IntelProfilerAuditor::handle( const Incident& incident )
281 {
282 if ( IncidentType::BeginEvent != incident.type() ) return;
283 // Increment the event counter
284 ++m_nEvents;
285
286 if ( m_nStartFromEvent == m_nEvents ) {
287 info() << "Start profiling (event #" << m_nEvents << ")" << endmsg;
288 start();
289 }
290
291 if ( m_nStopAtEvent == m_nEvents ) {
292 info() << "Stop profiling (event #" << m_nEvents << ")" << endmsg;
293 stop();
294 }
295 }
296
297 void IntelProfilerAuditor::before( StandardEventType type, INamedInterface* i )
298 {
299 // Skip unnecessary event types.
300 if ( !( ( type == IAuditor::Execute ) && m_isStarted ) ) return;
301
302 // Name of the current component.
303 const std::string& name = i->name();
304 // debug() << "Before: " << name << " " << type << endmsg;
305
306 if ( isRunning() ) {
307 if ( isExcluded( name ) ) {
308 // If profiling is running and component is explicitly excluded
309 // then skip component.
310 skip_profiling_component( name );
311 } else {
312 // If profiling is running and component is'not explicitly excluded
313 // then start profiling for component (add to stack).
314 start_profiling_component( name );
315 }
316 } else {
317 if ( hasIncludes() ) {
318 // If the profiling is not running and "includes" is explicitly defined ...
319 if ( isIncluded( name ) ) {
320 // and the current component is in the include's list then start the
321 // component profiling.
322 start_profiling_component( name );
323 } else {
324 // and the current component is not in the includes list then skip
325 // a profiling of the component.
326 skip_profiling_component( name );
327 }
328 } else {
329 // If "Includes" property isn't present and the component is ...
330 if ( isExcluded( name ) ) {
331 // in the excludes list then skip a profiling
332 skip_profiling_component( name );
333 } else {
334 // not in the exclude list then start a profiling
335 start_profiling_component( name );
336 }
337 }
338 }
339 if ( m_nEvents % m_frames_rate == 0 ) {
340 __itt_frame_begin_v3( domain, NULL );
341 }
342 }
343
344 void IntelProfilerAuditor::after( StandardEventType type, INamedInterface* i, const StatusCode& /* sc*/ )
345 {
346 // Skip unnecessary event types
347 if ( !( ( type == IAuditor::Execute ) && m_isStarted ) ) return;
348
349 if ( ( m_nEvents + 1 ) % m_frames_rate == 0 ) {
350 __itt_frame_end_v3( domain, NULL );
351 }
352
353 // Name of the current component
354 const std::string& name = i->name();
355 stack_entity state = m_stack.back();
356 // Remove component from stack.
357 m_stack.pop_back();
358
359 if ( state.event != 0 ) {
360 debug() << stackIndent( true ) << "End event for " << name << endmsg;
361 __itt_event_end( state.event );
362
363 if ( state.parent_event != 0 ) {
364 debug() << stackIndent() << "Resume event for " << state.parent_event << endmsg;
365 __itt_event_start( state.parent_event );
366 }
367 }
368
369 if ( m_stack.empty() ) {
370 // Pause if there are no parent components (top algorithm).
371 pause();
372 } else if ( state.status ) {
373 // If the profiling is running and we have parent component that is
374 // paused then pause the profiling.
375 if ( !m_stack.back().status ) {
376 pause();
377 }
378 } else {
379 // If the profiling was stopped, but the parent component should be profiled
380 // then resume profiling.
381 if ( m_stack.back().status ) {
382 resume();
383 }
384 }
385 }
386
387 // Register the auditor
388 DECLARE_COMPONENT( IntelProfilerAuditor )
IntelProfilerAuditor::start_profiling_component
void start_profiling_component(const std::string &name)
Definition: IntelProfilerAuditor.cpp:129
TaskTypes
std::map< std::string, __itt_event > TaskTypes
Definition: IntelProfilerAuditor.cpp:26
IntelProfilerAuditor::m_nStartFromEvent
Gaudi::Property< int > m_nStartFromEvent
Definition: IntelProfilerAuditor.cpp:66
StatusCode::SUCCESS
Definition: StatusCode.h:31
IntelProfilerAuditor::m_nStopAtEvent
Gaudi::Property< int > m_nStopAtEvent
Definition: IntelProfilerAuditor.cpp:68
Incident::type
const std::string & type() const
Access to the incident type.
Definition: Incident.h:41
compareRootHistos.state
state
Definition: compareRootHistos.py:422
Gaudi::Property
Implementation of property with value of concrete type.
Definition: Property.h:319
MsgStream.h
IntelProfilerAuditor::resume
void resume()
Definition: IntelProfilerAuditor.cpp:173
CommonMessagingBase::info
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
Definition: CommonMessaging.h:117
IntelProfilerAuditor::after
void after(StandardEventType type, INamedInterface *i, const StatusCode &sc) override
Definition: IntelProfilerAuditor.cpp:344
IntelProfilerAuditor::m_algs_for_tasktypes
Gaudi::Property< std::vector< std::string > > m_algs_for_tasktypes
Definition: IntelProfilerAuditor.cpp:71
IAuditorSvc.h
IntelProfilerAuditor::skip_profiling_component
void skip_profiling_component(const std::string &name)
Definition: IntelProfilerAuditor.cpp:187
IntelProfilerAuditor::isRunning
bool isRunning() const
Definition: IntelProfilerAuditor.cpp:213
IntelProfilerAuditor::stack_entity::name
std::string name
Definition: IntelProfilerAuditor.cpp:54
IntelProfilerAuditor
Definition: IntelProfilerAuditor.cpp:31
IntelProfilerAuditor::m_included
Gaudi::Property< std::vector< std::string > > m_included
Definition: IntelProfilerAuditor.cpp:64
IntelProfilerAuditor::domain
__itt_domain * domain
Definition: IntelProfilerAuditor.cpp:95
IntelProfilerAuditor::isExcluded
bool isExcluded(const std::string &name) const
Definition: IntelProfilerAuditor.cpp:208
std::map::end
T end(T...args)
IntelProfilerAuditor::initialize
StatusCode initialize() override
Definition: IntelProfilerAuditor.cpp:235
IntelProfilerAuditor::m_frames_rate
Gaudi::Property< int > m_frames_rate
Definition: IntelProfilerAuditor.cpp:82
std::map< std::string, __itt_event >
StatusCode::isFailure
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
std::stringstream
STL class.
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:33
std::setw
T setw(T...args)
IntelProfilerAuditor::stack_entity::parent_event
__itt_event parent_event
Definition: IntelProfilerAuditor.cpp:60
std::string
STL class.
IntelProfilerAuditor::m_tasktypes
TaskTypes m_tasktypes
Definition: IntelProfilerAuditor.cpp:101
ISvcLocator::service
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:79
IntelProfilerAuditor::stack_entity::event
__itt_event event
Definition: IntelProfilerAuditor.cpp:58
IntelProfilerAuditor::stack_entity::stack_entity
stack_entity(const std::string &name_, bool status_, const __itt_event event_=0, const __itt_event parent_event_=0)
Definition: IntelProfilerAuditor.cpp:48
IntelProfilerAuditor::stackLevel
int stackLevel() const
Definition: IntelProfilerAuditor.cpp:215
IntelProfilerAuditor::m_nEvents
int m_nEvents
Definition: IntelProfilerAuditor.cpp:93
IIncidentSvc.h
StatusCode
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:28
IntelProfilerAuditor::start
void start()
Definition: IntelProfilerAuditor.cpp:123
Auditor::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Auditor.cpp:206
GaudiException.h
gaudirun.type
type
Definition: gaudirun.py:133
Auditor::after
void after(StandardEventType, INamedInterface *, const StatusCode &) override
Definition: Auditor.cpp:110
IntelProfilerAuditor::m_excluded
Gaudi::Property< std::vector< std::string > > m_excluded
Definition: IntelProfilerAuditor.cpp:65
std::stringstream::str
T str(T...args)
IntelProfilerAuditor::pause
void pause()
Definition: IntelProfilerAuditor.cpp:180
IntelProfilerAuditor::m_enable_frames
Gaudi::Property< bool > m_enable_frames
Definition: IntelProfilerAuditor.cpp:80
IntelProfilerAuditor::m_stack
std::vector< stack_entity > m_stack
Definition: IntelProfilerAuditor.cpp:99
IntelProfilerAuditor::stackIndent
std::string stackIndent(bool newLevel=false) const
Definition: IntelProfilerAuditor.cpp:217
std::map::insert
T insert(T...args)
INamedInterface
IInterface compliant class extending IInterface with the name() method.
Definition: INamedInterface.h:15
std::map::find
T find(T...args)
IntelProfilerAuditor::taskTypeName
std::string taskTypeName(const std::string &component_name) const
Definition: IntelProfilerAuditor.cpp:224
std::string::size
T size(T...args)
IntelProfilerAuditor::m_alg_delim
Gaudi::Property< std::string > m_alg_delim
Definition: IntelProfilerAuditor.cpp:77
std::vector
STL class.
CommonMessagingBase::debug
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
Definition: CommonMessaging.h:120
extends
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
IntelProfilerAuditor::handle
void handle(const Incident &incident) override
Definition: IntelProfilerAuditor.cpp:280
std::string::c_str
T c_str(T...args)
Incident
Base class for all Incidents (computing events).
Definition: Incident.h:17
IntelProfilerAuditor::hasIncludes
bool hasIncludes() const
Definition: IntelProfilerAuditor.cpp:201
IntelProfilerAuditor::stack_entity
Definition: IntelProfilerAuditor.cpp:47
IIncidentSvc::addListener
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)=0
Add listener.
IAuditor::Execute
Definition: IAuditor.h:25
IntelProfilerAuditor::isIncluded
bool isIncluded(const std::string &name) const
Definition: IntelProfilerAuditor.cpp:203
IIncidentListener.h
IntelProfilerAuditor::stack_entity::status
bool status
Definition: IntelProfilerAuditor.cpp:56
GaudiDict::typeName
std::string typeName(const std::type_info &typ)
Definition: Dictionary.cpp:23
Auditor.h
Auditor::before
void before(StandardEventType, INamedInterface *) override
The following methods are meant to be implemented by the child class...
Definition: Auditor.cpp:73
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
INamedInterface::name
virtual const std::string & name() const =0
Retrieve the name of the instance.
IntelProfilerAuditor::stop
void stop()
Definition: IntelProfilerAuditor.cpp:194
IIncidentSvc
The interface implemented by the IncidentSvc service.
Definition: IIncidentSvc.h:23
IntelProfilerAuditor::m_isStarted
bool m_isStarted
Definition: IntelProfilerAuditor.cpp:97
IntelProfilerAuditor::before
void before(StandardEventType type, INamedInterface *i) override
Definition: IntelProfilerAuditor.cpp:297