DPC++ Runtime
Runtime libraries for oneAPI DPC++
launch_policy.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Copyright (C) Codeplay Software Ltd.
4  *
5  * Part of the LLVM Project, under the Apache License v2.0 with LLVM
6  * Exceptions. See https://llvm.org/LICENSE.txt for license information.
7  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  * SYCL compatibility extension
16  *
17  * launch.hpp
18  *
19  * Description:
20  * launch functionality for the SYCL compatibility extension
21  **************************************************************************/
22 
23 #pragma once
24 
27 #include <sycl/event.hpp>
28 #include <sycl/nd_range.hpp>
29 #include <sycl/queue.hpp>
30 #include <sycl/range.hpp>
31 
32 #include <syclcompat/defs.hpp>
33 #include <syclcompat/device.hpp>
34 #include <syclcompat/dims.hpp>
35 #include <syclcompat/traits.hpp>
36 
37 namespace syclcompat {
38 namespace experimental {
39 
40 namespace sycl_exp = sycl::ext::oneapi::experimental;
41 
42 // Wrapper for kernel sycl_exp::properties
43 template <typename Properties> struct kernel_properties {
44  static_assert(sycl_exp::is_property_list_v<Properties>);
45  using Props = Properties;
46 
47  template <typename... Props>
48  kernel_properties(Props... properties) : props{properties...} {}
49 
50  template <typename... Props>
52  : props{properties} {}
53 
54  Properties props;
55 };
56 
57 template <typename... Props, typename = std::enable_if_t<detail::are_all_props<Props...>::value, void>>
58 kernel_properties(Props... props)
59  -> kernel_properties<decltype(sycl_exp::properties(props...))>;
60 
61 template <typename... Props>
64 
65 // Wrapper for launch sycl_exp::properties
66 template <typename Properties> struct launch_properties {
67  static_assert(sycl_exp::is_property_list_v<Properties>);
68  using Props = Properties;
69 
70  template <typename... Props>
71  launch_properties(Props... properties) : props{properties...} {}
72 
73  template <typename... Props>
75  : props{properties} {}
76 
77  Properties props;
78 };
79 
80 template <typename... Props, typename = std::enable_if_t<detail::are_all_props<Props...>::value, void>>
81 launch_properties(Props... props)
82  -> launch_properties<decltype(sycl_exp::properties(props...))>;
83 
84 template <typename... Props>
87 
88 // Wrapper for local memory size
90  local_mem_size(size_t size = 0) : size{size} {};
91  size_t size;
92 };
93 
94 // launch_policy is constructed by the user & passed to `compat_exp::launch`
95 template <typename Range, typename KProps, typename LProps, bool LocalMem>
97  static_assert(sycl_exp::is_property_list_v<KProps>);
98  static_assert(sycl_exp::is_property_list_v<LProps>);
99  static_assert(syclcompat::detail::is_range_or_nd_range_v<Range>);
100  static_assert(syclcompat::detail::is_nd_range_v<Range> || !LocalMem,
101  "sycl::range kernel launches are incompatible with local "
102  "memory usage!");
103 
104 public:
105  using KPropsT = KProps;
106  using LPropsT = LProps;
107  using RangeT = Range;
108  static constexpr bool HasLocalMem = LocalMem;
109 
110 private:
111  launch_policy() = default;
112 
113  template <typename... Ts>
114  launch_policy(Ts... ts)
115  : _kernel_properties{detail::property_getter<
116  kernel_properties, kernel_properties<KPropsT>, std::tuple<Ts...>>()(
117  std::tuple<Ts...>(ts...))},
118  _launch_properties{detail::property_getter<
119  launch_properties, launch_properties<LPropsT>, std::tuple<Ts...>>()(
120  std::tuple<Ts...>(ts...))},
121  _local_mem_size{
122  detail::local_mem_getter<local_mem_size, std::tuple<Ts...>>()(
123  std::tuple<Ts...>(ts...))} {
124  check_variadic_args(ts...);
125  }
126 
127  template <typename... Ts> void check_variadic_args(Ts...) {
128  static_assert(
129  std::conjunction_v<std::disjunction<detail::is_kernel_properties<Ts>,
130  detail::is_launch_properties<Ts>,
131  detail::is_local_mem_size<Ts>>...>,
132  "Received an unexpected argument to ctor. Did you forget to wrap "
133  "in "
134  "compat::kernel_properties, launch_properties, local_mem_size?");
135  }
136 
137 public:
138  template <typename... Ts>
139  launch_policy(Range range, Ts... ts) : launch_policy(ts...) {
140  _range = range;
141  check_variadic_args(ts...);
142  }
143 
144  template <typename... Ts>
145  launch_policy(dim3 global_range, Ts... ts) : launch_policy(ts...) {
146  _range = Range{global_range};
147  check_variadic_args(ts...);
148  }
149 
150  template <typename... Ts>
151  launch_policy(dim3 global_range, dim3 local_range, Ts... ts)
152  : launch_policy(ts...) {
153  _range = Range{global_range * local_range, local_range};
154  check_variadic_args(ts...);
155  }
156 
157  KProps get_kernel_properties() { return _kernel_properties.props; }
158  LProps get_launch_properties() { return _launch_properties.props; }
159  size_t get_local_mem_size() { return _local_mem_size.size; }
160  Range get_range() { return _range; }
161 
162 private:
163  Range _range;
164  kernel_properties<KProps> _kernel_properties;
165  launch_properties<LProps> _launch_properties;
166  local_mem_size _local_mem_size;
167 };
168 
169 // Deduction guides for launch_policy
170 template <typename Range, typename... Ts>
171 launch_policy(Range, Ts...) -> launch_policy<
172  Range, detail::properties_or_empty<kernel_properties, Ts...>,
173  detail::properties_or_empty<launch_properties, Ts...>,
174  detail::has_type<local_mem_size, std::tuple<Ts...>>::value>;
175 
176 template <int Dim, typename... Ts>
178  sycl::nd_range<Dim>, detail::properties_or_empty<kernel_properties, Ts...>,
179  detail::properties_or_empty<launch_properties, Ts...>,
180  detail::has_type<local_mem_size, std::tuple<Ts...>>::value>;
181 
182 template <typename... Ts>
184  sycl::range<3>, detail::properties_or_empty<kernel_properties, Ts...>,
185  detail::properties_or_empty<launch_properties, Ts...>,
186  detail::has_type<local_mem_size, std::tuple<Ts...>>::value>;
187 
188 template <typename... Ts>
190  sycl::nd_range<3>, detail::properties_or_empty<kernel_properties, Ts...>,
191  detail::properties_or_empty<launch_properties, Ts...>,
192  detail::has_type<local_mem_size, std::tuple<Ts...>>::value>;
193 
194 namespace detail {
195 
196 template <auto F, typename Range, typename KProps, bool HasLocalMem,
197  typename... Args>
199  KernelFunctor(KProps kernel_props, Args... args)
200  : _kernel_properties{kernel_props},
201  _argument_tuple(std::make_tuple(args...)) {}
202 
203  KernelFunctor(KProps kernel_props, sycl::local_accessor<char, 1> local_acc,
204  Args... args)
205  : _kernel_properties{kernel_props}, _local_acc{local_acc},
206  _argument_tuple(std::make_tuple(args...)) {}
207 
209 
212  if constexpr (HasLocalMem) {
213  char *local_mem_ptr = static_cast<char *>(
214  _local_acc.template get_multi_ptr<sycl::access::decorated::no>().get());
215  std::apply(
216  [lmem_ptr = local_mem_ptr](auto &&...args) { F(args..., lmem_ptr); },
218  } else {
219  std::apply([](auto &&...args) { F(args...); }, _argument_tuple);
220  }
221  }
222 
224  std::tuple<Args...> _argument_tuple;
225  std::conditional_t<HasLocalMem, sycl::local_accessor<char, 1>, std::monostate>
226  _local_acc; // monostate for empty type
227 };
228 
229 //====================================================================
230 // This helper function avoids 2 nested `if constexpr` in detail::launch
231 template <auto F, typename LaunchPolicy, typename... Args>
233  Args... args)
234  -> KernelFunctor<F, typename LaunchPolicy::RangeT,
235  typename LaunchPolicy::KPropsT, LaunchPolicy::HasLocalMem,
236  Args...> {
237  if constexpr (LaunchPolicy::HasLocalMem) {
238  sycl::local_accessor<char, 1> local_memory(
240  return KernelFunctor<F, typename LaunchPolicy::RangeT,
241  typename LaunchPolicy::KPropsT,
242  LaunchPolicy::HasLocalMem, Args...>(
243  launch_policy.get_kernel_properties(), local_memory, args...);
244  } else {
245  return KernelFunctor<F, typename LaunchPolicy::RangeT,
246  typename LaunchPolicy::KPropsT,
247  LaunchPolicy::HasLocalMem, Args...>(
249  }
250 }
251 
252 } // namespace detail
253 } // namespace experimental
254 } // namespace syclcompat
Command group handler class.
Definition: handler.hpp:478
Defines the iteration domain of both the work-groups and the overall dispatch.
Definition: nd_range.hpp:22
Defines the iteration domain of either a single work-group in a parallel dispatch,...
Definition: range.hpp:26
launch_policy(dim3 global_range, Ts... ts)
launch_policy(dim3 global_range, dim3 local_range, Ts... ts)
#define __syclcompat_inline__
Definition: defs.hpp:46
constexpr tuple< Ts... > make_tuple(Ts... Args)
Definition: tuple.hpp:35
typename range_to_item_map< T >::ItemT range_to_item_t
Definition: traits.hpp:90
auto build_kernel_functor(sycl::handler &cgh, LaunchPolicy launch_policy, Args... args) -> KernelFunctor< F, typename LaunchPolicy::RangeT, typename LaunchPolicy::KPropsT, LaunchPolicy::HasLocalMem, Args... >
kernel_properties(Props... props) -> kernel_properties< decltype(sycl_exp::properties(props...))>
launch_policy(Range, Ts...) -> launch_policy< Range, detail::properties_or_empty< kernel_properties, Ts... >, detail::properties_or_empty< launch_properties, Ts... >, detail::has_type< local_mem_size, std::tuple< Ts... >>::value >
launch_properties(Props... props) -> launch_properties< decltype(sycl_exp::properties(props...))>
KernelFunctor(KProps kernel_props, sycl::local_accessor< char, 1 > local_acc, Args... args)
std::conditional_t< HasLocalMem, sycl::local_accessor< char, 1 >, std::monostate > _local_acc
__syclcompat_inline__ void operator()(syclcompat::detail::range_to_item_t< Range >) const
KernelFunctor(KProps kernel_props, Args... args)
kernel_properties(sycl_exp::properties< Props... > properties)
launch_properties(sycl_exp::properties< Props... > properties)