Skip to content

Commit d357020

Browse files
author
Alexander Batashev
authored
[SYCL] Refactor memory objects to improve ABI stability (#1076)
This patch is a part of effort to decouple SYCL Runtime library interface from its actual implementation. The goal is to improve SYCL ABI/API compatibility between different versions of library. The following changes were applied to SYCLMemObjT, as well as buffer and image classes: Introduced a type-erased allocator. This allowed removal of templates for SYCLMemObjT, buffer_impl, and image_imp. sycl_mem_obj_t.hpp, image_impl.hpp, and buffer_impl.hpp were refactored to use public APIs only. All usages of private APIs were moved to cpp files. get_access member functions were moved from image_impl and buffer_impl to image and buffer accordingly, since they did not use any private APIs at all. Signed-off-by: Alexander Batashev <[email protected]>
1 parent 4df18fa commit d357020

File tree

12 files changed

+636
-519
lines changed

12 files changed

+636
-519
lines changed

sycl/include/CL/sycl/buffer.hpp

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -50,71 +50,81 @@ class buffer {
5050
buffer(const range<dimensions> &bufferRange,
5151
const property_list &propList = {})
5252
: Range(bufferRange) {
53-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
54-
get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)),
55-
propList);
53+
impl = std::make_shared<detail::buffer_impl>(
54+
get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)), propList,
55+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>());
5656
}
5757

5858
buffer(const range<dimensions> &bufferRange, AllocatorT allocator,
5959
const property_list &propList = {})
6060
: Range(bufferRange) {
61-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
61+
impl = std::make_shared<detail::buffer_impl>(
6262
get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)), propList,
63-
allocator);
63+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>(
64+
allocator));
6465
}
6566

6667
buffer(T *hostData, const range<dimensions> &bufferRange,
6768
const property_list &propList = {})
6869
: Range(bufferRange) {
69-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
70+
impl = std::make_shared<detail::buffer_impl>(
7071
hostData, get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)),
71-
propList);
72+
propList,
73+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>());
7274
}
7375

7476
buffer(T *hostData, const range<dimensions> &bufferRange,
7577
AllocatorT allocator, const property_list &propList = {})
7678
: Range(bufferRange) {
77-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
79+
impl = std::make_shared<detail::buffer_impl>(
7880
hostData, get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)),
79-
propList, allocator);
81+
propList,
82+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>(
83+
allocator));
8084
}
8185

8286
template <typename _T = T>
8387
buffer(EnableIfSameNonConstIterators<T, _T> const *hostData,
8488
const range<dimensions> &bufferRange,
8589
const property_list &propList = {})
8690
: Range(bufferRange) {
87-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
91+
impl = std::make_shared<detail::buffer_impl>(
8892
hostData, get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)),
89-
propList);
93+
propList,
94+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>());
9095
}
9196

9297
template <typename _T = T>
9398
buffer(EnableIfSameNonConstIterators<T, _T> const *hostData,
9499
const range<dimensions> &bufferRange, AllocatorT allocator,
95100
const property_list &propList = {})
96101
: Range(bufferRange) {
97-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
102+
impl = std::make_shared<detail::buffer_impl>(
98103
hostData, get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)),
99-
propList, allocator);
104+
propList,
105+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>(
106+
allocator));
100107
}
101108

102109
buffer(const shared_ptr_class<T> &hostData,
103110
const range<dimensions> &bufferRange, AllocatorT allocator,
104111
const property_list &propList = {})
105112
: Range(bufferRange) {
106-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
113+
impl = std::make_shared<detail::buffer_impl>(
107114
hostData, get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)),
108-
propList, allocator);
115+
propList,
116+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>(
117+
allocator));
109118
}
110119

111120
buffer(const shared_ptr_class<T> &hostData,
112121
const range<dimensions> &bufferRange,
113122
const property_list &propList = {})
114123
: Range(bufferRange) {
115-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
124+
impl = std::make_shared<detail::buffer_impl>(
116125
hostData, get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)),
117-
propList);
126+
propList,
127+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>());
118128
}
119129

120130
template <class InputIterator, int N = dimensions,
@@ -123,9 +133,11 @@ class buffer {
123133
buffer(InputIterator first, InputIterator last, AllocatorT allocator,
124134
const property_list &propList = {})
125135
: Range(range<1>(std::distance(first, last))) {
126-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
136+
impl = std::make_shared<detail::buffer_impl>(
127137
first, last, get_count() * sizeof(T),
128-
detail::getNextPowerOfTwo(sizeof(T)), propList, allocator);
138+
detail::getNextPowerOfTwo(sizeof(T)), propList,
139+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>(
140+
allocator));
129141
}
130142

