Skip to content

Add vectorised track combiner

Olli Lupton requested to merge olupton_simd_combiner into master

Brief summary: add a vectorised track combiner CombineTracksSIMD (which produces v2::Composites), and a whole bunch of other related changes to selection/functor code to enable this.

CombineTracksSIMD:

  • Implements generic N-body combinations from a single input container of tracks, producing v2::Composites
  • The combiner has to be explicitly instantiated for each input container type, N and target vector backend. The output type v2::Composites erases all of these details.
  • If a relevant functor cache is available, the combination generation, combination cut(s), vertex fit and vertex/parent cut are all explicitly vectorised. If no cache is available, the cuts are JIT compiled and the algorithm falls back to scalar calculation.
  • Vertex fit implementation is lifted from ThOrParticleCombiner, thanks @nnolte :)

Converters:

  • Add LHCb::Converters::Composites::ToVectorOfRecVertex<T> algorithm for converting v2::Composites to a vector of vertices, for use in the SelReports code

Functor interface changes:

  • Store whether a functor with JIT compiled or loaded from the functor cache.
  • Add getFunctors() method to with_functors mixin to return multiple decoded functors at once.
  • Add Functors::mask_arg_t tag type; this can be used to tag that the following (second) argument is a mask that gives the validity of the remaining arguments: Functor<Output( mask_arg_t, mask_v const&, Input const& )>. This is useful when Input is some type representing a vector of values.
  • Drop BPVIPCHI2STATE functor
  • Make the CompositeMass functor return p.momentum().M() instead of p.measuredMass() when applied to a v1::Particle
  • Make the COMB functor [reconstructing a "combination" object from a "composite"] compatible with a runtime-variable number of heterogeneous child types & vectorised instantiation
  • Make the MVA functor support vectorised instantiation; the calculation of inputs is vectorised, but evaluation of the classifier is [masked] scalar. (We should really get some faster MVA implementations here!)
  • Add POD functor (meaning Plain Old Data, but perhaps someone would like to suggest a better name) that wraps the new Sel::Utils::as_arithmetic helper. This converts objects representing scalar values into plain C++ types (e.g. SIMDWrapper::scalar::int_v -> int). This is a step on the way to retiring the "unwrapping" functionality of LHCb::Pr::Zip. POD can be automatically added as a wrapper around a functor expression to make it yield a type that e.g. TTree can understand.

Selection utilities changes:

  • Add Sel::Utils::hmin, Sel::Utils::hmax, Sel::Utils::as_arithmetic helpers for writing generic code that handles both plain C++ types and e.g. SIMDWrapper int/float types.
  • Add various helpers for writing generic code, e.g. Sel::vector::dot{}( a, b ) takes the dot product of vectors a and b, abstracting away some API inconsistencies between different vector types in the codebase
  • Reorganise various type trait helpers, e.g. Sel::type_traits::has_eta_v<T> queries whether an object of type T has an eta() method
  • Add Sel::Utils::stateDOCA( s1, s2 ) helper for calculating the distance of closest approach between two states of distinct type. This is copied from LHCb::TrackVertexUtils::doca to avoid the unfortunate issue that calling LHCb::TrackVertexUtils::doca with two arguments of different types despatches to the calculation of DOCA between a state and a point (a state has x/y/z accessors, so this is not a compile error!)

Event model changes:

  • Add v2::Composites-compatible accessors to TrackCompactVertex
  • Prefer static_assert( std::numeric_limits<T>::is_specialized ) and std::numeric_limits<T> now SIMDWrapper supports std::numeric_limits

Internal functor changes:

  • Pass Functors::TopLevelInfo& to internal functor bind methods instead of Gaudi::Algorithm*, making it easier to expose more helper functionality; add a helper to avoid hitting https://its.cern.ch/jira/browse/GAUDI-1023 when multiple functors need to access the same service
  • Add some missing inheritance from Function and Predicate
  • Use demangled typeid( T ).name() in some error messages
  • Minor code improvements/cleanups.
  • Support explicit masks in functors. If a functor defines constexpr static bool requires_explicit_mask = true then it will be invoked with a mask as its first argument, which gives the validity of the remaining arguments. Make this change in the various adapter functors.
  • Use explicit mask support in MINIP[CHI2]CUT functors, where the mask can be used to short-circuit earlier.

To be tested with LHCb!2650 (merged) and Moore!562 (merged)

cc: @nnolte

Edited by Olli Lupton

Merge request reports