CMS 3D CMS Logo

workdivision.h
Go to the documentation of this file.
1 #ifndef HeterogeneousCore_AlpakaInterface_interface_workdivision_h
2 #define HeterogeneousCore_AlpakaInterface_interface_workdivision_h
3 
4 #include <type_traits>
5 
6 #include <alpaka/alpaka.hpp>
7 
10 
11 namespace cms::alpakatools {
12 
13  using namespace alpaka_common;
14 
15  // If the first argument is not a multiple of the second argument, round it up to the next multiple
16  inline constexpr Idx round_up_by(Idx value, Idx divisor) { return (value + divisor - 1) / divisor * divisor; }
17 
18  // Return the integer division of the first argument by the second argument, rounded up to the next integer
19  inline constexpr Idx divide_up_by(Idx value, Idx divisor) { return (value + divisor - 1) / divisor; }
20 
21  // Trait describing whether or not the accelerator expects the threads-per-block and elements-per-thread to be swapped
22  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
23  struct requires_single_thread_per_block : public std::true_type {};
24 
25 #ifdef ALPAKA_ACC_GPU_CUDA_ENABLED
26  template <typename TDim>
27  struct requires_single_thread_per_block<alpaka::AccGpuCudaRt<TDim, Idx>> : public std::false_type {};
28 #endif // ALPAKA_ACC_GPU_CUDA_ENABLED
29 
30 #ifdef ALPAKA_ACC_GPU_HIP_ENABLED
31  template <typename TDim>
32  struct requires_single_thread_per_block<alpaka::AccGpuHipRt<TDim, Idx>> : public std::false_type {};
33 #endif // ALPAKA_ACC_GPU_HIP_ENABLED
34 
35 #ifdef ALPAKA_ACC_CPU_B_SEQ_T_THREADS_ENABLED
36  template <typename TDim>
37  struct requires_single_thread_per_block<alpaka::AccCpuThreads<TDim, Idx>> : public std::false_type {};
38 #endif // ALPAKA_ACC_CPU_B_SEQ_T_THREADS_ENABLED
39 
40  // Whether or not the accelerator expects the threads-per-block and elements-per-thread to be swapped
41  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
43 
44  // Create an accelerator-dependent work division for 1-dimensional kernels
45  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc> and alpaka::Dim<TAcc>::value == 1>>
47  if constexpr (not requires_single_thread_per_block_v<TAcc>) {
48  // On GPU backends, each thread is looking at a single element:
49  // - the number of threads per block is "elements";
50  // - the number of elements per thread is always 1.
51  return WorkDiv<Dim1D>(blocks, elements, Idx{1});
52  } else {
53  // On CPU backends, run serially with a single thread per block:
54  // - the number of threads per block is always 1;
55  // - the number of elements per thread is "elements".
56  return WorkDiv<Dim1D>(blocks, Idx{1}, elements);
57  }
58  }
59 
60  // Create the accelerator-dependent workdiv for N-dimensional kernels
61  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
62  inline WorkDiv<alpaka::Dim<TAcc>> make_workdiv(const Vec<alpaka::Dim<TAcc>>& blocks,
63  const Vec<alpaka::Dim<TAcc>>& elements) {
64  using Dim = alpaka::Dim<TAcc>;
65  if constexpr (not requires_single_thread_per_block_v<TAcc>) {
66  // On GPU backends, each thread is looking at a single element:
67  // - the number of threads per block is "elements";
68  // - the number of elements per thread is always 1.
70  } else {
71  // On CPU backends, run serially with a single thread per block:
72  // - the number of threads per block is always 1;
73  // - the number of elements per thread is "elements".
75  }
76  }
77 
78  /* ElementIndex
79  *
80  * an aggregate that containes the .global and .local indices of an element; returned by iterating over elements_in_block.
81  */
82 
83  struct ElementIndex {
86  };
87 
88  /* elements_with_stride
89  */
90 
91  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc> and alpaka::Dim<TAcc>::value == 1>>
93  public:
94  ALPAKA_FN_ACC inline elements_with_stride(TAcc const& acc)
95  : elements_{alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)[0u]},
96  thread_{alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0u] * elements_},
97  stride_{alpaka::getWorkDiv<alpaka::Grid, alpaka::Threads>(acc)[0u] * elements_},
98  extent_{stride_} {}
99 
100  ALPAKA_FN_ACC inline elements_with_stride(TAcc const& acc, Idx extent)
101  : elements_{alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)[0u]},
102  thread_{alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc)[0u] * elements_},
103  stride_{alpaka::getWorkDiv<alpaka::Grid, alpaka::Threads>(acc)[0u] * elements_},
104  extent_{extent} {}
105 
106  class iterator {
107  friend class elements_with_stride;
108 
109  ALPAKA_FN_ACC inline iterator(Idx elements, Idx stride, Idx extent, Idx first)
110  : elements_{elements},
111  stride_{stride},
112  extent_{extent},
113  first_{std::min(first, extent)},
114  index_{first_},
115  range_{std::min(first + elements, extent)} {}
116 
117  public:
118  ALPAKA_FN_ACC inline Idx operator*() const { return index_; }
119 
120  // pre-increment the iterator
121  ALPAKA_FN_ACC inline iterator& operator++() {
122  if constexpr (requires_single_thread_per_block_v<TAcc>) {
123  // increment the index along the elements processed by the current thread
124  ++index_;
125  if (index_ < range_)
126  return *this;
127  }
128 
129  // increment the thread index with the grid stride
130  first_ += stride_;
131  index_ = first_;
132  range_ = std::min(first_ + elements_, extent_);
133  if (index_ < extent_)
134  return *this;
135 
136  // the iterator has reached or passed the end of the extent, clamp it to the extent
137  first_ = extent_;
138  index_ = extent_;
139  range_ = extent_;
140  return *this;
141  }
142 
143  // post-increment the iterator
144  ALPAKA_FN_ACC inline iterator operator++(int) {
145  iterator old = *this;
146  ++(*this);
147  return old;
148  }
149 
150  ALPAKA_FN_ACC inline bool operator==(iterator const& other) const {
151  return (index_ == other.index_) and (first_ == other.first_);
152  }
153 
154  ALPAKA_FN_ACC inline bool operator!=(iterator const& other) const { return not(*this == other); }
155 
156  private:
157  // non-const to support iterator copy and assignment
161  // modified by the pre/post-increment operator
165  };
166 
167  ALPAKA_FN_ACC inline iterator begin() const { return iterator(elements_, stride_, extent_, thread_); }
168 
169  ALPAKA_FN_ACC inline iterator end() const { return iterator(elements_, stride_, extent_, extent_); }
170 
171  private:
172  const Idx elements_;
173  const Idx thread_;
174  const Idx stride_;
175  const Idx extent_;
176  };
177 
178  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc> and (alpaka::Dim<TAcc>::value > 0)>>
180  public:
181  using Dim = alpaka::Dim<TAcc>;
182  using Vec = alpaka::Vec<Dim, Idx>;
183 
184  ALPAKA_FN_ACC inline elements_with_stride_nd(TAcc const& acc)
185  : elements_{alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)},
186  thread_{alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc) * elements_},
187  stride_{alpaka::getWorkDiv<alpaka::Grid, alpaka::Threads>(acc) * elements_},
188  extent_{stride_} {}
189 
190  ALPAKA_FN_ACC inline elements_with_stride_nd(TAcc const& acc, Vec extent)
191  : elements_{alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)},
192  thread_{alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc) * elements_},
193  stride_{alpaka::getWorkDiv<alpaka::Grid, alpaka::Threads>(acc) * elements_},
194  extent_{extent} {}
195 
196  // tag used to construct an end iterator
197  struct at_end_t {};
198 
199  class iterator {
201 
202  public:
203  ALPAKA_FN_ACC inline Vec operator*() const { return index_; }
204 
205  // pre-increment the iterator
206  ALPAKA_FN_ACC constexpr inline iterator operator++() {
207  increment();
208  return *this;
209  }
210 
211  // post-increment the iterator
212  ALPAKA_FN_ACC constexpr inline iterator operator++(int) {
213  iterator old = *this;
214  increment();
215  return old;
216  }
217 
218  ALPAKA_FN_ACC constexpr inline bool operator==(iterator const& other) const { return (index_ == other.index_); }
219 
220  ALPAKA_FN_ACC constexpr inline bool operator!=(iterator const& other) const { return not(*this == other); }
221 
222  private:
223  // construct an iterator pointing to the first element to be processed by the current thread
224  ALPAKA_FN_ACC inline iterator(elements_with_stride_nd const* loop, Vec first)
225  : loop_{loop},
226  first_{alpaka::elementwise_min(first, loop->extent_)},
227  range_{alpaka::elementwise_min(first + loop->elements_, loop->extent_)},
228  index_{first_} {}
229 
230  // construct an end iterator, pointing post the end of the extent
231  ALPAKA_FN_ACC inline iterator(elements_with_stride_nd const* loop, at_end_t const&)
232  : loop_{loop}, first_{loop_->extent_}, range_{loop_->extent_}, index_{loop_->extent_} {}
233 
234  template <size_t I>
235  ALPAKA_FN_ACC inline constexpr bool nth_elements_loop() {
236  bool overflow = false;
237  ++index_[I];
238  if (index_[I] >= range_[I]) {
239  index_[I] = first_[I];
240  overflow = true;
241  }
242  return overflow;
243  }
244 
245  template <size_t N>
246  ALPAKA_FN_ACC inline constexpr bool do_elements_loops() {
247  if constexpr (N == 0) {
248  // overflow
249  return true;
250  } else {
251  if (not nth_elements_loop<N - 1>()) {
252  return false;
253  } else {
254  return do_elements_loops<N - 1>();
255  }
256  }
257  }
258 
259  template <size_t I>
260  ALPAKA_FN_ACC inline constexpr bool nth_strided_loop() {
261  bool overflow = false;
262  first_[I] += loop_->stride_[I];
263  if (first_[I] >= loop_->extent_[I]) {
264  first_[I] = loop_->thread_[I];
265  overflow = true;
266  }
267  index_[I] = first_[I];
268  range_[I] = std::min(first_[I] + loop_->elements_[I], loop_->extent_[I]);
269  return overflow;
270  }
271 
272  template <size_t N>
273  ALPAKA_FN_ACC inline constexpr bool do_strided_loops() {
274  if constexpr (N == 0) {
275  // overflow
276  return true;
277  } else {
278  if (not nth_strided_loop<N - 1>()) {
279  return false;
280  } else {
281  return do_strided_loops<N - 1>();
282  }
283  }
284  }
285 
286  // increment the iterator
287  ALPAKA_FN_ACC inline constexpr void increment() {
288  if constexpr (requires_single_thread_per_block_v<TAcc>) {
289  // linear N-dimensional loops over the elements associated to the thread;
290  // do_elements_loops<>() returns true if any of those loops overflows
291  if (not do_elements_loops<Dim::value>()) {
292  // the elements loops did not overflow, return the next index
293  return;
294  }
295  }
296 
297  // strided N-dimensional loop over the threads in the kernel launch grid;
298  // do_strided_loops<>() returns true if any of those loops overflows
299  if (not do_strided_loops<Dim::value>()) {
300  // the strided loops did not overflow, return the next index
301  return;
302  }
303 
304  // the iterator has reached or passed the end of the extent, clamp it to the extent
305  first_ = loop_->extent_;
306  range_ = loop_->extent_;
307  index_ = loop_->extent_;
308  }
309 
310  // const pointer to the elements_with_stride_nd that the iterator refers to
312 
313  // modified by the pre/post-increment operator
314  Vec first_; // first element processed by this thread
315  Vec range_; // last element processed by this thread
316  Vec index_; // current element processed by this thread
317  };
318 
319  ALPAKA_FN_ACC inline iterator begin() const {
320  // check that all dimensions of the current thread index are within the extent
321  if ((thread_ < extent_).all()) {
322  // construct an iterator pointing to the first element to be processed by the current thread
323  return iterator{this, thread_};
324  } else {
325  // construct an end iterator, pointing post the end of the extent
326  return iterator{this, at_end_t{}};
327  }
328  }
329 
330  ALPAKA_FN_ACC inline iterator end() const {
331  // construct an end iterator, pointing post the end of the extent
332  return iterator{this, at_end_t{}};
333  }
334 
335  private:
336  const Vec elements_;
337  const Vec thread_;
338  const Vec stride_;
339  const Vec extent_;
340  };
341 
342  /* blocks_with_stride
343  *
344  * `blocks_with_stride(acc, size)` returns a range than spans the (virtual) block indices required to cover the given
345  * problem size.
346  *
347  * For example, if size is 1000 and the block size is 16, it will return the range from 1 to 62.
348  * If the work division has more than 63 blocks, only the first 63 will perform one iteration of the loop, and the
349  * other will exit immediately.
350  * If the work division has less than 63 blocks, some of the blocks will perform more than one iteration, in order to
351  * cover then whole problem space.
352  *
353  * All threads in a block see the same loop iterations, while threads in different blocks may see a different number
354  * of iterations.
355  */
356 
357  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc> and alpaka::Dim<TAcc>::value == 1>>
359  public:
360  ALPAKA_FN_ACC inline blocks_with_stride(TAcc const& acc)
361  : first_{alpaka::getIdx<alpaka::Grid, alpaka::Blocks>(acc)[0u]},
362  stride_{alpaka::getWorkDiv<alpaka::Grid, alpaka::Blocks>(acc)[0u]},
363  extent_{stride_} {}
364 
365  // extent is the total number of elements (not blocks)
366  ALPAKA_FN_ACC inline blocks_with_stride(TAcc const& acc, Idx extent)
367  : first_{alpaka::getIdx<alpaka::Grid, alpaka::Blocks>(acc)[0u]},
368  stride_{alpaka::getWorkDiv<alpaka::Grid, alpaka::Blocks>(acc)[0u]},
369  extent_{divide_up_by(extent, alpaka::getWorkDiv<alpaka::Block, alpaka::Elems>(acc)[0u])} {}
370 
371  class iterator {
372  friend class blocks_with_stride;
373 
374  ALPAKA_FN_ACC inline iterator(Idx stride, Idx extent, Idx first)
375  : stride_{stride}, extent_{extent}, first_{std::min(first, extent)} {}
376 
377  public:
378  ALPAKA_FN_ACC inline Idx operator*() const { return first_; }
379 
380  // pre-increment the iterator
381  ALPAKA_FN_ACC inline iterator& operator++() {
382  // increment the first-element-in-block index by the grid stride
383  first_ += stride_;
384  if (first_ < extent_)
385  return *this;
386 
387  // the iterator has reached or passed the end of the extent, clamp it to the extent
388  first_ = extent_;
389  return *this;
390  }
391 
392  // post-increment the iterator
393  ALPAKA_FN_ACC inline iterator operator++(int) {
394  iterator old = *this;
395  ++(*this);
396  return old;
397  }
398 
399  ALPAKA_FN_ACC inline bool operator==(iterator const& other) const { return (first_ == other.first_); }
400 
401  ALPAKA_FN_ACC inline bool operator!=(iterator const& other) const { return not(*this == other); }
402 
403  private:
404  // non-const to support iterator copy and assignment
407  // modified by the pre/post-increment operator
409  };
410 
411  ALPAKA_FN_ACC inline iterator begin() const { return iterator(stride_, extent_, first_); }
412 
413  ALPAKA_FN_ACC inline iterator end() const { return iterator(stride_, extent_, extent_); }
414 
415  private:
416  const Idx first_;
417  const Idx stride_;
418  const Idx extent_;
419  };
420 
421  /* elements_in_block
422  *
423  * `elements_in_block(acc, block, size)` returns a range that spans all the elements within the given block.
424  * Iterating over the range yields values of type ElementIndex, that contain both .global and .local indices
425  * of the corresponding element.
426  *
427  * If the work division has only one element per thread, the loop will perform at most one iteration.
428  * If the work division has more than one elements per thread, the loop will perform that number of iterations,
429  * or less if it reaches size.
430  */
431 
432  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc> and alpaka::Dim<TAcc>::value == 1>>
434  public:
435  ALPAKA_FN_ACC inline elements_in_block(TAcc const& acc, Idx block)
436  : first_{block * alpaka::getWorkDiv<alpaka::Block, alpaka::Elems>(acc)[0u]},
437  local_{alpaka::getIdx<alpaka::Block, alpaka::Threads>(acc)[0u] *
438  alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)[0u]},
439  range_{local_ + alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)[0u]} {}
440 
441  ALPAKA_FN_ACC inline elements_in_block(TAcc const& acc, Idx block, Idx extent)
442  : first_{block * alpaka::getWorkDiv<alpaka::Block, alpaka::Elems>(acc)[0u]},
443  local_{std::min(extent - first_,
444  alpaka::getIdx<alpaka::Block, alpaka::Threads>(acc)[0u] *
445  alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)[0u])},
446  range_{std::min(extent - first_, local_ + alpaka::getWorkDiv<alpaka::Thread, alpaka::Elems>(acc)[0u])} {}
447 
448  class iterator {
449  friend class elements_in_block;
450 
451  ALPAKA_FN_ACC inline iterator(Idx local, Idx first, Idx range) : index_{local}, first_{first}, range_{range} {}
452 
453  public:
454  ALPAKA_FN_ACC inline ElementIndex operator*() const { return ElementIndex{index_ + first_, index_}; }
455 
456  // pre-increment the iterator
457  ALPAKA_FN_ACC inline iterator& operator++() {
458  if constexpr (requires_single_thread_per_block_v<TAcc>) {
459  // increment the index along the elements processed by the current thread
460  ++index_;
461  if (index_ < range_)
462  return *this;
463  }
464 
465  // the iterator has reached or passed the end of the extent, clamp it to the extent
466  index_ = range_;
467  return *this;
468  }
469 
470  // post-increment the iterator
471  ALPAKA_FN_ACC inline iterator operator++(int) {
472  iterator old = *this;
473  ++(*this);
474  return old;
475  }
476 
477  ALPAKA_FN_ACC inline bool operator==(iterator const& other) const { return (index_ == other.index_); }
478 
479  ALPAKA_FN_ACC inline bool operator!=(iterator const& other) const { return not(*this == other); }
480 
481  private:
482  // modified by the pre/post-increment operator
484  // non-const to support iterator copy and assignment
487  };
488 
489  ALPAKA_FN_ACC inline iterator begin() const { return iterator(local_, first_, range_); }
490 
491  ALPAKA_FN_ACC inline iterator end() const { return iterator(range_, first_, range_); }
492 
493  private:
494  const Idx first_;
495  const Idx local_;
496  const Idx range_;
497  };
498 
499  /* once_per_grid
500  *
501  * `once_per_grid(acc)` returns true for a single thread within the kernel execution grid.
502  *
503  * Usually the condition is true for block 0 and thread 0, but these indices should not be relied upon.
504  */
505 
506  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
507  ALPAKA_FN_ACC inline constexpr bool once_per_grid(TAcc const& acc) {
508  return alpaka::getIdx<alpaka::Grid, alpaka::Threads>(acc) == Vec<alpaka::Dim<TAcc>>::zeros();
509  }
510 
511  /* once_per_block
512  *
513  * `once_per_block(acc)` returns true for a single thread within the block.
514  *
515  * Usually the condition is true for thread 0, but this index should not be relied upon.
516  */
517 
518  template <typename TAcc, typename = std::enable_if_t<alpaka::isAccelerator<TAcc>>>
519  ALPAKA_FN_ACC inline constexpr bool once_per_block(TAcc const& acc) {
520  return alpaka::getIdx<alpaka::Block, alpaka::Threads>(acc) == Vec<alpaka::Dim<TAcc>>::zeros();
521  }
522 
523 } // namespace cms::alpakatools
524 
525 #endif // HeterogeneousCore_AlpakaInterface_interface_workdivision_h
ALPAKA_FN_ACC constexpr bool nth_strided_loop()
Definition: workdivision.h:260
ALPAKA_FN_ACC elements_with_stride_nd(TAcc const &acc, Vec extent)
Definition: workdivision.h:190
ALPAKA_FN_ACC constexpr bool once_per_block(TAcc const &acc)
Definition: workdivision.h:519
ALPAKA_FN_ACC constexpr bool operator==(iterator const &other) const
Definition: workdivision.h:218
ALPAKA_FN_ACC elements_with_stride(TAcc const &acc)
Definition: workdivision.h:94
ALPAKA_FN_ACC elements_in_block(TAcc const &acc, Idx block, Idx extent)
Definition: workdivision.h:441
WorkDiv< Dim1D > make_workdiv(Idx blocks, Idx elements)
Definition: workdivision.h:46
def all(container)
workaround iterator generators for ROOT classes
Definition: cmstools.py:25
constexpr Idx divide_up_by(Idx value, Idx divisor)
Definition: workdivision.h:19
ALPAKA_FN_ACC elements_with_stride(TAcc const &acc, Idx extent)
Definition: workdivision.h:100
ALPAKA_FN_ACC bool operator==(iterator const &other) const
Definition: workdivision.h:399
ALPAKA_FN_ACC iterator begin() const
Definition: workdivision.h:489
uint32_t Idx
Definition: config.h:14
ALPAKA_FN_ACC iterator begin() const
Definition: workdivision.h:167
ALPAKA_FN_ACC ElementIndex operator*() const
Definition: workdivision.h:454
ALPAKA_FN_ACC iterator(Idx local, Idx first, Idx range)
Definition: workdivision.h:451
ALPAKA_FN_ACC iterator end() const
Definition: workdivision.h:413
ALPAKA_FN_ACC elements_with_stride_nd(TAcc const &acc)
Definition: workdivision.h:184
ALPAKA_FN_ACC bool operator!=(iterator const &other) const
Definition: workdivision.h:479
alpaka::WorkDivMembers< TDim, Idx > WorkDiv
Definition: config.h:31
ALPAKA_FN_ACC iterator(elements_with_stride_nd const *loop, at_end_t const &)
Definition: workdivision.h:231
ALPAKA_FN_ACC constexpr bool nth_elements_loop()
Definition: workdivision.h:235
ALPAKA_FN_ACC iterator end() const
Definition: workdivision.h:491
ALPAKA_FN_ACC iterator end() const
Definition: workdivision.h:169
constexpr Idx round_up_by(Idx value, Idx divisor)
Definition: workdivision.h:16
ALPAKA_FN_ACC iterator(Idx elements, Idx stride, Idx extent, Idx first)
Definition: workdivision.h:109
const std::complex< double > I
Definition: I.h:8
Definition: value.py:1
ALPAKA_FN_ACC bool operator!=(iterator const &other) const
Definition: workdivision.h:401
ALPAKA_FN_ACC iterator end() const
Definition: workdivision.h:330
ALPAKA_FN_ACC constexpr iterator operator++()
Definition: workdivision.h:206
ALPAKA_FN_ACC iterator(Idx stride, Idx extent, Idx first)
Definition: workdivision.h:374
ALPAKA_FN_ACC iterator begin() const
Definition: workdivision.h:411
#define N
Definition: blowfish.cc:9
ALPAKA_FN_ACC bool operator==(iterator const &other) const
Definition: workdivision.h:477
alpaka::Vec< TDim, Idx > Vec
Definition: config.h:24
ALPAKA_FN_ACC elements_in_block(TAcc const &acc, Idx block)
Definition: workdivision.h:435
ALPAKA_FN_ACC constexpr bool once_per_grid(TAcc const &acc)
Definition: workdivision.h:507
ALPAKA_FN_ACC blocks_with_stride(TAcc const &acc, Idx extent)
Definition: workdivision.h:366
ALPAKA_FN_ACC constexpr bool do_elements_loops()
Definition: workdivision.h:246
ALPAKA_FN_ACC bool operator==(iterator const &other) const
Definition: workdivision.h:150
ALPAKA_FN_ACC iterator operator++(int)
Definition: workdivision.h:471
ALPAKA_FN_ACC iterator begin() const
Definition: workdivision.h:319
ALPAKA_FN_ACC constexpr iterator operator++(int)
Definition: workdivision.h:212
constexpr bool requires_single_thread_per_block_v
Definition: workdivision.h:42
ALPAKA_FN_ACC iterator(elements_with_stride_nd const *loop, Vec first)
Definition: workdivision.h:224
ALPAKA_FN_ACC blocks_with_stride(TAcc const &acc)
Definition: workdivision.h:360
ALPAKA_FN_ACC constexpr bool do_strided_loops()
Definition: workdivision.h:273
ALPAKA_FN_ACC constexpr bool operator!=(iterator const &other) const
Definition: workdivision.h:220
ALPAKA_FN_ACC bool operator!=(iterator const &other) const
Definition: workdivision.h:154