| The Gaudi Framework v28r2p1 (f1a77ff4)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

GaudiParallelizer.cpp
Go to the documentation of this file.
1 // Include files
2 // From Gaudi
3 #include "GaudiAlg/ISequencerTimerTool.h"
4 #include "GaudiKernel/AlgFactory.h"
5 #include "GaudiKernel/IAlgManager.h"
6 #include "GaudiKernel/IJobOptionsSvc.h"
7 #include "GaudiKernel/SerializeSTL.h"
8
9 #include "GaudiParallelizer.h"
10
11 // ----------------------------------------------------------------------------
12 // Implementation file for class: GaudiParallelizer
13 //
14 // 09/12/2011: Illya Shapoval
15 // ----------------------------------------------------------------------------
16 DECLARE_ALGORITHM_FACTORY( GaudiParallelizer )
17
18 // ============================================================================
19 // Standard constructor, initializes variables
20 // ============================================================================
21 GaudiParallelizer::GaudiParallelizer( const std::string& name, ISvcLocator* pSvcLocator )
22 : GaudiAlgorithm( name, pSvcLocator )
23 {
24 m_names.declareUpdateHandler( &GaudiParallelizer::membershipHandler, this );
25 }
26
27 // ============================================================================
28 // Initialization
29 // ============================================================================
30 StatusCode GaudiParallelizer::initialize()
31 {
32 if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Initialize" << endmsg;
33 StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first
34 if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm
35
36 StatusCode status = decodeNames();
37 if ( !status.isSuccess() ) return status;
38
39 m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" );
40 if ( m_timerTool->globalTiming() ) m_measureTime = true;
41
42 if ( m_measureTime ) {
43 m_timer = m_timerTool->addTimer( name() );
44 m_timerTool->increaseIndent();
45 } else {
46 release( m_timerTool );
47 m_timerTool = 0;
48 }
49
50 //== Initialize the algorithms
51 std::vector<AlgorithmEntry>::iterator itE;
52 for ( itE = m_entries.begin(); m_entries.end() != itE; itE++ ) {
53 Algorithm* myAlg = itE->algorithm();
54 if ( m_measureTime ) {
55 itE->setTimer( m_timerTool->addTimer( myAlg->name() ) );
56 }
57
58 status = myAlg->sysInitialize();
59 if ( !status.isSuccess() ) {
60 return Error( "Can not initialize " + myAlg->name(), status );
61 }
62 }
63
64 if ( m_measureTime ) m_timerTool->decreaseIndent();
65
66 if ( m_nthreads != 0 ) {
67 // Construct the TBB task scheduler with m_nthreads threads
68 tbb::task_scheduler_init init( m_nthreads );
69 } else {
70 m_nthreads = tbb::task_scheduler_init::default_num_threads();
71 }
72
73 if ( msgLevel( MSG::DEBUG ) )
74 debug() << "Number of threads set to be used in the TBB thread pool is " << m_nthreads << endmsg;
75 return StatusCode::SUCCESS;
76 }
77
78 // ============================================================================
79 // Main execution
80 // ============================================================================
81 StatusCode GaudiParallelizer::execute()
82 {
83 if ( m_measureTime ) m_timerTool->start( m_timer );
84
85 if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Execute algorithms in parallel" << endmsg;
86
87 for ( std::vector<AlgorithmEntry>::iterator itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
88 Algorithm* myAlg = itE->algorithm();
89 if ( !myAlg->isEnabled() ) continue;
90 if ( !myAlg->isExecuted() ) {
91
92 m_task_group.run( boost::bind( &AlgorithmEntry::run, boost::ref( *itE ), boost::ref( *this ) ) );
93 }
94 }
95
96 m_task_group.wait();
97 if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Joining parallel algorithm tasks" << endmsg;
98
99 for ( std::vector<AlgorithmEntry>::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it ) {
100 if ( msgLevel( MSG::DEBUG ) )
101 debug() << "Algorithm wrapper " << &*it << " around the algorithm " << it->algorithm()->name()
102 << " received return status code " << it->m_returncode << endmsg;
103 }
104
105 for ( std::vector<AlgorithmEntry>::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it )
106 if ( !( it->m_returncode.isSuccess() ) ) return it->m_returncode;
107
108 setExecuted( true );
109 if ( m_measureTime ) m_timerTool->stop( m_timer );
110 return StatusCode::SUCCESS;
111 }
112
113 // ============================================================================
114 // Finalize
115 // ============================================================================
116 StatusCode GaudiParallelizer::finalize()
117 {
118 if ( msgLevel( MSG::DEBUG ) ) debug() << "==> Finalize" << endmsg;
119
120 return GaudiAlgorithm::finalize(); // must be called after all other actions
121 }
122
123 // ============================================================================
124
125 StatusCode GaudiParallelizer::decodeNames()
126 {
127
128 StatusCode final = StatusCode::SUCCESS;
129 m_entries.clear();
130
131 //== Get the "Context" option if in the file...
132 auto jos = service<IJobOptionsSvc>( "JobOptionsSvc" );
133 bool addedContext = false; //= Have we added the context ?
134 bool addedRootInTES = false; //= Have we added the rootInTES ?
135
136 //= Get the Application manager, to see if algorithm exist
137 auto appMgr = service<IAlgManager>( "ApplicationMgr" );
138 const std::vector<std::string>& nameVector = m_names.value();
139 std::vector<std::string>::const_iterator it;
140 for ( it = nameVector.begin(); nameVector.end() != it; it++ ) {
141 const Gaudi::Utils::TypeNameString typeName( *it );
142 const std::string& theName = typeName.name();
143 const std::string& theType = typeName.type();
144
145 //== Check whether the specified algorithm already exists. If not, create it
146 StatusCode result = StatusCode::SUCCESS;
147 SmartIF<IAlgorithm> myIAlg = appMgr->algorithm( typeName, false ); // do not create it now
148 if ( !myIAlg.isValid() ) {
149 //== Set the Context if not in the jobOptions list
150 if ( !context().empty() || !rootInTES().empty() ) {
151 bool foundContext = false;
152 bool foundRootInTES = false;
153 const auto properties = jos->getProperties( theName );
154 if ( properties ) {
155 // Iterate over the list to set the options
156 for ( const auto& p : *properties ) {
157 if ( "Context" == p->name() ) {
158 foundContext = true;
159 }
160 if ( "RootInTES" == p->name() ) {
161 foundRootInTES = true;
162 }
163 }
164 }
165 if ( !foundContext && !context().empty() ) {
166 Gaudi::Property<std::string> contextProperty( "Context", context() );
167 jos->addPropertyToCatalogue( theName, contextProperty ).ignore();
168 addedContext = true;
169 }
170 if ( !foundRootInTES && !rootInTES().empty() ) {
171 Gaudi::Property<std::string> rootInTESProperty( "RootInTES", rootInTES() );
172 jos->addPropertyToCatalogue( theName, rootInTESProperty ).ignore();
173 addedRootInTES = true;
174 }
175 }
176
177 Algorithm* myAlg = nullptr;
178 result = createSubAlgorithm( theType, theName, myAlg );
179 // (MCl) this should prevent bug #35199... even if I didn't manage to
180 // reproduce it with a simple test.
181 if ( result.isSuccess() ) myIAlg = myAlg;
182 } else {
183 Algorithm* myAlg = dynamic_cast<Algorithm*>( myIAlg.get() );
184 if ( myAlg ) {
185 subAlgorithms()->push_back( myAlg );
186 // when the algorithm is not created, the ref count is short by one, so we have to fix it.
187 myAlg->addRef();
188 }
189 }
190
191 //== Remove the property, in case this is not a GaudiAlgorithm...
192 if ( addedContext ) {
193 jos->removePropertyFromCatalogue( theName, "Context" ).ignore();
194 addedContext = false;
195 }
196 if ( addedRootInTES ) {
197 jos->removePropertyFromCatalogue( theName, "RootInTES" ).ignore();
198 addedRootInTES = false;
199 }
200
201 // propagate the sub-algorithm into own state.
202 if ( result.isSuccess() && Gaudi::StateMachine::INITIALIZED <= FSMState() && myIAlg.isValid() &&
203 Gaudi::StateMachine::INITIALIZED > myIAlg->FSMState() ) {
204 StatusCode sc = myIAlg->sysInitialize();
205 if ( sc.isFailure() ) {
206 result = sc;
207 }
208 }
209
210 // propagate the sub-algorithm into own state.
211 if ( result.isSuccess() && Gaudi::StateMachine::RUNNING <= FSMState() && myIAlg.isValid() &&
212 Gaudi::StateMachine::RUNNING > myIAlg->FSMState() ) {
213 StatusCode sc = myIAlg->sysStart();
214 if ( sc.isFailure() ) {
215 result = sc;
216 }
217 }
218
219 //== Is it an Algorithm ? Strange test...
220 if ( result.isSuccess() ) {
221 // TODO: (MCl) it is possible to avoid the dynamic_cast in most of the
222 // cases by keeping the result of createSubAlgorithm.
223 Algorithm* myAlg = dynamic_cast<Algorithm*>( myIAlg.get() );
224 if ( myAlg != 0 ) {
225 // Note: The reference counting is kept by the system of sub-algorithms
226 m_entries.push_back( AlgorithmEntry( myAlg ) );
227 if ( msgLevel( MSG::DEBUG ) ) debug() << "Added algorithm " << theName << endmsg;
228 } else {
229 warning() << theName << " is not an Algorithm - failed dynamic_cast" << endmsg;
230 final = StatusCode::FAILURE;
231 }
232 } else {
233 warning() << "Unable to find or create " << theName << endmsg;
234 final = result;
235 }
236 }
237 //== Print the list of algorithms
238 MsgStream& msg = info();
239 if ( m_modeOR ) msg << "OR ";
240 msg << "Member list: ";
241 using GaudiUtils::details::ostream_joiner;
242 ostream_joiner( msg, m_entries, ", ", []( MsgStream& msg, const AlgorithmEntry& entry ) -> MsgStream& {
243 Algorithm* myAlg = entry.algorithm();
244 auto myAlgType = System::typeinfoName( typeid( *myAlg ) );
245 if ( myAlg->name() != myAlgType ) {
246 msg << myAlgType << "/";
247 }
248 return msg << myAlg->name();
249 } );
250 if ( !context().empty() ) msg << ", with context '" << context() << "'";
251 if ( !rootInTES().empty() ) msg << ", with rootInTES '" << rootInTES() << "'";
252 msg << endmsg;
253 return final;
254 }
255
256 //=========================================================================
257 // Interface for the Property manager
258 //=========================================================================
259 void GaudiParallelizer::membershipHandler( Gaudi::Details::PropertyBase& /* p */ )
260 {
261 // no action for not-yet initialized sequencer
262 if ( Gaudi::StateMachine::INITIALIZED > FSMState() ) {
263 return;
264 } // RETURN
265
266 decodeNames().ignore();
267
268 if ( !m_measureTime ) {
269 return;
270 } // RETURN
271
272 // add the entries into timer table:
273
274 if ( 0 == m_timerTool ) {
275 m_timerTool = tool<ISequencerTimerTool>( "SequencerTimerTool" );
276 }
277
278 if ( m_timerTool->globalTiming() ) m_measureTime = true;
279
280 m_timer = m_timerTool->addTimer( name() );
281 m_timerTool->increaseIndent();
282
283 for ( std::vector<AlgorithmEntry>::iterator itE = m_entries.begin(); m_entries.end() != itE; ++itE ) {
284 itE->setTimer( m_timerTool->addTimer( itE->algorithm()->name() ) );
285 }
286
287 m_timerTool->decreaseIndent();
288 }
289 //=============================================================================
GaudiParallelizer::initialize
StatusCode initialize() override
Algorithm initialization.
Definition: GaudiParallelizer.cpp:30
GaudiParallelizer::m_measureTime
Gaudi::Property< bool > m_measureTime
Definition: GaudiParallelizer.h:78
GaudiParallelizer::execute
StatusCode execute() override
Algorithm execution.
Definition: GaudiParallelizer.cpp:81
MsgStream
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
Gaudi::StateMachine::INITIALIZED
Definition: StateMachine.h:15
StatusCode::SUCCESS
Definition: StatusCode.h:30
SmartIF< IAlgorithm >
CommonMessagingBase::msg
MsgStream & msg() const
shortcut for the method msgStream(MSG::INFO)
Definition: CommonMessaging.h:132
std::string::empty
T empty(T...args)
GaudiParallelizer::m_modeOR
Gaudi::Property< bool > m_modeOR
Definition: GaudiParallelizer.h:77
ISvcLocator
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
ISequencerTimerTool::decreaseIndent
virtual void decreaseIndent()=0
Decrease the indentation of the name.
Algorithm::createSubAlgorithm
StatusCode createSubAlgorithm(const std::string &type, const std::string &name, Algorithm *&pSubAlg)
Create a sub algorithm.
Definition: Algorithm.cpp:815
GaudiParallelizer::AlgorithmEntry::algorithm
Algorithm * algorithm() const
Definition: GaudiParallelizer.h:50
Algorithm::name
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:715
gaudiComponentHelp.name
name
Definition: gaudiComponentHelp.py:28
StatusCode::FAILURE
Definition: StatusCode.h:29
Gaudi::Property
Implementation of property with value of concrete type.
Definition: Property.h:314
IAlgorithm::sysStart
virtual StatusCode sysStart()=0
Startup method invoked by the framework.
GaudiCommon< Algorithm >::rootInTES
const std::string & rootInTES() const
Returns the "rootInTES" string.
Definition: GaudiCommon.h:708
Algorithm::isExecuted
bool isExecuted() const override
Has this algorithm been executed since the last reset?
Definition: Algorithm.cpp:725
CommonMessagingBase::info
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
Definition: CommonMessaging.h:123
System::typeinfoName
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:299
ISequencerTimerTool::addTimer
virtual int addTimer(const std::string &name)=0
add a timer entry with the specified name
GaudiAlgorithm::initialize
StatusCode initialize() override
standard initialization method
Definition: GaudiAlgorithm.cpp:44
StatusCode::isSuccess
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:74
GaudiCommon< Algorithm >::Error
StatusCode Error(const std::string &msg, const StatusCode st=StatusCode::FAILURE, const size_t mx=10) const
Print the error message and return with the given StatusCode.
MSG::DEBUG
Definition: IMessageSvc.h:18
GaudiParallelizer
Definition: GaudiParallelizer.h:21
std
STL namespace.
GaudiParallelizer::decodeNames
StatusCode decodeNames()
Decode a vector of string.
Definition: GaudiParallelizer.cpp:125
GaudiCommon< Algorithm >::context
const std::string & context() const
Returns the "context" string. Used to identify different processing states.
Definition: GaudiCommon.h:704
ISequencerTimerTool::increaseIndent
virtual void increaseIndent()=0
Increase the indentation of the name.
std::string::end
T end(T...args)
StatusCode::isFailure
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:84
ISequencerTimerTool::globalTiming
virtual bool globalTiming()=0
returns the flag telling that global timing is wanted
IAlgorithm::sysInitialize
virtual StatusCode sysInitialize()=0
Initialization method invoked by the framework.
SerializeSTL.h
Provide serialization function (output only) for some common STL classes (vectors, lists, pairs, maps) plus GaudiUtils::Map and GaudiUtils::HashMap.
std::string
STL class.
compareRootHistos.ref
string ref
Definition: compareRootHistos.py:14
GaudiParallelizer::finalize
StatusCode finalize() override
Algorithm finalization.
Definition: GaudiParallelizer.cpp:116
SmartIF::get
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:76
std::vector::push_back
T push_back(T...args)
Algorithm::isEnabled
bool isEnabled() const override
Is this algorithm enabled or disabled?
Definition: Algorithm.cpp:740
Gaudi::Utils::TypeNameString
Helper class to parse a string of format "type/name".
Definition: TypeNameString.h:12
Algorithm::setExecuted
void setExecuted(bool state) override
Set the executed flag to the specified state.
Definition: Algorithm.cpp:730
CommonMessagingBase::warning
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
Definition: CommonMessaging.h:120
StatusCode
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
GaudiParallelizer.h
GaudiAlgorithm::finalize
StatusCode finalize() override
standard finalization method
Definition: GaudiAlgorithm.cpp:58
DECLARE_ALGORITHM_FACTORY
#define DECLARE_ALGORITHM_FACTORY(x)
Definition: Algorithm.h:620
GaudiAlgorithm
The useful base class for data processing algorithms.
Definition: GaudiAlgorithm.h:94
Gaudi::Details::PropertyBase
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:32
GaudiParallelizer::m_nthreads
Gaudi::Property< unsigned short > m_nthreads
Definition: GaudiParallelizer.h:80
GaudiUtils::details::ostream_joiner
Stream & ostream_joiner(Stream &os, Iterator first, Iterator last, Separator sep, OutputElement output=OutputElement{})
Definition: SerializeSTL.h:35
GaudiParallelizer::m_task_group
tbb::task_group m_task_group
TBB task group.
Definition: GaudiParallelizer.h:87
ISequencerTimerTool::start
virtual void start(int index)=0
start the counter, i.e.
Algorithm::subAlgorithms
const std::vector< Algorithm * > * subAlgorithms() const
List of sub-algorithms. Returns a pointer to a vector of (sub) Algorithms.
Definition: Algorithm.cpp:754
Algorithm
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:78
Gaudi::StateMachine::RUNNING
Definition: StateMachine.h:16
std::vector
STL class.
gaudiComponentHelp.properties
properties
Definition: gaudiComponentHelp.py:37
CommonMessagingBase::debug
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
Definition: CommonMessaging.h:126
SmartIF::isValid
bool isValid() const
Allow for check if smart pointer is valid.
Definition: SmartIF.h:62
std::vector::begin
T begin(T...args)
Gaudi::Utils::TypeNameString::type
const std::string & type() const
Definition: TypeNameString.h:39
GaudiParallelizer::m_entries
std::vector< AlgorithmEntry > m_entries
List of algorithms to process.
Definition: GaudiParallelizer.h:82
IOTest.appMgr
appMgr
Definition: IOTest.py:83
ISequencerTimerTool.h
GaudiParallelizer::membershipHandler
void membershipHandler(Gaudi::Details::PropertyBase &theProp)
for asynchronous changes in the list of algorithms
Definition: GaudiParallelizer.cpp:259
GaudiParallelizer::m_names
Gaudi::Property< std::vector< std::string > > m_names
Definition: GaudiParallelizer.h:76
IAlgManager.h
GaudiParallelizer::m_timerTool
ISequencerTimerTool * m_timerTool
Pointer to the timer tool.
Definition: GaudiParallelizer.h:84
GaudiParallelizer::m_timer
int m_timer
Timer number for the sequencer.
Definition: GaudiParallelizer.h:85
AlgFactory.h
Gaudi::Utils::TypeNameString::name
const std::string & name() const
Definition: TypeNameString.h:40
StatusCode::ignore
void ignore() const
Definition: StatusCode.h:106
GaudiDict::typeName
std::string typeName(const std::type_info &typ)
Definition: Dictionary.cpp:21
CommonMessagingBase::msgLevel
MSG::Level msgLevel() const
get the output level from the embedded MsgStream
Definition: CommonMessaging.h:135
GaudiParallelizer::AlgorithmEntry
Definition: GaudiParallelizer.h:36
Algorithm::sysInitialize
StatusCode sysInitialize() override
Initialization method invoked by the framework.
Definition: Algorithm.cpp:82
ISequencerTimerTool::stop
virtual double stop(int index)=0
stop the counter, return the elapsed time
GaudiCommon< Algorithm >::release
StatusCode release(const IInterface *interface) const
Manual forced (and &#39;safe&#39;) release of the active tool or service.
GaudiParallelizer::AlgorithmEntry::run
void run(GaudiParallelizer &prlzr)
Thread task executor method to wrap an algorithm execution in.
Definition: GaudiParallelizer.h:56
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
Algorithm::FSMState
Gaudi::StateMachine::State FSMState() const override
returns the current state of the algorithm
Definition: Algorithm.h:190
IJobOptionsSvc.h