RAJA
RAJA provides a collection of platform portability abstractions for C++ HPC applications.
WorkGroup.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_HPP
21 #define RAJA_PATTERN_WorkGroup_HPP
22 
23 #include "RAJA/config.hpp"
24 
27 
29 #include "RAJA/util/plugins.hpp"
30 
31 namespace RAJA
32 {
33 
62 template<typename... Args>
63 using xargs = camp::list<Args...>;
64 
65 namespace detail
66 {
67 
68 template<typename T>
69 struct is_xargs
70 {
71  static constexpr bool value = false;
72 };
73 
74 template<typename... Args>
75 struct is_xargs<xargs<Args...>>
76 {
77  static constexpr bool value = true;
78 };
79 
80 } // namespace detail
81 
82 //
83 // Forward declarations for WorkPool and WorkGroup templates.
84 // Actual classes appear in forall_*.hxx header files.
85 //
86 
119 template<typename WORKGROUP_POLICY_T,
120  typename INDEX_T,
121  typename EXTRA_ARGS_T,
122  typename ALLOCATOR_T>
123 struct WorkPool
124 {
125  static_assert(
127  "WorkPool: WORKGROUP_POLICY_T must be a workgroup policy");
129  "WorkPool: EXTRA_ARGS_T must be a RAJA::xargs<...> type");
130 };
131 
158 template<typename WORKGROUP_POLICY_T,
159  typename INDEX_T,
160  typename EXTRA_ARGS_T,
161  typename ALLOCATOR_T>
162 struct WorkGroup
163 {
164  static_assert(
166  "WorkGroup: WORKGROUP_POLICY_T must be a workgroup policy");
168  "WorkGroup: EXTRA_ARGS_T must be a RAJA::xargs<...> type");
169 };
170 
196 template<typename WORKGROUP_POLICY_T,
197  typename INDEX_T,
198  typename EXTRA_ARGS_T,
199  typename ALLOCATOR_T>
200 struct WorkSite
201 {
202  static_assert(
204  "WorkSite: WORKGROUP_POLICY_T must be a workgroup policy");
206  "WorkSite: EXTRA_ARGS_T must be a RAJA::xargs<...> type");
207 };
208 
209 template<typename EXEC_POLICY_T,
210  typename ORDER_POLICY_T,
211  typename STORAGE_POLICY_T,
212  typename DISPATCH_POLICY_T,
213  typename INDEX_T,
214  typename... Args,
215  typename ALLOCATOR_T>
216 struct WorkPool<WorkGroupPolicy<EXEC_POLICY_T,
217  ORDER_POLICY_T,
218  STORAGE_POLICY_T,
219  DISPATCH_POLICY_T>,
220  INDEX_T,
221  xargs<Args...>,
222  ALLOCATOR_T>
223 {
224  using exec_policy = EXEC_POLICY_T;
225  using order_policy = ORDER_POLICY_T;
226  using storage_policy = STORAGE_POLICY_T;
227  using dispatch_policy = DISPATCH_POLICY_T;
229  order_policy,
232  using index_type = INDEX_T;
233  using xarg_type = xargs<Args...>;
234  using Allocator = ALLOCATOR_T;
235 
238 
239 private:
241  order_policy,
243  Allocator,
244  index_type,
245  Args...>;
246  using storage_type =
248  Allocator,
249  typename workrunner_type::dispatcher_type>;
250 
251  friend workgroup_type;
252  friend worksite_type;
253 
254 public:
255  using resource_type = typename workrunner_type::resource_type;
256 
257  explicit WorkPool(Allocator const& aloc) : m_storage(aloc) {}
258 
259  WorkPool(WorkPool const&) = delete;
260  WorkPool& operator=(WorkPool const&) = delete;
261 
262  WorkPool(WorkPool&&) = default;
263  WorkPool& operator=(WorkPool&&) = default;
264 
265  size_t num_loops() const { return m_storage.size(); }
266 
267  size_t storage_bytes() const { return m_storage.storage_size(); }
268 
269  void reserve(size_t num_loops, size_t storage_bytes)
270  {
271  m_storage.reserve(num_loops, storage_bytes);
272  }
273 
274  template<typename segment_T, typename loop_T>
275  inline void enqueue(segment_T&& seg, loop_T&& loop_body)
276  {
277  {
278  // ignore zero length loops
279  using std::begin;
280  using std::end;
281  if (begin(seg) == end(seg)) return;
282  }
283  if (m_storage.begin() == m_storage.end())
284  {
285  // perform auto-reserve on reuse
286  reserve(m_max_num_loops, m_max_storage_bytes);
287  }
288 
289  util::PluginContext context {
290  util::make_context<exec_policy>(std::string())};
292 
294  auto body = trigger_updates_before(loop_body);
295 
296  m_runner.enqueue(m_storage, std::forward<segment_T>(seg), std::move(body));
297 
299  }
300 
301  inline workgroup_type instantiate();
302 
303  void clear()
304  {
305  // storage is about to be destroyed
306  // but it was never used so no synchronization necessary
307  m_storage.clear();
308  m_runner.clear();
309  }
310 
311  ~WorkPool() { clear(); }
312 
313 private:
314  storage_type m_storage;
315  size_t m_max_num_loops = 0;
316  size_t m_max_storage_bytes = 0;
317 
318  workrunner_type m_runner;
319 };
320 
321 template<typename EXEC_POLICY_T,
322  typename ORDER_POLICY_T,
323  typename STORAGE_POLICY_T,
324  typename DISPATCH_POLICY_T,
325  typename INDEX_T,
326  typename... Args,
327  typename ALLOCATOR_T>
328 struct WorkGroup<WorkGroupPolicy<EXEC_POLICY_T,
329  ORDER_POLICY_T,
330  STORAGE_POLICY_T,
331  DISPATCH_POLICY_T>,
332  INDEX_T,
333  xargs<Args...>,
334  ALLOCATOR_T>
335 {
336  using exec_policy = EXEC_POLICY_T;
337  using order_policy = ORDER_POLICY_T;
338  using storage_policy = STORAGE_POLICY_T;
339  using dispatch_policy = DISPATCH_POLICY_T;
341  order_policy,
344  using index_type = INDEX_T;
345  using xarg_type = xargs<Args...>;
346  using Allocator = ALLOCATOR_T;
347 
350 
351 private:
352  using storage_type = typename workpool_type::storage_type;
353  using workrunner_type = typename workpool_type::workrunner_type;
354 
355  friend workpool_type;
356  friend worksite_type;
357 
358 public:
359  using resource_type = typename workpool_type::resource_type;
360 
361  WorkGroup(WorkGroup const&) = delete;
362  WorkGroup& operator=(WorkGroup const&) = delete;
363 
364  WorkGroup(WorkGroup&&) = default;
366 
367  inline worksite_type run(resource_type r, Args...);
368 
370  {
371  auto r = resource_type::get_default();
372  return run(r, std::move(args)...);
373  }
374 
375  void clear()
376  {
377  // storage is about to be destroyed
378  // TODO: synchronize
379  m_storage.clear();
380  m_runner.clear();
381  }
382 
383  ~WorkGroup() { clear(); }
384 
385 private:
386  storage_type m_storage;
387  workrunner_type m_runner;
388 
389  WorkGroup(storage_type&& storage, workrunner_type&& runner)
390  : m_storage(std::move(storage)),
391  m_runner(std::move(runner))
392  {}
393 };
394 
395 template<typename EXEC_POLICY_T,
396  typename ORDER_POLICY_T,
397  typename STORAGE_POLICY_T,
398  typename DISPATCH_POLICY_T,
399  typename INDEX_T,
400  typename... Args,
401  typename ALLOCATOR_T>
402 struct WorkSite<WorkGroupPolicy<EXEC_POLICY_T,
403  ORDER_POLICY_T,
404  STORAGE_POLICY_T,
405  DISPATCH_POLICY_T>,
406  INDEX_T,
407  xargs<Args...>,
408  ALLOCATOR_T>
409 {
410  using exec_policy = EXEC_POLICY_T;
411  using order_policy = ORDER_POLICY_T;
412  using storage_policy = STORAGE_POLICY_T;
413  using dispatch_policy = DISPATCH_POLICY_T;
415  order_policy,
418  using index_type = INDEX_T;
419  using xarg_type = xargs<Args...>;
420  using Allocator = ALLOCATOR_T;
421 
424 
425 private:
426  using workrunner_type = typename workgroup_type::workrunner_type;
427  using per_run_storage = typename workrunner_type::per_run_storage;
428 
429  friend workpool_type;
430  friend workgroup_type;
431 
432 public:
433  using resource_type = typename workpool_type::resource_type;
434 
435  WorkSite(WorkSite const&) = delete;
436  WorkSite& operator=(WorkSite const&) = delete;
437 
438  WorkSite(WorkSite&&) = default;
439  WorkSite& operator=(WorkSite&&) = default;
440 
441  resource_type get_resource() const { return m_resource; }
442 
443  void clear()
444  {
445  // resources is about to be released
446  // TODO: synchronize
447  }
448 
449  ~WorkSite() { clear(); }
450 
451 private:
452  per_run_storage m_run_storage;
453  resource_type m_resource;
454 
455  explicit WorkSite(resource_type r, per_run_storage&& run_storage)
456  : m_run_storage(std::move(run_storage)),
457  m_resource(r)
458  {}
459 };
460 
461 template<typename EXEC_POLICY_T,
462  typename ORDER_POLICY_T,
463  typename STORAGE_POLICY_T,
464  typename DISPATCH_POLICY_T,
465  typename INDEX_T,
466  typename... Args,
467  typename ALLOCATOR_T>
468 inline typename WorkPool<WorkGroupPolicy<EXEC_POLICY_T,
469  ORDER_POLICY_T,
470  STORAGE_POLICY_T,
471  DISPATCH_POLICY_T>,
472  INDEX_T,
473  xargs<Args...>,
474  ALLOCATOR_T>::workgroup_type
475 WorkPool<WorkGroupPolicy<EXEC_POLICY_T,
476  ORDER_POLICY_T,
477  STORAGE_POLICY_T,
478  DISPATCH_POLICY_T>,
479  INDEX_T,
480  xargs<Args...>,
481  ALLOCATOR_T>::instantiate()
482 {
483  // update max sizes to auto-reserve on reuse
484  m_max_num_loops = std::max(m_storage.size(), m_max_num_loops);
485  m_max_storage_bytes = std::max(m_storage.storage_size(), m_max_storage_bytes);
486 
487  // move storage into workgroup
488  return workgroup_type {std::move(m_storage), std::move(m_runner)};
489 }
490 
491 template<typename EXEC_POLICY_T,
492  typename ORDER_POLICY_T,
493  typename STORAGE_POLICY_T,
494  typename DISPATCH_POLICY_T,
495  typename INDEX_T,
496  typename... Args,
497  typename ALLOCATOR_T>
498 inline typename WorkGroup<WorkGroupPolicy<EXEC_POLICY_T,
499  ORDER_POLICY_T,
500  STORAGE_POLICY_T,
501  DISPATCH_POLICY_T>,
502  INDEX_T,
503  xargs<Args...>,
504  ALLOCATOR_T>::worksite_type
505 WorkGroup<
506  WorkGroupPolicy<EXEC_POLICY_T,
507  ORDER_POLICY_T,
508  STORAGE_POLICY_T,
509  DISPATCH_POLICY_T>,
510  INDEX_T,
511  xargs<Args...>,
512  ALLOCATOR_T>::run(typename WorkGroup<WorkGroupPolicy<EXEC_POLICY_T,
513  ORDER_POLICY_T,
514  STORAGE_POLICY_T,
515  DISPATCH_POLICY_T>,
516  INDEX_T,
518  ALLOCATOR_T>::resource_type r,
519  Args... args)
520 {
521  util::PluginContext context {
522  util::make_context<EXEC_POLICY_T>(std::string())};
524 
525  // move any per run storage into worksite
526  worksite_type site(r,
527  m_runner.run(m_storage, r, std::forward<Args>(args)...));
528 
530 
531  return site;
532 }
533 
534 } // namespace RAJA
535 
536 #endif // closing endif for header file include guard
Header file providing RAJA WorkStorage.
Args args
Definition: WorkRunner.hpp:212
RAJA_INLINE void callPreLaunchPlugins(const PluginContext &p)
Definition: plugins.hpp:56
RAJA_INLINE void callPostCapturePlugins(const PluginContext &p)
Definition: plugins.hpp:46
RAJA_INLINE auto trigger_updates_before(T &&item) -> typename std::remove_reference< T >::type
Definition: plugins.hpp:29
RAJA_INLINE void callPostLaunchPlugins(const PluginContext &p)
Definition: plugins.hpp:66
RAJA_INLINE void callPreCapturePlugins(const PluginContext &p)
Definition: plugins.hpp:36
Definition: AlignedRangeIndexSetBuilders.cpp:35
auto & body
Definition: launch.hpp:177
camp::list< Args... > xargs
xargs alias.
Definition: WorkGroup.hpp:63
RAJA_HOST_DEVICE constexpr RAJA_INLINE Result max(Args... args)
Definition: foldl.hpp:155
Definition: ListSegment.hpp:416
Header file providing RAJA WorkStorage.
WorkGroup class template. Owns loops from an instantiated WorkPool.
Definition: WorkGroup.hpp:163
WorkPool class template.
Definition: WorkGroup.hpp:124
WorkSite class template. Owns per run objects from a single run of a WorkGroup.
Definition: WorkGroup.hpp:201
Definition: WorkGroup.hpp:70
static constexpr bool value
Definition: WorkGroup.hpp:71
Definition: PolicyBase.hpp:117
Definition: WorkGroup.hpp:104
Definition: PluginContext.hpp:26