ATLAS Offline Software
Loading...
Searching...
No Matches
GlobalSim::GraphSvc Class Reference

The GraphSvc can be used to create an execution graph of the global simulation part of the job. More...

#include <GraphSvc.h>

Inheritance diagram for GlobalSim::GraphSvc:
Collaboration diagram for GlobalSim::GraphSvc:

Public Member Functions

virtual StatusCode initialize () override
 Initialise.
virtual StatusCode start () override
 Start - do graph calculation here, to ensure EventLoopMgr initialized already.
virtual StatusCode finalize () override
 Finalise.

Private Attributes

StringProperty m_fileName {this,"FileName","graph.dot","Output file"}
StringProperty m_topSequence {this,"SequenceNameFilter","AthAlgSeq","Regex of sequence names to include"}
ServiceHandle< IAlgResourcePool > m_algResourcePool

Detailed Description

The GraphSvc can be used to create an execution graph of the global simulation part of the job.

Definition at line 17 of file GraphSvc.h.

Member Function Documentation

◆ finalize()

StatusCode GlobalSim::GraphSvc::finalize ( )
overridevirtual

Finalise.

Definition at line 178 of file GraphSvc.cxx.

178 {
179
180 ATH_MSG_INFO("To view graph run: dot -Teps " << m_fileName.value() << " -o graph.eps; gv graph.eps &");
181
182 return StatusCode::SUCCESS;
183
184 }
#define ATH_MSG_INFO(x,...)
StringProperty m_fileName
Definition GraphSvc.h:32

◆ initialize()

StatusCode GlobalSim::GraphSvc::initialize ( )
overridevirtual

Initialise.

Definition at line 21 of file GraphSvc.cxx.

21 {
22 return StatusCode::SUCCESS;
23 }

◆ start()

StatusCode GlobalSim::GraphSvc::start ( )
overridevirtual

Start - do graph calculation here, to ensure EventLoopMgr initialized already.

Definition at line 25 of file GraphSvc.cxx.