131143
template <class InputIterator, int N = dimensions,
@@ -134,9 +146,10 @@ class buffer {
134146
buffer(InputIterator first, InputIterator last,
135147
const property_list &propList = {})
136148
: Range(range<1>(std::distance(first, last))) {
137-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
149+
impl = std::make_shared<detail::buffer_impl>(
138150
first, last, get_count() * sizeof(T),
139-
detail::getNextPowerOfTwo(sizeof(T)), propList);
151+
detail::getNextPowerOfTwo(sizeof(T)), propList,
152+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>());
140153
}
141154

142155
// This constructor is a prototype for a future SYCL specification
@@ -146,10 +159,11 @@ class buffer {
146159
buffer(Container &container, AllocatorT allocator,
147160
const property_list &propList = {})
148161
: Range(range<1>(container.size())) {
149-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
162+
impl = std::make_shared<detail::buffer_impl>(
150163
container.data(), container.data() + container.size(),
151164
get_count() * sizeof(T), detail::getNextPowerOfTwo(sizeof(T)), propList,
152-
allocator);
165+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>(
166+
allocator));
153167
}
154168

155169
// This constructor is a prototype for a future SYCL specification
@@ -185,8 +199,10 @@ class buffer {
185199
CL_MEM_SIZE, sizeof(size_t), &BufSize, nullptr);
186200

187201
Range[0] = BufSize / sizeof(T);
188-
impl = std::make_shared<detail::buffer_impl<AllocatorT>>(
189-
MemObject, SyclContext, BufSize, AvailableEvent);
202+
impl = std::make_shared<detail::buffer_impl>(
203+
MemObject, SyclContext, BufSize,
204+
make_unique_ptr<detail::SYCLMemObjAllocatorHolder<AllocatorT>>(),
205+
AvailableEvent);
190206
}
191207

