00001
00002
00003 #include <algorithm>
00004 #include <vector>
00005 #include <stack>
00006 #include <string>
00007 #include <utility>
00008 #include <memory>
00009 #include <iomanip>
00010 #include <sstream>
00011
00012
00013 #include <boost/foreach.hpp>
00014
00015
00016 #include "GaudiKernel/AudFactory.h"
00017 #include "GaudiKernel/Auditor.h"
00018 #include "GaudiKernel/IAuditorSvc.h"
00019 #include "GaudiKernel/GaudiException.h"
00020 #include "GaudiKernel/MsgStream.h"
00021 #include "GaudiKernel/IIncidentListener.h"
00022 #include "GaudiKernel/IIncidentSvc.h"
00023
00024
00025 #ifdef __GNUC__
00026 #pragma GCC diagnostic ignored "-Wunused-function"
00027 #endif
00028 #include "ittnotify.h"
00029
00030 typedef std::map<std::string, __itt_event> TaskTypes;
00031
00032
00033
00034
00035 class IntelProfilerAuditor: public Auditor, virtual public IIncidentListener {
00036 public:
00037
00038 IntelProfilerAuditor(const std::string& name, ISvcLocator* pSvcLocator);
00039 StatusCode initialize();
00040
00041 void handle(const Incident& incident);
00042 using Auditor::before;
00043 void before(StandardEventType type, INamedInterface* i);
00044 using Auditor::after;
00045 void after(StandardEventType type, INamedInterface* i, const StatusCode& sc);
00046
00047 private:
00048
00049
00050 struct stack_entity {
00051 stack_entity(const std::string& name_, bool status_,
00052 const __itt_event event_ = 0, const __itt_event parent_event_ = 0):
00053 name(name_),
00054 status(status_),
00055 event(event_),
00056 parent_event(parent_event_){}
00057
00058 std::string name;
00059
00060 bool status;
00061
00062 __itt_event event;
00063
00064 __itt_event parent_event;
00065 };
00066 private:
00067
00068 int m_nStartFromEvent;
00069
00070
00071 int m_nStopAtEvent;
00072
00073 std::vector<std::string> m_excluded;
00074
00075 std::vector<std::string> m_included;
00076
00077 std::vector<std::string> m_algs_for_tasktypes;
00078
00079
00080 std::string m_alg_delim;
00081
00082 bool m_enable_frames;
00083
00084
00085
00086
00087
00088 int m_frames_rate;
00089 private:
00090
00091 MsgStream m_log;
00092
00093 int m_nEvents;
00094
00095 __itt_domain* domain;
00096
00097 bool m_isStarted;
00098
00099 std::vector<stack_entity> m_stack;
00100
00101 TaskTypes m_tasktypes;
00102 private:
00103
00104 void start_profiling_component(const std::string& name);
00105 void skip_profiling_component(const std::string& name);
00106
00107 void start();
00108 void pause();
00109 void resume();
00110 void stop();
00111
00112 bool hasIncludes() const;
00113 bool isIncluded(const std::string& name) const;
00114 bool isExcluded(const std::string& name) const;
00115 bool isRunning() const;
00116
00117 int stackLevel() const;
00118 std::string stackIndent(bool newLevel = false) const;
00119 std::string taskTypeName(const std::string& component_name) const;
00120 };
00121
00122
00123 IntelProfilerAuditor::IntelProfilerAuditor(const std::string& name,
00124 ISvcLocator* pSvcLocator) : Auditor(name, pSvcLocator), m_log(msgSvc(), name)
00125 ,m_nEvents(0), m_isStarted(false) {
00126
00127 declareProperty("IncludeAlgorithms", m_included,
00128 "Names of included algorithms."
00129 );
00130 declareProperty("ExcludeAlgorithms", m_excluded,
00131 "Names of excluded algorithms."
00132 );
00133 declareProperty("StartFromEventN", m_nStartFromEvent = 1,
00134 "After what event we stop profiling. "
00135 "If 0 than we also profile finalization stage."
00136 );
00137 declareProperty("StopAtEventN", m_nStopAtEvent = 0,
00138 "After what event we stop profiling. "
00139 "If 0 than we also profile finalization stage. Default = 0."
00140 );
00141 declareProperty("ComponentsForTaskTypes", m_algs_for_tasktypes,
00142 "Algorithm name, for which intel amplifier task type will be created."
00143 "By default all algorithms have a corresponding task type.");
00144 declareProperty("TaskTypeNameDelimeter", m_alg_delim = " ",
00145 "The String delimiter between sequences/algorithms names in "
00146 "\"Task Type\" grouping at Amplifier. Default=\" \"."
00147 );
00148 declareProperty("EnableFrames", m_enable_frames = false,
00149 "Enable frames (needed for detecting slow events). Default=false."
00150 );
00151 declareProperty("FramesRate", m_frames_rate = 100,
00152 "Frames rate. The recommended maximum rate for calling the Frame API is "
00153 "1000 frames (events) per second. A higher rate may result in large product"
00154 " memory consumption and slow finalization. "
00155 "You need update \"slow-frames-threshold\" and \"fast-frames-threshold\" "
00156 "parameters of amplxe-cl tool to separate slow, medium and fast events. "
00157 "For use frames you need to switch on \"EnableFrames\". "
00158 "Default=100"
00159 );
00160 }
00161
00162 void IntelProfilerAuditor::start() {
00163 m_isStarted = true;
00164 __itt_resume();
00165 }
00166
00167 void IntelProfilerAuditor::start_profiling_component(const std::string& name) {
00168 if (!m_isStarted) return;
00169 std::string typeName = taskTypeName(name);
00170 __itt_event taskId = 0;
00171 TaskTypes::const_iterator iter = m_tasktypes.find(typeName);
00172 if( iter != m_tasktypes.end()) {
00173 taskId = iter->second;
00174 }
00175
00176 if(!taskId && m_algs_for_tasktypes.empty()) {
00177
00178 taskId = __itt_event_create(typeName.c_str(), typeName.size());
00179 m_tasktypes.insert(TaskTypes::value_type(typeName, taskId));
00180 }
00181
00182 stack_entity state = stack_entity(name, true, taskId);
00183 stack_entity* parent = !m_stack.empty()?&m_stack.back():NULL;
00184
00185 if (parent != NULL) {
00186 if (parent->event) {
00187 state.parent_event = parent->event;
00188 } else {
00189 state.parent_event = parent->parent_event;
00190 }
00191 }
00192
00193 if (taskId && state.parent_event) {
00194 m_log << MSG::DEBUG << stackIndent() << "Pause event " <<
00195 state.parent_event << endmsg;
00196 __itt_event_end(state.parent_event);
00197 }
00198 m_stack.push_back(state);
00199
00200 m_log << MSG::DEBUG << stackIndent() << "Start profiling component "
00201 << typeName << endmsg;
00202
00203 if (taskId) {
00204
00205 m_log << MSG::DEBUG << stackIndent() << "Start event type "
00206 << state.event << " for " << typeName << endmsg;
00207 __itt_event_start(state.event);
00208 }
00209
00210 __itt_resume();
00211 }
00212
00213 void IntelProfilerAuditor::resume() {
00214 if (!m_isStarted) return;
00215 m_log << MSG::DEBUG << stackIndent() << "Resume" << endmsg;
00216 __itt_resume();
00217 }
00218
00219 void IntelProfilerAuditor::pause() {
00220 if (!m_isStarted) return;
00221 m_log << MSG::DEBUG << stackIndent() << "Pause" << endmsg;
00222 __itt_pause();
00223 }
00224
00225 void IntelProfilerAuditor::skip_profiling_component(const std::string& name) {
00226 if (!m_isStarted) return;
00227 m_stack.push_back(stack_entity(name, false));
00228 m_log << MSG::DEBUG << stackIndent() << "Skip component "
00229 << name << endmsg;
00230 }
00231
00232 void IntelProfilerAuditor::stop() {
00233 if (!m_isStarted) return;
00234 m_isStarted = false;
00235 __itt_pause();
00236 }
00237
00238 bool IntelProfilerAuditor::hasIncludes() const {
00239 return !m_included.empty();
00240 }
00241
00242 bool IntelProfilerAuditor::isIncluded(const std::string& name) const {
00243 return std::find(m_included.begin(), m_included.end(), name) !=
00244 m_included.end();
00245 }
00246
00247 bool IntelProfilerAuditor::isExcluded(const std::string& name) const {
00248 return std::find(m_excluded.begin(), m_excluded.end(), name) !=
00249 m_excluded.end();
00250 }
00251
00252 bool IntelProfilerAuditor::isRunning() const {
00253 return !m_stack.empty() && m_stack.back().status;
00254 }
00255
00256 int IntelProfilerAuditor::stackLevel() const {
00257 return m_stack.size();
00258 }
00259
00260 std::string IntelProfilerAuditor::stackIndent(bool newLevel) const{
00261 std::stringstream indent(std::stringstream::out);
00262 indent << std::setw(stackLevel()*2+(newLevel?2:0)) << " ";
00263 return indent.str();
00264 }
00265
00266 std::string
00267 IntelProfilerAuditor::taskTypeName(const std::string& component_name) const {
00268 std::string result;
00269 std::string delim = "";
00270 BOOST_FOREACH(const stack_entity& value,
00271 m_stack) {
00272 result += delim+value.name;
00273 delim = m_alg_delim;
00274 }
00275 return result+m_alg_delim+component_name;
00276 }
00277
00278 StatusCode IntelProfilerAuditor::initialize() {
00279 m_log.setLevel(outputLevel());
00280 m_log << MSG::INFO << "Initialised" << endmsg;
00281
00282 IIncidentSvc * inSvc = NULL;
00283 const StatusCode sc = serviceLocator()->service("IncidentSvc", inSvc);
00284 if (sc.isFailure())
00285 return sc;
00286
00287
00288
00289 inSvc->addListener(this, IncidentType::BeginEvent);
00290
00291
00292 inSvc->addListener(this, IncidentType::EndProcessing);
00293
00294 std::string str_excluded, str_included, str_eventtypes;
00295 BOOST_FOREACH(const std::string& name, m_excluded)
00296 {
00297 str_excluded += " " + name;
00298 }
00299 BOOST_FOREACH(const std::string& name, m_included)
00300 {
00301 str_included += " " + name;
00302 }
00303
00304 BOOST_FOREACH(const std::string& name, m_algs_for_tasktypes)
00305 {
00306 str_eventtypes += " " + name;
00307 }
00308
00309 if (!m_included.empty()) {
00310 m_log << MSG::INFO << "Included algorithms (" << m_included.size()
00311 << "): " << str_included << endmsg;
00312 }
00313
00314 if (!m_excluded.empty()){
00315 m_log << MSG::INFO << "Excluded algorithms (" << m_excluded.size()
00316 << "): " << str_excluded << endmsg;
00317 }
00318
00319 if (!m_algs_for_tasktypes.empty()){
00320 m_log << MSG::INFO << "Event types (" << m_algs_for_tasktypes.size()
00321 << "): " << str_eventtypes << endmsg;
00322 }
00323
00324
00325 domain = __itt_domain_create("Event loop");
00326 domain->flags = m_enable_frames;
00327
00328 return StatusCode::SUCCESS;
00329 }
00330
00331
00332
00333 void IntelProfilerAuditor::handle(const Incident& incident) {
00334 if (IncidentType::BeginEvent != incident.type()) return;
00335
00336 ++m_nEvents;
00337
00338 if (m_nStartFromEvent == m_nEvents) {
00339 m_log << MSG::INFO << "Start profiling (event #" << m_nEvents << ")"
00340 << endmsg;
00341 start();
00342 }
00343
00344 if (m_nStopAtEvent == m_nEvents) {
00345 m_log << MSG::INFO << "Stop profiling (event #" << m_nEvents << ")"
00346 << endmsg;
00347 stop();
00348 }
00349 }
00350
00351 void IntelProfilerAuditor::before(StandardEventType type, INamedInterface* i) {
00352
00353 if (!((type == IAuditor::Execute) && m_isStarted)) return;
00354
00355
00356 const std::string& name = i->name();
00357
00358
00359 if (isRunning()) {
00360 if (isExcluded(name)) {
00361
00362
00363 skip_profiling_component(name);
00364 }else{
00365
00366
00367 start_profiling_component(name);
00368 }
00369 }else {
00370 if (hasIncludes()) {
00371
00372 if (isIncluded(name)) {
00373
00374
00375 start_profiling_component(name);
00376 } else{
00377
00378
00379 skip_profiling_component(name);
00380 }
00381 }else {
00382
00383 if (isExcluded(name)) {
00384
00385 skip_profiling_component(name);
00386 }else{
00387
00388 start_profiling_component(name);
00389 }
00390 }
00391 }
00392 if (m_nEvents % m_frames_rate == 0) {
00393 __itt_frame_begin_v3(domain, NULL);
00394 }
00395
00396 }
00397
00398 void IntelProfilerAuditor::after(StandardEventType type,
00399 INamedInterface* i, const StatusCode&) {
00400
00401 if (!((type == IAuditor::Execute) && m_isStarted)) return;
00402
00403 if ((m_nEvents+1) % m_frames_rate == 0) {
00404 __itt_frame_end_v3(domain, NULL);
00405 }
00406
00407
00408 const std::string& name = i->name();
00409 stack_entity state = m_stack.back();
00410
00411 m_stack.pop_back();
00412
00413
00414 if (state.event != 0) {
00415 m_log << MSG::DEBUG << stackIndent(true) << "End event for "
00416 << name << endmsg;
00417 __itt_event_end(state.event);
00418
00419 if (state.parent_event != 0) {
00420 m_log << MSG::DEBUG << stackIndent() << "Resume event for "
00421 << state.parent_event << endmsg;
00422 __itt_event_start(state.parent_event);
00423 }
00424 }
00425
00426 if (m_stack.empty()) {
00427
00428 pause();
00429 } else if (state.status) {
00430
00431
00432 if (!m_stack.back().status) {
00433 pause();
00434 }
00435 }else {
00436
00437
00438 if (m_stack.back().status) {
00439 resume();
00440 }
00441 }
00442 }
00443
00444
00445 DECLARE_AUDITOR_FACTORY(IntelProfilerAuditor)