11 #include <unordered_set>
29 unsigned int hint = 0;
61 <<
"PathsAndConsumesOfModules::removeModules() is trying to remove a module with label "
73 if (
found != modules.end()) {
75 for (
auto iBranchType = 0U; iBranchType !=
NumBranchTypes; ++iBranchType) {
82 if (idToIndex.second >= iModule) {
92 unsigned int moduleID)
const {
97 unsigned int dummy = 0;
98 auto target = std::make_pair(moduleID, dummy);
99 std::vector<std::pair<unsigned int, unsigned int>>::const_iterator iter =
103 <<
"PathsAndConsumesOfModules::moduleDescription: Unknown moduleID " << moduleID <<
"\n";
113 unsigned int endPathIndex)
const {
118 unsigned int moduleID,
BranchType branchType)
const {
133 unsigned int dummy = 0;
134 auto target = std::make_pair(moduleID, dummy);
135 std::vector<std::pair<unsigned int, unsigned int>>::const_iterator iter =
139 <<
"PathsAndConsumesOfModules::moduleIndex: Unknown moduleID " << moduleID <<
"\n";
149 std::unordered_set<unsigned int>& consumedModules) {
152 if (consumedModules.find(module->
id()) != consumedModules.end()) {
155 consumedModules.insert(module->
id());
159 findAllConsumedModules(iPnC,
c, consumedModules);
168 const std::string kTriggerResults(
"TriggerResults");
170 std::vector<std::string> pathNames = iPnC.
paths();
171 const unsigned int kFirstEndPathIndex = pathNames.size();
172 pathNames.insert(pathNames.end(), iPnC.
endPaths().begin(), iPnC.
endPaths().end());
180 std::vector<ModuleDescription const*> consumerModules;
181 for (
unsigned int pathIndex = 0; pathIndex != pathNames.size(); ++pathIndex) {
182 std::vector<ModuleDescription const*>
const* moduleDescriptions;
183 if (pathIndex < kFirstEndPathIndex) {
186 moduleDescriptions = &(iPnC.
modulesOnEndPath(pathIndex - kFirstEndPathIndex));
188 std::copy(moduleDescriptions->begin(), moduleDescriptions->end(), std::back_inserter(consumerModules));
200 }
else if (std::binary_search(consumedByChildren.begin(),
201 consumedByChildren.end(),
203 std::binary_search(consumedByChildren.begin(),
204 consumedByChildren.end(),
212 std::unordered_set<unsigned int> consumedModules;
214 findAllConsumedModules(iPnC,
description, consumedModules);
219 std::vector<ModuleDescription const*> unusedModules;
220 std::copy_if(allModules.begin(),
222 std::back_inserter(unusedModules),
224 return consumedModules.find(
description->id()) == consumedModules.end();
226 return unusedModules;
271 struct ModuleStatus {
272 std::vector<unsigned int> dependsOn_;
273 std::vector<unsigned int> pathsOn_;
274 unsigned long long lastSearch = 0;
275 bool onPath_ =
false;
276 bool wasRun_ =
false;
280 std::vector<unsigned int> modulesOnPath_;
281 unsigned long int activeModuleSlot_ = 0;
282 unsigned long int nModules_ = 0;
283 unsigned int index_ = 0;
284 bool endPath_ =
false;
287 class CircularDependencyException {};
289 bool checkIfCanRun(
unsigned long long searchIndex,
290 unsigned int iModuleToCheckID,
291 std::vector<ModuleStatus>& iModules,
292 std::vector<unsigned int>& stackTrace) {
293 auto&
status = iModules[iModuleToCheckID];
298 if (
status.lastSearch == searchIndex) {
302 auto itFound =
std::find(stackTrace.begin(), stackTrace.end(), iModuleToCheckID);
303 if (itFound != stackTrace.end()) {
304 stackTrace.push_back(iModuleToCheckID);
305 throw CircularDependencyException();
310 stackTrace.push_back(iModuleToCheckID);
311 status.lastSearch = searchIndex;
313 bool allDependenciesRan =
true;
315 auto& dep = iModules[
index];
317 if (not dep.wasRun_) {
318 allDependenciesRan =
false;
320 }
else if (not checkIfCanRun(searchIndex,
index, iModules, stackTrace)) {
321 allDependenciesRan =
false;
324 if (allDependenciesRan) {
327 stackTrace.pop_back();
329 return allDependenciesRan;
336 std::unordered_map<unsigned int, std::string> moduleIndexToNames;
338 std::unordered_map<std::string, unsigned int> pathStatusInserterModuleLabelToModuleID;
341 const std::string kTriggerResults(
"TriggerResults");
342 const std::string kPathStatusInserter(
"PathStatusInserter");
343 const std::string kEndPathStatusInserter(
"EndPathStatusInserter");
345 ModuleStatus triggerResultsStatus;
346 unsigned int largestIndex = 0;
349 if (kTriggerResults ==
description->moduleLabel()) {
355 if (
description->moduleName() == kPathStatusInserter) {
356 triggerResultsStatus.dependsOn_.push_back(
description->id());
358 if (
description->moduleName() == kPathStatusInserter ||
description->moduleName() == kEndPathStatusInserter) {
363 std::vector<ModuleStatus> statusOfModules(largestIndex + 1);
364 for (
auto const& nameID : pathStatusInserterModuleLabelToModuleID) {
365 statusOfModules[nameID.second].onPath_ =
true;
366 unsigned int pathIndex;
369 if (itFound !=
paths.end()) {
370 pathIndex = itFound -
paths.begin();
372 auto const& endPaths = iPnC.
endPaths();
373 itFound =
std::find(endPaths.begin(), endPaths.end(), nameID.first);
374 assert(itFound != endPaths.end());
375 pathIndex = itFound - endPaths.begin() + iPnC.
paths().size();
377 statusOfModules[nameID.second].pathsOn_.push_back(pathIndex);
379 if (kTriggerResultsIndex != kInvalidIndex) {
380 statusOfModules[kTriggerResultsIndex] =
std::move(triggerResultsStatus);
383 std::vector<PathStatus> statusOfPaths(iPnC.
paths().size() + iPnC.
endPaths().size());
386 if (statusOfPaths.empty()) {
391 auto nPaths = iPnC.
paths().size();
392 for (
unsigned int p = 0;
p < nPaths; ++
p) {
393 auto&
status = statusOfPaths[
p];
396 std::unordered_set<unsigned int> uniqueModules;
398 if (uniqueModules.insert(
mod->id()).
second) {
399 status.modulesOnPath_.push_back(
mod->id());
400 statusOfModules[
mod->id()].onPath_ =
true;
401 statusOfModules[
mod->id()].pathsOn_.push_back(
p);
404 status.nModules_ = uniqueModules.size() + 1;
407 auto found = pathStatusInserterModuleLabelToModuleID.find(iPnC.
paths()[
p]);
408 assert(
found != pathStatusInserterModuleLabelToModuleID.end());
414 auto nPaths = iPnC.
endPaths().size();
415 for (
unsigned int p = 0;
p < nPaths; ++
p) {
420 std::unordered_set<unsigned int> uniqueModules;
422 if (uniqueModules.insert(
mod->id()).
second) {
423 status.modulesOnPath_.push_back(
mod->id());
424 statusOfModules[
mod->id()].onPath_ =
true;
425 statusOfModules[
mod->id()].pathsOn_.push_back(
p +
offset);
428 status.nModules_ = uniqueModules.size() + 1;
431 auto found = pathStatusInserterModuleLabelToModuleID.find(iPnC.
endPaths()[
p]);
432 assert(
found != pathStatusInserterModuleLabelToModuleID.end());
438 unsigned int const moduleIndex =
description->id();
440 auto&
deps = statusOfModules[moduleIndex];
441 deps.dependsOn_.reserve(dependentModules.size());
442 for (
auto const& depDescription : dependentModules) {
443 if (iPrintDependencies) {
445 <<
"ModuleDependency '" <<
description->moduleLabel() <<
"' depends on data products from module '"
446 << depDescription->moduleLabel() <<
"'";
448 deps.dependsOn_.push_back(depDescription->id());
452 unsigned int nPathsFinished = 0;
455 std::vector<unsigned int> stackTrace;
456 bool madeForwardProgress =
true;
460 unsigned long long searchIndex = 0;
461 while (madeForwardProgress and nPathsFinished != statusOfPaths.size()) {
462 madeForwardProgress =
false;
463 for (
auto&
p : statusOfPaths) {
465 if (
p.activeModuleSlot_ ==
p.nModules_) {
469 bool didRun = checkIfCanRun(searchIndex,
p.modulesOnPath_[
p.activeModuleSlot_], statusOfModules, stackTrace);
471 madeForwardProgress =
true;
472 ++
p.activeModuleSlot_;
473 if (
p.activeModuleSlot_ ==
p.nModules_) {
479 }
catch (CircularDependencyException
const&) {
481 std::ostringstream oStr;
483 unsigned int lastIndex = stackTrace.front();
484 bool firstSkipped =
false;
485 for (
auto id : stackTrace) {
487 oStr <<
" module '" << moduleIndexToNames[
lastIndex] <<
"' depends on " << moduleIndexToNames[
id] <<
"\n";
494 <<
"Circular module dependency found in configuration\n"
502 return iPnC.
paths()[iP.index_];
506 if (not madeForwardProgress) {
507 std::ostringstream oStr;
509 unsigned int presentPath;
510 for (
auto itP = statusOfPaths.begin(); itP != statusOfPaths.end(); ++itP) {
511 auto const&
p = *itP;
512 if (
p.activeModuleSlot_ ==
p.nModules_) {
516 modIndex =
p.modulesOnPath_[
p.activeModuleSlot_];
517 presentPath = itP - statusOfPaths.begin();
523 struct ProgressInfo {
524 ProgressInfo(
unsigned int iMod,
unsigned int iPath,
bool iPreceeds =
false)
525 : moduleIndex_(iMod), pathIndex_(iPath), preceeds_(iPreceeds) {}
527 ProgressInfo(
unsigned int iMod) : moduleIndex_(iMod), pathIndex_{}, preceeds_(
false) {}
530 std::optional<unsigned int> pathIndex_;
533 bool operator==(ProgressInfo
const& iOther)
const {
534 return moduleIndex_ == iOther.moduleIndex_ and pathIndex_ == iOther.pathIndex_;
538 std::vector<ProgressInfo> progressTrace;
539 progressTrace.emplace_back(modIndex, presentPath);
552 bool foundUnrunModule;
555 foundUnrunModule =
false;
556 for (
auto depMod : statusOfModules[modIndex].dependsOn_) {
557 auto const& depStatus = statusOfModules[depMod];
558 if (not depStatus.wasRun_ and depStatus.onPath_) {
559 foundUnrunModule =
true;
561 bool lastOnPath =
false;
562 unsigned int foundPath;
563 for (
auto pathOn : depStatus.pathsOn_) {
564 auto const& depPaths = statusOfPaths[pathOn];
565 if (depPaths.modulesOnPath_[depPaths.activeModuleSlot_] == depMod) {
573 progressTrace.emplace_back(modIndex, foundPath);
576 progressTrace.emplace_back(depMod, depStatus.pathsOn_[0]);
577 auto const& depPath = statusOfPaths[depStatus.pathsOn_[0]];
578 modIndex = depPath.modulesOnPath_[depPath.activeModuleSlot_];
579 progressTrace.emplace_back(modIndex, depStatus.pathsOn_[0],
true);
584 if (not foundUnrunModule) {
586 for (
auto depMod : statusOfModules[modIndex].dependsOn_) {
587 auto const& depStatus = statusOfModules[depMod];
588 if (not depStatus.wasRun_ and not depStatus.onPath_) {
589 foundUnrunModule =
true;
590 progressTrace.emplace_back(depMod);
596 }
while (foundUnrunModule and (0 ==
std::count(progressTrace.begin(),
597 progressTrace.begin() + progressTrace.size() - 1,
598 progressTrace.back())));
600 auto printTrace = [&](
auto& oStr,
auto itBegin,
auto itEnd) {
601 for (
auto itTrace = itBegin; itTrace != itEnd; ++itTrace) {
602 if (itTrace != itBegin) {
603 if (itTrace->preceeds_) {
604 oStr <<
" and follows module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"' on the path\n";
606 oStr <<
" and depends on module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"'\n";
609 if (itTrace + 1 != itEnd) {
610 if (itTrace->pathIndex_) {
611 oStr <<
" module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"' is on path '"
612 <<
pathName(statusOfPaths[*itTrace->pathIndex_]) <<
"'";
614 oStr <<
" module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"' is in a task";
620 if (not foundUnrunModule) {
623 oStr <<
"Algorithm Error, unable to find problem. Contact framework group.\n Traced problem this far\n";
624 printTrace(oStr, progressTrace.begin(), progressTrace.end());
627 oStr,
std::find(progressTrace.begin(), progressTrace.end(), progressTrace.back()), progressTrace.end());
632 <<
"The Path/EndPath configuration could cause the job to deadlock\n"
640 for (
auto&
p : statusOfPaths) {
641 for (
unsigned long int i = 0;
p.nModules_ > 0 and
i <
p.nModules_ - 1; ++
i) {
642 auto moduleID =
p.modulesOnPath_[
i];
643 if (not statusOfModules[moduleID].dependsOn_.empty()) {
644 for (
unsigned long int j =
i + 1;
j <
p.nModules_; ++
j) {
645 auto testModuleID =
p.modulesOnPath_[
j];
646 for (
auto depModuleID : statusOfModules[moduleID].dependsOn_) {
647 if (depModuleID == testModuleID) {
649 <<
"Dependent module later on Path\n"
650 <<
" module '" << moduleIndexToNames[moduleID] <<
"' depends on '"
651 << moduleIndexToNames[depModuleID] <<
"' which is later on path " <<
pathName(
p);
661 unsigned int modIndex = 0;
662 for (
auto&
mod : statusOfModules) {
663 for (
auto& depIndex :
mod.dependsOn_) {
664 std::size_t
count = 0;
665 std::size_t nonEndPaths = 0;
666 for (
auto modPathID :
mod.pathsOn_) {
667 if (statusOfPaths[modPathID].endPath_) {
671 for (
auto depPathID : statusOfModules[depIndex].pathsOn_) {
672 if (depPathID == modPathID) {
678 if (count != 0 and count != nonEndPaths) {
679 std::ostringstream onStr;
680 std::ostringstream missingStr;
682 for (
auto modPathID :
mod.pathsOn_) {
683 if (statusOfPaths[modPathID].endPath_) {
687 for (
auto depPathID : statusOfModules[depIndex].pathsOn_) {
688 if (depPathID == modPathID) {
692 auto&
s = statusOfPaths[modPathID];
700 <<
"Paths are non consistent\n"
701 <<
" module '" << moduleIndexToNames[modIndex] <<
"' depends on '" << moduleIndexToNames[depIndex]
702 <<
"' which appears on paths\n " << onStr.str() <<
"\nbut is missing from\n " << missingStr.str();
constexpr bool operator==(ELseverityLevel const &e1, ELseverityLevel const &e2) noexcept
const edm::EventSetup & c
AllWorkers const & allWorkers() const
returns the collection of pointers to workers
uint16_t *__restrict__ id
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
unsigned int doLargestModuleID() const override
std::array< std::vector< std::vector< ModuleDescription const * > >, NumBranchTypes > modulesWhoseProductsAreConsumedBy_
std::vector< ModuleDescription const * > nonConsumedUnscheduledModules(edm::PathsAndConsumesOfModulesBase const &iPnC, std::vector< ModuleProcessName > &consumedByChildren)
void fillModuleAndConsumesInfo(std::vector< ModuleDescription const * > &allModuleDescriptions, std::vector< std::pair< unsigned int, unsigned int >> &moduleIDToIndex, std::array< std::vector< std::vector< ModuleDescription const * >>, NumBranchTypes > &modulesWhoseProductsAreConsumedBy, std::vector< std::vector< ModuleProcessName >> &modulesInPreviousProcessesWhoseProductsAreConsumedBy, ProductRegistry const &preg) const
std::vector< ModuleDescription const * > const & modulesOnEndPath(unsigned int endPathIndex) const
std::vector< ModuleDescription const * > const & modulesOnPath(unsigned int pathIndex) const
unsigned int moduleIndex(unsigned int moduleID) const
void moduleDescriptionsInEndPath(std::string const &iEndPathLabel, std::vector< ModuleDescription const * > &descriptions, unsigned int hint) const
std::vector< ModuleDescription const * > const & doModulesOnPath(unsigned int pathIndex) const override
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
std::vector< std::pair< unsigned int, unsigned int > > moduleIDToIndex_
std::vector< ModuleDescription const * > allModuleDescriptions_
std::vector< std::string > paths_
std::vector< ModuleDescription const * > const & allModules() const
std::vector< std::string > const & endPaths() const
U second(std::pair< T, U > const &p)
void initialize(Schedule const *, std::shared_ptr< ProductRegistry const >)
std::vector< std::vector< ModuleDescription const * > > modulesOnPaths_
void triggerPaths(std::vector< std::string > &oLabelsToFill) const
std::vector< std::vector< ModuleProcessName > > modulesInPreviousProcessesWhoseProductsAreConsumedBy_
virtual std::vector< ConsumesInfo > consumesInfo() const =0
std::vector< ModuleProcessName > const & modulesInPreviousProcessesWhoseProductsAreConsumedBy(unsigned int moduleID) const
static std::atomic< unsigned int > lastIndex
std::vector< std::string > endPaths_
void checkForModuleDependencyCorrectness(edm::PathsAndConsumesOfModulesBase const &iPnC, bool iPrintDependencies)
std::vector< ModuleDescription const * > const & modulesWhoseProductsAreConsumedBy(unsigned int moduleID, BranchType branchType=InEvent) const
std::shared_ptr< ProductRegistry const > preg_
ModuleDescription const * doModuleDescription(unsigned int moduleID) const override
void removeModules(std::vector< ModuleDescription const * > const &modules)
~PathsAndConsumesOfModules() override
Schedule const * schedule_
std::vector< ModuleDescription const * > const & doModulesWhoseProductsAreConsumedBy(unsigned int moduleID, BranchType branchType) const override
__host__ __device__ constexpr RandomIt lower_bound(RandomIt first, RandomIt last, const T &value, Compare comp={})
PathsAndConsumesOfModules()
std::vector< std::string > const & paths() const
std::vector< ConsumesInfo > doConsumesInfo(unsigned int moduleID) const override
Log< level::System, true > LogAbsolute
std::vector< ModuleDescription const * > const & doModulesOnEndPath(unsigned int endPathIndex) const override
std::vector< std::vector< ModuleDescription const * > > modulesOnEndPaths_
T mod(const T &a, const T &b)
constexpr auto kInvalidIndex
void endPaths(std::vector< std::string > &oLabelsToFill) const
adds to oLabelsToFill the labels for all end paths in the process
void moduleDescriptionsInPath(std::string const &iPathLabel, std::vector< ModuleDescription const * > &descriptions, unsigned int hint) const