kokkos-execution 0.0.1
Loading...
Searching...
No Matches
completion_signal.hpp
Go to the documentation of this file.
1#ifndef KOKKOS_EXECUTION_IMPL_COMPLETION_SIGNAL_HPP
2#define KOKKOS_EXECUTION_IMPL_COMPLETION_SIGNAL_HPP
3
5
6#if defined(KOKKOS_EXECUTION_ENABLE_DEBUG_LOGGING)
7# include "plog/Log.h"
8#endif
9
11
18
20
28template <Kokkos::ExecutionSpace Exec, stdexec::receiver Rcvr>
31 bool operator()(const Exec& exec, const Rcvr& rcvr) const noexcept
32 requires(stdexec::__queryable_with<stdexec::env_of_t<Rcvr>, get_exec_t>)
33 {
34 if constexpr (
35 std::same_as<
36 std::remove_cvref_t<stdexec::__query_result_t<stdexec::env_of_t<Rcvr>, get_exec_t>>,
38 >) {
39 const auto& src = exec;
40 const auto& dst = get_exec(stdexec::get_env(rcvr)).get();
41#if defined(KOKKOS_EXECUTION_ENABLE_DEBUG_LOGGING)
42 PLOG_DEBUG << "The synchronization happens if " << Kokkos::Tools::Experimental::device_id(src)
43 << " is not equal to " << Kokkos::Tools::Experimental::device_id(dst) << '.';
44#endif
45 return src != dst;
46 }
47 return true;
48 }
49
51 constexpr bool operator()(const Exec&, const Rcvr&) const noexcept
52 requires(!stdexec::__queryable_with<stdexec::env_of_t<Rcvr>, get_exec_t>)
53 {
54#if defined(KOKKOS_EXECUTION_ENABLE_DEBUG_LOGGING)
55 PLOG_DEBUG << "Synchronization always required.";
56#endif
57 return true;
58 }
59};
60
61struct DeferredCompletionReceiverTag : public stdexec::receiver_tag { };
62
63template <typename Rcvr, typename Exec>
65 stdexec::receiver<Rcvr>
66 && std::derived_from<typename std::remove_cvref_t<Rcvr>::receiver_concept, DeferredCompletionReceiverTag>
67 && requires(std::remove_reference_t<Rcvr> rcvr, const Event<Exec>& event) {
68 std::move(rcvr).continues_after();
69 std::move(rcvr).continues_after(event);
70 };
71
72struct SyncPolicy {
73 struct InlineFenceExec { };
75 struct PassThrough { };
76 struct DeferWaitEvent { };
77};
78
79template <typename Policy, Kokkos::ExecutionSpace Exec, stdexec::receiver Rcvr>
81
87template <Kokkos::ExecutionSpace Exec, stdexec::receiver Rcvr>
88struct CompletionSignal<SyncPolicy::InlineFenceExec, Exec, Rcvr> {
89 static constexpr auto label = Impl::dispatch_label<Exec, ": after dispatch">();
90
91 Rcvr rcvr;
92
93 void propagate(stdexec::set_value_t, const Exec& exec) & noexcept {
94 if (!RequiresSync<Exec, Rcvr>{}(exec, rcvr)) {
95 stdexec::set_value(std::move(rcvr));
96 } else {
97 try {
98 exec.fence(std::string(label));
99 stdexec::set_value(std::move(rcvr));
100 } catch (...) {
101 stdexec::set_error(std::move(rcvr), std::current_exception());
102 }
103 }
104 }
105
106 template <typename Error>
107 void propagate(stdexec::set_error_t, Error&& err) & noexcept {
108 stdexec::set_error(std::move(rcvr), std::forward<Error>(err));
109 }
110
111 void propagate(stdexec::set_stopped_t) & noexcept {
112 stdexec::set_stopped(std::move(rcvr));
113 }
114};
115
116template <Kokkos::ExecutionSpace Exec, stdexec::receiver Rcvr>
118 using receiver_concept = stdexec::receiver_tag;
119
121
122 void set_value() && noexcept {
123 try {
125 stdexec::set_value(std::move(completion_signal->rcvr));
126 } catch (...) {
127 stdexec::set_error(std::move(completion_signal->rcvr), std::current_exception());
128 }
129 }
130};
131
138template <Kokkos::ExecutionSpace Exec, stdexec::receiver Rcvr>
139struct CompletionSignal<SyncPolicy::ScheduleWaitEvent, Exec, Rcvr> {
142 using inner_opstate_t = stdexec::connect_result_t<
143 stdexec::schedule_result_t<delegation_scheduler_t>,
145 >;
146
147 Rcvr rcvr;
150
151 constexpr explicit CompletionSignal(Rcvr rcvr_) noexcept(std::is_nothrow_move_constructible_v<Rcvr>)
152 : rcvr(std::move(rcvr_)) {
153 }
154
155 void propagate(stdexec::set_value_t, const Exec& exec) & noexcept {
156 if (!RequiresSync<Exec, Rcvr>{}(exec, rcvr)) {
157 stdexec::set_value(std::move(rcvr));
158 } else {
159 try {
160 event.emplace();
161 record(*event, exec);
162 inner_opstate.emplace_from(
163 stdexec::connect,
164 stdexec::schedule(stdexec::get_delegation_scheduler(stdexec::get_env(rcvr))),
166 stdexec::start(inner_opstate.get());
167 } catch (...) {
168 stdexec::set_error(std::move(rcvr), std::current_exception());
169 }
170 }
171 }
172
173 template <typename Error>
174 void propagate(stdexec::set_error_t, Error&& err) & noexcept {
175 stdexec::set_error(std::move(rcvr), std::forward<Error>(err));
176 }
177
178 void propagate(stdexec::set_stopped_t) & noexcept {
179 stdexec::set_stopped(std::move(rcvr));
180 }
181};
182
183template <Kokkos::ExecutionSpace Exec, stdexec::receiver Rcvr>
184struct CompletionSignal<SyncPolicy::PassThrough, Exec, Rcvr> {
185 Rcvr rcvr;
186
188 void propagate(stdexec::set_value_t) & noexcept {
189 stdexec::set_value(std::move(rcvr));
190 }
191
192 void propagate(stdexec::set_value_t, const Exec&) & noexcept {
193 std::move(rcvr).continues_after();
194 }
195
196 template <typename Error>
197 void propagate(stdexec::set_error_t, Error&& err) & noexcept {
198 stdexec::set_error(std::move(rcvr), std::forward<Error>(err));
199 }
200
201 void propagate(stdexec::set_stopped_t) & noexcept {
202 stdexec::set_stopped(std::move(rcvr));
203 }
204};
205
212template <Kokkos::ExecutionSpace Exec, stdexec::receiver Rcvr>
213struct CompletionSignal<SyncPolicy::DeferWaitEvent, Exec, Rcvr> {
215
216 Rcvr rcvr;
218
219 constexpr explicit CompletionSignal(Rcvr rcvr_) noexcept(std::is_nothrow_move_constructible_v<Rcvr>)
220 : rcvr(std::move(rcvr_)) {
221 }
222
223 void propagate(stdexec::set_value_t, const Exec& exec) & noexcept {
224 if (!RequiresSync<Exec, Rcvr>{}(exec, rcvr)) {
225 std::move(rcvr).continues_after();
226 } else {
227 event.emplace();
228 record(*event, exec);
229 std::move(rcvr).continues_after(*event);
230 }
231 }
232
233 template <typename Error>
234 void propagate(stdexec::set_error_t, Error&& err) & noexcept {
235 stdexec::set_error(std::move(rcvr), std::forward<Error>(err));
236 }
237
238 void propagate(stdexec::set_stopped_t) & noexcept {
239 stdexec::set_stopped(std::move(rcvr));
240 }
241};
242
243} // namespace Kokkos::Execution::Impl
244
245#endif // KOKKOS_EXECUTION_IMPL_COMPLETION_SIGNAL_HPP
Data structure that has an interface similar to std::optional but stores the value with stdexec::__ma...
Constrain an EventType type to be a valid event type for Exec execution space type.
Definition event.hpp:24
std::optional< Event< Exec > > event_storage_t
Definition event.hpp:167
stdexec::__query_result_t< const Env &, stdexec::get_delegation_scheduler_t > delegation_scheduler_of_t
Definition schedulers.hpp:9
void record(Event< Exec > &event, const Exec &exec)
Record event on exec.
Definition event.hpp:138
constexpr get_exec_t get_exec
Definition get_exec.hpp:17
void wait(const Event< Exec > &event)
Wait for event to complete.
Definition event.hpp:145
consteval std::string_view dispatch_label() noexcept
View the dispatch label as a std::string_view.
constexpr CompletionSignal(Rcvr rcvr_) noexcept(std::is_nothrow_move_constructible_v< Rcvr >)
stdexec::connect_result_t< stdexec::schedule_result_t< delegation_scheduler_t >, ScheduleWaitEventReceiver< Exec, Rcvr > > inner_opstate_t
constexpr CompletionSignal(Rcvr rcvr_) noexcept(std::is_nothrow_move_constructible_v< Rcvr >)
Impl::delegation_scheduler_of_t< stdexec::env_of_t< Rcvr > > delegation_scheduler_t
An event that can be recorded on an execution space instance.
Definition event.hpp:108
Wrap a Kokkos execution space to make it cheap to copy/move in new environments.
Definition get_exec.hpp:27
constexpr bool operator()(const Exec &, const Rcvr &) const noexcept
bool operator()(const Exec &exec, const Rcvr &rcvr) const noexcept
CompletionSignal< SyncPolicy::ScheduleWaitEvent, Exec, Rcvr > * completion_signal