kokkos-utils 0.0.1
 
Loading...
Searching...
No Matches
Manager.hpp
Go to the documentation of this file.
1#ifndef KOKKOS_UTILS_CALLBACKS_MANAGER_HPP
2#define KOKKOS_UTILS_CALLBACKS_MANAGER_HPP
3
4#include <list>
5#include <ranges>
6
9
11{
12
13namespace impl
14{
15
28{
29 virtual ~ListenerConceptBase() = default;
30};
31
32template <Event EventType>
34{
35 virtual ~ListenerConceptCallOperator() = default;
36
37 virtual void operator()(const EventType& event) const = 0;
38};
39
40template <typename...>
42
43template <typename Callable>
45{
46 template <typename T> requires std::same_as<std::remove_cvref_t<T>, Callable>
47 explicit ListenerModelBase(T&& callable_) : callable(std::forward<T>(callable_)) {}
48
49 Callable callable;
50};
51
52template <Event EventType, typename ListenerModel>
54{
55 void operator()(const EventType& event) const override
56 {
57 // Distinguish between a callable object that is a function object and one that is a shared pointer.
58 if constexpr (std::is_invocable_v<decltype(static_cast<const ListenerModel*>(this)->callable), const EventType&>) {
59 static_cast<const ListenerModel*>(this)->callable.operator()(event);
60 } else {
61 static_cast<const ListenerModel*>(this)->callable->operator()(event);
62 }
63 };
64};
65
66template <typename Callable, Event... EventTypes>
67struct ListenerModel<Callable, EventTypes...>
68 : public ListenerModelCallOperator<EventTypes, ListenerModel<Callable, EventTypes...>>...,
69 public ListenerModelBase<Callable>
70{
71 using event_type_list_t = Kokkos::Impl::type_list<EventTypes...>;
72
74};
75
76template <typename Callable, Event... EventTypes>
77struct ListenerModel<Callable, Kokkos::Impl::type_list<EventTypes...>>
78 : public ListenerModel<Callable, EventTypes...>
79{
80 using event_type_list_t = Kokkos::Impl::type_list<EventTypes...>;
81
82 using ListenerModel<Callable, EventTypes...>::ListenerModel;
83};
84
86template <Event EventType>
88{
89 using type = std::list<const ListenerConceptCallOperator<EventType>*>;
90};
91
98>;
100
101} // namespace impl
102
140{
141public:
142 using listener_list_t = std::list<std::unique_ptr<impl::ListenerConceptBase>>;
143 using listener_list_const_iter_t = typename listener_list_t::const_iterator;
145
146public:
147 Manager(const Manager&) = delete;
148 Manager& operator=(const Manager&) = delete;
149
150 ~Manager() { reset_context_callbacks(); }
151
152protected:
157 Manager() : context_callbacks(Kokkos::Tools::Experimental::get_callbacks()) {}
158
159public:
160 static void initialize() { singleton = std::unique_ptr<Manager>(new Manager()); }
161 static void finalize() { singleton.reset(); }
162
163 static Manager& get_instance() { return *singleton; }
164
170 template <Listener Callable>
171 static listener_list_const_iter_t register_listener(std::shared_ptr<Callable> callable)
172 {
173 using event_type_list_t = listener_event_type_list_t<Callable>;
174 using listener_model_t = impl::ListenerModel<std::shared_ptr<Callable>, event_type_list_t>;
175 return register_listener_impl<listener_model_t>(std::move(callable));
176 }
177
184 template <typename T> requires Listener<std::remove_cvref_t<T>>
186 {
187 using event_type_list_t = listener_event_type_list_t<std::remove_cvref_t<T>>;
188 using listener_model_t = impl::ListenerModel<std::remove_cvref_t<T>, event_type_list_t>;
189 return register_listener_impl<listener_model_t>(std::forward<T>(callable));
190 }
191
193 template <Listener Callable>
194 static void unregister_listener(const Callable* const callable)
195 {
196 using event_type_list_t = listener_event_type_list_t<Callable>;
197
198 using listener_model_t = impl::ListenerModel<std::shared_ptr<Callable>, event_type_list_t>;
199
200 auto& listeners = get_instance().listeners;
201
202 const auto iter = std::ranges::find_if(
203 listeners,
204 [&] (const std::unique_ptr<impl::ListenerConceptBase>& listener)
205 {
206 auto* const listener_ptr = dynamic_cast<listener_model_t*>(listener.get());
207 return listener_ptr == nullptr ? false : listener_ptr->callable.get() == callable;
208 }
209 );
210
212 get<Kokkos::utils::impl::type_list_index_v<EventType, EventTypeList>>(get_instance().registered_callbacks).remove(
213 dynamic_cast<const impl::ListenerConceptCallOperator<EventType>*>(iter->get())
214 );
215 });
216
217 listeners.erase(iter);
218
219 get_instance().set_dispatching_callbacks();
220 }
221
223 {
225 get<Kokkos::utils::impl::type_list_index_v<EventType, EventTypeList>>(get_instance().registered_callbacks).remove(
226 dynamic_cast<const impl::ListenerConceptCallOperator<EventType>*>(iter->get())
227 );
228 });
229
230 get_instance().listeners.erase(iter);
231
232 get_instance().set_dispatching_callbacks();
233 }
234
235private:
240 void reset_context_callbacks() const {
241 Kokkos::Tools::Experimental::set_callbacks(context_callbacks);
242 }
243
244 template <typename ListenerModelType, typename CallableType>
245 static listener_list_const_iter_t register_listener_impl(CallableType&& callable)
246 {
247 using event_type_list_t = typename ListenerModelType::event_type_list_t;
248
249 auto& listeners = get_instance().listeners;
250
252 const auto iter = listeners.insert(
253 listeners.end(), std::make_unique<ListenerModelType>(std::forward<CallableType>(callable))
254 );
255
259 get<Kokkos::utils::impl::type_list_index_v<EventType, EventTypeList>>(get_instance().registered_callbacks).push_back(
260 dynamic_cast<const impl::ListenerConceptCallOperator<EventType>*>(iter->get())
261 );
262 });
263
264 get_instance().set_dispatching_callbacks();
265
266 return iter;
267 }
268
274 void set_dispatching_callbacks() const
275 {
276 Kokkos::utils::impl::for_each<EventTypeList>([&] <Event EventType>() {
277 set_dispatching_callback_impl<EventType>();
278 });
279 }
280
281 template <Event EventType>
282 void set_dispatching_callback_impl() const
283 {
285 get<Kokkos::utils::impl::type_list_index_v<EventType, EventTypeList>>(registered_callbacks).empty()
286 ? get_callback_from_eventset<EventType>(context_callbacks)
287 : create_dispatching_callback_for_event_type_impl<EventType>()
288 );
289 }
290
293 template <Event EventType>
294 static auto create_dispatching_callback_for_event_type_impl()
295 {
296 return [] <typename... Args>(Args... args) -> void {
297 EventType event{args...};
298 get_instance().dispatch(event);
299 };
300 }
301
302 template <BeginEvent EventType>
303 static auto create_dispatching_callback_for_event_type_impl()
304 {
305 return [] (const char* name, const uint32_t dev_id, uint64_t* event_id) -> void
306 {
307 EventType event{ .name = name, .dev_id = dev_id, .event_id = *event_id };
308 get_instance().dispatch(event);
309 *event_id = event.event_id;
310 };
311 }
312
313 template <DataEvent EventType>
314 static auto create_dispatching_callback_for_event_type_impl()
315 {
316 return [] (Kokkos_Profiling_SpaceHandle kpsh, const char* name, const void* ptr, uint64_t size) -> void
317 {
318 EventType event{ .alloc = { .kpsh = kpsh, .name = name, .ptr = ptr, .size = size } };
319 get_instance().dispatch(event);
320 };
321 }
322
323 template <Event EventType> requires std::same_as<EventType, BeginDeepCopyEvent>
324 static auto create_dispatching_callback_for_event_type_impl()
325 {
326 return [] (Kokkos_Profiling_SpaceHandle dst_kpsh, const char* dst_name, const void* dst_ptr,
327 Kokkos_Profiling_SpaceHandle src_kpsh, const char* src_name, const void* src_ptr, uint64_t size) -> void
328 {
329 EventType event{
330 .dst = { .kpsh = dst_kpsh, .name = dst_name, .ptr = dst_ptr, .size = size },
331 .src = { .kpsh = src_kpsh, .name = src_name, .ptr = src_ptr, .size = size }
332 };
333 get_instance().dispatch(event);
334 };
335 }
336
337 template <Event EventType> requires std::same_as<EventType, CreateProfileSectionEvent>
338 static auto create_dispatching_callback_for_event_type_impl()
339 {
340 return [] (const char* name, uint32_t* section_id) -> void
341 {
342 EventType event{ .name = name, .section_id = *section_id };
343 get_instance().dispatch(event);
344 *section_id = event.section_id;
345 };
346 }
347
352 template <Event EventType>
353 void dispatch(EventType& event)
354 {
355 dispatch_context_callback(event);
356
357 dispatch_registered_callbacks(event);
358 }
359
361 template <Event EventType>
362 void dispatch_context_callback(EventType& event)
363 {
364 auto* context_callback = get_callback_from_eventset<EventType>(context_callbacks);
365
366 if (context_callback) {
367 dispatch_context_callback_for_event_type_impl(context_callback, event);
368 } else {
369 increment_id_if_needed_for_event_type_impl(event);
370 }
371 }
372
373 template <typename ContextCallbackType, BeginEvent EventType>
374 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, EventType& event) {
375 context_callback(event.name.c_str(), event.dev_id, &event.event_id);
376 }
377
378 template <typename ContextCallbackType, EndEvent EventType>
379 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const EventType& event) {
380 context_callback(event.event_id);
381 }
382
383 template <typename ContextCallbackType, DataEvent EventType>
384 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const EventType& event) {
385 context_callback(event.alloc.kpsh, event.alloc.name.c_str(), event.alloc.ptr, event.alloc.size);
386 }
387
388 template <typename ContextCallbackType>
389 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const BeginDeepCopyEvent& event) {
390 context_callback(event.dst.kpsh, event.dst.name.c_str(), event.dst.ptr,
391 event.src.kpsh, event.src.name.c_str(), event.src.ptr, event.src.size);
392 }
393
394 template <typename ContextCallbackType>
395 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const EndDeepCopyEvent& /* event */) {
396 context_callback();
397 }
398
399 template <typename ContextCallbackType>
400 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, CreateProfileSectionEvent& event) {
401 context_callback(event.name.c_str(), &event.section_id);
402 }
403
404 template <typename ContextCallbackType, ProfileSectionManipulationEvent EventType>
405 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const EventType& event) {
406 context_callback(event.section_id);
407 }
408
409 template <typename ContextCallbackType>
410 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const PushRegionEvent& event) {
411 context_callback(event.name.c_str());
412 }
413
414 template <typename ContextCallbackType>
415 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const PopRegionEvent& /* event */) {
416 context_callback();
417 }
418
419 template <typename ContextCallbackType>
420 static void dispatch_context_callback_for_event_type_impl(ContextCallbackType* context_callback, const ProfileEvent& event) {
421 context_callback(event.name.c_str());
422 }
423
424 template <Event EventType>
425 void increment_id_if_needed_for_event_type_impl(EventType& /* event */) {}
426
427 template <BeginEvent EventType>
428 void increment_id_if_needed_for_event_type_impl(EventType& event) {
429 event.event_id = next_event_id++;
430 }
431
432 void increment_id_if_needed_for_event_type_impl(CreateProfileSectionEvent& event) {
433 event.section_id = next_section_id++;
434 }
435
436 template <Event EventType>
437 void dispatch_registered_callbacks(const EventType& event) const
438 {
439 for (const auto& listener : get<Kokkos::utils::impl::type_list_index_v<EventType, EventTypeList>>(registered_callbacks)) {
440 listener->operator()(event);
441 }
442 }
443
444private:
445 listener_call_opr_list_tuple_t registered_callbacks {};
446
447 listener_list_t listeners {};
448
449 static inline std::unique_ptr<Manager> singleton = nullptr;
450
451 Kokkos::Tools::Experimental::EventSet context_callbacks {};
452
453 uint64_t next_event_id = 0;
454 uint32_t next_section_id = 0;
455};
456
457} // namespace Kokkos::utils::callbacks
458
459#endif // KOKKOS_UTILS_CALLBACKS_MANAGER_HPP
std::list< std::unique_ptr< impl::ListenerConceptBase > > listener_list_t
Definition Manager.hpp:142
static void unregister_listener(const Callable *const callable)
Unregister a callable object as a listener.
Definition Manager.hpp:194
static Manager & get_instance()
Definition Manager.hpp:163
Manager(const Manager &)=delete
static listener_list_const_iter_t register_listener(T &&callable)
Definition Manager.hpp:185
Manager()
Constructor. Retrieves and stores the Kokkos::Tools::Experimental::EventSet containing the Kokkos cal...
Definition Manager.hpp:157
impl::listener_call_opr_list_tuple_t listener_call_opr_list_tuple_t
Definition Manager.hpp:144
typename listener_list_t::const_iterator listener_list_const_iter_t
Definition Manager.hpp:143
Manager & operator=(const Manager &)=delete
static void unregister_listener(const listener_list_const_iter_t &iter)
Definition Manager.hpp:222
static listener_list_const_iter_t register_listener(std::shared_ptr< Callable > callable)
Register a callable object, passed as a shared pointer, as a listener.
Definition Manager.hpp:171
Concept that models that a callable object to be registered as a listener by Kokkos::utils::callbacks...
Definition Listener.hpp:31
Kokkos::utils::impl::type_list_to_tuple_t< Kokkos::utils::impl::transform_type_list_t< ListOfListenerCallOprPerEventTypeTransformer, EventTypeList > > listener_call_opr_list_tuple_t
Type of container used by Kokkos::utils::callbacks::Manager to store pointers to the registered liste...
Definition Manager.hpp:96
Kokkos::Impl::filter_type_list_t< impl::IsListenerFor< Callable >::template type, EventTypeList > listener_event_type_list_t
Type list holding the event types that a callable object can be a listener for.
Definition Listener.hpp:24
auto get_callback_from_eventset(const Kokkos::Tools::Experimental::EventSet &event_set)
auto get_callback_setter()
Get the setter function of a Kokkos profiling callback corresponding to EventType.
constexpr void for_each(Callable callable)
Calls the instantiation of the call operator of a callable object for each type in a Kokkos::Impl::ty...
typename TransformTypeList< TransformerType, T >::type transform_type_list_t
Definition type_list.hpp:70
typename TypeListToTuple< T >::type type_list_to_tuple_t
Definition type_list.hpp:85
constexpr size_t type_list_index_v
Helper struct needed for the implementation of Kokkos::utils::callbacks::impl::listener_call_opr_list...
Definition Manager.hpp:88
std::list< const ListenerConceptCallOperator< EventType > * > type
Definition Manager.hpp:89
Helper structures used by Kokkos::utils::callbacks::Manager to store and call registered listeners.
Definition Manager.hpp:28
virtual void operator()(const EventType &event) const =0
void operator()(const EventType &event) const override
Definition Manager.hpp:55