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 // Filter out the devices that are not compatible with SYCL_DEVICE_FILTER or
210 // ONEAPI_DEVICE_SELECTOR This function matches devices in the order of backend,
211 // device_type, and device_num. The device_filter and ods_target structs pun for
212 // each other, as do device_filter_list and ods_target_list.
213 // Since ONEAPI_DEVICE_SELECTOR admits negative filters, we use type traits
214 // to distinguish the case where we are working with ONEAPI_DEVICE_SELECTOR
215 // in the places where the functionality diverges between these two
216 // environment variables.
217 // The return value is a vector that represents the indices of the chosen
218 // devices.
219 template <typename ListT, typename FilterT>
220 std::vector<int> platform_impl::filterDeviceFilter(
221  std::vector<sycl::detail::pi::PiDevice> &PiDevices,
222  ListT *FilterList) const {
223 
224  constexpr bool is_ods_target = std::is_same_v<FilterT, ods_target>;
225  // There are some differences in implementation between SYCL_DEVICE_FILTER
226  // and ONEAPI_DEVICE_SELECTOR so we use if constexpr to select the
227  // appropriate execution path if we are dealing with the latter variable.
228 
229  if constexpr (is_ods_target) {
230 
231  // Since we are working with ods_target filters ,which can be negative,
232  // we sort the filters so that all the negative filters appear before
233  // all the positive filters. This enables us to have the full list of
234  // blacklisted devices by the time we get to the positive filters
235  // so that if a positive filter matches a blacklisted device we do
236  // not add it to the list of available devices.
237  std::sort(FilterList->get().begin(), FilterList->get().end(),
238  [](const ods_target &filter1, const ods_target &filter2) {
239  return filter1.IsNegativeTarget && !filter2.IsNegativeTarget;
240  });
241  }
242 
243  // this map keeps track of devices discarded by negative filters, it is only
244  // used in the ONEAPI_DEVICE_SELECTOR implemenation. It cannot be placed
245  // in the if statement above because it will then be out of scope in the rest
246  // of the function
247  std::map<int, bool> Blacklist;
248  // original indices keeps track of the device numbers of the chosen
249  // devices and is whats returned by the function
250  std::vector<int> original_indices;
251 
252  // Find out backend of the platform
254  MPlugin->call<PiApiKind::piPlatformGetInfo>(
255  MPlatform, PI_EXT_PLATFORM_INFO_BACKEND,
256  sizeof(sycl::detail::pi::PiPlatformBackend), &PiBackend, nullptr);
257  backend Backend = convertBackend(PiBackend);
258 
259  int InsertIDx = 0;
260  // DeviceIds should be given consecutive numbers across platforms in the same
261  // backend
262  std::lock_guard<std::mutex> Guard(*MPlugin->getPluginMutex());
263  int DeviceNum = MPlugin->getStartingDeviceId(MPlatform);
264  for (sycl::detail::pi::PiDevice Device : PiDevices) {
266  MPlugin->call<PiApiKind::piDeviceGetInfo>(
268  &PiDevType, nullptr);
269  // Assumption here is that there is 1-to-1 mapping between PiDevType and
270  // Sycl device type for GPU, CPU, and ACC.
271  info::device_type DeviceType = pi::cast<info::device_type>(PiDevType);
272 
273  for (const FilterT &Filter : FilterList->get()) {
274  backend FilterBackend = Filter.Backend.value_or(backend::all);
275  // First, match the backend entry
276  if (FilterBackend == Backend || FilterBackend == backend::all) {
277  info::device_type FilterDevType =
278  Filter.DeviceType.value_or(info::device_type::all);
279  // Next, match the device_type entry
280  if (FilterDevType == info::device_type::all) {
281  // Last, match the device_num entry
282  if (!Filter.DeviceNum || DeviceNum == Filter.DeviceNum.value()) {
283  if constexpr (is_ods_target) { // dealing with ODS filters
284  if (!Blacklist[DeviceNum]) { // ensure it is not blacklisted
285  if (!Filter.IsNegativeTarget) { // is filter positive?
286  PiDevices[InsertIDx++] = Device;
287  original_indices.push_back(DeviceNum);
288  } else {
289  // Filter is negative and the device matches the filter so
290  // blacklist the device.
291  Blacklist[DeviceNum] = true;
292  }
293  }
294  } else { // dealing with SYCL_DEVICE_FILTER
295  PiDevices[InsertIDx++] = Device;
296  original_indices.push_back(DeviceNum);
297  }
298  break;
299  }
300 
301  } else if (FilterDevType == DeviceType) {
302  if (!Filter.DeviceNum || DeviceNum == Filter.DeviceNum.value()) {
303  if constexpr (is_ods_target) {
304  if (!Blacklist[DeviceNum]) {
305  if (!Filter.IsNegativeTarget) {
306  PiDevices[InsertIDx++] = Device;
307  original_indices.push_back(DeviceNum);
308  } else {
309  // Filter is negative and the device matches the filter so
310  // blacklist the device.
311  Blacklist[DeviceNum] = true;
312  }
313  }
314  } else {
315  PiDevices[InsertIDx++] = Device;
316  original_indices.push_back(DeviceNum);
317  }
318  break;
319  }
320  }
321  }
322  }
323  DeviceNum++;
324  }
325  PiDevices.resize(InsertIDx);
326  // remember the last backend that has gone through this filter function
327  // to assign a unique device id number across platforms that belong to
328  // the same backend. For example, opencl:cpu:0, opencl:acc:1, opencl:gpu:2
329  MPlugin->setLastDeviceId(MPlatform, DeviceNum);
330  return original_indices;
331 }
332 
333 std::shared_ptr<device_impl>
335  const std::lock_guard<std::mutex> Guard(MDeviceMapMutex);
336  return getDeviceImplHelper(PiDevice);
337 }
338 
339 std::shared_ptr<device_impl> platform_impl::getOrMakeDeviceImpl(
341  const std::shared_ptr<platform_impl> &PlatformImpl) {
342  const std::lock_guard<std::mutex> Guard(MDeviceMapMutex);
343  // If we've already seen this device, return the impl
344  std::shared_ptr<device_impl> Result = getDeviceImplHelper(PiDevice);
345  if (Result)
346  return Result;
347 
348  // Otherwise make the impl
349  Result = std::make_shared<device_impl>(PiDevice, PlatformImpl);
350  MDeviceCache.emplace_back(Result);
351 
352  return Result;
353 }
354 
355 static bool supportsAffinityDomain(const device &dev,
356  info::partition_property partitionProp,
359  return true;
360  }
361  auto supported = dev.get_info<info::device::partition_affinity_domains>();
362  auto It = std::find(std::begin(supported), std::end(supported), domain);
363  return It != std::end(supported);
364 }
365 
366 static bool supportsPartitionProperty(const device &dev,
367  info::partition_property partitionProp) {
368  auto supported = dev.get_info<info::device::partition_properties>();
369  auto It =
370  std::find(std::begin(supported), std::end(supported), partitionProp);
371  return It != std::end(supported);
372 }
373 
374 static std::vector<device> amendDeviceAndSubDevices(
375  backend PlatformBackend, std::vector<device> &DeviceList,
376  ods_target_list *OdsTargetList, const std::vector<int> &original_indices,
377  PlatformImplPtr PlatformImpl) {
378  constexpr info::partition_property partitionProperty =
380  constexpr info::partition_affinity_domain affinityDomain =
382 
383  std::vector<device> FinalResult;
384  // (Only) when amending sub-devices for ONEAPI_DEVICE_SELECTOR, all
385  // sub-devices are treated as root.
386  TempAssignGuard<bool> TAG(PlatformImpl->MAlwaysRootDevice, true);
387 
388  for (unsigned i = 0; i < DeviceList.size(); i++) {
389  // device has already been screened. The question is whether it should be a
390  // top level device and/or is expected to add its sub-devices to the list.
391  device &dev = DeviceList[i];
392  bool deviceAdded = false;
393  for (ods_target target : OdsTargetList->get()) {
394  backend TargetBackend = target.Backend.value_or(backend::all);
395  if (PlatformBackend == TargetBackend || TargetBackend == backend::all) {
396  bool deviceMatch = target.HasDeviceWildCard; // opencl:*
397  if (target.DeviceType) { // opencl:gpu
398  deviceMatch = ((target.DeviceType == info::device_type::all) ||
400  target.DeviceType));
401 
402  } else if (target.DeviceNum) { // opencl:0
403  deviceMatch = (target.DeviceNum.value() == original_indices[i]);
404  }
405 
406  if (deviceMatch) {
407  // Top level matches. Do we add it, or subdevices, or sub-sub-devices?
408  bool wantSubDevice =
409  target.SubDeviceNum || target.HasSubDeviceWildCard;
410  bool supportsSubPartitioning =
411  (supportsPartitionProperty(dev, partitionProperty) &&
412  supportsAffinityDomain(dev, partitionProperty, affinityDomain));
413  bool wantSubSubDevice =
414  target.SubSubDeviceNum || target.HasSubSubDeviceWildCard;
415 
416  // -- Add top level device.
417  if (!wantSubDevice) {
418  if (!deviceAdded) {
419  FinalResult.push_back(dev);
420  deviceAdded = true;
421  }
422  } else {
423  if (!supportsSubPartitioning) {
424  if (target.DeviceNum ||
425  (target.DeviceType &&
426  (target.DeviceType.value() != info::device_type::all))) {
427  // This device was specifically requested and yet is not
428  // partitionable.
429  std::cout << "device is not partitionable: " << target
430  << std::endl;
431  }
432  continue;
433  }
434  // -- Add sub sub device.
435  if (wantSubSubDevice) {
436 
437  auto subDevicesToPartition =
438  dev.create_sub_devices<partitionProperty>(affinityDomain);
439  if (target.SubDeviceNum) {
440  if (subDevicesToPartition.size() >
441  target.SubDeviceNum.value()) {
442  subDevicesToPartition[0] =
443  subDevicesToPartition[target.SubDeviceNum.value()];
444  subDevicesToPartition.resize(1);
445  } else {
446  std::cout << "subdevice index out of bounds: " << target
447  << std::endl;
448  continue;
449  }
450  }
451  for (device subDev : subDevicesToPartition) {
452  bool supportsSubSubPartitioning =
453  (supportsPartitionProperty(subDev, partitionProperty) &&
454  supportsAffinityDomain(subDev, partitionProperty,
455  affinityDomain));
456  if (!supportsSubSubPartitioning) {
457  if (target.SubDeviceNum) {
458  // Parent subdevice was specifically requested, yet is not
459  // partitionable.
460  std::cout << "sub-device is not partitionable: " << target
461  << std::endl;
462  }
463  continue;
464  }
465  // Allright, lets get them sub-sub-devices.
466  auto subSubDevices =
467  subDev.create_sub_devices<partitionProperty>(
468  affinityDomain);
469  if (target.HasSubSubDeviceWildCard) {
470  FinalResult.insert(FinalResult.end(), subSubDevices.begin(),
471  subSubDevices.end());
472  } else {
473  if (subSubDevices.size() > target.SubSubDeviceNum.value()) {
474  FinalResult.push_back(
475  subSubDevices[target.SubSubDeviceNum.value()]);
476  } else {
477  std::cout
478  << "sub-sub-device index out of bounds: " << target
479  << std::endl;
480  }
481  }
482  }
483  } else if (wantSubDevice) {
484  auto subDevices = dev.create_sub_devices<
486  affinityDomain);
487  if (target.HasSubDeviceWildCard) {
488  FinalResult.insert(FinalResult.end(), subDevices.begin(),
489  subDevices.end());
490  } else {
491  if (subDevices.size() > target.SubDeviceNum.value()) {
492  FinalResult.push_back(
493  subDevices[target.SubDeviceNum.value()]);
494  } else {
495  std::cout << "subdevice index out of bounds: " << target
496  << std::endl;
497  }
498  }
499  }
500  }
501  } // /if deviceMatch
502  }
503  } // /for
504  } // /for
505  return FinalResult;
506 }
507 
508 std::vector<device>
510  std::vector<device> Res;
511  // Will we be filtering with SYCL_DEVICE_FILTER or ONEAPI_DEVICE_SELECTOR ?
512  // We do NOT attempt to support both simultaneously.
515 
516  if (is_host() && (DeviceType == info::device_type::host ||
517  DeviceType == info::device_type::all)) {
518  Res.push_back(
519  createSyclObjFromImpl<device>(device_impl::getHostDeviceImpl()));
520  }
521 
522  // If any DeviceType other than host was requested for host platform,
523  // an empty vector will be returned.
524  if (is_host() || DeviceType == info::device_type::host)
525  return Res;
526 
527  pi_uint32 NumDevices = 0;
528  MPlugin->call<PiApiKind::piDevicesGet>(
529  MPlatform, pi::cast<sycl::detail::pi::PiDeviceType>(DeviceType),
530  0, // CP info::device_type::all
531  pi::cast<sycl::detail::pi::PiDevice *>(nullptr), &NumDevices);
532  const backend Backend = getBackend();
533 
534  if (NumDevices == 0) {
535  // If platform doesn't have devices (even without filter)
536  // LastDeviceIds[PlatformId] stay 0 that affects next platform devices num
537  // analysis. Doing adjustment by simple copy of last device num from
538  // previous platform.
539  // Needs non const plugin reference.
540  std::vector<PluginPtr> &Plugins = sycl::detail::pi::initialize();
541  auto It = std::find_if(Plugins.begin(), Plugins.end(),
542  [&Platform = MPlatform](PluginPtr &Plugin) {
543  return Plugin->containsPiPlatform(Platform);
544  });
545  if (It != Plugins.end()) {
546  PluginPtr &Plugin = *It;
547  std::lock_guard<std::mutex> Guard(*Plugin->getPluginMutex());
548  Plugin->adjustLastDeviceId(MPlatform);
549  }
550  return Res;
551  }
552 
553  std::vector<sycl::detail::pi::PiDevice> PiDevices(NumDevices);
554  // TODO catch an exception and put it to list of asynchronous exceptions
555  MPlugin->call<PiApiKind::piDevicesGet>(
556  MPlatform,
557  pi::cast<sycl::detail::pi::PiDeviceType>(
558  DeviceType), // CP info::device_type::all
559  NumDevices, PiDevices.data(), nullptr);
560 
561  // Some elements of PiDevices vector might be filtered out, so make a copy of
562  // handles to do a cleanup later
563  std::vector<sycl::detail::pi::PiDevice> PiDevicesToCleanUp = PiDevices;
564 
565  // Filter out devices that are not present in the SYCL_DEVICE_ALLOWLIST
567  applyAllowList(PiDevices, MPlatform, MPlugin);
568 
569  // The first step is to filter out devices that are not compatible with
570  // SYCL_DEVICE_FILTER or ONEAPI_DEVICE_SELECTOR. This is also the mechanism by
571  // which top level device ids are assigned.
572  std::vector<int> PlatformDeviceIndices;
573  if (OdsTargetList) {
574  if (FilterList) {
576  "ONEAPI_DEVICE_SELECTOR cannot be used in "
577  "conjunction with SYCL_DEVICE_FILTER");
578  }
579  PlatformDeviceIndices = filterDeviceFilter<ods_target_list, ods_target>(
580  PiDevices, OdsTargetList);
581  } else if (FilterList) {
582  PlatformDeviceIndices =
583  filterDeviceFilter<device_filter_list, device_filter>(PiDevices,
584  FilterList);
585  }
586 
587  // The next step is to inflate the filtered PIDevices into SYCL Device
588  // objects.
589  PlatformImplPtr PlatformImpl = getOrMakePlatformImpl(MPlatform, MPlugin);
590  std::transform(
591  PiDevices.begin(), PiDevices.end(), std::back_inserter(Res),
592  [PlatformImpl](const sycl::detail::pi::PiDevice &PiDevice) -> device {
593  return detail::createSyclObjFromImpl<device>(
594  PlatformImpl->getOrMakeDeviceImpl(PiDevice, PlatformImpl));
595  });
596 
597  // The reference counter for handles, that we used to create sycl objects, is
598  // incremented, so we need to call release here.
599  for (sycl::detail::pi::PiDevice &PiDev : PiDevicesToCleanUp)
600  MPlugin->call<PiApiKind::piDeviceRelease>(PiDev);
601 
602  // If we aren't using ONEAPI_DEVICE_SELECTOR, then we are done.
603  // and if there are no devices so far, there won't be any need to replace them
604  // with subdevices.
605  if (!OdsTargetList || Res.size() == 0)
606  return Res;
607 
608  // Otherwise, our last step is to revisit the devices, possibly replacing
609  // them with subdevices (which have been ignored until now)
610  return amendDeviceAndSubDevices(Backend, Res, OdsTargetList,
611  PlatformDeviceIndices, PlatformImpl);
612 }
613 
614 bool platform_impl::has_extension(const std::string &ExtensionName) const {
615  if (is_host())
616  return false;
617 
618  std::string AllExtensionNames = get_platform_info_string_impl(
619  MPlatform, getPlugin(),
621  return (AllExtensionNames.find(ExtensionName) != std::string::npos);
622 }
623 
625  const auto &Plugin = getPlugin();
626  pi_native_handle Handle;
628  &Handle);
629  return Handle;
630 }
631 
632 template <typename Param>
633 typename Param::return_type platform_impl::get_info() const {
634  if (is_host())
635  return get_platform_info_host<Param>();
636 
637  return get_platform_info<Param>(this->getHandleRef(), getPlugin());
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
sycl::_V1::info::partition_affinity_domain
partition_affinity_domain
Definition: info_desc.hpp:72
sycl::_V1::info::partition_affinity_domain::next_partitionable
@ next_partitionable
_pi_platform_backend
_pi_platform_backend
Definition: pi.h:264
sycl::_V1::backend
backend
Definition: backend_types.hpp:18
sycl::_V1::detail::platform_impl::getNative
pi_native_handle getNative() const
Gets the native handle of the SYCL platform.
Definition: platform_impl.cpp:624
sycl::_V1::detail::pi::initialize
std::vector< PluginPtr > & initialize()
Definition: pi.cpp:429
sycl::_V1::info::partition_property
partition_property
Definition: info_desc.hpp:64
sycl::_V1::detail::PlatformImplPtr
std::shared_ptr< detail::platform_impl > PlatformImplPtr
Definition: context_impl.hpp:32
sycl::_V1::make_error_code
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
Definition: exception.cpp:94
config.hpp
sycl::_V1::detail::platform_impl::get_platforms
static std::vector< platform > get_platforms()
Returns all available SYCL platforms in the system.
Definition: platform_impl.cpp:108
device.hpp
sycl::_V1::detail::convertBackend
backend convertBackend(pi_platform_backend PiBackend)
Definition: backend.cpp:49
sycl::_V1::detail::GlobalHandler::instance
static GlobalHandler & instance()
Definition: global_handler.cpp:123
sycl::_V1::detail::pi::PiDevice
::pi_device PiDevice
Definition: pi.hpp:131
sycl::_V1::detail::SYCLConfig
Definition: config.hpp:111
piPlatformGetInfo
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:30
_pi_device_type
_pi_device_type
Definition: pi.h:253
sycl::_V1::detail::platform_impl::has_extension
bool has_extension(const std::string &ExtensionName) const
Checks if this platform supports extension.
Definition: platform_impl.cpp:614
sycl::_V1::detail::platform_impl::get_info
Param::return_type get_info() const
Queries this SYCL platform for info.
Definition: platform_impl.cpp:633
sycl::_V1::detail::ods_target
Definition: device_filter.hpp:34
PI_DEVICE_INFO_PLATFORM
@ PI_DEVICE_INFO_PLATFORM
Definition: pi.h:345
sycl::_V1::detail::platform_impl::getHostPlatformImpl
static std::shared_ptr< platform_impl > getHostPlatformImpl()
Static functions that help maintain platform uniquess and equality of comparison.
Definition: platform_impl.cpp:33
sycl
Definition: access.hpp:18
sycl::_V1::backend::all
@ all
sycl::_V1::detail::PiInfoCode
Definition: info_desc_helpers.hpp:25
device_impl.hpp
_pi_platform
Definition: pi_cuda.hpp:44
sycl::_V1::detail::get_platform_info_string_impl
std::string get_platform_info_string_impl(sycl::detail::pi::PiPlatform Plt, const PluginPtr &Plugin, pi_platform_info PiCode)
Definition: platform_info.hpp:22
sycl::_V1::detail::pi::PiPlatform
::pi_platform PiPlatform
Definition: pi.hpp:129
sycl::_V1::detail::pi::PiDeviceType
::pi_device_type PiDeviceType
Definition: pi.hpp:132
sycl::_V1::detail::platform_impl::has
bool has(aspect Aspect) const
Indicates if all of the SYCL devices on this platform have the given feature.
Definition: platform_impl.cpp:641
sycl::_V1::detail::platform_impl::getPlugin
const PluginPtr & getPlugin() const
Definition: platform_impl.hpp:132
sycl::_V1::info::partition_property::partition_by_affinity_domain
@ partition_by_affinity_domain
pi_uint32
uint32_t pi_uint32
Definition: pi.h:194
platform_impl.hpp
sycl::_V1::detail::TempAssignGuard
Definition: util.hpp:38
sycl::_V1::detail::platform_impl::is_host
bool is_host() const
Definition: platform_impl.hpp:82
sycl::_V1::detail::amendDeviceAndSubDevices
static std::vector< device > amendDeviceAndSubDevices(backend PlatformBackend, std::vector< device > &DeviceList, ods_target_list *OdsTargetList, const std::vector< int > &original_indices, PlatformImplPtr PlatformImpl)
Definition: platform_impl.cpp:374
piDeviceGetInfo
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:73
sycl::_V1::exception
Definition: exception.hpp:68
sycl::_V1::detail::platform_impl::getPlatformFromPiDevice
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.
Definition: platform_impl.cpp:65
sycl::_V1::detail::IsBannedPlatform
static bool IsBannedPlatform(platform Platform)
Definition: platform_impl.cpp:75
global_handler.hpp
sycl::_V1::detail::platform_impl::getDeviceImpl
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...
Definition: platform_impl.cpp:334
sycl::_V1::device
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:59
sycl::_V1::access::target
target
Definition: access.hpp:22
platform_info.hpp
sycl::_V1::info::device_type
device_type
Definition: info_desc.hpp:53
sycl::_V1::device::create_sub_devices
std::vector< device > create_sub_devices(size_t ComputeUnits) const
Partition device into sub devices.
Definition: device.cpp:94
piDeviceRelease
pi_result piDeviceRelease(pi_device device)
Definition: pi_cuda.cpp:69
sycl::_V1::errc::invalid
@ invalid
pi_native_handle
uintptr_t pi_native_handle
Definition: pi.h:198
sycl::_V1::detail::applyAllowList
void applyAllowList(std::vector< sycl::detail::pi::PiDevice > &PiDevices, sycl::detail::pi::PiPlatform PiPlatform, const PluginPtr &Plugin)
Definition: allowlist.cpp:345
sycl::_V1::info::device_type::host
@ host
sycl::_V1::detail::platform_impl::getBackend
backend getBackend(void) const
Returns the backend of this platform.
Definition: platform_impl.hpp:85
sycl::_V1::info::device_type::all
@ all
piPlatformsGet
pi_result piPlatformsGet(pi_uint32 num_entries, pi_platform *platforms, pi_uint32 *num_platforms)
Definition: pi_cuda.cpp:25
iostream_proxy.hpp
sycl::_V1::backend::opencl
@ opencl
sycl::_V1::platform::get_devices
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
sycl::_V1::detail::device_filter_list
Definition: device_filter.hpp:84
sycl::_V1::device::get_info
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:136
piextPlatformGetNativeHandle
pi_result piextPlatformGetNativeHandle(pi_platform platform, pi_native_handle *nativeHandle)
Gets the native handle of a PI platform object.
Definition: pi_cuda.cpp:37
sycl::_V1::detail::platform_impl::getOrMakePlatformImpl
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.
Definition: platform_impl.cpp:40
PI_EXT_PLATFORM_INFO_BACKEND
@ PI_EXT_PLATFORM_INFO_BACKEND
Definition: pi.h:226
sycl::_V1::detail::ods_target_list
Definition: device_filter.hpp:55
backend.hpp
sycl::_V1::detail::platform_impl::get_devices
std::vector< device > get_devices(info::device_type DeviceType=info::device_type::all) const
Returns all SYCL devices associated with this platform.
Definition: platform_impl.cpp:509
sycl::_V1::detail::pi::PiPlatformBackend
::pi_platform_backend PiPlatformBackend
Definition: pi.hpp:130
sycl::_V1::detail::device_impl::getHostDeviceImpl
static std::shared_ptr< device_impl > getHostDeviceImpl()
Gets the single instance of the Host Device.
Definition: device_impl.cpp:575
piDevicesGet
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:58
sycl::_V1::detail::pi::PI_TRACE_ALL
@ PI_TRACE_ALL
Definition: pi.hpp:60
sycl::_V1::detail::ods_target_list::get
std::vector< ods_target > & get()
Definition: device_filter.hpp:61
util.hpp
sycl::_V1::platform
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:63
allowlist.hpp
PI_DEVICE_INFO_TYPE
@ PI_DEVICE_INFO_TYPE
Definition: pi.h:286
sycl::_V1::detail::GlobalHandler::registerDefaultContextReleaseHandler
static void registerDefaultContextReleaseHandler()
Definition: global_handler.cpp:250
sycl::_V1::detail::platform_impl::getHandleRef
const sycl::detail::pi::PiPlatform & getHandleRef() const
Returns raw underlying plug-in platform handle.
Definition: platform_impl.hpp:114
sycl::_V1::detail::platform_impl::getOrMakeDeviceImpl
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 ...
Definition: platform_impl.cpp:339
sycl::_V1::detail::pi::trace
bool trace(TraceLevel level)
Definition: pi.cpp:423
std::cout
__SYCL_EXTERN_STREAM_ATTRS ostream cout
Linked to standard output.
sycl::_V1::platform::get_info
detail::is_platform_info_desc< Param >::return_type get_info() const
Queries this SYCL platform for info.
Definition: platform.cpp:61
sycl::_V1::detail::supportsPartitionProperty
static bool supportsPartitionProperty(const device &dev, info::partition_property partitionProp)
Definition: platform_impl.cpp:366
sycl::_V1::detail::SYCLConfig::get
static const char * get()
Definition: config.hpp:115
sycl::_V1::detail::supportsAffinityDomain
static bool supportsAffinityDomain(const device &dev, info::partition_property partitionProp, info::partition_affinity_domain domain)
Definition: platform_impl.cpp:355
sycl::_V1::detail::GlobalHandler::getPlatformCache
std::vector< PlatformImplPtr > & getPlatformCache()
Definition: global_handler.cpp:190
sycl::_V1::detail::getSyclObjImpl
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
_pi_device
Definition: pi_cuda.hpp:48
sycl::_V1::detail::PluginPtr
std::shared_ptr< plugin > PluginPtr
Definition: pi.hpp:48