File indexing completed on 2021-02-14 23:30:11
0001
0002
0003
0004
0005 #include <cassert>
0006 #include <iostream>
0007 #include <string>
0008 #include <type_traits>
0009 #include <vector>
0010
0011
0012 #pragma GCC diagnostic push
0013 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
0014 #include <boost/graph/depth_first_search.hpp>
0015 #pragma GCC diagnostic pop
0016
0017 #include "DataFormats/Provenance/interface/ModuleDescription.h"
0018 #include "FWCore/Framework/interface/TriggerNamesService.h"
0019 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0020 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0021 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0022 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0023 #include "FWCore/ParameterSet/interface/Registry.h"
0024 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0025 #include "FWCore/ServiceRegistry/interface/ConsumesInfo.h"
0026 #include "FWCore/ServiceRegistry/interface/PathsAndConsumesOfModulesBase.h"
0027 #include "FWCore/ServiceRegistry/interface/ProcessContext.h"
0028 #include "FWCore/ServiceRegistry/interface/Service.h"
0029 #include "FWCore/Utilities/interface/EDMException.h"
0030 #include "HLTrigger/Timer/interface/ProcessCallGraph.h"
0031
0032 ProcessCallGraph::ProcessCallGraph() = default;
0033
0034
0035 template <typename I>
0036 struct iterator_pair_as_a_range : std::pair<I, I> {
0037 public:
0038 using std::pair<I, I>::pair;
0039
0040 I begin() { return this->first; }
0041 I end() { return this->second; }
0042 };
0043
0044 template <typename I>
0045 iterator_pair_as_a_range<I> make_range(std::pair<I, I> p) {
0046 return iterator_pair_as_a_range<I>(p);
0047 }
0048
0049
0050
0051 void ProcessCallGraph::preSourceConstruction(edm::ModuleDescription const& module) {
0052
0053 source_ = module.id();
0054
0055
0056 boost::add_vertex(graph_);
0057 graph_.m_graph[module.id()] = {module, edm::EDMModuleType::kSource, true};
0058 }
0059
0060
0061
0062
0063
0064 void ProcessCallGraph::preBeginJob(edm::PathsAndConsumesOfModulesBase const& pathsAndConsumes,
0065 edm::ProcessContext const& context) {
0066 unsigned int pid = registerProcess(context);
0067
0068
0069 GraphType& graph = context.isSubProcess() ? graph_.create_subgraph() : graph_.root();
0070
0071
0072 boost::get_property(graph, boost::graph_name) = context.processName();
0073
0074
0075 unsigned int size = pathsAndConsumes.largestModuleID() - boost::num_vertices(graph) + 1;
0076 for (size_t i = 0; i < size; ++i)
0077 boost::add_vertex(graph);
0078
0079
0080 std::vector<unsigned int> modules;
0081 modules.reserve(size);
0082 for (edm::ModuleDescription const* module : pathsAndConsumes.allModules()) {
0083 modules.push_back(module->id());
0084 graph_.m_graph[module->id()] = {*module, edmModuleTypeEnum(*module), false};
0085 }
0086
0087
0088 for (edm::ModuleDescription const* consumer : pathsAndConsumes.allModules()) {
0089 for (edm::ModuleDescription const* module : pathsAndConsumes.modulesWhoseProductsAreConsumedBy(consumer->id())) {
0090
0091 boost::add_edge(consumer->id(), module->id(), graph_);
0092 }
0093 }
0094
0095
0096 edm::service::TriggerNamesService const& tns = *edm::Service<edm::service::TriggerNamesService>();
0097
0098
0099 size = pathsAndConsumes.paths().size();
0100 assert(tns.getTrigPaths().size() == size);
0101 std::vector<PathType> paths;
0102 paths.reserve(size);
0103 for (unsigned int i = 0; i < size; ++i) {
0104 std::vector<unsigned int> modules;
0105 for (edm::ModuleDescription const* module : pathsAndConsumes.modulesOnPath(i)) {
0106 modules.push_back(module->id());
0107
0108 graph_.m_graph[module->id()].scheduled_ = true;
0109 }
0110 auto deps = dependencies(modules);
0111 paths.emplace_back(tns.getTrigPath(i), modules, deps.first, deps.second);
0112 }
0113 size = pathsAndConsumes.endPaths().size();
0114 std::vector<PathType> endPaths;
0115 endPaths.reserve(size);
0116 for (unsigned int i = 0; i < size; ++i) {
0117 std::vector<unsigned int> modules;
0118 for (edm::ModuleDescription const* module : pathsAndConsumes.modulesOnEndPath(i)) {
0119 modules.push_back(module->id());
0120
0121 graph_.m_graph[module->id()].scheduled_ = true;
0122 }
0123 auto deps = dependencies(modules);
0124 endPaths.emplace_back(tns.getEndPath(i), modules, deps.first, deps.second);
0125 }
0126
0127
0128 process_description_.emplace_back(context.processName(), graph, modules, paths, endPaths);
0129 assert(process_description_.size() == pid + 1);
0130
0131
0132 if (context.isSubProcess()) {
0133 unsigned int parent_pid = processId(context.parentProcessContext());
0134 process_description_[parent_pid].subprocesses_.push_back(pid);
0135 }
0136 }
0137
0138
0139 unsigned int ProcessCallGraph::size() const { return boost::num_vertices(graph_); }
0140
0141
0142 edm::ModuleDescription const& ProcessCallGraph::source() const { return graph_.m_graph[source_].module_; }
0143
0144
0145 edm::ModuleDescription const& ProcessCallGraph::module(unsigned int module) const {
0146 return graph_.m_graph[module].module_;
0147 }
0148
0149
0150 ProcessCallGraph::NodeType const& ProcessCallGraph::operator[](unsigned int module) const {
0151 return graph_.m_graph[module];
0152 }
0153
0154
0155 std::vector<unsigned int> ProcessCallGraph::depends(unsigned int module) const {
0156 std::vector<unsigned int> colors(boost::num_vertices(graph_));
0157 auto colormap = boost::make_container_vertex_map(colors);
0158
0159
0160 boost::default_dfs_visitor visitor;
0161 boost::depth_first_visit(graph_, module, visitor, colormap);
0162
0163
0164
0165 unsigned int size = 0;
0166 for (unsigned int color : colors)
0167 if (boost::black_color == color)
0168 ++size;
0169 std::vector<unsigned int> dependencies(size);
0170 unsigned j = 0;
0171 for (unsigned int i = 0; i < colors.size(); ++i)
0172 if (boost::black_color == colors[i])
0173 dependencies[j++] = i;
0174 assert(size == j);
0175
0176 return dependencies;
0177 }
0178
0179
0180
0181
0182
0183
0184 std::pair<std::vector<unsigned int>, std::vector<unsigned int>> ProcessCallGraph::dependencies(
0185 std::vector<unsigned int> const& path) {
0186 std::vector<unsigned int> colors(boost::num_vertices(graph_));
0187 auto colormap = boost::make_container_vertex_map(colors);
0188
0189
0190 boost::default_dfs_visitor visitor;
0191 for (unsigned int module : path)
0192 boost::depth_first_visit(graph_, module, visitor, colormap);
0193
0194 unsigned int size = 0;
0195 for (unsigned int color : colors)
0196 if (color == 0)
0197 ++size;
0198
0199
0200 std::vector<unsigned int> dependencies(size);
0201 dependencies.resize(0);
0202 std::vector<unsigned int> indices(path.size());
0203 indices.resize(0);
0204
0205
0206 for (unsigned int& color : colors)
0207 color = 0;
0208
0209
0210 struct record_vertices : boost::default_dfs_visitor {
0211 record_vertices(std::vector<unsigned int>& vertices) : vertices_(vertices) {}
0212
0213 void discover_vertex(unsigned int vertex, GraphType const& graph) { vertices_.push_back(vertex); }
0214
0215 std::vector<unsigned int>& vertices_;
0216 };
0217 record_vertices recorder(dependencies);
0218
0219 for (unsigned int module : path) {
0220
0221 if (colors[module] != boost::black_color)
0222 boost::depth_first_visit(graph_, module, recorder, colormap);
0223 indices.push_back(dependencies.size());
0224 }
0225
0226 return std::make_pair(dependencies, indices);
0227 }
0228
0229
0230
0231 unsigned int ProcessCallGraph::registerProcess(edm::ProcessContext const& context) {
0232 static unsigned int s_id = 0;
0233
0234
0235 if (context.isSubProcess() and process_id_.find(context.parentProcessContext().processName()) == process_id_.end()) {
0236 throw edm::Exception(edm::errors::LogicError)
0237 << "ProcessCallGraph::preBeginJob(): called for subprocess \"" << context.processName() << "\""
0238 << " before being called for its parent process \"" << context.parentProcessContext().processName() << "\"";
0239 }
0240
0241
0242 auto id = process_id_.find(context.processName());
0243 if (id != process_id_.end()) {
0244 throw edm::Exception(edm::errors::LogicError)
0245 << "ProcessCallGraph::preBeginJob(): called twice for the same "
0246 << (context.isSubProcess() ? "subprocess" : "process") << " " << context.processName();
0247 }
0248
0249 std::tie(id, std::ignore) = process_id_.insert(std::make_pair(context.processName(), s_id++));
0250 return id->second;
0251 }
0252
0253
0254
0255 unsigned int ProcessCallGraph::processId(edm::ProcessContext const& context) const {
0256 auto id = process_id_.find(context.processName());
0257 if (id == process_id_.end())
0258 throw edm::Exception(edm::errors::LogicError)
0259 << "ProcessCallGraph::processId(): unexpected " << (context.isSubProcess() ? "subprocess" : "process") << " "
0260 << context.processName();
0261 return id->second;
0262 }
0263
0264
0265
0266 unsigned int ProcessCallGraph::processId(std::string const& processName) const {
0267 auto id = process_id_.find(processName);
0268 if (id == process_id_.end())
0269 throw edm::Exception(edm::errors::LogicError)
0270 << "ProcessCallGraph::processId(): unexpected (sub)process " << processName;
0271 return id->second;
0272 }
0273
0274
0275 std::vector<ProcessCallGraph::ProcessType> const& ProcessCallGraph::processes() const { return process_description_; }
0276
0277
0278 ProcessCallGraph::ProcessType const& ProcessCallGraph::processDescription(unsigned int pid) const {
0279 return process_description_.at(pid);
0280 }
0281
0282
0283 ProcessCallGraph::ProcessType const& ProcessCallGraph::processDescription(edm::ProcessContext const& context) const {
0284 unsigned int pid = processId(context);
0285 return process_description_[pid];
0286 }
0287
0288
0289 ProcessCallGraph::ProcessType const& ProcessCallGraph::processDescription(std::string const& processName) const {
0290 unsigned int pid = processId(processName);
0291 return process_description_[pid];
0292 }