DPC++ Runtime
Runtime libraries for oneAPI DPC++
group_load_store.hpp
Go to the documentation of this file.
1 //==---- group_load_store.hpp --- SYCL extension for group loads/stores ----==//
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 // Implements sycl_ext_oneapi_group_load_store extension.
10 
11 #pragma once
12 
14 #include <sycl/sycl_span.hpp>
15 
16 namespace sycl {
17 inline namespace _V1 {
18 namespace ext::oneapi::experimental {
19 
21 
23  : detail::compile_time_property_key<detail::PropKind::DataPlacement> {
24  template <data_placement_enum Placement>
25  using value_t =
27  // TODO: Extension uses data_placement_enum directly here.
28  std::integral_constant<int, static_cast<int>(Placement)>>;
29 };
30 
31 template <data_placement_enum Placement>
33 
38 
40  : detail::compile_time_property_key<detail::PropKind::ContiguousMemory> {
42 };
43 
45 
47  : detail::compile_time_property_key<detail::PropKind::FullGroup> {
49 };
50 
52 
53 namespace detail {
54 using namespace sycl::detail;
55 
56 template <typename InputIteratorT, typename OutputElemT>
57 inline constexpr bool verify_load_types =
58  std::is_same_v<
59  typename std::iterator_traits<InputIteratorT>::iterator_category,
60  std::random_access_iterator_tag> &&
61  std::is_convertible_v<remove_decoration_t<typename std::iterator_traits<
62  InputIteratorT>::value_type>,
63  OutputElemT> &&
64  std::is_trivially_copyable_v<remove_decoration_t<
66  std::is_default_constructible_v<remove_decoration_t<
68  std::is_trivially_copyable_v<OutputElemT> &&
69  std::is_default_constructible_v<OutputElemT>;
70 
71 template <typename InputElemT, typename OutputIteratorT>
72 inline constexpr bool verify_store_types =
73  std::is_same_v<
74  typename std::iterator_traits<OutputIteratorT>::iterator_category,
75  std::random_access_iterator_tag> &&
76  std::is_convertible_v<InputElemT,
77  remove_decoration_t<typename std::iterator_traits<
78  OutputIteratorT>::value_type>> &&
79  std::is_trivially_copyable_v<remove_decoration_t<
81  std::is_default_constructible_v<remove_decoration_t<
83  std::is_trivially_copyable_v<InputElemT> &&
84  std::is_default_constructible_v<InputElemT>;
85 
86 template <typename Properties> constexpr bool isBlocked(Properties properties) {
87  if constexpr (properties.template has_property<data_placement_key>())
88  return properties.template get_property<data_placement_key>() ==
90  else
91  return true;
92 }
93 
94 template <bool IsBlocked, int VEC_OR_ARRAY_SIZE, typename GroupTy>
95 int get_mem_idx(GroupTy g, int vec_or_array_idx) {
96  if constexpr (IsBlocked)
97  return g.get_local_linear_id() * VEC_OR_ARRAY_SIZE + vec_or_array_idx;
98  else
99  return g.get_local_linear_id() +
100  g.get_local_linear_range() * vec_or_array_idx;
101 }
102 } // namespace detail
103 
104 #ifdef __SYCL_DEVICE_ONLY__
105 // Load API span overload.
106 template <typename Group, typename InputIteratorT, typename OutputT,
107  std::size_t ElementsPerWorkItem,
108  typename Properties = decltype(properties())>
109 std::enable_if_t<detail::verify_load_types<InputIteratorT, OutputT> &&
110  detail::is_generic_group_v<Group>>
111 group_load(Group g, InputIteratorT in_ptr,
112  span<OutputT, ElementsPerWorkItem> out, Properties properties = {}) {
113  constexpr bool blocked = detail::isBlocked(properties);
114 
115  group_barrier(g);
116  for (int i = 0; i < out.size(); ++i)
117  out[i] = in_ptr[detail::get_mem_idx<blocked, ElementsPerWorkItem>(g, i)];
118  group_barrier(g);
119 }
120 
121 // Store API span overload.
122 template <typename Group, typename InputT, std::size_t ElementsPerWorkItem,
123  typename OutputIteratorT,
124  typename Properties = decltype(properties())>
125 std::enable_if_t<detail::verify_store_types<InputT, OutputIteratorT> &&
126  detail::is_generic_group_v<Group>>
128  OutputIteratorT out_ptr, Properties properties = {}) {
129  constexpr bool blocked = detail::isBlocked(properties);
130 
131  group_barrier(g);
132  for (int i = 0; i < in.size(); ++i)
133  out_ptr[detail::get_mem_idx<blocked, ElementsPerWorkItem>(g, i)] = in[i];
134  group_barrier(g);
135 }
136 
137 // Load API scalar.
138 template <typename Group, typename InputIteratorT, typename OutputT,
139  typename Properties = decltype(properties())>
140 std::enable_if_t<detail::verify_load_types<InputIteratorT, OutputT> &&
141  detail::is_generic_group_v<Group>>
142 group_load(Group g, InputIteratorT in_ptr, OutputT &out,
143  Properties properties = {}) {
144  group_load(g, in_ptr, span<OutputT, 1>(&out, 1), properties);
145 }
146 
147 // Store API scalar.
148 template <typename Group, typename InputT, typename OutputIteratorT,
149  typename Properties = decltype(properties())>
150 std::enable_if_t<detail::verify_store_types<InputT, OutputIteratorT> &&
151  detail::is_generic_group_v<Group>>
152 group_store(Group g, const InputT &in, OutputIteratorT out_ptr,
153  Properties properties = {}) {
154  group_store(g, span<const InputT, 1>(&in, 1), out_ptr, properties);
155 }
156 
157 // Load API sycl::vec overload.
158 template <typename Group, typename InputIteratorT, typename OutputT, int N,
159  typename Properties = decltype(properties())>
160 std::enable_if_t<detail::verify_load_types<InputIteratorT, OutputT> &&
161  detail::is_generic_group_v<Group>>
162 group_load(Group g, InputIteratorT in_ptr, sycl::vec<OutputT, N> &out,
163  Properties properties = {}) {
164  group_load(g, in_ptr, span<OutputT, N>(&out[0], N), properties);
165 }
166 
167 // Store API sycl::vec overload.
168 template <typename Group, typename InputT, int N, typename OutputIteratorT,
169  typename Properties = decltype(properties())>
170 std::enable_if_t<detail::verify_store_types<InputT, OutputIteratorT> &&
171  detail::is_generic_group_v<Group>>
172 group_store(Group g, const sycl::vec<InputT, N> &in, OutputIteratorT out_ptr,
173  Properties properties = {}) {
174  group_store(g, span<const InputT, N>(&in[0], N), out_ptr, properties);
175 }
176 
177 #else
178 template <typename... Args> void group_load(Args...) {
179  throw sycl::exception(
180  std::error_code(PI_ERROR_INVALID_DEVICE, sycl::sycl_category()),
181  "Group loads/stores are not supported on host.");
182 }
183 template <typename... Args> void group_store(Args...) {
184  throw sycl::exception(
185  std::error_code(PI_ERROR_INVALID_DEVICE, sycl::sycl_category()),
186  "Group loads/stores are not supported on host.");
187 }
188 #endif
189 } // namespace ext::oneapi::experimental
190 } // namespace _V1
191 } // namespace sycl
constexpr _SYCL_SPAN_INLINE_VISIBILITY size_type size() const noexcept
Definition: sycl_span.hpp:352
class sycl::vec ///////////////////////// Provides a cross-patform vector class template that works e...
constexpr bool isBlocked(Properties properties)
int get_mem_idx(GroupTy g, int vec_or_array_idx)
constexpr data_placement_key::value_t< Placement > data_placement
constexpr data_placement_key::value_t< data_placement_enum::striped > data_placement_striped
constexpr full_group_key::value_t full_group
constexpr data_placement_key::value_t< data_placement_enum::blocked > data_placement_blocked
constexpr contiguous_memory_key::value_t contiguous_memory
void group_barrier(ext::oneapi::experimental::root_group< dimensions > G, memory_scope FenceScope=decltype(G)::fence_scope)
Definition: root_group.hpp:102
const std::error_category & sycl_category() noexcept
Definition: exception.cpp:88
const void value_type
Definition: multi_ptr.hpp:457
typename remove_decoration< T >::type remove_decoration_t
Definition: access.hpp:325
Definition: access.hpp:18
error_code
Definition: defs.hpp:59