| The Gaudi Framework v30r0 (c919700c)

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