|
| 1 | +/* |
| 2 | + * Definitions of SoA common parameters for SoA class generators |
| 3 | + */ |
| 4 | + |
| 5 | +#ifndef DataStructures_SoACommon_h |
| 6 | +#define DataStructures_SoACommon_h |
| 7 | + |
| 8 | +#include "boost/preprocessor.hpp" |
| 9 | +#include <Eigen/Core> |
| 10 | + |
| 11 | +// CUDA attributes |
| 12 | +#ifdef __CUDACC__ |
| 13 | +#define SOA_HOST_ONLY __host__ |
| 14 | +#define SOA_DEVICE_ONLY __device__ |
| 15 | +#define SOA_HOST_DEVICE __host__ __device__ |
| 16 | +#define SOA_HOST_DEVICE_INLINE __host__ __device__ __forceinline__ |
| 17 | +#define SOA_DEVICE_RESTRICT __restrict__ |
| 18 | +#else |
| 19 | +#define SOA_HOST_ONLY |
| 20 | +#define SOA_DEVICE_ONLY |
| 21 | +#define SOA_HOST_DEVICE |
| 22 | +#define SOA_HOST_DEVICE_INLINE inline |
| 23 | +#define SOA_DEVICE_RESTRICT |
| 24 | +#endif |
| 25 | + |
| 26 | +#if defined(__CUDACC__) && defined(__CUDA_ARCH__) |
| 27 | +// Read a pointer content via read-only (non coherent) cache. |
| 28 | +#define LOAD_INCOHERENT(A) __ldg(A) |
| 29 | +#define LOAD_STREAMED(A) __ldcs(A) |
| 30 | +#define STORE_STREAMED(A, V) __stcs(A, V) |
| 31 | +#else |
| 32 | +#define LOAD_INCOHERENT(A) *(A) |
| 33 | +#define LOAD_STREAMED(A) *(A) |
| 34 | +#define STORE_STREAMED(A, V) *(A) = (V) |
| 35 | +#endif |
| 36 | + |
| 37 | +// compile-time sized SoA |
| 38 | + |
| 39 | +// Helper template managing the value within it column |
| 40 | +template<typename T> |
| 41 | +class SoAValue { |
| 42 | +public: |
| 43 | + SOA_HOST_DEVICE_INLINE SoAValue(size_t i, T * col): idx_(i), col_(col) {} |
| 44 | + /* SOA_HOST_DEVICE_INLINE operator T&() { return col_[idx_]; } */ |
| 45 | + SOA_HOST_DEVICE_INLINE T& operator() () { return col_[idx_]; } |
| 46 | + SOA_HOST_DEVICE_INLINE T operator() () const { return *(col_ + idx_); } |
| 47 | + SOA_HOST_DEVICE_INLINE T* operator& () { return &col_[idx_]; } |
| 48 | + SOA_HOST_DEVICE_INLINE const T* operator& () const { return &col_[idx_]; } |
| 49 | + template <typename T2> |
| 50 | + SOA_HOST_DEVICE_INLINE T& operator= (const T2& v) { return col_[idx_] = v; } |
| 51 | + typedef T valueType; |
| 52 | + static constexpr auto valueSize = sizeof(T); |
| 53 | +private: |
| 54 | + size_t idx_; |
| 55 | + T *col_; |
| 56 | +}; |
| 57 | + |
| 58 | +// Helper template managing the value within it column |
| 59 | +template<typename T> |
| 60 | +class SoAConstValue { |
| 61 | +public: |
| 62 | + SOA_HOST_DEVICE_INLINE SoAConstValue(size_t i, const T * col): idx_(i), col_(col) {} |
| 63 | + /* SOA_HOST_DEVICE_INLINE operator T&() { return col_[idx_]; } */ |
| 64 | + SOA_HOST_DEVICE_INLINE T operator() () const { return *(col_ + idx_); } |
| 65 | + SOA_HOST_DEVICE_INLINE const T* operator& () const { return &col_[idx_]; } |
| 66 | + typedef T valueType; |
| 67 | + static constexpr auto valueSize = sizeof(T); |
| 68 | +private: |
| 69 | + size_t idx_; |
| 70 | + const T *col_; |
| 71 | +}; |
| 72 | + |
| 73 | + |
| 74 | +// Helper template managing the value within it column |
| 75 | +template<class C> |
| 76 | +class SoAEigenValue { |
| 77 | +public: |
| 78 | + typedef C Type; |
| 79 | + typedef Eigen::Map<C, 0, Eigen::InnerStride<Eigen::Dynamic>> MapType; |
| 80 | + typedef Eigen::Map<const C, 0, Eigen::InnerStride<Eigen::Dynamic>> CMapType; |
| 81 | + SOA_HOST_DEVICE_INLINE SoAEigenValue(size_t i, typename C::Scalar * col, size_t stride): |
| 82 | + val_(col + i, C::RowsAtCompileTime, C::ColsAtCompileTime, |
| 83 | + Eigen::InnerStride<Eigen::Dynamic>(stride)), |
| 84 | + crCol_(col), |
| 85 | + cVal_(crCol_ + i, C::RowsAtCompileTime, C::ColsAtCompileTime, |
| 86 | + Eigen::InnerStride<Eigen::Dynamic>(stride)), |
| 87 | + stride_(stride) {} |
| 88 | + SOA_HOST_DEVICE_INLINE MapType& operator() () { return val_; } |
| 89 | + SOA_HOST_DEVICE_INLINE const CMapType& operator() () const { return cVal_; } |
| 90 | + SOA_HOST_DEVICE_INLINE operator C() { return val_; } |
| 91 | + SOA_HOST_DEVICE_INLINE operator const C() const { return cVal_; } |
| 92 | + SOA_HOST_DEVICE_INLINE C* operator& () { return &val_; } |
| 93 | + SOA_HOST_DEVICE_INLINE const C* operator& () const { return &cVal_; } |
| 94 | + template <class C2> |
| 95 | + SOA_HOST_DEVICE_INLINE MapType& operator= (const C2& v) { return val_ = v; } |
| 96 | + typedef typename C::Scalar ValueType; |
| 97 | + static constexpr auto valueSize = sizeof(C::Scalar); |
| 98 | + SOA_HOST_DEVICE_INLINE size_t stride() { return stride_; } |
| 99 | + template<typename OtherDerived> |
| 100 | + typename Eigen::MatrixBase<C>::template cross_product_return_type<OtherDerived>::type |
| 101 | + SOA_HOST_DEVICE_INLINE cross(const Eigen::MatrixBase<OtherDerived>& other) const { return cVal_.cross(other); } |
| 102 | + |
| 103 | + template<typename OtherType> |
| 104 | + typename Eigen::MatrixBase<C>::template cross_product_return_type<typename OtherType::MapType>::type |
| 105 | + SOA_HOST_DEVICE_INLINE cross(const OtherType& other) const { return cVal_.cross(other.cVal_); } |
| 106 | + |
| 107 | +private: |
| 108 | + MapType val_; |
| 109 | + const typename C::Scalar * __restrict__ crCol_; |
| 110 | + CMapType cVal_; |
| 111 | + size_t stride_; |
| 112 | +}; |
| 113 | + |
| 114 | +// Helper template to avoid commas in macro |
| 115 | +template<class C> |
| 116 | +struct EigenConstMapMaker { |
| 117 | + typedef Eigen::Map<const C, 0, Eigen::InnerStride<Eigen::Dynamic>> Type; |
| 118 | + class DataHolder { |
| 119 | + public: |
| 120 | + DataHolder(const typename C::Scalar * data): data_(data) {} |
| 121 | + EigenConstMapMaker::Type withStride(size_t stride) { |
| 122 | + return EigenConstMapMaker::Type(data_, C::RowsAtCompileTime, C::ColsAtCompileTime, |
| 123 | + Eigen::InnerStride<Eigen::Dynamic>(stride)); |
| 124 | + } |
| 125 | + private: |
| 126 | + const typename C::Scalar * const data_; |
| 127 | + }; |
| 128 | + static DataHolder withData(const typename C::Scalar * data) { |
| 129 | + return DataHolder(data); |
| 130 | + } |
| 131 | +}; |
| 132 | + |
| 133 | +// Helper function to compute aligned size |
| 134 | +inline size_t alignSize(size_t size, size_t alignment = 128) { |
| 135 | + if (size) |
| 136 | + return ((size - 1) / alignment + 1) * alignment; |
| 137 | + else |
| 138 | + return 0; |
| 139 | +} |
| 140 | + |
| 141 | +/* declare "scalars" (one value shared across the whole SoA) and "columns" (one value per element) */ |
| 142 | +#define _VALUE_TYPE_SCALAR 0 |
| 143 | +#define _VALUE_TYPE_COLUMN 1 |
| 144 | +#define _VALUE_TYPE_EIGEN_COLUMN 2 |
| 145 | + |
| 146 | +enum class SoAColumnType { |
| 147 | + scalar = _VALUE_TYPE_SCALAR, |
| 148 | + column = _VALUE_TYPE_COLUMN, |
| 149 | + eigen = _VALUE_TYPE_EIGEN_COLUMN |
| 150 | +}; |
| 151 | + |
| 152 | +#define SoA_scalar(TYPE, NAME) (_VALUE_TYPE_SCALAR, TYPE, NAME) |
| 153 | +#define SoA_column(TYPE, NAME) (_VALUE_TYPE_COLUMN, TYPE, NAME) |
| 154 | +#define SoA_eigenColumn(TYPE, NAME) (_VALUE_TYPE_EIGEN_COLUMN, TYPE, NAME) |
| 155 | + |
| 156 | +/* Iterate on the macro MACRO and return the result as a comma separated list */ |
| 157 | +#define _ITERATE_ON_ALL_COMMA(MACRO, DATA, ...) \ |
| 158 | + BOOST_PP_TUPLE_ENUM( \ |
| 159 | + BOOST_PP_SEQ_TO_TUPLE( \ |
| 160 | + _ITERATE_ON_ALL(MACRO, DATA, __VA_ARGS__) \ |
| 161 | + ) \ |
| 162 | + ) |
| 163 | +/* Iterate MACRO on all elements */ |
| 164 | +#define _ITERATE_ON_ALL(MACRO, DATA, ...) \ |
| 165 | + BOOST_PP_SEQ_FOR_EACH(MACRO, DATA, \ |
| 166 | + BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \ |
| 167 | + ) |
| 168 | + |
| 169 | +/* Switch on macros depending on scalar / column type */ |
| 170 | +#define _SWITCH_ON_TYPE(VALUE_TYPE, IF_SCALAR, IF_COLUMN, IF_EIGEN_COLUMN) \ |
| 171 | + BOOST_PP_IF(BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_SCALAR), \ |
| 172 | + IF_SCALAR, \ |
| 173 | + BOOST_PP_IF(BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_COLUMN), \ |
| 174 | + IF_COLUMN, \ |
| 175 | + BOOST_PP_IF(BOOST_PP_EQUAL(VALUE_TYPE, _VALUE_TYPE_EIGEN_COLUMN), \ |
| 176 | + IF_EIGEN_COLUMN, \ |
| 177 | + BOOST_PP_EMPTY() \ |
| 178 | + ) \ |
| 179 | + ) \ |
| 180 | + ) |
| 181 | + |
| 182 | +#endif // ndef DataStructures_SoACommon_h |
| 183 | + |
0 commit comments