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