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.
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.
Do we not have this somewhere?
There was a problem hiding this comment.
If not it would be good to add it in a more general header.
There was a problem hiding this comment.
Agreed. I'll look into moving this to camp.
804abcd to
5ba920d
Compare
|
|
||
| } | ||
|
|
||
| // void test_subviewGPU() { |
There was a problem hiding this comment.
To Do: Fix GPU tests.
include/RAJA/util/SubView.hpp
Outdated
| ViewType view_; | ||
| camp::tuple<Slices...> slices_; |
There was a problem hiding this comment.
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.
@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.
Added set_slice to allow things like "sliding windows"
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.
This should be a static member variable of the class.
There was a problem hiding this comment.
It would be nice to have something like num_slices as well.
There was a problem hiding this comment.
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.
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.
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.
| 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.
| 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.
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.
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.
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.
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.
Does this support negative strides? I'm pretty sure that the strided range supports negative strides.
There was a problem hiding this comment.
It does support negative strides. For example, specifying stride = -1 is how we reverse the iteration order of a loop.
| 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.
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.
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.
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.
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.
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.
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.
How about using Slices::reduces_dimension as a boolean if its a boolean?
There was a problem hiding this comment.
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.
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.
If there really is a dimension that is completely projected out, shouldn't the size be 0?
There was a problem hiding this comment.
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.
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) { |
| // 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.
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.