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  : AthService( 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  void** ppvIF ) {
41 
42  if( ! ppvIF ) {
43  return StatusCode::FAILURE;
44  }
45 
46  if( riid == IVTuneProfilerSvc::interfaceID() ) {
47  *ppvIF = static_cast< IVTuneProfilerSvc* >( this );
48  return StatusCode::SUCCESS;
49  }
50 
51  return AthService::queryInterface( riid, ppvIF );
52 
53 }
54 
55 
60 
61  // Print information
62  ATH_MSG_INFO( "Initializing VTuneProfilerService" );
63 
64  // Use the auditor if a list of algorithms is provided
65  if(!m_algs.empty()) {
66 
67  // Resume/Pause event don't work in conjuction w/ a list of algorithms
68  ATH_MSG_INFO("ResumeEvent/PauseEvent don't work in conjuction with ProfiledAlgs. " <<
69  "Execute methods of all provided algorithms will be sampled in all events." );
70 
71  // Create the auditor
72  makeAuditor("VTuneAuditor",auditorSvc()).ignore();
73 
74  // Check if the auditor is correctly created
75  if ((auditorSvc()==0) || auditorSvc()->getAuditor("VTuneAuditor")==0) {
76  ATH_MSG_ERROR ("Cannot find [VTuneAuditor]. ");
77  return StatusCode::FAILURE;
78  }
79  else {
80  ATH_MSG_VERBOSE ("Found [VTuneAuditor].");
81  }
82 
83  }
84 
85  // Set up listening to the incidents
86  CHECK( m_incidentSvc.retrieve() );
87  m_incidentSvc->addListener( this, BEGINEVENT_INCIDENT_NAME );
88  m_incidentSvc->addListener( this, ENDEVENT_INCIDENT_NAME );
89  m_incidentSvc->addListener( this, ENDEVTLOOP_INCIDENT_NAME );
90 
91  // Reset the event counter:
93 
94  return StatusCode::SUCCESS;
95 
96 }
97 
102 
103  // Check whether the profiling is already running:
104  if( m_runner ) {
105  ATH_MSG_INFO( "VTune profiling already running!" );
106  return StatusCode::SUCCESS;
107  }
108 
109  // Print information
110  ATH_MSG_INFO( "Starting VTune profiling." );
111 
112  // Resume VTune
113  m_runner = std::make_unique< VTuneProfileRunner >();
114 
115  return StatusCode::SUCCESS;
116 
117 }
118 
123 
124  // Check whether the profiling is already running:
125  if( !m_runner ) {
126  ATH_MSG_INFO( "VTune profiling is not running!" );
127  return StatusCode::SUCCESS;
128  }
129 
130  // Print information
131  ATH_MSG_INFO( "Stopping VTune profiling." );
132 
133  // Pause VTune
134  m_runner.reset();
135 
136  return StatusCode::SUCCESS;
137 
138 }
139 
144 
145  return (m_runner!=nullptr);
146 
147 }
148 
152 void VTuneProfilerService::handle( const Incident& inc ) {
153 
154  // Use incidents only if there is no auditor
155  // Next step is to get rid of the incidents altogether
156  if ( !m_algs.empty() ) return;
157 
158  //
159  // Pause the profiling after the last event
160  //
161  if( inc.type() == ENDEVTLOOP_INCIDENT_NAME ) {
162  if( m_runner ) {
163  if( pauseProfiling().isFailure() ) {
164  REPORT_MESSAGE( MSG::ERROR )
165  << "Could not pause the profiling";
166  }
167  }
168  return;
169  }
170 
171  //
172  // Resume/Pause the profiling on the right event
173  //
174  if( inc.type() == BEGINEVENT_INCIDENT_NAME ) {
176  !m_runner ) {
177  std::lock_guard<std::mutex> lock(m_mutex);
178  //double checked locking pattern
179  //https://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
180  //cppcheck-suppress identicalInnerCondition
181  if (!m_runner) {
182  if( resumeProfiling().isFailure() ) {
183  REPORT_MESSAGE( MSG::ERROR )
184  << "Could not resume the profiling";
185  }
186  }
187  }
189  return;
190  }
191  else if( inc.type() == ENDEVENT_INCIDENT_NAME ) {
193  std::lock_guard<std::mutex> lock(m_mutex);
194  //double checked locking pattern
195  //https://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
196  //cppcheck-suppress identicalInnerCondition
197  if (m_runner) {
198  if( pauseProfiling().isFailure() &&
199  m_runner ) {
200  REPORT_MESSAGE( MSG::ERROR )
201  << "Could not pause the profiling";
202  }
203  }
204  }
205  return;
206  }
207 
208  // Complain if we received an incident that we didn't expect:
209  ATH_MSG_WARNING( "Wrong incident type received: " << inc.type() );
210  return;
211 
212 }
213 
217 StatusCode VTuneProfilerService::makeAuditor (const std::string& audName,
218  IAuditorSvc* audSvc)
219 {
220  if ( 0 == audSvc ) {
221  ATH_MSG_ERROR ("Null pointer to IAuditorSvc !!");
222  return StatusCode::FAILURE;
223  }
224 
225  if ( 0 != audSvc->getAuditor( audName ) ) {
226  ATH_MSG_VERBOSE ("AuditorSvc already knows about ["
227  << audName << "]... good.");
228  return StatusCode::SUCCESS;
229  }
230 
231  const std::string propName = "Auditors";
232  IProperty * audSvcProp = dynamic_cast<IProperty*>(audSvc);
233 
234  if ( 0 == audSvcProp ) {
235  ATH_MSG_ERROR ("Could not dyn-cast IAuditorSvc to an IProperty !!");
236  return StatusCode::FAILURE;
237  }
238 
239  StringArrayProperty audNames;
240  audNames.assign( audSvcProp->getProperty(propName) );
241  std::vector<std::string> updatedNames( audNames.value() );
242  updatedNames.push_back( audName );
243  audNames.set( updatedNames );
244  audNames.setName( propName );
245  if ( !audSvcProp->setProperty( audNames ).isSuccess() ) {
247  ("Could not add [" << audName
248  << "] to the list of auditors of [AuditorSvc] !!"
249  << endmsg
250  << audSvcProp->getProperty(propName));
251  return StatusCode::FAILURE;
252  }
253 
254  // make sure the auditor has been created...
255  if ( 0 == audSvc->getAuditor( audName ) ) {
256  ATH_MSG_ERROR ("Failed to make AuditorSvc instantiating ["
257  << audName << "] !!");
258  return StatusCode::FAILURE;
259  }
260 
261  ATH_MSG_VERBOSE ("[" << audName << "] successfully created.");
262  return StatusCode::SUCCESS;
263 }
VTuneProfilerService::isProfilingRunning
virtual bool isProfilingRunning() const override
Is the profiling running at the moment?
Definition: VTuneProfilerService.cxx:143
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
IVTuneProfilerSvc::interfaceID
static const InterfaceID & interfaceID()
Interface ID definition.
Definition: IVTuneProfilerSvc.h:16
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:61
VTuneProfilerService::pauseProfiling
virtual StatusCode pauseProfiling() override
Pause profiling.
Definition: VTuneProfilerService.cxx:122
VTuneProfilerService::m_processedEvents
std::atomic< int > m_processedEvents
Number of events processed so far.
Definition: VTuneProfilerService.h:76
VTuneProfilerService::resumeProfiling
virtual StatusCode resumeProfiling() override
Resume profiling.
Definition: VTuneProfilerService.cxx:101
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:64
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
AthService
Definition: AthService.h:32
VTuneProfilerService::m_mutex
std::mutex m_mutex
Definition: VTuneProfilerService.h:78
VTuneProfilerService::VTuneProfilerService
VTuneProfilerService(const std::string &name, ISvcLocator *svcloc)
Standard Gaudi service constructor.
Definition: VTuneProfilerService.cxx:21
VTuneProfilerService::queryInterface
virtual StatusCode queryInterface(const InterfaceID &riid, void **ppvIF) override
Function declaring the interface(s) implemented by the service.
Definition: VTuneProfilerService.cxx:39
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:152
VTuneProfilerService::m_pauseEvent
int m_pauseEvent
Property: Event in which profiling should pause.
Definition: VTuneProfilerService.h:67
VTuneProfilerService.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
L1CaloPhase1Monitoring.propName
propName
Definition: L1CaloPhase1Monitoring.py:398
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:59
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:217
VTuneProfilerService::m_runner
std::unique_ptr< VTuneProfileRunner > m_runner
Unique ptr to the VTuneProfileRunner.
Definition: VTuneProfilerService.h:73
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:70
IVTuneProfilerSvc
Definition: IVTuneProfilerSvc.h:11