alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
BufGenericSyclTraits.hpp
Go to the documentation of this file.
1/* Copyright 2025 Jan Stephan, Luca Ferragina, Aurora Perego, Andrea Bocci, Anton Reinhard, Maria Michailidi
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
10
11#ifdef ALPAKA_ACC_SYCL_ENABLED
12
13namespace alpaka::trait
14{
15 //! The SYCL device memory buffer type trait specialization.
16 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
17 struct BufType<DevGenericSycl<TTag>, TElem, TDim, TIdx>
18 {
19 using type = BufGenericSycl<TElem, TDim, TIdx, TTag>;
20 };
21
22 //! The BufGenericSycl device type trait specialization.
23 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
24 struct DevType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
25 {
26 using type = DevGenericSycl<TTag>;
27 };
28
29 //! The BufGenericSycl device get trait specialization.
30 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
31 struct GetDev<BufGenericSycl<TElem, TDim, TIdx, TTag>>
32 {
33 ALPAKA_FN_HOST static auto getDev(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf) -> DevGenericSycl<TTag>
34 {
35 return buf.m_spBufImpl->m_dev;
36 }
37 };
38
39 //! The BufGenericSycl dimension getter trait.
40 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
41 struct DimType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
42 {
43 using type = TDim;
44 };
45
46 //! The BufGenericSycl memory element type get trait specialization.
47 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
48 struct ElemType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
49 {
50 using type = TElem;
51 };
52
53 //! The BufGenericSycl width get trait specialization.
54 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
55 struct GetExtents<BufGenericSycl<TElem, TDim, TIdx, TTag>>
56 {
57 ALPAKA_FN_HOST auto operator()(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf)
58 {
59 return buf.m_spBufImpl->m_extentElements;
60 }
61 };
62
63 //! The BufGenericSycl native pointer get trait specialization.
64 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
65 struct GetPtrNative<BufGenericSycl<TElem, TDim, TIdx, TTag>>
66 {
67 ALPAKA_FN_HOST static auto getPtrNative(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf) -> TElem const*
68 {
69 return buf.m_spBufImpl->m_pMem;
70 }
71
72 ALPAKA_FN_HOST static auto getPtrNative(BufGenericSycl<TElem, TDim, TIdx, TTag>& buf) -> TElem*
73 {
74 return buf.m_spBufImpl->m_pMem;
75 }
76 };
77
78 //! The BufGenericSycl pointer on device get trait specialization.
79 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
80 struct GetPtrDev<BufGenericSycl<TElem, TDim, TIdx, TTag>, DevGenericSycl<TTag>>
81 {
82 ALPAKA_FN_HOST static auto getPtrDev(
83 BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf,
84 DevGenericSycl<TTag> const& dev) -> TElem const*
85 {
86 if(dev == getDev(buf))
87 {
88 return buf.m_spBufImpl->m_pMem;
89 }
90 else
91 {
92 throw std::runtime_error("The buffer is not accessible from the given device!");
93 }
94 }
95
96 ALPAKA_FN_HOST static auto getPtrDev(
97 BufGenericSycl<TElem, TDim, TIdx, TTag>& buf,
98 DevGenericSycl<TTag> const& dev) -> TElem*
99 {
100 if(dev == getDev(buf))
101 {
102 return buf.m_spBufImpl->m_pMem;
103 }
104 else
105 {
106 throw std::runtime_error("The buffer is not accessible from the given device!");
107 }
108 }
109 };
110
111 //! The BufGenericSycl offset get trait specialization.
112 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
113 struct GetOffsets<BufGenericSycl<TElem, TDim, TIdx, TTag>>
114 {
115 ALPAKA_FN_HOST auto operator()(BufGenericSycl<TElem, TDim, TIdx, TTag> const& /*buf*/) const -> Vec<TDim, TIdx>
116 {
117 return Vec<TDim, TIdx>::zeros();
118 }
119 };
120
121 //! The BufGenericSycl idx type trait specialization.
122 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
123 struct IdxType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
124 {
125 using type = TIdx;
126 };
127
128 //! The MakeConstBuf trait for Sycl buffers.
129 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
130 struct MakeConstBuf<BufGenericSycl<TElem, TDim, TIdx, TTag>>
131 {
132 ALPAKA_FN_HOST static auto makeConstBuf(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf)
133 -> ConstBufGenericSycl<TElem, TDim, TIdx, TTag>
134 {
135 return ConstBufGenericSycl<TElem, TDim, TIdx, TTag>(buf);
136 }
137
138 ALPAKA_FN_HOST static auto makeConstBuf(BufGenericSycl<TElem, TDim, TIdx, TTag>&& buf)
139 -> ConstBufGenericSycl<TElem, TDim, TIdx, TTag>
140 {
141 return ConstBufGenericSycl<TElem, TDim, TIdx, TTag>(std::move(buf));
142 }
143 };
144
145 //! The SYCL memory allocation trait specialization.
146 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
147 struct BufAlloc<TElem, TDim, TIdx, DevGenericSycl<TTag>>
148 {
149 template<typename TExtent>
150 ALPAKA_FN_HOST static auto allocBuf(DevGenericSycl<TTag> const& dev, TExtent const& extent)
151 -> BufGenericSycl<TElem, TDim, TIdx, TTag>
152 {
154
155# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
156 if constexpr(TDim::value == 0)
157 std::cout << __func__ << " ewb: " << sizeof(TElem) << '\n';
158 else if constexpr(TDim::value == 1)
159 {
160 auto const width = getWidth(extent);
161
162 auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
163 std::cout << __func__ << " ew: " << width << " ewb: " << widthBytes << '\n';
164 }
165 else if constexpr(TDim::value == 2)
166 {
167 auto const width = getWidth(extent);
168 auto const height = getHeight(extent);
169
170 auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
171 std::cout << __func__ << " ew: " << width << " eh: " << height << " ewb: " << widthBytes
172 << " pitch: " << widthBytes << '\n';
173 }
174 else if constexpr(TDim::value == 3)
175 {
176 auto const width = getWidth(extent);
177 auto const height = getHeight(extent);
178 auto const depth = getDepth(extent);
179
180 auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
181 std::cout << __func__ << " ew: " << width << " eh: " << height << " ed: " << depth
182 << " ewb: " << widthBytes << " pitch: " << widthBytes << '\n';
183 }
184# endif
185
186 auto const& [nativeDev, nativeContext] = dev.getNativeHandle();
187 TElem* memPtr = sycl::malloc_device<TElem>(
188 static_cast<std::size_t>(getExtentProduct(extent)),
189 nativeDev,
190 nativeContext);
191 auto deleter = [ctx = nativeContext](TElem* ptr) { sycl::free(ptr, ctx); };
192
193 return BufGenericSycl<TElem, TDim, TIdx, TTag>(dev, memPtr, std::move(deleter), extent);
194 }
195 };
196
197 //! The SYCL caching memory allocation trait specialization.
198 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag, typename TAllocator>
199 struct BufAllocWithAllocator<TElem, TDim, TIdx, DevGenericSycl<TTag>, TAllocator>
200 {
201 template<typename TExtent>
202 ALPAKA_FN_HOST static auto allocBuf(
203 DevGenericSycl<TTag> const& dev,
204 TExtent const& extent,
205 TAllocator allocator) -> BufGenericSycl<TElem, TDim, TIdx, TTag>
206 {
208
209 std::size_t const bytes = static_cast<std::size_t>(getExtentProduct(extent)) * sizeof(TElem);
210 void* const memPtr = allocator.allocate(bytes, alignof(TElem));
211 auto deleter = [alloc = std::move(allocator)](TElem* ptr) mutable { alloc.deallocate(ptr); };
212 return BufGenericSycl<TElem, TDim, TIdx, TTag>(
213 dev,
214 static_cast<TElem*>(memPtr),
215 std::move(deleter),
216 extent);
217 }
218 };
219
220 //! The BufGenericSycl stream-ordered memory allocation capability trait specialization.
221 template<typename TDim, concepts::Tag TTag>
222 struct HasAsyncBufSupport<TDim, DevGenericSycl<TTag>> : std::true_type
223 {
224 };
225
226 //! The SYCL caching stream-ordered memory allocation trait specialization.
227 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag, typename TAllocator>
228 struct AsyncBufAllocWithAllocator<TElem, TDim, TIdx, DevGenericSycl<TTag>, TAllocator>
229 {
230 template<bool TBlocking, typename TExtent>
231 ALPAKA_FN_HOST static auto allocAsyncBuf(
232 alpaka::detail::QueueGenericSyclBase<TTag, TBlocking> queue,
233 TExtent const& extent,
234 TAllocator allocator) -> BufGenericSycl<TElem, TDim, TIdx, TTag>
235 {
237
238 auto const dev = getDev(queue);
239 std::size_t const bytes = static_cast<std::size_t>(getExtentProduct(extent)) * sizeof(TElem);
240 void* const memPtr = allocator.allocate(bytes, alignof(TElem));
241 auto deleter = [alloc = std::move(allocator)](TElem* ptr) mutable { alloc.deallocate(ptr); };
242 return BufGenericSycl<TElem, TDim, TIdx, TTag>(
243 dev,
244 static_cast<TElem*>(memPtr),
245 std::move(deleter),
246 extent);
247 }
248 };
249
250 //! The BufGenericSycl stream-ordered memory allocation trait specialization.
251 template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
252 struct AsyncBufAlloc<TElem, TDim, TIdx, DevGenericSycl<TTag>>
253 {
254 template<bool TBlocking, typename TExtent>
255 ALPAKA_FN_HOST static auto allocAsyncBuf(
256 alpaka::detail::QueueGenericSyclBase<TTag, TBlocking> queue,
257 TExtent const& extent) -> BufGenericSycl<TElem, TDim, TIdx, TTag>
258 {
260
261# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
262 if constexpr(TDim::value == 0)
263 std::cout << __func__ << " ewb: " << sizeof(TElem) << '\n';
264 else if constexpr(TDim::value == 1)
265 {
266 auto const width = getWidth(extent);
267
268 auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
269 std::cout << __func__ << " ew: " << width << " ewb: " << widthBytes << '\n';
270 }
271 else if constexpr(TDim::value == 2)
272 {
273 auto const width = getWidth(extent);
274 auto const height = getHeight(extent);
275
276 auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
277 std::cout << __func__ << " ew: " << width << " eh: " << height << " ewb: " << widthBytes
278 << " pitch: " << widthBytes << '\n';
279 }
280 else if constexpr(TDim::value == 3)
281 {
282 auto const width = getWidth(extent);
283 auto const height = getHeight(extent);
284 auto const depth = getDepth(extent);
285
286 auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
287 std::cout << __func__ << " ew: " << width << " eh: " << height << " ed: " << depth
288 << " ewb: " << widthBytes << " pitch: " << widthBytes << '\n';
289 }
290# endif
291
292 sycl::queue q = queue.getNativeHandle();
293 TElem* memPtr = sycl::malloc_device<TElem>(static_cast<std::size_t>(getExtentProduct(extent)), q);
294 auto deleter = [q](TElem* ptr) mutable
295 {
296 if constexpr(TBlocking)
297 {
298 // If the queue is blocking, all operations submitted when the buffer goes out of scope should
299 // always have completed. Free the memory immediately, and wait for the free operation to complete.
300 // From SYCL 4.8.3.6: Note: Whether free is blocking or non-blocking is unspecified. Applications
301 // should not rely on free for synchronization, nor assume that free cannot cause deadlocks.
302 sycl::free(ptr, q);
303 q.wait();
304 }
305 else
306 {
307 // If the queue is non-blocking, enqueue the free() operation in a host_task.
308 q.submit([&](sycl::handler& cgh) { //
309 cgh.host_task([=]() { sycl::free(ptr, q); });
310 });
311 }
312 };
313
314 return BufGenericSycl<TElem, TDim, TIdx, TTag>(getDev(queue), memPtr, std::move(deleter), extent);
315 }
316 };
317
318 //! The pinned/mapped memory allocation capability trait specialization.
319 template<concepts::Tag TTag>
320 struct HasMappedBufSupport<PlatformGenericSycl<TTag>> : public std::true_type
321 {
322 };
323
324 //! The pinned/mapped memory allocation trait specialization for the SYCL devices.
325 template<concepts::Tag TTag, typename TElem, typename TDim, typename TIdx>
326 struct BufAllocMapped<PlatformGenericSycl<TTag>, TElem, TDim, TIdx>
327 {
328 template<typename TExtent>
329 ALPAKA_FN_HOST static auto allocMappedBuf(
330 DevCpu const& host,
331 PlatformGenericSycl<TTag> const& platform,
332 TExtent const& extent) -> BufCpu<TElem, TDim, TIdx>
333 {
335
336 // Allocate SYCL page-locked memory on the host, mapped into the SYCL platform's address space and
337 // accessible to all devices in the SYCL platform.
338 auto ctx = platform.syclContext();
339 TElem* memPtr = sycl::malloc_host<TElem>(static_cast<std::size_t>(getExtentProduct(extent)), ctx);
340 auto deleter = [ctx](TElem* ptr) { sycl::free(ptr, ctx); };
341
342 return BufCpu<TElem, TDim, TIdx>(host, memPtr, std::move(deleter), extent);
343 }
344 };
345
346 //! The unified/managed memory allocation trait specialization for the SYCL devices.
347 template<concepts::Tag TTag, typename TElem, typename TDim, typename TIdx>
348 struct BufAllocManaged<PlatformGenericSycl<TTag>, TElem, TDim, TIdx>
349 {
350 template<typename TExtent>
352 DevCpu const& host,
353 PlatformGenericSycl<TTag> const& platform,
354 TExtent const& extent) -> BufCpu<TElem, TDim, TIdx>
355 {
357
358 // Allocate SYCL managed (unified) memory,
359 // accessible to all devices in the SYCL platform.
360 auto devices = platform.syclDevices();
361 auto dev = devices.front(); // sycl::device
362 auto ctx = platform.syclContext();
363 TElem* memPtr = sycl::malloc_shared<TElem>(static_cast<std::size_t>(getExtentProduct(extent)), dev, ctx);
364 auto deleter = [ctx](TElem* ptr) { sycl::free(ptr, ctx); };
365
366 return BufCpu<TElem, TDim, TIdx>(host, memPtr, std::move(deleter), extent);
367 }
368 };
369
370} // namespace alpaka::trait
371
372#endif
#define ALPAKA_DEBUG_MINIMAL_LOG_SCOPE
Definition Debug.hpp:55
ALPAKA_NO_HOST_ACC_WARNING static ALPAKA_FN_HOST_ACC constexpr auto zeros() -> Vec< TDim, TVal >
Zero value constructor.
Definition Vec.hpp:99
#define ALPAKA_FN_HOST
Definition Common.hpp:43
The accelerator traits.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getExtentProduct(T const &object) -> Idx< T >
Definition Traits.hpp:134
ALPAKA_FN_HOST auto allocManagedBuf(DevCpu const &host, TPlatform const &platform, TExtent const &extent=TExtent())
Allocates unified/managed memory, accessible by all devices in the given platform.
Definition Traits.hpp:276
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getHeight(TExtent const &extent=TExtent()) -> Idx< TExtent >
Definition Traits.hpp:108
ALPAKA_FN_HOST auto makeConstBuf(TBuf const &buf)
Creates a constant buffer from the given mutable buffer.
Definition Traits.hpp:332
ALPAKA_FN_HOST auto allocMappedBuf(DevCpu const &host, TPlatform const &platform, TExtent const &extent=TExtent())
Allocates pinned/mapped host memory, accessible by all devices in the given platform.
Definition Traits.hpp:256
ALPAKA_FN_HOST auto getPtrNative(TView const &view) -> Elem< TView > const *
Gets the native pointer of the memory view.
Definition Traits.hpp:177
ALPAKA_FN_HOST auto allocBuf(TDev const &dev, TExtent const &extent=TExtent())
Allocates memory on the given device.
Definition Traits.hpp:119
ALPAKA_FN_HOST auto getDev(T const &t)
Definition Traits.hpp:75
ALPAKA_FN_HOST auto getPtrDev(TView const &view, TDev const &dev) -> Elem< TView > const *
Gets the pointer to the view on the given device.
Definition Traits.hpp:198
ALPAKA_FN_HOST auto allocAsyncBuf(TQueue queue, TExtent const &extent=TExtent())
Allocates stream-ordered memory on the given device.
Definition Traits.hpp:157
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getDepth(TExtent const &extent=TExtent()) -> Idx< TExtent >
Definition Traits.hpp:121
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getWidth(TExtent const &extent=TExtent()) -> Idx< TExtent >
Definition Traits.hpp:95