ATLAS Offline Software
VTuneProfilerService.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Gaudi/Athena include(s):
7 
8 // Local include(s):
9 #include "VTuneProfilerService.h"
10 
11 //
12 // Convenience variable(s):
13 //
14 static const std::string BEGINEVENT_INCIDENT_NAME = "BeginEvent";
15 static const std::string ENDEVENT_INCIDENT_NAME = "EndEvent";
16 static const std::string ENDEVTLOOP_INCIDENT_NAME = "EndEvtLoop";
17 
21 VTuneProfilerService::VTuneProfilerService( const std::string& name, ISvcLocator* svcloc )
22  : base_class( name, svcloc ),
23  m_incidentSvc( "IncidentSvc", name ),
24  m_processedEvents( 0 ) {
25 
26  declareProperty( "ResumeEvent", m_resumeEvent = 0,
27  "Event in which to resume the profiling." );
28  declareProperty( "PauseEvent", m_pauseEvent = -1,
29  "Event in which to pause the profiling. Negative number "
30  "profiles the entire event-loop." );
31  declareProperty( "ProfiledAlgs", m_algs,
32  "List of profiled algorithms." );
33 
34 }
35 
40 
41  // Print information
42  ATH_MSG_INFO( "Initializing VTuneProfilerService" );
43 
44  // Use the auditor if a list of algorithms is provided
45  if(!m_algs.empty()) {
46 
47  // Resume/Pause event don't work in conjuction w/ a list of algorithms
48  ATH_MSG_INFO("ResumeEvent/PauseEvent don't work in conjuction with ProfiledAlgs. " <<
49  "Execute methods of all provided algorithms will be sampled in all events." );
50 
51  // Create the auditor
52  makeAuditor("VTuneAuditor",auditorSvc()).ignore();
53 
54  // Check if the auditor is correctly created
55  if ((auditorSvc()==0) || auditorSvc()->getAuditor("VTuneAuditor")==0) {
56  ATH_MSG_ERROR ("Cannot find [VTuneAuditor]. ");
57  return StatusCode::FAILURE;
58  }
59  else {
60  ATH_MSG_VERBOSE ("Found [VTuneAuditor].");
61  }
62 
63  }
64 
65  // Set up listening to the incidents
66  CHECK( m_incidentSvc.retrieve() );
67  m_incidentSvc->addListener( this, BEGINEVENT_INCIDENT_NAME );
68  m_incidentSvc->addListener( this, ENDEVENT_INCIDENT_NAME );
69  m_incidentSvc->addListener( this, ENDEVTLOOP_INCIDENT_NAME );
70 
71  // Reset the event counter:
73 
74  return StatusCode::SUCCESS;
75 
76 }
77 
82 
83  // Check whether the profiling is already running:
84  if( m_runner ) {
85  ATH_MSG_INFO( "VTune profiling already running!" );
86  return StatusCode::SUCCESS;
87  }
88 
89  // Print information
90  ATH_MSG_INFO( "Starting VTune profiling." );
91 
92  // Resume VTune
93  m_runner = std::make_unique< VTuneProfileRunner >();
94 
95  return StatusCode::SUCCESS;
96 
97 }
98 
103 
104  // Check whether the profiling is already running:
105  if( !m_runner ) {
106  ATH_MSG_INFO( "VTune profiling is not running!" );
107  return StatusCode::SUCCESS;
108  }
109 
110  // Print information
111  ATH_MSG_INFO( "Stopping VTune profiling." );
112 
113  // Pause VTune
114  m_runner.reset();
115 
116  return StatusCode::SUCCESS;
117 
118 }
119 
124 
125  return (m_runner!=nullptr);
126 
127 }
128 
132 void VTuneProfilerService::handle( const Incident& inc ) {
133 
134  // Use incidents only if there is no auditor
135  // Next step is to get rid of the incidents altogether
136  if ( !m_algs.empty() ) return;
137 
138  //
139  // Pause the profiling after the last event
140  //
141  if( inc.type() == ENDEVTLOOP_INCIDENT_NAME ) {
142  if( m_runner ) {
143  if( pauseProfiling().isFailure() ) {
144  REPORT_MESSAGE( MSG::ERROR )
145  << "Could not pause the profiling";
146  }
147  }
148  return;
149  }
150 
151  //
152  // Resume/Pause the profiling on the right event
153  //
154  if( inc.type() == BEGINEVENT_INCIDENT_NAME ) {
156  !m_runner ) {
157  std::lock_guard<std::mutex> lock(m_mutex);
158  //double checked locking pattern
159  //https://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
160  //cppcheck-suppress identicalInnerCondition
161  if (!m_runner) {
162  if( resumeProfiling().isFailure() ) {
163  REPORT_MESSAGE( MSG::ERROR )
164  << "Could not resume the profiling";
165  }
166  }
167  }
169  return;
170  }
171  else if( inc.type() == ENDEVENT_INCIDENT_NAME ) {
173  std::lock_guard<std::mutex> lock(m_mutex);
174  //double checked locking pattern
175  //https://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
176  //cppcheck-suppress identicalInnerCondition
177  if (m_runner) {
178  if( pauseProfiling().isFailure() &&
179  m_runner ) {
180  REPORT_MESSAGE( MSG::ERROR )
181  << "Could not pause the profiling";
182  }
183  }
184  }
185  return;
186  }
187 
188  // Complain if we received an incident that we didn't expect:
189  ATH_MSG_WARNING( "Wrong incident type received: " << inc.type() );
190  return;
191 
192 }
193 
197 StatusCode VTuneProfilerService::makeAuditor (const std::string& audName,
198  IAuditorSvc* audSvc)
199 {
200  if ( 0 == audSvc ) {
201  ATH_MSG_ERROR ("Null pointer to IAuditorSvc !!");
202  return StatusCode::FAILURE;
203  }
204 
205  if ( 0 != audSvc->getAuditor( audName ) ) {
206  ATH_MSG_VERBOSE ("AuditorSvc already knows about ["
207  << audName << "]... good.");
208  return StatusCode::SUCCESS;
209  }
210 
211  const std::string propName = "Auditors";
212  IProperty * audSvcProp = dynamic_cast<IProperty*>(audSvc);
213 
214  if ( 0 == audSvcProp ) {
215  ATH_MSG_ERROR ("Could not dyn-cast IAuditorSvc to an IProperty !!");
216  return StatusCode::FAILURE;
217  }
218 
219  StringArrayProperty audNames;
220  audNames.assign( audSvcProp->getProperty(propName) );
221  std::vector<std::string> updatedNames( audNames.value() );
222  updatedNames.push_back( audName );
223  audNames.set( updatedNames );
224  audNames.setName( propName );
225  if ( !audSvcProp->setProperty( audNames ).isSuccess() ) {
227  ("Could not add [" << audName
228  << "] to the list of auditors of [AuditorSvc] !!"
229  << endmsg
230  << audSvcProp->getProperty(propName));
231  return StatusCode::FAILURE;
232  }
233 
234  // make sure the auditor has been created...
235  if ( 0 == audSvc->getAuditor( audName ) ) {
236  ATH_MSG_ERROR ("Failed to make AuditorSvc instantiating ["
237  << audName << "] !!");
238  return StatusCode::FAILURE;
239  }
240 
241  ATH_MSG_VERBOSE ("[" << audName << "] successfully created.");
242  return StatusCode::SUCCESS;
243 }
VTuneProfilerService::isProfilingRunning
virtual bool isProfilingRunning() const override
Is the profiling running at the moment?
Definition: VTuneProfilerService.cxx:123
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
VTuneProfilerService::m_incidentSvc
ServiceHandle< IIncidentSvc > m_incidentSvc
Handle to the incident service.
Definition: VTuneProfilerService.h:57
VTuneProfilerService::pauseProfiling
virtual StatusCode pauseProfiling() override
Pause profiling.
Definition: VTuneProfilerService.cxx:102
VTuneProfilerService::m_processedEvents
std::atomic< int > m_processedEvents
Number of events processed so far.
Definition: VTuneProfilerService.h:72
VTuneProfilerService::resumeProfiling
virtual StatusCode resumeProfiling() override
Resume profiling.
Definition: VTuneProfilerService.cxx:81
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
VTuneProfilerService::m_resumeEvent
int m_resumeEvent
Property: Event in which profiling should start.
Definition: VTuneProfilerService.h:60
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
VTuneProfilerService::m_mutex
std::mutex m_mutex
Definition: VTuneProfilerService.h:74
VTuneProfilerService::VTuneProfilerService
VTuneProfilerService(const std::string &name, ISvcLocator *svcloc)
Standard Gaudi service constructor.
Definition: VTuneProfilerService.cxx:21
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
VTuneProfilerService::handle
virtual void handle(const Incident &inc) override
Function handling incoming incidents.
Definition: VTuneProfilerService.cxx:132
VTuneProfilerService::m_pauseEvent
int m_pauseEvent
Property: Event in which profiling should pause.
Definition: VTuneProfilerService.h:63
VTuneProfilerService.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
L1CaloPhase1Monitoring.propName
propName
Definition: L1CaloPhase1Monitoring.py:451
errorcheck.h
Helpers for checking error return status codes and reporting errors.
VTuneProfilerService::initialize
virtual StatusCode initialize() override
Standard Gaudi initialization function.
Definition: VTuneProfilerService.cxx:39
REPORT_MESSAGE
#define REPORT_MESSAGE(LVL)
Report a message.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:365
VTuneProfilerService::makeAuditor
StatusCode makeAuditor(const std::string &audName, IAuditorSvc *audSvc)
Helper method to create auditors.
Definition: VTuneProfilerService.cxx:197
VTuneProfilerService::m_runner
std::unique_ptr< VTuneProfileRunner > m_runner
Unique ptr to the VTuneProfileRunner.
Definition: VTuneProfilerService.h:69
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
VTuneProfilerService::m_algs
std::vector< std::string > m_algs
Property: List of algorithms to profile.
Definition: VTuneProfilerService.h:66