DPC++ Runtime
Runtime libraries for oneAPI DPC++
helpers.hpp
Go to the documentation of this file.
1 //==---------------- helpers.hpp - SYCL helpers ----------------------------==//
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/access/access.hpp>
14 #include <sycl/detail/common.hpp>
15 #include <sycl/detail/export.hpp>
16 #include <sycl/detail/memcpy.hpp>
17 #include <sycl/detail/pi.hpp>
19 
20 #include <memory>
21 #include <stdexcept>
22 #include <type_traits>
23 #include <vector>
24 
25 namespace sycl {
27 class context;
28 class event;
29 template <int Dims, bool WithOffset> class item;
30 template <int Dims> class group;
31 template <int Dims> class range;
32 template <int Dims> class id;
33 template <int Dims> class nd_item;
34 template <int Dims> class h_item;
35 template <typename Type, std::size_t NumElements> class marray;
36 enum class memory_order;
37 
38 namespace detail {
39 
40 class context_impl;
41 // The function returns list of events that can be passed to OpenCL API as
42 // dependency list and waits for others.
43 __SYCL_EXPORT std::vector<RT::PiEvent>
44 getOrWaitEvents(std::vector<sycl::event> DepEvents,
45  std::shared_ptr<sycl::detail::context_impl> Context);
46 
47 __SYCL_EXPORT void waitEvents(std::vector<sycl::event> DepEvents);
48 
49 template <typename T> T *declptr() { return static_cast<T *>(nullptr); }
50 
51 // Function to get of store id, item, nd_item, group for the host implementation
52 // Pass nullptr to get stored object. Pass valid address to store object
53 template <typename T> T get_or_store(const T *obj) {
54  static thread_local auto stored = *obj;
55  if (obj != nullptr) {
56  stored = *obj;
57  }
58  return stored;
59 }
60 
61 class Builder {
62 public:
63  Builder() = delete;
64 
65  template <int Dims>
66  static group<Dims>
67  createGroup(const range<Dims> &Global, const range<Dims> &Local,
68  const range<Dims> &Group, const id<Dims> &Index) {
69  return group<Dims>(Global, Local, Group, Index);
70  }
71 
72  template <int Dims>
73  static group<Dims> createGroup(const range<Dims> &Global,
74  const range<Dims> &Local,
75  const id<Dims> &Index) {
76  return group<Dims>(Global, Local, Global / Local, Index);
77  }
78 
79  template <class ResType, typename BitsType>
80  static ResType createSubGroupMask(BitsType Bits, size_t BitsNum) {
81  return ResType(Bits, BitsNum);
82  }
83 
84  template <int Dims, bool WithOffset>
86  createItem(const range<Dims> &Extent, const id<Dims> &Index,
87  const id<Dims> &Offset) {
88  return item<Dims, WithOffset>(Extent, Index, Offset);
89  }
90 
91  template <int Dims, bool WithOffset>
93  createItem(const range<Dims> &Extent, const id<Dims> &Index) {
94  return item<Dims, WithOffset>(Extent, Index);
95  }
96 
97  template <int Dims>
99  const item<Dims, false> &Local,
100  const group<Dims> &Group) {
101  return nd_item<Dims>(Global, Local, Group);
102  }
103 
104  template <int Dims>
106  const item<Dims, false> &Local) {
107  return h_item<Dims>(Global, Local);
108  }
109 
110  template <int Dims>
112  const item<Dims, false> &Local,
113  const range<Dims> &Flex) {
114  return h_item<Dims>(Global, Local, Flex);
115  }
116 
117  template <int Dims, bool WithOffset>
118  static void updateItemIndex(sycl::item<Dims, WithOffset> &Item,
119  const id<Dims> &NextIndex) {
120  Item.MImpl.MIndex = NextIndex;
121  }
122 
123 #ifdef __SYCL_DEVICE_ONLY__
124 
125  template <int N>
126  using is_valid_dimensions = std::integral_constant<bool, (N > 0) && (N < 4)>;
127 
128  template <int Dims> static const id<Dims> getElement(id<Dims> *) {
129  static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
130  return __spirv::initGlobalInvocationId<Dims, id<Dims>>();
131  }
132 
133  template <int Dims> static const group<Dims> getElement(group<Dims> *) {
134  static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
135  range<Dims> GlobalSize{__spirv::initGlobalSize<Dims, range<Dims>>()};
136  range<Dims> LocalSize{__spirv::initWorkgroupSize<Dims, range<Dims>>()};
137  range<Dims> GroupRange{__spirv::initNumWorkgroups<Dims, range<Dims>>()};
138  id<Dims> GroupId{__spirv::initWorkgroupId<Dims, id<Dims>>()};
139  return createGroup<Dims>(GlobalSize, LocalSize, GroupRange, GroupId);
140  }
141 
142  template <int Dims, bool WithOffset>
143  static detail::enable_if_t<WithOffset, const item<Dims, WithOffset>>
144  getItem() {
145  static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
146  id<Dims> GlobalId{__spirv::initGlobalInvocationId<Dims, id<Dims>>()};
147  range<Dims> GlobalSize{__spirv::initGlobalSize<Dims, range<Dims>>()};
148  id<Dims> GlobalOffset{__spirv::initGlobalOffset<Dims, id<Dims>>()};
149  return createItem<Dims, true>(GlobalSize, GlobalId, GlobalOffset);
150  }
151 
152  template <int Dims, bool WithOffset>
153  static detail::enable_if_t<!WithOffset, const item<Dims, WithOffset>>
154  getItem() {
155  static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
156  id<Dims> GlobalId{__spirv::initGlobalInvocationId<Dims, id<Dims>>()};
157  range<Dims> GlobalSize{__spirv::initGlobalSize<Dims, range<Dims>>()};
158  return createItem<Dims, false>(GlobalSize, GlobalId);
159  }
160 
161  template <int Dims> static const nd_item<Dims> getElement(nd_item<Dims> *) {
162  static_assert(is_valid_dimensions<Dims>::value, "invalid dimensions");
163  range<Dims> GlobalSize{__spirv::initGlobalSize<Dims, range<Dims>>()};
164  range<Dims> LocalSize{__spirv::initWorkgroupSize<Dims, range<Dims>>()};
165  range<Dims> GroupRange{__spirv::initNumWorkgroups<Dims, range<Dims>>()};
166  id<Dims> GroupId{__spirv::initWorkgroupId<Dims, id<Dims>>()};
167  id<Dims> GlobalId{__spirv::initGlobalInvocationId<Dims, id<Dims>>()};
168  id<Dims> LocalId{__spirv::initLocalInvocationId<Dims, id<Dims>>()};
169  id<Dims> GlobalOffset{__spirv::initGlobalOffset<Dims, id<Dims>>()};
170  group<Dims> Group =
171  createGroup<Dims>(GlobalSize, LocalSize, GroupRange, GroupId);
172  item<Dims, true> GlobalItem =
173  createItem<Dims, true>(GlobalSize, GlobalId, GlobalOffset);
174  item<Dims, false> LocalItem = createItem<Dims, false>(LocalSize, LocalId);
175  return createNDItem<Dims>(GlobalItem, LocalItem, Group);
176  }
177 
178  template <int Dims, bool WithOffset>
179  static auto getElement(item<Dims, WithOffset> *)
180  -> decltype(getItem<Dims, WithOffset>()) {
181  return getItem<Dims, WithOffset>();
182  }
183 
184  template <int Dims>
185  static auto getNDItem() -> decltype(getElement(declptr<nd_item<Dims>>())) {
186  return getElement(declptr<nd_item<Dims>>());
187  }
188 
189 #endif // __SYCL_DEVICE_ONLY__
190 };
191 
192 inline constexpr __spv::MemorySemanticsMask::Flag
195 }
196 
197 inline constexpr uint32_t
199  const __spv::MemorySemanticsMask LocalScopeMask =
201  // Huge ternary operator below is a workaround for constexpr function
202  // requirement that such function can only contain return statement and
203  // nothing more
204  //
205  // It is equivalent to the following code:
206  //
207  // uint32_t Flags =
208  // static_cast<uint32_t>(__spv::MemorySemanticsMask::SequentiallyConsistent);
209  // switch (AccessSpace) {
210  // case access::fence_space::global_space:
211  // Flags |=
212  // static_cast<uint32_t>(__spv::MemorySemanticsMask::CrossWorkgroupMemory);
213  // break;
214  // case access::fence_space::local_space:
215  // Flags |= static_cast<uint32_t>(LocalScopeMask);
216  // break;
217  // case access::fence_space::global_and_local:
218  // default:
219  // Flags |= static_cast<uint32_t>(
220  // __spv::MemorySemanticsMask::CrossWorkgroupMemory) |
221  // static_cast<uint32_t>(LocalScopeMask);
222  // break;
223  // }
224  // return Flags;
225 
226  return (AccessSpace == access::fence_space::global_space)
227  ? static_cast<uint32_t>(
230  : (AccessSpace == access::fence_space::local_space)
231  ? static_cast<uint32_t>(
233  LocalScopeMask)
234  : /* default: (AccessSpace ==
235  access::fence_space::global_and_local) */
236  static_cast<uint32_t>(
239  LocalScopeMask);
240 }
241 
242 // To ensure loop unrolling is done when processing dimensions.
243 template <size_t... Inds, class F>
244 void dim_loop_impl(std::integer_sequence<size_t, Inds...>, F &&f) {
245  (f(Inds), ...);
246 }
247 
248 template <size_t count, class F> void dim_loop(F &&f) {
249  dim_loop_impl(std::make_index_sequence<count>{}, std::forward<F>(f));
250 }
251 
252 } // namespace detail
253 
254 } // __SYCL_INLINE_VER_NAMESPACE(_V1)
255 } // namespace sycl
sycl::_V1::detail::Builder
Definition: helpers.hpp:61
sycl::_V1::detail::Builder::createItem
static detail::enable_if_t< WithOffset, item< Dims, WithOffset > > createItem(const range< Dims > &Extent, const id< Dims > &Index, const id< Dims > &Offset)
Definition: helpers.hpp:86
sycl::_V1::detail::Builder::createSubGroupMask
static ResType createSubGroupMask(BitsType Bits, size_t BitsNum)
Definition: helpers.hpp:80
type_traits.hpp
sycl::_V1::detail::waitEvents
void waitEvents(std::vector< sycl::event > DepEvents)
Definition: helpers.cpp:60
sycl::_V1::ext::oneapi::experimental::obj
global_pointer_t obj
Definition: annotated_arg.hpp:76
memcpy.hpp
sycl::_V1::detail::declptr
T * declptr()
Definition: helpers.hpp:49
__SYCL_INLINE_VER_NAMESPACE
#define __SYCL_INLINE_VER_NAMESPACE(X)
Definition: defines_elementary.hpp:11
sycl::_V1::errc::event
@ event
sycl::_V1::detail::Builder::createHItem
static h_item< Dims > createHItem(const item< Dims, false > &Global, const item< Dims, false > &Local, const range< Dims > &Flex)
Definition: helpers.hpp:111
spirv_vars.hpp
sycl
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:14
__spv::MemorySemanticsMask::CrossWorkgroupMemory
@ CrossWorkgroupMemory
Definition: spirv_types.hpp:97
access.hpp
pi.hpp
sycl::_V1::id
A unique identifier of an item in an index space.
Definition: array.hpp:17
sycl::_V1::detail::dim_loop
void dim_loop(F &&f)
Definition: helpers.hpp:248
sycl::_V1::access::fence_space
fence_space
Definition: access.hpp:39
sycl::_V1::detail::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: stl_type_traits.hpp:24
sycl::_V1::range
Defines the iteration domain of either a single work-group in a parallel dispatch,...
Definition: buffer.hpp:28
export.hpp
__spv::MemorySemanticsMask
Definition: spirv_types.hpp:86
sycl::_V1::detail::get_or_store
T get_or_store(const T *obj)
Definition: helpers.hpp:53
sycl::_V1::nd_item
Identifies an instance of the function object executing at each point in an nd_range.
Definition: helpers.hpp:33
sycl::_V1::detail::dim_loop_impl
void dim_loop_impl(std::integer_sequence< size_t, Inds... >, F &&f)
Definition: helpers.hpp:244
sycl::_V1::item
Identifies an instance of the function object executing at each point in a range.
Definition: helpers.hpp:29
sycl::_V1::marray
Provides a cross-platform math array class template that works on SYCL devices as well as in host C++...
Definition: generic_type_lists.hpp:25
sycl::_V1::detail::Builder::createGroup
static group< Dims > createGroup(const range< Dims > &Global, const range< Dims > &Local, const id< Dims > &Index)
Definition: helpers.hpp:73
sycl::_V1::detail::getOrWaitEvents
std::vector< RT::PiEvent > getOrWaitEvents(std::vector< sycl::event > DepEvents, std::shared_ptr< sycl::detail::context_impl > Context)
common.hpp
sycl::_V1::h_item
Identifies an instance of a group::parallel_for_work_item function object executing at each point in ...
Definition: helpers.hpp:34
sycl::_V1::detail::memory_order
sycl::memory_order memory_order
Definition: atomic.hpp:38
__spv::MemorySemanticsMask::SequentiallyConsistent
@ SequentiallyConsistent
Definition: spirv_types.hpp:93
__spv::MemorySemanticsMask::None
@ None
Definition: spirv_types.hpp:89
sycl::_V1::detail::getSPIRVMemorySemanticsMask
constexpr uint32_t getSPIRVMemorySemanticsMask(const access::fence_space AccessSpace, const __spv::MemorySemanticsMask LocalScopeMask=__spv::MemorySemanticsMask::WorkgroupMemory)
Definition: helpers.hpp:198
__spv::MemorySemanticsMask::WorkgroupMemory
@ WorkgroupMemory
Definition: spirv_types.hpp:96
__spv::MemorySemanticsMask::Flag
Flag
Definition: spirv_types.hpp:88
sycl::_V1::detail::Builder::createItem
static detail::enable_if_t<!WithOffset, item< Dims, WithOffset > > createItem(const range< Dims > &Extent, const id< Dims > &Index)
Definition: helpers.hpp:93
sycl::_V1::detail::Builder::createHItem
static h_item< Dims > createHItem(const item< Dims, false > &Global, const item< Dims, false > &Local)
Definition: helpers.hpp:105
sycl::_V1::detail::Builder::createGroup
static group< Dims > createGroup(const range< Dims > &Global, const range< Dims > &Local, const range< Dims > &Group, const id< Dims > &Index)
Definition: helpers.hpp:67
sycl::_V1::memory_order
memory_order
Definition: memory_enums.hpp:16
sycl::_V1::detail::Builder::createNDItem
static nd_item< Dims > createNDItem(const item< Dims, true > &Global, const item< Dims, false > &Local, const group< Dims > &Group)
Definition: helpers.hpp:98
sycl::_V1::detail::Builder::updateItemIndex
static void updateItemIndex(sycl::item< Dims, WithOffset > &Item, const id< Dims > &NextIndex)
Definition: helpers.hpp:118
sycl::_V1::group
Definition: helpers.hpp:30
spirv_types.hpp