Skip to content

Commit de4f28a

Browse files
[NFC][SYCL] Add devices_range helper to cleanup persistent_device_code_cache (#19405)
Same idea as with `nodes_range` from #19295, this PR generalizes the approach and makes both `nodes_|devices_range` use the same common utility. `persistent_device_code_cache` was chosen randomly to apply simplifications by using the new helper. Subsequent PRs will likely make wider usage of it.
1 parent ad75198 commit de4f28a

File tree

7 files changed

+194
-138
lines changed

7 files changed

+194
-138
lines changed

sycl/source/detail/device_impl.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#pragma once
1010

11+
#include <detail/helpers.hpp>
1112
#include <detail/platform_impl.hpp>
1213
#include <detail/program_manager/program_manager.hpp>
1314
#include <sycl/aspects.hpp>
@@ -2281,6 +2282,33 @@ class device_impl : public std::enable_shared_from_this<device_impl> {
22812282

22822283
}; // class device_impl
22832284

2285+
struct devices_deref_impl {
2286+
template <typename T> static device_impl &dereference(T &Elem) {
2287+
using Ty = std::decay_t<decltype(Elem)>;
2288+
if constexpr (std::is_same_v<Ty, device>) {
2289+
return *getSyclObjImpl(Elem);
2290+
} else if constexpr (std::is_same_v<Ty, device_impl>) {
2291+
return Elem;
2292+
} else {
2293+
return *Elem;
2294+
}
2295+
}
2296+
};
2297+
using devices_iterator =
2298+
variadic_iterator<devices_deref_impl,
2299+
std::vector<std::shared_ptr<device_impl>>::const_iterator,
2300+
std::vector<device>::const_iterator, device_impl *>;
2301+
2302+
class devices_range : public iterator_range<devices_iterator> {
2303+
private:
2304+
using Base = iterator_range<devices_iterator>;
2305+
2306+
public:
2307+
using Base::Base;
2308+
devices_range(const device &Dev)
2309+
: devices_range(&*getSyclObjImpl(Dev), (&*getSyclObjImpl(Dev) + 1), 1) {}
2310+
};
2311+
22842312
#ifndef __INTEL_PREVIEW_BREAKING_CHANGES
22852313
template <typename Param>
22862314
typename Param::return_type device_impl::get_info() const {

sycl/source/detail/graph/node_impl.hpp

Lines changed: 37 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010

1111
#include <detail/accessor_impl.hpp> // for AccessorImplHost
1212
#include <detail/cg.hpp> // for CGExecKernel, CGHostTask, ArgDesc...
13-
#include <detail/host_task.hpp> // for HostTask
14-
#include <sycl/detail/cg_types.hpp> // for CGType
13+
#include <detail/helpers.hpp>
14+
#include <detail/host_task.hpp> // for HostTask
15+
#include <sycl/detail/cg_types.hpp> // for CGType
1516
#include <sycl/detail/kernel_desc.hpp> // for kernel_param_kind_t
1617

1718
#include <cstring>
@@ -761,82 +762,43 @@ class node_impl : public std::enable_shared_from_this<node_impl> {
761762
}
762763
};
763764

764-
// Non-owning!
765-
class nodes_range {
766-
template <typename... Containers>
767-
using storage_iter_impl =
768-
std::variant<typename Containers::const_iterator...>;
769-
770-
using storage_iter = storage_iter_impl<
771-
std::vector<std::shared_ptr<node_impl>>, std::vector<node_impl *>,
772-
// Next one is temporary. It looks like `weak_ptr`s aren't
773-
// used for the actual lifetime management and the objects are
774-
// always guaranteed to be alive. Once the code is cleaned
775-
// from `weak_ptr`s this alternative should be removed too.
776-
std::vector<std::weak_ptr<node_impl>>,
777-
//
778-
std::set<std::shared_ptr<node_impl>>, std::set<node_impl *>,
779-
//
780-
std::list<node_impl *>>;
781-
782-
storage_iter Begin;
783-
storage_iter End;
784-
const size_t Size;
785-
786-
public:
787-
nodes_range(const nodes_range &Other) = default;
788-
789-
template <
790-
typename ContainerTy,
791-
typename = std::enable_if_t<!std::is_same_v<nodes_range, ContainerTy>>>
792-
nodes_range(ContainerTy &Container)
793-
: Begin{Container.begin()}, End{Container.end()}, Size{Container.size()} {
765+
struct nodes_deref_impl {
766+
template <typename T> static node_impl &dereference(T &Elem) {
767+
if constexpr (std::is_same_v<std::decay_t<decltype(Elem)>,
768+
std::weak_ptr<node_impl>>) {
769+
// This assumes that weak_ptr doesn't actually manage lifetime and
770+
// the object is guaranteed to be alive (which seems to be the
771+
// assumption across all graph code).
772+
return *Elem.lock();
773+
} else {
774+
return *Elem;
775+
}
794776
}
777+
};
795778

796-
class iterator {
797-
storage_iter It;
798-
799-
iterator(storage_iter It) : It(It) {}
800-
friend class nodes_range;
801-
802-
public:
803-
iterator &operator++() {
804-
It = std::visit(
805-
[](auto &&It) {
806-
++It;
807-
return storage_iter{It};
808-
},
809-
It);
810-
return *this;
811-
}
812-
bool operator!=(const iterator &Other) const { return It != Other.It; }
813-
814-
node_impl &operator*() {
815-
return std::visit(
816-
[](auto &&It) -> node_impl & {
817-
auto &Elem = *It;
818-
if constexpr (std::is_same_v<std::decay_t<decltype(Elem)>,
819-
std::weak_ptr<node_impl>>) {
820-
// This assumes that weak_ptr doesn't actually manage lifetime and
821-
// the object is guaranteed to be alive (which seems to be the
822-
// assumption across all graph code).
823-
return *Elem.lock();
824-
} else {
825-
return *Elem;
826-
}
827-
},
828-
It);
829-
}
830-
};
779+
template <typename... ContainerTy>
780+
using nodes_iterator_impl =
781+
variadic_iterator<nodes_deref_impl,
782+
typename ContainerTy::const_iterator...>;
783+
784+
using nodes_iterator = nodes_iterator_impl<
785+
std::vector<std::shared_ptr<node_impl>>, std::vector<node_impl *>,
786+
// Next one is temporary. It looks like `weak_ptr`s aren't
787+
// used for the actual lifetime management and the objects are
788+
// always guaranteed to be alive. Once the code is cleaned
789+
// from `weak_ptr`s this alternative should be removed too.
790+
std::vector<std::weak_ptr<node_impl>>,
791+
//
792+
std::set<std::shared_ptr<node_impl>>, std::set<node_impl *>,
793+
//
794+
std::list<node_impl *>>;
795+
796+
class nodes_range : public iterator_range<nodes_iterator> {
797+
private:
798+
using Base = iterator_range<nodes_iterator>;
831799

832-
iterator begin() const {
833-
return {std::visit([](auto &&It) { return storage_iter{It}; }, Begin)};
834-
}
835-
iterator end() const {
836-
return {std::visit([](auto &&It) { return storage_iter{It}; }, End)};
837-
}
838-
size_t size() const { return Size; }
839-
bool empty() const { return Size == 0; }
800+
public:
801+
using Base::Base;
840802
};
841803

842804
inline nodes_range node_impl::successors() const { return MSuccessors; }

sycl/source/detail/helpers.hpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#pragma once
10+
911
#include <sycl/detail/kernel_name_str_t.hpp>
1012

1113
#include <ur_api.h>
1214

1315
#include <memory>
1416
#include <tuple>
17+
#include <variant>
1518
#include <vector>
1619

1720
namespace sycl {
@@ -26,6 +29,63 @@ class RTDeviceBinaryImage;
2629
std::tuple<const RTDeviceBinaryImage *, ur_program_handle_t>
2730
retrieveKernelBinary(queue_impl &Queue, KernelNameStrRefT KernelName,
2831
CGExecKernel *CGKernel = nullptr);
32+
33+
template <typename DereferenceImpl, typename... Iterators>
34+
class variadic_iterator {
35+
using storage_iter = std::variant<Iterators...>;
36+
37+
storage_iter It;
38+
39+
public:
40+
template <typename IterTy>
41+
variadic_iterator(IterTy &&It) : It(std::forward<IterTy>(It)) {}
42+
43+
variadic_iterator &operator++() {
44+
It = std::visit(
45+
[](auto &&It) {
46+
++It;
47+
return storage_iter{It};
48+
},
49+
It);
50+
return *this;
51+
}
52+
bool operator!=(const variadic_iterator &Other) const {
53+
return It != Other.It;
54+
}
55+
56+
decltype(auto) operator*() {
57+
return std::visit(
58+
[](auto &&It) -> decltype(auto) {
59+
return DereferenceImpl::dereference(*It);
60+
},
61+
It);
62+
}
63+
};
64+
65+
// Non-owning!
66+
template <typename iterator> class iterator_range {
67+
public:
68+
iterator_range(const iterator_range &Other) = default;
69+
70+
template <typename IterTy>
71+
iterator_range(IterTy Begin, IterTy End, size_t Size)
72+
: Begin(Begin), End(End), Size(Size) {}
73+
74+
template <typename ContainerTy>
75+
iterator_range(const ContainerTy &Container)
76+
: iterator_range(Container.begin(), Container.end(), Container.size()) {}
77+
78+
iterator begin() const { return Begin; }
79+
iterator end() const { return End; }
80+
size_t size() const { return Size; }
81+
bool empty() const { return Size == 0; }
82+
decltype(auto) front() const { return *begin(); }
83+
84+
private:
85+
iterator Begin;
86+
iterator End;
87+
const size_t Size;
88+
};
2989
} // namespace detail
3090
} // namespace _V1
3191
} // namespace sycl

0 commit comments

Comments
 (0)