The Gaudi Framework  v28r3 (cc1cf868)
PrecedenceRulesGraph.h
Go to the documentation of this file.
1 #ifndef GAUDIHIVE_PRECEDENCERULESGRAPH_H
2 #define GAUDIHIVE_PRECEDENCERULESGRAPH_H
3 
4 // std includes
5 #include <vector>
6 #include <algorithm>
7 #include <unordered_map>
8 #include <chrono>
9 #include <fstream>
10 #include <sstream>
11 
12 #include <boost/graph/adjacency_list.hpp>
13 #include <boost/graph/graphml.hpp>
14 
15 // fwk includes
16 #include "AlgsExecutionStates.h"
17 #include "EventSlot.h"
18 #include "IGraphVisitor.h"
19 #include "GaudiKernel/Algorithm.h"
21 
22 #include "CPUCruncher.h"
23 
24 namespace boost {
25 
26  struct AlgoNodeStruct {
28  AlgoNodeStruct (const std::string& name, const int index = -1, const int& rank = -1, const double& runtime = -1, const double& eccentricity = -1.0) :
29  m_name(name), m_index(index), m_rank(rank), m_runtime(runtime), m_eccentricity(eccentricity) {}
31  int m_index;
32  int m_rank;
33  double m_runtime;
35  };
36 
37  typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, AlgoNodeStruct> ExecPlan;
38  typedef graph_traits<ExecPlan>::vertex_descriptor AlgoVertex;
39 }
40 
41 namespace concurrency {
42 
45 
47  public:
49  ControlFlowNode(PrecedenceRulesGraph& graph, unsigned int nodeIndex, const std::string& name) :
50  m_graph(&graph), m_nodeIndex(nodeIndex), m_nodeName(name) {}
52  virtual ~ControlFlowNode() {}
54  virtual void initialize(const std::unordered_map<std::string,unsigned int>& algname_index_map) = 0;
56  virtual bool accept(IGraphVisitor& visitor) = 0;
58  virtual bool promoteToControlReadyState(const int& slotNum,
59  AlgsExecutionStates& states,
60  std::vector<int>& node_decisions) const = 0;
62  virtual int updateState(AlgsExecutionStates& states,
63  std::vector<int>& node_decisions) const = 0;
65  virtual void printState(std::stringstream& output,
66  AlgsExecutionStates& states,
67  const std::vector<int>& node_decisions,
68  const unsigned int& recursionLevel) const = 0;
70  const unsigned int& getNodeIndex() const { return m_nodeIndex; }
71  const std::string& getNodeName() const { return m_nodeName; }
72  virtual void updateDecision(const int& slotNum,
73  AlgsExecutionStates& states,
74  std::vector<int>& node_decisions,
75  const AlgorithmNode* requestor = nullptr) const = 0;
76  public:
78  protected:
80  std::string stateToString(const int& stateId) const;
81  unsigned int m_nodeIndex;
83  };
84 
85 
86  class DecisionNode : public ControlFlowNode {
87  public:
89  DecisionNode(PrecedenceRulesGraph& graph, unsigned int nodeIndex, const std::string& name, bool modeConcurrent, bool modePromptDecision, bool modeOR, bool allPass) :
90  ControlFlowNode(graph, nodeIndex, name),
91  m_modeConcurrent(modeConcurrent), m_modePromptDecision(modePromptDecision), m_modeOR(modeOR), m_allPass(allPass), m_children()
92  {}
94  ~DecisionNode() override;
96  void initialize(const std::unordered_map<std::string,unsigned int>& algname_index_map) override;
97  bool accept(IGraphVisitor& visitor) override;
99  bool promoteToControlReadyState(const int& slotNum,
100  AlgsExecutionStates& states,
101  std::vector<int>& node_decisions) const override;
103  void updateDecision(const int& slotNum,
104  AlgsExecutionStates& states,
105  std::vector<int>& node_decisions,
106  const AlgorithmNode* requestor = nullptr) const override;
108  int updateState(AlgsExecutionStates& states,
109  std::vector<int>& node_decisions) const override;
111  void addParentNode(DecisionNode* node);
113  void addDaughterNode(ControlFlowNode* node);
115  const std::vector<ControlFlowNode*>& getDaughters() const {return m_children;}
117  void printState(std::stringstream& output,
118  AlgsExecutionStates& states,
119  const std::vector<int>& node_decisions,
120  const unsigned int& recursionLevel) const override;
121  public:
128  bool m_modeOR;
130  bool m_allPass;
131  private:
136  };
137 
138  class DataNode;
139 
141  public:
143  AlgorithmNode(PrecedenceRulesGraph& graph, unsigned int nodeIndex, const std::string& algoName, bool inverted, bool allPass, bool IOBound) :
144  ControlFlowNode(graph, nodeIndex, algoName),
145  m_algoIndex(0),m_algoName(algoName),m_inverted(inverted),m_allPass(allPass),m_rank(-1),m_isIOBound(IOBound)
146  {};
148  ~AlgorithmNode();
150  void initialize(const std::unordered_map<std::string,unsigned int>& algname_index_map) override;
152  bool accept(IGraphVisitor& visitor) override;
154  void addParentNode(DecisionNode* node);
155 
157  void addSupplierNode(AlgorithmNode* node) { m_suppliers.push_back(node); }
159  void addConsumerNode(AlgorithmNode* node) { m_consumers.push_back(node); }
161  void attachAlgorithm(IAlgorithm* ialgo) { m_representatives.push_back(ialgo); }
163  const std::vector<IAlgorithm*>& getAlgorithmRepresentatives () const { return m_representatives; }
165  const std::vector<AlgorithmNode*>& getSupplierNodes() const {return m_suppliers;}
167  const std::vector<AlgorithmNode*>& getConsumerNodes() const {return m_consumers;}
169  const std::vector<DecisionNode*>& getParentDecisionHubs() const {return m_parents;}
170 
172  void addOutputDataNode(DataNode* node);
174  void addInputDataNode(DataNode* node);
176  const std::vector<DataNode*>& getOutputDataNodes() const {return m_outputs;}
180  void setRank(float& rank) {m_rank = rank;}
182  const float& getRank() const {return m_rank;}
183 
185  const unsigned int& getAlgoIndex() const { return m_algoIndex; }
187  void setIOBound(bool value) { m_isIOBound = value;}
189  bool isIOBound() const {return m_isIOBound;}
191  bool isOptimist() const {return m_allPass;};
193  bool isLiar() const {return m_inverted;};
195  bool dataDependenciesSatisfied(const int& slotNum) const;
197  int updateState(AlgsExecutionStates& states,
198  std::vector<int>& node_decisions) const override;
200  bool promoteToControlReadyState(const int& slotNum,
201  AlgsExecutionStates& states,
202  std::vector<int>& node_decisions) const override;
204  bool promoteToDataReadyState(const int& slotNum, const AlgorithmNode* requestor = nullptr) const;
206  void updateDecision(const int& slotNum,
207  AlgsExecutionStates& states,
208  std::vector<int>& node_decisions,
209  const AlgorithmNode* requestor = nullptr) const override;
211  void printState(std::stringstream& output,
212  AlgsExecutionStates& states,
213  const std::vector<int>& node_decisions,
214  const unsigned int& recursionLevel) const override;
215  private:
217  unsigned int m_algoIndex;
223  bool m_allPass;
226 
232 
239  float m_rank;
244  };
245 
246 class DataNode {
247 public:
249  DataNode(PrecedenceRulesGraph& graph, const DataObjID& path): m_graph(&graph), m_data_object_path(path) {}
252  const DataObjID& getPath() {return m_data_object_path;}
254  bool accept(IGraphVisitor& visitor) {
255  if (visitor.visitEnter(*this))
256  return visitor.visit(*this);
257  return true;
258  }
261  if (std::find(m_producers.begin(),m_producers.end(),node) == m_producers.end())
262  m_producers.push_back(node);
263  }
266  if (std::find(m_consumers.begin(),m_consumers.end(),node) == m_consumers.end())
267  m_consumers.push_back(node);
268  }
270  const std::vector<AlgorithmNode*>& getProducers() const {return m_producers;}
272  const std::vector<AlgorithmNode*>& getConsumers() const {return m_consumers;}
273 public:
275 private:
279  };
280 
284 
287 
290  virtual ~IPrecedenceRulesGraph() = default;
291 };
292 
293 class PrecedenceRulesGraph : public CommonMessaging<IPrecedenceRulesGraph> {
295 public:
298  m_headNode(0), m_nodeCounter(0), m_svcLocator(svc), m_name(name), m_initTime(std::chrono::system_clock::now()),
299  m_eventSlots(nullptr) {}
302  if (m_headNode != 0) delete m_headNode;
303  }
305  StatusCode initialize(const std::unordered_map<std::string,unsigned int>& algname_index_map);
306  StatusCode initialize(const std::unordered_map<std::string,unsigned int>& algname_index_map,
307  std::vector<EventSlot>& eventSlots);
309  void registerIODataObjects(const Algorithm* algo);
311  StatusCode buildDataDependenciesRealm();
313  StatusCode buildAugmentedDataDependenciesRealm();
315  void addHeadNode(const std::string& headName, bool modeConcurrent, bool modePromptDecision, bool modeOR, bool allPass);
317  StatusCode addAlgorithmNode(Algorithm* daughterAlgo, const std::string& parentName, bool inverted, bool allPass);
319  template<class T>
320  void attachAlgorithmsToNodes(const std::string& algo_name, const T& container) {
321  auto node = getAlgorithmNode(algo_name);
322  for (auto ialgoIt = container.unsafe_begin(); ialgoIt != container.unsafe_end(); ++ialgoIt)
323  node->attachAlgorithm(*ialgoIt);
324  }
326  AlgorithmNode* getAlgorithmNode(const std::string& algoName) const;
328  StatusCode addDataNode(const DataObjID& dataPath);
330  DataNode* getDataNode(const DataObjID& dataPath) const;
332  StatusCode addDecisionHubNode(Algorithm* daughterAlgo, const std::string& parentName, bool modeConcurrent, bool modePromptDecision, bool modeOR, bool allPass);
334  unsigned int getControlFlowNodeCounter() const {return m_nodeCounter;}
336  void updateEventState(AlgsExecutionStates& states,
337  std::vector<int>& node_decisions) const;
339  void updateDecision(const std::string& algo_name,
340  const int& slotNum,
341  AlgsExecutionStates& states,
342  std::vector<int>& node_decisions) const;
344  void rankAlgorithms(IGraphVisitor& ranker) const;
347  AlgsExecutionStates& states,
348  const std::vector<int>& node_decisions,
349  const unsigned int& recursionLevel) const {m_headNode->printState(output,states,node_decisions,recursionLevel);}
351  const std::vector<AlgorithmNode*> getDataIndependentNodes() const;
353  const std::string& name() const override {return m_name;}
355  SmartIF<ISvcLocator>& serviceLocator() const override {return m_svcLocator;}
357  const std::chrono::system_clock::time_point getInitTime() const {return m_initTime;}
359  AlgsExecutionStates& getAlgoStates(const int& slotNum) const {return m_eventSlots->at(slotNum).algsStates;}
361  std::vector<int>& getNodeDecisions(const int& slotNum) const {return m_eventSlots->at(slotNum).controlFlowState;}
363  std::string dumpDataFlow() const;
365  std::string dumpControlFlow() const;
367  void dumpExecutionPlan();
369  void addEdgeToExecutionPlan(const AlgorithmNode* u, const AlgorithmNode* v);
370 
371 private:
384  unsigned int m_nodeCounter;
392 public:
394 
395  void dumpControlFlow(std::ostringstream&, ControlFlowNode*,
396  const int&) const;
397 
398 
399  };
400 
401 
402 } // namespace concurrency
403 
404 
405 #endif
std::vector< DataNode * > m_outputs
Vectors, used in augmented data dependencies realm Outputs of the algorithm, represented as DataNode&#39;...
const unsigned int & getAlgoIndex() const
XXX: CF tests.
std::vector< DecisionNode * > m_parents
XXX: CF tests. All direct parent nodes in the tree.
ControlFlowNode(PrecedenceRulesGraph &graph, unsigned int nodeIndex, const std::string &name)
Constructor.
std::unordered_map< std::string, DataObjIDColl > AlgoOutputsMap
unsigned int m_algoIndex
The index of the algorithm.
const std::chrono::system_clock::time_point getInitTime() const
DecisionNode(PrecedenceRulesGraph &graph, unsigned int nodeIndex, const std::string &name, bool modeConcurrent, bool modePromptDecision, bool modeOR, bool allPass)
Constructor.
AlgoNodeStruct(const std::string &name, const int index=-1, const int &rank=-1, const double &runtime=-1, const double &eccentricity=-1.0)
The namespace threadpool contains a thread pool and related utility classes.
Definition: iter_pos.hpp:13
void setIOBound(bool value)
Set the I/O-boundness flag.
void attachAlgorithmsToNodes(const std::string &algo_name, const T &container)
Attach pointers to real Algorithms (and their clones) to Algorithm nodes of the graph.
const std::chrono::system_clock::time_point m_initTime
std::string m_algoName
The name of the algorithm.
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, AlgoNodeStruct > ExecPlan
const std::vector< DataNode * > & getInputDataNodes() const
Get all consumer nodes.
bool isOptimist() const
Check if positive control flow decision is enforced.
std::vector< AlgorithmNode * > m_consumers
AlgorithmNodes that represent algorithms which need the output of the algorithm.
SmartIF< ISvcLocator > & serviceLocator() const override
Retrieve pointer to service locator.
AlgoNodesMap m_algoNameToAlgoNodeMap
Index: map of algorithm&#39;s name to AlgorithmNode.
virtual bool visit(DecisionNode &)
Definition: IGraphVisitor.h:17
void setRank(float &rank)
Set Algorithm rank.
std::vector< ControlFlowNode * > m_children
All direct daughter nodes in the tree.
std::unordered_map< std::string, DecisionNode * > DecisionHubsMap
const std::vector< IAlgorithm * > & getAlgorithmRepresentatives() const
get Algorithm representatives
void printState(std::stringstream &output, AlgsExecutionStates &states, const std::vector< int > &node_decisions, const unsigned int &recursionLevel) const
Print a string representing the control flow state.
std::vector< DecisionNode * > m_parents
XXX: CF tests.
STL namespace.
const std::vector< DataNode * > & getOutputDataNodes() const
Get all supplier nodes.
bool m_inverted
Whether the selection result is negated or not.
bool m_allPass
Whether always passing regardless of daughter results.
const std::vector< DecisionNode * > & getParentDecisionHubs() const
Get all parent decision hubs.
std::vector< int > & getNodeDecisions(const int &slotNum) const
bool isIOBound() const
Check if algorithm is I/O-bound.
~PrecedenceRulesGraph() override
Destructor.
virtual bool visitEnter(DecisionNode &) const
Definition: IGraphVisitor.h:16
STL class.
AlgorithmNode(PrecedenceRulesGraph &graph, unsigned int nodeIndex, const std::string &algoName, bool inverted, bool allPass, bool IOBound)
Constructor.
virtual ~ControlFlowNode()
Destructor.
bool m_modeOR
Whether acting as "and" (false) or "or" node (true)
T at(T...args)
const float & getRank() const
Get Algorithm rank.
std::vector< EventSlot > * m_eventSlots
The AlgsExecutionStates encodes the state machine for the execution of algorithms within a single eve...
Manage the execution flow using a graph of task precedence rules Once initialized, the graph is const and can be shared across events.
PrecedenceRulesGraph * m_graph
const DataObjID & getPath()
DecisionNode * m_headNode
the head node of the control flow graph; may want to have multiple ones once supporting trigger paths...
std::vector< AlgorithmNode * > m_consumers
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
std::unordered_map< DataObjID, DataNode *, DataObjID_Hasher > DataNodesMap
const std::vector< ControlFlowNode * > & getDaughters() const
bool accept(IGraphVisitor &visitor)
Entry point for a visitor.
graph_traits< ExecPlan >::vertex_descriptor AlgoVertex
std::unordered_map< std::string, DataObjIDColl > AlgoInputsMap
std::map< std::string, boost::AlgoVertex > m_exec_plan_map
const std::vector< AlgorithmNode * > & getConsumers() const
Get all data object consumers.
DataNode(PrecedenceRulesGraph &graph, const DataObjID &path)
Constructor.
const std::vector< AlgorithmNode * > & getConsumerNodes() const
Get all consumer nodes.
void addConsumerNode(AlgorithmNode *node)
Associate an AlgorithmNode, which is a data consumer of this one.
void attachAlgorithm(IAlgorithm *ialgo)
Attach Algorithm representative.
The IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:27
PrecedenceRulesGraph(const std::string &name, SmartIF< ISvcLocator > svc)
Constructor.
bool m_modePromptDecision
Whether to evaluate the hub decision ASA its child decisions allow to do that.
AlgsExecutionStates & getAlgoStates(const int &slotNum) const
float m_rank
Algorithm rank of any kind.
std::vector< IAlgorithm * > m_representatives
Representatives (including clones) of the node.
std::unordered_map< std::string, AlgorithmNode * > AlgoNodesMap
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:78
T find(T...args)
void addSupplierNode(AlgorithmNode *node)
Associate an AlgorithmNode, which is a data supplier for this one.
std::vector< InputHandle_t< In > > m_inputs
const std::vector< AlgorithmNode * > & getSupplierNodes() const
Get all supplier nodes.
std::vector< DataNode * > m_inputs
Inputs of the algorithm, represented as DataNode&#39;s.
bool m_modeConcurrent
Whether all daughters will be evaluated concurrently or sequentially.
Clock::time_point time_point
Definition: ITimelineSvc.h:11
std::vector< AlgorithmNode * > m_producers
boost::ExecPlan m_ExecPlan
temporary items to experiment with execution planning
unsigned int m_nodeCounter
Total number of nodes in the graph.
bool isLiar() const
Check if control flow logic is always inverted.
PrecedenceRulesGraph * m_graph
const std::string & getNodeName() const
const unsigned int & getNodeIndex() const
XXX: CF tests.
std::vector< AlgorithmNode * > m_suppliers
Vectors, used in data dependencies realm AlgorithmNodes that represent algorithms producing an input ...
State
Execution states of the algorithms.
const std::string & name() const override
Retrieve name of the service.
bool m_isIOBound
If an algorithm is I/O-bound (in the broad sense of Von Neumann bottleneck)
bool m_allPass
Whether the selection result is relevant or always "pass".
AlgoInputsMap m_algoNameToAlgoInputsMap
Indexes: maps of algorithm&#39;s name to algorithm&#39;s inputs/outputs.
void addProducerNode(AlgorithmNode *node)
Associate an AlgorithmNode, which is a data supplier for this one.
const std::vector< AlgorithmNode * > & getProducers() const
Get all data object producers.
DataNodesMap m_dataPathToDataNodeMap
Index: map of data path to DataNode.
unsigned int getControlFlowNodeCounter() const
Get total number of graph nodes.
SmartIF< ISvcLocator > m_svcLocator
Service locator (needed to access the MessageSvc)
AlgsExecutionStates::State State
void addConsumerNode(AlgorithmNode *node)
Associate an AlgorithmNode, which is a data consumer of this one.
DecisionHubsMap m_decisionNameToDecisionHubMap
Index: map of decision&#39;s name to DecisionHub.