| The Gaudi Framework v32r1 (f65d50dc)

Promoters.cpp
Go to the documentation of this file.
1 #include "Promoters.h"
2 #include "../../AlgsExecutionStates.h"
3 #include "Validators.h"
4
5 #include "GaudiKernel/DataObjID.h"
6 #include "GaudiKernel/ICondSvc.h"
7
8 #include <queue>
9
10 namespace concurrency {
11 using AState = AlgsExecutionStates::State;
12
13 //--------------------------------------------------------------------------
14 bool DataReadyPromoter::visitEnter( AlgorithmNode& node ) const {
15
16 if ( AState::CONTROLREADY != m_slot->algsStates[node.getAlgoIndex()] ) return false;
17
18 return true;
19 }
20
21 //--------------------------------------------------------------------------
22 bool DataReadyPromoter::visit( AlgorithmNode& node ) {
23
24 bool result = true; // return true if this algorithm has no data inputs
25
26 for ( auto dataNode : node.getInputDataNodes() ) {
27
28 result = dataNode->accept( *this );
29
30 // With ConditionNodes, one may decide NOT to break here so that associated
31 // ConditionAlgorithms are scheduled ASAP. This behavior can be made configurable
32 if ( !result ) break; // skip checking other inputs if this input was not produced yet
33 }
34
35 if ( result ) {
36 m_slot->algsStates.set( node.getAlgoIndex(), AState::DATAREADY ).ignore();
37
38 if ( m_trace ) {
39 auto sourceNode = ( m_cause.m_source == Cause::source::Task )
40 ? node.m_graph->getAlgorithmNode( m_cause.m_sourceName )
41 : nullptr;
42 node.m_graph->addEdgeToPrecTrace( sourceNode, &node );
43 }
44 }
45
46 // return true only if an algorithm is promoted to DR
47 return result;
48 }
49
50 //--------------------------------------------------------------------------
51 bool DataReadyPromoter::visitEnter( DataNode& ) const { return true; }
52
53 //--------------------------------------------------------------------------
54 bool DataReadyPromoter::visit( DataNode& node ) {
55 /* Implements 'observer' strategy, i.e., only check if producer of this DataNode
56 * has been already executed or not */
57
58 auto const& producers = node.getProducers();
59 for ( auto algoNode : producers ) {
60 const auto& state = m_slot->algsStates[algoNode->getAlgoIndex()];
61 if ( AState::EVTACCEPTED == state || AState::EVTREJECTED == state ) {
62 return true; // skip checking other producers if one was found to be executed
63 }
64 }
65
66 // Check parent slot if necessary
67 if ( m_slot->parentSlot ) {
68 for ( auto algoNode : producers ) {
69 const auto& state = m_slot->parentSlot->algsStates[algoNode->getAlgoIndex()];
70 if ( AState::EVTACCEPTED == state || AState::EVTREJECTED == state ) {
71 return true; // skip checking other producers if one was found to be executed
72 }
73 }
74 }
75
76 // return true only if this DataNode is produced
77 return false;
78 }
79
80 //--------------------------------------------------------------------------
81 bool DataReadyPromoter::visitEnter( ConditionNode& node ) const {
82
83 if ( node.m_condSvc->isValidID( *( m_slot->eventContext ), node.getPath() ) )
84 return false; // do not enter this ConditionNode if the condition has bee already loaded
85
86 return true;
87 }
88
89 //--------------------------------------------------------------------------
90 bool DataReadyPromoter::visit( ConditionNode& node ) {
91 /* Implements 'requester' strategy, i.e., requests this ConditionNode to be loaded
92 * by its associated ConditionAlgorithm */
93
94 auto promoter = Supervisor( *m_slot, m_cause, m_trace );
95
96 for ( auto condAlg : node.getProducers() ) condAlg->accept( promoter );
97
98 // this method is called if, and only if, this ConditionNode is not yet produced.
99 // thus, by definition, this ConditionNode is not yet available at this moment
100 return false;
101 }
102
103 //--------------------------------------------------------------------------
104 bool DecisionUpdater::visit( AlgorithmNode& node ) {
105
106 auto& states = m_slot->algsStates;
107 const AState& state = states[node.getAlgoIndex()];
108 int decision = -1;
109
110 if ( true == node.isOptimist() )
111 decision = 1;
112 else if ( AState::EVTACCEPTED == state )
113 decision = !node.isLiar();
114 else if ( AState::EVTREJECTED == state )
115 decision = node.isLiar();
116
117 if ( -1 != decision ) {
118
119 m_slot->controlFlowState[node.getNodeIndex()] = decision;
120
121 auto promoter = DataReadyPromoter( *m_slot, m_cause, m_trace );
122 for ( const auto& output : node.getOutputDataNodes() )
123 for ( auto& consumer : output->getConsumers() ) consumer->accept( promoter );
124
125 // propagate decision upward to active regions of the graph
126 auto vis = concurrency::Supervisor( *m_slot, m_cause, m_trace );
127 auto& parents = node.getParentDecisionHubs();
128 if ( parents.size() == 1 ) {
129 parents[0]->accept( vis );
130 } else if ( m_slot->parentSlot ) {
131 auto scout = SubSlotScout( m_slot, node );
132 for ( auto& p : parents ) {
133 p->accept( scout );
134 if ( scout.reply() ) p->accept( vis );
135 scout.reset();
136 }
137 } else {
138 auto scout = ActiveLineageScout( m_slot, node );
139 for ( auto& p : parents ) {
140 p->accept( scout );
141 if ( scout.reply() ) p->accept( vis );
142 scout.reset();
143 }
144 }
145
146 return true; // return true only if the algorithm produced a decision
147 }
148
149 return false;
150 }
151
152 //---------------------------------------------------------------------------
153 bool Supervisor::visitEnter( DecisionNode& node ) const {
154
155 if ( m_slot->controlFlowState[node.getNodeIndex()] != -1 ) return false;
156 return true;
157 }
158
159 //---------------------------------------------------------------------------
160 bool Supervisor::visit( DecisionNode& node ) {
161
162 bool foundNonResolvedChild = false;
163 bool foundNegativeChild = false;
164 bool foundPositiveChild = false;
165 int decision = -1;
166
167 // Leave a sub-slot if this is the exit node
168 EventSlot* oldSlot = nullptr;
169 if ( m_slot->parentSlot && m_slot->entryPoint == node.getNodeName() ) {
170 oldSlot = m_slot;
171 m_slot = m_slot->parentSlot;
172 }
173
174 // If children are in sub-slots, loop over all
175 auto searchResult = m_slot->subSlotsByNode.find( node.getNodeName() );
176 if ( searchResult != m_slot->subSlotsByNode.end() ) {
177 bool breakout = false;
178 for ( unsigned int slotIndex : searchResult->second ) {
179
180 // Enter the sub-slot
181 m_slot = &( m_slot->allSubSlots[slotIndex] );
182
183 for ( auto child : node.getDaughters() ) {
184
185 int& childDecision = m_slot->controlFlowState[child->getNodeIndex()];
186
187 if ( childDecision == -1 )
188 foundNonResolvedChild = true;
189 else if ( childDecision == 1 )
190 foundPositiveChild = true;
191 else
192 foundNegativeChild = true;
193
194 if ( node.m_modePromptDecision ) {
195 if ( node.m_modeOR && foundPositiveChild ) {
196 decision = 1;
197 breakout = true;
198 break;
199 } else if ( !node.m_modeOR && foundNegativeChild ) {
200 decision = 0;
201 breakout = true;
202 break;
203 }
204 } else {
205 if ( foundNonResolvedChild ) {
206 breakout = true;
207 break;
208 }
209 }
210 }
211
212 // Leave the sub-slot
213 m_slot = m_slot->parentSlot;
214 if ( breakout ) break;
215 }
216 } else {
217 for ( auto child : node.getDaughters() ) {
218 int& childDecision = m_slot->controlFlowState[child->getNodeIndex()];
219
220 if ( childDecision == -1 )
221 foundNonResolvedChild = true;
222 else if ( childDecision == 1 )
223 foundPositiveChild = true;
224 else
225 foundNegativeChild = true;
226
227 if ( node.m_modePromptDecision ) {
228 if ( node.m_modeOR && foundPositiveChild ) {
229 decision = 1;
230 break;
231 } else if ( !node.m_modeOR && foundNegativeChild ) {
232 decision = 0;
233 break;
234 }
235 } else {
236 if ( foundNonResolvedChild ) break;
237 }
238 }
239 } // end monitoring children
240
241 if ( !foundNonResolvedChild && decision == -1 ) {
242 if ( node.m_modeOR ) { // OR
243 if ( foundPositiveChild )
244 decision = 1;
245 else
246 decision = 0;
247 } else { // AND
248 if ( foundNegativeChild )
249 decision = 0;
250 else
251 decision = 1;
252 }
253 }
254
255 if ( node.m_inverted && decision == 1 )
256 decision = 0;
257 else if ( node.m_inverted && decision == 0 )
258 decision = 1;
259
260 if ( node.m_allPass && !foundNonResolvedChild ) decision = 1;
261
262 if ( decision != -1 ) {
263 m_slot->controlFlowState[node.getNodeIndex()] = decision;
264
265 // propagate aggregated decision upward to active regions of the graph
266 if ( node.m_parents.size() == 1 ) {
267 node.m_parents[0]->accept( *this );
268 } else if ( m_slot->parentSlot ) {
269 auto scout = SubSlotScout( m_slot, node );
270 for ( auto& p : node.m_parents ) {
271 p->accept( scout );
272 if ( scout.reply() ) p->accept( *this );
273 scout.reset();
274 }
275 } else {
276 auto scout = ActiveLineageScout( m_slot, node );
277 for ( auto& p : node.m_parents ) {
278 p->accept( scout );
279 if ( scout.reply() ) p->accept( *this );
280 scout.reset();
281 }
282 }
283
284 if ( oldSlot ) m_slot = oldSlot;
285 return true;
286 }
287
288 // if no decision can be made yet, request further information downwards
289 // Enter subslots for children if needed
290 if ( searchResult != m_slot->subSlotsByNode.end() ) {
291 for ( unsigned int slotIndex : searchResult->second ) {
292
293 // Enter sub-slot
294 m_slot = &( m_slot->allSubSlots[slotIndex] );
295
296 for ( auto child : node.getDaughters() ) {
297 bool result = child->accept( *this );
298 if ( !node.m_modeConcurrent )
299 if ( result ) break; // stop on first unresolved child if its decision hub is sequential
300 }
301
302 // Leave sub-slot
303 m_slot = m_slot->parentSlot;
304 }
305 } else {
306 for ( auto child : node.getDaughters() ) {
307 bool result = child->accept( *this );
308 if ( !node.m_modeConcurrent )
309 if ( result ) break; // stop on first unresolved child if its decision hub is sequential
310 }
311 }
312
313 if ( oldSlot ) m_slot = oldSlot;
314 return false;
315 }
316
317 //---------------------------------------------------------------------------
318 bool Supervisor::visitEnter( AlgorithmNode& node ) const {
319
320 if ( m_slot->controlFlowState[node.getNodeIndex()] != -1 ) return false;
321 return true;
322 }
323
324 //--------------------------------------------------------------------------
325 bool Supervisor::visit( AlgorithmNode& node ) {
326
327 bool result = false;
328
329 auto& states = m_slot->algsStates;
330 auto& state = states[node.getAlgoIndex()];
331
332 // Promote with INITIAL->CR
333 if ( AState::INITIAL == state ) states.set( node.getAlgoIndex(), AState::CONTROLREADY ).ignore();
334
335 // Try to promote with CR->DR
336 if ( AState::CONTROLREADY == state ) {
337 auto promoter = DataReadyPromoter( *m_slot, m_cause, m_trace );
338 result = promoter.visit( node );
339 } else {
340 result = true;
341 }
342
343 // return true only when an algorithm is not lower than DR in its FSM
344 // i.e., the visitor has done everything it could with this algorithm
345 return result;
346 }
347
348 //---------------------------------------------------------------------------
349 bool RunSimulator::visitEnter( DecisionNode& node ) const {
350
351 if ( m_slot->controlFlowState[node.getNodeIndex()] != 1 ) return true;
352 return false;
353 }
354
355 //---------------------------------------------------------------------------
356 bool RunSimulator::visit( DecisionNode& node ) {
357
358 bool allChildDecisionsResolved = true;
359
360 for ( const auto& child : node.getDaughters() ) {
361
362 child->accept( *this );
363
364 int childDecision = m_slot->controlFlowState[child->getNodeIndex()];
365 if ( childDecision == -1 ) allChildDecisionsResolved = false;
366
367 // process children sequentially if their decision hub is sequential
368 if ( !node.m_modeConcurrent && childDecision == -1 ) return false;
369
370 if ( childDecision == 1 && node.m_modeOR && node.m_modePromptDecision ) {
371 m_slot->controlFlowState[node.getNodeIndex()] = 1;
372
373 // if a decision was made for this node, propagate the result upwards
374 for ( auto parent : node.m_parents ) { parent->accept( *this ); }
375 return true;
376 }
377 }
378
379 if ( allChildDecisionsResolved ) {
380 m_slot->controlFlowState[node.getNodeIndex()] = 1;
381
382 // if a decision was made for this node, propagate the result upwards
383 for ( auto parent : node.m_parents ) { parent->accept( *this ); }
384 }
385
386 return allChildDecisionsResolved;
387 }
388
389 //---------------------------------------------------------------------------
390 bool RunSimulator::visitEnter( AlgorithmNode& node ) const {
391
392 if ( m_slot->controlFlowState[node.getNodeIndex()] != 1 ) return true;
393 return false;
394 }
395
396 //--------------------------------------------------------------------------
397 bool RunSimulator::visit( AlgorithmNode& node ) {
398
399 auto& states = m_slot->algsStates;
400 int& decision = m_slot->controlFlowState[node.getNodeIndex()];
401
402 auto dataPromoter = DataReadyPromoter( *m_slot, m_cause );
403
404 if ( AState::INITIAL == states[node.getAlgoIndex()] ) {
405 states.set( node.getAlgoIndex(), AState::CONTROLREADY );
406 if ( dataPromoter.visit( node ) ) {
407 states.set( node.getAlgoIndex(), AState::SCHEDULED );
408 states.set( node.getAlgoIndex(), AState::EVTACCEPTED );
409 decision = 1;
410 ++m_nodesSucceeded;
411 // std::cout << "Algorithm decided: " << node.getNodeName() << std::endl;
412 return true;
413 }
414 } else if ( AState::CONTROLREADY == states[node.getAlgoIndex()] && dataPromoter.visit( node ) ) {
415 states.set( node.getAlgoIndex(), AState::SCHEDULED );
416 states.set( node.getAlgoIndex(), AState::EVTACCEPTED );
417 decision = 1;
418 ++m_nodesSucceeded;
419 // std::cout << "Algorithm decided: " << node.getNodeName() << std::endl;
420 return true;
421 }
422
423 return false;
424 }
425 } // namespace concurrency
concurrency::Supervisor::m_slot
EventSlot * m_slot
Definition: Promoters.h:71
EventSlot::entryPoint
std::string entryPoint
Event Views bookkeeping (TODO: optimize view bookkeeping)
Definition: EventSlot.h:84
EventSlot
Class representing an event slot.
Definition: EventSlot.h:14
Cause::source::Task
concurrency::DecisionNode::m_parents
std::vector< DecisionNode * > m_parents
Direct parent nodes.
Definition: PrecedenceRulesGraph.h:469
concurrency::DecisionNode
Definition: PrecedenceRulesGraph.h:430
concurrency::RunSimulator::m_nodesSucceeded
int m_nodesSucceeded
Definition: Promoters.h:97
concurrency::ControlFlowNode::getNodeName
const std::string & getNodeName() const
Get node name.
Definition: PrecedenceRulesGraph.h:420
concurrency::PrecedenceRulesGraph::getAlgorithmNode
AlgorithmNode * getAlgorithmNode(const std::string &algoName) const
Get the AlgorithmNode from by algorithm name using graph index.
Definition: PrecedenceRulesGraph.h:649
concurrency::DataReadyPromoter::visit
bool visit(AlgorithmNode &) override
Definition: Promoters.cpp:22
concurrency::AlgorithmNode::getParentDecisionHubs
const std::vector< DecisionNode * > & getParentDecisionHubs() const
Get all parent decision hubs.
Definition: PrecedenceRulesGraph.h:494
concurrency::DataNode
Definition: PrecedenceRulesGraph.h:555
gaudirun.output
output
Definition: gaudirun.py:484
concurrency
Definition: PrecedenceRulesGraph.cpp:27
concurrency::Supervisor::m_trace
bool m_trace
Definition: Promoters.h:73
concurrency::SubSlotScout
Definition: Validators.h:65
concurrency::DataReadyPromoter::m_slot
EventSlot * m_slot
Definition: Promoters.h:32
concurrency::DecisionUpdater::m_slot
EventSlot * m_slot
Definition: Promoters.h:48
Promoters.h
EventSlot::controlFlowState
std::vector< int > controlFlowState
State of the control flow.
Definition: EventSlot.h:77
Cause::m_source
source m_source
Definition: PrecedenceRulesGraph.h:390
std::unordered_map::end
T end(T... args)
EventSlot::allSubSlots
std::vector< EventSlot > allSubSlots
Actual sub-slot instances.
Definition: EventSlot.h:90
concurrency::DecisionNode::m_allPass
bool m_allPass
Whether always passing regardless of daughter results.
Definition: PrecedenceRulesGraph.h:463
concurrency::RunSimulator::visit
bool visit(DecisionNode &) override
Definition: Promoters.cpp:356
concurrency::AlgorithmNode::isOptimist
bool isOptimist() const
Check if positive control flow decision is enforced.
Definition: PrecedenceRulesGraph.h:521
concurrency::DataReadyPromoter::visitEnter
bool visitEnter(AlgorithmNode &) const override
Definition: Promoters.cpp:14
concurrency::DecisionUpdater::visit
bool visit(AlgorithmNode &) override
Definition: Promoters.cpp:104
concurrency::AlgorithmNode::getAlgoIndex
const unsigned int & getAlgoIndex() const
Get algorithm index.
Definition: PrecedenceRulesGraph.h:513
concurrency::DecisionNode::m_modeOR
bool m_modeOR
Whether acting as "and" (false) or "or" node (true)
Definition: PrecedenceRulesGraph.h:461
Validators.h
concurrency::DataNode::getProducers
const std::vector< AlgorithmNode * > & getProducers() const
Get all data object producers.
Definition: PrecedenceRulesGraph.h:580
concurrency::RunSimulator::m_cause
Cause m_cause
Definition: Promoters.h:96
concurrency::ControlFlowNode::m_graph
PrecedenceRulesGraph * m_graph
Definition: PrecedenceRulesGraph.h:423
concurrency::DataNode::getPath
const DataObjID & getPath()
Definition: PrecedenceRulesGraph.h:563
concurrency::RunSimulator::m_slot
EventSlot * m_slot
Definition: Promoters.h:93
ICondSvc::isValidID
virtual bool isValidID(const EventContext &ctx, const DataObjID &id) const =0
check to see if a specific condition object ID is valid for this event
AlgsExecutionStates::set
StatusCode set(unsigned int iAlgo, State newState)
Definition: AlgsExecutionStates.cpp:13
compareRootHistos.state
def state
Definition: compareRootHistos.py:455
concurrency::DecisionUpdater::m_trace
bool m_trace
Definition: Promoters.h:50
concurrency::ActiveLineageScout
Definition: Validators.h:33
concurrency::DataReadyPromoter::m_trace
bool m_trace
Definition: Promoters.h:34
AlgsExecutionStates::State
State
Execution states of the algorithms.
Definition: AlgsExecutionStates.h:29
concurrency::DecisionNode::getDaughters
const std::vector< ControlFlowNode * > & getDaughters() const
Get children nodes.
Definition: PrecedenceRulesGraph.h:450
concurrency::DecisionNode::m_modePromptDecision
bool m_modePromptDecision
Whether to evaluate the hub decision ASA its child decisions allow to do that.
Definition: PrecedenceRulesGraph.h:459
concurrency::DataReadyPromoter::m_cause
Cause m_cause
Definition: Promoters.h:33
DataObjID.h
concurrency::PrecedenceRulesGraph::addEdgeToPrecTrace
void addEdgeToPrecTrace(const AlgorithmNode *u, const AlgorithmNode *v)
set cause-effect connection between two algorithms in the precedence trace
Definition: PrecedenceRulesGraph.cpp:635
concurrency::Supervisor::visitEnter
bool visitEnter(DecisionNode &) const override
Definition: Promoters.cpp:153
concurrency::Supervisor::visit
bool visit(DecisionNode &) override
Definition: Promoters.cpp:160
std::unordered_map::find
T find(T... args)
concurrency::DecisionNode::m_modeConcurrent
bool m_modeConcurrent
Whether all daughters will be evaluated concurrently or sequentially.
Definition: PrecedenceRulesGraph.h:456
concurrency::AlgorithmNode::getInputDataNodes
const std::vector< DataNode * > & getInputDataNodes() const
Get all consumer nodes.
Definition: PrecedenceRulesGraph.h:503
concurrency::DecisionUpdater::m_cause
Cause m_cause
Definition: Promoters.h:49
concurrency::RunSimulator::visitEnter
bool visitEnter(DecisionNode &) const override
Definition: Promoters.cpp:349
concurrency::ConditionNode
Definition: PrecedenceRulesGraph.h:593
concurrency::AlgorithmNode::getOutputDataNodes
const std::vector< DataNode * > & getOutputDataNodes() const
Get all supplier nodes.
Definition: PrecedenceRulesGraph.h:501
EventSlot::parentSlot
EventSlot * parentSlot
Pointer to parent slot (null for top level)
Definition: EventSlot.h:86
concurrency::AlgorithmNode
Definition: PrecedenceRulesGraph.h:475
concurrency::DecisionNode::m_inverted
bool m_inverted
Whether the selection result is negated or not.
Definition: PrecedenceRulesGraph.h:465
concurrency::DataReadyPromoter
Definition: Promoters.h:11
concurrency::AlgorithmNode::isLiar
bool isLiar() const
Check if control flow logic is always inverted.
Definition: PrecedenceRulesGraph.h:523
concurrency::Supervisor
Definition: Promoters.h:54
concurrency::ControlFlowNode::getNodeIndex
const unsigned int & getNodeIndex() const
Get node index.
Definition: PrecedenceRulesGraph.h:418
concurrency::Supervisor::m_cause
Cause m_cause
Definition: Promoters.h:72
EventSlot::subSlotsByNode
std::unordered_map< std::string, std::vector< unsigned int > > subSlotsByNode
Listing of sub-slots by the node (name) they are attached to.
Definition: EventSlot.h:88
ICondSvc.h
EventSlot::eventContext
std::unique_ptr< EventContext > eventContext
Cache for the eventContext.
Definition: EventSlot.h:73
Cause::m_sourceName
std::string m_sourceName
Definition: PrecedenceRulesGraph.h:391
EventSlot::algsStates
AlgsExecutionStates algsStates
Vector of algorithms states.
Definition: EventSlot.h:75
concurrency::ConditionNode::m_condSvc
SmartIF< ICondSvc > m_condSvc
Definition: PrecedenceRulesGraph.h:608