From 16ab933ab8a2ad8cf0c9c46907afbca71e9f3468 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen <pauli.t.virtanen@jyu.fi> Date: Wed, 3 Aug 2022 17:22:23 +0300 Subject: [PATCH] array: deal with alignment --- src/array.hpp | 36 ++++++++++++++++++++++++++++++++++-- src/main.cpp | 2 +- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/array.hpp b/src/array.hpp index 6d7e763..1ed483f 100644 --- a/src/array.hpp +++ b/src/array.hpp @@ -181,7 +181,7 @@ namespace detail /*! Simple data-by-reference strided array class a la Fortran */ -template <typename Scalar, typename Shape> +template <typename Scalar, typename Shape, size_t Alignment=0> class Array : public std::conditional_t<Shape::fixed, detail::fixed_base<Shape>, detail::dynamic_base<Shape> > { private: @@ -196,12 +196,28 @@ private: return (n == Dynamic) ? Eigen::Dynamic : n; } + static constexpr int eigen_alignment() + { + switch (alignment()) { + case 128: return Eigen::Aligned128; + case 64: return Eigen::Aligned64; + case 32: return Eigen::Aligned32; + case 16: return Eigen::Aligned16; + case 8: return Eigen::Aligned8; + default: return Eigen::Unaligned; + } + }; + public: Array(Scalar *data, size_t size, const std::array<size_t, Shape::ndim> shape) : Base(shape), data_(data) { static_assert(!Shape::fixed, "array shape must not be compile-time fixed"); Base::data_bounds_check(size); +#ifndef NO_BOUNDS_CHECK + if (reinterpret_cast<intptr_t>(data) % alignment() != 0) + throw std::runtime_error("data is not aligned"); +#endif } Array(Scalar *data, size_t size) @@ -209,6 +225,10 @@ public: { static_assert(Shape::fixed, "array shape must be compile-time fixed"); Base::data_bounds_check(size); +#ifndef NO_BOUNDS_CHECK + if (reinterpret_cast<intptr_t>(data) % alignment() != 0) + throw std::runtime_error("data is not aligned"); +#endif } template <typename... Idx> @@ -229,6 +249,18 @@ public: Scalar* data() { return data_; } + static constexpr int alignment() + { + if (Alignment > 0) + return Alignment; + else if (sizeof(Scalar) % 16 == 0) + return 16; + else if (sizeof(Scalar) % 8 == 0) + return 8; + else + return 1; + }; + template <typename... Idx> size_t index(Idx... idxs) const { @@ -281,7 +313,7 @@ public: } typedef Eigen::Matrix<Scalar, eigen_shape<0>(), eigen_shape<1>(), Eigen::RowMajor> EigenMatrix; - typedef Eigen::Map<EigenMatrix> EigenMap; + typedef Eigen::Map<EigenMatrix, eigen_alignment()> EigenMap; EigenMap matrix() const { diff --git a/src/main.cpp b/src/main.cpp index fdd5ad9..199216d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,7 +38,7 @@ int main() mat = mat * mat * mat; - static_assert(std::is_same<decltype(mat), Eigen::Map<Eigen::Matrix<double, 2, 2, Eigen::RowMajor> > >::value, "wrong type"); + static_assert(std::is_same<decltype(mat), Eigen::Map<Eigen::Matrix<double, 2, 2, Eigen::RowMajor>, Eigen::Aligned8 > >::value, "wrong type"); dump(Q0); return 0; -- GitLab