| The Gaudi Framework v27r1

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