-
Notifications
You must be signed in to change notification settings - Fork 110
Add SubView class #1915
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Add SubView class #1915
Changes from 8 commits
0e97668
7ebc87a
67d9653
b942833
5ba920d
ffc1d4c
e899696
d8a9081
6aa5662
17d24e6
45206ac
2f45d02
1e928d3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| /*! | ||
| ****************************************************************************** | ||
| * | ||
| * \file | ||
| * | ||
| * \brief RAJA header file defining the SubView class | ||
| * | ||
| ****************************************************************************** | ||
| */ | ||
|
|
||
| //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// | ||
| // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC | ||
| // and RAJA project contributors. See the RAJA/LICENSE file for details. | ||
| // | ||
| // SPDX-License-Identifier: (BSD-3-Clause) | ||
| //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// | ||
|
|
||
| #ifndef RAJA_SUBVIEW_HPP | ||
| #define RAJA_SUBVIEW_HPP | ||
|
|
||
| #include "RAJA/util/for_each.hpp" | ||
| #include "RAJA/util/types.hpp" | ||
| #include "camp/number.hpp" | ||
| #include "camp/tuple.hpp" | ||
| #include "camp/array.hpp" | ||
|
|
||
| namespace RAJA | ||
| { | ||
|
|
||
| // Slice descriptors | ||
|
|
||
| // template<typename SliceType> | ||
| // RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(IndexType& idx) const { | ||
| // return start + idx; | ||
| // } | ||
|
|
||
| template<typename IndexType = Index_type> | ||
| struct RangeSlice { | ||
| IndexType start, end; | ||
|
|
||
| static constexpr bool reduces_dimension = false; | ||
|
|
||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(IndexType& idx) const { | ||
| return start + idx; | ||
| } | ||
| }; | ||
|
|
||
| template<typename IndexType = Index_type> | ||
| struct FixedSlice { | ||
| IndexType idx; | ||
|
|
||
| static constexpr bool reduces_dimension = true; | ||
|
|
||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(IndexType&) const { | ||
| return idx; | ||
| } | ||
| }; | ||
|
|
||
| template<typename IndexType = Index_type> | ||
| struct NoSlice { | ||
| static constexpr bool reduces_dimension = false; | ||
|
|
||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(IndexType& idx) const { | ||
| return idx; | ||
| } | ||
| }; | ||
|
|
||
| template <typename T, size_t N, RAJA::Index_type... Is> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto array_to_tuple_impl(const camp::array<T, N>& arr, camp::idx_seq<Is...>) { | ||
| return camp::make_tuple(arr[Is]...); | ||
| } | ||
|
|
||
| template <typename T, size_t N> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto array_to_tuple(const camp::array<T, N>& arr) { | ||
| return array_to_tuple_impl(arr, camp::make_idx_seq_t<N>{}); | ||
| } | ||
|
|
||
| template <typename ViewType, typename SliceTypes, typename IndexType = Index_type> | ||
| class SubView; | ||
|
|
||
| template <typename ViewType, typename IndexType, typename... Slices> | ||
| class SubView<ViewType, camp::list<Slices...>, IndexType> { | ||
| ViewType view_; | ||
| camp::tuple<Slices...> slices_; | ||
|
||
| std::array<IndexType, sizeof...(Slices)> map_; | ||
|
||
|
|
||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto make_subview_index_map() { | ||
| size_t sub_idx = 0; | ||
| std::array<IndexType, sizeof...(Slices)> map; | ||
|
|
||
| for_each_tuple_index( slices_, | ||
|
||
| [&](auto slice, auto index) { | ||
| map[index] = decltype(slice)::reduces_dimension ? -1 : sub_idx++; | ||
| }); | ||
|
|
||
| return map; | ||
| } | ||
|
|
||
| public: | ||
|
|
||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr SubView(ViewType view, Slices... slices) | ||
| : view_(view), slices_(slices...), map_(make_subview_index_map()) { } | ||
|
|
||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr void set_slices(Slices... slices) { | ||
| slices_ = camp::tuple<Slices...>(slices...); | ||
| } | ||
|
|
||
| template<IndexType Index, typename Slice> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr void set_slice(Slice slice) { | ||
| camp::get<Index>(slices_) = slice; | ||
| } | ||
|
|
||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto& get_slices() { | ||
| return slices_; | ||
| } | ||
|
|
||
| template<IndexType Index> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto& get_slice() { | ||
| return camp::get<Index>(slices_); | ||
| } | ||
|
|
||
| template <typename... Idxs> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType operator()(Idxs... idxs) const { | ||
| constexpr size_t nidx = ((Slices::reduces_dimension == false ? 1 : 0) + ...); | ||
|
||
| static_assert(sizeof...(idxs) == nidx, "Wrong number of indices for subview"); | ||
|
|
||
| camp::array<Index_type, nidx> arr{idxs...}; | ||
| camp::array<Index_type, sizeof...(Slices)> parent_indices; | ||
|
|
||
| for_each_tuple_index( slices_, | ||
| [&](auto slice, auto index) { | ||
| parent_indices[index] = slice.map_index(arr[map_[index]]); | ||
|
||
| }); | ||
|
|
||
| return camp::apply(view_, array_to_tuple(parent_indices)); | ||
|
||
| } | ||
| }; | ||
|
|
||
| template <typename ViewType, typename... Slices> | ||
| SubView(ViewType, Slices...) -> SubView<ViewType, camp::list<Slices...>>; | ||
|
|
||
| } // namespace RAJA | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -24,6 +24,9 @@ | |||||||||
| #include <type_traits> | ||||||||||
|
|
||||||||||
| #include "camp/list.hpp" | ||||||||||
| #include "camp/concepts.hpp" | ||||||||||
| #include "camp/number.hpp" | ||||||||||
| #include "camp/tuple.hpp" | ||||||||||
|
|
||||||||||
| #include "RAJA/pattern/detail/algorithm.hpp" | ||||||||||
|
|
||||||||||
|
|
@@ -36,6 +39,20 @@ namespace RAJA | |||||||||
| namespace detail | ||||||||||
| { | ||||||||||
|
|
||||||||||
| // compile time expansion applying func to each of the indices | ||||||||||
| RAJA_SUPPRESS_HD_WARN | ||||||||||
| template<typename UnaryFunc, typename IndexType, IndexType... Is> | ||||||||||
| RAJA_HOST_DEVICE RAJA_INLINE UnaryFunc for_each_index(camp::idx_seq<Is...>, | ||||||||||
|
||||||||||
| template<typename UnaryFunc, typename IndexType, IndexType... Is> | |
| RAJA_HOST_DEVICE RAJA_INLINE UnaryFunc for_each_index(camp::idx_seq<Is...>, | |
| template<typename UnaryFunc, camp::idx_t... Is> | |
| RAJA_HOST_DEVICE RAJA_INLINE UnaryFunc for_each_index(camp::idx_seq<Is...>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should all be size_t or camp::idx_t.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| int seq_unused_array[] = {0, (func(get<Is>(std::forward<Tuple>(t)), Is), 0)...}; | |
| int seq_unused_array[] = {0, (func(get<Is>(std::forward<Tuple>(t)), std::integral_constant<std::size_t, Is>{}), 0)...}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// | ||
| // Copyright (c) 2016-25, Lawrence Livermore National Security, LLC | ||
| // and RAJA project contributors. See the RAJA/LICENSE file for details. | ||
| // | ||
| // SPDX-License-Identifier: (BSD-3-Clause) | ||
| //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// | ||
|
|
||
| #include <gtest/gtest.h> | ||
| #include "RAJA/policy/PolicyBase.hpp" | ||
| #include "RAJA/util/SubView.hpp" | ||
| #include "RAJA/util/types.hpp" | ||
| #include "RAJA_test-base.hpp" | ||
| #include "RAJA_unit-test-forone.hpp" | ||
|
|
||
| using namespace RAJA; | ||
|
|
||
| TEST(SubView, RangeSubView1D) | ||
| { | ||
|
|
||
| Index_type a[] = {1,2,3,4,5}; | ||
|
|
||
| View<Index_type, Layout<1>> view(&a[0], Layout<1>(5)); | ||
|
|
||
| // sv = View[1:3] | ||
| auto sv = SubView(view, RangeSlice<>{1,3}); | ||
|
|
||
| EXPECT_EQ(sv(0), 2); | ||
| EXPECT_EQ(sv(1), 3); | ||
| EXPECT_EQ(sv(2), 4); | ||
|
|
||
| } | ||
|
|
||
| TEST(SubView, RangeSubView2D) | ||
| { | ||
|
|
||
| Index_type a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; | ||
|
|
||
| View<Index_type, Layout<2>> view(&a[0][0], Layout<2>(3,3)); | ||
|
|
||
| // sv = View[1:2,1:2] | ||
| auto sv = SubView(view, RangeSlice<>{1,2}, RangeSlice<>{1,2}); | ||
|
|
||
| EXPECT_EQ(sv(0,0), 5); | ||
| EXPECT_EQ(sv(0,1), 6); | ||
| EXPECT_EQ(sv(1,0), 8); | ||
| EXPECT_EQ(sv(1,1), 9); | ||
|
|
||
| } | ||
|
|
||
| TEST(SubView, RangeFixedSubView2D) | ||
| { | ||
|
|
||
| Index_type a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; | ||
|
|
||
| View<Index_type, Layout<2>> view(&a[0][0], Layout<2>(3,3)); | ||
|
|
||
| // sv = View[1:2,1] | ||
| auto sv = SubView(view, RangeSlice<>{1,2}, FixedSlice<>{1}); | ||
|
|
||
| EXPECT_EQ(sv(0), 5); | ||
| EXPECT_EQ(sv(1), 8); | ||
|
|
||
| } | ||
|
|
||
| TEST(SubView, FixedFirstDimSubView2D) | ||
| { | ||
|
|
||
| Index_type a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; | ||
|
|
||
| View<Index_type, Layout<2>> view(&a[0][0], Layout<2>(3,3)); | ||
|
|
||
| // sv = View[1,:] | ||
| auto sv = SubView(view, FixedSlice<>{1}, NoSlice{}); | ||
|
|
||
| EXPECT_EQ(sv(0), 4); | ||
| EXPECT_EQ(sv(1), 5); | ||
| EXPECT_EQ(sv(2), 6); | ||
|
|
||
| } | ||
|
|
||
| TEST(SubView, RangeFirstDimSubView2D) | ||
| { | ||
|
|
||
| Index_type a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; | ||
|
|
||
| View<Index_type, Layout<2>> view(&a[0][0], Layout<2>(3,3)); | ||
|
|
||
| // sv = View[1:2,:] | ||
| auto sv = SubView(view, RangeSlice<>{1,2}, NoSlice{}); | ||
|
|
||
| EXPECT_EQ(sv(0,0), 4); | ||
| EXPECT_EQ(sv(0,1), 5); | ||
| EXPECT_EQ(sv(0,2), 6); | ||
|
|
||
| EXPECT_EQ(sv(1,0), 7); | ||
| EXPECT_EQ(sv(1,1), 8); | ||
| EXPECT_EQ(sv(1,2), 9); | ||
|
|
||
| sv.set_slice<0>(RangeSlice<>{0,1}); | ||
|
|
||
| EXPECT_EQ(sv(0,0), 1); | ||
| EXPECT_EQ(sv(0,1), 2); | ||
| EXPECT_EQ(sv(0,2), 3); | ||
|
|
||
| EXPECT_EQ(sv(1,0), 4); | ||
| EXPECT_EQ(sv(1,1), 5); | ||
| EXPECT_EQ(sv(1,2), 6); | ||
|
|
||
| } | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gberg617 how would you do something like we have in the original impl of SubViews: https://github.com/LLNL/SNLS/blob/develop/test/SNLS_forall_subviews.cxx#L69-L75 where we allow for a sliding window with the SubView. Additionally, how can we get the underlying data pointer at the SubView's (0..) index like here: https://github.com/LLNL/SNLS/blob/develop/test/SNLS_forall_subviews.cxx#L150 ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added |
||
| // To Do tests: subview of subview, "sliding winow" modify slice entries, GPU tests. | ||
|
|
||
| // void test_subviewGPU() { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To Do: Fix GPU tests. |
||
| // #if defined(RAJA_ENABLE_HIP) | ||
| // forone<test_hip>([=] __host__ __device__ () { | ||
| // Index_type a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; | ||
|
|
||
| // View<Index_type, Layout<2>> view(&a[0][0], Layout<2>(3,3)); | ||
|
|
||
| // // sv = View[1:2,:] | ||
| // auto sv = SubView(view, RangeSlice<>{1,2}, NoSlice{}); | ||
|
|
||
| // //printf("sv(0,0): %ld\n", sv(0,0)); | ||
|
|
||
| // }); | ||
| // #endif | ||
| // } | ||
|
|
||
| // TEST(SubView, RangeFirstDimSubView2DGPU) | ||
| // { | ||
| // test_subviewGPU(); | ||
| // } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we not have this somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If not it would be good to add it in a more general header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. I'll look into moving this to camp.