Gaudi Framework, version v23r5

Home   Generated: Wed Nov 28 2012
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 // * Boost
13 #include <boost/foreach.hpp>
14 
15 // * Gaudi libraries.
16 #include "GaudiKernel/AudFactory.h"
17 #include "GaudiKernel/Auditor.h"
20 #include "GaudiKernel/MsgStream.h"
23 
24 // * Intel User API
25 #ifdef __GNUC__
26 #pragma GCC diagnostic ignored "-Wunused-function"
27 #endif
28 #include "ittnotify.h"
29 
31 
32 // Gaudi profiling auditor. The auditor use Intel API for control profiling
33 // flow. We need to run profiling throw Intel Amplifier amplxe-cl command
34 // line tool.
35 class IntelProfilerAuditor: public Auditor, virtual public IIncidentListener {
36 public:
37  // ## Public functions.
38  IntelProfilerAuditor(const std::string& name, ISvcLocator* pSvcLocator);
40  // Overridden functions.
41  void handle(const Incident& incident);
42  using Auditor::before; // avoid hiding base-class methods
43  void before(StandardEventType type, INamedInterface* i);
44  using Auditor::after; // avoid hiding base-class methods
45  void after(StandardEventType type, INamedInterface* i, const StatusCode& sc);
46 // ## Private attributes.
47 private:
48  // Stack for store current component(algorithm) chain with useful
49  // information for the auditor.
50  struct stack_entity {
51  stack_entity(const std::string& name_, bool status_,
52  const __itt_event event_ = 0, const __itt_event parent_event_ = 0):
53  name(name_),
54  status(status_),
55  event(event_),
56  parent_event(parent_event_){}
57  // Name of the component.
59  // Running status: on/off.
60  bool status;
61  // Task type holder.
62  __itt_event event;
63  // Parent task type.
64  __itt_event parent_event;
65  };
66 private:
67  // From what event to start profiling. Default = 1.
69  // After what event we stop profiling. If 0 than we also profile finalization
70  // stage. Default = 0.
72  // Names of excluded algorithms.
74  // Names of included algorithms.
76  // Algorithm name, for which intel amplifier event type will be created.
78  // The String delimiter between sequences/algorithms names in
79  // "Task Type" grouping at Amplifier.
81  // Enable frames (needed for detecting slow events).
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.
89 private:
90  // Logger.
92  // Events counter.
93  int m_nEvents;
94  // Domain for event loop.
95  __itt_domain* domain;
96  // True if profiler is started.
98  // Current stack of sequences/algorithms.
100  // Mapping of task type name to Amplifier event .
102 private:
103  // ## Private functions.
104  void start_profiling_component(const std::string& name);
105  void skip_profiling_component(const std::string& name);
106 
107  void start();
108  void pause();
109  void resume();
110  void stop();
111 
112  bool hasIncludes() const;
113  bool isIncluded(const std::string& name) const;
114  bool isExcluded(const std::string& name) const;
115  bool isRunning() const;
116 
117  int stackLevel() const;
118  std::string stackIndent(bool newLevel = false) const;
119  std::string taskTypeName(const std::string& component_name) const;
120 };
121 // ## Implementation.
122 // Constructor
124  ISvcLocator* pSvcLocator) : Auditor(name, pSvcLocator), m_log(msgSvc(), name)
125  ,m_nEvents(0), m_isStarted(false) {
126  // ## Properties
127  declareProperty("IncludeAlgorithms", m_included,
128  "Names of included algorithms."
129  );
130  declareProperty("ExcludeAlgorithms", m_excluded,
131  "Names of excluded algorithms."
132  );
133  declareProperty("StartFromEventN", m_nStartFromEvent = 1,
134  "After what event we stop profiling. "
135  "If 0 than we also profile finalization stage."
136  );
137  declareProperty("StopAtEventN", m_nStopAtEvent = 0,
138  "After what event we stop profiling. "
139  "If 0 than we also profile finalization stage. Default = 0."
140  );
141  declareProperty("ComponentsForTaskTypes", m_algs_for_tasktypes,
142  "Algorithm name, for which intel amplifier task type will be created."
143  "By default all algorithms have a corresponding task type.");
144  declareProperty("TaskTypeNameDelimeter", m_alg_delim = " ",
145  "The String delimiter between sequences/algorithms names in "
146  "\"Task Type\" grouping at Amplifier. Default=\" \"."
147  );
148  declareProperty("EnableFrames", m_enable_frames = false,
149  "Enable frames (needed for detecting slow events). Default=false."
150  );
151  declareProperty("FramesRate", m_frames_rate = 100,
152  "Frames rate. The recommended maximum rate for calling the Frame API is "
153  "1000 frames (events) per second. A higher rate may result in large product"
154  " memory consumption and slow finalization. "
155  "You need update \"slow-frames-threshold\" and \"fast-frames-threshold\" "
156  "parameters of amplxe-cl tool to separate slow, medium and fast events. "
157  "For use frames you need to switch on \"EnableFrames\". "
158  "Default=100"
159  );
160 }
161 
163  m_isStarted = true;
164  __itt_resume();
165 }
166 
168  if (!m_isStarted) return;
170  __itt_event taskId = 0;
171  TaskTypes::const_iterator iter = m_tasktypes.find(typeName);
172  if( iter != m_tasktypes.end()) {
173  taskId = iter->second;
174  }
175 
176  if(!taskId && m_algs_for_tasktypes.empty()) {
177  // Create event
178  taskId = __itt_event_create(typeName.c_str(), typeName.size());
179  m_tasktypes.insert(TaskTypes::value_type(typeName, taskId));
180  }
181 
182  stack_entity state = stack_entity(name, true, taskId);
183  stack_entity* parent = !m_stack.empty()?&m_stack.back():NULL;
184 
185  if (parent != NULL) {
186  if (parent->event) {
187  state.parent_event = parent->event;
188  } else {
189  state.parent_event = parent->parent_event;
190  }
191  }
192 
193  if (taskId && state.parent_event) {
194  m_log << MSG::DEBUG << stackIndent() << "Pause event " <<
195  state.parent_event << endmsg;
196  __itt_event_end(state.parent_event);
197  }
198  m_stack.push_back(state);
199 
200  m_log << MSG::DEBUG << stackIndent() << "Start profiling component "
201  << typeName << endmsg;
202 
203  if (taskId) {
204  // Start event
205  m_log << MSG::DEBUG << stackIndent() << "Start event type "
206  << state.event << " for " << typeName << endmsg;
207  __itt_event_start(state.event);
208  }
209 
210  __itt_resume();
211 }
212 
214  if (!m_isStarted) return;
215  m_log << MSG::DEBUG << stackIndent() << "Resume" << endmsg;
216  __itt_resume();
217 }
218 
220  if (!m_isStarted) return;
221  m_log << MSG::DEBUG << stackIndent() << "Pause" << endmsg;
222  __itt_pause();
223 }
224 
226  if (!m_isStarted) return;
227  m_stack.push_back(stack_entity(name, false));
228  m_log << MSG::DEBUG << stackIndent() << "Skip component "
229  << name << endmsg;
230 }
231 
233  if (!m_isStarted) return;
234  m_isStarted = false;
235  __itt_pause();
236 }
237 
239  return !m_included.empty();
240 }
241 
243  return std::find(m_included.begin(), m_included.end(), name) !=
244  m_included.end();
245 }
246 
248  return std::find(m_excluded.begin(), m_excluded.end(), name) !=
249  m_excluded.end();
250 }
251 
253  return !m_stack.empty() && m_stack.back().status;
254 }
255 
257  return m_stack.size();
258 }
259 
261  std::stringstream indent(std::stringstream::out);
262  indent << std::setw(stackLevel()*2+(newLevel?2:0)) << " ";
263  return indent.str();
264 }
265 
267 IntelProfilerAuditor::taskTypeName(const std::string& component_name) const {
268  std::string result;
269  std::string delim = "";
270  BOOST_FOREACH(const stack_entity& value,
271  m_stack) {
272  result += delim+value.name;
273  delim = m_alg_delim;
274  }
275  return result+m_alg_delim+component_name;
276 }
277 
280  m_log << MSG::INFO << "Initialised" << endmsg;
281 
282  IIncidentSvc * inSvc = NULL;
283  const StatusCode sc = serviceLocator()->service("IncidentSvc", inSvc);
284  if (sc.isFailure())
285  return sc;
286  // Useful to start profiling only after some event, we don't need profile
287  // initialization stage. For that we need to count events with BeginEvent
288  // listener.
290  // If the end event number don't setup we finish profiling at the end
291  // of loop. We don't need profiling finalization stage.
293 
294  std::string str_excluded, str_included, str_eventtypes;
295  BOOST_FOREACH(const std::string& name, m_excluded)
296  {
297  str_excluded += " " + name;
298  }
299  BOOST_FOREACH(const std::string& name, m_included)
300  {
301  str_included += " " + name;
302  }
303 
304  BOOST_FOREACH(const std::string& name, m_algs_for_tasktypes)
305  {
306  str_eventtypes += " " + name;
307  }
308 
309  if (!m_included.empty()) {
310  m_log << MSG::INFO << "Included algorithms (" << m_included.size()
311  << "): " << str_included << endmsg;
312  }
313 
314  if (!m_excluded.empty()){
315  m_log << MSG::INFO << "Excluded algorithms (" << m_excluded.size()
316  << "): " << str_excluded << endmsg;
317  }
318 
319  if (!m_algs_for_tasktypes.empty()){
320  m_log << MSG::INFO << "Event types (" << m_algs_for_tasktypes.size()
321  << "): " << str_eventtypes << endmsg;
322  }
323 
324  // Create a profiler domain for detection of slow events.
325  domain = __itt_domain_create("Event loop");
326  domain->flags = m_enable_frames;
327 
328  return StatusCode::SUCCESS;
329 }
330 
331 
332 
333 void IntelProfilerAuditor::handle(const Incident& incident) {
334  if (IncidentType::BeginEvent != incident.type()) return;
335  // Increment the event counter
336  ++m_nEvents;
337 
338  if (m_nStartFromEvent == m_nEvents) {
339  m_log << MSG::INFO << "Start profiling (event #" << m_nEvents << ")"
340  << endmsg;
341  start();
342  }
343 
344  if (m_nStopAtEvent == m_nEvents) {
345  m_log << MSG::INFO << "Stop profiling (event #" << m_nEvents << ")"
346  << endmsg;
347  stop();
348  }
349 }
350 
352  // Skip unnecessary event types.
353  if (!((type == IAuditor::Execute) && m_isStarted)) return;
354 
355  // Name of the current component.
356  const std::string& name = i->name();
357  //m_log << MSG::DEBUG << "Before: " << name << " " << type << endmsg;
358 
359  if (isRunning()) {
360  if (isExcluded(name)) {
361  // If profiling is running and component is explicitly excluded
362  // then skip component.
364  }else{
365  // If profiling is running and component is'not explicitly excluded
366  // then start profiling for component (add to stack).
368  }
369  }else {
370  if (hasIncludes()) {
371  // If the profiling is not running and "includes" is explicitly defined ...
372  if (isIncluded(name)) {
373  // and the current component is in the include's list then start the
374  // component profiling.
376  } else{
377  // and the current component is not in the includes list then skip
378  // a profiling of the component.
380  }
381  }else {
382  // If "Includes" property isn't present and the component is ...
383  if (isExcluded(name)) {
384  // in the excludes list then skip a profiling
386  }else{
387  // not in the exclude list then start a profiling
389  }
390  }
391  }
392  if (m_nEvents % m_frames_rate == 0) {
393  __itt_frame_begin_v3(domain, NULL);
394  }
395 
396 }
397 
398 void IntelProfilerAuditor::after(StandardEventType type,
399  INamedInterface* i, const StatusCode&/* sc*/) {
400  // Skip unnecessary event types
401  if (!((type == IAuditor::Execute) && m_isStarted)) return;
402 
403  if ((m_nEvents+1) % m_frames_rate == 0) {
404  __itt_frame_end_v3(domain, NULL);
405  }
406 
407  // Name of the current component
408  const std::string& name = i->name();
410  // Remove component from stack.
411  m_stack.pop_back();
412 
413 
414  if (state.event != 0) {
415  m_log << MSG::DEBUG << stackIndent(true) << "End event for "
416  << name << endmsg;
417  __itt_event_end(state.event);
418 
419  if (state.parent_event != 0) {
420  m_log << MSG::DEBUG << stackIndent() << "Resume event for "
421  << state.parent_event << endmsg;
422  __itt_event_start(state.parent_event);
423  }
424  }
425 
426  if (m_stack.empty()) {
427  // Pause if there are no parent components (top algorithm).
428  pause();
429  } else if (state.status) {
430  // If the profiling is running and we have parent component that is
431  // paused then pause the profiling.
432  if (!m_stack.back().status) {
433  pause();
434  }
435  }else {
436  // If the profiling was stopped, but the parent component should be profiled
437  // then resume profiling.
438  if (m_stack.back().status) {
439  resume();
440  }
441  }
442 }
443 
444 // Register the auditor

Generated at Wed Nov 28 2012 12:17:17 for Gaudi Framework, version v23r5 by Doxygen version 1.8.2 written by Dimitri van Heesch, © 1997-2004