RAJA
RAJA provides a collection of platform portability abstractions for C++ HPC applications.
Tile.hpp
Go to the documentation of this file.
1 
11 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
12 // Copyright (c) Lawrence Livermore National Security, LLC and other
13 // RAJA Project Developers. See top-level LICENSE and COPYRIGHT
14 // files for dates and other details. No copyright assignment is required
15 // to contribute to RAJA.
16 //
17 // SPDX-License-Identifier: (BSD-3-Clause)
18 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
19 
20 #ifndef RAJA_pattern_kernel_Tile_HPP
21 #define RAJA_pattern_kernel_Tile_HPP
22 
23 #include "RAJA/config.hpp"
24 
25 #include <iostream>
26 #include <type_traits>
27 
28 #include "camp/camp.hpp"
29 #include "camp/concepts.hpp"
30 #include "camp/tuple.hpp"
31 
33 #include "RAJA/util/macros.hpp"
34 #include "RAJA/util/types.hpp"
35 
36 namespace RAJA
37 {
38 
39 struct TileSize
40 {
41  const camp::idx_t size;
42 
44 
45  RAJA_INLINE
46  constexpr TileSize(camp::idx_t size_) : size {size_} {}
47 };
48 
49 namespace statement
50 {
51 
52 
57 template<camp::idx_t ArgumentId,
58  typename TilePolicy,
59  typename ExecPolicy,
60  typename... EnclosedStmts>
61 struct Tile : public internal::Statement<ExecPolicy, EnclosedStmts...>
62 {
63  using tile_policy_t = TilePolicy;
65 };
66 
67 } // end namespace statement
68 
70 template<camp::idx_t chunk_size_>
71 struct tile_fixed
72 {
73  static constexpr camp::idx_t chunk_size = chunk_size_;
74 };
75 
76 template<camp::idx_t ArgumentId>
78 {
79  static constexpr camp::idx_t id = ArgumentId;
80 };
81 
82 namespace internal
83 {
84 
90 template<camp::idx_t ArgumentId,
91  typename Data,
92  typename Types,
93  typename... EnclosedStmts>
94 struct TileWrapper : public GenericWrapper<Data, Types, EnclosedStmts...>
95 {
96 
97  using Base = GenericWrapper<Data, Types, EnclosedStmts...>;
98  using Base::Base;
100 
101  template<typename InSegmentIndexType>
102  RAJA_INLINE void operator()(InSegmentIndexType si)
103  {
104  // Assign the tile's segment to the tuple
105  camp::get<ArgumentId>(Base::data.segment_tuple) = si.s;
106 
107  // Execute enclosed statements
108  Base::exec();
109  }
110 };
111 
112 template<typename Iterable>
114 {
115  using value_type = camp::decay<Iterable>;
116 
117  struct iterate
118  {
121  };
122 
123  class iterator
124  {
125  // NOTE: this must be held by value for NVCC support, *even on the host*
126  const IterableTiler itiler;
127  const Index_type block_id;
128 
129  public:
131  using difference_type = camp::idx_t;
132  using pointer = value_type*;
134  using iterator_category = std::random_access_iterator_tag;
135 
137 
138  RAJA_INLINE
139  constexpr iterator(IterableTiler const& itiler_, Index_type block_id_)
140  : itiler {itiler_},
141  block_id {block_id_}
142  {}
143 
145 
146  RAJA_INLINE
148  {
149  auto start = block_id * itiler.block_size;
150  return iterate {itiler.it.slice(start, itiler.block_size), block_id};
151  }
152 
154  RAJA_INLINE difference_type operator-(const iterator& rhs) const
155  {
156  return static_cast<difference_type>(block_id) -
157  static_cast<difference_type>(rhs.block_id);
158  }
159 
161  RAJA_INLINE iterator operator-(const difference_type& rhs) const
162  {
163  return iterator(itiler, block_id - rhs);
164  }
165 
167  RAJA_INLINE iterator operator+(const difference_type& rhs) const
168  {
169  return iterator(itiler, block_id + rhs >= itiler.num_blocks
170  ? itiler.num_blocks
171  : block_id + rhs);
172  }
173 
175  RAJA_INLINE value_type operator[](difference_type rhs) const
176  {
177  return *((*this) + rhs);
178  }
179 
181  RAJA_INLINE bool operator!=(const iterator& rhs) const
182  {
183  return block_id != rhs.block_id;
184  }
185 
187  RAJA_INLINE bool operator<(const iterator& rhs) const
188  {
189  return block_id < rhs.block_id;
190  }
191  };
192 
194 
195  RAJA_INLINE
196  IterableTiler(const Iterable& it_, camp::idx_t block_size_)
197  : it {it_},
198  block_size {block_size_}
199  {
200  using std::begin;
201  using std::distance;
202  using std::end;
203  dist = it.end() - it.begin(); // distance(begin(it), end(it));
205  // if (dist % block_size) num_blocks += 1;
206  if (dist - num_blocks * block_size > 0)
207  {
208  num_blocks += 1;
209  }
210  }
211 
213 
214  RAJA_INLINE
215  iterator begin() const { return iterator(*this, 0); }
216 
218 
219  RAJA_INLINE
220  iterator end() const { return iterator(*this, num_blocks); }
221 
223  camp::idx_t block_size;
224  camp::idx_t num_blocks;
225  camp::idx_t dist;
226 };
227 
233 template<camp::idx_t ArgumentId,
234  camp::idx_t ChunkSize,
235  typename EPol,
236  typename... EnclosedStmts,
237  typename Types>
239  statement::Tile<ArgumentId, tile_fixed<ChunkSize>, EPol, EnclosedStmts...>,
240  Types>
241 {
242 
243  template<typename Data>
244  static RAJA_INLINE void exec(Data& data)
245  {
246  // Get the segment we are going to tile
247  auto const& segment = camp::get<ArgumentId>(data.segment_tuple);
248 
249  // Get the tiling policies chunk size
250  auto chunk_size = tile_fixed<ChunkSize>::chunk_size;
251 
252  // Create a tile iterator, needs to survive until the forall is
253  // done executing.
254  IterableTiler<decltype(segment)> tiled_iterable(segment, chunk_size);
255 
256  // Wrap in case forall_impl needs to thread_privatize
257  TileWrapper<ArgumentId, Data, Types, EnclosedStmts...> tile_wrapper(data);
258 
259  // Loop over tiles, executing enclosed statement list
261  forall_impl(r, EPol {}, tiled_iterable, tile_wrapper,
262  RAJA::expt::get_empty_forall_param_pack());
263 
264  // Set range back to original values
265  camp::get<ArgumentId>(data.segment_tuple) = tiled_iterable.it;
266  }
267 };
268 
269 template<camp::idx_t ArgumentId,
270  typename EPol,
271  typename... EnclosedStmts,
272  typename Types>
274  statement::
275  Tile<ArgumentId, tile_dynamic<ArgumentId>, EPol, EnclosedStmts...>,
276  Types>
277 {
278 
279  template<typename Data>
280  static RAJA_INLINE void exec(Data& data)
281  {
282  // Get the segment we are going to tile
283  auto const& segment = camp::get<ArgumentId>(data.segment_tuple);
284 
285  // Get the tiling policies chunk size
286  auto chunk_size = camp::get<ArgumentId>(data.param_tuple);
287  static_assert(
288  camp::concepts::metalib::is_same<TileSize, decltype(chunk_size)>::value,
289  "Extracted parameter must be of type TileSize.");
290 
291  // Create a tile iterator
292  IterableTiler<decltype(segment)> tiled_iterable(segment, chunk_size.size);
293 
294  // Wrap in case forall_impl needs to thread_privatize
295  TileWrapper<ArgumentId, Data, Types, EnclosedStmts...> tile_wrapper(data);
296 
297  // Loop over tiles, executing enclosed statement list
299  forall_impl(r, EPol {}, tiled_iterable, tile_wrapper,
300  RAJA::expt::get_empty_forall_param_pack());
301 
302  // Set range back to original values
303  camp::get<ArgumentId>(data.segment_tuple) = tiled_iterable.it;
304  }
305 };
306 
307 } // end namespace internal
308 } // end namespace RAJA
309 
310 #endif /* RAJA_pattern_kernel_HPP */
RAJA_HOST_DEVICE RAJA_INLINE bool operator<(const iterator &rhs) const
Definition: Tile.hpp:187
std::random_access_iterator_tag iterator_category
Definition: Tile.hpp:134
RAJA_HOST_DEVICE RAJA_INLINE bool operator!=(const iterator &rhs) const
Definition: Tile.hpp:181
RAJA_HOST_DEVICE RAJA_INLINE value_type operator[](difference_type rhs) const
Definition: Tile.hpp:175
RAJA_HOST_DEVICE constexpr RAJA_INLINE iterator(IterableTiler const &itiler_, Index_type block_id_)
Definition: Tile.hpp:139
RAJA_HOST_DEVICE RAJA_INLINE iterator operator+(const difference_type &rhs) const
Definition: Tile.hpp:167
RAJA_HOST_DEVICE RAJA_INLINE iterator operator-(const difference_type &rhs) const
Definition: Tile.hpp:161
camp::idx_t difference_type
Definition: Tile.hpp:131
RAJA_HOST_DEVICE RAJA_INLINE difference_type operator-(const iterator &rhs) const
Definition: Tile.hpp:154
RAJA_HOST_DEVICE RAJA_INLINE value_type operator*()
Definition: Tile.hpp:147
Header file for common RAJA internal macro definitions.
#define RAJA_HOST_DEVICE
Definition: macros.hpp:65
RAJA_INLINE void forall_impl(MultiPolicy< Selector, Policies... > p, Iterable &&iter, Body &&body)
Definition: MultiPolicy.hpp:96
Definition: AlignedRangeIndexSetBuilders.cpp:35
std::ptrdiff_t Index_type
Definition: types.hpp:226
Header file for loop kernel internals.
Definition: Tile.hpp:40
RAJA_HOST_DEVICE constexpr RAJA_INLINE TileSize(camp::idx_t size_)
Definition: Tile.hpp:46
const camp::idx_t size
Definition: Tile.hpp:41
Definition: LoopData.hpp:196
RAJA_INLINE void exec()
Definition: LoopData.hpp:205
Index_type i
Definition: Tile.hpp:120
value_type s
Definition: Tile.hpp:119
Definition: Tile.hpp:114
camp::idx_t num_blocks
Definition: Tile.hpp:224
RAJA_HOST_DEVICE RAJA_INLINE iterator begin() const
Definition: Tile.hpp:215
value_type it
Definition: Tile.hpp:222
camp::decay< Iterable > value_type
Definition: Tile.hpp:115
RAJA_HOST_DEVICE RAJA_INLINE iterator end() const
Definition: Tile.hpp:220
RAJA_HOST_DEVICE RAJA_INLINE IterableTiler(const Iterable &it_, camp::idx_t block_size_)
Definition: Tile.hpp:196
camp::idx_t block_size
Definition: Tile.hpp:223
camp::idx_t dist
Definition: Tile.hpp:225
Definition: LoopData.hpp:216
Definition: Statement.hpp:48
Definition: Statement.hpp:35
Definition: Tile.hpp:95
RAJA_INLINE void operator()(InSegmentIndexType si)
Definition: Tile.hpp:102
Definition: IndexSet.hpp:70
Definition: resource.hpp:48
Definition: Tile.hpp:62
TilePolicy tile_policy_t
Definition: Tile.hpp:63
Definition: Tile.hpp:78
! tag for a tiling loop
Definition: Tile.hpp:72
static constexpr camp::idx_t chunk_size
Definition: Tile.hpp:73
Header file for RAJA type definitions.