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
PersistencyNode
will be run if any node underHLTLinesNode
passes. - The configuration of
SelReportsAlg
has the output ofTwoTrackCombinerAlg
as input. - In an event, let's say that
PVFilterAlg
fails, soTwoTrackCombinerAlg
will not be run, butTrueFilterAlg
passes. ThenHLTLinesNode
passes and hencePersistencyNode
is run.SelReportsAlg
is run and the scheduler sees the data dependency on the output ofTwoTrackCombinerAlg
and 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::Property
andDataHandle
objects. - 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.)