RAJA
RAJA provides a collection of platform portability abstractions for C++ HPC applications.
WorkRunner.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_WORKGROUP_WorkRunner_HPP
21 #define RAJA_PATTERN_WORKGROUP_WorkRunner_HPP
22 
23 #include "RAJA/config.hpp"
24 
25 #include <utility>
26 #include <type_traits>
27 
29 
30 #include "RAJA/pattern/forall.hpp"
31 
34 
35 namespace RAJA
36 {
37 
38 namespace detail
39 {
40 
44 template<typename LoopBody, typename... Args>
46 {
47  // NOTE: This constructor is disabled when body_in is not LoopBody
48  // to avoid it conflicting with the copy and move constructors
49  template<typename body_in,
50  typename = typename std::enable_if<
51  std::is_same<LoopBody, camp::decay<body_in>>::value>::type>
52  HoldBodyArgs_base(body_in&& body, Args... args)
53  : m_body(std::forward<body_in>(body)),
54  m_arg_tuple(std::forward<Args>(args)...)
55  {}
56 
57 protected:
58  LoopBody m_body;
59  camp::tuple<Args...> m_arg_tuple;
60 };
61 
66 template<typename LoopBody, typename index_type, typename... Args>
67 struct HoldBodyArgs_host : HoldBodyArgs_base<LoopBody, Args...>
68 {
69  using base = HoldBodyArgs_base<LoopBody, Args...>;
70  using base::base;
71 
72  RAJA_INLINE void operator()(index_type i) const
73  {
74  invoke(i, camp::make_idx_seq_t<sizeof...(Args)> {});
75  }
76 
77  template<camp::idx_t... Is>
78  RAJA_INLINE void invoke(index_type i, camp::idx_seq<Is...>) const
79  {
80  this->m_body(i, get<Is>(this->m_arg_tuple)...);
81  }
82 };
83 
88 template<typename LoopBody, typename index_type, typename... Args>
89 struct HoldBodyArgs_device : HoldBodyArgs_base<LoopBody, Args...>
90 {
91  using base = HoldBodyArgs_base<LoopBody, Args...>;
92  using base::base;
93 
94  RAJA_DEVICE RAJA_INLINE void operator()(index_type i) const
95  {
96  invoke(i, camp::make_idx_seq_t<sizeof...(Args)> {});
97  }
98 
99  template<camp::idx_t... Is>
100  RAJA_DEVICE RAJA_INLINE void invoke(index_type i, camp::idx_seq<Is...>) const
101  {
102  this->m_body(i, get<Is>(this->m_arg_tuple)...);
103  }
104 };
105 
109 template<typename ExecutionPolicy,
110  typename Segment_type,
111  typename LoopBody,
112  typename index_type,
113  typename... Args>
115 {
117  using HoldBodyArgs = typename std::conditional<
119  HoldBodyArgs_host<LoopBody, index_type, Args...>,
120  HoldBodyArgs_device<LoopBody, index_type, Args...>>::type;
121 
122  template<typename segment_in, typename body_in>
123  HoldForall(segment_in&& segment, body_in&& body)
124  : m_segment(std::forward<segment_in>(segment)),
125  m_body(std::forward<body_in>(body))
126  {}
127 
128  RAJA_INLINE void operator()(resource_type r, Args... args) const
129  {
130  wrap::forall(r, ExecutionPolicy(), m_segment,
131  HoldBodyArgs {m_body, std::forward<Args>(args)...});
132  }
133 
134 private:
135  Segment_type m_segment;
136  LoopBody m_body;
137 };
138 
139 
143 template<typename EXEC_POLICY_T,
144  typename ORDER_POLICY_T,
145  typename DISPATCH_POLICY_T,
146  typename ALLOCATOR_T,
147  typename INDEX_T,
148  typename... Args>
149 struct WorkRunner;
150 
154 template<typename FORALL_EXEC_POLICY,
155  typename EXEC_POLICY_T,
156  typename ORDER_POLICY_T,
157  typename DISPATCH_POLICY_T,
158  typename ALLOCATOR_T,
159  typename INDEX_T,
160  typename... Args>
162 {
163  using exec_policy = EXEC_POLICY_T;
164  using order_policy = ORDER_POLICY_T;
165  using dispatch_policy = DISPATCH_POLICY_T;
166  using Allocator = ALLOCATOR_T;
167  using index_type = INDEX_T;
170 
171  using forall_exec_policy = FORALL_EXEC_POLICY;
172 
173  // The type that will hold the segment and loop body in work storage
174  struct holder_type
175  {
176  template<typename T>
177  using type =
179  typename camp::at<T, camp::num<0>>::type, // segment_type
180  typename camp::at<T, camp::num<1>>::type, // loop_type
181  index_type,
182  Args...>;
183  };
184 
186  template<typename T>
187  using holder_type_t = typename holder_type::template type<T>;
188 
189  // The policy indicating where the call function is invoked
190  // in this case the values are called on the host in a loop
192 
193  // The Dispatcher policy with holder_types used internally to handle the
194  // ranges and callables passed in by the user.
197 
198  using dispatcher_type = Dispatcher<Platform::host,
200  void,
202  Args...>;
203 
205 
208  delete;
209 
212  default;
213 
214  // runner interfaces with storage to enqueue so the runner can get
215  // information from the segment and loop at enqueue time
216  template<typename WorkContainer, typename segment_T, typename loop_T>
217  inline void enqueue(WorkContainer& storage, segment_T&& seg, loop_T&& loop)
218  {
219  using holder =
221 
222  storage.template emplace<holder>(
223  get_Dispatcher<holder, dispatcher_type>(dispatcher_exec_policy {}),
224  std::forward<segment_T>(seg), std::forward<loop_T>(loop));
225  }
226 
227  // clear any state so ready to be destroyed or reused
228  void clear() {}
229 
230  // no extra storage required here
231  using per_run_storage = int;
232 };
233 
237 template<typename FORALL_EXEC_POLICY,
238  typename EXEC_POLICY_T,
239  typename ORDER_POLICY_T,
240  typename DISPATCH_POLICY_T,
241  typename ALLOCATOR_T,
242  typename INDEX_T,
243  typename... Args>
245  : WorkRunnerForallOrdered_base<FORALL_EXEC_POLICY,
246  EXEC_POLICY_T,
247  ORDER_POLICY_T,
248  DISPATCH_POLICY_T,
249  ALLOCATOR_T,
250  INDEX_T,
251  Args...>
252 {
253  using base = WorkRunnerForallOrdered_base<FORALL_EXEC_POLICY,
254  EXEC_POLICY_T,
255  ORDER_POLICY_T,
256  DISPATCH_POLICY_T,
257  ALLOCATOR_T,
258  INDEX_T,
259  Args...>;
260  using base::base;
261 
262  // run the loops using forall in the order that they were enqueued
263  template<typename WorkContainer>
264  typename base::per_run_storage run(WorkContainer const& storage,
265  typename base::resource_type r,
266  Args... args) const
267  {
268  using value_type = typename WorkContainer::value_type;
269 
270  typename base::per_run_storage run_storage {};
271 
272  auto end = storage.end();
273  for (auto iter = storage.begin(); iter != end; ++iter)
274  {
275  value_type::host_call(&*iter, r, args...);
276  }
277 
278  return run_storage;
279  }
280 };
281 
285 template<typename FORALL_EXEC_POLICY,
286  typename EXEC_POLICY_T,
287  typename ORDER_POLICY_T,
288  typename DISPATCH_POLICY_T,
289  typename ALLOCATOR_T,
290  typename INDEX_T,
291  typename... Args>
293  : WorkRunnerForallOrdered_base<FORALL_EXEC_POLICY,
294  EXEC_POLICY_T,
295  ORDER_POLICY_T,
296  DISPATCH_POLICY_T,
297  ALLOCATOR_T,
298  INDEX_T,
299  Args...>
300 {
301  using base = WorkRunnerForallOrdered_base<FORALL_EXEC_POLICY,
302  EXEC_POLICY_T,
303  ORDER_POLICY_T,
304  DISPATCH_POLICY_T,
305  ALLOCATOR_T,
306  INDEX_T,
307  Args...>;
308  using base::base;
309 
310  // run the loops using forall in the reverse order to the order they were
311  // enqueued
312  template<typename WorkContainer>
313  typename base::per_run_storage run(WorkContainer const& storage,
314  typename base::resource_type r,
315  Args... args) const
316  {
317  using value_type = typename WorkContainer::value_type;
318 
319  typename base::per_run_storage run_storage {};
320 
321  auto begin = storage.begin();
322  for (auto iter = storage.end(); iter != begin; --iter)
323  {
324  value_type::host_call(&*(iter - 1), r, args...);
325  }
326 
327  return run_storage;
328  }
329 };
330 
331 } // namespace detail
332 
333 } // namespace RAJA
334 
335 #endif // closing endif for header file include guard
#define RAJA_DEVICE
Definition: macros.hpp:66
Args args
Definition: WorkRunner.hpp:212
value_type::device_call &[i_loop] iter
Definition: WorkRunner.hpp:216
typename dispatcher_transform_types< dispatch_policy, holder_type >::type dispatcher_transform_types_t
Definition: Dispatcher.hpp:72
RAJA_INLINE concepts::enable_if_t< RAJA::resources::EventProxy< Res >, concepts::negate< type_traits::is_indexset_policy< ExecutionPolicy > >, type_traits::is_range< Container > > forall(Res r, ExecutionPolicy &&p, Container &&c, LoopBody &&loop_body, ForallParams &&f_params)
Generic dispatch over containers with a value-based policy.
Definition: forall.hpp:186
Definition: AlignedRangeIndexSetBuilders.cpp:35
RAJA_SUPPRESS_HD_WARN RAJA_HOST_DEVICE RAJA_INLINE void loop(CONTEXT const &ctx, SEGMENT const &segment, BODY const &body)
Definition: launch_core.hpp:490
auto & body
Definition: launch.hpp:177
Definition: ListSegment.hpp:416
Header file providing RAJA Dispatcher for workgroup.
Header file containing RAJA index set and segment iteration template methods that take an execution p...
RAJA wrapper for "multi-policy" and dynamic policy selection.
Header file containing RAJA sequential policy definitions.
Definition: Dispatcher.hpp:85
Definition: WorkRunner.hpp:46
camp::tuple< Args... > m_arg_tuple
Definition: WorkRunner.hpp:59
LoopBody m_body
Definition: WorkRunner.hpp:58
HoldBodyArgs_base(body_in &&body, Args... args)
Definition: WorkRunner.hpp:52
Definition: WorkRunner.hpp:90
RAJA_DEVICE RAJA_INLINE void invoke(index_type i, camp::idx_seq< Is... >) const
Definition: WorkRunner.hpp:100
RAJA_DEVICE RAJA_INLINE void operator()(index_type i) const
Definition: WorkRunner.hpp:94
Definition: WorkRunner.hpp:68
RAJA_INLINE void operator()(index_type i) const
Definition: WorkRunner.hpp:72
RAJA_INLINE void invoke(index_type i, camp::idx_seq< Is... >) const
Definition: WorkRunner.hpp:78
Definition: WorkRunner.hpp:115
RAJA_INLINE void operator()(resource_type r, Args... args) const
Definition: WorkRunner.hpp:128
HoldForall(segment_in &&segment, body_in &&body)
Definition: WorkRunner.hpp:123
typename resources::get_resource< ExecutionPolicy >::type resource_type
Definition: WorkRunner.hpp:116
typename std::conditional< !type_traits::is_device_exec_policy< ExecutionPolicy >::value, HoldBodyArgs_host< LoopBody, index_type, Args... >, HoldBodyArgs_device< LoopBody, index_type, Args... > >::type HoldBodyArgs
Definition: WorkRunner.hpp:120
HoldForall< forall_exec_policy, typename camp::at< T, camp::num< 0 > >::type, typename camp::at< T, camp::num< 1 > >::type, index_type, Args... > type
Definition: WorkRunner.hpp:182
Definition: WorkRunner.hpp:162
WorkRunnerForallOrdered_base & operator=(WorkRunnerForallOrdered_base const &)=delete
typename resources::get_resource< FORALL_EXEC_POLICY >::type resource_type
Definition: WorkRunner.hpp:169
ORDER_POLICY_T order_policy
Definition: WorkRunner.hpp:164
WorkRunnerForallOrdered_base(WorkRunnerForallOrdered_base const &)=delete
DISPATCH_POLICY_T dispatch_policy
Definition: WorkRunner.hpp:165
INDEX_T index_type
Definition: WorkRunner.hpp:167
EXEC_POLICY_T exec_policy
Definition: WorkRunner.hpp:163
typename holder_type::template type< T > holder_type_t
Definition: WorkRunner.hpp:187
void enqueue(WorkContainer &storage, segment_T &&seg, loop_T &&loop)
Definition: WorkRunner.hpp:217
WorkRunnerForallOrdered_base & operator=(WorkRunnerForallOrdered_base &&)=default
WorkRunnerForallOrdered_base(WorkRunnerForallOrdered_base &&)=default
int per_run_storage
Definition: WorkRunner.hpp:231
FORALL_EXEC_POLICY forall_exec_policy
Definition: WorkRunner.hpp:171
dispatcher_transform_types_t< dispatch_policy, holder_type > dispatcher_holder_policy
Definition: WorkRunner.hpp:196
ALLOCATOR_T Allocator
Definition: WorkRunner.hpp:166
void clear()
Definition: WorkRunner.hpp:228
Definition: WorkRunner.hpp:252
base::per_run_storage run(WorkContainer const &storage, typename base::resource_type r, Args... args) const
Definition: WorkRunner.hpp:264
Definition: WorkRunner.hpp:300
base::per_run_storage run(WorkContainer const &storage, typename base::resource_type r, Args... args) const
Definition: WorkRunner.hpp:313
Definition: WorkRunner.hpp:149
Definition: policy.hpp:92
camp::resources::Host type
Definition: resource.hpp:49
Definition: PolicyBase.hpp:237