Skip to content
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

Improve the SoA accessors and optimisations #39919

Merged
merged 5 commits into from Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions DataFormats/SoATemplate/README.md
Expand Up @@ -66,8 +66,9 @@ Serialization of Eigen data is not yet supported.
The template shared by layouts and parameters are:
- Byte aligment (defaulting to the nVidia GPU cache line size (128 bytes))
- Alignment enforcement (`relaxed` or `enforced`). When enforced, the alignment will be checked at construction
time, and the accesses are done with compiler hinting (using the widely supported `__builtin_assume_aligned`
intrinsic).
time.~~, and the accesses are done with compiler hinting (using the widely supported `__builtin_assume_aligned`
intrinsic).~~ It turned out that hinting `nvcc` for alignement removed the benefit of more important `__restrict__`
hinting. The `__builtin_assume_aligned` is hence currently not use.

In addition, the views also provide access parameters:
- Restrict qualify: add restrict hints to read accesses, so that the compiler knows it can relax accesses to the
Expand Down
91 changes: 46 additions & 45 deletions DataFormats/SoATemplate/interface/SoACommon.h
Expand Up @@ -287,19 +287,19 @@ namespace cms::soa {

SOA_HOST_DEVICE SOA_INLINE Ref operator()() {
// Ptr type will add the restrict qualifyer if needed
Ptr col = alignedCol();
Ptr col = col_;
return col[idx_];
}

SOA_HOST_DEVICE SOA_INLINE RefToConst operator()() const {
// PtrToConst type will add the restrict qualifyer if needed
PtrToConst col = alignedCol();
PtrToConst col = col_();
return col[idx_];
}

SOA_HOST_DEVICE SOA_INLINE Ptr operator&() { return &alignedCol()[idx_]; }
SOA_HOST_DEVICE SOA_INLINE Ptr operator&() { return &col_[idx_]; }

SOA_HOST_DEVICE SOA_INLINE PtrToConst operator&() const { return &alignedCol()[idx_]; }
SOA_HOST_DEVICE SOA_INLINE PtrToConst operator&() const { return &col_[idx_]; }

/* This was an attempt to implement the syntax
*
Expand All @@ -318,7 +318,7 @@ namespace cms::soa {

template <typename T2>
SOA_HOST_DEVICE SOA_INLINE Ref operator=(const T2& v) {
return alignedCol()[idx_] = v;
return col_[idx_] = v;
}
*/

Expand All @@ -327,13 +327,6 @@ namespace cms::soa {
static constexpr auto valueSize = sizeof(T);

private:
SOA_HOST_DEVICE SOA_INLINE Ptr alignedCol() const {
if constexpr (ALIGNMENT) {
return reinterpret_cast<Ptr>(__builtin_assume_aligned(col_, ALIGNMENT));
}
return reinterpret_cast<Ptr>(col_);
}

size_type idx_;
T* col_;
};
Expand Down Expand Up @@ -437,11 +430,11 @@ namespace cms::soa {

SOA_HOST_DEVICE SOA_INLINE RefToConst operator()() const {
// Ptr type will add the restrict qualifyer if needed
PtrToConst col = alignedCol();
PtrToConst col = col_;
return col[idx_];
}

SOA_HOST_DEVICE SOA_INLINE const T* operator&() const { return &alignedCol()[idx_]; }
SOA_HOST_DEVICE SOA_INLINE const T* operator&() const { return &col_[idx_]; }

/* This was an attempt to implement the syntax
*
Expand All @@ -461,13 +454,6 @@ namespace cms::soa {
static constexpr auto valueSize = sizeof(T);

private:
SOA_HOST_DEVICE SOA_INLINE PtrToConst alignedCol() const {
if constexpr (ALIGNMENT) {
return reinterpret_cast<PtrToConst>(__builtin_assume_aligned(col_, ALIGNMENT));
}
return reinterpret_cast<PtrToConst>(col_);
}

size_type idx_;
const T* col_;
};
Expand Down Expand Up @@ -584,47 +570,49 @@ namespace cms::soa {
/* Column accessors: templates implementing the global accesors (soa::x() and soa::x(index) */
enum class SoAAccessType : bool { mutableAccess, constAccess };

template <typename, SoAColumnType, SoAAccessType>
template <typename, SoAColumnType, SoAAccessType, byte_size_type, bool>
struct SoAColumnAccessorsImpl {};

// TODO from Eric Cano:
// - add alignment support
// - SFINAE-based const/non const variants

// Column
template <typename T>
struct SoAColumnAccessorsImpl<T, SoAColumnType::column, SoAAccessType::mutableAccess> {
//SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(T* baseAddress) : baseAddress_(baseAddress) {}
template <typename T, byte_size_type alignment, bool restrictQualify>
struct SoAColumnAccessorsImpl<T, SoAColumnType::column, SoAAccessType::mutableAccess, alignment, restrictQualify> {
SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAParametersImpl<SoAColumnType::column, T>& params)
: params_(params) {}
SOA_HOST_DEVICE SOA_INLINE T* operator()() { return params_.addr_; }
using NoParamReturnType = T*;
using ParamReturnType = T&;
SOA_HOST_DEVICE SOA_INLINE T& operator()(size_type index) { return params_.addr_[index]; }

private:
SoAParametersImpl<SoAColumnType::column, T> params_;
};

// Const column
template <typename T>
struct SoAColumnAccessorsImpl<T, SoAColumnType::column, SoAAccessType::constAccess> {
template <typename T, byte_size_type alignment, bool restrictQualify>
struct SoAColumnAccessorsImpl<T, SoAColumnType::column, SoAAccessType::constAccess, alignment, restrictQualify> {
SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAConstParametersImpl<SoAColumnType::column, T>& params)
: params_(params) {}
SOA_HOST_DEVICE SOA_INLINE const T* operator()() const { return params_.addr_; }
using NoParamReturnType = const T*;
SOA_HOST_DEVICE SOA_INLINE T operator()(size_type index) const { return params_.addr_[index]; }
using ParamReturnType = const T&;
SOA_HOST_DEVICE SOA_INLINE T const& operator()(size_type index) const { return params_.addr_[index]; }

private:
SoAConstParametersImpl<SoAColumnType::column, T> params_;
};

// Scalar
template <typename T>
struct SoAColumnAccessorsImpl<T, SoAColumnType::scalar, SoAAccessType::mutableAccess> {
template <typename T, byte_size_type alignment, bool restrictQualify>
struct SoAColumnAccessorsImpl<T, SoAColumnType::scalar, SoAAccessType::mutableAccess, alignment, restrictQualify> {
SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAParametersImpl<SoAColumnType::scalar, T>& params)
: params_(params) {}
SOA_HOST_DEVICE SOA_INLINE T& operator()() { return *params_.addr_; }
using NoParamReturnType = T&;
using ParamReturnType = void;
SOA_HOST_DEVICE SOA_INLINE void operator()(size_type index) const {
assert(false && "Indexed access impossible for SoA scalars.");
}
Expand All @@ -634,12 +622,13 @@ namespace cms::soa {
};

// Const scalar
template <typename T>
struct SoAColumnAccessorsImpl<T, SoAColumnType::scalar, SoAAccessType::constAccess> {
template <typename T, byte_size_type alignment, bool restrictQualify>
struct SoAColumnAccessorsImpl<T, SoAColumnType::scalar, SoAAccessType::constAccess, alignment, restrictQualify> {
SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAConstParametersImpl<SoAColumnType::scalar, T>& params)
: params_(params) {}
SOA_HOST_DEVICE SOA_INLINE T operator()() const { return *params_.addr_; }
using NoParamReturnType = T;
SOA_HOST_DEVICE SOA_INLINE T const& operator()() const { return *params_.addr_; }
using NoParamReturnType = T const&;
using ParamReturnType = void;
SOA_HOST_DEVICE SOA_INLINE void operator()(size_type index) const {
assert(false && "Indexed access impossible for SoA scalars.");
}
Expand All @@ -649,27 +638,32 @@ namespace cms::soa {
};

// Eigen-type
template <typename T>
struct SoAColumnAccessorsImpl<T, SoAColumnType::eigen, SoAAccessType::mutableAccess> {
//SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(T* baseAddress) : baseAddress_(baseAddress) {}
template <typename T, byte_size_type alignment, bool restrictQualify>
struct SoAColumnAccessorsImpl<T, SoAColumnType::eigen, SoAAccessType::mutableAccess, alignment, restrictQualify> {
SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAParametersImpl<SoAColumnType::eigen, T>& params)
: params_(params) {}
SOA_HOST_DEVICE SOA_INLINE typename T::Scalar* operator()() { return params_.addr_; }
using NoParamReturnType = typename T::Scalar*;
//SOA_HOST_DEVICE SOA_INLINE T& operator()(size_type index) { return params_.addr_[index]; }
using ParamReturnType = typename SoAValue<SoAColumnType::eigen, T, alignment, restrictQualify>::MapType;
SOA_HOST_DEVICE SOA_INLINE ParamReturnType operator()(size_type index) {
return SoAValue<SoAColumnType::eigen, T, alignment, restrictQualify>(index, params_)();
}

private:
SoAParametersImpl<SoAColumnType::eigen, T> params_;
};

// Const Eigen-type
template <typename T>
struct SoAColumnAccessorsImpl<T, SoAColumnType::eigen, SoAAccessType::constAccess> {
template <typename T, byte_size_type alignment, bool restrictQualify>
struct SoAColumnAccessorsImpl<T, SoAColumnType::eigen, SoAAccessType::constAccess, alignment, restrictQualify> {
SOA_HOST_DEVICE SOA_INLINE SoAColumnAccessorsImpl(const SoAConstParametersImpl<SoAColumnType::eigen, T>& params)
: params_(params) {}
SOA_HOST_DEVICE SOA_INLINE const typename T::Scalar* operator()() const { return params_.addr_; }
using NoParamReturnType = typename T::Scalar*;
//SOA_HOST_DEVICE SOA_INLINE T operator()(size_type index) const { return params_.addr_[index]; }
SOA_HOST_DEVICE SOA_INLINE typename T::Scalar const* operator()() const { return params_.addr_; }
using NoParamReturnType = typename T::Scalar const*;
using ParamReturnType = typename SoAValue<SoAColumnType::eigen, T, alignment, restrictQualify>::CMapType;
SOA_HOST_DEVICE SOA_INLINE ParamReturnType operator()(size_type index) const {
return SoAConstValue<SoAColumnType::eigen, T, alignment, restrictQualify>(index, params_)();
}

private:
SoAConstParametersImpl<SoAColumnType::eigen, T> params_;
Expand All @@ -681,8 +675,15 @@ namespace cms::soa {
template <auto columnType>
struct ColumnType {
template <auto accessType>
struct AccessType : public SoAColumnAccessorsImpl<T, columnType, accessType> {
using SoAColumnAccessorsImpl<T, columnType, accessType>::SoAColumnAccessorsImpl;
struct AccessType {
template <auto alignment>
struct Alignment {
template <auto restrictQualify>
struct RestrictQualifier
: public SoAColumnAccessorsImpl<T, columnType, accessType, alignment, restrictQualify> {
using SoAColumnAccessorsImpl<T, columnType, accessType, alignment, restrictQualify>::SoAColumnAccessorsImpl;
};
};
};
};
};
Expand Down
11 changes: 0 additions & 11 deletions DataFormats/SoATemplate/interface/SoALayout.h
Expand Up @@ -581,17 +581,6 @@
throw std::runtime_error("In " #CLASS "::" #CLASS ": unexpected end pointer."); \
} \
\
/* Range checker conditional to the macro _DO_RANGECHECK */ \
SOA_HOST_DEVICE SOA_INLINE \
void rangeCheck(size_type index) const { \
if constexpr (_DO_RANGECHECK) { \
if (index >= elements_) { \
printf("In " #CLASS "::rangeCheck(): index out of range: %zu with elements: %zu\n", index, elements_); \
assert(false); \
} \
} \
} \
\
/* Data members */ \
std::byte* mem_; \
size_type elements_; \
Expand Down