alpaka
Abstraction Library for Parallel Kernel Acceleration
BufGenericSycl.hpp
Go to the documentation of this file.
1 /* Copyright 2024 Jan Stephan, Luca Ferragina, Aurora Perego, Andrea Bocci
2  * SPDX-License-Identifier: MPL-2.0
3  */
4 
5 #pragma once
6 
7 #include "alpaka/core/Sycl.hpp"
9 #include "alpaka/dev/Traits.hpp"
11 #include "alpaka/dim/Traits.hpp"
15 #include "alpaka/vec/Vec.hpp"
16 
17 #include <memory>
18 #include <type_traits>
19 
20 #ifdef ALPAKA_ACC_SYCL_ENABLED
21 
22 # include <sycl/sycl.hpp>
23 
24 namespace alpaka
25 {
26  //! The SYCL memory buffer.
27  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
28  class BufGenericSycl : public internal::ViewAccessOps<BufGenericSycl<TElem, TDim, TIdx, TTag>>
29  {
30  public:
31  static_assert(
32  !std::is_const_v<TElem>,
33  "The elem type of the buffer can not be const because the C++ Standard forbids containers of const "
34  "elements!");
35  static_assert(!std::is_const_v<TIdx>, "The idx type of the buffer can not be const!");
36 
37  //! Constructor
38  template<typename TExtent, typename Deleter>
39  BufGenericSycl(DevGenericSycl<TTag> const& dev, TElem* const pMem, Deleter deleter, TExtent const& extent)
40  : m_dev{dev}
41  , m_extentElements{getExtentVecEnd<TDim>(extent)}
42  , m_spMem(pMem, std::move(deleter))
43  {
45 
46  static_assert(
47  TDim::value == Dim<TExtent>::value,
48  "The dimensionality of TExtent and the dimensionality of the TDim template parameter have to be "
49  "identical!");
50 
51  static_assert(
52  std::is_same_v<TIdx, Idx<TExtent>>,
53  "The idx type of TExtent and the TIdx template parameter have to be identical!");
54  }
55 
56  DevGenericSycl<TTag> m_dev;
57  Vec<TDim, TIdx> m_extentElements;
58  std::shared_ptr<TElem> m_spMem;
59  };
60 } // namespace alpaka
61 
62 namespace alpaka::trait
63 {
64  //! The BufGenericSycl device type trait specialization.
65  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
66  struct DevType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
67  {
68  using type = DevGenericSycl<TTag>;
69  };
70 
71  //! The BufGenericSycl device get trait specialization.
72  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
73  struct GetDev<BufGenericSycl<TElem, TDim, TIdx, TTag>>
74  {
75  static auto getDev(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf)
76  {
77  return buf.m_dev;
78  }
79  };
80 
81  //! The BufGenericSycl dimension getter trait specialization.
82  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
83  struct DimType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
84  {
85  using type = TDim;
86  };
87 
88  //! The BufGenericSycl memory element type get trait specialization.
89  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
90  struct ElemType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
91  {
92  using type = TElem;
93  };
94 
95  //! The BufGenericSycl extent get trait specialization.
96  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
97  struct GetExtents<BufGenericSycl<TElem, TDim, TIdx, TTag>>
98  {
99  auto operator()(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf) const
100  {
101  return buf.m_extentElements;
102  }
103  };
104 
105  //! The BufGenericSycl native pointer get trait specialization.
106  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
107  struct GetPtrNative<BufGenericSycl<TElem, TDim, TIdx, TTag>>
108  {
109  static auto getPtrNative(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf) -> TElem const*
110  {
111  return buf.m_spMem.get();
112  }
113 
114  static auto getPtrNative(BufGenericSycl<TElem, TDim, TIdx, TTag>& buf) -> TElem*
115  {
116  return buf.m_spMem.get();
117  }
118  };
119 
120  //! The BufGenericSycl pointer on device get trait specialization.
121  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
122  struct GetPtrDev<BufGenericSycl<TElem, TDim, TIdx, TTag>, DevGenericSycl<TTag>>
123  {
124  static auto getPtrDev(BufGenericSycl<TElem, TDim, TIdx, TTag> const& buf, DevGenericSycl<TTag> const& dev)
125  -> TElem const*
126  {
127  if(dev == getDev(buf))
128  {
129  return buf.m_spMem.get();
130  }
131  else
132  {
133  throw std::runtime_error("The buffer is not accessible from the given device!");
134  }
135  }
136 
137  static auto getPtrDev(BufGenericSycl<TElem, TDim, TIdx, TTag>& buf, DevGenericSycl<TTag> const& dev) -> TElem*
138  {
139  if(dev == getDev(buf))
140  {
141  return buf.m_spMem.get();
142  }
143  else
144  {
145  throw std::runtime_error("The buffer is not accessible from the given device!");
146  }
147  }
148  };
149 
150  //! The SYCL memory allocation trait specialization.
151  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
152  struct BufAlloc<TElem, TDim, TIdx, DevGenericSycl<TTag>>
153  {
154  template<typename TExtent>
155  static auto allocBuf(DevGenericSycl<TTag> const& dev, TExtent const& extent)
156  -> BufGenericSycl<TElem, TDim, TIdx, TTag>
157  {
159 
160 # if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
161  if constexpr(TDim::value == 0)
162  std::cout << __func__ << " ewb: " << sizeof(TElem) << '\n';
163  else if constexpr(TDim::value == 1)
164  {
165  auto const width = getWidth(extent);
166 
167  auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
168  std::cout << __func__ << " ew: " << width << " ewb: " << widthBytes << '\n';
169  }
170  else if constexpr(TDim::value == 2)
171  {
172  auto const width = getWidth(extent);
173  auto const height = getHeight(extent);
174 
175  auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
176  std::cout << __func__ << " ew: " << width << " eh: " << height << " ewb: " << widthBytes
177  << " pitch: " << widthBytes << '\n';
178  }
179  else if constexpr(TDim::value == 3)
180  {
181  auto const width = getWidth(extent);
182  auto const height = getHeight(extent);
183  auto const depth = getDepth(extent);
184 
185  auto const widthBytes = width * static_cast<TIdx>(sizeof(TElem));
186  std::cout << __func__ << " ew: " << width << " eh: " << height << " ed: " << depth
187  << " ewb: " << widthBytes << " pitch: " << widthBytes << '\n';
188  }
189 # endif
190 
191  auto const& [nativeDev, nativeContext] = dev.getNativeHandle();
192  TElem* memPtr = sycl::malloc_device<TElem>(
193  static_cast<std::size_t>(getExtentProduct(extent)),
194  nativeDev,
195  nativeContext);
196  auto deleter = [ctx = nativeContext](TElem* ptr) { sycl::free(ptr, ctx); };
197 
198  return BufGenericSycl<TElem, TDim, TIdx, TTag>(dev, memPtr, std::move(deleter), extent);
199  }
200  };
201 
202  //! The BufGenericSycl stream-ordered memory allocation capability trait specialization.
203  template<typename TDim, concepts::Tag TTag>
204  struct HasAsyncBufSupport<TDim, DevGenericSycl<TTag>> : std::false_type
205  {
206  };
207 
208  //! The BufGenericSycl offset get trait specialization.
209  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
210  struct GetOffsets<BufGenericSycl<TElem, TDim, TIdx, TTag>>
211  {
212  auto operator()(BufGenericSycl<TElem, TDim, TIdx, TTag> const&) const -> Vec<TDim, TIdx>
213  {
214  return Vec<TDim, TIdx>::zeros();
215  }
216  };
217 
218  //! The pinned/mapped memory allocation trait specialization for the SYCL devices.
219  template<concepts::Tag TTag, typename TElem, typename TDim, typename TIdx>
220  struct BufAllocMapped<PlatformGenericSycl<TTag>, TElem, TDim, TIdx>
221  {
222  template<typename TExtent>
223  static auto allocMappedBuf(
224  DevCpu const& host,
225  PlatformGenericSycl<TTag> const& platform,
226  TExtent const& extent) -> BufCpu<TElem, TDim, TIdx>
227  {
229 
230  // Allocate SYCL page-locked memory on the host, mapped into the SYCL platform's address space and
231  // accessible to all devices in the SYCL platform.
232  auto ctx = platform.syclContext();
233  TElem* memPtr = sycl::malloc_host<TElem>(static_cast<std::size_t>(getExtentProduct(extent)), ctx);
234  auto deleter = [ctx](TElem* ptr) { sycl::free(ptr, ctx); };
235 
236  return BufCpu<TElem, TDim, TIdx>(host, memPtr, std::move(deleter), extent);
237  }
238  };
239 
240  //! The pinned/mapped memory allocation capability trait specialization.
241  template<concepts::Tag TTag>
242  struct HasMappedBufSupport<PlatformGenericSycl<TTag>> : public std::true_type
243  {
244  };
245 
246  //! The BufGenericSycl idx type trait specialization.
247  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
248  struct IdxType<BufGenericSycl<TElem, TDim, TIdx, TTag>>
249  {
250  using type = TIdx;
251  };
252 
253  //! The BufCpu pointer on SYCL device get trait specialization.
254  template<typename TElem, typename TDim, typename TIdx, concepts::Tag TTag>
255  struct GetPtrDev<BufCpu<TElem, TDim, TIdx>, DevGenericSycl<TTag>>
256  {
257  static auto getPtrDev(BufCpu<TElem, TDim, TIdx> const& buf, DevGenericSycl<TTag> const&) -> TElem const*
258  {
259  return getPtrNative(buf);
260  }
261 
262  static auto getPtrDev(BufCpu<TElem, TDim, TIdx>& buf, DevGenericSycl<TTag> const&) -> TElem*
263  {
264  return getPtrNative(buf);
265  }
266  };
267 } // namespace alpaka::trait
268 
270 # include "alpaka/mem/buf/sycl/Set.hpp"
271 
272 #endif
#define ALPAKA_DEBUG_MINIMAL_LOG_SCOPE
Definition: Debug.hpp:55
ALPAKA_NO_HOST_ACC_WARNING static constexpr ALPAKA_FN_HOST_ACC auto zeros() -> Vec< TDim, TVal >
Zero value constructor.
Definition: Vec.hpp:126
The accelerator traits.
The alpaka accelerator library.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getExtentProduct(T const &object) -> Idx< T >
Definition: Traits.hpp:134
ALPAKA_FN_HOST auto free(TAlloc const &alloc, T const *const ptr) -> void
Frees the memory identified by the given pointer.
Definition: Traits.hpp:41
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 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:138
ALPAKA_FN_HOST auto getPtrNative(TView const &view) -> Elem< TView > const *
Gets the native pointer of the memory view.
Definition: Traits.hpp:136
ALPAKA_FN_HOST auto allocBuf(TDev const &dev, TExtent const &extent=TExtent())
Allocates memory on the given device.
Definition: Traits.hpp:64
ALPAKA_FN_HOST auto getDev(T const &t)
Definition: Traits.hpp:68
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: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
ALPAKA_NO_HOST_ACC_WARNING constexpr ALPAKA_FN_HOST_ACC auto getExtentVecEnd(T const &object={}) -> Vec< TDim, Idx< T >>
Definition: Traits.hpp:78