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 
130 
140 
143  const std::vector<device> &getDevices() const { return MDevices; }
144 
146  std::map<std::pair<DeviceLibExt, sycl::detail::pi::PiDevice>,
148 
163  return {MCachedLibPrograms, MCachedLibProgramsMutex};
164  }
165 
167 
169  bool hasDevice(std::shared_ptr<detail::device_impl> Device) const;
170 
176  // OpenCL does not support using descendants of context members within that
177  // context yet.
178  // TODO remove once this limitation is lifted
179  if (!is_host() && Device->getBackend() == backend::opencl)
180  return hasDevice(Device);
181 
182  while (!hasDevice(Device)) {
183  if (Device->isRootDevice())
184  return false;
185  Device = detail::getSyclObjImpl(
186  Device->get_info<info::device::parent_device>());
187  }
188 
189  return true;
190  }
191 
192  // Returns the backend of this context
193  backend getBackend() const {
194  assert(MPlatform && "MPlatform must be not null");
195  return MPlatform->getBackend();
196  }
197 
202 
206  pi_native_handle getNative() const;
207 
208  // Returns true if buffer_location property is supported by devices
209  bool isBufferLocationSupported() const;
210 
212  void addAssociatedDeviceGlobal(const void *DeviceGlobalPtr);
213 
216  const std::vector<device> &Devs,
217  const RTDeviceBinaryImage *BinImage);
218 
220  std::vector<sycl::detail::pi::PiEvent>
222  const std::shared_ptr<queue_impl> &QueueImpl);
223 
225  const std::shared_ptr<device_impl> &DeviceImpl,
226  const void *DeviceGlobalPtr, const void *Src, size_t DeviceGlobalTSize,
227  bool IsDeviceImageScoped, size_t NumBytes, size_t Offset);
228 
229  void
230  memcpyFromHostOnlyDeviceGlobal(const std::shared_ptr<device_impl> &DeviceImpl,
231  void *Dest, const void *DeviceGlobalPtr,
232  bool IsDeviceImageScoped, size_t NumBytes,
233  size_t Offset);
234 
236  std::optional<sycl::detail::pi::PiProgram>
237  getProgramForDeviceGlobal(const device &Device,
238  DeviceGlobalMapEntry *DeviceGlobalEntry);
240  std::optional<sycl::detail::pi::PiProgram>
241  getProgramForHostPipe(const device &Device, HostPipeMapEntry *HostPipeEntry);
242 
244  std::optional<sycl::detail::pi::PiProgram>
245  getProgramForDevImgs(const device &Device,
246  const std::set<std::uintptr_t> &ImgIdentifiers,
247  const std::string &ObjectTypeName);
248 
249  bool isOwnedByRuntime() { return MOwnedByRuntime; };
250 
252 
253 private:
254  bool MOwnedByRuntime;
255  async_handler MAsyncHandler;
256  std::vector<device> MDevices;
258  PlatformImplPtr MPlatform;
259  property_list MPropList;
260  bool MHostContext;
261  CachedLibProgramsT MCachedLibPrograms;
262  std::mutex MCachedLibProgramsMutex;
263  mutable KernelProgramCache MKernelProgramCache;
264  mutable PropertySupport MSupportBufferLocationByDevices;
265 
266  std::set<const void *> MAssociatedDeviceGlobals;
267  std::mutex MAssociatedDeviceGlobalsMutex;
268 
269  struct DeviceGlobalInitializer {
270  DeviceGlobalInitializer() = default;
271  DeviceGlobalInitializer(const RTDeviceBinaryImage *BinImage)
272  : MBinImage(BinImage) {
273  // If there are no device globals, they are trivially fully initialized.
274  // Note: Lock is not needed during construction.
275  MDeviceGlobalsFullyInitialized = BinImage->getDeviceGlobals().size() == 0;
276  }
277 
279  void ClearEvents(const PluginPtr &Plugin);
280 
282  const RTDeviceBinaryImage *MBinImage = nullptr;
283 
285  std::mutex MDeviceGlobalInitMutex;
286 
294  bool MDeviceGlobalsFullyInitialized = false;
295 
298  std::vector<sycl::detail::pi::PiEvent> MDeviceGlobalInitEvents;
299  };
300 
301  std::map<std::pair<sycl::detail::pi::PiProgram, sycl::detail::pi::PiDevice>,
302  DeviceGlobalInitializer>
303  MDeviceGlobalInitializers;
304  std::mutex MDeviceGlobalInitializersMutex;
305 
306  // For device_global variables that are not used in any kernel code we still
307  // allow copy operations on them. MDeviceGlobalUnregisteredData stores the
308  // associated writes.
309  // The key to this map is a combination of a the pointer to the device_global
310  // and optionally a device if the device_global has device image scope.
311  std::map<std::pair<const void *, std::optional<sycl::detail::pi::PiDevice>>,
312  std::unique_ptr<std::byte[]>>
313  MDeviceGlobalUnregisteredData;
314  std::mutex MDeviceGlobalUnregisteredDataMutex;
315 };
316 
317 template <typename T, typename Capabilities>
318 void GetCapabilitiesIntersectionSet(const std::vector<sycl::device> &Devices,
319  std::vector<T> &CapabilityList) {
320  for (const sycl::device &Device : Devices) {
321  std::vector<T> NewCapabilityList;
322  std::vector<T> DeviceCapabilities = Device.get_info<Capabilities>();
323  std::set_intersection(
324  CapabilityList.begin(), CapabilityList.end(),
325  DeviceCapabilities.begin(), DeviceCapabilities.end(),
326  std::inserter(NewCapabilityList, NewCapabilityList.begin()));
327  CapabilityList = NewCapabilityList;
328  }
329  CapabilityList.shrink_to_fit();
330 }
331 
332 } // namespace detail
333 } // namespace _V1
334 } // 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.
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:65
detail::ABINeutralT_t< typename 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.cpp:140
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::string string
Definition: handler.hpp:423
std::function< void(sycl::exception_list)> async_handler
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:206
C++ wrapper of extern "C" PI interfaces.
_Abi const simd< _Tp, _Abi > & noexcept
Definition: simd.hpp:1324