diff --git a/Detectors/GenericTracking/.clang-tidy b/Detectors/GenericTracking/.clang-tidy new file mode 100644 index 0000000000000..b9af34ed01651 --- /dev/null +++ b/Detectors/GenericTracking/.clang-tidy @@ -0,0 +1,137 @@ +--- +# GenericTracking: a generic, GPU-capable CA track finder. +# +# Three properties of this code shape the disabled list below. +# +# 1. Parts of it compile as device code. std::array, std::span, exceptions +# and RTTI are unavailable there, so the checks that push C arrays and +# pointer arithmetic towards those replacements are actively wrong. +# +# 2. It is detector software. Short identifiers are the domain's notation -- +# x, y, z, r, phi, eta, pt, bz -- and spelling them out makes formulas +# harder to check, not easier. +# +# 3. It interoperates with ROOT and O2. Generated dictionary code and +# macro expansions are not ours to fix. + +Checks: + - -* + - bugprone-* + - performance-* + - modernize-* + - portability-* + - cppcoreguidelines-* + - misc-* + - readability-* + - clang-analyzer-* + + # -- device code cannot use the recommended replacements ------------------ + - -cppcoreguidelines-avoid-c-arrays # GPUd() paths take raw pointers + - -modernize-avoid-c-arrays # and fixed C arrays by design + - -cppcoreguidelines-pro-bounds-pointer-arithmetic + - -cppcoreguidelines-pro-bounds-constant-array-index + - -cppcoreguidelines-pro-bounds-array-to-pointer-decay + - -cppcoreguidelines-pro-bounds-avoid-unchecked-container-access # Eigen v[i] + - -cppcoreguidelines-init-variables # T x{} is already value-initialised + + # -- the domain's notation ------------------------------------------------ + - -readability-identifier-length # r, z, phi, pt, bz are the names + - -bugprone-easily-swappable-parameters # (x, y, z) is the whole API + - -readability-math-missing-parentheses # transcribed formulas stay flat + # Geometry is arithmetic. The offending literals are rotation-matrix element + # indices (rot[5]), the 2 in "twice the half-width" and the 0.5 in "half the + # span"; a named constant for any of them obscures the formula it appears in. + - -cppcoreguidelines-avoid-magic-numbers + - -readability-magic-numbers + + # -- POD data model ------------------------------------------------------- + # Sensor, Layer, Digit, Cluster and the SoA views are deliberately public + # aggregates: they are uploaded to the device as-is, so an accessor layer + # would be a lie about their layout. + - -misc-non-private-member-variables-in-classes + - -cppcoreguidelines-non-private-member-variables-in-classes + - -cppcoreguidelines-pro-type-member-init # aggregate init at the use site + # Small index enums -- kLoc0..kQOverP, kFree/kShared/kExclusive, the reports' + # kinds ending in a count -- stay unscoped with a fixed underlying type: they + # index arrays and size them without a cast (BoundIndex, Definitions.h). + - -cppcoreguidelines-use-enum-class + + # -- ROOT and Boost own memory their own way ------------------------------ + # ROOT's object model is `new` handing ownership to a manager singleton: + # gGeoManager owns every TGeoMaterial, TGeoVolume and TGeoMatrix created + # under it, and deleting one ourselves is a crash. There is no owner<> to + # be had, so the check has nothing correct to suggest. + - -cppcoreguidelines-owning-memory + - -cppcoreguidelines-no-malloc + # Fires inside Boost.ProgramOptions' own headers, on instantiations our TU + # triggers rather than on anything we wrote. HeaderFilterRegex cannot + # suppress it because the diagnostic is attributed to our source file. + - -portability-template-virtual-member-function + + # -- style choices -------------------------------------------------------- + - -modernize-use-trailing-return-type + # A multi-way choice of a label or a kind reads best as one chained + # conditional: `a ? x : b ? y : z`. + - -readability-avoid-nested-conditional-operator + + # -- untrue of a Boost.Test suite ----------------------------------------- + # Every BOOST_TEST expands to branches, so a test case that checks a dozen + # properties in a loop scores as deeply nested code that nobody wrote. + - -readability-function-cognitive-complexity + # BOOST_AUTO_TEST_CASE expands to a static function; the check fires on the + # macro expansion, so there is nothing at the call site to fix. + - -misc-use-anonymous-namespace + # Fixed seeds are the point -- digitiser noise and MC closure tests are only + # meaningful if the sequence reproduces. + - -bugprone-random-generator-seed + + # -- IWYU enforcement, deliberately off ----------------------------------- + # misc-include-cleaner cannot see through O2's GPUCommon* include structure + # and would demand every TU name the header behind each type rather than the + # one it actually uses. Too much churn for the benefit. + - -misc-include-cleaner + +WarningsAsErrors: '*' + +HeaderFilterRegex: 'GenericTracking/.*\.(h|cuh)$' + +CheckOptions: + # Naming follows O2's conventions. + readability-identifier-naming.ClassCase: CamelCase + readability-identifier-naming.StructCase: CamelCase + readability-identifier-naming.EnumCase: CamelCase + readability-identifier-naming.EnumConstantCase: CamelCase + readability-identifier-naming.EnumConstantIgnoredRegexp: '^k[A-Z][a-zA-Z0-9]*$' + readability-identifier-naming.ConceptCase: CamelCase + readability-identifier-naming.TypeAliasCase: CamelCase + readability-identifier-naming.TypedefCase: CamelCase + readability-identifier-naming.TemplateParameterCase: CamelCase + readability-identifier-naming.TypeTemplateParameterCase: CamelCase + readability-identifier-naming.FunctionCase: camelBack + readability-identifier-naming.ParameterCase: camelBack + readability-identifier-naming.VariableCase: camelBack + readability-identifier-naming.NamespaceCase: lower_case + # O2 spells non-public members mFoo; the POD aggregates keep plain camelBack + # public names because they are part of the wire format. + readability-identifier-naming.PrivateMemberCase: CamelCase + readability-identifier-naming.PrivateMemberPrefix: m + readability-identifier-naming.ProtectedMemberCase: CamelCase + readability-identifier-naming.ProtectedMemberPrefix: m + readability-identifier-naming.PublicMemberCase: camelBack + readability-identifier-naming.MacroDefinitionCase: UPPER_CASE + readability-identifier-naming.MacroDefinitionIgnoredRegexp: '^[A-Z][A-Z0-9_]*_?$' + readability-identifier-naming.ConstexprVariableCase: camelBack + readability-identifier-naming.ConstexprVariableIgnoredRegexp: '^k[A-Z][a-zA-Z0-9]*$' + readability-identifier-naming.GlobalConstantCase: camelBack + readability-identifier-naming.GlobalConstantIgnoredRegexp: '^k[A-Z][a-zA-Z0-9]*$' + # BOOST_AUTO_TEST_CASE(SomeName) expands its argument into a function name; + # the diagnostic points into the macro, so there is no per-case fix. + readability-identifier-naming.FunctionIgnoredRegexp: '^[A-Z][A-Za-z0-9]*$' + + misc-include-cleaner.IgnoreHeaders: 'Eigen/.*;GPUCommon.*' + # Values and references only: the pointee analysis does not count a pointer + # handed out -- returned as void*, stored in an allocation's void* data -- as + # a use of the pointee, and asks for const where it cannot compile. + misc-const-correctness.WarnPointersAsPointers: false + performance-move-const-arg.CheckTriviallyCopyableMove: false +... diff --git a/Detectors/GenericTracking/CMakeLists.txt b/Detectors/GenericTracking/CMakeLists.txt index 2c865e20d88a5..2d6b535792065 100644 --- a/Detectors/GenericTracking/CMakeLists.txt +++ b/Detectors/GenericTracking/CMakeLists.txt @@ -8,8 +8,15 @@ # In applying this license CERN does not waive the privileges and immunities # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2_add_library(GenericTracking - SOURCES src/BoundedAllocator.cxx - PRIVATE_LINK_LIBRARIES O2::GPUCommon O2::FrameworkLogger) +# Every unit that instantiates the header tracker -- the tracking device's, the +# study library's, the sink's and the benches' -- compiles at -O3 in +# RelWithDebInfo, where the tracker runs faster than at O2's -O2. +set(GTRK_TRACKER_OPTIMIZATION "$<$,$>:-O3>") -add_subdirectory(test) +add_subdirectory(base) +add_subdirectory(tracking) +add_subdirectory(workflow) +if(ENABLE_UPGRADES) + add_subdirectory(tools) + add_subdirectory(study) +endif() diff --git a/Detectors/GenericTracking/base/CMakeLists.txt b/Detectors/GenericTracking/base/CMakeLists.txt new file mode 100644 index 0000000000000..4915ff0996a82 --- /dev/null +++ b/Detectors/GenericTracking/base/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +# The base: what includes no tracking code -- the geometry and time model +# (Base/, the detectors' layouts in Detectors/), the bounded allocator, the SoA +# columns, the host algorithms, the lanes, the portable math and the capacity +# estimator. Header code but for the three sources; host only. +o2_add_library(GTrkBase + SOURCES src/BoundedAllocator.cxx + src/CapacityEstimator.cxx + src/LayerEnvelopes.cxx + PUBLIC_LINK_LIBRARIES O2::GPUCommon + TARGETVARNAME targetName) + +# o2_add_library installs the headers of include/ only. +target_include_directories(${targetName} PUBLIC $) +target_include_directories(${targetName} SYSTEM PUBLIC $ + $) +install(DIRECTORY include/GenericTracking DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +install(DIRECTORY External/memlayout DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GenericTracking/External) + +add_subdirectory(test) diff --git a/Detectors/GenericTracking/base/External/memlayout/wrapper.h b/Detectors/GenericTracking/base/External/memlayout/wrapper.h new file mode 100644 index 0000000000000..f193d686577c6 --- /dev/null +++ b/Detectors/GenericTracking/base/External/memlayout/wrapper.h @@ -0,0 +1,564 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef MEMLAYOUT_H +#define MEMLAYOUT_H + +// Upstream forward-declares std::iterator_traits here. libc++ declares it +// differently, so the two are ambiguous in any translation unit that also +// includes a standard container. Including the real header instead. +#include +#include + +#ifndef MEMLAYOUT_HOST_DEVICE +#ifdef GPUhdi +#define MEMLAYOUT_HOST_DEVICE GPUhdi() +#else +#define MEMLAYOUT_HOST_DEVICE +#endif +#endif + +// Local addition: the element access -- operator[] and what it calls -- is +// always inlined. It builds a proxy of one reference per column; inlined, +// the references a caller never reads fold away and `view[i].x` is one load, +// but a compiler that keeps it out of line (GCC at -O2 does, for a record of +// many columns) computes and stores every one of them on each call. nvcc and +// HIP's clang take the attribute as they take __forceinline__. +// +// It only reaches as far as the proxy does inline: a proxy returned by, or +// passed to, a function the compiler keeps out of line is built whole again. +// Code that needs a few columns of a row is better served reading them from +// the view, `view.x[i]`, which builds no proxy at all. +#ifndef MEMLAYOUT_INLINE +#if defined(__GNUC__) || defined(__clang__) +#define MEMLAYOUT_INLINE __attribute__((always_inline)) +#else +#define MEMLAYOUT_INLINE +#endif +#endif + +namespace memlayout +{ + +using size_t = decltype(sizeof(0)); +using ptrdiff_t = decltype(static_cast(nullptr) - static_cast(nullptr)); + +template +using value = T; +template +using reference = T&; +template +using const_reference = const T&; +template +using pointer = T*; +template +using const_pointer = const T*; + +// Local addition: a default value for a field of a struct templated on its +// storage. In the record form, Container = value, the field takes `v`; in +// every other form it is value-initialised -- a null pointer, an empty +// container -- so one declaration serves as record and as columns: +// +// C x = memlayout::default_value(0.F); +// +// The reference forms have no default; that is safe because a default member +// initializer of a class template is instantiated only where it is used, and +// the wrapper always initialises every member. +template