192208
buffer(const buffer &rhs) = default;
@@ -213,38 +229,42 @@ class buffer {
213229

214230
size_t get_size() const { return get_count() * sizeof(T); }
215231

216-
AllocatorT get_allocator() const { return impl->get_allocator(); }
232+
AllocatorT get_allocator() const {
233+
return impl->template get_allocator<AllocatorT>();
234+
}
217235

218-
template <access::mode mode,
219-
access::target target = access::target::global_buffer>
220-
accessor<T, dimensions, mode, target, access::placeholder::false_t>
221-
get_access(handler &commandGroupHandler) {
222-
return impl->template get_access<T, dimensions, mode, target>(
223-
*this, commandGroupHandler);
236+
template <access::mode Mode,
237+
access::target Target = access::target::global_buffer>
238+
accessor<T, dimensions, Mode, Target, access::placeholder::false_t>
239+
get_access(handler &CommandGroupHandler) {
240+
return accessor<T, dimensions, Mode, Target, access::placeholder::false_t>(
241+
*this, CommandGroupHandler);
224242
}
225243

226244
template <access::mode mode>
227245
accessor<T, dimensions, mode, access::target::host_buffer,
228246
access::placeholder::false_t>
229247
get_access() {
230-
return impl->template get_access<T, dimensions, mode>(*this);
248+
return accessor<T, dimensions, mode, access::target::host_buffer,
249+
access::placeholder::false_t>(*this);
231250
}
232251

233252
template <access::mode mode,
234253
access::target target = access::target::global_buffer>
235254
accessor<T, dimensions, mode, target, access::placeholder::false_t>
236255
get_access(handler &commandGroupHandler, range<dimensions> accessRange,
237256
id<dimensions> accessOffset = {}) {
238-
return impl->template get_access<T, dimensions, mode, target>(
257+
return accessor<T, dimensions, mode, target, access::placeholder::false_t>(
239258
*this, commandGroupHandler, accessRange, accessOffset);
240259
}
241260

242261
template <access::mode mode>
243262
accessor<T, dimensions, mode, access::target::host_buffer,
244263
access::placeholder::false_t>
245264
get_access(range<dimensions> accessRange, id<dimensions> accessOffset = {}) {
246-
return impl->template get_access<T, dimensions, mode>(*this, accessRange,
247-
accessOffset);
265+
return accessor<T, dimensions, mode, access::target::host_buffer,
266+
access::placeholder::false_t>(*this, accessRange,
267+
accessOffset);
248268
}
249269

250270
template <typename Destination = std::nullptr_t>
@@ -278,7 +298,7 @@ class buffer {
278298
}
279299

280300
private:
281-
shared_ptr_class<detail::buffer_impl<AllocatorT>> impl;
301+
shared_ptr_class<detail::buffer_impl> impl;
282302
template <class Obj>
283303
friend decltype(Obj::impl) detail::getSyclObjImpl(const Obj &SyclObject);
284304
template <typename A, int dims, typename C> friend class buffer;
@@ -292,7 +312,7 @@ class buffer {
292312
bool IsSubBuffer = false;
293313

294314
// Reinterpret contructor
295-
buffer(shared_ptr_class<detail::buffer_impl<AllocatorT>> Impl,
315+
buffer(shared_ptr_class<detail::buffer_impl> Impl,
296316
range<dimensions> reinterpretRange, size_t reinterpretOffset,
297317
bool isSubBuffer)
298318
: impl(Impl), Range(reinterpretRange), OffsetInBytes(reinterpretOffset),
@@ -381,7 +401,7 @@ template <typename T, int dimensions, typename AllocatorT>
381401
struct hash<cl::sycl::buffer<T, dimensions, AllocatorT>> {
382402
size_t
383403
operator()(const cl::sycl::buffer<T, dimensions, AllocatorT> &b) const {
384-
return hash<std::shared_ptr<cl::sycl::detail::buffer_impl<AllocatorT>>>()(
404+
return hash<std::shared_ptr<cl::sycl::detail::buffer_impl>>()(
385405
cl::sycl::detail::getSyclObjImpl(b));
386406
}
387407
};

sycl/include/CL/sycl/detail/buffer_impl.hpp

Lines changed: 25 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,8 @@
1111
#include <CL/cl.h>
1212
#include <CL/sycl/access/access.hpp>
1313
#include <CL/sycl/context.hpp>
14-
#include <CL/sycl/detail/context_impl.hpp>
15-
#include <CL/sycl/detail/aligned_allocator.hpp>
1614
#include <CL/sycl/detail/common.hpp>
1715
#include <CL/sycl/detail/helpers.hpp>
18-
#include <CL/sycl/detail/memory_manager.hpp>
19-
#include <CL/sycl/detail/pi.hpp>
20-
#include <CL/sycl/detail/scheduler/scheduler.hpp>
2116
#include <CL/sycl/detail/sycl_mem_obj_t.hpp>
2217
#include <CL/sycl/handler.hpp>
2318
#include <CL/sycl/property_list.hpp>
@@ -42,33 +37,35 @@ using buffer_allocator = detail::sycl_memory_object_allocator;
4237

4338
namespace detail {
4439

45-
template <typename AllocatorT>
46-
class buffer_impl final : public SYCLMemObjT<AllocatorT> {
47-
using BaseT = SYCLMemObjT<AllocatorT>;
40+
class buffer_impl final : public SYCLMemObjT {
41+
using BaseT = SYCLMemObjT;
4842
using typename BaseT::MemObjType;
4943

5044
public:
5145
buffer_impl(size_t SizeInBytes, size_t RequiredAlign,
52-
const property_list &Props, AllocatorT Allocator = AllocatorT())
53-
: BaseT(SizeInBytes, Props, Allocator) {}
46+
const property_list &Props,
47+
unique_ptr_class<SYCLMemObjAllocator> Allocator)
48+
: BaseT(SizeInBytes, Props, std::move(Allocator)) {}
5449

5550
buffer_impl(void *HostData, size_t SizeInBytes, size_t RequiredAlign,
56-
const property_list &Props, AllocatorT Allocator = AllocatorT())
57-
: BaseT(SizeInBytes, Props, Allocator) {
51+
const property_list &Props,
52+
unique_ptr_class<SYCLMemObjAllocator> Allocator)
53+
: BaseT(SizeInBytes, Props, std::move(Allocator)) {
5854
BaseT::handleHostData(HostData, RequiredAlign);
5955
}
6056

6157
buffer_impl(const void *HostData, size_t SizeInBytes, size_t RequiredAlign,
62-
const property_list &Props, AllocatorT Allocator = AllocatorT())
63-
: BaseT(SizeInBytes, Props, Allocator) {
58+
const property_list &Props,
59+
unique_ptr_class<SYCLMemObjAllocator> Allocator)
60+
: BaseT(SizeInBytes, Props, std::move(Allocator)) {
6461
BaseT::handleHostData(HostData, RequiredAlign);
6562
}
6663

6764
template <typename T>
6865
buffer_impl(const shared_ptr_class<T> &HostData, const size_t SizeInBytes,
6966
size_t RequiredAlign, const property_list &Props,
70-
AllocatorT Allocator = AllocatorT())
71-
: BaseT(SizeInBytes, Props, Allocator) {
67+
unique_ptr_class<SYCLMemObjAllocator> Allocator)
68+
: BaseT(SizeInBytes, Props, std::move(Allocator)) {
7269
BaseT::handleHostData(HostData, RequiredAlign);
7370
}
7471

@@ -79,8 +76,9 @@ class buffer_impl final : public SYCLMemObjT<AllocatorT> {
7976
template <class InputIterator>
8077
buffer_impl(EnableIfNotConstIterator<InputIterator> First, InputIterator Last,
8178
const size_t SizeInBytes, size_t RequiredAlign,
82-
const property_list &Props, AllocatorT Allocator = AllocatorT())
83-
: BaseT(SizeInBytes, Props, Allocator) {
79+
const property_list &Props,
80+
unique_ptr_class<SYCLMemObjAllocator> Allocator)
81+
: BaseT(SizeInBytes, Props, std::move(Allocator)) {
8482
BaseT::handleHostData(First, Last, RequiredAlign);
8583
// TODO: There is contradiction in the spec, in one place it says
8684
// the data is not copied back at all if the buffer is construted
@@ -97,70 +95,21 @@ class buffer_impl final : public SYCLMemObjT<AllocatorT> {
9795
template <class InputIterator>
9896
buffer_impl(EnableIfConstIterator<InputIterator> First, InputIterator Last,
9997
const size_t SizeInBytes, size_t RequiredAlign,
100-
const property_list &Props, AllocatorT Allocator = AllocatorT())
101-
: BaseT(SizeInBytes, Props, Allocator) {
98+
const property_list &Props,
99+
unique_ptr_class<SYCLMemObjAllocator> Allocator)
100+
: BaseT(SizeInBytes, Props, std::move(Allocator)) {
102101
BaseT::handleHostData(First, Last, RequiredAlign);
103102
}
104103

105104
buffer_impl(cl_mem MemObject, const context &SyclContext,
106-
const size_t SizeInBytes, event AvailableEvent = {})
107-
: BaseT(MemObject, SyclContext, SizeInBytes, std::move(AvailableEvent)) {}
108-
109-
template <typename T, int Dimensions, access::mode Mode,
110-
access::target Target = access::target::global_buffer>
111-
accessor<T, Dimensions, Mode, Target, access::placeholder::false_t>
112-
get_access(buffer<T, Dimensions, AllocatorT> &Buffer,
113-
handler &CommandGroupHandler) {
114-
return accessor<T, Dimensions, Mode, Target, access::placeholder::false_t>(
115-
Buffer, CommandGroupHandler);
116-
}
117-
118-
template <typename T, int Dimensions, access::mode Mode>
119-
accessor<T, Dimensions, Mode, access::target::host_buffer,
120-
access::placeholder::false_t>
121-
get_access(buffer<T, Dimensions, AllocatorT> &Buffer) {
122-
return accessor<T, Dimensions, Mode, access::target::host_buffer,
123-
access::placeholder::false_t>(Buffer);
124-
}
125-
126-
template <typename T, int dimensions, access::mode mode,
127-
access::target target = access::target::global_buffer>
128-
accessor<T, dimensions, mode, target, access::placeholder::false_t>
129-
get_access(buffer<T, dimensions, AllocatorT> &Buffer,
130-
handler &commandGroupHandler, range<dimensions> accessRange,
131-
id<dimensions> accessOffset) {
132-
return accessor<T, dimensions, mode, target, access::placeholder::false_t>(
133-
Buffer, commandGroupHandler, accessRange, accessOffset);
134-
}
135-
136-
template <typename T, int dimensions, access::mode mode>
137-
accessor<T, dimensions, mode, access::target::host_buffer,
138-
access::placeholder::false_t>
139-
get_access(buffer<T, dimensions, AllocatorT> &Buffer,
140-
range<dimensions> accessRange, id<dimensions> accessOffset) {
141-
return accessor<T, dimensions, mode, access::target::host_buffer,
142-
access::placeholder::false_t>(Buffer, accessRange,
143-
accessOffset);
144-
}
105+
const size_t SizeInBytes,
106+
unique_ptr_class<SYCLMemObjAllocator> Allocator,
107+
event AvailableEvent)
108+
: BaseT(MemObject, SyclContext, SizeInBytes, std::move(AvailableEvent),
109+
std::move(Allocator)) {}
145110

146111
void *allocateMem(ContextImplPtr Context, bool InitFromUserData,
147-
void *HostPtr, RT::PiEvent &OutEventToWait) override {
148-
149-
assert(!(InitFromUserData && HostPtr) &&
150-
"Cannot init from user data and reuse host ptr provided "
151-
"simultaneously");
152-
153-
void *UserPtr = InitFromUserData ? BaseT::getUserPtr() : HostPtr;
154-
155-
assert(!(nullptr == UserPtr && BaseT::useHostPtr() && Context->is_host()) &&
156-
"Internal error. Allocating memory on the host "
157-
"while having use_host_ptr property");
158-
159-
return MemoryManager::allocateMemBuffer(
160-
std::move(Context), this, UserPtr, BaseT::MHostPtrReadOnly,
161-
BaseT::getSize(), BaseT::MInteropEvent, BaseT::MInteropContext,
162-
OutEventToWait);
163-
}
112+
void *HostPtr, RT::PiEvent &OutEventToWait) override;
164113

165114
MemObjType getType() const override { return MemObjType::BUFFER; }
166115

0 commit comments

Comments
 (0)