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