Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
kernel_call.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10#pragma once
11
18
19#include "shambase/optional.hpp"
25#include <functional>
26#include <optional>
27
28namespace sham {
29
30 namespace details {
31
33 template<class index_t, class RefIn, class RefOut, class Functor>
36 RefIn in,
37 RefOut in_out,
38 index_t n,
39 Functor &&kernel_gen,
40 SourceLocation &&callsite = SourceLocation{}) {
41
43
44 if (n == 0) {
45 shambase::throw_with_loc<std::runtime_error>("kernel call with : n == 0");
46 }
47
48 sham::EventList depends_list;
49
50 auto acc_in = in.get_read_access(depends_list);
51 auto acc_in_out = in_out.get_write_access(depends_list);
52
53 sycl::event e;
54
55 // unpack the tuples of accessors
56 std::apply(
57 [&](auto &...__acc_in) {
58 std::apply(
59 [&](auto &...__acc_in_out) {
60 // submit the kernel generated by the functor
61 e = q.submit(depends_list, kernel_gen(n, __acc_in..., __acc_in_out...));
62 },
63 acc_in_out);
64 },
65 acc_in);
66
67 in.complete_event_state(e);
68 in_out.complete_event_state(e);
69 }
70
72 // Helper types for kernel signature checking (and clean error messages)
74
76 template<class index_t, class RefIn, class RefOut>
78
79 using args_types = decltype(std::tuple_cat(
80 std::tuple<index_t>{},
81
82 std::declval<decltype(std::declval<RefIn>().get_read_access(
83 std::declval<sham::EventList &>()))>(),
84
85 std::declval<decltype(std::declval<RefOut>().get_write_access(
86 std::declval<sham::EventList &>()))>()));
87 };
88
90 template<typename Tuple>
92
93 template<typename... Ts>
94 struct tuple_to_signature<std::tuple<Ts...>> {
95 using type = void(Ts...);
96 };
97
99 template<typename Signature>
101
102 template<typename Ret, typename... Ts>
103 struct expected_kernel_signature<Ret(Ts...)> {};
104
106 template<class index_t, class RefIn, class RefOut>
108 typename kernel_gen_args<index_t, RefIn, RefOut>::args_types>::type>;
109
111 template<typename F, typename Signature>
113
114 template<typename F, typename Ret, typename... Ts>
116 : std::bool_constant<std::invocable<F, Ts...>> {};
117
121 template<typename F, typename Signature>
123
126 template<typename Signature>
128
129 template<typename Ret, typename... Ts>
131 using type = Ret(Ts...);
132 };
133
135 template<class ExpectedFnSignature>
136 inline constexpr bool matches_expected_kernel_signature = false;
137
143 template<class index_t, class RefIn, class RefOut, class Functor>
146 RefIn in,
147 RefOut in_out,
148 index_t n,
149 Functor &&func,
150 SourceLocation &&callsite = SourceLocation{}) {
151
152 using expected_sig = kernel_expected_signature<index_t, RefIn, RefOut>;
153
154 if constexpr (is_kernel_invocable<Functor, expected_sig>::value) {
155 __shamrock_log_callsite(callsite);
156
157 typed_index_kernel_call_lambda(
158 q,
159 in,
160 in_out,
161 n,
162 [func
163 = std::forward<Functor>(func)](u32 n, auto... __acc_in, auto... __acc_in_out) {
164 return [=](sycl::handler &cgh) {
165 cgh.parallel_for(sycl::range<1>{n}, [=](sycl::item<1> item) {
166 func(index_t(item.get_linear_id()), __acc_in..., __acc_in_out...);
167 });
168 };
169 });
170 } else {
171 static_assert(
174 "Kernel functor is not invocable with the expected signature; see "
175 "matches_expected_kernel_signature<void(...)> for the required argument list.");
176 }
177 }
178 } // namespace details
179
343 template<class RefIn, class RefOut, class Functor>
346 RefIn in,
347 RefOut in_out,
348 u32 n,
349 Functor &&func,
350 SourceLocation &&callsite = SourceLocation{}) {
351
352 __shamrock_log_callsite(callsite);
353
354 details::typed_index_kernel_call<u32, RefIn, RefOut>(
355 q, in, in_out, n, std::forward<Functor>(func));
356 }
357
359 template<class RefIn, class RefOut, class Functor>
362 RefIn in,
363 RefOut in_out,
364 u64 n,
365 Functor &&func,
366 SourceLocation &&callsite = SourceLocation{}) {
367
368 __shamrock_log_callsite(callsite);
369
370 details::typed_index_kernel_call<u64, RefIn, RefOut>(
371 q, in, in_out, n, std::forward<Functor>(func));
372 }
373
374 // version where one supplies a kernel generator in the form of [&](sycl::handler &cgh) { ... }
375 template<class RefIn, class RefOut, class Functor>
376 void kernel_call_hndl(
377 sham::DeviceQueue &q,
378 RefIn in,
379 RefOut in_out,
380 u32 n,
381 Functor &&kernel_gen,
382 SourceLocation &&callsite = SourceLocation{}) {
383
384 __shamrock_log_callsite(callsite);
385
387 q, in, in_out, n, std::forward<Functor>(kernel_gen));
388 }
389
391 template<class RefIn, class RefOut, class Functor>
394 RefIn in,
395 RefOut in_out,
396 u64 n,
397 Functor &&kernel_gen,
398 SourceLocation &&callsite = SourceLocation{}) {
399
400 __shamrock_log_callsite(callsite);
401
402 details::typed_index_kernel_call_lambda<u64, RefIn, RefOut>(
403 q, in, in_out, n, std::forward<Functor>(kernel_gen));
404 }
405
406} // namespace sham
std::uint32_t u32
32 bit unsigned integer
std::uint64_t u64
64 bit unsigned integer
A SYCL queue associated with a device and a context.
sycl::event submit(Fct &&fct)
Submits a kernel to the SYCL queue.
Class to manage a list of SYCL events.
Definition EventList.hpp:31
constexpr bool matches_expected_kernel_signature
Always-false flag parameterized by the expected function type (shown in static_assert).
void typed_index_kernel_call(sham::DeviceQueue &q, RefIn in, RefOut in_out, index_t n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
expected_kernel_signature< typename tuple_to_signature< typename kernel_gen_args< index_t, RefIn, RefOut >::args_types >::type > kernel_expected_signature
The expected signature of the kernel generator.
void typed_index_kernel_call_lambda(sham::DeviceQueue &q, RefIn in, RefOut in_out, index_t n, Functor &&kernel_gen, SourceLocation &&callsite=SourceLocation{})
internal implementation of typed_index_kernel_call
namespace for backends this one is named only sham since shambackends is too long to write
void kernel_call_u64(sham::DeviceQueue &q, RefIn in, RefOut in_out, u64 n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
u64 indexed variant of kernel_call
void kernel_call(sham::DeviceQueue &q, RefIn in, RefOut in_out, u32 n, Functor &&func, SourceLocation &&callsite=SourceLocation{})
Submit a kernel to a SYCL queue.
void kernel_call_hndl_u64(sham::DeviceQueue &q, RefIn in, RefOut in_out, u64 n, Functor &&kernel_gen, SourceLocation &&callsite=SourceLocation{})
u64 indexed variant of kernel_call_hndl
void throw_with_loc(std::string message, SourceLocation loc=SourceLocation{})
Throw an exception and append the source location to it.
Traits for C++ types.
#define __shamrock_stack_entry_with_callsite(callsite)
Macro to create a stack entry.
#define __shamrock_log_callsite(callsite)
Macro to create a stack entry from a given location. Can be used only on SourceLocation &&.
provide information about the source location
Trick to name the error message if we want to use it.
Helper to check if the functor is invocable with the expected signature.
helper type to get the arguments types of the kernel generator
Helper to extract the function signature from a tuple of types.