DPC++ Runtime
Runtime libraries for oneAPI DPC++
root_group.hpp
Go to the documentation of this file.
1 //==--- root_group.hpp --- SYCL extension for root groups ------------------==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #pragma once
10 
13 #include <sycl/group.hpp>
14 #include <sycl/memory_enums.hpp>
15 #include <sycl/nd_item.hpp>
16 #include <sycl/sub_group.hpp>
17 
18 namespace sycl {
19 inline namespace _V1 {
20 namespace ext::oneapi::experimental {
21 
22 namespace info::kernel_queue_specific {
23 // TODO: Revisit and align with sycl_ext_oneapi_forward_progress extension once
24 // #7598 is merged.
26  using return_type = size_t;
27 };
28 } // namespace info::kernel_queue_specific
29 
31  : detail::compile_time_property_key<detail::PropKind::UseRootSync> {
33 };
34 
36 
37 template <int Dimensions> class root_group {
38 public:
41  using linear_id_type = size_t;
42  static constexpr int dimensions = Dimensions;
44 
46 
47  id<Dimensions> get_local_id() const { return it.get_global_id(); }
48 
50  if constexpr (Dimensions == 3) {
51  return range<3>{1, 1, 1};
52  } else if constexpr (Dimensions == 2) {
53  return range<2>{1, 1};
54  } else {
55  return range<1>{1};
56  }
57  }
58 
59  range<Dimensions> get_local_range() const { return it.get_global_range(); };
60 
62 
63  size_t get_group_linear_id() const { return 0; };
64 
65  size_t get_local_linear_id() const { return it.get_global_linear_id(); }
66 
67  size_t get_group_linear_range() const { return get_group_range().size(); };
68 
69  size_t get_local_linear_range() const { return get_local_range().size(); };
70 
71  bool leader() const { return get_local_id() == 0; };
72 
73 private:
76 
77  root_group(nd_item<Dimensions> it) : it{it} {}
78 
80 };
81 
82 template <int Dimensions>
84  (void)g;
85  return this_group<Dimensions>();
86 }
87 
88 template <int Dimensions> sycl::sub_group get_child_group(group<Dimensions> g) {
89  (void)g;
90  return this_sub_group();
91 }
92 namespace this_work_item {
93 template <int Dimensions> root_group<Dimensions> get_root_group() {
94  return sycl::ext::oneapi::this_work_item::get_nd_item<Dimensions>()
95  .ext_oneapi_get_root_group();
96 }
97 } // namespace this_work_item
98 
99 namespace this_kernel {
100 template <int Dimensions>
102  "use sycl::ext::oneapi::experimental::this_work_item::get_root_group() "
103  "instead")
105  this_work_item::get_root_group<Dimensions>();
106 }
107 } // namespace this_kernel
108 
109 } // namespace ext::oneapi::experimental
110 
111 template <int dimensions>
113  memory_scope FenceScope = decltype(G)::fence_scope) {
114 #ifdef __SYCL_DEVICE_ONLY__
115  // Root group barrier synchronizes using a work group barrier if there's only
116  // one work group. This allows backends to ignore the ControlBarrier with
117  // Device scope if their maximum number of work groups is 1. This is a
118  // workaround that's not intended to reduce the bar for SPIR-V modules
119  // acceptance, but rather make a pessimistic case work until we have full
120  // support for the device barrier built-in from backends.
121  const auto ChildGroup = ext::oneapi::experimental::get_child_group(G);
122  if (ChildGroup.get_group_linear_range() == 1) {
123  group_barrier(ChildGroup);
124  } else {
125  detail::spirv::ControlBarrier(G, FenceScope, memory_order::seq_cst);
126  }
127 #else
128  (void)G;
129  (void)FenceScope;
130  throw sycl::runtime_error("Barriers are not supported on host device",
131  PI_ERROR_INVALID_DEVICE);
132 #endif
133 }
134 
135 } // namespace _V1
136 } // namespace sycl
range< Dimensions > get_max_local_range() const
Definition: root_group.hpp:61
range< Dimensions > get_local_range() const
Definition: root_group.hpp:59
static constexpr memory_scope fence_scope
Definition: root_group.hpp:43
range< Dimensions > get_group_range() const
Definition: root_group.hpp:49
A unique identifier of an item in an index space.
Definition: id.hpp:36
Identifies an instance of the function object executing at each point in an nd_range.
Definition: nd_item.hpp:48
sycl::ext::oneapi::experimental::root_group< Dimensions > ext_oneapi_get_root_group() const
Definition: nd_item.hpp:499
size_t size() const
Definition: range.hpp:56
fence_scope
The scope that fence() operation should apply to.
Definition: common.hpp:350
__SYCL_DEPRECATED("use sycl::ext::oneapi::experimental::this_work_item::get_root_group() " "instead") root_group< Dimensions > get_root_group()
Definition: root_group.hpp:101
group< Dimensions > get_child_group(root_group< Dimensions > g)
Definition: root_group.hpp:83
constexpr use_root_sync_key::value_t use_root_sync
Definition: root_group.hpp:35
void group_barrier(ext::oneapi::experimental::root_group< dimensions > G, memory_scope FenceScope=decltype(G)::fence_scope)
Definition: root_group.hpp:112
class __SYCL_EBO __SYCL_SPECIAL_CLASS __SYCL_TYPE(local_accessor) local_accessor class __SYCL_EBO __SYCL_SPECIAL_CLASS Dimensions
Definition: accessor.hpp:3233
Definition: access.hpp:18