DPC++ Runtime
Runtime libraries for oneAPI DPC++
virtual_mem.cpp
Go to the documentation of this file.
1 //==- virtual_mem.cpp - sycl_ext_oneapi_virtual_mem virtual mem free funcs -==//
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 
10 #include <detail/device_impl.hpp>
13 
14 // System headers for querying page-size.
15 #ifdef _WIN32
16 #include <windows.h>
17 #else
18 #include <unistd.h>
19 #endif
20 
21 namespace sycl {
22 inline namespace _V1 {
23 namespace ext::oneapi::experimental {
24 
25 __SYCL_EXPORT size_t get_mem_granularity(const device &SyclDevice,
26  const context &SyclContext,
28  if (!SyclDevice.has(aspect::ext_oneapi_virtual_mem))
29  throw sycl::exception(
30  sycl::make_error_code(sycl::errc::feature_not_supported),
31  "Device does not support aspect::ext_oneapi_virtual_mem.");
32 
33  ur_virtual_mem_granularity_info_t GranularityQuery = [=]() {
34  switch (Mode) {
36  return UR_VIRTUAL_MEM_GRANULARITY_INFO_MINIMUM;
38  return UR_VIRTUAL_MEM_GRANULARITY_INFO_RECOMMENDED;
39  }
40  throw sycl::exception(sycl::make_error_code(sycl::errc::invalid),
41  "Unrecognized granularity mode.");
42  }();
43 
44  std::shared_ptr<sycl::detail::device_impl> DeviceImpl =
45  sycl::detail::getSyclObjImpl(SyclDevice);
46  std::shared_ptr<sycl::detail::context_impl> ContextImpl =
47  sycl::detail::getSyclObjImpl(SyclContext);
48  const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin();
49 #ifndef NDEBUG
50  size_t InfoOutputSize;
51  Plugin->call(urVirtualMemGranularityGetInfo, ContextImpl->getHandleRef(),
52  DeviceImpl->getHandleRef(), GranularityQuery, 0, nullptr,
53  &InfoOutputSize);
54  assert(InfoOutputSize == sizeof(size_t) &&
55  "Unexpected output size of granularity info query.");
56 #endif // NDEBUG
57  size_t Granularity = 0;
58  Plugin->call(urVirtualMemGranularityGetInfo, ContextImpl->getHandleRef(),
59  DeviceImpl->getHandleRef(), GranularityQuery, sizeof(size_t),
60  &Granularity, nullptr);
61  return Granularity;
62 }
63 
64 __SYCL_EXPORT size_t get_mem_granularity(const context &SyclContext,
66  const std::vector<device> Devices = SyclContext.get_devices();
67  if (!std::all_of(Devices.cbegin(), Devices.cend(), [](const device &Dev) {
68  return Dev.has(aspect::ext_oneapi_virtual_mem);
69  })) {
70  throw sycl::exception(
71  sycl::make_error_code(sycl::errc::feature_not_supported),
72  "One or more devices in the context does not support "
73  "aspect::ext_oneapi_virtual_mem.");
74  }
75 
76  // CUDA only needs page-size granularity.
77  if (SyclContext.get_backend() == backend::ext_oneapi_cuda) {
78 #ifdef _WIN32
79  SYSTEM_INFO SystemInfo;
80  GetSystemInfo(&SystemInfo);
81  return static_cast<size_t>(SystemInfo.dwPageSize);
82 #else
83  return static_cast<size_t>(sysconf(_SC_PAGESIZE));
84 #endif
85  }
86 
87  // Otherwise, we find the least common multiple of granularity of the devices
88  // in the context.
89  size_t LCMGranularity = get_mem_granularity(Devices[0], SyclContext, Mode);
90  for (size_t I = 1; I < Devices.size(); ++I) {
91  size_t DevGranularity = get_mem_granularity(Devices[I], SyclContext, Mode);
92  size_t GCD = LCMGranularity;
93  size_t Rem = DevGranularity % GCD;
94  while (Rem != 0) {
95  std::swap(GCD, Rem);
96  Rem %= GCD;
97  }
98  LCMGranularity *= DevGranularity / GCD;
99  }
100  return LCMGranularity;
101 }
102 
103 __SYCL_EXPORT uintptr_t reserve_virtual_mem(uintptr_t Start, size_t NumBytes,
104  const context &SyclContext) {
105  std::vector<device> Devs = SyclContext.get_devices();
106  if (std::any_of(Devs.cbegin(), Devs.cend(), [](const device &Dev) {
107  return !Dev.has(aspect::ext_oneapi_virtual_mem);
108  }))
109  throw sycl::exception(
110  sycl::make_error_code(sycl::errc::feature_not_supported),
111  "One or more devices in the supplied context does not support "
112  "aspect::ext_oneapi_virtual_mem.");
113 
114  std::shared_ptr<sycl::detail::context_impl> ContextImpl =
115  sycl::detail::getSyclObjImpl(SyclContext);
116  const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin();
117  void *OutPtr = nullptr;
118  Plugin->call(urVirtualMemReserve, ContextImpl->getHandleRef(),
119  reinterpret_cast<void *>(Start), NumBytes, &OutPtr);
120  return reinterpret_cast<uintptr_t>(OutPtr);
121 }
122 
123 __SYCL_EXPORT void free_virtual_mem(uintptr_t Ptr, size_t NumBytes,
124  const context &SyclContext) {
125  std::shared_ptr<sycl::detail::context_impl> ContextImpl =
126  sycl::detail::getSyclObjImpl(SyclContext);
127  const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin();
128  Plugin->call(urVirtualMemFree, ContextImpl->getHandleRef(),
129  reinterpret_cast<void *>(Ptr), NumBytes);
130 }
131 
132 __SYCL_EXPORT void set_access_mode(const void *Ptr, size_t NumBytes,
134  const context &SyclContext) {
136  std::shared_ptr<sycl::detail::context_impl> ContextImpl =
137  sycl::detail::getSyclObjImpl(SyclContext);
138  const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin();
139  Plugin->call(urVirtualMemSetAccess, ContextImpl->getHandleRef(), Ptr,
140  NumBytes, AccessFlags);
141 }
142 
143 __SYCL_EXPORT address_access_mode get_access_mode(const void *Ptr,
144  size_t NumBytes,
145  const context &SyclContext) {
146  std::shared_ptr<sycl::detail::context_impl> ContextImpl =
147  sycl::detail::getSyclObjImpl(SyclContext);
148  const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin();
149 #ifndef NDEBUG
150  size_t InfoOutputSize = 0;
151  Plugin->call(urVirtualMemGetInfo, ContextImpl->getHandleRef(), Ptr, NumBytes,
152  UR_VIRTUAL_MEM_INFO_ACCESS_MODE, 0, nullptr, &InfoOutputSize);
153  assert(InfoOutputSize == sizeof(ur_virtual_mem_access_flags_t) &&
154  "Unexpected output size of access mode info query.");
155 #endif // NDEBUG
156  ur_virtual_mem_access_flags_t AccessFlags;
157  Plugin->call(urVirtualMemGetInfo, ContextImpl->getHandleRef(), Ptr, NumBytes,
158  UR_VIRTUAL_MEM_INFO_ACCESS_MODE,
159  sizeof(ur_virtual_mem_access_flags_t), &AccessFlags, nullptr);
160 
161  if (AccessFlags & UR_VIRTUAL_MEM_ACCESS_FLAG_READ_WRITE)
163  if (AccessFlags & UR_VIRTUAL_MEM_ACCESS_FLAG_READ_ONLY)
166 }
167 
168 __SYCL_EXPORT void unmap(const void *Ptr, size_t NumBytes,
169  const context &SyclContext) {
170  std::shared_ptr<sycl::detail::context_impl> ContextImpl =
171  sycl::detail::getSyclObjImpl(SyclContext);
172  const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin();
173  Plugin->call(urVirtualMemUnmap, ContextImpl->getHandleRef(), Ptr, NumBytes);
174 }
175 
176 } // Namespace ext::oneapi::experimental
177 } // namespace _V1
178 } // Namespace sycl
The context class represents a SYCL context on which kernel functions may be executed.
Definition: context.hpp:50
std::vector< device > get_devices() const
Gets devices associated with this SYCL context.
Definition: context.cpp:124
backend get_backend() const noexcept
Gets OpenCL interoperability context.
Definition: context.cpp:118
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
bool has(aspect Aspect) const __SYCL_WARN_IMAGE_ASPECT(Aspect)
Indicates if the SYCL device has the given feature.
Definition: device.cpp:207
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:31
std::shared_ptr< plugin > PluginPtr
Definition: ur.hpp:60
ur_virtual_mem_access_flag_t AccessModeToVirtualAccessFlags(ext::oneapi::experimental::address_access_mode Mode)
size_t get_mem_granularity(const device &SyclDevice, const context &SyclContext, granularity_mode Mode=granularity_mode::recommended)
Definition: virtual_mem.cpp:25
void unmap(const void *Ptr, size_t NumBytes, const context &SyclContext)
void set_access_mode(const void *Ptr, size_t NumBytes, address_access_mode Mode, const context &SyclContext)
address_access_mode get_access_mode(const void *Ptr, size_t NumBytes, const context &SyclContext)
void free_virtual_mem(uintptr_t Ptr, size_t NumBytes, const context &SyclContext)
uintptr_t reserve_virtual_mem(uintptr_t Start, size_t NumBytes, const context &SyclContext)
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:65
Definition: access.hpp:18
bool any_of(const simd_mask< _Tp, _Abi > &) noexcept
bool all_of(const simd_mask< _Tp, _Abi > &) noexcept