11 #include <unordered_set> 29 unsigned int hint = 0;
61 <<
"PathsAndConsumesOfModules::removeModules() is trying to remove a module with label " 75 for (
auto iBranchType = 0
U; iBranchType !=
NumBranchTypes; ++iBranchType) {
82 if (idToIndex.second >= iModule) {
92 unsigned int moduleID)
const {
97 unsigned int dummy = 0;
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;
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;
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;
332 void findAllDependenciesForModule(
unsigned int iModID,
333 std::vector<ModuleStatus>
const& iStatus,
334 std::vector<std::unordered_set<unsigned int>>& oDependencies) {
335 auto const&
dependsOn = iStatus[iModID].dependsOn_;
336 if (
dependsOn.empty()
or !oDependencies[iModID].empty()) {
341 findAllDependenciesForModule(dep, iStatus, oDependencies);
342 oDependencies[iModID].merge(oDependencies[dep]);
345 std::vector<std::unordered_set<unsigned int>> findAllDependenciesForModules(
346 std::vector<ModuleStatus>
const& iStatus) {
347 std::vector<std::unordered_set<unsigned int>>
ret(iStatus.size());
348 for (
unsigned int id = 0;
id < iStatus.size(); ++
id) {
349 findAllDependenciesForModule(
id, iStatus,
ret);
358 std::unordered_map<unsigned int, std::string> moduleIndexToNames;
360 std::unordered_map<std::string, unsigned int> pathStatusInserterModuleLabelToModuleID;
363 const std::string kTriggerResults(
"TriggerResults");
364 const std::string kPathStatusInserter(
"PathStatusInserter");
365 const std::string kEndPathStatusInserter(
"EndPathStatusInserter");
367 ModuleStatus triggerResultsStatus;
368 unsigned int largestIndex = 0;
371 if (kTriggerResults ==
description->moduleLabel()) {
377 if (
description->moduleName() == kPathStatusInserter) {
378 triggerResultsStatus.dependsOn_.push_back(
description->id());
380 if (
description->moduleName() == kPathStatusInserter ||
description->moduleName() == kEndPathStatusInserter) {
385 std::vector<ModuleStatus> statusOfModules(largestIndex + 1);
386 for (
auto const& nameID : pathStatusInserterModuleLabelToModuleID) {
387 statusOfModules[nameID.second].onPath_ =
true;
388 unsigned int pathIndex;
391 if (itFound !=
paths.end()) {
392 pathIndex = itFound -
paths.begin();
394 auto const& endPaths = iPnC.
endPaths();
395 itFound =
std::find(endPaths.begin(), endPaths.end(), nameID.first);
396 assert(itFound != endPaths.end());
397 pathIndex = itFound - endPaths.begin() + iPnC.
paths().size();
399 statusOfModules[nameID.second].pathsOn_.push_back(pathIndex);
402 statusOfModules[kTriggerResultsIndex] =
std::move(triggerResultsStatus);
405 std::vector<PathStatus> statusOfPaths(iPnC.
paths().size() + iPnC.
endPaths().size());
408 if (statusOfPaths.empty()) {
413 auto nPaths = iPnC.
paths().size();
414 for (
unsigned int p = 0;
p < nPaths; ++
p) {
415 auto&
status = statusOfPaths[
p];
418 std::unordered_set<unsigned int> uniqueModules;
420 if (uniqueModules.insert(
mod->id()).
second) {
421 status.modulesOnPath_.push_back(
mod->id());
422 statusOfModules[
mod->id()].onPath_ =
true;
423 statusOfModules[
mod->id()].pathsOn_.push_back(
p);
426 status.nModules_ = uniqueModules.size() + 1;
429 auto found = pathStatusInserterModuleLabelToModuleID.find(iPnC.
paths()[
p]);
430 assert(
found != pathStatusInserterModuleLabelToModuleID.end());
436 auto nPaths = iPnC.
endPaths().size();
437 for (
unsigned int p = 0;
p < nPaths; ++
p) {
442 std::unordered_set<unsigned int> uniqueModules;
444 if (uniqueModules.insert(
mod->id()).
second) {
445 status.modulesOnPath_.push_back(
mod->id());
446 statusOfModules[
mod->id()].onPath_ =
true;
447 statusOfModules[
mod->id()].pathsOn_.push_back(
p +
offset);
450 status.nModules_ = uniqueModules.size();
453 auto found = pathStatusInserterModuleLabelToModuleID.find(iPnC.
endPaths()[
p]);
454 if (
found != pathStatusInserterModuleLabelToModuleID.end()) {
462 unsigned int const moduleIndex =
description->id();
464 auto&
deps = statusOfModules[moduleIndex];
465 deps.dependsOn_.reserve(dependentModules.size());
466 for (
auto const& depDescription : dependentModules) {
467 if (iPrintDependencies) {
469 <<
"ModuleDependency '" <<
description->moduleLabel() <<
"' depends on data products from module '" 470 << depDescription->moduleLabel() <<
"'";
472 deps.dependsOn_.push_back(depDescription->id());
476 unsigned int nPathsFinished = 0;
477 for (
auto const&
status : statusOfPaths) {
478 if (
status.nModules_ == 0) {
484 std::vector<unsigned int> stackTrace;
485 bool madeForwardProgress =
true;
489 unsigned long long searchIndex = 0;
490 while (madeForwardProgress and nPathsFinished != statusOfPaths.size()) {
491 madeForwardProgress =
false;
492 for (
auto&
p : statusOfPaths) {
494 if (
p.activeModuleSlot_ ==
p.nModules_) {
498 bool didRun = checkIfCanRun(searchIndex,
p.modulesOnPath_[
p.activeModuleSlot_], statusOfModules, stackTrace);
500 madeForwardProgress =
true;
501 ++
p.activeModuleSlot_;
502 if (
p.activeModuleSlot_ ==
p.nModules_) {
508 }
catch (CircularDependencyException
const&) {
510 std::ostringstream oStr;
512 unsigned int lastIndex = stackTrace.front();
513 bool firstSkipped =
false;
514 for (
auto id : stackTrace) {
516 oStr <<
" module '" << moduleIndexToNames[
lastIndex] <<
"' depends on " << moduleIndexToNames[
id] <<
"\n";
523 <<
"Circular module dependency found in configuration\n" 531 return iPnC.
paths()[iP.index_];
535 if (not madeForwardProgress) {
536 std::ostringstream oStr;
538 unsigned int presentPath;
539 for (
auto itP = statusOfPaths.begin(); itP != statusOfPaths.end(); ++itP) {
540 auto const&
p = *itP;
541 if (
p.activeModuleSlot_ ==
p.nModules_) {
545 modIndex =
p.modulesOnPath_[
p.activeModuleSlot_];
546 presentPath = itP - statusOfPaths.begin();
552 struct ProgressInfo {
553 ProgressInfo(
unsigned int iMod,
unsigned int iPath,
bool iPreceeds =
false)
554 : moduleIndex_(iMod), pathIndex_(iPath), preceeds_(iPreceeds) {}
556 ProgressInfo(
unsigned int iMod) : moduleIndex_(iMod), pathIndex_{}, preceeds_(
false) {}
559 std::optional<unsigned int> pathIndex_;
562 bool operator==(ProgressInfo
const& iOther)
const {
563 return moduleIndex_ == iOther.moduleIndex_ and pathIndex_ == iOther.pathIndex_;
567 std::vector<ProgressInfo> progressTrace;
568 progressTrace.emplace_back(modIndex, presentPath);
581 bool foundUnrunModule;
584 foundUnrunModule =
false;
585 for (
auto depMod : statusOfModules[modIndex].dependsOn_) {
586 auto const& depStatus = statusOfModules[depMod];
587 if (not depStatus.wasRun_ and depStatus.onPath_) {
588 foundUnrunModule =
true;
590 bool lastOnPath =
false;
591 unsigned int foundPath;
592 for (
auto pathOn : depStatus.pathsOn_) {
593 auto const& depPaths = statusOfPaths[pathOn];
594 if (depPaths.modulesOnPath_[depPaths.activeModuleSlot_] == depMod) {
602 progressTrace.emplace_back(modIndex, foundPath);
605 progressTrace.emplace_back(depMod, depStatus.pathsOn_[0]);
606 auto const& depPath = statusOfPaths[depStatus.pathsOn_[0]];
607 modIndex = depPath.modulesOnPath_[depPath.activeModuleSlot_];
608 progressTrace.emplace_back(modIndex, depStatus.pathsOn_[0],
true);
613 if (not foundUnrunModule) {
615 for (
auto depMod : statusOfModules[modIndex].dependsOn_) {
616 auto const& depStatus = statusOfModules[depMod];
617 if (not depStatus.wasRun_ and not depStatus.onPath_) {
618 foundUnrunModule =
true;
619 progressTrace.emplace_back(depMod);
625 }
while (foundUnrunModule and (0 ==
std::count(progressTrace.begin(),
626 progressTrace.begin() + progressTrace.size() - 1,
627 progressTrace.back())));
629 auto printTrace = [&](
auto& oStr,
auto itBegin,
auto itEnd) {
630 for (
auto itTrace = itBegin; itTrace != itEnd; ++itTrace) {
631 if (itTrace != itBegin) {
632 if (itTrace->preceeds_) {
633 oStr <<
" and follows module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"' on the path\n";
635 oStr <<
" and depends on module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"'\n";
638 if (itTrace + 1 != itEnd) {
639 if (itTrace->pathIndex_) {
640 oStr <<
" module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"' is on path '" 641 <<
pathName(statusOfPaths[*itTrace->pathIndex_]) <<
"'";
643 oStr <<
" module '" << moduleIndexToNames[itTrace->moduleIndex_] <<
"' is in a task";
649 if (not foundUnrunModule) {
652 oStr <<
"Algorithm Error, unable to find problem. Contact framework group.\n Traced problem this far\n";
653 printTrace(oStr, progressTrace.begin(), progressTrace.end());
656 oStr,
std::find(progressTrace.begin(), progressTrace.end(), progressTrace.back()), progressTrace.end());
661 <<
"The Path/EndPath configuration could cause the job to deadlock\n" 670 unsigned int modIndex = 0;
671 for (
auto&
mod : statusOfModules) {
672 for (
auto& depIndex :
mod.dependsOn_) {
673 std::size_t
count = 0;
674 std::size_t nonEndPaths = 0;
675 for (
auto modPathID :
mod.pathsOn_) {
676 if (statusOfPaths[modPathID].endPath_) {
680 for (
auto depPathID : statusOfModules[depIndex].pathsOn_) {
681 if (depPathID == modPathID) {
688 std::ostringstream onStr;
689 std::ostringstream missingStr;
691 for (
auto modPathID :
mod.pathsOn_) {
692 if (statusOfPaths[modPathID].endPath_) {
696 for (
auto depPathID : statusOfModules[depIndex].pathsOn_) {
697 if (depPathID == modPathID) {
701 auto&
s = statusOfPaths[modPathID];
709 <<
"Paths are non consistent\n" 710 <<
" module '" << moduleIndexToNames[modIndex] <<
"' depends on '" << moduleIndexToNames[depIndex]
711 <<
"' which appears on paths\n " << onStr.str() <<
"\nbut is missing from\n " << missingStr.str();
718 auto allDependencies = findAllDependenciesForModules(statusOfModules);
719 for (
auto&
p : statusOfPaths) {
720 for (
unsigned long int i = 0;
p.nModules_ > 0 and
i <
p.nModules_ - 1; ++
i) {
721 auto moduleID =
p.modulesOnPath_[
i];
722 if (not allDependencies[moduleID].
empty()) {
723 for (
unsigned long int j =
i + 1;
j <
p.nModules_; ++
j) {
724 auto testModuleID =
p.modulesOnPath_[
j];
725 if (allDependencies[moduleID].
find(testModuleID) != allDependencies[moduleID].end()) {
727 <<
"Dependent module later on Path\n" 728 <<
" module '" << moduleIndexToNames[moduleID] <<
"' depends on '" 729 << moduleIndexToNames[testModuleID] <<
"' which is later on path " <<
pathName(
p);
constexpr bool operator==(ELseverityLevel const &e1, ELseverityLevel const &e2) noexcept
depends_on::OneHolder< T, TDependsOnRecord > dependsOn(void(T::*iT)(const TDependsOnRecord &))
std::vector< ModuleDescription const * > const & allModules() const
ret
prodAgent to be discontinued
unsigned int doLargestModuleID() const override
std::vector< ModuleDescription const * > const & modulesOnPath(unsigned int pathIndex) const
std::array< std::vector< std::vector< ModuleDescription const * > >, NumBranchTypes > modulesWhoseProductsAreConsumedBy_
std::vector< ModuleProcessName > const & modulesInPreviousProcessesWhoseProductsAreConsumedBy(unsigned int moduleID) const
constexpr auto kInvalidIndex
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 * > const & doModulesWhoseProductsAreConsumedBy(unsigned int moduleID, BranchType branchType) const override
std::vector< ModuleDescription const * > allModuleDescriptions_
std::vector< std::string > paths_
ModuleDescription const * doModuleDescription(unsigned int moduleID) const override
std::vector< std::string > const & endPaths() const
std::vector< ModuleDescription const * > const & modulesOnEndPath(unsigned int endPathIndex) const
U second(std::pair< T, U > const &p)
std::vector< std::vector< ModuleDescription const * > > modulesOnPaths_
std::vector< std::vector< ModuleProcessName > > modulesInPreviousProcessesWhoseProductsAreConsumedBy_
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::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
std::vector< ModuleDescription const * > const & doModulesOnPath(unsigned int pathIndex) const override
virtual std::vector< ConsumesInfo > consumesInfo() const =0
void initialize(Schedule const *, std::shared_ptr< ProductRegistry const >)
std::vector< ModuleDescription const * > nonConsumedUnscheduledModules(edm::PathsAndConsumesOfModulesBase const &iPnC, std::vector< ModuleProcessName > &consumedByChildren)
static std::atomic< unsigned int > lastIndex
std::vector< std::string > endPaths_
void checkForModuleDependencyCorrectness(edm::PathsAndConsumesOfModulesBase const &iPnC, bool iPrintDependencies)
AllWorkers const & allWorkers() const
returns the collection of pointers to workers
std::shared_ptr< ProductRegistry const > preg_
~PathsAndConsumesOfModules() override
Schedule const * schedule_
unsigned int moduleIndex(unsigned int moduleID) const
PathsAndConsumesOfModules()
void removeModules(std::vector< ModuleDescription const *> const &modules)
std::vector< ConsumesInfo > doConsumesInfo(unsigned int moduleID) const override
std::vector< ModuleDescription const * > const & modulesWhoseProductsAreConsumedBy(unsigned int moduleID, BranchType branchType=InEvent) const
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)
std::vector< std::string > const & paths() const