From f905d91e941479e841c98fe33ac2ca61574e7278 Mon Sep 17 00:00:00 2001 From: Simeon Ehrig Date: Thu, 27 Jan 2022 13:05:10 +0000 Subject: [PATCH 1/5] Rename Iterator to Memory Access Strategy - rename was necessary to avoid confusions with fancy iterator - rename and flat namespace of the mem access strategy - move related files to new folder --- include/vikunja/access/BaseStrategy.hpp | 127 +++++++ .../access/PolicyBasedBlockStrategy.hpp | 317 +++++++++++++++++ include/vikunja/mem/iterator/BaseIterator.hpp | 135 -------- .../mem/iterator/PolicyBasedBlockIterator.hpp | 326 ------------------ .../reduce/detail/BlockThreadReduceKernel.hpp | 6 +- include/vikunja/reduce/reduce.hpp | 16 +- .../detail/BlockThreadTransformKernel.hpp | 24 +- include/vikunja/transform/transform.hpp | 16 +- test/include/vikunja/test/utility.hpp | 6 +- test/unit/iterator/src/Iterator.cpp | 22 +- 10 files changed, 492 insertions(+), 503 deletions(-) create mode 100644 include/vikunja/access/BaseStrategy.hpp create mode 100644 include/vikunja/access/PolicyBasedBlockStrategy.hpp delete mode 100644 include/vikunja/mem/iterator/BaseIterator.hpp delete mode 100644 include/vikunja/mem/iterator/PolicyBasedBlockIterator.hpp diff --git a/include/vikunja/access/BaseStrategy.hpp b/include/vikunja/access/BaseStrategy.hpp new file mode 100644 index 0000000..9efc18c --- /dev/null +++ b/include/vikunja/access/BaseStrategy.hpp @@ -0,0 +1,127 @@ +/* Copyright 2022 Hauke Mewes, Jonas Schenke, Simeon Ehrig + * + * This file is part of vikunja. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +namespace vikunja::MemAccess +{ + //! An iterator base class. + //! + //! \tparam T The type. + //! \tparam TIterator The iterator type (standard is T*) + template + class BaseStrategy + { + protected: + TIterator const mData; // The underlying iterator must be const as we pass it by ref + uint64_t mIndex; + const uint64_t mMaximum; + + public: + //----------------------------------------------------------------------------- + //! Constructor. + //! + //! \param data A pointer to the data. + //! \param index The index. + //! \param maximum The first index outside of the iterator memory. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseStrategy(TIterator const& data, uint64_t index, uint64_t maximum) + : mData(data) + , mIndex(index) + , mMaximum(maximum) + { + } + + //----------------------------------------------------------------------------- + //! Constructor. + //! + //! \param other The other iterator object. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseStrategy(const BaseStrategy& other) = default; + + //----------------------------------------------------------------------------- + //! Compare operator. + //! + //! \param other The other object. + //! + //! Returns true if objects are equal and false otherwise. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator==(const BaseStrategy& other) const -> bool + { + return (this->mData == other.mData) && (this->mIndex == other.mIndex) + && (this->mMaximum == other.mMaximum); + } + + //----------------------------------------------------------------------------- + //! Compare operator. + //! + //! \param other The other object. + //! + //! Returns false if objects are equal and true otherwise. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator!=(const BaseStrategy& other) const -> bool + { + return !operator==(other); + } + + //----------------------------------------------------------------------------- + //! Compare operator. + //! + //! \param other The other object. + //! + //! Returns false if the other object is equal or smaller and true + //! otherwise. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<(const BaseStrategy& other) const -> bool + { + return mIndex < other.mIndex; + } + + //----------------------------------------------------------------------------- + //! Compare operator. + //! + //! \param other The other object. + //! + //! Returns false if the other object is equal or bigger and true otherwise. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>(const BaseStrategy& other) const -> bool + { + return mIndex > other.mIndex; + } + + //----------------------------------------------------------------------------- + //! Compare operator. + //! + //! \param other The other object. + //! + //! Returns true if the other object is equal or bigger and false otherwise. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<=(const BaseStrategy& other) const -> bool + { + return mIndex <= other.mIndex; + } + + //----------------------------------------------------------------------------- + //! Compare operator. + //! + //! \param other The other object. + //! + //! Returns true if the other object is equal or smaller and false + //! otherwise. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>=(const BaseStrategy& other) const -> bool + { + return mIndex >= other.mIndex; + } + + //----------------------------------------------------------------------------- + //! Returns the current element. + //! + //! Returns a reference to the current index. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator*() -> decltype(*(mData + mIndex))& + { + return *(mData + mIndex); + } + }; + +} // namespace vikunja::MemAccess diff --git a/include/vikunja/access/PolicyBasedBlockStrategy.hpp b/include/vikunja/access/PolicyBasedBlockStrategy.hpp new file mode 100644 index 0000000..ab4418a --- /dev/null +++ b/include/vikunja/access/PolicyBasedBlockStrategy.hpp @@ -0,0 +1,317 @@ +/* Copyright 2022 Hauke Mewes, Simeon Ehrig + * + * This file is part of vikunja. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "BaseStrategy.hpp" + +#include + +namespace vikunja::MemAccess +{ + /** + * A policy based iterator that splits the data into chunks. Depending on the memory access policy, + * these chunks can access the data sequential or in a striding pattern. + * @tparam MemAccessPolicy The memory access policy to use. + * @tparam TAcc The alpaka accelerator type. + * @tparam TIterator The underlying iterator. + * + * The memory access policy should provide three values: + * - The startIndex of the iterator, which is the first index to use. + * - The endIndex of the iterator, which is the last index to use. + * - The stepSize of the iterator, which tells how far the iterator should move. + */ + template + class PolicyBasedBlockStrategy : public BaseStrategy + { + private: + uint64_t mStep; /**< The step size of this iterator. */ + public: + /** + * Create a policy based block iterator + * @param data The data to iterate over. + * @param acc The accelerator type to use. + * @param problemSize The size of the original iterator. + * @param blockSize The size of the blocks. + */ + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE + PolicyBasedBlockStrategy(TIterator const& data, TAcc const& acc, uint64_t problemSize, uint64_t blockSize) + : BaseStrategy( + data, + MemAccessPolicy::getStartIndex(acc, problemSize, blockSize), + MemAccessPolicy::getEndIndex(acc, problemSize, blockSize)) + , mStep(MemAccessPolicy::getStepSize(acc, problemSize, blockSize)) + { + } + + /** + * Default copy constructor. + * @param other To be copied. + */ + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE PolicyBasedBlockStrategy(const PolicyBasedBlockStrategy& other) = default; + + //----------------------------------------------------------------------------- + //! Returns the iterator for the last item. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> PolicyBasedBlockStrategy + { + PolicyBasedBlockStrategy ret(*this); + ret.mIndex = this->mMaximum; + return ret; + } + + //----------------------------------------------------------------------------- + //! Increments the internal pointer to the next one and returns this + //! element. + //! + //! Returns a reference to the next index. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> PolicyBasedBlockStrategy& + { + this->mIndex += this->mStep; + return *this; + } + + //----------------------------------------------------------------------------- + //! Returns the current element and increments the internal pointer to the + //! next one. + //! + //! Returns a reference to the current index. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> PolicyBasedBlockStrategy + { + auto ret(*this); + this->mIndex += this->mStep; + return ret; + } + + //----------------------------------------------------------------------------- + //! Decrements the internal pointer to the previous one and returns the this + //! element. + //! + //! Returns a reference to the previous index. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> PolicyBasedBlockStrategy& + { + this->mIndex -= this->mStep; + return *this; + } + + //----------------------------------------------------------------------------- + //! Returns the current element and decrements the internal pointer to the + //! previous one. + //! + //! Returns a reference to the current index. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> PolicyBasedBlockStrategy + { + auto ret(*this); + this->mIndex -= this->mStep; + return ret; + } + + //----------------------------------------------------------------------------- + //! Returns the index + a supplied offset. + //! + //! \param n The offset. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const -> PolicyBasedBlockStrategy + { + auto ret(*this); + ret.mIndex += n * mStep; + return ret; + } + + //----------------------------------------------------------------------------- + //! Returns the index - a supplied offset. + //! + //! \param n The offset. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const -> PolicyBasedBlockStrategy + { + auto ret(*this); + ret.mIndex -= n * mStep; + return ret; + } + + //----------------------------------------------------------------------------- + //! Addition assignment. + //! + //! \param offset The offset. + //! + //! Returns the current object offset by the offset. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset) -> PolicyBasedBlockStrategy& + { + this->mIndex += offset * this->mStep; + return *this; + } + + //----------------------------------------------------------------------------- + //! Substraction assignment. + //! + //! \param offset The offset. + //! + //! Returns the current object offset by the offset. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset) -> PolicyBasedBlockStrategy& + { + this->mIndex -= offset * this->mStep; + return *this; + } + }; + + namespace policies + { + /** + * A memory policy for the PolicyBlockBasedIterator that provides grid striding memory access. + */ + struct GridStridingMemAccessPolicy + { + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStartIndex( + TAcc const& acc, + TIdx const& problemSize __attribute__((unused)), + TIdx const& blockSize __attribute__((unused))) -> TIdx const + { + constexpr TIdx xIndex = alpaka::Dim::value - 1u; + return alpaka::getIdx(acc)[xIndex]; + } + + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getEndIndex( + TAcc const& acc, + TIdx const& problemSize, + TIdx const& blockSize __attribute__((unused))) -> TIdx const + { + return problemSize; + } + + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStepSize( + TAcc const& acc, + TIdx const& problemSize __attribute__((unused)), + TIdx const& blockSize) -> TIdx const + { + constexpr TIdx xIndex = alpaka::Dim::value - 1u; + auto gridDimension = alpaka::getWorkDiv(acc)[xIndex]; + return gridDimension * blockSize; + } + + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto isValidThreadResult( + TAcc const& acc, + TIdx const& problemSize, + TIdx const& blockSize __attribute__((unused))) -> bool const + { + constexpr TIdx xIndex = alpaka::Dim::value - 1u; + auto threadIndex = (alpaka::getIdx(acc)[xIndex]); + return threadIndex < problemSize; + } + + static constexpr bool isThreadOrderCompliant = true; + + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto getName() -> char* + { + return const_cast("GridStridingMemAccessPolicy"); + } + }; + + /** + * A memory access policy for the PolicyBlockBasedIterator that provides linear memory access. + */ + struct LinearMemAccessPolicy + { + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStartIndex( + TAcc const& acc, + TIdx const& problemSize, + TIdx const& blockSize) -> TIdx const + { + constexpr TIdx xIndex = alpaka::Dim::value - 1u; + auto gridDimension = alpaka::getWorkDiv(acc)[xIndex]; + auto indexInBlock = alpaka::getIdx(acc)[xIndex]; + auto gridSize = gridDimension * blockSize; + // TODO: catch overflow + return (problemSize * indexInBlock) / gridSize; + } + + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getEndIndex( + TAcc const& acc, + TIdx const& problemSize, + TIdx const& blockSize) -> TIdx const + { + constexpr TIdx xIndex = alpaka::Dim::value - 1u; + auto gridDimension = alpaka::getWorkDiv(acc)[xIndex]; + auto indexInBlock = alpaka::getIdx(acc)[xIndex]; + auto gridSize = gridDimension * blockSize; + // TODO: catch overflow + return (problemSize * indexInBlock + problemSize) / gridSize; + } + + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto getStepSize( + TAcc const& acc __attribute__((unused)), + TIdx const& problemSize __attribute__((unused)), + TIdx const& blockSize __attribute__((unused))) -> TIdx const + { + return 1; + } + + template + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto isValidThreadResult( + TAcc const& acc __attribute__((unused)), + TIdx const& problemSize __attribute__((unused)), + TIdx const& blockSize __attribute__((unused))) -> bool const + { + return true; + } + + static constexpr bool isThreadOrderCompliant = false; + + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto getName() -> char* + { + return const_cast("LinearMemAccessPolicy"); + } + }; + } // namespace policies + + namespace traits + { + /** + * The memory access policy getter trait by platform. + * @tparam TAcc The platform type. + * @tparam TSfinae + */ + template + struct GetMemAccessPolicyByPltf + { + }; + + /** + * On cpu, default memory access is linear. + */ + template<> + struct GetMemAccessPolicyByPltf + { + using type = policies::LinearMemAccessPolicy; + }; + +#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) || defined(ALPAKA_ACC_GPU_HIP_ENABLED) + /** + * On cuda, default memory access is grid striding. + */ + template<> + struct GetMemAccessPolicyByPltf + { + using type = policies::GridStridingMemAccessPolicy; + }; +#endif // (ALPAKA_ACC_GPU_CUDA_ENABLED) || defined(ALPAKA_ACC_GPU_HIP_ENABLED) + + } // namespace traits + + /** + * Shortcut to derive memory access policy from accelerator. + */ + template + using MemAccessPolicy = typename traits::GetMemAccessPolicyByPltf>>::type; + +} // namespace vikunja::MemAccess diff --git a/include/vikunja/mem/iterator/BaseIterator.hpp b/include/vikunja/mem/iterator/BaseIterator.hpp deleted file mode 100644 index 1a4a1d3..0000000 --- a/include/vikunja/mem/iterator/BaseIterator.hpp +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright 2021 Hauke Mewes, Jonas Schenke - * - * This file is part of vikunja. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include - -namespace vikunja -{ - namespace mem - { - namespace iterator - { - // TODO: this class is from Jonas Schenke - - //! An iterator base class. - //! - //! \tparam T The type. - //! \tparam TIterator The iterator type (standard is T*) - template - class BaseIterator - { - protected: - TIterator const mData; // The underlying iterator must be const as we pass it by ref - uint64_t mIndex; - const uint64_t mMaximum; - - public: - //----------------------------------------------------------------------------- - //! Constructor. - //! - //! \param data A pointer to the data. - //! \param index The index. - //! \param maximum The first index outside of the iterator memory. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE - BaseIterator(TIterator const& data, uint64_t index, uint64_t maximum) - : mData(data) - , mIndex(index) - , mMaximum(maximum) - { - } - - //----------------------------------------------------------------------------- - //! Constructor. - //! - //! \param other The other iterator object. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseIterator(const BaseIterator& other) = default; - - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns true if objects are equal and false otherwise. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator==(const BaseIterator& other) const -> bool - { - return (this->mData == other.mData) && (this->mIndex == other.mIndex) - && (this->mMaximum == other.mMaximum); - } - - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns false if objects are equal and true otherwise. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator!=(const BaseIterator& other) const -> bool - { - return !operator==(other); - } - - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns false if the other object is equal or smaller and true - //! otherwise. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<(const BaseIterator& other) const -> bool - { - return mIndex < other.mIndex; - } - - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns false if the other object is equal or bigger and true otherwise. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>(const BaseIterator& other) const -> bool - { - return mIndex > other.mIndex; - } - - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns true if the other object is equal or bigger and false otherwise. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<=(const BaseIterator& other) const -> bool - { - return mIndex <= other.mIndex; - } - - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns true if the other object is equal or smaller and false - //! otherwise. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>=(const BaseIterator& other) const -> bool - { - return mIndex >= other.mIndex; - } - - //----------------------------------------------------------------------------- - //! Returns the current element. - //! - //! Returns a reference to the current index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator*() -> decltype(*(mData + mIndex))& - { - return *(mData + mIndex); - } - }; - } // namespace iterator - } // namespace mem -} // namespace vikunja diff --git a/include/vikunja/mem/iterator/PolicyBasedBlockIterator.hpp b/include/vikunja/mem/iterator/PolicyBasedBlockIterator.hpp deleted file mode 100644 index 3e5f70b..0000000 --- a/include/vikunja/mem/iterator/PolicyBasedBlockIterator.hpp +++ /dev/null @@ -1,326 +0,0 @@ -/* Copyright 2021 Hauke Mewes - * - * This file is part of vikunja. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include "BaseIterator.hpp" - -#include - -namespace vikunja -{ - namespace mem - { - namespace iterator - { - /** - * A policy based iterator that splits the data into chunks. Depending on the memory access policy, - * these chunks can access the data sequential or in a striding pattern. - * @tparam MemAccessPolicy The memory access policy to use. - * @tparam TAcc The alpaka accelerator type. - * @tparam TIterator The underlying iterator. - * - * The memory access policy should provide three values: - * - The startIndex of the iterator, which is the first index to use. - * - The endIndex of the iterator, which is the last index to use. - * - The stepSize of the iterator, which tells how far the iterator should move. - */ - template - class PolicyBasedBlockIterator : public BaseIterator - { - private: - uint64_t mStep; /**< The step size of this iterator. */ - public: - /** - * Create a policy based block iterator - * @param data The data to iterate over. - * @param acc The accelerator type to use. - * @param problemSize The size of the original iterator. - * @param blockSize The size of the blocks. - */ - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE PolicyBasedBlockIterator( - TIterator const& data, - TAcc const& acc, - uint64_t problemSize, - uint64_t blockSize) - : BaseIterator( - data, - MemAccessPolicy::getStartIndex(acc, problemSize, blockSize), - MemAccessPolicy::getEndIndex(acc, problemSize, blockSize)) - , mStep(MemAccessPolicy::getStepSize(acc, problemSize, blockSize)) - { - } - - /** - * Default copy constructor. - * @param other To be copied. - */ - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE PolicyBasedBlockIterator(const PolicyBasedBlockIterator& other) - = default; - - //----------------------------------------------------------------------------- - //! Returns the iterator for the last item. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> PolicyBasedBlockIterator - { - PolicyBasedBlockIterator ret(*this); - ret.mIndex = this->mMaximum; - return ret; - } - - //----------------------------------------------------------------------------- - //! Increments the internal pointer to the next one and returns this - //! element. - //! - //! Returns a reference to the next index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> PolicyBasedBlockIterator& - { - this->mIndex += this->mStep; - return *this; - } - - //----------------------------------------------------------------------------- - //! Returns the current element and increments the internal pointer to the - //! next one. - //! - //! Returns a reference to the current index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> PolicyBasedBlockIterator - { - auto ret(*this); - this->mIndex += this->mStep; - return ret; - } - - //----------------------------------------------------------------------------- - //! Decrements the internal pointer to the previous one and returns the this - //! element. - //! - //! Returns a reference to the previous index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> PolicyBasedBlockIterator& - { - this->mIndex -= this->mStep; - return *this; - } - - //----------------------------------------------------------------------------- - //! Returns the current element and decrements the internal pointer to the - //! previous one. - //! - //! Returns a reference to the current index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> PolicyBasedBlockIterator - { - auto ret(*this); - this->mIndex -= this->mStep; - return ret; - } - - //----------------------------------------------------------------------------- - //! Returns the index + a supplied offset. - //! - //! \param n The offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const -> PolicyBasedBlockIterator - { - auto ret(*this); - ret.mIndex += n * mStep; - return ret; - } - - //----------------------------------------------------------------------------- - //! Returns the index - a supplied offset. - //! - //! \param n The offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const -> PolicyBasedBlockIterator - { - auto ret(*this); - ret.mIndex -= n * mStep; - return ret; - } - - //----------------------------------------------------------------------------- - //! Addition assignment. - //! - //! \param offset The offset. - //! - //! Returns the current object offset by the offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset) -> PolicyBasedBlockIterator& - { - this->mIndex += offset * this->mStep; - return *this; - } - - //----------------------------------------------------------------------------- - //! Substraction assignment. - //! - //! \param offset The offset. - //! - //! Returns the current object offset by the offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset) -> PolicyBasedBlockIterator& - { - this->mIndex -= offset * this->mStep; - return *this; - } - }; - - namespace policies - { - /** - * A memory policy for the PolicyBlockBasedIterator that provides grid striding memory access. - */ - struct GridStridingMemAccessPolicy - { - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStartIndex( - TAcc const& acc, - TIdx const& problemSize __attribute__((unused)), - TIdx const& blockSize __attribute__((unused))) -> TIdx const - { - constexpr TIdx xIndex = alpaka::Dim::value - 1u; - return alpaka::getIdx(acc)[xIndex]; - } - - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getEndIndex( - TAcc const& acc, - TIdx const& problemSize, - TIdx const& blockSize __attribute__((unused))) -> TIdx const - { - return problemSize; - } - - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStepSize( - TAcc const& acc, - TIdx const& problemSize __attribute__((unused)), - TIdx const& blockSize) -> TIdx const - { - constexpr TIdx xIndex = alpaka::Dim::value - 1u; - auto gridDimension = alpaka::getWorkDiv(acc)[xIndex]; - return gridDimension * blockSize; - } - - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto isValidThreadResult( - TAcc const& acc, - TIdx const& problemSize, - TIdx const& blockSize __attribute__((unused))) -> bool const - { - constexpr TIdx xIndex = alpaka::Dim::value - 1u; - auto threadIndex = (alpaka::getIdx(acc)[xIndex]); - return threadIndex < problemSize; - } - - static constexpr bool isThreadOrderCompliant = true; - - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto getName() -> char* - { - return const_cast("GridStridingMemAccessPolicy"); - } - }; - - /** - * A memory access policy for the PolicyBlockBasedIterator that provides linear memory access. - */ - struct LinearMemAccessPolicy - { - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStartIndex( - TAcc const& acc, - TIdx const& problemSize, - TIdx const& blockSize) -> TIdx const - { - constexpr TIdx xIndex = alpaka::Dim::value - 1u; - auto gridDimension = alpaka::getWorkDiv(acc)[xIndex]; - auto indexInBlock = alpaka::getIdx(acc)[xIndex]; - auto gridSize = gridDimension * blockSize; - // TODO: catch overflow - return (problemSize * indexInBlock) / gridSize; - } - - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getEndIndex( - TAcc const& acc, - TIdx const& problemSize, - TIdx const& blockSize) -> TIdx const - { - constexpr TIdx xIndex = alpaka::Dim::value - 1u; - auto gridDimension = alpaka::getWorkDiv(acc)[xIndex]; - auto indexInBlock = alpaka::getIdx(acc)[xIndex]; - auto gridSize = gridDimension * blockSize; - // TODO: catch overflow - return (problemSize * indexInBlock + problemSize) / gridSize; - } - - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto getStepSize( - TAcc const& acc __attribute__((unused)), - TIdx const& problemSize __attribute__((unused)), - TIdx const& blockSize __attribute__((unused))) -> TIdx const - { - return 1; - } - - template - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto isValidThreadResult( - TAcc const& acc __attribute__((unused)), - TIdx const& problemSize __attribute__((unused)), - TIdx const& blockSize __attribute__((unused))) -> bool const - { - return true; - } - - static constexpr bool isThreadOrderCompliant = false; - - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto getName() -> char* - { - return const_cast("LinearMemAccessPolicy"); - } - }; - } // namespace policies - - namespace traits - { - /** - * The memory access policy getter trait by platform. - * @tparam TAcc The platform type. - * @tparam TSfinae - */ - template - struct GetMemAccessPolicyByPltf - { - }; - - /** - * On cpu, default memory access is linear. - */ - template<> - struct GetMemAccessPolicyByPltf - { - using type = policies::LinearMemAccessPolicy; - }; - -#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) || defined(ALPAKA_ACC_GPU_HIP_ENABLED) - /** - * On cuda, default memory access is grid striding. - */ - template<> - struct GetMemAccessPolicyByPltf - { - using type = policies::GridStridingMemAccessPolicy; - }; -#endif // (ALPAKA_ACC_GPU_CUDA_ENABLED) || defined(ALPAKA_ACC_GPU_HIP_ENABLED) - - } // namespace traits - - /** - * Shortcut to derive memory access policy from accelerator. - */ - template - using MemAccessPolicy = typename traits::GetMemAccessPolicyByPltf>>::type; - } // namespace iterator - } // namespace mem -} // namespace vikunja diff --git a/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp b/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp index cafbb89..dde2c77 100644 --- a/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp +++ b/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp @@ -1,4 +1,4 @@ -/* Copyright 2021 Hauke Mewes +/* Copyright 2022 Hauke Mewes, Simeon Ehrig * * This file is part of vikunja. * @@ -9,7 +9,7 @@ #pragma once -#include +#include #include @@ -104,7 +104,7 @@ namespace vikunja using MemPolicy = TMemAccessPolicy; // Create an iterator with the specified memory access policy that wraps the input iterator. - vikunja::mem::iterator::PolicyBasedBlockIterator iter( + vikunja::MemAccess::PolicyBasedBlockStrategy iter( source, acc, n, diff --git a/include/vikunja/reduce/reduce.hpp b/include/vikunja/reduce/reduce.hpp index 906ed43..6537116 100644 --- a/include/vikunja/reduce/reduce.hpp +++ b/include/vikunja/reduce/reduce.hpp @@ -1,4 +1,4 @@ -/* Copyright 2021 Hauke Mewes, Simeon Ehrig +/* Copyright 2022 Hauke Mewes, Simeon Ehrig * * This file is part of vikunja. * @@ -9,7 +9,7 @@ #pragma once -#include +#include #include #include #include @@ -54,7 +54,7 @@ namespace vikunja * @tparam WorkDivPolicy The working division policy. Defaults to a templated value depending on the * accelerator. For the API of this, see workdiv/BlockBasedWorkDiv.hpp * @tparam MemAccessPolicy The memory access policy. Defaults to a templated value depending on the - * accelerator. For the API of this, see mem/iterator/PolicyBasedBlockIterator + * accelerator. For the API of this, see vikunja::MemAccess::PolicyBasedBlockStrategy * @tparam TTransformFunc Type of the transform operator. * @tparam TReduceFunc Type of the reduce operator. * @tparam TInputIterator Type of the input iterator. Should be a pointer-like type. @@ -77,7 +77,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TTransformFunc, typename TReduceFunc, typename TInputIterator, @@ -219,7 +219,7 @@ namespace vikunja * @tparam WorkDivPolicy The working division policy. Defaults to a templated value depending on the * accelerator. For the API of this, see workdiv/BlockBasedWorkDiv.hpp * @tparam MemAccessPolicy The memory access policy. Defaults to a templated value depending on the - * accelerator. For the API of this, see mem/iterator/PolicyBasedBlockIterator + * accelerator. For the API of this, see vikunja::MemAccess::PolicyBasedBlockStrategy * @tparam TTransformFunc Type of the transform operator. * @tparam TReduceFunc Type of the reduce operator. * @tparam TInputIterator Type of the input iterator. Should be a pointer-like type. @@ -241,7 +241,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TTransformFunc, typename TReduceFunc, typename TInputIterator, @@ -293,7 +293,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TFunc, typename TInputIterator, typename TDevAcc, @@ -352,7 +352,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TFunc, typename TInputIterator, typename TDevAcc, diff --git a/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp b/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp index 2760a13..70ab4cc 100644 --- a/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp +++ b/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp @@ -1,4 +1,4 @@ -/* Copyright 2021 Hauke Mewes +/* Copyright 2022 Hauke Mewes, Simeon Ehrig * * This file is part of vikunja. * @@ -9,7 +9,7 @@ #pragma once -#include +#include #include @@ -41,9 +41,12 @@ namespace vikunja TIdx const& n, TFunc const& func) const { - vikunja::mem::iterator::PolicyBasedBlockIterator - inputIterator(source, acc, n, TBlockSize); - vikunja::mem::iterator::PolicyBasedBlockIterator + vikunja::MemAccess::PolicyBasedBlockStrategy inputIterator( + source, + acc, + n, + TBlockSize); + vikunja::MemAccess::PolicyBasedBlockStrategy outputIterator(destination, acc, n, TBlockSize); while(inputIterator < inputIterator.end()) @@ -69,11 +72,14 @@ namespace vikunja TIdx const& n, TFunc const& func) const { - vikunja::mem::iterator::PolicyBasedBlockIterator - inputIterator(source, acc, n, TBlockSize); - vikunja::mem::iterator::PolicyBasedBlockIterator + vikunja::MemAccess::PolicyBasedBlockStrategy inputIterator( + source, + acc, + n, + TBlockSize); + vikunja::MemAccess::PolicyBasedBlockStrategy inputIteratorSecond(sourceSecond, acc, n, TBlockSize); - vikunja::mem::iterator::PolicyBasedBlockIterator + vikunja::MemAccess::PolicyBasedBlockStrategy outputIterator(destination, acc, n, TBlockSize); while(inputIterator < inputIterator.end()) diff --git a/include/vikunja/transform/transform.hpp b/include/vikunja/transform/transform.hpp index fb4eb66..2ead173 100644 --- a/include/vikunja/transform/transform.hpp +++ b/include/vikunja/transform/transform.hpp @@ -1,4 +1,4 @@ -/* Copyright 2021 Hauke Mewes, Simeon Ehrig +/* Copyright 2022 Hauke Mewes, Simeon Ehrig * * This file is part of vikunja. * @@ -9,7 +9,7 @@ #pragma once -#include +#include #include #include #include @@ -32,7 +32,7 @@ namespace vikunja * @tparam WorkDivPolicy The working division policy. Defaults to a templated value depending on the * accelerator. For the API of this, see workdiv/BlockBasedWorkDiv.hpp * @tparam MemAccessPolicy The memory access policy. Defaults to a templated value depending on the - * accelerator. For the API of this, see mem/iterator/PolicyBasedBlockIterator + * accelerator. For the API of this, see vikunja::MemAccess::PolicyBasedBlockStrategy * @tparam TFunc Type of the transform operator. * @tparam TInputIterator Type of the input iterator. Should be a pointer-like type. * @tparam TOutputIterator Type of the output iterator. Should be a pointer-like type. @@ -50,7 +50,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TFunc, typename TInputIterator, typename TOutputIterator, @@ -112,7 +112,7 @@ namespace vikunja * @tparam WorkDivPolicy The working division policy. Defaults to a templated value depending on the * accelerator. For the API of this, see workdiv/BlockBasedWorkDiv.hpp * @tparam MemAccessPolicy The memory access policy. Defaults to a templated value depending on the - * accelerator. For the API of this, see mem/iterator/PolicyBasedBlockIterator + * accelerator. For the API of this, see vikunja::MemAccess::PolicyBasedBlockStrategy * @tparam TFunc Type of the transform operator. * @tparam TInputIterator Type of the input iterator. Should be a pointer-like type. * @tparam TOutputIterator Type of the output iterator. Should be a pointer-like type. @@ -129,7 +129,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TFunc, typename TInputIterator, typename TOutputIterator, @@ -174,7 +174,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TFunc, typename TInputIterator, typename TInputIteratorSecond, @@ -254,7 +254,7 @@ namespace vikunja template< typename TAcc, typename WorkDivPolicy = vikunja::workdiv::BlockBasedPolicy, - typename MemAccessPolicy = vikunja::mem::iterator::MemAccessPolicy, + typename MemAccessPolicy = vikunja::MemAccess::MemAccessPolicy, typename TFunc, typename TInputIterator, typename TInputIteratorSecond, diff --git a/test/include/vikunja/test/utility.hpp b/test/include/vikunja/test/utility.hpp index d375cbd..b96936c 100644 --- a/test/include/vikunja/test/utility.hpp +++ b/test/include/vikunja/test/utility.hpp @@ -1,4 +1,4 @@ -/* Copyright 2021 Simeon Ehrig +/* Copyright 2022 Simeon Ehrig * * This file is part of vikunja. * @@ -9,7 +9,7 @@ #pragma once -#include +#include #include #include @@ -35,7 +35,7 @@ namespace vikunja using Acc = alpaka::ExampleDefaultAcc; strs << "Testing accelerator: " << alpaka::getAccName() << " with size: " << size << "\n"; - using MemAccess = vikunja::mem::iterator::MemAccessPolicy; + using MemAccess = vikunja::MemAccess::MemAccessPolicy; strs << "MemAccessPolicy: " << MemAccess::getName() << "\n"; return strs.str(); diff --git a/test/unit/iterator/src/Iterator.cpp b/test/unit/iterator/src/Iterator.cpp index c7e9a71..b69b1f4 100644 --- a/test/unit/iterator/src/Iterator.cpp +++ b/test/unit/iterator/src/Iterator.cpp @@ -1,4 +1,4 @@ -/* Copyright 2021 Hauke Mewes, Simeon Ehrig +/* Copyright 2022 Hauke Mewes, Simeon Ehrig * * This file is part of vikunja. * @@ -7,8 +7,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include -#include +#include +#include #include @@ -19,7 +19,7 @@ using Type = uint64_t; using IType = Type*; using Idx = std::size_t; -using namespace vikunja::mem::iterator; +using namespace vikunja::MemAccess; std::vector generateIndexVector(Idx size) { @@ -31,15 +31,15 @@ std::vector generateIndexVector(Idx size) return data; } -TEST_CASE("BaseIterator", "[iterator]") +TEST_CASE("BaseStrategy", "[iterator]") { constexpr Idx size = 64; std::vector testData{generateIndexVector(size)}; - BaseIterator zeroFirst(testData.data(), 0, size); - BaseIterator zeroSecond(testData.data(), 0, size); - BaseIterator one(testData.data(), 1, size); - BaseIterator copyOfZeroFirst(zeroFirst); + BaseStrategy zeroFirst(testData.data(), 0, size); + BaseStrategy zeroSecond(testData.data(), 0, size); + BaseStrategy one(testData.data(), 1, size); + BaseStrategy copyOfZeroFirst(zeroFirst); REQUIRE(zeroFirst == zeroSecond); @@ -68,7 +68,7 @@ struct TestPolicyBasedBlockIteratorKernel }; template<> -struct TestPolicyBasedBlockIteratorKernel +struct TestPolicyBasedBlockIteratorKernel { template ALPAKA_FN_ACC void operator()(TAcc const& acc, Type* data, TIdx const& n) const @@ -110,7 +110,7 @@ struct TestPolicyBasedBlockIterator } }; -TEST_CASE("PolicyBasedBlockIterator", "[iterator]") +TEST_CASE("PolicyBasedBlockStrategy", "[iterator]") { // constexpr Idx size = 64; From dbc5d3a1653c8ae930c643d192ade66c070d17ef Mon Sep 17 00:00:00 2001 From: Simeon Ehrig Date: Fri, 28 Jan 2022 21:30:28 +0000 Subject: [PATCH 2/5] Remove data member from the memory access strategy - now, the memory access strategy returns the index instead the actual data element --- include/vikunja/access/BaseStrategy.hpp | 86 ++++++------------- .../access/PolicyBasedBlockStrategy.hpp | 54 +++++------- .../reduce/detail/BlockThreadReduceKernel.hpp | 27 +++--- .../detail/BlockThreadTransformKernel.hpp | 33 ++----- test/unit/iterator/src/Iterator.cpp | 10 +-- 5 files changed, 70 insertions(+), 140 deletions(-) diff --git a/include/vikunja/access/BaseStrategy.hpp b/include/vikunja/access/BaseStrategy.hpp index 9efc18c..e8313eb 100644 --- a/include/vikunja/access/BaseStrategy.hpp +++ b/include/vikunja/access/BaseStrategy.hpp @@ -13,114 +13,76 @@ namespace vikunja::MemAccess { - //! An iterator base class. + //! Base class to implement memory access strategy. //! - //! \tparam T The type. - //! \tparam TIterator The iterator type (standard is T*) - template + //! \tparam TIdx Index type + template class BaseStrategy { protected: - TIterator const mData; // The underlying iterator must be const as we pass it by ref - uint64_t mIndex; - const uint64_t mMaximum; + TIdx m_index; + TIdx const m_maximum; public: //----------------------------------------------------------------------------- //! Constructor. //! - //! \param data A pointer to the data. //! \param index The index. //! \param maximum The first index outside of the iterator memory. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseStrategy(TIterator const& data, uint64_t index, uint64_t maximum) - : mData(data) - , mIndex(index) - , mMaximum(maximum) + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseStrategy(TIdx const index, TIdx const maximum) + : m_index(index) + , m_maximum(maximum) { } - //----------------------------------------------------------------------------- - //! Constructor. - //! - //! \param other The other iterator object. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseStrategy(const BaseStrategy& other) = default; - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns true if objects are equal and false otherwise. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator==(const BaseStrategy& other) const -> bool { - return (this->mData == other.mData) && (this->mIndex == other.mIndex) - && (this->mMaximum == other.mMaximum); + return (this->m_index == other.m_index) && (this->m_maximum == other.m_maximum); } - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns false if objects are equal and true otherwise. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator!=(const BaseStrategy& other) const -> bool { return !operator==(other); } - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns false if the other object is equal or smaller and true - //! otherwise. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<(const BaseStrategy& other) const -> bool { - return mIndex < other.mIndex; + return m_index < other.m_index; } - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns false if the other object is equal or bigger and true otherwise. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>(const BaseStrategy& other) const -> bool { - return mIndex > other.mIndex; + return m_index > other.m_index; } - //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. - //! - //! Returns true if the other object is equal or bigger and false otherwise. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<=(const BaseStrategy& other) const -> bool { - return mIndex <= other.mIndex; + return m_index <= other.m_index; + } + + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>=(const BaseStrategy& other) const -> bool + { + return m_index >= other.m_index; } //----------------------------------------------------------------------------- - //! Compare operator. - //! - //! \param other The other object. + //! Get the current index. //! - //! Returns true if the other object is equal or smaller and false - //! otherwise. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>=(const BaseStrategy& other) const -> bool + //! Returns a const reference to the current index. + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator*() const -> TIdx const& { - return mIndex >= other.mIndex; + return m_index; } //----------------------------------------------------------------------------- - //! Returns the current element. + //! Set the current index //! //! Returns a reference to the current index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator*() -> decltype(*(mData + mIndex))& + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator*() -> TIdx& { - return *(mData + mIndex); + return m_index; } }; diff --git a/include/vikunja/access/PolicyBasedBlockStrategy.hpp b/include/vikunja/access/PolicyBasedBlockStrategy.hpp index ab4418a..eff6efb 100644 --- a/include/vikunja/access/PolicyBasedBlockStrategy.hpp +++ b/include/vikunja/access/PolicyBasedBlockStrategy.hpp @@ -16,98 +16,90 @@ namespace vikunja::MemAccess { /** - * A policy based iterator that splits the data into chunks. Depending on the memory access policy, - * these chunks can access the data sequential or in a striding pattern. + * A policy based memory access strategy that splits the data access into chunks. Depending on the memory access + * policy, these chunks can access the data sequential or in a striding pattern. * @tparam MemAccessPolicy The memory access policy to use. * @tparam TAcc The alpaka accelerator type. - * @tparam TIterator The underlying iterator. + * @tparam TIdx The index type * * The memory access policy should provide three values: * - The startIndex of the iterator, which is the first index to use. * - The endIndex of the iterator, which is the last index to use. * - The stepSize of the iterator, which tells how far the iterator should move. */ - template - class PolicyBasedBlockStrategy : public BaseStrategy + template + class PolicyBasedBlockStrategy : public BaseStrategy { private: - uint64_t mStep; /**< The step size of this iterator. */ + TIdx m_step; /**< The step size of this iterator. */ public: /** * Create a policy based block iterator - * @param data The data to iterate over. * @param acc The accelerator type to use. * @param problemSize The size of the original iterator. * @param blockSize The size of the blocks. */ - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE - PolicyBasedBlockStrategy(TIterator const& data, TAcc const& acc, uint64_t problemSize, uint64_t blockSize) - : BaseStrategy( - data, + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE PolicyBasedBlockStrategy(TAcc const& acc, TIdx problemSize, TIdx blockSize) + : BaseStrategy( MemAccessPolicy::getStartIndex(acc, problemSize, blockSize), MemAccessPolicy::getEndIndex(acc, problemSize, blockSize)) - , mStep(MemAccessPolicy::getStepSize(acc, problemSize, blockSize)) + , m_step(MemAccessPolicy::getStepSize(acc, problemSize, blockSize)) { } - /** - * Default copy constructor. - * @param other To be copied. - */ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE PolicyBasedBlockStrategy(const PolicyBasedBlockStrategy& other) = default; //----------------------------------------------------------------------------- - //! Returns the iterator for the last item. + //! Returns a memory access object with the index set to the last item. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> PolicyBasedBlockStrategy { PolicyBasedBlockStrategy ret(*this); - ret.mIndex = this->mMaximum; + ret.m_index = this->m_maximum; return ret; } //----------------------------------------------------------------------------- - //! Increments the internal pointer to the next one and returns this - //! element. + //! Increments the internal index to the next one. //! //! Returns a reference to the next index. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> PolicyBasedBlockStrategy& { - this->mIndex += this->mStep; + this->m_index += this->m_step; return *this; } //----------------------------------------------------------------------------- - //! Returns the current element and increments the internal pointer to the + //! Returns the current index and increments the internal index to the //! next one. //! //! Returns a reference to the current index. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> PolicyBasedBlockStrategy { auto ret(*this); - this->mIndex += this->mStep; + this->m_index += this->m_step; return ret; } //----------------------------------------------------------------------------- - //! Decrements the internal pointer to the previous one and returns the this + //! Decrements the internal index to the previous one and returns the this //! element. //! //! Returns a reference to the previous index. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> PolicyBasedBlockStrategy& { - this->mIndex -= this->mStep; + this->m_index -= this->m_step; return *this; } //----------------------------------------------------------------------------- - //! Returns the current element and decrements the internal pointer to the + //! Returns the current index and decrements the internal pointer to the //! previous one. //! //! Returns a reference to the current index. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> PolicyBasedBlockStrategy { auto ret(*this); - this->mIndex -= this->mStep; + this->m_index -= this->m_step; return ret; } @@ -118,7 +110,7 @@ namespace vikunja::MemAccess ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const -> PolicyBasedBlockStrategy { auto ret(*this); - ret.mIndex += n * mStep; + ret.m_index += n * m_step; return ret; } @@ -129,7 +121,7 @@ namespace vikunja::MemAccess ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const -> PolicyBasedBlockStrategy { auto ret(*this); - ret.mIndex -= n * mStep; + ret.m_index -= n * m_step; return ret; } @@ -141,7 +133,7 @@ namespace vikunja::MemAccess //! Returns the current object offset by the offset. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset) -> PolicyBasedBlockStrategy& { - this->mIndex += offset * this->mStep; + this->m_index += offset * this->m_step; return *this; } @@ -153,7 +145,7 @@ namespace vikunja::MemAccess //! Returns the current object offset by the offset. ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset) -> PolicyBasedBlockStrategy& { - this->mIndex -= offset * this->mStep; + this->m_index -= offset * this->m_step; return *this; } }; diff --git a/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp b/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp index dde2c77..b17e8cb 100644 --- a/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp +++ b/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp @@ -104,11 +104,10 @@ namespace vikunja using MemPolicy = TMemAccessPolicy; // Create an iterator with the specified memory access policy that wraps the input iterator. - vikunja::MemAccess::PolicyBasedBlockStrategy iter( - source, - acc, - n, - TBlockSize); + using MenIndex = vikunja::MemAccess::PolicyBasedBlockStrategy; + MenIndex iter(acc, n, TBlockSize); + MenIndex end = iter.end(); + auto startIndex = MemPolicy::getStartIndex(acc, static_cast(n), static_cast(TBlockSize)); // only do work if the index is in bounds. @@ -117,10 +116,10 @@ namespace vikunja if(startIndex < n) { // no neutral element is used, so initialize with value from first element. - auto tSum = TTransformOperator::run(acc, transformFunc, *iter); + auto tSum = TTransformOperator::run(acc, transformFunc, source[*iter]); ++iter; // Manual unrolling. I dont know if this is really necessary, but - while(iter + 3 < iter.end()) + for(; (iter + 3) < end; iter += 4) { tSum = TReduceOperator::run( acc, @@ -135,20 +134,18 @@ namespace vikunja acc, reduceFunc, tSum, - TTransformOperator::run(acc, transformFunc, *iter)), - TTransformOperator::run(acc, transformFunc, *(iter + 1))), - TTransformOperator::run(acc, transformFunc, *(iter + 2))), - TTransformOperator::run(acc, transformFunc, *(iter + 3))); - iter += 4; + TTransformOperator::run(acc, transformFunc, source[*iter])), + TTransformOperator::run(acc, transformFunc, source[*(iter + 1)])), + TTransformOperator::run(acc, transformFunc, source[*(iter + 2)])), + TTransformOperator::run(acc, transformFunc, source[*(iter + 3)])); } - while(iter < iter.end()) + for(; iter < end; ++iter) { tSum = TReduceOperator::run( acc, reduceFunc, tSum, - TTransformOperator::run(acc, transformFunc, *iter)); - ++iter; + TTransformOperator::run(acc, transformFunc, source[*iter])); } // This condition actually relies on the memory access pattern. // When gridStriding is used, the first n threads always get the first n values, diff --git a/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp b/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp index 70ab4cc..16091e7 100644 --- a/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp +++ b/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp @@ -41,19 +41,10 @@ namespace vikunja TIdx const& n, TFunc const& func) const { - vikunja::MemAccess::PolicyBasedBlockStrategy inputIterator( - source, - acc, - n, - TBlockSize); - vikunja::MemAccess::PolicyBasedBlockStrategy - outputIterator(destination, acc, n, TBlockSize); - - while(inputIterator < inputIterator.end()) + using MenIndex = vikunja::MemAccess::PolicyBasedBlockStrategy; + for(MenIndex iter(acc, n, TBlockSize), end = iter.end(); iter < end; ++iter) { - *outputIterator = TOperator::run(acc, func, *inputIterator); - ++inputIterator; - ++outputIterator; + destination[*iter] = TOperator::run(acc, func, source[*iter]); } } @@ -72,22 +63,10 @@ namespace vikunja TIdx const& n, TFunc const& func) const { - vikunja::MemAccess::PolicyBasedBlockStrategy inputIterator( - source, - acc, - n, - TBlockSize); - vikunja::MemAccess::PolicyBasedBlockStrategy - inputIteratorSecond(sourceSecond, acc, n, TBlockSize); - vikunja::MemAccess::PolicyBasedBlockStrategy - outputIterator(destination, acc, n, TBlockSize); - - while(inputIterator < inputIterator.end()) + using MenIndex = vikunja::MemAccess::PolicyBasedBlockStrategy; + for(MenIndex iter(acc, n, TBlockSize), end = iter.end(); iter < end; ++iter) { - *outputIterator = TOperator::run(acc, func, *inputIterator, *inputIteratorSecond); - ++inputIterator; - ++inputIteratorSecond; - ++outputIterator; + destination[*iter] = TOperator::run(acc, func, source[*iter], sourceSecond[*iter]); } } }; diff --git a/test/unit/iterator/src/Iterator.cpp b/test/unit/iterator/src/Iterator.cpp index b69b1f4..11e76e9 100644 --- a/test/unit/iterator/src/Iterator.cpp +++ b/test/unit/iterator/src/Iterator.cpp @@ -36,10 +36,10 @@ TEST_CASE("BaseStrategy", "[iterator]") constexpr Idx size = 64; std::vector testData{generateIndexVector(size)}; - BaseStrategy zeroFirst(testData.data(), 0, size); - BaseStrategy zeroSecond(testData.data(), 0, size); - BaseStrategy one(testData.data(), 1, size); - BaseStrategy copyOfZeroFirst(zeroFirst); + BaseStrategy zeroFirst(0, size); + BaseStrategy zeroSecond(0, size); + BaseStrategy one(1, size); + BaseStrategy copyOfZeroFirst(zeroFirst); REQUIRE(zeroFirst == zeroSecond); @@ -59,7 +59,7 @@ TEST_CASE("BaseStrategy", "[iterator]") *zeroFirst = 2; REQUIRE(*zeroFirst == 2); - REQUIRE(*zeroSecond == 2); + REQUIRE(*zeroSecond == 0); }; template From 5b3f091098e9dd46aeb049477750c7e54b2911de Mon Sep 17 00:00:00 2001 From: Simeon Ehrig Date: Mon, 31 Jan 2022 10:13:12 +0000 Subject: [PATCH 3/5] rename iterator test to MemAccessStrategy test - rename also folder hierarchy --- test/unit/CMakeLists.txt | 2 +- test/unit/{iterator => access}/CMakeLists.txt | 4 ++-- .../src/Iterator.cpp => access/src/MemAccessStrategy.cpp} | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) rename test/unit/{iterator => access}/CMakeLists.txt (88%) rename test/unit/{iterator/src/Iterator.cpp => access/src/MemAccessStrategy.cpp} (96%) diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 6bafa3a..c897118 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.18) -add_subdirectory("iterator/") +add_subdirectory("access/") add_subdirectory("operators/") if(VIKUNJA_ENABLE_CXX_TEST) add_subdirectory("cxx/") diff --git a/test/unit/iterator/CMakeLists.txt b/test/unit/access/CMakeLists.txt similarity index 88% rename from test/unit/iterator/CMakeLists.txt rename to test/unit/access/CMakeLists.txt index 620799d..129eb93 100644 --- a/test/unit/iterator/CMakeLists.txt +++ b/test/unit/access/CMakeLists.txt @@ -8,12 +8,12 @@ cmake_minimum_required(VERSION 3.18) -set(_TARGET_NAME "test_iterator") +set(_TARGET_NAME "test_memAccessStrategy") alpaka_add_executable( ${_TARGET_NAME} - src/Iterator.cpp + src/MemAccessStrategy.cpp ) target_link_libraries(${_TARGET_NAME} diff --git a/test/unit/iterator/src/Iterator.cpp b/test/unit/access/src/MemAccessStrategy.cpp similarity index 96% rename from test/unit/iterator/src/Iterator.cpp rename to test/unit/access/src/MemAccessStrategy.cpp index 11e76e9..5634dfa 100644 --- a/test/unit/iterator/src/Iterator.cpp +++ b/test/unit/access/src/MemAccessStrategy.cpp @@ -31,7 +31,7 @@ std::vector generateIndexVector(Idx size) return data; } -TEST_CASE("BaseStrategy", "[iterator]") +TEST_CASE("BaseStrategy", "[MemAccessStrategy]") { constexpr Idx size = 64; std::vector testData{generateIndexVector(size)}; @@ -110,7 +110,7 @@ struct TestPolicyBasedBlockIterator } }; -TEST_CASE("PolicyBasedBlockStrategy", "[iterator]") +TEST_CASE("PolicyBasedBlockStrategy", "[MemAccessStrategy]") { // constexpr Idx size = 64; From 44bd5dbb5cdb6ebfd727c35f1cc289c8b03755f8 Mon Sep 17 00:00:00 2001 From: Simeon Ehrig Date: Tue, 8 Feb 2022 13:04:11 +0000 Subject: [PATCH 4/5] Rename MemAccessStrategy.cpp to BaseStrategy.cpp - clean up of the test - prepare for addition iterator tests - add cmake helper function for tests - add memory allocation function for tests --- CMakeLists.txt | 1 + cmake/testUtils.cmake | 60 +++++++++++ test/include/vikunja/test/AlpakaSetup.hpp | 58 +++++++++- test/unit/access/CMakeLists.txt | 18 +--- test/unit/access/src/BaseStrategy.cpp | 61 +++++++++++ test/unit/access/src/MemAccessStrategy.cpp | 120 --------------------- 6 files changed, 181 insertions(+), 137 deletions(-) create mode 100644 cmake/testUtils.cmake create mode 100644 test/unit/access/src/BaseStrategy.cpp delete mode 100644 test/unit/access/src/MemAccessStrategy.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5aedee0..5cbdf9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,7 @@ if(${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) ######################################### if(BUILD_TESTING) + include("${PROJECT_SOURCE_DIR}/cmake/testUtils.cmake") include(CTest) enable_testing() add_subdirectory("test/") diff --git a/cmake/testUtils.cmake b/cmake/testUtils.cmake new file mode 100644 index 0000000..de46d46 --- /dev/null +++ b/cmake/testUtils.cmake @@ -0,0 +1,60 @@ +# Copyright 2022 Simeon Ehrig +# +# This file is part of vikunja. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Create an executable file for the test, link it to the required test targets and add it to ctest. +# +# vikunja_add_default_test(TARGET +# SOURCE +# [INCLUDE ] +# ) +# +# * TARGET: name of the executable, will be prefixed with `test_` +# * SOURCE: path of the source file(s) +# * INCLUDE: optional path(s) to include folder(s) +macro(vikunja_add_default_test) + set(_MACRO_PREFIX "vikTest") + set(_SINGLE_ARG TARGET) + set(_MULTI_ARG SOURCE INCLUDE) + + cmake_parse_arguments( + "${_MACRO_PREFIX}" + "" # option + "${_SINGLE_ARG}" + "${_MULTI_ARG}" + "${ARGN}" + ) + + if(NOT DEFINED ${_MACRO_PREFIX}_TARGET) + message(FATAL_ERROR "vikunja_add_default_test: no target name defined") + endif() + + if(NOT DEFINED ${_MACRO_PREFIX}_SOURCE) + message(FATAL_ERROR "vikunja_add_default_test: no source files defined") + endif() + + set(_TARGET_NAME "test_${${_MACRO_PREFIX}_TARGET}") + + alpaka_add_executable( + ${_TARGET_NAME} + ${${_MACRO_PREFIX}_SOURCE} + ) + + if(DEFINED ${_MACRO_PREFIX}_INCLUDE) + message(VERBOSE "vikunja_add_default_test: add ${${_MACRO_PREFIX}_INCLUDE} include paths to ${_TARGET_NAME}") + target_include_directories(${_TARGET_NAME} PRIVATE ${${_MACRO_PREFIX}_INCLUDE}) + endif() + + target_link_libraries(${_TARGET_NAME} + PRIVATE + vikunja::internalvikunja + vikunja::testSetup + ) + + add_test(NAME ${_TARGET_NAME} COMMAND ${_TARGET_NAME} ${_VIKUNJA_TEST_OPTIONS}) + +endmacro() diff --git a/test/include/vikunja/test/AlpakaSetup.hpp b/test/include/vikunja/test/AlpakaSetup.hpp index 1387761..d97f645 100644 --- a/test/include/vikunja/test/AlpakaSetup.hpp +++ b/test/include/vikunja/test/AlpakaSetup.hpp @@ -1,4 +1,4 @@ -/* Copyright 2021 Hauke Mewes, Simeon Ehrig +/* Copyright 2022 Hauke Mewes, Simeon Ehrig * * This file is part of vikunja. * @@ -50,6 +50,62 @@ namespace vikunja , queueAcc{devAcc} { } + + /** + * @brief Allocate 1D memory on host. + * + * @tparam TData Type of the memory. + * @param size Size of the memory. + * @return auto Alpaka memory buffer on the host. + */ + template + auto allocHost(Idx size) + { + using Vec = alpaka::Vec, Idx>; + return alpaka::allocBuf(devHost, Vec::all(size)); + } + + /** + * @brief Allocate ND memory on host. + * + * @tparam TData Type of the memory. + * @tparam TExtentDim alpaka::Vec + * @param size Vector with the sizes for each memory dimension. + * @return auto Alpaka memory buffer on the host. + */ + template + auto allocHost(alpaka::Vec size) + { + return alpaka::allocBuf(devHost, size); + } + + /** + * @brief Allocate 1D memory on device. + * + * @tparam TData Type of the memory. + * @param size Size of the memory. + * @return auto Alpaka memory buffer on the device. + */ + template + auto allocDev(Idx size) + { + using Vec = alpaka::Vec, Idx>; + return alpaka::allocBuf(devAcc, Vec::all(size)); + } + + /** + * @brief Allocate ND memory on device. + * + * @tparam TData Type of the memory. + * @tparam TExtentDim alpaka::Vec + * @param size Vector with the sizes for each memory dimension. + * @return auto Alpaka memory buffer on the device. + */ + template + auto allocDev(alpaka::Vec size) + { + return alpaka::allocBuf(devAcc, size); + } }; } // namespace test } // namespace vikunja diff --git a/test/unit/access/CMakeLists.txt b/test/unit/access/CMakeLists.txt index 129eb93..7c421b8 100644 --- a/test/unit/access/CMakeLists.txt +++ b/test/unit/access/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2021 Hauke Mewes, Simeon Ehrig +# Copyright 2022 Hauke Mewes, Simeon Ehrig # # This file is part of vikunja. # @@ -8,18 +8,4 @@ cmake_minimum_required(VERSION 3.18) -set(_TARGET_NAME "test_memAccessStrategy") - - -alpaka_add_executable( - ${_TARGET_NAME} - src/MemAccessStrategy.cpp - ) - -target_link_libraries(${_TARGET_NAME} - PRIVATE - vikunja::internalvikunja - vikunja::testSetup - ) - -add_test(NAME ${_TARGET_NAME} COMMAND ${_TARGET_NAME} ${_VIKUNJA_TEST_OPTIONS}) +vikunja_add_default_test(TARGET "memAccessBaseStrategy" SOURCE "src/BaseStrategy.cpp") diff --git a/test/unit/access/src/BaseStrategy.cpp b/test/unit/access/src/BaseStrategy.cpp new file mode 100644 index 0000000..96da0e7 --- /dev/null +++ b/test/unit/access/src/BaseStrategy.cpp @@ -0,0 +1,61 @@ +/* Copyright 2022 Hauke Mewes, Simeon Ehrig + * + * This file is part of vikunja. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include + +#include + +#include + +#include + +using namespace vikunja::MemAccess; + +TEST_CASE("BaseStrategy", "[MemAccessStrategy]") +{ + using Idx = std::size_t; + constexpr auto size = static_cast(64); + + + BaseStrategy zeroFirst(0, size); + BaseStrategy zeroSecond(0, size); + BaseStrategy one(1, size); + + SECTION("test comparison operators") + { + REQUIRE(zeroFirst == zeroSecond); + REQUIRE(zeroSecond == zeroFirst); + REQUIRE(zeroFirst != one); + REQUIRE(one != zeroFirst); + REQUIRE(zeroFirst < one); + REQUIRE(one > zeroFirst); + REQUIRE_FALSE(zeroFirst < zeroSecond); + REQUIRE_FALSE(zeroFirst > zeroSecond); + REQUIRE(zeroFirst <= zeroSecond); + REQUIRE(zeroSecond <= zeroFirst); + REQUIRE(zeroFirst <= one); + } + SECTION("test access operators") + { + REQUIRE(*zeroFirst == 0); + REQUIRE(*one == 1); + *zeroFirst = 2; + REQUIRE(*zeroFirst == 2); + REQUIRE(*zeroSecond == 0); + REQUIRE_FALSE(*zeroFirst == *zeroSecond); + } + SECTION("test copy operator") + { + BaseStrategy copyOfZeroFirst(zeroFirst); + REQUIRE(copyOfZeroFirst == zeroFirst); + *copyOfZeroFirst = 3; + REQUIRE(copyOfZeroFirst != zeroFirst); + } +} diff --git a/test/unit/access/src/MemAccessStrategy.cpp b/test/unit/access/src/MemAccessStrategy.cpp deleted file mode 100644 index 5634dfa..0000000 --- a/test/unit/access/src/MemAccessStrategy.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright 2022 Hauke Mewes, Simeon Ehrig - * - * This file is part of vikunja. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include -#include - -#include - -#include - -#include - -using Type = uint64_t; -using IType = Type*; -using Idx = std::size_t; -using namespace vikunja::MemAccess; - -std::vector generateIndexVector(Idx size) -{ - std::vector data(size); - for(Idx i = 0; i < size; ++i) - { - data[i] = i; - } - return data; -} - -TEST_CASE("BaseStrategy", "[MemAccessStrategy]") -{ - constexpr Idx size = 64; - std::vector testData{generateIndexVector(size)}; - - BaseStrategy zeroFirst(0, size); - BaseStrategy zeroSecond(0, size); - BaseStrategy one(1, size); - BaseStrategy copyOfZeroFirst(zeroFirst); - - - REQUIRE(zeroFirst == zeroSecond); - REQUIRE(zeroSecond == zeroFirst); - REQUIRE(zeroFirst != one); - REQUIRE(one != zeroFirst); - REQUIRE(zeroFirst < one); - REQUIRE(one > zeroFirst); - REQUIRE_FALSE(zeroFirst < zeroSecond); - REQUIRE_FALSE(zeroFirst > zeroSecond); - REQUIRE(zeroFirst <= zeroSecond); - REQUIRE(zeroSecond <= zeroFirst); - REQUIRE(zeroFirst <= one); - REQUIRE(*zeroFirst == 0); - REQUIRE(*one == 1); - REQUIRE(copyOfZeroFirst == zeroFirst); - - *zeroFirst = 2; - REQUIRE(*zeroFirst == 2); - REQUIRE(*zeroSecond == 0); -}; - -template -struct TestPolicyBasedBlockIteratorKernel -{ -}; - -template<> -struct TestPolicyBasedBlockIteratorKernel -{ - template - ALPAKA_FN_ACC void operator()(TAcc const& acc, Type* data, TIdx const& n) const - { - } -}; - -template -struct TestPolicyBasedBlockIterator -{ - template - void operator()() - { - using Idx = alpaka::Idx; - using Dim = alpaka::Dim; - - constexpr Idx n = 65; - constexpr Idx blocksPerGrid = 2; - constexpr Idx threadsPerBlock = 1; - constexpr Idx elementsPerThread = n / 2 + 1; - - using DevAcc = alpaka::Dev; - using PltfAcc = alpaka::Pltf; - using QueueAcc = alpaka::QueueCpuBlocking; - // alpaka::test::queue::DefaultQueue>; - using PltfHost = alpaka::PltfCpu; - using DevHost = alpaka::Dev; - using QueueHost = alpaka::QueueCpuBlocking; - using WorkDiv = alpaka::WorkDivMembers; - // Get the host device. - DevHost devHost(alpaka::getDevByIdx(0u)); - // Get a queue on the host device. - QueueHost queueHost(devHost); - // Select a device to execute on. - DevAcc devAcc(alpaka::getDevByIdx(0u)); - // Get a queue on the accelerator device. - QueueAcc queueAcc(devAcc); - WorkDiv workdiv{blocksPerGrid, threadsPerBlock, elementsPerThread}; - } -}; - -TEST_CASE("PolicyBasedBlockStrategy", "[MemAccessStrategy]") -{ - // constexpr Idx size = 64; - - SECTION("LinearMemAccessPolicy") - { - } -} From f3aaa68ef990f640e633613572cf4fcbaa82bf1a Mon Sep 17 00:00:00 2001 From: Simeon Ehrig Date: Mon, 14 Feb 2022 16:15:58 +0000 Subject: [PATCH 5/5] Overwork several thinks in mem access strategy - thanks to @j-stephan --- include/vikunja/access/BaseStrategy.hpp | 38 +++++++---- ...sedBlockStrategy.hpp => BlockStrategy.hpp} | 66 +++++++++---------- .../reduce/detail/BlockThreadReduceKernel.hpp | 8 +-- include/vikunja/reduce/reduce.hpp | 2 +- .../detail/BlockThreadTransformKernel.hpp | 10 +-- include/vikunja/transform/transform.hpp | 2 +- test/include/vikunja/test/AlpakaSetup.hpp | 8 +-- test/include/vikunja/test/utility.hpp | 2 +- test/unit/access/src/BaseStrategy.cpp | 1 - 9 files changed, 74 insertions(+), 63 deletions(-) rename include/vikunja/access/{PolicyBasedBlockStrategy.hpp => BlockStrategy.hpp} (82%) diff --git a/include/vikunja/access/BaseStrategy.hpp b/include/vikunja/access/BaseStrategy.hpp index e8313eb..e020024 100644 --- a/include/vikunja/access/BaseStrategy.hpp +++ b/include/vikunja/access/BaseStrategy.hpp @@ -28,7 +28,7 @@ namespace vikunja::MemAccess //! Constructor. //! //! \param index The index. - //! \param maximum The first index outside of the iterator memory. + //! \param maximum value of the index (not inclusive). ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseStrategy(TIdx const index, TIdx const maximum) : m_index(index) , m_maximum(maximum) @@ -37,34 +37,46 @@ namespace vikunja::MemAccess ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BaseStrategy(const BaseStrategy& other) = default; - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator==(const BaseStrategy& other) const -> bool + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE constexpr friend auto operator==( + BaseStrategy const& st, + const BaseStrategy& other) -> bool { - return (this->m_index == other.m_index) && (this->m_maximum == other.m_maximum); + return (st.m_index == other.m_index) && (st.m_maximum == other.m_maximum); } - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator!=(const BaseStrategy& other) const -> bool + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE constexpr friend auto operator!=( + BaseStrategy const& st, + const BaseStrategy& other) -> bool { - return !operator==(other); + return !operator==(st, other); } - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<(const BaseStrategy& other) const -> bool + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE constexpr friend auto operator<( + BaseStrategy const& st, + const BaseStrategy& other) -> bool { - return m_index < other.m_index; + return st.m_index < other.m_index; } - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>(const BaseStrategy& other) const -> bool + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE constexpr friend auto operator>( + BaseStrategy const& st, + const BaseStrategy& other) -> bool { - return m_index > other.m_index; + return st.m_index > other.m_index; } - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator<=(const BaseStrategy& other) const -> bool + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE constexpr friend auto operator<=( + BaseStrategy const& st, + const BaseStrategy& other) -> bool { - return m_index <= other.m_index; + return st.m_index <= other.m_index; } - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator>=(const BaseStrategy& other) const -> bool + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE constexpr friend auto operator>=( + BaseStrategy const& st, + const BaseStrategy& other) -> bool { - return m_index >= other.m_index; + return st.m_index >= other.m_index; } //----------------------------------------------------------------------------- diff --git a/include/vikunja/access/PolicyBasedBlockStrategy.hpp b/include/vikunja/access/BlockStrategy.hpp similarity index 82% rename from include/vikunja/access/PolicyBasedBlockStrategy.hpp rename to include/vikunja/access/BlockStrategy.hpp index eff6efb..a94494d 100644 --- a/include/vikunja/access/PolicyBasedBlockStrategy.hpp +++ b/include/vikunja/access/BlockStrategy.hpp @@ -17,29 +17,29 @@ namespace vikunja::MemAccess { /** * A policy based memory access strategy that splits the data access into chunks. Depending on the memory access - * policy, these chunks can access the data sequential or in a striding pattern. + * policy, these chunks can access the data sequentially or in a striding pattern. * @tparam MemAccessPolicy The memory access policy to use. * @tparam TAcc The alpaka accelerator type. * @tparam TIdx The index type * * The memory access policy should provide three values: - * - The startIndex of the iterator, which is the first index to use. - * - The endIndex of the iterator, which is the last index to use. - * - The stepSize of the iterator, which tells how far the iterator should move. + * - The startIndex which is the first index to use. + * - The endIndex which is the last index to use. + * - The stepSize which specifies how large the distance is between an index position and its successor. */ template - class PolicyBasedBlockStrategy : public BaseStrategy + class BlockStrategy : public BaseStrategy { private: - TIdx m_step; /**< The step size of this iterator. */ + TIdx m_step; /**< The step size of this strategy. */ public: /** - * Create a policy based block iterator + * Create a policy based block strategy accessor * @param acc The accelerator type to use. - * @param problemSize The size of the original iterator. + * @param problemSize The size of the original strategy. * @param blockSize The size of the blocks. */ - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE PolicyBasedBlockStrategy(TAcc const& acc, TIdx problemSize, TIdx blockSize) + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BlockStrategy(TAcc const& acc, TIdx problemSize, TIdx blockSize) : BaseStrategy( MemAccessPolicy::getStartIndex(acc, problemSize, blockSize), MemAccessPolicy::getEndIndex(acc, problemSize, blockSize)) @@ -47,13 +47,13 @@ namespace vikunja::MemAccess { } - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE PolicyBasedBlockStrategy(const PolicyBasedBlockStrategy& other) = default; + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE BlockStrategy(const BlockStrategy& other) = default; //----------------------------------------------------------------------------- //! Returns a memory access object with the index set to the last item. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> PolicyBasedBlockStrategy + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto end() const -> BlockStrategy { - PolicyBasedBlockStrategy ret(*this); + BlockStrategy ret(*this); ret.m_index = this->m_maximum; return ret; } @@ -62,7 +62,7 @@ namespace vikunja::MemAccess //! Increments the internal index to the next one. //! //! Returns a reference to the next index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> PolicyBasedBlockStrategy& + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++() -> BlockStrategy& { this->m_index += this->m_step; return *this; @@ -73,7 +73,7 @@ namespace vikunja::MemAccess //! next one. //! //! Returns a reference to the current index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> PolicyBasedBlockStrategy + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator++(int) -> BlockStrategy { auto ret(*this); this->m_index += this->m_step; @@ -85,7 +85,7 @@ namespace vikunja::MemAccess //! element. //! //! Returns a reference to the previous index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> PolicyBasedBlockStrategy& + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--() -> BlockStrategy& { this->m_index -= this->m_step; return *this; @@ -96,7 +96,7 @@ namespace vikunja::MemAccess //! previous one. //! //! Returns a reference to the current index. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> PolicyBasedBlockStrategy + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator--(int) -> BlockStrategy { auto ret(*this); this->m_index -= this->m_step; @@ -107,7 +107,7 @@ namespace vikunja::MemAccess //! Returns the index + a supplied offset. //! //! \param n The offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const -> PolicyBasedBlockStrategy + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+(uint64_t n) const -> BlockStrategy { auto ret(*this); ret.m_index += n * m_step; @@ -118,7 +118,7 @@ namespace vikunja::MemAccess //! Returns the index - a supplied offset. //! //! \param n The offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const -> PolicyBasedBlockStrategy + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-(uint64_t n) const -> BlockStrategy { auto ret(*this); ret.m_index -= n * m_step; @@ -131,7 +131,7 @@ namespace vikunja::MemAccess //! \param offset The offset. //! //! Returns the current object offset by the offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset) -> PolicyBasedBlockStrategy& + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator+=(uint64_t offset) -> BlockStrategy& { this->m_index += offset * this->m_step; return *this; @@ -143,7 +143,7 @@ namespace vikunja::MemAccess //! \param offset The offset. //! //! Returns the current object offset by the offset. - ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset) -> PolicyBasedBlockStrategy& + ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE auto operator-=(uint64_t offset) -> BlockStrategy& { this->m_index -= offset * this->m_step; return *this; @@ -153,15 +153,15 @@ namespace vikunja::MemAccess namespace policies { /** - * A memory policy for the PolicyBlockBasedIterator that provides grid striding memory access. + * A memory policy for the BlockStrategy that provides grid striding memory access. */ struct GridStridingMemAccessPolicy { template ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStartIndex( TAcc const& acc, - TIdx const& problemSize __attribute__((unused)), - TIdx const& blockSize __attribute__((unused))) -> TIdx const + TIdx const& /* problemSize */, + TIdx const& /* blockSize */) -> TIdx const { constexpr TIdx xIndex = alpaka::Dim::value - 1u; return alpaka::getIdx(acc)[xIndex]; @@ -171,7 +171,7 @@ namespace vikunja::MemAccess ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getEndIndex( TAcc const& acc, TIdx const& problemSize, - TIdx const& blockSize __attribute__((unused))) -> TIdx const + TIdx const& /* blockSize */) -> TIdx const { return problemSize; } @@ -179,7 +179,7 @@ namespace vikunja::MemAccess template ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto getStepSize( TAcc const& acc, - TIdx const& problemSize __attribute__((unused)), + TIdx const& /* problemSize */, TIdx const& blockSize) -> TIdx const { constexpr TIdx xIndex = alpaka::Dim::value - 1u; @@ -191,7 +191,7 @@ namespace vikunja::MemAccess ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static auto isValidThreadResult( TAcc const& acc, TIdx const& problemSize, - TIdx const& blockSize __attribute__((unused))) -> bool const + TIdx const& /* blockSize */) -> bool const { constexpr TIdx xIndex = alpaka::Dim::value - 1u; auto threadIndex = (alpaka::getIdx(acc)[xIndex]); @@ -207,7 +207,7 @@ namespace vikunja::MemAccess }; /** - * A memory access policy for the PolicyBlockBasedIterator that provides linear memory access. + * A memory access policy for the BlockStrategy that provides linear memory access. */ struct LinearMemAccessPolicy { @@ -241,18 +241,18 @@ namespace vikunja::MemAccess template ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto getStepSize( - TAcc const& acc __attribute__((unused)), - TIdx const& problemSize __attribute__((unused)), - TIdx const& blockSize __attribute__((unused))) -> TIdx const + TAcc const& /* acc */, + TIdx const& /* problemSize */, + TIdx const& /* blockSize */) -> TIdx const { return 1; } template ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr auto isValidThreadResult( - TAcc const& acc __attribute__((unused)), - TIdx const& problemSize __attribute__((unused)), - TIdx const& blockSize __attribute__((unused))) -> bool const + TAcc const& /* acc */, + TIdx const& /* problemSize */, + TIdx const& /* blockSize */) -> bool const { return true; } diff --git a/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp b/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp index b17e8cb..f08a242 100644 --- a/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp +++ b/include/vikunja/reduce/detail/BlockThreadReduceKernel.hpp @@ -9,7 +9,7 @@ #pragma once -#include +#include #include @@ -104,9 +104,9 @@ namespace vikunja using MemPolicy = TMemAccessPolicy; // Create an iterator with the specified memory access policy that wraps the input iterator. - using MenIndex = vikunja::MemAccess::PolicyBasedBlockStrategy; - MenIndex iter(acc, n, TBlockSize); - MenIndex end = iter.end(); + using MemIndex = vikunja::MemAccess::BlockStrategy; + MemIndex iter(acc, n, TBlockSize); + MemIndex end = iter.end(); auto startIndex = MemPolicy::getStartIndex(acc, static_cast(n), static_cast(TBlockSize)); diff --git a/include/vikunja/reduce/reduce.hpp b/include/vikunja/reduce/reduce.hpp index 6537116..dca4d74 100644 --- a/include/vikunja/reduce/reduce.hpp +++ b/include/vikunja/reduce/reduce.hpp @@ -9,7 +9,7 @@ #pragma once -#include +#include #include #include #include diff --git a/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp b/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp index 16091e7..b9f759b 100644 --- a/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp +++ b/include/vikunja/transform/detail/BlockThreadTransformKernel.hpp @@ -9,7 +9,7 @@ #pragma once -#include +#include #include @@ -41,8 +41,8 @@ namespace vikunja TIdx const& n, TFunc const& func) const { - using MenIndex = vikunja::MemAccess::PolicyBasedBlockStrategy; - for(MenIndex iter(acc, n, TBlockSize), end = iter.end(); iter < end; ++iter) + using MemIndex = vikunja::MemAccess::BlockStrategy; + for(MemIndex iter(acc, n, TBlockSize), end = iter.end(); iter < end; ++iter) { destination[*iter] = TOperator::run(acc, func, source[*iter]); } @@ -63,8 +63,8 @@ namespace vikunja TIdx const& n, TFunc const& func) const { - using MenIndex = vikunja::MemAccess::PolicyBasedBlockStrategy; - for(MenIndex iter(acc, n, TBlockSize), end = iter.end(); iter < end; ++iter) + using MemIndex = vikunja::MemAccess::BlockStrategy; + for(MemIndex iter(acc, n, TBlockSize), end = iter.end(); iter < end; ++iter) { destination[*iter] = TOperator::run(acc, func, source[*iter], sourceSecond[*iter]); } diff --git a/include/vikunja/transform/transform.hpp b/include/vikunja/transform/transform.hpp index 2ead173..edbe623 100644 --- a/include/vikunja/transform/transform.hpp +++ b/include/vikunja/transform/transform.hpp @@ -9,7 +9,7 @@ #pragma once -#include +#include #include #include #include diff --git a/test/include/vikunja/test/AlpakaSetup.hpp b/test/include/vikunja/test/AlpakaSetup.hpp index d97f645..ec48896 100644 --- a/test/include/vikunja/test/AlpakaSetup.hpp +++ b/test/include/vikunja/test/AlpakaSetup.hpp @@ -52,7 +52,7 @@ namespace vikunja } /** - * @brief Allocate 1D memory on host. + * @brief Allocate 1D memory on the host. * * @tparam TData Type of the memory. * @param size Size of the memory. @@ -66,7 +66,7 @@ namespace vikunja } /** - * @brief Allocate ND memory on host. + * @brief Allocate ND memory on the host. * * @tparam TData Type of the memory. * @tparam TExtentDim alpaka::Vec @@ -80,7 +80,7 @@ namespace vikunja } /** - * @brief Allocate 1D memory on device. + * @brief Allocate 1D memory on the device. * * @tparam TData Type of the memory. * @param size Size of the memory. @@ -94,7 +94,7 @@ namespace vikunja } /** - * @brief Allocate ND memory on device. + * @brief Allocate ND memory on the device. * * @tparam TData Type of the memory. * @tparam TExtentDim alpaka::Vec diff --git a/test/include/vikunja/test/utility.hpp b/test/include/vikunja/test/utility.hpp index b96936c..78d5b11 100644 --- a/test/include/vikunja/test/utility.hpp +++ b/test/include/vikunja/test/utility.hpp @@ -9,7 +9,7 @@ #pragma once -#include +#include #include #include diff --git a/test/unit/access/src/BaseStrategy.cpp b/test/unit/access/src/BaseStrategy.cpp index 96da0e7..1135db0 100644 --- a/test/unit/access/src/BaseStrategy.cpp +++ b/test/unit/access/src/BaseStrategy.cpp @@ -8,7 +8,6 @@ */ #include -#include #include