DPC++ Runtime
Runtime libraries for oneAPI DPC++
opportunistic_group.hpp
Go to the documentation of this file.
1 //==--- opportunistic_group.hpp --- SYCL extension for non-uniform 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 
11 #include <sycl/aspects.hpp>
12 #include <sycl/detail/pi.h> // for PI_ERROR_INVALID_DEVICE
13 #include <sycl/detail/type_traits.hpp> // for is_group, is_user_cons...
14 #include <sycl/exception.hpp> // for runtime_error
15 #include <sycl/ext/oneapi/sub_group_mask.hpp> // for sub_group_mask
16 #include <sycl/id.hpp> // for id
17 #include <sycl/memory_enums.hpp> // for memory_scope
18 #include <sycl/range.hpp> // for range
19 
20 #include <stdint.h> // for uint32_t
21 #include <type_traits> // for true_type
22 
23 namespace sycl {
24 inline namespace _V1 {
25 namespace ext::oneapi::experimental {
26 
27 class opportunistic_group;
28 
29 namespace this_kernel {
30 #ifdef __SYCL_DEVICE_ONLY__
31 [[__sycl_detail__::__uses_aspects__(
32  sycl::aspect::ext_oneapi_opportunistic_group)]]
33 #endif
35 } // namespace this_kernel
36 
38 public:
39  using id_type = id<1>;
41  using linear_id_type = uint32_t;
42  static constexpr int dimensions = 1;
43  static constexpr sycl::memory_scope fence_scope =
45 
47 #ifdef __SYCL_DEVICE_ONLY__
48  return static_cast<id_type>(0);
49 #else
50  throw runtime_error("Non-uniform groups are not supported on host device.",
51  PI_ERROR_INVALID_DEVICE);
52 #endif
53  }
54 
56 #ifdef __SYCL_DEVICE_ONLY__
57  return sycl::detail::CallerPositionInMask(Mask);
58 #else
59  throw runtime_error("Non-uniform groups are not supported on host device.",
60  PI_ERROR_INVALID_DEVICE);
61 #endif
62  }
63 
65 #ifdef __SYCL_DEVICE_ONLY__
66  return 1;
67 #else
68  throw runtime_error("Non-uniform groups are not supported on host device.",
69  PI_ERROR_INVALID_DEVICE);
70 #endif
71  }
72 
74 #ifdef __SYCL_DEVICE_ONLY__
75  return Mask.count();
76 #else
77  throw runtime_error("Non-uniform groups are not supported on host device.",
78  PI_ERROR_INVALID_DEVICE);
79 #endif
80  }
81 
83 #ifdef __SYCL_DEVICE_ONLY__
84  return static_cast<linear_id_type>(get_group_id()[0]);
85 #else
86  throw runtime_error("Non-uniform groups are not supported on host device.",
87  PI_ERROR_INVALID_DEVICE);
88 #endif
89  }
90 
92 #ifdef __SYCL_DEVICE_ONLY__
93  return static_cast<linear_id_type>(get_local_id()[0]);
94 #else
95  throw runtime_error("Non-uniform groups are not supported on host device.",
96  PI_ERROR_INVALID_DEVICE);
97 #endif
98  }
99 
101 #ifdef __SYCL_DEVICE_ONLY__
102  return static_cast<linear_id_type>(get_group_range()[0]);
103 #else
104  throw runtime_error("Non-uniform groups are not supported on host device.",
105  PI_ERROR_INVALID_DEVICE);
106 #endif
107  }
108 
110 #ifdef __SYCL_DEVICE_ONLY__
111  return static_cast<linear_id_type>(get_local_range()[0]);
112 #else
113  throw runtime_error("Non-uniform groups are not supported on host device.",
114  PI_ERROR_INVALID_DEVICE);
115 #endif
116  }
117 
118  bool leader() const {
119 #ifdef __SYCL_DEVICE_ONLY__
120  uint32_t Lowest = static_cast<uint32_t>(Mask.find_low()[0]);
121  return __spirv_SubgroupLocalInvocationId() == Lowest;
122 #else
123  throw runtime_error("Non-uniform groups are not supported on host device.",
124  PI_ERROR_INVALID_DEVICE);
125 #endif
126  }
127 
128 protected:
130 
132 
134 
136  sycl::detail::GetMask<opportunistic_group>(opportunistic_group Group);
137 };
138 
139 namespace this_kernel {
140 
142 #ifdef __SYCL_DEVICE_ONLY__
143 #if defined(__SPIR__) || defined(__SPIRV__)
144  // TODO: It may be wiser to call the intrinsic than rely on this_group()
145  sycl::sub_group sg = sycl::ext::oneapi::experimental::this_sub_group();
147  return opportunistic_group(mask);
148 #elif defined(__NVPTX__)
149  uint32_t active_mask;
150  asm volatile("activemask.b32 %0;" : "=r"(active_mask));
151  sub_group_mask mask =
152  sycl::detail::Builder::createSubGroupMask<ext::oneapi::sub_group_mask>(
153  active_mask, 32);
154  return opportunistic_group(mask);
155 #endif
156 #else
157  throw runtime_error("Non-uniform groups are not supported on host device.",
158  PI_ERROR_INVALID_DEVICE);
159 #endif
160 }
161 
162 } // namespace this_kernel
163 
164 template <>
165 struct is_user_constructed_group<opportunistic_group> : std::true_type {};
166 
167 } // namespace ext::oneapi::experimental
168 
169 template <>
170 struct is_group<ext::oneapi::experimental::opportunistic_group>
171  : std::true_type {};
172 
173 } // namespace _V1
174 } // namespace sycl
std::enable_if_t< std::is_same_v< std::decay_t< Group >, sub_group >||std::is_same_v< std::decay_t< Group >, sycl::sub_group >, sub_group_mask > group_ballot(Group g, bool predicate=true)
Definition: access.hpp:18