SelReportsMaker configurations causes line algorithms to run unconditionally.
The configuration of the SelReportsMaker algorithm has the (converted) output of all lines as input. When the scheduler runs the maker, it resolves the data dependency tree by running the line algorithms, regardless of whether or not the line's control flow node passed. Some line algorithms should not be run if their prefilters fail, but the dependency resolution ignores this. This is wasteful and potentially meaningless.
In summary, we somehow need to handle optional data dependencies.
Detail
Imagine this control flow (which is similar to what Moore constructs) for two lines:
MooreNode
HLTLinesNode
PassthroughLineNode
TrueFilterAlg
PhysicsLineNode
PVFilterAlg
TwoTrackCombinerAlg
PersistencyNode
DecReportsAlg
SelReportsAlg
- The algorithms in
PersistencyNodewill be run if any node underHLTLinesNodepasses. - The configuration of
SelReportsAlghas the output ofTwoTrackCombinerAlgas input. - In an event, let's say that
PVFilterAlgfails, soTwoTrackCombinerAlgwill not be run, butTrueFilterAlgpasses. ThenHLTLinesNodepasses and hencePersistencyNodeis run.SelReportsAlgis run and the scheduler sees the data dependency on the output ofTwoTrackCombinerAlgand so runs the combiner algorithm.
The combiner algorithm may have undefined behaviour if the prefilter in the control flow fails. For example, the functor may require a non-zero number of PVs in order for the functor evaluation to make sense. But now the scheduler is running this algorithm regardless of whether the PV container is empty or not.
IRL
We observed this problem in the HLT1 performance comparison configuration. This runs a 'GEC passthrough' line which fires if the GEC passes. If every physics line fails but the passthrough line fires, the output algorithm of each line will be run by the scheduler in order to meet the data dependencies of the SelReports maker. !439 (merged) temporarily addresses this by removing the passthrough line from the configuration, but the underlying problem remains; any line that fires without requiring PVs will trigger the issue.
Solutions
A couple of ideas for dealing with optional data dependencies (for this particular case; maybe there's a better solution that's more general):
-
getIfExists. The maker algorithm has list of inputs, one per line, and it could retrieve them with agetIfExists, skipping making a SelReport if the dependecy doesn't exists. This isn't nice because:- It circumvents the explicit declarations made possible via
Gaudi::PropertyandDataHandleobjects. - The actual input might not be the direct output of a line algorithm, but the output of a converter, so we might need the dependency resolution mechanism to walk up the tree for us to run the (chain of) converters.
- It circumvents the explicit declarations made possible via
- Tie the control flow node dependency explicitly to the data dependency. Each input is, somehow, a pair that expresses the intent of "only resolve this data dependency if that control flow node passed".
The second solution seems most elegant to me, and the implementation in the scheduler is probably fairly straight forward. The tricky part is how to express this in the algorithm implementation, i.e. the implementation of the OptionalDataHandle property (and associated lists/maps of optional deps.) and how these are passed to the operator(). (These problems may be of interest to @graven.)