Skip to content

Commit 2fec2ab

Browse files
committed
Remove SubProcess related code from the DependencyGraph service
1 parent c83ecb1 commit 2fec2ab

File tree

1 file changed

+68
-71
lines changed

1 file changed

+68
-71
lines changed

FWCore/Services/plugins/DependencyGraph.cc

Lines changed: 68 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
/*
22
* Simple Service to make a GraphViz graph of the modules runtime dependencies:
33
* - draw hard dependencies according to the "consumes" dependencies;
4-
* - draw soft dependencies to reflect the order of scheduled modue in each path;
5-
* - draw SubProcesses in subgraphs.
4+
* (only event dependences included, not run/lumi/process block dependences)
5+
* - draw soft dependencies to reflect the order of scheduled modules in each path;
66
*
77
* Use GraphViz dot to generate an SVG representation of the dependencies:
88
*
99
* dot -v -Tsvg dependency.dot -o dependency.svg
1010
*
1111
*/
1212

13-
#include <iostream>
14-
#include <vector>
13+
#include <cstddef>
14+
#include <fstream>
15+
#include <limits>
16+
#include <map>
1517
#include <string>
1618
#include <type_traits>
19+
#include <unordered_set>
20+
#include <utility>
21+
#include <vector>
1722

1823
// boost optional (used by boost graph) results in some false positives with -Wmaybe-uninitialized
1924
#pragma GCC diagnostic push
@@ -31,7 +36,6 @@
3136
#include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
3237
#include "FWCore/ServiceRegistry/interface/PathsAndConsumesOfModulesBase.h"
3338
#include "FWCore/ServiceRegistry/interface/ProcessContext.h"
34-
#include "FWCore/Utilities/interface/Exception.h"
3539
#include "FWCore/MessageLogger/interface/MessageLogger.h"
3640

