-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#410: Dependent Epochs rewritten #2204
base: develop
Are you sure you want to change the base?
Changes from 1 commit
ccd5afd
b393469
9a1efe8
72fbfec
5cd8599
10147f4
1db25fa
a9816c6
4de8a74
bfdc3f4
3c1ac7f
cdf69ab
9764708
a974aba
3e76af5
3d2b117
f746269
cb2b519
4b3a9c6
48f7a8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,6 +89,24 @@ struct EpochManip : runtime::component::Component<EpochManip> { | |
*/ | ||
static bool isRooted(EpochType const& epoch); | ||
|
||
/** | ||
* \brief Gets whether an epoch is DS or onot | ||
* | ||
* \param[in] epoch the epoch | ||
* | ||
* \return whether it is DS | ||
*/ | ||
static bool isDS(EpochType epoch); | ||
|
||
/** | ||
* \brief Gets whether an epoch is dependent or onot | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo. |
||
* | ||
* \param[in] epoch the epoch | ||
* | ||
* \return whether it is dependent | ||
*/ | ||
static bool isDep(EpochType epoch); | ||
|
||
/** | ||
* \brief Gets the \c eEpochCategory of a given epoch | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -931,10 +931,12 @@ void TerminationDetector::finishedEpoch(EpochType const& epoch) { | |
} | ||
|
||
EpochType TerminationDetector::makeEpochRootedWave( | ||
ParentEpochCapture successor, std::string const& label | ||
ParentEpochCapture successor, std::string const& label, bool is_dep | ||
) { | ||
auto const no_cat = epoch::eEpochCategory::NoCategoryEpoch; | ||
auto const epoch = theEpoch()->getNextRootedEpoch(no_cat); | ||
auto const cat = is_dep ? | ||
epoch::eEpochCategory::DependentEpoch : | ||
epoch::eEpochCategory::NoCategoryEpoch; | ||
auto const epoch = theEpoch()->getNextRootedEpoch(cat); | ||
initializeRootedWaveEpoch(epoch, successor, label); | ||
return epoch; | ||
|
||
|
@@ -970,10 +972,16 @@ void TerminationDetector::initializeRootedWaveEpoch( | |
} | ||
|
||
EpochType TerminationDetector::makeEpochRootedDS( | ||
ParentEpochCapture successor, std::string const& label | ||
ParentEpochCapture successor, std::string const& label, bool is_dep | ||
) { | ||
auto const ds_cat = epoch::eEpochCategory::DijkstraScholtenEpoch; | ||
auto const epoch = theEpoch()->getNextRootedEpoch(ds_cat); | ||
auto cat = epoch::eEpochCategory::DijkstraScholtenEpoch; | ||
if (is_dep) { | ||
cat = theEpoch()->makeCat( | ||
epoch::eEpochCategory::DependentEpoch, | ||
epoch::eEpochCategory::DijkstraScholtenEpoch | ||
); | ||
} | ||
auto const epoch = theEpoch()->getNextRootedEpoch(cat); | ||
initializeRootedDSEpoch(epoch, successor, label); | ||
return epoch; | ||
} | ||
|
@@ -1002,13 +1010,14 @@ void TerminationDetector::initializeRootedDSEpoch( | |
} | ||
|
||
EpochType TerminationDetector::makeEpochRooted( | ||
UseDS use_ds, ParentEpochCapture successor | ||
UseDS use_ds, ParentEpochCapture successor, bool is_dep | ||
) { | ||
return makeEpochRooted("", use_ds, successor); | ||
return makeEpochRooted("", use_ds, successor, is_dep); | ||
} | ||
|
||
EpochType TerminationDetector::makeEpochRooted( | ||
std::string const& label, UseDS use_ds, ParentEpochCapture successor | ||
std::string const& label, UseDS use_ds, ParentEpochCapture successor, | ||
bool is_dep | ||
) { | ||
/* | ||
* This method should only be called by the root node for the rooted epoch | ||
|
@@ -1029,9 +1038,9 @@ EpochType TerminationDetector::makeEpochRooted( | |
vtAssertExpr(not (force_use_ds and force_use_wave)); | ||
|
||
if ((use_ds or force_use_ds) and not force_use_wave) { | ||
return makeEpochRootedDS(successor, label); | ||
return makeEpochRootedDS(successor, label, is_dep); | ||
} else { | ||
return makeEpochRootedWave(successor, label); | ||
return makeEpochRootedWave(successor, label, is_dep); | ||
} | ||
} | ||
|
||
|
@@ -1047,20 +1056,23 @@ void TerminationDetector::initializeRootedEpoch( | |
} | ||
|
||
EpochType TerminationDetector::makeEpochCollective( | ||
ParentEpochCapture successor | ||
ParentEpochCapture successor, bool is_dep | ||
) { | ||
vt_debug_print( | ||
normal, term, | ||
"makeEpochCollective: no label\n" | ||
); | ||
|
||
return makeEpochCollective("", successor); | ||
return makeEpochCollective("", successor, is_dep); | ||
} | ||
|
||
EpochType TerminationDetector::makeEpochCollective( | ||
std::string const& label, ParentEpochCapture successor | ||
std::string const& label, ParentEpochCapture successor, bool is_dep | ||
) { | ||
auto const epoch = theEpoch()->getNextCollectiveEpoch(); | ||
auto const cat = is_dep ? | ||
epoch::eEpochCategory::DependentEpoch : | ||
epoch::eEpochCategory::NoCategoryEpoch; | ||
auto const epoch = theEpoch()->getNextCollectiveEpoch(cat); | ||
initializeCollectiveEpoch(epoch, label, successor); | ||
return epoch; | ||
} | ||
|
@@ -1105,11 +1117,121 @@ void TerminationDetector::initializeCollectiveEpoch( | |
|
||
EpochType TerminationDetector::makeEpoch( | ||
std::string const& label, bool is_coll, UseDS use_ds, | ||
ParentEpochCapture successor | ||
ParentEpochCapture successor, bool is_dep | ||
) { | ||
return is_coll ? | ||
makeEpochCollective(label, successor) : | ||
makeEpochRooted(label, use_ds, successor); | ||
makeEpochCollective(label, successor, is_dep) : | ||
makeEpochRooted(label, use_ds, successor, is_dep); | ||
} | ||
|
||
void TerminationDetector::releaseEpoch(EpochType epoch) { | ||
bool const is_dep = isDep(epoch); | ||
|
||
if (is_dep) { | ||
// Put the epoch in the released set, which is not conclusive due to | ||
// dependencies, which effects the status. An epoch is *released* iff the | ||
lifflander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// epoch is in the released set and all succesrros are *released* (or there | ||
lifflander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// are no successors). The epoch any_epoch_sentinel does not count as a | ||
// succcessor. | ||
epoch_released_.insert(epoch); | ||
|
||
bool const is_released = epochReleased(epoch); | ||
if (is_released) { | ||
runReleaseEpochActions(epoch); | ||
} else { | ||
// Enqueue continuations to potentially release this epoch since the | ||
// successor graph is not inverted (one-way knowledge) | ||
auto const& successors = getEpochDep(epoch)->getSuccessors(); | ||
vtAssert(successors.size() > 0, "Must have unreleased successors in this case"); | ||
for (auto&& suc : successors) { | ||
if (not epochReleased(suc)) { | ||
onReleaseEpoch(suc, [epoch]{ theTerm()->releaseEpoch(epoch); }); | ||
} | ||
} | ||
} | ||
} else { | ||
// The user might have made a mistake if they are trying to release an epoch | ||
// that is released-by-default (not dependent) | ||
vtWarn("Trying to release non-dependent epoch"); | ||
} | ||
} | ||
|
||
void TerminationDetector::runReleaseEpochActions(EpochType epoch) { | ||
auto iter = epoch_release_action_.find(epoch); | ||
if (iter != epoch_release_action_.end()) { | ||
auto actions = std::move(iter->second); | ||
epoch_release_action_.erase(iter); | ||
for (auto&& fn : actions) { | ||
fn(); | ||
} | ||
} | ||
lifflander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
theMsg()->releaseEpochMsgs(epoch); | ||
} | ||
|
||
void TerminationDetector::onReleaseEpoch(EpochType epoch, ActionType action) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should use the same approach as term actions after #2196 |
||
// Run an action if an epoch has been released | ||
bool const is_dep = isDep(epoch); | ||
if (not is_dep or (is_dep and epochReleased(epoch))) { | ||
action(); | ||
} else { | ||
epoch_release_action_[epoch].push_back(action); | ||
} | ||
} | ||
|
||
bool TerminationDetector::epochSuccessorsReleased(EpochType epoch) { | ||
// Test of all parents of a given epoch are released | ||
bool released = true; | ||
auto const& successors = getEpochDep(epoch)->getSuccessors(); | ||
if (successors.size() != 0) { | ||
for (auto&& suc : successors) { | ||
released &= epochReleased(suc); | ||
} | ||
} | ||
return released; | ||
} | ||
|
||
bool TerminationDetector::epochReleased(EpochType epoch) { | ||
// Because of case (2), ignore dep <- no-dep because this should not be called | ||
// unless dep is released | ||
bool const is_dep = isDep(epoch); | ||
if (not is_dep) { | ||
return true; | ||
} | ||
|
||
// Terminated epochs are always released | ||
bool const is_term = theEpoch()->getTerminatedWindow(epoch)->isTerminated( | ||
epoch | ||
); | ||
if (is_term) { | ||
return true; | ||
} | ||
Comment on lines
+1149
to
+1155
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this should be true, or an empty dependent epoch could terminate before being released, which seems counter-intuitive.
Your added action could run before releasing in the above, or in cases where a set of functions may or may not actually send messages. We should produce once on dependent epoch creation and consume on release, to align the no-messages behavior with typical behavior. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lifflander What are your thoughts on Matthew's concern? |
||
|
||
// All successors must be released for an epoch to be released even if its in | ||
lifflander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// the release set. Epochs are put in the release set early as to reduce | ||
// tracking of epoch "release chains" | ||
bool const is_successors_released = epochSuccessorsReleased(epoch); | ||
if (not is_successors_released) { | ||
return false; | ||
} | ||
|
||
// Check the release set | ||
auto iter = epoch_released_.find(epoch); | ||
return iter != epoch_released_.end(); | ||
} | ||
|
||
void TerminationDetector::cleanupReleasedEpoch(EpochType epoch) { | ||
bool const is_dep = isDep(epoch); | ||
if (is_dep) { | ||
bool const is_term = theEpoch()->getTerminatedWindow(epoch)->isTerminated( | ||
epoch | ||
); | ||
if (is_term) { | ||
auto iter = epoch_released_.find(epoch); | ||
if (iter != epoch_released_.end()) { | ||
epoch_released_.erase(iter); | ||
} | ||
lifflander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} | ||
|
||
void TerminationDetector::activateEpoch(EpochType const& epoch) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo.