DPC++ Runtime
Runtime libraries for oneAPI DPC++
platform_impl.cpp
Go to the documentation of this file.
1 //==----------- platform_impl.cpp ------------------------------------------==//
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 #include <detail/allowlist.hpp>
10 #include <detail/config.hpp>
11 #include <detail/device_impl.hpp>
13 #include <detail/platform_impl.hpp>
14 #include <detail/platform_info.hpp>
15 #include <sycl/backend.hpp>
17 #include <sycl/detail/util.hpp>
18 #include <sycl/device.hpp>
19 
20 #include <algorithm>
21 #include <cstring>
22 #include <mutex>
23 #include <string>
24 #include <unordered_set>
25 #include <vector>
26 
27 namespace sycl {
28 inline namespace _V1 {
29 namespace detail {
30 
31 using PlatformImplPtr = std::shared_ptr<platform_impl>;
32 
34  static PlatformImplPtr HostImpl = std::make_shared<platform_impl>();
35 
36  return HostImpl;
37 }
38 
41  const PluginPtr &Plugin) {
42  PlatformImplPtr Result;
43  {
44  const std::lock_guard<std::mutex> Guard(
45  GlobalHandler::instance().getPlatformMapMutex());
46 
47  std::vector<PlatformImplPtr> &PlatformCache =
49 
50  // If we've already seen this platform, return the impl
51  for (const auto &PlatImpl : PlatformCache) {
52  if (PlatImpl->getHandleRef() == PiPlatform)
53  return PlatImpl;
54  }
55 
56  // Otherwise make the impl
57  Result = std::make_shared<platform_impl>(PiPlatform, Plugin);
58  PlatformCache.emplace_back(Result);
59  }
60 
61  return Result;
62 }
63 
66  const PluginPtr &Plugin) {
68  nullptr; // TODO catch an exception and put it to list
69  // of asynchronous exceptions
71  sizeof(Plt), &Plt, nullptr);
72  return getOrMakePlatformImpl(Plt, Plugin);
73 }
74 
75 static bool IsBannedPlatform(platform Platform) {
76  // The NVIDIA OpenCL platform is currently not compatible with DPC++
77  // since it is only 1.2 but gets selected by default in many systems
78  // There is also no support on the PTX backend for OpenCL consumption,
79  // and there have been some internal reports.
80  // To avoid problems on default users and deployment of DPC++ on platforms
81  // where CUDA is available, the OpenCL support is disabled.
82  //
83  // There is also no support for the AMD HSA backend for OpenCL consumption,
84  // as well as reported problems with device queries, so AMD OpenCL support
85  // is disabled as well.
86  //
87  auto IsMatchingOpenCL = [](platform Platform, const std::string_view name) {
88  if (getSyclObjImpl(Platform)->is_host())
89  return false;
90 
91  const bool HasNameMatch = Platform.get_info<info::platform::name>().find(
92  name) != std::string::npos;
93  const auto Backend = detail::getSyclObjImpl(Platform)->getBackend();
94  const bool IsMatchingOCL = (HasNameMatch && Backend == backend::opencl);
96  IsMatchingOCL) {
97  std::cout << "SYCL_PI_TRACE[all]: " << name
98  << " OpenCL platform found but is not compatible." << std::endl;
99  }
100  return IsMatchingOCL;
101  };
102  return IsMatchingOpenCL(Platform, "NVIDIA CUDA") ||
103  IsMatchingOpenCL(Platform, "AMD Accelerated Parallel Processing");
104 }
105 
106 // This routine has the side effect of registering each platform's last device
107 // id into each plugin, which is used for device counting.
108 std::vector<platform> platform_impl::get_platforms() {
109 
110  // Get the vector of platforms supported by a given PI plugin
111  auto getPluginPlatforms = [](PluginPtr &Plugin) {
112  std::vector<platform> Platforms;
113  pi_uint32 NumPlatforms = 0;
114  if (Plugin->call_nocheck<PiApiKind::piPlatformsGet>(
115  0, nullptr, &NumPlatforms) != PI_SUCCESS)
116  return Platforms;
117 
118  if (NumPlatforms) {
119  std::vector<sycl::detail::pi::PiPlatform> PiPlatforms(NumPlatforms);
120  if (Plugin->call_nocheck<PiApiKind::piPlatformsGet>(
121  NumPlatforms, PiPlatforms.data(), nullptr) != PI_SUCCESS)
122  return Platforms;
123 
124  for (const auto &PiPlatform : PiPlatforms) {
125  platform Platform = detail::createSyclObjFromImpl<platform>(
127  if (IsBannedPlatform(Platform)) {
128  continue; // bail as early as possible, otherwise banned platforms may
129  // mess up device counting
130  }
131 
132  // The SYCL spec says that a platform has one or more devices. ( SYCL
133  // 2020 4.6.2 ) If we have an empty platform, we don't report it back
134  // from platform::get_platforms().
135  if (!Platform.get_devices(info::device_type::all).empty()) {
136  Platforms.push_back(Platform);
137  }
138  }
139  }
140  return Platforms;
141  };
142 
143  static const bool PreferUR = [] {
144  const char *PreferURStr = std::getenv("SYCL_PREFER_UR");
145  return (PreferURStr && (std::stoi(PreferURStr) != 0));
146  }();
147 
148  // See which platform we want to be served by which plugin.
149  // There should be just one plugin serving each backend.
150  std::vector<PluginPtr> &Plugins = sycl::detail::pi::initialize();
151  std::vector<std::pair<platform, PluginPtr>> PlatformsWithPlugin;
152 
153  // First check Unified Runtime
154  // Keep track of backends covered by UR
155  std::unordered_set<backend> BackendsUR;
156  if (PreferUR) {
157  PluginPtr *PluginUR = nullptr;
158  for (PluginPtr &Plugin : Plugins) {
159  if (Plugin->hasBackend(backend::all)) { // this denotes UR
160  PluginUR = &Plugin;
161  break;
162  }
163  }
164  if (PluginUR) {
165  for (const auto &P : getPluginPlatforms(*PluginUR)) {
166  PlatformsWithPlugin.push_back({P, *PluginUR});
167  BackendsUR.insert(getSyclObjImpl(P)->getBackend());
168  }
169  }
170  }
171 
172  // Then check backend-specific plugins
173  for (auto &Plugin : Plugins) {
174  if (Plugin->hasBackend(backend::all)) {
175  continue; // skip UR on this pass
176  }
177  const auto &PluginPlatforms = getPluginPlatforms(Plugin);
178  for (const auto &P : PluginPlatforms) {
179  // Only add those not already covered by UR
180  if (BackendsUR.find(getSyclObjImpl(P)->getBackend()) ==
181  BackendsUR.end()) {
182  PlatformsWithPlugin.push_back({P, Plugin});
183  }
184  }
185  }
186 
187  // For the selected platforms register them with their plugins
188  std::vector<platform> Platforms;
189  for (auto &Platform : PlatformsWithPlugin) {
190  auto &Plugin = Platform.second;
191  std::lock_guard<std::mutex> Guard(*Plugin->getPluginMutex());
192  Plugin->getPlatformId(getSyclObjImpl(Platform.first)->getHandleRef());
193  Platforms.push_back(Platform.first);
194  }
195 
196  // Register default context release handler after plugins have been loaded and
197  // after the first calls to each plugin. This initializes a function-local
198  // variable that should be destroyed before any global variables in the
199  // plugins are destroyed. This is done after the first call to the backends to
200  // ensure any lazy-loaded dependencies are loaded prior to the handler
201  // variable's initialization. Note: The default context release handler is not
202  // guaranteed to be destroyed before function-local static variables as they
203  // may be initialized after.
205 
206  return Platforms;
207 }
208 
209 // Since ONEAPI_DEVICE_SELECTOR admits negative filters, we use type traits
210 // to distinguish the case where we are working with ONEAPI_DEVICE_SELECTOR
211 // in the places where the functionality diverges between these two
212 // environment variables.
213 // The return value is a vector that represents the indices of the chosen
214 // devices.
215 template <typename ListT, typename FilterT>
216 std::vector<int> platform_impl::filterDeviceFilter(
217  std::vector<sycl::detail::pi::PiDevice> &PiDevices,
218  ListT *FilterList) const {
219 
220  constexpr bool is_ods_target = std::is_same_v<FilterT, ods_target>;
221 
222  if constexpr (is_ods_target) {
223 
224  // Since we are working with ods_target filters ,which can be negative,
225  // we sort the filters so that all the negative filters appear before
226  // all the positive filters. This enables us to have the full list of
227  // blacklisted devices by the time we get to the positive filters
228  // so that if a positive filter matches a blacklisted device we do
229  // not add it to the list of available devices.
230  std::sort(FilterList->get().begin(), FilterList->get().end(),
231  [](const ods_target &filter1, const ods_target &filter2) {
232  return filter1.IsNegativeTarget && !filter2.IsNegativeTarget;
233  });
234  }
235 
236  // this map keeps track of devices discarded by negative filters, it is only
237  // used in the ONEAPI_DEVICE_SELECTOR implemenation. It cannot be placed
238  // in the if statement above because it will then be out of scope in the rest
239  // of the function
240  std::map<int, bool> Blacklist;
241  // original indices keeps track of the device numbers of the chosen
242  // devices and is whats returned by the function
243  std::vector<int> original_indices;
244 
245  // Find out backend of the platform
247  MPlugin->call<PiApiKind::piPlatformGetInfo>(
248  MPlatform, PI_EXT_PLATFORM_INFO_BACKEND,
249  sizeof(sycl::detail::pi::PiPlatformBackend), &PiBackend, nullptr);
250  backend Backend = convertBackend(PiBackend);
251 
252  int InsertIDx = 0;
253  // DeviceIds should be given consecutive numbers across platforms in the same
254  // backend
255  std::lock_guard<std::mutex> Guard(*MPlugin->getPluginMutex());
256  int DeviceNum = MPlugin->getStartingDeviceId(MPlatform);
257  for (sycl::detail::pi::PiDevice Device : PiDevices) {
259  MPlugin->call<PiApiKind::piDeviceGetInfo>(
261  &PiDevType, nullptr);
262  // Assumption here is that there is 1-to-1 mapping between PiDevType and
263  // Sycl device type for GPU, CPU, and ACC.
264  info::device_type DeviceType = pi::cast<info::device_type>(PiDevType);
265 
266  for (const FilterT &Filter : FilterList->get()) {
267  backend FilterBackend = Filter.Backend.value_or(backend::all);
268  // First, match the backend entry.
269  if (FilterBackend != Backend && FilterBackend != backend::all)
270  continue;
271  info::device_type FilterDevType =
272  Filter.DeviceType.value_or(info::device_type::all);
273 
274  // Match the device_num entry.
275  if (Filter.DeviceNum && DeviceNum != Filter.DeviceNum.value())
276  continue;
277 
278  if (FilterDevType != info::device_type::all &&
279  FilterDevType != DeviceType)
280  continue;
281 
282  if constexpr (is_ods_target) {
283  // Dealing with ONEAPI_DEVICE_SELECTOR - check for negative filters.
284  if (Blacklist[DeviceNum]) // already blacklisted.
285  break;
286 
287  if (Filter.IsNegativeTarget) {
288  // Filter is negative and the device matches the filter so
289  // blacklist the device now.
290  Blacklist[DeviceNum] = true;
291  break;
292  }
293  }
294 
295  PiDevices[InsertIDx++] = Device;
296  original_indices.push_back(DeviceNum);
297  break;
298  }
299  DeviceNum++;
300  }
301  PiDevices.resize(InsertIDx);
302  // remember the last backend that has gone through this filter function
303  // to assign a unique device id number across platforms that belong to
304  // the same backend. For example, opencl:cpu:0, opencl:acc:1, opencl:gpu:2
305  MPlugin->setLastDeviceId(MPlatform, DeviceNum);
306  return original_indices;
307 }
308 
309 std::shared_ptr<device_impl>
311  const std::lock_guard<std::mutex> Guard(MDeviceMapMutex);
312  return getDeviceImplHelper(PiDevice);
313 }
314 
315 std::shared_ptr<device_impl> platform_impl::getOrMakeDeviceImpl(
317  const std::shared_ptr<platform_impl> &PlatformImpl) {
318  const std::lock_guard<std::mutex> Guard(MDeviceMapMutex);
319  // If we've already seen this device, return the impl
320  std::shared_ptr<device_impl> Result = getDeviceImplHelper(PiDevice);
321  if (Result)
322  return Result;
323 
324  // Otherwise make the impl
325  Result = std::make_shared<device_impl>(PiDevice, PlatformImpl);
326  MDeviceCache.emplace_back(Result);
327 
328  return Result;
329 }
330 
331 static bool supportsAffinityDomain(const device &dev,
332  info::partition_property partitionProp,
335  return true;
336  }
337  auto supported = dev.get_info<info::device::partition_affinity_domains>();
338  auto It = std::find(std::begin(supported), std::end(supported), domain);
339  return It != std::end(supported);
340 }
341 
342 static bool supportsPartitionProperty(const device &dev,
343  info::partition_property partitionProp) {
344  auto supported = dev.get_info<info::device::partition_properties>();
345  auto It =
346  std::find(std::begin(supported), std::end(supported), partitionProp);
347  return It != std::end(supported);
348 }
349 
350 static std::vector<device> amendDeviceAndSubDevices(
351  backend PlatformBackend, std::vector<device> &DeviceList,
352  ods_target_list *OdsTargetList, const std::vector<int> &original_indices,
353  PlatformImplPtr PlatformImpl) {
354  constexpr info::partition_property partitionProperty =
356  constexpr info::partition_affinity_domain affinityDomain =
358 
359  std::vector<device> FinalResult;
360  // (Only) when amending sub-devices for ONEAPI_DEVICE_SELECTOR, all
361  // sub-devices are treated as root.
362  TempAssignGuard<bool> TAG(PlatformImpl->MAlwaysRootDevice, true);
363 
364  for (unsigned i = 0; i < DeviceList.size(); i++) {
365  // device has already been screened. The question is whether it should be a
366  // top level device and/or is expected to add its sub-devices to the list.
367  device &dev = DeviceList[i];
368  bool deviceAdded = false;
369  for (ods_target target : OdsTargetList->get()) {
370  backend TargetBackend = target.Backend.value_or(backend::all);
371  if (PlatformBackend != TargetBackend && TargetBackend != backend::all)
372  continue;
373 
374  bool deviceMatch = target.HasDeviceWildCard; // opencl:*
375  if (target.DeviceType) { // opencl:gpu
376  deviceMatch =
377  ((target.DeviceType == info::device_type::all) ||
378  (dev.get_info<info::device::device_type>() == target.DeviceType));
379 
380  } else if (target.DeviceNum) { // opencl:0
381  deviceMatch = (target.DeviceNum.value() == original_indices[i]);
382  }
383 
384  if (!deviceMatch)
385  continue;
386 
387  // Top level matches. Do we add it, or subdevices, or sub-sub-devices?
388  bool wantSubDevice = target.SubDeviceNum || target.HasSubDeviceWildCard;
389  bool supportsSubPartitioning =
390  (supportsPartitionProperty(dev, partitionProperty) &&
391  supportsAffinityDomain(dev, partitionProperty, affinityDomain));
392  bool wantSubSubDevice =
393  target.SubSubDeviceNum || target.HasSubSubDeviceWildCard;
394 
395  if (!wantSubDevice) {
396  // -- Add top level device only.
397  if (!deviceAdded) {
398  FinalResult.push_back(dev);
399  deviceAdded = true;
400  }
401  continue;
402  }
403 
404  if (!supportsSubPartitioning) {
405  if (target.DeviceNum ||
406  (target.DeviceType &&
407  (target.DeviceType.value() != info::device_type::all))) {
408  // This device was specifically requested and yet is not
409  // partitionable.
410  std::cout << "device is not partitionable: " << target << std::endl;
411  }
412  continue;
413  }
414 
415  auto subDevices = dev.create_sub_devices<
417  affinityDomain);
418  if (target.SubDeviceNum) {
419  if (subDevices.size() <= target.SubDeviceNum.value()) {
420  std::cout << "subdevice index out of bounds: " << target << std::endl;
421  continue;
422  }
423  subDevices[0] = subDevices[target.SubDeviceNum.value()];
424  subDevices.resize(1);
425  }
426 
427  if (!wantSubSubDevice) {
428  // -- Add sub device(s) only.
429  FinalResult.insert(FinalResult.end(), subDevices.begin(),
430  subDevices.end());
431  continue;
432  }
433 
434  // -- Add sub sub device(s).
435  for (device subDev : subDevices) {
436  bool supportsSubSubPartitioning =
437  (supportsPartitionProperty(subDev, partitionProperty) &&
438  supportsAffinityDomain(subDev, partitionProperty, affinityDomain));
439  if (!supportsSubSubPartitioning) {
440  if (target.SubDeviceNum) {
441  // Parent subdevice was specifically requested, yet is not
442  // partitionable.
443  std::cout << "sub-device is not partitionable: " << target
444  << std::endl;
445  }
446  continue;
447  }
448 
449  // Allright, lets get them sub-sub-devices.
450  auto subSubDevices =
451  subDev.create_sub_devices<partitionProperty>(affinityDomain);
452  if (target.SubSubDeviceNum) {
453  if (subSubDevices.size() <= target.SubSubDeviceNum.value()) {
454  std::cout << "sub-sub-device index out of bounds: " << target
455  << std::endl;
456  continue;
457  }
458  subSubDevices[0] = subSubDevices[target.SubSubDeviceNum.value()];
459  subSubDevices.resize(1);
460  }
461  FinalResult.insert(FinalResult.end(), subSubDevices.begin(),
462  subSubDevices.end());
463  }
464  }
465  }
466  return FinalResult;
467 }
468 
469 std::vector<device>
471  std::vector<device> Res;
472 
474 
475  if (is_host() && (DeviceType == info::device_type::host ||
476  DeviceType == info::device_type::all)) {
477  Res.push_back(
478  createSyclObjFromImpl<device>(device_impl::getHostDeviceImpl()));
479  }
480 
481  // If any DeviceType other than host was requested for host platform,
482  // an empty vector will be returned.
483  if (is_host() || DeviceType == info::device_type::host)
484  return Res;
485 
486  pi_uint32 NumDevices = 0;
487  MPlugin->call<PiApiKind::piDevicesGet>(
488  MPlatform, pi::cast<sycl::detail::pi::PiDeviceType>(DeviceType),
489  0, // CP info::device_type::all
490  pi::cast<sycl::detail::pi::PiDevice *>(nullptr), &NumDevices);
491  const backend Backend = getBackend();
492 
493  if (NumDevices == 0) {
494  // If platform doesn't have devices (even without filter)
495  // LastDeviceIds[PlatformId] stay 0 that affects next platform devices num
496  // analysis. Doing adjustment by simple copy of last device num from
497  // previous platform.
498  // Needs non const plugin reference.
499  std::vector<PluginPtr> &Plugins = sycl::detail::pi::initialize();
500  auto It = std::find_if(Plugins.begin(), Plugins.end(),
501  [&Platform = MPlatform](PluginPtr &Plugin) {
502  return Plugin->containsPiPlatform(Platform);
503  });
504  if (It != Plugins.end()) {
505  PluginPtr &Plugin = *It;
506  std::lock_guard<std::mutex> Guard(*Plugin->getPluginMutex());
507  Plugin->adjustLastDeviceId(MPlatform);
508  }
509  return Res;
510  }
511 
512  std::vector<sycl::detail::pi::PiDevice> PiDevices(NumDevices);
513  // TODO catch an exception and put it to list of asynchronous exceptions
514  MPlugin->call<PiApiKind::piDevicesGet>(
515  MPlatform,
516  pi::cast<sycl::detail::pi::PiDeviceType>(
517  DeviceType), // CP info::device_type::all
518  NumDevices, PiDevices.data(), nullptr);
519 
520  // Some elements of PiDevices vector might be filtered out, so make a copy of
521  // handles to do a cleanup later
522  std::vector<sycl::detail::pi::PiDevice> PiDevicesToCleanUp = PiDevices;
523 
524  // Filter out devices that are not present in the SYCL_DEVICE_ALLOWLIST
526  applyAllowList(PiDevices, MPlatform, MPlugin);
527 
528  // The first step is to filter out devices that are not compatible with
529  // ONEAPI_DEVICE_SELECTOR. This is also the mechanism by which top level
530  // device ids are assigned.
531  std::vector<int> PlatformDeviceIndices;
532  if (OdsTargetList) {
533  PlatformDeviceIndices = filterDeviceFilter<ods_target_list, ods_target>(
534  PiDevices, OdsTargetList);
535  }
536 
537  // The next step is to inflate the filtered PIDevices into SYCL Device
538  // objects.
539  PlatformImplPtr PlatformImpl = getOrMakePlatformImpl(MPlatform, MPlugin);
540  std::transform(
541  PiDevices.begin(), PiDevices.end(), std::back_inserter(Res),
542  [PlatformImpl](const sycl::detail::pi::PiDevice &PiDevice) -> device {
543  return detail::createSyclObjFromImpl<device>(
544  PlatformImpl->getOrMakeDeviceImpl(PiDevice, PlatformImpl));
545  });
546 
547  // The reference counter for handles, that we used to create sycl objects, is
548  // incremented, so we need to call release here.
549  for (sycl::detail::pi::PiDevice &PiDev : PiDevicesToCleanUp)
550  MPlugin->call<PiApiKind::piDeviceRelease>(PiDev);
551 
552  // If we aren't using ONEAPI_DEVICE_SELECTOR, then we are done.
553  // and if there are no devices so far, there won't be any need to replace them
554  // with subdevices.
555  if (!OdsTargetList || Res.size() == 0)
556  return Res;
557 
558  // Otherwise, our last step is to revisit the devices, possibly replacing
559  // them with subdevices (which have been ignored until now)
560  return amendDeviceAndSubDevices(Backend, Res, OdsTargetList,
561  PlatformDeviceIndices, PlatformImpl);
562 }
563 
564 bool platform_impl::has_extension(const std::string &ExtensionName) const {
565  if (is_host())
566  return false;
567 
568  std::string AllExtensionNames = get_platform_info_string_impl(
569  MPlatform, getPlugin(),
571  return (AllExtensionNames.find(ExtensionName) != std::string::npos);
572 }
573 
575  return getBackend() != backend::opencl ||
576  has_extension("cl_intel_unified_shared_memory");
577 }
578 
580  const auto &Plugin = getPlugin();
581  pi_native_handle Handle;
583  &Handle);
584  return Handle;
585 }
586 
587 template <typename Param>
588 typename Param::return_type platform_impl::get_info() const {
589  if (is_host())
590  return get_platform_info_host<Param>();
591 
592  return get_platform_info<Param>(this->getHandleRef(), getPlugin());
593 }
594 
595 template <>
596 typename info::platform::version::return_type
597 platform_impl::get_backend_info<info::platform::version>() const {
598  if (getBackend() != backend::opencl) {
600  "the info::platform::version info descriptor can "
601  "only be queried with an OpenCL backend");
602  }
603  return get_info<info::platform::version>();
604 }
605 
606 device select_device(DSelectorInvocableType DeviceSelectorInvocable,
607  std::vector<device> &Devices);
608 
609 template <>
610 typename info::device::version::return_type
611 platform_impl::get_backend_info<info::device::version>() const {
612  if (getBackend() != backend::opencl) {
614  "the info::device::version info descriptor can only "
615  "be queried with an OpenCL backend");
616  }
617  auto Devices = get_devices();
618  if (Devices.empty()) {
619  return "No available device";
620  }
621  // Use default selector to pick a device.
622  return select_device(default_selector_v, Devices)
623  .get_info<info::device::version>();
624 }
625 
626 template <>
627 typename info::device::backend_version::return_type
628 platform_impl::get_backend_info<info::device::backend_version>() const {
629  if (getBackend() != backend::ext_oneapi_level_zero) {
631  "the info::device::backend_version info descriptor "
632  "can only be queried with a Level Zero backend");
633  }
634  return "";
635  // Currently The Level Zero backend does not define the value of this
636  // information descriptor and implementations are encouraged to return the
637  // empty string as per specification.
638 }
639 
640 // All devices on the platform must have the given aspect.
641 bool platform_impl::has(aspect Aspect) const {
642  for (const auto &dev : get_devices()) {
643  if (dev.has(Aspect) == false) {
644  return false;
645  }
646  }
647  return true;
648 }
649 
650 std::shared_ptr<device_impl>
651 platform_impl::getDeviceImplHelper(sycl::detail::pi::PiDevice PiDevice) {
652  for (const std::weak_ptr<device_impl> &DeviceWP : MDeviceCache) {
653  if (std::shared_ptr<device_impl> Device = DeviceWP.lock()) {
654  if (Device->getHandleRef() == PiDevice)
655  return Device;
656  }
657  }
658  return nullptr;
659 }
660 
661 #define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, PiCode) \
662  template ReturnT platform_impl::get_info<info::platform::Desc>() const;
663 
664 #include <sycl/info/platform_traits.def>
665 #undef __SYCL_PARAM_TRAITS_SPEC
666 
667 } // namespace detail
668 } // namespace _V1
669 } // namespace sycl
static void registerDefaultContextReleaseHandler()
std::vector< PlatformImplPtr > & getPlatformCache()
static GlobalHandler & instance()
static const char * get()
Definition: config.hpp:115
static std::shared_ptr< device_impl > getHostDeviceImpl()
Gets the single instance of the Host Device.
std::vector< ods_target > & get()
pi_native_handle getNative() const
Gets the native handle of the SYCL platform.
static std::shared_ptr< platform_impl > getHostPlatformImpl()
Static functions that help maintain platform uniquess and equality of comparison.
std::shared_ptr< device_impl > getOrMakeDeviceImpl(sycl::detail::pi::PiDevice PiDevice, const std::shared_ptr< platform_impl > &PlatformImpl)
Queries the device_impl cache to either return a shared_ptr for the device_impl corresponding to the ...
static std::shared_ptr< platform_impl > getOrMakePlatformImpl(sycl::detail::pi::PiPlatform PiPlatform, const PluginPtr &Plugin)
Queries the cache to see if the specified PiPlatform has been seen before.
Param::return_type get_info() const
Queries this SYCL platform for info.
static std::vector< platform > get_platforms()
Returns all available SYCL platforms in the system.
backend getBackend(void) const
Returns the backend of this platform.
bool has(aspect Aspect) const
Indicates if all of the SYCL devices on this platform have the given feature.
std::shared_ptr< device_impl > getDeviceImpl(sycl::detail::pi::PiDevice PiDevice)
Queries the device_impl cache to return a shared_ptr for the device_impl corresponding to the PiDevic...
bool has_extension(const std::string &ExtensionName) const
Checks if this platform supports extension.
std::vector< device > get_devices(info::device_type DeviceType=info::device_type::all) const
Returns all SYCL devices associated with this platform.
const sycl::detail::pi::PiPlatform & getHandleRef() const
Returns raw underlying plug-in platform handle.
static std::shared_ptr< platform_impl > getPlatformFromPiDevice(sycl::detail::pi::PiDevice PiDevice, const PluginPtr &Plugin)
Queries the cache for the specified platform based on an input device.
const PluginPtr & getPlugin() const
bool supports_usm() const
Checks if this platform supports usm.
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
std::vector< device > create_sub_devices(size_t ComputeUnits) const
Partition device into sub devices.
Definition: device.cpp:88
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
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:99
detail::is_platform_info_desc< Param >::return_type get_info() const
Queries this SYCL platform for info.
Definition: platform.hpp:184
std::vector< device > get_devices(info::device_type DeviceType=info::device_type::all) const
Returns all SYCL devices associated with this platform.
Definition: platform.cpp:49
class __SYCL2020_DEPRECATED("Host device is no longer supported.") host_selector int default_selector_v(const device &dev)
Selects SYCL host device.
__SYCL_EXTERN_STREAM_ATTRS ostream cout
Linked to standard output.
::pi_device PiDevice
Definition: pi.hpp:131
::pi_platform PiPlatform
Definition: pi.hpp:129
std::vector< PluginPtr > & initialize()
Definition: pi.cpp:372
::pi_device_type PiDeviceType
Definition: pi.hpp:132
bool trace(TraceLevel level)
Definition: pi.cpp:366
::pi_platform_backend PiPlatformBackend
Definition: pi.hpp:130
backend convertBackend(pi_platform_backend PiBackend)
Definition: backend.cpp:49
static std::vector< device > amendDeviceAndSubDevices(backend PlatformBackend, std::vector< device > &DeviceList, ods_target_list *OdsTargetList, const std::vector< int > &original_indices, PlatformImplPtr PlatformImpl)
static bool supportsPartitionProperty(const device &dev, info::partition_property partitionProp)
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
std::string get_platform_info_string_impl(sycl::detail::pi::PiPlatform Plt, const PluginPtr &Plugin, pi_platform_info PiCode)
std::function< int(const sycl::device &)> DSelectorInvocableType
device select_device(const DSelectorInvocableType &DeviceSelectorInvocable)
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:48
std::shared_ptr< detail::platform_impl > PlatformImplPtr
static bool supportsAffinityDomain(const device &dev, info::partition_property partitionProp, info::partition_affinity_domain domain)
void applyAllowList(std::vector< sycl::detail::pi::PiDevice > &PiDevices, sycl::detail::pi::PiPlatform PiPlatform, const PluginPtr &Plugin)
Definition: allowlist.cpp:346
static bool IsBannedPlatform(platform Platform)
Definition: access.hpp:18
uintptr_t pi_native_handle
Definition: pi.h:217
@ PI_DEVICE_INFO_PLATFORM
Definition: pi.h:364
@ PI_DEVICE_INFO_TYPE
Definition: pi.h:305
pi_result piextPlatformGetNativeHandle(pi_platform platform, pi_native_handle *nativeHandle)
Gets the native handle of a PI platform object.
Definition: pi_cuda.cpp:42
@ PI_EXT_PLATFORM_INFO_BACKEND
Definition: pi.h:245
pi_result piDeviceGetInfo(pi_device device, pi_device_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
Returns requested info for provided native device Return PI_DEVICE_INFO_EXTENSION_DEVICELIB_ASSERT fo...
Definition: pi_cuda.cpp:78
pi_result piPlatformsGet(pi_uint32 num_entries, pi_platform *platforms, pi_uint32 *num_platforms)
Definition: pi_cuda.cpp:30
_pi_device_type
Definition: pi.h:272
pi_result piDevicesGet(pi_platform platform, pi_device_type device_type, pi_uint32 num_entries, pi_device *devices, pi_uint32 *num_devices)
Definition: pi_cuda.cpp:63
uint32_t pi_uint32
Definition: pi.h:213
pi_result piDeviceRelease(pi_device device)
Definition: pi_cuda.cpp:74
_pi_platform_backend
Definition: pi.h:283
pi_result piPlatformGetInfo(pi_platform platform, pi_platform_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)
Definition: pi_cuda.cpp:35