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  template <typename propertyT> bool has_property() const noexcept {
82  return MPropList.has_property<propertyT>();
83  }
84 
91  template <typename propertyT> propertyT get_property() const {
92  return MPropList.get_property<propertyT>();
93  }
94 
98  cl_context get() const;
99 
103  bool is_host() const;
104 
108  const async_handler &get_async_handler() const;
109 
111  const PluginPtr &getPlugin() const { return MPlatform->getPlugin(); }
112 
114  PlatformImplPtr getPlatformImpl() const { return MPlatform; }
115 
119  template <typename Param> typename Param::return_type get_info() const;
120 
124  template <typename Param>
125  typename Param::return_type get_backend_info() const;
126 
136 
146 
149  const std::vector<device> &getDevices() const { return MDevices; }
150 
152  std::map<std::pair<DeviceLibExt, sycl::detail::pi::PiDevice>,
154 
169  return {MCachedLibPrograms, MCachedLibProgramsMutex};
170  }
171 
173 
175  bool hasDevice(std::shared_ptr<detail::device_impl> Device) const;
176 
182  // OpenCL does not support using descendants of context members within that
183  // context yet.
184  // TODO remove once this limitation is lifted
185  if (!is_host() && Device->getBackend() == backend::opencl)
186  return hasDevice(Device);
187 
188  while (!hasDevice(Device)) {
189  if (Device->isRootDevice())
190  return false;
191  Device = detail::getSyclObjImpl(
192  Device->get_info<info::device::parent_device>());
193  }
194 
195  return true;
196  }
197 
198  // Returns the backend of this context
199  backend getBackend() const {
200  assert(MPlatform && "MPlatform must be not null");
201  return MPlatform->getBackend();
202  }
203 
208 
212  pi_native_handle getNative() const;
213 
214  // Returns true if buffer_location property is supported by devices
215  bool isBufferLocationSupported() const;
216 
218  void addAssociatedDeviceGlobal(const void *DeviceGlobalPtr);
219 
222  const std::vector<device> &Devs,
223  const RTDeviceBinaryImage *BinImage);
224 
226  std::vector<sycl::detail::pi::PiEvent>
228  const std::shared_ptr<queue_impl> &QueueImpl);
229 
231  const std::shared_ptr<device_impl> &DeviceImpl,
232  const void *DeviceGlobalPtr, const void *Src, size_t DeviceGlobalTSize,
233  bool IsDeviceImageScoped, size_t NumBytes, size_t Offset);
234 
235  void
236  memcpyFromHostOnlyDeviceGlobal(const std::shared_ptr<device_impl> &DeviceImpl,
237  void *Dest, const void *DeviceGlobalPtr,
238  bool IsDeviceImageScoped, size_t NumBytes,
239  size_t Offset);
240 
242  std::optional<sycl::detail::pi::PiProgram>
243  getProgramForDeviceGlobal(const device &Device,
244  DeviceGlobalMapEntry *DeviceGlobalEntry);
246  std::optional<sycl::detail::pi::PiProgram>
247  getProgramForHostPipe(const device &Device, HostPipeMapEntry *HostPipeEntry);
248 
250  std::optional<sycl::detail::pi::PiProgram>
251  getProgramForDevImgs(const device &Device,
252  const std::set<std::uintptr_t> &ImgIdentifiers,
253  const std::string &ObjectTypeName);
254 
255  bool isOwnedByRuntime() { return MOwnedByRuntime; };
256 
258 
259 private:
260  bool MOwnedByRuntime;
261  async_handler MAsyncHandler;
262  std::vector<device> MDevices;
264  PlatformImplPtr MPlatform;
265  property_list MPropList;
266  bool MHostContext;
267  CachedLibProgramsT MCachedLibPrograms;
268  std::mutex MCachedLibProgramsMutex;
269  mutable KernelProgramCache MKernelProgramCache;
270  mutable PropertySupport MSupportBufferLocationByDevices;
271 
272  std::set<const void *> MAssociatedDeviceGlobals;
273  std::mutex MAssociatedDeviceGlobalsMutex;
274 
275  struct DeviceGlobalInitializer {
276  DeviceGlobalInitializer() = default;
277  DeviceGlobalInitializer(const RTDeviceBinaryImage *BinImage)
278  : MBinImage(BinImage) {
279  // If there are no device globals, they are trivially fully initialized.
280  // Note: Lock is not needed during construction.
281  MDeviceGlobalsFullyInitialized = BinImage->getDeviceGlobals().size() == 0;
282  }
283 
285  void ClearEvents(const PluginPtr &Plugin);
286 
288  const RTDeviceBinaryImage *MBinImage = nullptr;
289 
291  std::mutex MDeviceGlobalInitMutex;
292 
300  bool MDeviceGlobalsFullyInitialized = false;
301 
304  std::vector<sycl::detail::pi::PiEvent> MDeviceGlobalInitEvents;
305  };
306 
307  std::map<std::pair<sycl::detail::pi::PiProgram, sycl::detail::pi::PiDevice>,
308  DeviceGlobalInitializer>
309  MDeviceGlobalInitializers;
310  std::mutex MDeviceGlobalInitializersMutex;
311 
312  // For device_global variables that are not used in any kernel code we still
313  // allow copy operations on them. MDeviceGlobalUnregisteredData stores the
314  // associated writes.
315  // The key to this map is a combination of a the pointer to the device_global
316  // and optionally a device if the device_global has device image scope.
317  std::map<std::pair<const void *, std::optional<sycl::detail::pi::PiDevice>>,
318  std::unique_ptr<std::byte[]>>
319  MDeviceGlobalUnregisteredData;
320  std::mutex MDeviceGlobalUnregisteredDataMutex;
321 };
322 
323 template <typename T, typename Capabilities>
324 void GetCapabilitiesIntersectionSet(const std::vector<sycl::device> &Devices,
325  std::vector<T> &CapabilityList) {
326  for (const sycl::device &Device : Devices) {
327  std::vector<T> NewCapabilityList;
328  std::vector<T> DeviceCapabilities = Device.get_info<Capabilities>();
329  std::set_intersection(
330  CapabilityList.begin(), CapabilityList.end(),
331  DeviceCapabilities.begin(), DeviceCapabilities.end(),
332  std::inserter(NewCapabilityList, NewCapabilityList.begin()));
333  CapabilityList = NewCapabilityList;
334  }
335  CapabilityList.shrink_to_fit();
336 }
337 
338 } // namespace detail
339 } // namespace _V1
340 } // namespace sycl
Represents a reference to value with appropriate lock acquired.
Definition: locked.hpp:23
const PropertyRange & getDeviceGlobals() const
propertyT get_property() const
Gets the specified property of this context_impl.
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.
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
bool has_property() const noexcept
Checks if this context_impl has a property of type propertyT.
PlatformImplPtr getPlatformImpl() const
bool is_host() const
Checks if this context is a host context.
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:223
Objects of the property_list class are containers for the SYCL properties.
bool has_property() const noexcept
::pi_context PiContext
Definition: pi.hpp:135
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
void GetCapabilitiesIntersectionSet(const std::vector< sycl::device > &Devices, std::vector< T > &CapabilityList)
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:48
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:217
C++ wrapper of extern "C" PI interfaces.
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324