3741
using namespace edm;
@@ -40,6 +44,8 @@ using namespace edm::service;
4044
namespace {
4145
namespace {
4246

47+
constexpr std::size_t kInvalidVertex = std::numeric_limits<std::size_t>::max();
48+
4349
template <typename T>
4450
std::unordered_set<T> make_unordered_set(std::vector<T> &&entries) {
4551
std::unordered_set<T> u;
@@ -55,7 +61,7 @@ class DependencyGraph {
5561
public:
5662
DependencyGraph(const ParameterSet &, ActivityRegistry &);
5763

58-
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions);
64+
static void fillDescriptions(edm::ConfigurationDescriptions &);
5965

6066
void preSourceConstruction(ModuleDescription const &);
6167
void lookupInitializationComplete(PathsAndConsumesOfModulesBase const &, ProcessContext const &);
@@ -123,7 +129,9 @@ class DependencyGraph {
123129
std::unordered_set<std::string> m_highlightModules;
124130

125131
bool m_showPathDependencies;
126-
bool m_initialized;
132+
133+
std::vector<std::size_t> m_moduleIDToGraphIndex;
134+
std::size_t m_nextGraphIndexToAdd = 0;
127135
};
128136

129137
constexpr const char *DependencyGraph::module_type_desc[];
@@ -167,8 +175,7 @@ DependencyGraph::DependencyGraph(ParameterSet const &config, ActivityRegistry &r
167175
: m_filename(config.getUntrackedParameter<std::string>("fileName")),
168176
m_highlightModules(
169177
make_unordered_set(config.getUntrackedParameter<std::vector<std::string>>("highlightModules"))),
170-
m_showPathDependencies(config.getUntrackedParameter<bool>("showPathDependencies")),
171-
m_initialized(false) {
178+
m_showPathDependencies(config.getUntrackedParameter<bool>("showPathDependencies")) {
172179
registry.watchPreSourceConstruction(this, &DependencyGraph::preSourceConstruction);
173180
registry.watchLookupInitializationComplete(this, &DependencyGraph::lookupInitializationComplete);
174181
}
@@ -189,11 +196,19 @@ iterator_pair_as_a_range<I> make_range(std::pair<I, I> p) {
189196
}
190197

191198
void DependencyGraph::preSourceConstruction(ModuleDescription const &module) {
192-
// create graph vertex for the source module and fill its attributes
199+
if (module.id() >= m_moduleIDToGraphIndex.size()) {
200+
m_moduleIDToGraphIndex.resize(module.id() + 1, kInvalidVertex);
201+
}
202+
m_moduleIDToGraphIndex[module.id()] = m_nextGraphIndexToAdd;
203+
++m_nextGraphIndexToAdd;
204+
205+
auto graphIndex = m_moduleIDToGraphIndex[module.id()];
206+
207+
// Create graph vertex for the source module and fill its attributes
193208
boost::add_vertex(m_graph);
194-
m_graph.m_graph[module.id()] =
209+
m_graph.m_graph[graphIndex] =
195210
node{module.moduleLabel(), module.moduleName(), module.id(), EDMModuleType::Source, true};
196-
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), 0);
211+
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), graphIndex);
197212
attributes["label"] = module.moduleLabel();
198213
attributes["tooltip"] = module.moduleName();
199214
attributes["shape"] = shapes[static_cast<std::underlying_type_t<EDMModuleType>>(EDMModuleType::Source)];
@@ -204,47 +219,38 @@ void DependencyGraph::preSourceConstruction(ModuleDescription const &module) {
204219

205220
void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase const &pathsAndConsumes,
206221
ProcessContext const &context) {
207-
// if the Service is not in the main Process do not do anything
208-
if (context.isSubProcess() and not m_initialized) {
209-
edm::LogError("DependencyGraph") << "You have requested an instance of the DependencyGraph Service in the \""
210-
<< context.processName()
211-
<< "\" SubProcess, which is not supported.\nPlease move it to the main process.";
212-
return;
213-
}
214-
215-
if (not context.isSubProcess()) {
216-
// set the graph name property to the process name
217-
boost::get_property(m_graph, boost::graph_name) = context.processName();
218-
boost::get_property(m_graph, boost::graph_graph_attribute)["label"] = "process " + context.processName();
219-
boost::get_property(m_graph, boost::graph_graph_attribute)["labelloc"] = "top";
222+
// set the graph name property to the process name
223+
boost::get_property(m_graph, boost::graph_name) = context.processName();
224+
boost::get_property(m_graph, boost::graph_graph_attribute)["label"] = "process " + context.processName();
225+
boost::get_property(m_graph, boost::graph_graph_attribute)["labelloc"] = "top";
220226

221-
// create graph vertices associated to all modules in the process
222-
auto size = pathsAndConsumes.largestModuleID() - boost::num_vertices(m_graph) + 1;
223-
for (size_t i = 0; i < size; ++i)
224-
boost::add_vertex(m_graph);
225-
226-
m_initialized = true;
227-
} else {
228-
// create a subgraph to match the subprocess
229-
auto &graph = m_graph.create_subgraph();
230-
231-
// set the subgraph name property to the subprocess name
232-
boost::get_property(graph, boost::graph_name) = "cluster" + context.processName();
233-
boost::get_property(graph, boost::graph_graph_attribute)["label"] = "subprocess " + context.processName();
234-
boost::get_property(graph, boost::graph_graph_attribute)["labelloc"] = "top";
227+
if (pathsAndConsumes.largestModuleID() >= m_moduleIDToGraphIndex.size()) {
228+
m_moduleIDToGraphIndex.resize(pathsAndConsumes.largestModuleID() + 1, kInvalidVertex);
229+
}
235230

236-
// create graph vertices associated to all modules in the subprocess
237-
auto size = pathsAndConsumes.largestModuleID() - boost::num_vertices(m_graph) + 1;
238-
for (size_t i = 0; i < size; ++i)
239-
boost::add_vertex(graph);
231+
auto numberOfSourceGraphVertexes = m_nextGraphIndexToAdd;
232+
for (edm::ModuleDescription const *module : pathsAndConsumes.allModules()) {
233+
m_moduleIDToGraphIndex[module->id()] = m_nextGraphIndexToAdd;
234+
++m_nextGraphIndexToAdd;
235+
}
236+
auto numberOfGraphVertexes = m_nextGraphIndexToAdd;
237+
238+
// Create graph vertices associated to all modules in the process.
239+
// Note that we skip over source vertexes that were already made
240+
// (currently always 1 source but possibly in the future there
241+
// might be more than 1 source)
242+
for (std::size_t i = numberOfSourceGraphVertexes; i < numberOfGraphVertexes; ++i) {
243+
boost::add_vertex(m_graph);
240244
}
241245

242246
// set the vertices properties (use the module id as the global index into the graph)
243247
for (edm::ModuleDescription const *module : pathsAndConsumes.allModules()) {
244-
m_graph.m_graph[module->id()] = {
248+
auto graphIndex = m_moduleIDToGraphIndex[module->id()];
249+
250+
m_graph.m_graph[graphIndex] = {
245251
module->moduleLabel(), module->moduleName(), module->id(), edmModuleTypeEnum(*module), false};
246252

247-
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), module->id());
253+
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), graphIndex);
248254
attributes["label"] = module->moduleLabel();
249255
attributes["tooltip"] = module->moduleName();
250256
attributes["shape"] = shapes[static_cast<std::underlying_type_t<EDMModuleType>>(edmModuleTypeEnum(*module))];
@@ -262,7 +268,8 @@ void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase
262268
for (edm::ModuleDescription const *module : pathsAndConsumes.modulesWhoseProductsAreConsumedBy(consumer->id())) {
263269
edm::LogInfo("DependencyGraph") << "module " << consumer->moduleLabel() << " depends on module "
264270
<< module->moduleLabel();
265-
auto edge_status = boost::add_edge(consumer->id(), module->id(), m_graph);
271+
auto edge_status =
272+
boost::add_edge(m_moduleIDToGraphIndex[consumer->id()], m_moduleIDToGraphIndex[module->id()], m_graph);
266273
// highlight the edge between highlighted nodes
267274
if (highlighted(module->moduleLabel()) and highlighted(consumer->moduleLabel())) {
268275
auto const &edge = edge_status.first;
@@ -284,7 +291,7 @@ void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase
284291

285292
// add to the subgraph the node corresponding to the scheduled modules on the Path
286293
for (edm::ModuleDescription const *module : pathsAndConsumes.modulesOnPath(i)) {
287-
boost::add_vertex(module->id(), graph);
294+
boost::add_vertex(m_moduleIDToGraphIndex[module->id()], graph);
288295
}
289296
}
290297
for (unsigned int i = 0; i < endps.size(); ++i) {
@@ -298,7 +305,7 @@ void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase
298305

299306
// add to the subgraph the node corresponding to the scheduled modules on the EndPath
300307
for (edm::ModuleDescription const *module : pathsAndConsumes.modulesOnEndPath(i)) {
301-
boost::add_vertex(module->id(), graph);
308+
boost::add_vertex(m_moduleIDToGraphIndex[module->id()], graph);
302309
}
303310
}
304311

@@ -319,16 +326,18 @@ void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase
319326
for (unsigned int i = 0; i < paths.size(); ++i) {
320327
previous = nullptr;
321328
for (edm::ModuleDescription const *module : pathsAndConsumes.modulesOnPath(i)) {
322-
m_graph.m_graph[module->id()].scheduled = true;
323-
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), module->id());
329+
auto graphIndex = m_moduleIDToGraphIndex[module->id()];
330+
m_graph.m_graph[graphIndex].scheduled = true;
331+
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), graphIndex);
324332
attributes["fillcolor"] = highlighted(module->moduleLabel()) ? "lightgreen" : "white";
325333
if (previous and m_showPathDependencies) {
334+
auto previousGraphIndex = m_moduleIDToGraphIndex[previous->id()];
326335
edm::LogInfo("DependencyGraph") << "module " << module->moduleLabel() << " follows module "
327336
<< previous->moduleLabel() << " in Path " << paths[i];
328-
auto edge_status = boost::lookup_edge(module->id(), previous->id(), m_graph);
337+
auto edge_status = boost::lookup_edge(graphIndex, previousGraphIndex, m_graph);
329338
bool found = edge_status.second;
330339
if (not found) {
331-
edge_status = boost::add_edge(module->id(), previous->id(), m_graph);
340+
edge_status = boost::add_edge(graphIndex, previousGraphIndex, m_graph);
332341
auto const &edge = edge_status.first;
333342
auto &edgeAttributes = boost::get(boost::get(boost::edge_attribute, m_graph), edge);
334343
edgeAttributes["style"] = "dashed";
@@ -347,7 +356,7 @@ void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase
347356
edm::LogInfo("DependencyGraph") << "module " << paths[i] << " implicitly follows module "
348357
<< previous->moduleLabel() << " in Path " << paths[i];
349358
// add an edge from the PathStatusInserter module to the last module scheduled on the path
350-
auto edge_status = boost::add_edge(j, previous->id(), m_graph);
359+
auto edge_status = boost::add_edge(j, m_moduleIDToGraphIndex[previous->id()], m_graph);
351360
auto const &edge = edge_status.first;
352361
auto &edgeAttributes = boost::get(boost::get(boost::edge_attribute, m_graph), edge);
353362
edgeAttributes["style"] = "dashed";
@@ -375,16 +384,18 @@ void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase
375384
for (unsigned int i = 0; i < endps.size(); ++i) {
376385
previous = nullptr;
377386
for (edm::ModuleDescription const *module : pathsAndConsumes.modulesOnEndPath(i)) {
378-
m_graph.m_graph[module->id()].scheduled = true;
379-
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), module->id());
387+
auto graphIndex = m_moduleIDToGraphIndex[module->id()];
388+
m_graph.m_graph[graphIndex].scheduled = true;
389+
auto &attributes = boost::get(boost::get(boost::vertex_attribute, m_graph), graphIndex);
380390
attributes["fillcolor"] = highlighted(module->moduleLabel()) ? "lightgreen" : "white";
381391
if (previous and m_showPathDependencies) {
392+
auto previousGraphIndex = m_moduleIDToGraphIndex[previous->id()];
382393
edm::LogInfo("DependencyGraph") << "module " << module->moduleLabel() << " follows module "
383394
<< previous->moduleLabel() << " in EndPath " << i;
384-
auto edge_status = boost::lookup_edge(module->id(), previous->id(), m_graph);
395+
auto edge_status = boost::lookup_edge(graphIndex, previousGraphIndex, m_graph);
385396
bool found = edge_status.second;
386397
if (not found) {
387-
edge_status = boost::add_edge(module->id(), previous->id(), m_graph);
398+
edge_status = boost::add_edge(graphIndex, previousGraphIndex, m_graph);
388399
auto const &edge = edge_status.first;
389400
auto &edgeAttributes = boost::get(boost::get(boost::edge_attribute, m_graph), edge);
390401
edgeAttributes["style"] = "dashed";
@@ -397,26 +408,12 @@ void DependencyGraph::lookupInitializationComplete(PathsAndConsumesOfModulesBase
397408
}
398409
}
399410

400-
// remove the nodes corresponding to the modules that have been removed from the process
401-
for (int i = boost::num_vertices(m_graph) - 1; i > 1; --i) {
402-
if (m_graph.m_graph[i].label.empty())
403-
boost::remove_vertex(i, m_graph.m_graph);
404-
}
405-
406411
// draw the dependency graph
407412
std::ofstream out(m_filename);
408413
boost::write_graphviz(out, m_graph);
409414
out.close();
410415
}
411416

412-
namespace edm {
413-
namespace service {
414-
415-
inline bool isProcessWideService(DependencyGraph const *) { return true; }
416-
417-
} // namespace service
418-
} // namespace edm
419-
420417
// define as a framework servie
421418
#include "FWCore/ServiceRegistry/interface/ServiceMaker.h"
422419
DEFINE_FWK_SERVICE(DependencyGraph);

0 commit comments

Comments
 (0)