Orrery
A GPU-accelerated N-body gravitational simulator
Loading...
Searching...
No Matches
sycl_usm.hpp
Go to the documentation of this file.
1#pragma once
2
42
43#ifdef ORRERY_ENABLE_SYCL
44
45# include <cstddef>
46# include <cstdint>
47# include <new>
48# include <span>
49# include <utility>
50
51# include <sycl/sycl.hpp>
52
53namespace orrery::backend {
54
60enum class UsmKind : std::uint8_t {
64
67
70
73};
74
75[[nodiscard]] constexpr const char* to_string(UsmKind kind) noexcept {
76 switch (kind) {
77 case UsmKind::kHost:
78 return "host";
79 case UsmKind::kDevice:
80 return "device";
81 case UsmKind::kShared:
82 return "shared";
83 case UsmKind::kUnknown:
84 break;
85 }
86 return "unknown";
87}
88
93[[nodiscard]] UsmKind allocation_kind(const void* pointer, const sycl::queue& queue) noexcept;
94
107template<typename T> class UsmArray {
108public:
110 UsmArray() noexcept = default;
111
117 UsmArray(sycl::queue& queue, std::size_t count)
118 : queue_(&queue),
119 size_(count),
120 data_(count == 0 ? nullptr
121 : sycl::aligned_alloc_shared<T>(kAlignmentBytes, count, queue)) {
122 if (count != 0 && data_ == nullptr) {
123 throw std::bad_alloc{};
124 }
125 }
126
127 ~UsmArray() { release(); }
128
129 UsmArray(const UsmArray&) = delete;
130 UsmArray& operator=(const UsmArray&) = delete;
131
132 UsmArray(UsmArray&& other) noexcept
133 : queue_(std::exchange(other.queue_, nullptr)),
134 size_(std::exchange(other.size_, 0)),
135 data_(std::exchange(other.data_, nullptr)) {}
136
137 UsmArray& operator=(UsmArray&& other) noexcept {
138 if (this != &other) {
139 release();
140 queue_ = std::exchange(other.queue_, nullptr);
141 size_ = std::exchange(other.size_, 0);
142 data_ = std::exchange(other.data_, nullptr);
143 }
144 return *this;
145 }
146
151 [[nodiscard]] T* data() const noexcept { return data_; }
152
153 [[nodiscard]] std::size_t size() const noexcept { return size_; }
154
155 [[nodiscard]] bool empty() const noexcept { return size_ == 0; }
156
157 [[nodiscard]] std::span<T> span() const noexcept { return {data_, size_}; }
158
159private:
162 static constexpr std::size_t kAlignmentBytes = 64;
163
164 void release() noexcept {
165 if (data_ != nullptr && queue_ != nullptr) {
166 sycl::free(data_, *queue_);
167 }
168 data_ = nullptr;
169 size_ = 0;
170 queue_ = nullptr;
171 }
172
175 sycl::queue* queue_{nullptr};
176 std::size_t size_{0};
177 T* data_{nullptr};
178};
179
180} // namespace orrery::backend
181
182#endif // ORRERY_ENABLE_SYCL
An owning, movable, cache-line-aligned shared USM allocation.
Definition sycl_usm.hpp:107
T * data() const noexcept
The pointer, valid in host code and in device code alike.
Definition sycl_usm.hpp:151
UsmArray() noexcept=default
An empty array, owning nothing.
@ kUnknown
The platform does not distinguish, or the machine is homogeneous.
Definition cpu_topology.hpp:49
UsmKind
Which kind of USM allocation a pointer is, as the runtime sees it.
Definition sycl_usm.hpp:60
@ kDevice
Device memory, not host-addressable.
Definition sycl_usm.hpp:69
@ kShared
Addressable from both. What this backend allocates.
Definition sycl_usm.hpp:72
@ kHost
Host memory, device-addressable.
Definition sycl_usm.hpp:66
UsmKind allocation_kind(const void *pointer, const sycl::queue &queue) noexcept
What the runtime reports pointer to be, in queue's context.