DPC++ Runtime
Runtime libraries for oneAPI DPC++
context_impl.hpp
Go to the documentation of this file.
1 //==---------------- context_impl.hpp - SYCL context ------------*- 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 #pragma once
10 #include <detail/device_impl.hpp>
12 #include <detail/platform_impl.hpp>
14 #include <sycl/detail/common.hpp>
15 #include <sycl/detail/os_util.hpp>
16 #include <sycl/detail/pi.hpp>
17 #include <sycl/exception_list.hpp>
18 #include <sycl/info/info_desc.hpp>
19 #include <sycl/property_list.hpp>
20 
21 #include <map>
22 #include <memory>
23 #include <optional>
24 #include <set>
25 
26 namespace sycl {
27 inline namespace _V1 {
28 // Forward declaration
29 class device;
30 namespace detail {
31 using PlatformImplPtr = std::shared_ptr<detail::platform_impl>;
32 class context_impl {
33 public:
43  context_impl(const device &Device, async_handler AsyncHandler,
44  const property_list &PropList);
45 
58  context_impl(const std::vector<sycl::device> DeviceList,
59  async_handler AsyncHandler, const property_list &PropList);
60 
72  async_handler AsyncHandler, const PluginPtr &Plugin,
73  const std::vector<sycl::device> &DeviceList = {},
74  bool OwnedByRuntime = true);
75 
76  ~context_impl();
77 
81  cl_context get() const;
82 
86  const async_handler &get_async_handler() const;
87 
89  const PluginPtr &getPlugin() const { return MPlatform->getPlugin(); }
90 
92  PlatformImplPtr getPlatformImpl() const { return MPlatform; }
93 
97  template <typename Param> typename Param::return_type get_info() const;
98 
102  template <typename Param>
103  typename Param::return_type get_backend_info() const;
104 
114 
124 
127  const std::vector<device> &getDevices() const { return MDevices; }
128 
130  std::map<std::pair<DeviceLibExt, sycl::detail::pi::PiDevice>,
132 
147  return {MCachedLibPrograms, MCachedLibProgramsMutex};
148  }
149 
151 
153  bool hasDevice(std::shared_ptr<detail::device_impl> Device) const;
154 
160  while (!hasDevice(Device)) {
161  if (Device->isRootDevice()) {
162  if (Device->has(aspect::ext_oneapi_is_component)) {
163  // Component devices should be implicitly usable in context created
164  // for a composite device they belong to.
165  auto CompositeDevice = Device->get_info<
166  ext::oneapi::experimental::info::device::composite_device>();
167  return hasDevice(detail::getSyclObjImpl(CompositeDevice));
168  }
169 
170  return false;
171  } else if (Device->getBackend() == backend::opencl) {
172  // OpenCL does not support using descendants of context members within
173  // that context yet. We make the exception in case it supports
174  // component/composite devices.
175  // TODO remove once this limitation is lifted
176  return false;
177  }
178  Device = detail::getSyclObjImpl(
179  Device->get_info<info::device::parent_device>());
180  }
181 
182  return true;
183  }
184 
185  // Returns the backend of this context
186  backend getBackend() const {
187  assert(MPlatform && "MPlatform must be not null");
188  return MPlatform->getBackend();
189  }
190 
195 
199  pi_native_handle getNative() const;
200 
201  // Returns true if buffer_location property is supported by devices
202  bool isBufferLocationSupported() const;
203 
205  void addAssociatedDeviceGlobal(const void *DeviceGlobalPtr);
206 
209  const std::vector<device> &Devs,
210  const RTDeviceBinaryImage *BinImage);
211 
213  std::vector<sycl::detail::pi::PiEvent>
215  const std::shared_ptr<queue_impl> &QueueImpl);
216 
218  const std::shared_ptr<device_impl> &DeviceImpl,
219  const void *DeviceGlobalPtr, const void *Src, size_t DeviceGlobalTSize,
220  bool IsDeviceImageScoped, size_t NumBytes, size_t Offset);
221 
222  void
223  memcpyFromHostOnlyDeviceGlobal(const std::shared_ptr<device_impl> &DeviceImpl,
224  void *Dest, const void *DeviceGlobalPtr,
225  bool IsDeviceImageScoped, size_t NumBytes,
226  size_t Offset);
227 
229  std::optional<sycl::detail::pi::PiProgram>
230  getProgramForDeviceGlobal(const device &Device,
231  DeviceGlobalMapEntry *DeviceGlobalEntry);
233  std::optional<sycl::detail::pi::PiProgram>
234  getProgramForHostPipe(const device &Device, HostPipeMapEntry *HostPipeEntry);
235 
237  std::optional<sycl::detail::pi::PiProgram>
238  getProgramForDevImgs(const device &Device,
239  const std::set<std::uintptr_t> &ImgIdentifiers,
240  const std::string &ObjectTypeName);
241 
242  bool isOwnedByRuntime() { return MOwnedByRuntime; };
243 
245 
246  const property_list &getPropList() const { return MPropList; }
247 
248 private:
249  bool MOwnedByRuntime;
250  async_handler MAsyncHandler;
251  std::vector<device> MDevices;
253  PlatformImplPtr MPlatform;
254  property_list MPropList;
255  CachedLibProgramsT MCachedLibPrograms;
256  std::mutex MCachedLibProgramsMutex;
257  mutable KernelProgramCache MKernelProgramCache;
258  mutable PropertySupport MSupportBufferLocationByDevices;
259 
260  std::set<const void *> MAssociatedDeviceGlobals;
261  std::mutex MAssociatedDeviceGlobalsMutex;
262 
263  struct DeviceGlobalInitializer {
264  DeviceGlobalInitializer() = default;
265  DeviceGlobalInitializer(const RTDeviceBinaryImage *BinImage)
266  : MBinImage(BinImage) {
267  // If there are no device globals, they are trivially fully initialized.
268  // Note: Lock is not needed during construction.
269  MDeviceGlobalsFullyInitialized = BinImage->getDeviceGlobals().size() == 0;
270  }
271 
273  void ClearEvents(const PluginPtr &Plugin);
274 
276  const RTDeviceBinaryImage *MBinImage = nullptr;
277 
279  std::mutex MDeviceGlobalInitMutex;
280 
288  bool MDeviceGlobalsFullyInitialized = false;
289 
292  std::vector<sycl::detail::pi::PiEvent> MDeviceGlobalInitEvents;
293  };
294 
295  std::map<std::pair<sycl::detail::pi::PiProgram, sycl::detail::pi::PiDevice>,
296  DeviceGlobalInitializer>
297  MDeviceGlobalInitializers;
298  std::mutex MDeviceGlobalInitializersMutex;
299 
300  // For device_global variables that are not used in any kernel code we still
301  // allow copy operations on them. MDeviceGlobalUnregisteredData stores the
302  // associated writes.
303  // The key to this map is a combination of a the pointer to the device_global
304  // and optionally a device if the device_global has device image scope.
305  std::map<std::pair<const void *, std::optional<sycl::detail::pi::PiDevice>>,
306  std::unique_ptr<std::byte[]>>
307  MDeviceGlobalUnregisteredData;
308  std::mutex MDeviceGlobalUnregisteredDataMutex;
309 };
310 
311 template <typename T, typename Capabilities>
312 void GetCapabilitiesIntersectionSet(const std::vector<sycl::device> &Devices,
313  std::vector<T> &CapabilityList) {
314  for (const sycl::device &Device : Devices) {
315  std::vector<T> NewCapabilityList;
316  std::vector<T> DeviceCapabilities = Device.get_info<Capabilities>();
317  std::set_intersection(
318  CapabilityList.begin(), CapabilityList.end(),
319  DeviceCapabilities.begin(), DeviceCapabilities.end(),
320  std::inserter(NewCapabilityList, NewCapabilityList.begin()));
321  CapabilityList = NewCapabilityList;
322  }
323  CapabilityList.shrink_to_fit();
324 }
325 
326 } // namespace detail
327 } // namespace _V1
328 } // namespace sycl
Represents a reference to value with appropriate lock acquired.
Definition: locked.hpp:23
const PropertyRange & getDeviceGlobals() const
bool hasDevice(std::shared_ptr< detail::device_impl > Device) const
Returns true if and only if context contains the given device.
context_impl(const device &Device, async_handler AsyncHandler, const property_list &PropList)
Constructs a context_impl using a single SYCL devices.
bool isDeviceValid(DeviceImplPtr Device)
Returns true if and only if the device can be used within this context.
Locked< CachedLibProgramsT > acquireCachedLibPrograms()
In contrast to user programs, which are compiled from user code, library programs come from the SYCL ...
KernelProgramCache & getKernelProgramCache() const
void addDeviceGlobalInitializer(sycl::detail::pi::PiProgram Program, const std::vector< device > &Devs, const RTDeviceBinaryImage *BinImage)
Adds a device global initializer.
pi_native_handle getNative() const
Gets the native handle of the SYCL context.
void addAssociatedDeviceGlobal(const void *DeviceGlobalPtr)
Adds an associated device global to the tracked associates.
const property_list & getPropList() const
std::optional< sycl::detail::pi::PiProgram > getProgramForDeviceGlobal(const device &Device, DeviceGlobalMapEntry *DeviceGlobalEntry)
Gets a program associated with a device global from the cache.
const std::vector< device > & getDevices() const
Unlike ‘get_info<info::context::devices>’, this function returns a reference.
Param::return_type get_info() const
Queries this context for information.
std::map< std::pair< DeviceLibExt, sycl::detail::pi::PiDevice >, sycl::detail::pi::PiProgram > CachedLibProgramsT
std::optional< sycl::detail::pi::PiProgram > getProgramForDevImgs(const device &Device, const std::set< std::uintptr_t > &ImgIdentifiers, const std::string &ObjectTypeName)
Gets a program associated with Dev / Images pairs.
void memcpyFromHostOnlyDeviceGlobal(const std::shared_ptr< device_impl > &DeviceImpl, void *Dest, const void *DeviceGlobalPtr, bool IsDeviceImageScoped, size_t NumBytes, size_t Offset)
void memcpyToHostOnlyDeviceGlobal(const std::shared_ptr< device_impl > &DeviceImpl, const void *DeviceGlobalPtr, const void *Src, size_t DeviceGlobalTSize, bool IsDeviceImageScoped, size_t NumBytes, size_t Offset)
std::vector< sycl::detail::pi::PiEvent > initializeDeviceGlobals(pi::PiProgram NativePrg, const std::shared_ptr< queue_impl > &QueueImpl)
Initializes device globals for a program on the associated queue.
std::optional< sycl::detail::pi::PiProgram > getProgramForHostPipe(const device &Device, HostPipeMapEntry *HostPipeEntry)
Gets a program associated with a HostPipe Entry from the cache.
Param::return_type get_backend_info() const
Queries SYCL queue for SYCL backend-specific information.
const PluginPtr & getPlugin() const
PlatformImplPtr getPlatformImpl() const
cl_context get() const
Gets OpenCL interoperability context handle.
const async_handler & get_async_handler() const
Gets asynchronous exception handler.
DeviceImplPtr findMatchingDeviceImpl(sycl::detail::pi::PiDevice &DevicePI) const
Given a PiDevice, returns the matching shared_ptr<device_impl> within this context.
sycl::detail::pi::PiContext & getHandleRef()
Gets the underlying context object (if any) without reference count modification.
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
detail::is_device_info_desc< Param >::return_type get_info() const
Queries this SYCL device for information requested by the template parameter param.
Definition: device.hpp:215
Objects of the property_list class are containers for the SYCL properties.
::pi_context PiContext
Definition: pi.hpp:109
decltype(Obj::impl) const & getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:31
void GetCapabilitiesIntersectionSet(const std::vector< sycl::device > &Devices, std::vector< T > &CapabilityList)
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:47
std::shared_ptr< detail::platform_impl > PlatformImplPtr
std::shared_ptr< device_impl > DeviceImplPtr
std::function< void(sycl::exception_list)> async_handler
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:258
C++ wrapper of extern "C" PI interfaces.