25 {
26
27 std::function<void(IAlgorithm*,std::set<IAlgorithm*>&,bool)> func;
28
29 std::regex sequenceNameRegex( m_topSequence.value() );
30
31 // locate the desired algs ...
32 func = [&](IAlgorithm* alg, std::set<IAlgorithm*>& thealgs, bool isAdding) {
33 isAdding = (isAdding || std::regex_search( std::string(alg->nameKey()) , sequenceNameRegex) ); // activate adding when get to target
34 if(isAdding) {
35 thealgs.insert(alg);
36 }
37 if(auto seq = dynamic_cast<Gaudi::Sequence*>( alg )) {
38 auto subalgs = seq->subAlgorithms();
39 for(auto thisAlg : *subalgs) {
40 func(thisAlg,thealgs,isAdding);
41 }
42 }
43 };
44
45 // Get the list of algorithms
46 const std::list<IAlgorithm*>& algos = m_algResourcePool->getTopAlgList();
47 std::set<IAlgorithm*> subalgs;
48 for ( IAlgorithm* ialgoPtr : algos ) {
49 func(ialgoPtr,subalgs,false);
50 }
51
52
53 DataObjIDColl globalInp, globalOutp;
54 std::map<std::string, DataObjIDColl> algosOutputDependenciesMap;
55 std::map<std::string, DataObjIDColl> algosInputDependenciesMap;
56
57 for ( IAlgorithm* ialgoPtr : subalgs ) {
58 if(ialgoPtr->isSequence()) continue; // don't look at sequences, shouldn't have any inputs/outputs
59
60 Gaudi::Algorithm* algoPtr = dynamic_cast<Gaudi::Algorithm*>( ialgoPtr );
61 if ( !algoPtr ) continue;
62 DataObjIDColl algoOutputs;
63 for ( const auto & id : algoPtr->outputDataObjs() ) {
64 globalOutp.insert( id );
65 algoOutputs.insert( id );
66 }
67
68
69
70 DataObjIDColl i1, i2;
71 DHHVisitor avis( i1, i2 );
72 algoPtr->acceptDHVisitor( &avis );
73
74 DataObjIDColl algoDependencies;
75 for ( const DataObjID& id : algoPtr->inputDataObjs() ) {
76 algoDependencies.insert( id );
77 globalInp.insert( id );
78 }
79
80 std::string algoName = ialgoPtr->nameKey();
81 if(ialgoPtr->type()!= algoName) {
82 algoName = ialgoPtr->type() + "/" + algoName;
83 }
84
85 algosInputDependenciesMap[algoName] = std::move(algoDependencies);
86 algosOutputDependenciesMap[algoName] = std::move(algoOutputs);
87
88 }
89
90
91 ATH_MSG_INFO("Creating " << m_fileName.value());
92 std::ofstream stream{ m_fileName, std::ofstream::out };
93 stream << "digraph datadeps {\n rankdir=\"LR\";\n"; // left-to-right graph
94
95 auto addNode = [&](std::string_view id, std::string_view name, std::string_view shape="box", std::string_view textcol="" ) {
96 stream << " " << id << " [label=\"" << name << "\"";
97 if(!textcol.empty()) stream << ", fontcolor=\"" << textcol << "\"";
98 stream << ";shape=" << shape << "];\n"; // adds a node
99 };
100 auto addEdge = [&](std::string_view srcId, std::string_view tgtId, std::string_view label ) {
101 stream << " " << srcId << " -> " << tgtId << " [label=\"" << label << "\"];\n"; // adds an edge
102 };
103
104 // find all inputs that do not have an output. These will be our 'starting nodes' of shape='plaintext'
105 std::map<std::string,std::pair<std::set<std::string>,std::set<std::string>>> deps;
106
107 // key is dep name, value is pair of sets, first are "producers" of dep, second a "consumers" of dep
108 // if has no producer, is a global input. if has no consumer, is a global output.
109
110 std::map<std::string,std::string> inputTypes;
111
112 for ( const auto& [algName, ideps] : algosInputDependenciesMap ) {
113 for (const auto &dep: ideps) {
114 deps[dep.key()].second.insert(algName); // alg is a consumer
115 // store classes of inputs
116 inputTypes[dep.key()] = dep.className();
117 }
118 }
119 for ( const auto& [algName, odeps] : algosOutputDependenciesMap ) {
120 for (const auto &dep: odeps) {
121 deps[dep.key()].first.insert(algName); // alg is a producer
122 }
123 }
124
125 std::size_t algoIndex = 0ul;
126 std::map<std::string,std::string> keyToName;
127 std::string inputs,outputs;
128 // start by creating nodes of global inputs and outputs
129 for( auto& [dep, pcs] : deps) {
130 auto& [producers,consumers] = pcs;
131 if(producers.empty()) {
132 std::string algIndex = "Input_" + std::to_string( algoIndex );
133 addNode( algIndex, inputTypes[dep]+"/"+dep.substr(dep.find("+")+1), "plaintext", (dep.find("ConditionStore")==0) ? "blue" : "" );
134 keyToName[dep] = algIndex;
135 algoIndex++;
136 producers.insert(dep); // its a self-producer
137 inputs += algIndex + "; ";
138 } else if(consumers.empty()) {
139 std::string algIndex = "Output_" + std::to_string( algoIndex );
140 addNode( algIndex, dep.substr(dep.find("+")+1), "plaintext" );
141 keyToName[dep] = algIndex;
142 algoIndex++;
143 consumers.insert(dep); // its a self-consumer
144 outputs += algIndex + "; ";
145 }
146 }
147 // create nodes of all algorithms
148 for ( const auto& [algName, ideps] : algosInputDependenciesMap ) {
149 std::string algIndex = "Alg_" + std::to_string( algoIndex );
150 addNode( algIndex, algName, "box" );
151 keyToName[algName] = std::move(algIndex);
152 algoIndex++;
153 }
154 // now go through deps and create link from every producer to every consumer
155 for( const auto& [dep, pcs] : deps) {
156 auto& [producers,consumers] = pcs;
157 for(auto& producer : producers) {
158 for(auto& consumer: consumers) {
159 addEdge(keyToName.at(producer),keyToName.at(consumer),dep!=producer && dep!=consumer ? (inputTypes[dep]+"/"+dep.substr(dep.find("+")+1)) : " ");
160 }
161 }
162 }
163
164 if(!inputs.empty()) {
165 stream << " { rank = same; " << inputs << "}\n";
166 }
167 if(!outputs.empty()) {
168 stream << " { rank = same; " << outputs << "}\n";
169 }
170
171 stream << "}\n";
172 stream.close();
173
174 return StatusCode::SUCCESS;
175
176 }
StringProperty m_topSequence
Definition GraphSvc.h:33
ServiceHandle< IAlgResourcePool > m_algResourcePool
Definition GraphSvc.h:35
std::string label(const std::string &format, int i)
Definition label.h:19
unsigned long ul

Member Data Documentation

◆ m_algResourcePool

ServiceHandle<IAlgResourcePool> GlobalSim::GraphSvc::m_algResourcePool
private
Initial value:
{this,"AlgResourcePool","AlgResourcePool",
"Algorithm resource pool service."}

Definition at line 35 of file GraphSvc.h.

35 {this,"AlgResourcePool","AlgResourcePool",
36 "Algorithm resource pool service."};

◆ m_fileName

StringProperty GlobalSim::GraphSvc::m_fileName {this,"FileName","graph.dot","Output file"}
private

Definition at line 32 of file GraphSvc.h.

32{this,"FileName","graph.dot","Output file"};

◆ m_topSequence

StringProperty GlobalSim::GraphSvc::m_topSequence {this,"SequenceNameFilter","AthAlgSeq","Regex of sequence names to include"}
private

Definition at line 33 of file GraphSvc.h.

33{this,"SequenceNameFilter","AthAlgSeq","Regex of sequence names to include"};

The documentation for this class was generated from the following files: