DPC++ Runtime
Runtime libraries for oneAPI Data Parallel C++
usm_impl.cpp
Go to the documentation of this file.
1 //==---------------- usm_impl.cpp - USM API Utils -------------*- C++ -*---==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 // ===--------------------------------------------------------------------=== //
8 
9 #include <CL/sycl/context.hpp>
12 #include <CL/sycl/detail/pi.hpp>
13 #include <CL/sycl/device.hpp>
14 #include <CL/sycl/usm.hpp>
15 #include <detail/queue_impl.hpp>
16 
17 #include <cstdlib>
18 
20 namespace sycl {
21 
23 
24 namespace detail {
25 namespace usm {
26 
27 void *alignedAllocHost(size_t Alignment, size_t Size, const context &Ctxt,
28  alloc Kind) {
29  void *RetVal = nullptr;
30  if (Size == 0)
31  return nullptr;
32  if (Ctxt.is_host()) {
33  if (!Alignment) {
34  // worst case default
35  Alignment = 128;
36  }
37 
38  aligned_allocator<char> Alloc(Alignment);
39  try {
40  RetVal = Alloc.allocate(Size);
41  } catch (const std::bad_alloc &) {
42  // Conform with Specification behavior
43  RetVal = nullptr;
44  }
45  } else {
46  std::shared_ptr<context_impl> CtxImpl = detail::getSyclObjImpl(Ctxt);
47  pi_context C = CtxImpl->getHandleRef();
48  const detail::plugin &Plugin = CtxImpl->getPlugin();
49  pi_result Error;
50 
51  switch (Kind) {
52  case alloc::host: {
54  &RetVal, C, nullptr, Size, Alignment);
55  break;
56  }
57  case alloc::device:
58  case alloc::shared:
59  case alloc::unknown: {
60  RetVal = nullptr;
61  Error = PI_INVALID_VALUE;
62  break;
63  }
64  }
65 
66  // Error is for debugging purposes.
67  // The spec wants a nullptr returned, not an exception.
68  if (Error != PI_SUCCESS)
69  return nullptr;
70  }
71  return RetVal;
72 }
73 
74 void *alignedAlloc(size_t Alignment, size_t Size, const context &Ctxt,
75  const device &Dev, alloc Kind) {
76  void *RetVal = nullptr;
77  if (Size == 0)
78  return nullptr;
79  if (Ctxt.is_host()) {
80  if (Kind == alloc::unknown) {
81  RetVal = nullptr;
82  } else {
83  if (!Alignment) {
84  // worst case default
85  Alignment = 128;
86  }
87 
88  aligned_allocator<char> Alloc(Alignment);
89  try {
90  RetVal = Alloc.allocate(Size);
91  } catch (const std::bad_alloc &) {
92  // Conform with Specification behavior
93  RetVal = nullptr;
94  }
95  }
96  } else {
97  std::shared_ptr<context_impl> CtxImpl = detail::getSyclObjImpl(Ctxt);
98  pi_context C = CtxImpl->getHandleRef();
99  const detail::plugin &Plugin = CtxImpl->getPlugin();
100  pi_result Error;
101  pi_device Id;
102 
103  switch (Kind) {
104  case alloc::device: {
105  Id = detail::getSyclObjImpl(Dev)->getHandleRef();
107  &RetVal, C, Id, nullptr, Size, Alignment);
108  break;
109  }
110  case alloc::shared: {
111  Id = detail::getSyclObjImpl(Dev)->getHandleRef();
113  &RetVal, C, Id, nullptr, Size, Alignment);
114  break;
115  }
116  case alloc::host:
117  case alloc::unknown: {
118  RetVal = nullptr;
119  Error = PI_INVALID_VALUE;
120  break;
121  }
122  }
123 
124  // Error is for debugging purposes.
125  // The spec wants a nullptr returned, not an exception.
126  if (Error != PI_SUCCESS)
127  return nullptr;
128  }
129  return RetVal;
130 }
131 
132 void free(void *Ptr, const context &Ctxt) {
133  if (Ptr == nullptr)
134  return;
135  if (Ctxt.is_host()) {
136  // need to use alignedFree here for Windows
137  detail::OSUtil::alignedFree(Ptr);
138  } else {
139  std::shared_ptr<context_impl> CtxImpl = detail::getSyclObjImpl(Ctxt);
140  pi_context C = CtxImpl->getHandleRef();
141  const detail::plugin &Plugin = CtxImpl->getPlugin();
142  Plugin.call<PiApiKind::piextUSMFree>(C, Ptr);
143  }
144 }
145 
146 } // namespace usm
147 } // namespace detail
148 
149 void *malloc_device(size_t Size, const device &Dev, const context &Ctxt) {
150  return detail::usm::alignedAlloc(0, Size, Ctxt, Dev, alloc::device);
151 }
152 
153 void *malloc_device(size_t Size, const device &Dev, const context &Ctxt,
154  const property_list &) {
155  return malloc_device(Size, Dev, Ctxt);
156 }
157 
158 void *malloc_device(size_t Size, const queue &Q) {
159  return malloc_device(Size, Q.get_device(), Q.get_context());
160 }
161 
162 void *malloc_device(size_t Size, const queue &Q,
163  const property_list &PropList) {
164  return malloc_device(Size, Q.get_device(), Q.get_context(), PropList);
165 }
166 
167 void *aligned_alloc_device(size_t Alignment, size_t Size, const device &Dev,
168  const context &Ctxt) {
169  return detail::usm::alignedAlloc(Alignment, Size, Ctxt, Dev, alloc::device);
170 }
171 
172 void *aligned_alloc_device(size_t Alignment, size_t Size, const device &Dev,
173  const context &Ctxt, const property_list &) {
174  return aligned_alloc_device(Alignment, Size, Dev, Ctxt);
175 }
176 
177 void *aligned_alloc_device(size_t Alignment, size_t Size, const queue &Q) {
178  return aligned_alloc_device(Alignment, Size, Q.get_device(), Q.get_context());
179 }
180 
181 void *aligned_alloc_device(size_t Alignment, size_t Size, const queue &Q,
182  const property_list &PropList) {
183  return aligned_alloc_device(Alignment, Size, Q.get_device(), Q.get_context(),
184  PropList);
185 }
186 
187 void free(void *ptr, const context &Ctxt) {
188  return detail::usm::free(ptr, Ctxt);
189 }
190 
191 void free(void *ptr, const queue &Q) { return free(ptr, Q.get_context()); }
192 
194 // Restricted USM
196 void *malloc_host(size_t Size, const context &Ctxt) {
197  return detail::usm::alignedAllocHost(0, Size, Ctxt, alloc::host);
198 }
199 
200 void *malloc_host(size_t Size, const context &Ctxt, const property_list &) {
201  return malloc_host(Size, Ctxt);
202 }
203 
204 void *malloc_host(size_t Size, const queue &Q) {
205  return malloc_host(Size, Q.get_context());
206 }
207 
208 void *malloc_host(size_t Size, const queue &Q, const property_list &PropList) {
209  return malloc_host(Size, Q.get_context(), PropList);
210 }
211 
212 void *malloc_shared(size_t Size, const device &Dev, const context &Ctxt) {
213  return detail::usm::alignedAlloc(0, Size, Ctxt, Dev, alloc::shared);
214 }
215 
216 void *malloc_shared(size_t Size, const device &Dev, const context &Ctxt,
217  const property_list &) {
218  return malloc_shared(Size, Dev, Ctxt);
219 }
220 
221 void *malloc_shared(size_t Size, const queue &Q) {
222  return malloc_shared(Size, Q.get_device(), Q.get_context());
223 }
224 
225 void *malloc_shared(size_t Size, const queue &Q,
226  const property_list &PropList) {
227  return malloc_shared(Size, Q.get_device(), Q.get_context(), PropList);
228 }
229 
230 void *aligned_alloc_host(size_t Alignment, size_t Size, const context &Ctxt) {
231  return detail::usm::alignedAllocHost(Alignment, Size, Ctxt, alloc::host);
232 }
233 
234 void *aligned_alloc_host(size_t Alignment, size_t Size, const context &Ctxt,
235  const property_list &) {
236  return aligned_alloc_host(Alignment, Size, Ctxt);
237 }
238 
239 void *aligned_alloc_host(size_t Alignment, size_t Size, const queue &Q) {
240  return aligned_alloc_host(Alignment, Size, Q.get_context());
241 }
242 
243 void *aligned_alloc_host(size_t Alignment, size_t Size, const queue &Q,
244  const property_list &PropList) {
245  return aligned_alloc_host(Alignment, Size, Q.get_context(), PropList);
246 }
247 
248 void *aligned_alloc_shared(size_t Alignment, size_t Size, const device &Dev,
249  const context &Ctxt) {
250  return detail::usm::alignedAlloc(Alignment, Size, Ctxt, Dev, alloc::shared);
251 }
252 
253 void *aligned_alloc_shared(size_t Alignment, size_t Size, const device &Dev,
254  const context &Ctxt, const property_list &) {
255  return aligned_alloc_shared(Alignment, Size, Dev, Ctxt);
256 }
257 
258 void *aligned_alloc_shared(size_t Alignment, size_t Size, const queue &Q) {
259  return aligned_alloc_shared(Alignment, Size, Q.get_device(), Q.get_context());
260 }
261 
262 void *aligned_alloc_shared(size_t Alignment, size_t Size, const queue &Q,
263  const property_list &PropList) {
264  return aligned_alloc_shared(Alignment, Size, Q.get_device(), Q.get_context(),
265  PropList);
266 }
267 
268 // single form
269 
270 void *malloc(size_t Size, const device &Dev, const context &Ctxt, alloc Kind) {
271  void *RetVal = nullptr;
272 
273  if (Kind == alloc::host) {
274  RetVal = detail::usm::alignedAllocHost(0, Size, Ctxt, Kind);
275  } else {
276  RetVal = detail::usm::alignedAlloc(0, Size, Ctxt, Dev, Kind);
277  }
278 
279  return RetVal;
280 }
281 
282 void *malloc(size_t Size, const device &Dev, const context &Ctxt, alloc Kind,
283  const property_list &) {
284  return malloc(Size, Dev, Ctxt, Kind);
285 }
286 
287 void *malloc(size_t Size, const queue &Q, alloc Kind) {
288  return malloc(Size, Q.get_device(), Q.get_context(), Kind);
289 }
290 
291 void *malloc(size_t Size, const queue &Q, alloc Kind,
292  const property_list &PropList) {
293  return malloc(Size, Q.get_device(), Q.get_context(), Kind, PropList);
294 }
295 
296 void *aligned_alloc(size_t Alignment, size_t Size, const device &Dev,
297  const context &Ctxt, alloc Kind) {
298  void *RetVal = nullptr;
299 
300  if (Kind == alloc::host) {
301  RetVal = detail::usm::alignedAllocHost(Alignment, Size, Ctxt, Kind);
302  } else {
303  RetVal = detail::usm::alignedAlloc(Alignment, Size, Ctxt, Dev, Kind);
304  }
305 
306  return RetVal;
307 }
308 
309 void *aligned_alloc(size_t Alignment, size_t Size, const device &Dev,
310  const context &Ctxt, alloc Kind, const property_list &) {
311  return aligned_alloc(Alignment, Size, Dev, Ctxt, Kind);
312 }
313 
314 void *aligned_alloc(size_t Alignment, size_t Size, const queue &Q, alloc Kind) {
315  return aligned_alloc(Alignment, Size, Q.get_device(), Q.get_context(), Kind);
316 }
317 
318 void *aligned_alloc(size_t Alignment, size_t Size, const queue &Q, alloc Kind,
319  const property_list &PropList) {
320  return aligned_alloc(Alignment, Size, Q.get_device(), Q.get_context(), Kind,
321  PropList);
322 }
323 
324 // Pointer queries
330 alloc get_pointer_type(const void *Ptr, const context &Ctxt) {
331  if (!Ptr)
332  return alloc::unknown;
333 
334  // Everything on a host device is just system malloc so call it host
335  if (Ctxt.is_host())
336  return alloc::host;
337 
338  std::shared_ptr<detail::context_impl> CtxImpl = detail::getSyclObjImpl(Ctxt);
339  pi_context PICtx = CtxImpl->getHandleRef();
340  pi_usm_type AllocTy;
341 
342  // query type using PI function
343  const detail::plugin &Plugin = CtxImpl->getPlugin();
344  RT::PiResult Err =
346  PICtx, Ptr, PI_MEM_ALLOC_TYPE, sizeof(pi_usm_type), &AllocTy,
347  nullptr);
348 
349  // PI_INVALID_VALUE means USM doesn't know about this ptr
350  if (Err == PI_INVALID_VALUE)
351  return alloc::unknown;
352  // otherwise PI_SUCCESS is expected
353  if (Err != PI_SUCCESS) {
354  Plugin.reportPiError(Err, "get_pointer_type()");
355  }
356 
357  alloc ResultAlloc;
358  switch (AllocTy) {
359  case PI_MEM_TYPE_HOST:
360  ResultAlloc = alloc::host;
361  break;
362  case PI_MEM_TYPE_DEVICE:
363  ResultAlloc = alloc::device;
364  break;
365  case PI_MEM_TYPE_SHARED:
366  ResultAlloc = alloc::shared;
367  break;
368  default:
369  ResultAlloc = alloc::unknown;
370  break;
371  }
372 
373  return ResultAlloc;
374 }
375 
380 device get_pointer_device(const void *Ptr, const context &Ctxt) {
381  // Check if ptr is a valid USM pointer
382  if (get_pointer_type(Ptr, Ctxt) == alloc::unknown)
383  throw runtime_error("Ptr not a valid USM allocation!", PI_INVALID_VALUE);
384 
385  // Just return the host device in the host context
386  if (Ctxt.is_host())
387  return Ctxt.get_devices()[0];
388 
389  std::shared_ptr<detail::context_impl> CtxImpl = detail::getSyclObjImpl(Ctxt);
390 
391  // Check if ptr is a host allocation
392  if (get_pointer_type(Ptr, Ctxt) == alloc::host) {
393  auto Devs = CtxImpl->getDevices();
394  if (Devs.size() == 0)
395  throw runtime_error("No devices in passed context!", PI_INVALID_VALUE);
396 
397  // Just return the first device in the context
398  return Devs[0];
399  }
400 
401  pi_context PICtx = CtxImpl->getHandleRef();
402  pi_device DeviceId;
403 
404  // query device using PI function
405  const detail::plugin &Plugin = CtxImpl->getPlugin();
407  PICtx, Ptr, PI_MEM_ALLOC_DEVICE, sizeof(pi_device), &DeviceId, nullptr);
408 
409  for (const device &Dev : CtxImpl->getDevices()) {
410  // Try to find the real sycl device used in the context
411  if (detail::getSyclObjImpl(Dev)->getHandleRef() == DeviceId)
412  return Dev;
413  }
414 
415  throw runtime_error("Cannot find device associated with USM allocation!",
417 }
418 
419 } // namespace sycl
420 } // __SYCL_INLINE_NAMESPACE(cl)
cl::sycl::malloc
void * malloc(size_t size, const device &dev, const context &ctxt, usm::alloc kind)
Definition: usm_impl.cpp:270
PI_SUCCESS
@ PI_SUCCESS
Definition: pi.h:82
cl::sycl::detail::aligned_allocator
Definition: aligned_allocator.hpp:23
piextUSMFree
pi_result piextUSMFree(pi_context context, void *ptr)
Frees allocated USM memory.
Definition: pi_esimd_emulator.cpp:1448
cl::sycl::info::device
device
Definition: info_desc.hpp:49
PI_INVALID_OPERATION
@ PI_INVALID_OPERATION
Definition: pi.h:84
cl::sycl::detail::usm::alignedAllocHost
void * alignedAllocHost(size_t Alignment, size_t Bytes, const context &Ctxt, cl::sycl::usm::alloc Kind)
Definition: usm_impl.cpp:27
_pi_usm_type
_pi_usm_type
Definition: pi.h:1574
device.hpp
_pi_result
_pi_result
Definition: pi.h:81
context.hpp
os_util.hpp
cl::sycl::detail::usm::alignedAlloc
void * alignedAlloc(size_t Alignment, size_t Bytes, const context &Ctxt, const device &Dev, cl::sycl::usm::alloc Kind)
Definition: usm_impl.cpp:74
usm.hpp
queue_impl.hpp
cl::sycl::queue
Encapsulates a single SYCL queue which schedules kernels on a SYCL device.
Definition: queue.hpp:103
pi.hpp
piextUSMSharedAlloc
pi_result piextUSMSharedAlloc(void **result_ptr, pi_context context, pi_device device, pi_usm_mem_properties *properties, size_t size, pi_uint32 alignment)
Allocates memory accessible on both host and device.
Definition: pi_esimd_emulator.cpp:1419
PI_MEM_TYPE_DEVICE
@ PI_MEM_TYPE_DEVICE
Definition: pi.h:1577
cl::sycl::info::queue
queue
Definition: info_desc.hpp:219
cl::sycl::detail::plugin::call_nocheck
RT::PiResult call_nocheck(ArgsT... Args) const
Calls the PiApi, traces the call, and returns the result.
Definition: plugin.hpp:141
piextUSMDeviceAlloc
pi_result piextUSMDeviceAlloc(void **result_ptr, pi_context context, pi_device device, pi_usm_mem_properties *properties, size_t size, pi_uint32 alignment)
Allocates device memory.
Definition: pi_esimd_emulator.cpp:1414
cl::sycl::aligned_alloc_host
void * aligned_alloc_host(size_t alignment, size_t size, const context &ctxt)
Definition: usm_impl.cpp:230
piextUSMGetMemAllocInfo
pi_result piextUSMGetMemAllocInfo(pi_context context, const void *ptr, pi_mem_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
API to query information about USM allocated pointers Valid Queries: PI_MEM_ALLOC_TYPE returns host/d...
Definition: pi_esimd_emulator.cpp:1490
cl::sycl::malloc_device
void * malloc_device(size_t size, const device &dev, const context &ctxt)
Definition: usm_impl.cpp:149
cl::sycl::malloc_host
void * malloc_host(size_t size, const context &ctxt)
Definition: usm_impl.cpp:196
pi_usm_type
_pi_usm_type pi_usm_type
Definition: pi.h:1595
cl::sycl::device
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:34
cl::sycl::detail::usm::free
void free(void *Ptr, const context &Ctxt)
Definition: usm_impl.cpp:132
cl::sycl::context::is_host
bool is_host() const
Gets OpenCL interoperability context.
Definition: context.cpp:119
PI_MEM_TYPE_SHARED
@ PI_MEM_TYPE_SHARED
Definition: pi.h:1578
cl::sycl::detail::aligned_allocator::allocate
pointer allocate(size_t Size)
Definition: aligned_allocator.hpp:51
cl::sycl::detail::plugin::call
void call(ArgsT... Args) const
Calls the API, traces the call, checks the result.
Definition: plugin.hpp:182
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
cl::sycl::malloc_shared
void * malloc_shared(size_t size, const device &dev, const context &ctxt)
Definition: usm_impl.cpp:212
cl::sycl::get_pointer_device
device get_pointer_device(const void *ptr, const context &ctxt)
Queries the device against which the pointer was allocated Throws an invalid_object_error if ptr is a...
Definition: usm_impl.cpp:380
cl::sycl::alloc
cl::sycl::usm::alloc alloc
Definition: usm_impl.cpp:22
piextUSMHostAlloc
pi_result piextUSMHostAlloc(void **result_ptr, pi_context context, pi_usm_mem_properties *properties, size_t size, pi_uint32 alignment)
Allocates host memory accessible by the device.
Definition: pi_esimd_emulator.cpp:1409
cl::sycl::detail::plugin
The plugin class provides a unified interface to the underlying low-level runtimes for the device-agn...
Definition: plugin.hpp:89
aligned_allocator.hpp
cl::sycl::context::get_devices
std::vector< device > get_devices() const
Gets devices associated with this SYCL context.
Definition: context.cpp:127
cl::sycl::queue::get_device
device get_device() const
Definition: queue.cpp:74
cl::sycl::get_pointer_type
usm::alloc get_pointer_type(const void *ptr, const context &ctxt)
Query the allocation type from a USM pointer.
Definition: usm_impl.cpp:330
cl::sycl::aligned_alloc
void * aligned_alloc(size_t alignment, size_t size, const device &dev, const context &ctxt, usm::alloc kind, const property_list &propList)
Definition: usm.hpp:208
cl::sycl::queue::get_context
context get_context() const
Definition: queue.cpp:72
PI_INVALID_VALUE
@ PI_INVALID_VALUE
Definition: pi.h:87
cl::sycl::detail::getSyclObjImpl
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: common.hpp:182
cl::sycl::context
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:35
PI_MEM_ALLOC_DEVICE
@ PI_MEM_ALLOC_DEVICE
Definition: pi.h:1571
PI_MEM_ALLOC_TYPE
@ PI_MEM_ALLOC_TYPE
Definition: pi.h:1568
cl::sycl::info::context
context
Definition: info_desc.hpp:40
PI_MEM_TYPE_HOST
@ PI_MEM_TYPE_HOST
Definition: pi.h:1576
cl::sycl::aligned_alloc_shared
void * aligned_alloc_shared(size_t alignment, size_t size, const device &dev, const context &ctxt)
Definition: usm_impl.cpp:248
cl::sycl::detail::plugin::reportPiError
void reportPiError(RT::PiResult pi_result, const char *context) const
Definition: plugin.hpp:120
cl::sycl::aligned_alloc_device
void * aligned_alloc_device(size_t alignment, size_t size, const device &dev, const context &ctxt)
Definition: usm_impl.cpp:167
cl::sycl::usm::alloc
alloc
Definition: usm_enums.hpp:14
pi_device
_pi_device * pi_device
Definition: pi.h:867
_pi_context
PI context mapping to a CUDA context object.
Definition: pi_cuda.hpp:148
_pi_device
PI device mapping to a CUdevice.
Definition: pi_cuda.hpp:71
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12