-
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 all 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,268 @@ | ||||||||
| /*! | ||||||||
| ****************************************************************************** | ||||||||
| * | ||||||||
| * \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/macros.hpp" | ||||||||
| #include "RAJA/util/types.hpp" | ||||||||
| #include "camp/tuple.hpp" | ||||||||
| #include "camp/array.hpp" | ||||||||
|
|
||||||||
| namespace RAJA | ||||||||
| { | ||||||||
|
|
||||||||
| 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(const IndexType& idx) const { | ||||||||
| return start_ + idx; | ||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType DIM, typename LayoutType> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType size(const LayoutType&) const { | ||||||||
| return (end_ - start_ + 1); | ||||||||
| } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType stride() const { | ||||||||
| return 1; | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| template<typename IndexType = Index_type> | ||||||||
| struct RangeStartSlice { | ||||||||
| IndexType start_; | ||||||||
|
|
||||||||
| static constexpr bool reduces_dimension = false; | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(const IndexType& idx) const { | ||||||||
| return start_ + idx; | ||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType DIM, typename LayoutType> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType size(const LayoutType& layout) const { | ||||||||
| return (layout.size() - start_); | ||||||||
| } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType stride() const { | ||||||||
| return 1; | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| template<typename IndexType = Index_type> | ||||||||
| struct FixedSlice { | ||||||||
| IndexType idx_; | ||||||||
|
|
||||||||
| static constexpr bool reduces_dimension = true; | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(const IndexType&) const { | ||||||||
| return idx_; | ||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType DIM, typename LayoutType> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType size(const LayoutType&) const { | ||||||||
| return 1; | ||||||||
| } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType stride() const { | ||||||||
| return 1; | ||||||||
| } | ||||||||
|
|
||||||||
| }; | ||||||||
|
|
||||||||
| template<typename IndexType = Index_type> | ||||||||
| struct NoSlice { | ||||||||
| static constexpr bool reduces_dimension = false; | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(const IndexType& idx) const { | ||||||||
| return idx; | ||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType DIM, typename LayoutType> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType size(const LayoutType& layout) const { | ||||||||
| return layout.template get_dim_size<DIM>(); | ||||||||
| } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType stride() const { | ||||||||
| return 1; | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| template<typename IndexType = Index_type> | ||||||||
| struct StridedSlice { | ||||||||
| IndexType start_, end_, stride_; | ||||||||
|
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. Does this support negative strides? I'm pretty sure that the strided range supports negative strides.
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. It does support negative strides. For example, specifying stride = -1 is how we reverse the iteration order of a loop. |
||||||||
|
|
||||||||
| static constexpr bool reduces_dimension = false; | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType map_index(const IndexType& idx) const { | ||||||||
| return start_ + stride_ * idx; | ||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType DIM, typename LayoutType> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType size(const LayoutType&) const { | ||||||||
| return (end_ - start_) / stride_ + 1; | ||||||||
| } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType stride() const { | ||||||||
| return stride_; | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| template<typename IndexType, typename... Slices> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto make_slice_to_parent_index_map() { | ||||||||
| IndexType sub_idx = 0; | ||||||||
| IndexType i = 0; | ||||||||
| camp::array<IndexType, sizeof...(Slices)> map = {}; | ||||||||
|
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. Why not do something like this?
Suggested change
|
||||||||
| ((map[i++] = (Slices::reduces_dimension ? -1 : sub_idx++)), ...); | ||||||||
|
Comment on lines
+133
to
+134
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. Or even do something like this?
Suggested change
|
||||||||
| return map; | ||||||||
| } | ||||||||
|
|
||||||||
| template<typename IndexType, size_t n_parent_dims, typename... Slices> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto make_parent_to_slice_index_map() { | ||||||||
|
Comment on lines
+138
to
+139
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. Does it make more sense to take n_parent_dims as an argument or calculate it inside? |
||||||||
| IndexType sub_idx = 0; | ||||||||
| IndexType i = 0; | ||||||||
| camp::array<IndexType, n_parent_dims> map = {}; | ||||||||
|
|
||||||||
| auto process_slice = [&](auto slice_type) constexpr { | ||||||||
| if constexpr (!decltype(slice_type)::reduces_dimension) { | ||||||||
| map[sub_idx++] = i++; | ||||||||
| } else { | ||||||||
| i++; | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| (process_slice(Slices{}), ...); | ||||||||
|
|
||||||||
| return map; | ||||||||
| } | ||||||||
|
|
||||||||
| template <typename LayoutType, typename SliceTypes, typename IndexType = Index_type> | ||||||||
| struct SubRegion; | ||||||||
|
|
||||||||
| /* SubLayout is a semantic alias for a SubRegion whose parent is a layout */ | ||||||||
| template <typename LayoutType, typename SliceTypes, typename IndexType = Index_type> | ||||||||
| using SubLayout = SubRegion<LayoutType, SliceTypes, IndexType>; | ||||||||
|
|
||||||||
| /* SubView is a semantic alias for a SubRegion whose parent is a view */ | ||||||||
| template <typename LayoutType, typename SliceTypes, typename IndexType = Index_type> | ||||||||
| using SubView = SubRegion<LayoutType, SliceTypes, IndexType>; | ||||||||
|
|
||||||||
| template <typename LayoutType, typename IndexType, typename... Slices> | ||||||||
| struct SubRegion<LayoutType, camp::list<Slices...>, IndexType> { | ||||||||
|
|
||||||||
| using IndexLinear = IndexType; | ||||||||
|
|
||||||||
| const LayoutType& parent_; | ||||||||
|
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. Instead of having a copy of the parent this has a reference? What if you make the SubRegion on the host and then copy it to the device?
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. Also what do you think about using the member variables are named with m_ and static members are named with s_ convention? |
||||||||
| camp::tuple<Slices...> slices_; | ||||||||
|
|
||||||||
| static inline constexpr size_t num_slices_ = sizeof...(Slices); | ||||||||
|
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. Static data members and functions should be above non-static data members and functions. |
||||||||
|
|
||||||||
| static inline constexpr | ||||||||
| IndexType n_dims = ((Slices::reduces_dimension == false ? 1 : 0) + ...); | ||||||||
|
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. How about using
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. I like to have all the uses of something look similar if possible. I think this is often used like this |
||||||||
|
|
||||||||
| static inline constexpr | ||||||||
| camp::array<IndexType, num_slices_> slice_to_parent_map_ = | ||||||||
| make_slice_to_parent_index_map<IndexType, Slices...>(); | ||||||||
|
|
||||||||
| static inline constexpr | ||||||||
| camp::array<IndexType, n_dims> parent_to_slice_map_ = | ||||||||
| make_parent_to_slice_index_map<IndexType, n_dims, Slices...>(); | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr SubRegion(const LayoutType& parent, Slices... slices) | ||||||||
| : parent_(parent), slices_(slices...) { } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto& get_parent() const { | ||||||||
| return parent_; | ||||||||
| } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto& get_slices() const { | ||||||||
| return slices_; | ||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType Index> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto& get_slice() const { | ||||||||
| return camp::get<Index>(slices_); | ||||||||
| } | ||||||||
|
Comment on lines
+192
to
+203
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. Since there are const they should probably return const references. |
||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto size() const { | ||||||||
|
|
||||||||
| IndexType prod_dims = 1; | ||||||||
| for_each_tuple_index( slices_, | ||||||||
| [&](auto slice, auto index) { | ||||||||
| const IndexType dim_size = slice.template size<index>(parent_); | ||||||||
| prod_dims *= (dim_size == 0) ? 1 : dim_size; | ||||||||
|
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. If there really is a dimension that is completely projected out, shouldn't the size be 0?
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. Also do we have to consider the 0 dimension case? |
||||||||
| }); | ||||||||
|
|
||||||||
| return prod_dims; | ||||||||
| } | ||||||||
|
|
||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto size_noproj() const { | ||||||||
|
|
||||||||
| IndexType prod_dims = 1; | ||||||||
| for_each_tuple_index( slices_, | ||||||||
| [&](auto slice, auto index) { | ||||||||
| prod_dims *= slice.template size<index>(parent_); | ||||||||
| }); | ||||||||
|
|
||||||||
| return prod_dims; | ||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType DIM> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto get_dim_size() const { | ||||||||
| constexpr auto SliceDim = parent_to_slice_map_[DIM]; | ||||||||
| return camp::get<SliceDim>(slices_).template size<DIM>(parent_); | ||||||||
|
Comment on lines
+230
to
+231
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. We should be able to static_assert that DIM is in bounds. |
||||||||
| } | ||||||||
|
|
||||||||
| template<IndexType DIM> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto get_dim_stride() const { | ||||||||
| constexpr auto SliceDim = parent_to_slice_map_[DIM]; | ||||||||
| return camp::get<SliceDim>(slices_).stride(); | ||||||||
| } | ||||||||
|
|
||||||||
| template <typename... Idxs> | ||||||||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto operator()(Idxs... idxs) const { | ||||||||
| static_assert(sizeof...(idxs) == n_dims, "Wrong number of indices"); | ||||||||
|
|
||||||||
| camp::array<IndexType, n_dims> arr{idxs...}; | ||||||||
| camp::array<IndexType, num_slices_> parent_indices; | ||||||||
|
|
||||||||
| for_each_tuple_index( slices_, | ||||||||
| [&](auto slice, auto index) { | ||||||||
| if (slice_to_parent_map_[index] >= 0) { | ||||||||
|
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. should this be if constexpr? |
||||||||
| parent_indices[index] = slice.map_index(arr[slice_to_parent_map_[index]]); | ||||||||
| } else { | ||||||||
| // map_index will not need index values for dimension-reducing slices | ||||||||
| // so we pass a "dummy" value. | ||||||||
| constexpr IndexType dummy_value = -1; | ||||||||
| parent_indices[index] = slice.map_index(dummy_value); | ||||||||
|
Comment on lines
+252
to
+255
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. Should dimension reducing slices not take a value at all? |
||||||||
| } | ||||||||
| }); | ||||||||
|
|
||||||||
| return camp::apply(parent_, parent_indices); | ||||||||
| } | ||||||||
| }; | ||||||||
|
|
||||||||
| template <typename LayoutType, typename... Slices> | ||||||||
| SubRegion(LayoutType, Slices...) -> SubRegion<LayoutType, camp::list<Slices...>>; | ||||||||
|
|
||||||||
| } // namespace RAJA | ||||||||
|
|
||||||||
| #endif | ||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -669,16 +669,31 @@ class ViewBase | |
| constexpr layout_type const& get_layout() const { return m_layout; } | ||
|
|
||
| RAJA_HOST_DEVICE | ||
|
|
||
| RAJA_INLINE | ||
| constexpr linear_index_type size() const { return m_layout.size(); } | ||
|
|
||
| RAJA_HOST_DEVICE | ||
|
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. changes to View and MultiView are still a WIP. |
||
| RAJA_INLINE | ||
| constexpr linear_index_type size_noproj() const { return m_layout.size_noproj(); } | ||
|
|
||
| template<camp::idx_t DIM> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr linear_index_type get_dim_stride() const | ||
| { | ||
| return m_layout.template get_dim_stride<DIM>(); | ||
| } | ||
|
|
||
| template<camp::idx_t DIM> | ||
| RAJA_HOST_DEVICE RAJA_INLINE constexpr linear_index_type get_dim_size() const | ||
| { | ||
| return m_layout.template get_dim_size<DIM>(); | ||
| } | ||
|
|
||
| template<camp::idx_t DIM> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr linear_index_type get_dim_begin() const | ||
| { | ||
| return m_layout.template get_dim_begin<DIM>(); | ||
| } | ||
|
|
||
| template<typename... Args> | ||
| RAJA_HOST_DEVICE RAJA_INLINE constexpr view_return_type_t<value_type, | ||
| pointer_type, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
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.
Why is DIM here? If its unused we should use the unused arg macro so we don't get a warning.
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.
Also why the +1, this is including end?