DPC++ Runtime
Runtime libraries for oneAPI DPC++
context_impl.cpp
Go to the documentation of this file.
1 //==---------------- context_impl.cpp - 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 
11 #include <CL/sycl/detail/pi.hpp>
12 #include <CL/sycl/device.hpp>
13 #include <CL/sycl/exception.hpp>
16 #include <CL/sycl/platform.hpp>
19 #include <CL/sycl/stl.hpp>
20 #include <detail/context_impl.hpp>
21 #include <detail/context_info.hpp>
22 #include <detail/platform_impl.hpp>
23 
25 namespace sycl {
26 namespace detail {
27 
28 context_impl::context_impl(const device &Device, async_handler AsyncHandler,
29  const property_list &PropList)
30  : MAsyncHandler(AsyncHandler), MDevices(1, Device), MContext(nullptr),
31  MPlatform(), MPropList(PropList), MHostContext(Device.is_host()),
32  MSupportBufferLocationByDevices(NotChecked) {
33  MKernelProgramCache.setContextPtr(this);
34 }
35 
36 context_impl::context_impl(const std::vector<cl::sycl::device> Devices,
37  async_handler AsyncHandler,
38  const property_list &PropList)
39  : MAsyncHandler(AsyncHandler), MDevices(Devices), MContext(nullptr),
40  MPlatform(), MPropList(PropList), MHostContext(false),
41  MSupportBufferLocationByDevices(NotChecked) {
42  MPlatform = detail::getSyclObjImpl(MDevices[0].get_platform());
43  std::vector<RT::PiDevice> DeviceIds;
44  for (const auto &D : MDevices) {
45  DeviceIds.push_back(getSyclObjImpl(D)->getHandleRef());
46  }
47 
48  const auto Backend = getPlugin().getBackend();
49  if (Backend == backend::ext_oneapi_cuda) {
50  const bool UseCUDAPrimaryContext = MPropList.has_property<
52  const pi_context_properties Props[] = {
53  static_cast<pi_context_properties>(
55  static_cast<pi_context_properties>(UseCUDAPrimaryContext), 0};
56 
58  Props, DeviceIds.size(), DeviceIds.data(), nullptr, nullptr, &MContext);
59  } else {
60  getPlugin().call<PiApiKind::piContextCreate>(nullptr, DeviceIds.size(),
61  DeviceIds.data(), nullptr,
62  nullptr, &MContext);
63  }
64 
65  MKernelProgramCache.setContextPtr(this);
66 }
67 
69  const plugin &Plugin)
70  : MAsyncHandler(AsyncHandler), MDevices(), MContext(PiContext), MPlatform(),
71  MHostContext(false), MSupportBufferLocationByDevices(NotChecked) {
72 
73  std::vector<RT::PiDevice> DeviceIds;
74  size_t DevicesNum = 0;
75  // TODO catch an exception and put it to list of asynchronous exceptions
77  MContext, PI_CONTEXT_INFO_NUM_DEVICES, sizeof(DevicesNum), &DevicesNum,
78  nullptr);
79  DeviceIds.resize(DevicesNum);
80  // TODO catch an exception and put it to list of asynchronous exceptions
82  sizeof(RT::PiDevice) * DevicesNum,
83  &DeviceIds[0], nullptr);
84 
85  if (!DeviceIds.empty()) {
86  std::shared_ptr<detail::platform_impl> Platform =
87  platform_impl::getPlatformFromPiDevice(DeviceIds[0], Plugin);
88  for (RT::PiDevice Dev : DeviceIds) {
89  MDevices.emplace_back(createSyclObjFromImpl<device>(
90  Platform->getOrMakeDeviceImpl(Dev, Platform)));
91  }
92  MPlatform = Platform;
93  }
94  // TODO catch an exception and put it to list of asynchronous exceptions
95  // getPlugin() will be the same as the Plugin passed. This should be taken
96  // care of when creating device object.
97  //
98  // TODO: Move this backend-specific retain of the context to SYCL-2020 style
99  // make_context<backend::opencl> interop, when that is created.
100  if (getPlugin().getBackend() == cl::sycl::backend::opencl) {
102  }
103  MKernelProgramCache.setContextPtr(this);
104 }
105 
106 cl_context context_impl::get() const {
107  if (MHostContext) {
108  throw invalid_object_error(
109  "This instance of context doesn't support OpenCL interoperability.",
111  }
112  // TODO catch an exception and put it to list of asynchronous exceptions
114  return pi::cast<cl_context>(MContext);
115 }
116 
117 bool context_impl::is_host() const { return MHostContext; }
118 
120  for (auto LibProg : MCachedLibPrograms) {
121  assert(LibProg.second && "Null program must not be kept in the cache");
122  getPlugin().call<PiApiKind::piProgramRelease>(LibProg.second);
123  }
124  if (!MHostContext) {
125  // TODO catch an exception and put it to list of asynchronous exceptions
127  }
128 }
129 
131  return MAsyncHandler;
132 }
133 
134 template <>
135 cl_uint context_impl::get_info<info::context::reference_count>() const {
136  if (is_host())
137  return 0;
139  this->getHandleRef(), this->getPlugin());
140 }
141 template <> platform context_impl::get_info<info::context::platform>() const {
142  if (is_host())
143  return platform();
144  return createSyclObjFromImpl<platform>(MPlatform);
145 }
146 template <>
147 std::vector<cl::sycl::device>
148 context_impl::get_info<info::context::devices>() const {
149  return MDevices;
150 }
151 template <>
152 std::vector<cl::sycl::memory_order>
153 context_impl::get_info<info::context::atomic_memory_order_capabilities>()
154  const {
155  if (is_host())
159 
162  MContext,
163  pi::cast<pi_context_info>(
165  sizeof(Result), &Result, nullptr);
166  return readMemoryOrderBitfield(Result);
167 }
168 template <>
169 std::vector<cl::sycl::memory_scope>
170 context_impl::get_info<info::context::atomic_memory_scope_capabilities>()
171  const {
172  if (is_host())
177 
180  MContext,
181  pi::cast<pi_context_info>(
183  sizeof(Result), &Result, nullptr);
184  return readMemoryScopeBitfield(Result);
185 }
186 
188 const RT::PiContext &context_impl::getHandleRef() const { return MContext; }
189 
191  return MKernelProgramCache;
192 }
193 
195  std::shared_ptr<detail::device_impl> Device) const {
196  for (auto D : MDevices)
197  if (getSyclObjImpl(D) == Device)
198  return true;
199  return false;
200 }
201 
203  auto Plugin = getPlugin();
204  if (Plugin.getBackend() == backend::opencl)
206  pi_native_handle Handle;
207  Plugin.call<PiApiKind::piextContextGetNativeHandle>(getHandleRef(), &Handle);
208  return Handle;
209 }
210 
212  if (MSupportBufferLocationByDevices != NotChecked)
213  return MSupportBufferLocationByDevices == Supported ? true : false;
214  // Check that devices within context have support of buffer location
215  MSupportBufferLocationByDevices = Supported;
216  for (auto &Device : MDevices) {
217  if (!Device.has_extension("cl_intel_mem_alloc_buffer_location")) {
218  MSupportBufferLocationByDevices = NotSupported;
219  break;
220  }
221  }
222  return MSupportBufferLocationByDevices == Supported ? true : false;
223 }
224 
225 } // namespace detail
226 } // namespace sycl
227 } // __SYCL_INLINE_NAMESPACE(cl)
property_list.hpp
cl::sycl::detail::context_impl::NotSupported
@ NotSupported
Definition: context_impl.hpp:176
context_impl.hpp
cl::sycl::info::context::atomic_memory_order_capabilities
@ atomic_memory_order_capabilities
cl::sycl::ext::oneapi::cuda::property::context::use_primary_context
Definition: context_properties.hpp:22
cl::sycl::detail::KernelProgramCache
Definition: kernel_program_cache.hpp:31
cl::sycl::backend::opencl
@ opencl
cl::sycl::detail::getPlugin
static const plugin & getPlugin(backend Backend)
Definition: backend.cpp:32
stl.hpp
device.hpp
cl::sycl::detail::pi::PiDevice
::pi_device PiDevice
Definition: pi.hpp:102
cl::sycl::memory_scope::sub_group
@ sub_group
pi_context_properties
intptr_t pi_context_properties
Definition: pi.h:541
context_properties.hpp
cl::sycl::property_list::has_property
bool has_property() const
Definition: property_list.hpp:50
piContextGetInfo
pi_result piContextGetInfo(pi_context context, pi_context_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
Definition: pi_esimd_emulator.cpp:858
cuda_definitions.hpp
cl::sycl::detail::get_context_info::get
static RetType get(RT::PiContext ctx, const plugin &Plugin)
Definition: context_info.hpp:23
sycl
Definition: invoke_simd.hpp:68
cl::sycl::property_list
Objects of the property_list class are containers for the SYCL properties.
Definition: property_list.hpp:26
PI_CONTEXT_INFO_NUM_DEVICES
@ PI_CONTEXT_INFO_NUM_DEVICES
Definition: pi.h:342
cl::sycl::detail::pi::PiContext
::pi_context PiContext
Definition: pi.hpp:106
pi.hpp
cl::sycl::memory_order::acq_rel
@ acq_rel
cl::sycl::memory_order::acquire
@ acquire
PI_CONTEXT_INFO_DEVICES
@ PI_CONTEXT_INFO_DEVICES
Definition: pi.h:341
cl::sycl::detail::platform_impl::getPlatformFromPiDevice
static std::shared_ptr< platform_impl > getPlatformFromPiDevice(RT::PiDevice PiDevice, const plugin &Plugin)
Queries the cache for the specified platform based on an input device.
Definition: platform_impl.cpp:60
cl::sycl::detail::plugin::getBackend
backend getBackend(void) const
Definition: plugin.hpp:229
cl::sycl::detail::context_impl::hasDevice
bool hasDevice(std::shared_ptr< detail::device_impl > Device) const
Returns true if and only if context contains the given device.
Definition: context_impl.cpp:194
piContextRelease
pi_result piContextRelease(pi_context context)
Definition: pi_esimd_emulator.cpp:888
piProgramRelease
pi_result piProgramRelease(pi_program program)
Definition: pi_esimd_emulator.cpp:1338
platform_impl.hpp
cl::sycl::device
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:35
cl::sycl::memory_scope::system
@ system
cl::sycl::detail::context_impl::~context_impl
~context_impl()
Definition: context_impl.cpp:119
cl::sycl::detail::context_impl::NotChecked
@ NotChecked
Definition: context_impl.hpp:176
cl::sycl::detail::plugin::call
void call(ArgsT... Args) const
Calls the API, traces the call, checks the result.
Definition: plugin.hpp:217
cl::sycl::memory_scope::work_item
@ work_item
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
cl::sycl::detail::readMemoryOrderBitfield
std::vector< memory_order > readMemoryOrderBitfield(pi_memory_order_capabilities bits)
Definition: memory_enums.hpp:51
cl::sycl::detail::context_impl::Supported
@ Supported
Definition: context_impl.hpp:176
cl::sycl::memory_order::seq_cst
@ seq_cst
cl::sycl::detail::context_impl::context_impl
context_impl(const device &Device, async_handler AsyncHandler, const property_list &PropList)
Constructs a context_impl using a single SYCL devices.
Definition: context_impl.cpp:28
pi_memory_scope_capabilities
pi_bitfield pi_memory_scope_capabilities
Definition: pi.h:564
cl::sycl::detail::context_impl::get_async_handler
const async_handler & get_async_handler() const
Gets asynchronous exception handler.
Definition: context_impl.cpp:130
cl::sycl::detail::plugin
The plugin class provides a unified interface to the underlying low-level runtimes for the device-agn...
Definition: plugin.hpp:90
pi_native_handle
uintptr_t pi_native_handle
Definition: pi.h:76
piContextRetain
pi_result piContextRetain(pi_context context)
Definition: pi_esimd_emulator.cpp:878
cl::sycl::memory_order::relaxed
@ relaxed
PI_INVALID_CONTEXT
@ PI_INVALID_CONTEXT
Definition: pi.h:92
cl::sycl::backend::ext_oneapi_cuda
@ ext_oneapi_cuda
cl::sycl::detail::context_impl::get
cl_context get() const
Gets OpenCL interoperability context handle.
Definition: context_impl.cpp:106
cl::sycl::detail::getSyclObjImpl
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: common.hpp:198
platform.hpp
cl::sycl::detail::context_impl::getNative
pi_native_handle getNative() const
Gets the native handle of the SYCL context.
Definition: context_impl.cpp:202
piContextCreate
pi_result piContextCreate(const pi_context_properties *properties, pi_uint32 num_devices, const pi_device *devices, void(*pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, pi_context *ret_context)
exception.hpp
cl::sycl::platform
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:34
cl::sycl::detail::context_impl::is_host
bool is_host() const
Checks if this context is a host context.
Definition: context_impl.cpp:117
context_info.hpp
cl::sycl::cl_uint
std::uint32_t cl_uint
Definition: aliases.hpp:83
cl::sycl::detail::context_impl::isBufferLocationSupported
bool isBufferLocationSupported() const
Definition: context_impl.cpp:211
exception_list.hpp
cl::sycl::memory_scope::work_group
@ work_group
info_desc.hpp
cl::sycl::detail::context_impl::getPlugin
const plugin & getPlugin() const
Definition: context_impl.hpp:107
common.hpp
cl::sycl::memory_order::release
@ release
piextContextGetNativeHandle
pi_result piextContextGetNativeHandle(pi_context context, pi_native_handle *nativeHandle)
Gets the native handle of a PI context object.
Definition: pi_esimd_emulator.cpp:868
cl::sycl::info::context::atomic_memory_scope_capabilities
@ atomic_memory_scope_capabilities
cl::sycl::detail::readMemoryScopeBitfield
std::vector< memory_scope > readMemoryScopeBitfield(pi_memory_scope_capabilities bits)
Definition: memory_enums.hpp:67
pi_memory_order_capabilities
pi_bitfield pi_memory_order_capabilities
Definition: pi.h:557
cl::sycl::async_handler
std::function< void(cl::sycl::exception_list)> async_handler
Definition: exception_list.hpp:53
cl::sycl::detail::context_impl::getHandleRef
RT::PiContext & getHandleRef()
Gets the underlying context object (if any) without reference count modification.
Definition: context_impl.cpp:187
__SYCL_PI_CONTEXT_PROPERTIES_CUDA_PRIMARY
#define __SYCL_PI_CONTEXT_PROPERTIES_CUDA_PRIMARY
Definition: cuda_definitions.hpp:19
_pi_context
PI context mapping to a CUDA context object.
Definition: pi_cuda.hpp:150
_pi_device
PI device mapping to a CUdevice.
Definition: pi_cuda.hpp:73
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12
cl::sycl::memory_scope::device
@ device
cl::sycl::detail::context_impl::getKernelProgramCache
KernelProgramCache & getKernelProgramCache() const
Definition: context_impl.cpp:190
cl::sycl::detail::KernelProgramCache::setContextPtr
void setContextPtr(const ContextPtr &AContext)
Definition: kernel_program_cache.hpp:94