-
Notifications
You must be signed in to change notification settings - Fork 109
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
Conversation
|
This PR is still a WIP! |
include/RAJA/util/SubView.hpp
Outdated
| struct RangeSlice { long start, end; }; | ||
| struct FixedSlice { long idx; }; | ||
| struct NoSlice { }; |
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.
We will probably want to generalize the integer types used in the slices. We will probably want to add strongly typed slices like the strongly typed indices.
include/RAJA/util/SubView.hpp
Outdated
| 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>{}); | ||
| } |
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.
804abcd to
5ba920d
Compare
|
|
||
| } | ||
|
|
||
| // void 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.
To Do: Fix GPU tests.
include/RAJA/util/SubView.hpp
Outdated
| ViewType view_; | ||
| camp::tuple<Slices...> slices_; |
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.
Should there be a static assert that the dimensionality of the view and number of slices match?
| EXPECT_EQ(sv(1,2), 9); | ||
|
|
||
| } | ||
|
|
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.
@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 ?
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.
Added set_slice to allow things like "sliding windows"
include/RAJA/util/SubView.hpp
Outdated
| class SubView<ViewType, camp::list<Slices...>, IndexType> { | ||
| ViewType view_; | ||
| camp::tuple<Slices...> slices_; | ||
| std::array<IndexType, sizeof...(Slices)> map_; |
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.
Still need to make this static inline constexpr
include/RAJA/util/SubView.hpp
Outdated
| size_t sub_idx = 0; | ||
| std::array<IndexType, sizeof...(Slices)> map; | ||
|
|
||
| for_each_tuple_index( slices_, |
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.
This looks great. Unfortunately it uses a non-static member to do something static.
include/RAJA/util/SubView.hpp
Outdated
|
|
||
| template <typename... Idxs> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType operator()(Idxs... idxs) const { | ||
| constexpr size_t nidx = ((Slices::reduces_dimension == false ? 1 : 0) + ...); |
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.
This should be a static member variable of the class.
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 would be nice to have something like num_slices as well.
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 would also be nice to have a bit more descriptive names.
include/RAJA/util/SubView.hpp
Outdated
|
|
||
| for_each_tuple_index( slices_, | ||
| [&](auto slice, auto index) { | ||
| parent_indices[index] = slice.map_index(arr[map_[index]]); |
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.
This causes out of bounds accesses for slices that reduce dimensions.
include/RAJA/util/SubView.hpp
Outdated
| parent_indices[index] = slice.map_index(arr[map_[index]]); | ||
| }); | ||
|
|
||
| return camp::apply(view_, array_to_tuple(parent_indices)); |
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 not just use a tuple to start with?
include/RAJA/util/for_each.hpp
Outdated
| { | ||
| using camp::get; | ||
| // braced init lists are evaluated in order | ||
| int seq_unused_array[] = {0, (func(get<Is>(std::forward<Tuple>(t)), Is), 0)...}; |
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)...}; |
include/RAJA/util/for_each.hpp
Outdated
| template<typename UnaryFunc, typename IndexType, IndexType... 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.
| 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.
You mean something more like making a SubLayout that you can use anywhere a layout can be used? |
Yes, but the intent is that these "sub-layouts" are only used with SubViews. I will try to prototype something here soon. |
We'd have to think about it. It seems simpler to me if you can use a sublayout like a layout, that way a subview would just be a view using a sublayout. |
| RAJA_INLINE | ||
| constexpr linear_index_type size() const { return m_layout.size(); } | ||
|
|
||
| RAJA_HOST_DEVICE |
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.
changes to View and MultiView are still a WIP.
| template<IndexType DIM, typename LayoutType> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr IndexType size(const LayoutType&) const { | ||
| return (end_ - start_ + 1); | ||
| } |
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?
|
|
||
| template<typename IndexType = Index_type> | ||
| struct StridedSlice { | ||
| IndexType start_, end_, stride_; |
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.
Does this support negative strides? I'm pretty sure that the strided range supports negative strides.
| 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 = {}; |
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 not do something like this?
| camp::array<IndexType, sizeof...(Slices)> map = {}; | |
| camp::array<IndexType, sizeof...(Slices)> map{}; |
| camp::array<IndexType, sizeof...(Slices)> map = {}; | ||
| ((map[i++] = (Slices::reduces_dimension ? -1 : sub_idx++)), ...); |
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.
Or even do something like this?
| camp::array<IndexType, sizeof...(Slices)> map = {}; | |
| ((map[i++] = (Slices::reduces_dimension ? -1 : sub_idx++)), ...); | |
| camp::array<IndexType, sizeof...(Slices)> map{{(Slices::reduces_dimension ? -1 : sub_idx++)...}}; |
| template<typename IndexType, size_t n_parent_dims, typename... Slices> | ||
| RAJA_INLINE RAJA_HOST_DEVICE constexpr auto make_parent_to_slice_index_map() { |
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.
Does it make more sense to take n_parent_dims as an argument or calculate it inside?
|
|
||
| using IndexLinear = IndexType; | ||
|
|
||
| const LayoutType& parent_; |
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.
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?
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 what do you think about using the member variables are named with m_ and static members are named with s_ convention?
| const LayoutType& parent_; | ||
| camp::tuple<Slices...> slices_; | ||
|
|
||
| static inline constexpr size_t num_slices_ = sizeof...(Slices); |
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.
Static data members and functions should be above non-static data members and functions.
| static inline constexpr size_t num_slices_ = sizeof...(Slices); | ||
|
|
||
| static inline constexpr | ||
| IndexType n_dims = ((Slices::reduces_dimension == false ? 1 : 0) + ...); |
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.
How about using Slices::reduces_dimension as a boolean if its a boolean?
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.
I like to have all the uses of something look similar if possible. I think this is often used like this !Slices::reduces_dimension so it would be simpler to understand if this also looked the same.
| 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_); | ||
| } |
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.
Since there are const they should probably return const references.
| 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; |
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 there really is a dimension that is completely projected out, shouldn't the size be 0?
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 do we have to consider the 0 dimension case?
| constexpr auto SliceDim = parent_to_slice_map_[DIM]; | ||
| return camp::get<SliceDim>(slices_).template size<DIM>(parent_); |
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.
We should be able to static_assert that DIM is in bounds.
|
|
||
| for_each_tuple_index( slices_, | ||
| [&](auto slice, auto index) { | ||
| if (slice_to_parent_map_[index] >= 0) { |
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.
should this be if constexpr?
| // 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); |
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.
Should dimension reducing slices not take a value at all?
Summary
A few simple examples are provided below:
Here,
sv1andsv2are subviews of dimensions(2,3)and(2)respectively.