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>
16 #include <sycl/detail/util.hpp>
17 #include <sycl/device.hpp>
18 
19 #include <algorithm>
20 #include <cstring>
21 #include <mutex>
22 #include <string>
23 #include <vector>
24 
25 namespace sycl {
27 namespace detail {
28 
29 using PlatformImplPtr = std::shared_ptr<platform_impl>;
30 
31 PlatformImplPtr platform_impl::getHostPlatformImpl() {
32  static PlatformImplPtr HostImpl = std::make_shared<platform_impl>();
33 
34  return HostImpl;
35 }
36 
37 PlatformImplPtr platform_impl::getOrMakePlatformImpl(RT::PiPlatform PiPlatform,
38  const plugin &Plugin) {
39  PlatformImplPtr Result;
40  {
41  const std::lock_guard<std::mutex> Guard(
42  GlobalHandler::instance().getPlatformMapMutex());
43 
44  std::vector<PlatformImplPtr> &PlatformCache =
45  GlobalHandler::instance().getPlatformCache();
46 
47  // If we've already seen this platform, return the impl
48  for (const auto &PlatImpl : PlatformCache) {
49  if (PlatImpl->getHandleRef() == PiPlatform)
50  return PlatImpl;
51  }
52 
53  // Otherwise make the impl
54  Result = std::make_shared<platform_impl>(PiPlatform, Plugin);
55  PlatformCache.emplace_back(Result);
56  }
57 
58  return Result;
59 }
60 
61 PlatformImplPtr platform_impl::getPlatformFromPiDevice(RT::PiDevice PiDevice,
62  const plugin &Plugin) {
63  RT::PiPlatform Plt = nullptr; // TODO catch an exception and put it to list
64  // of asynchronous exceptions
66  sizeof(Plt), &Plt, nullptr);
67  return getOrMakePlatformImpl(Plt, Plugin);
68 }
69 
70 static bool IsBannedPlatform(platform Platform) {
71  // The NVIDIA OpenCL platform is currently not compatible with DPC++
72  // since it is only 1.2 but gets selected by default in many systems
73  // There is also no support on the PTX backend for OpenCL consumption,
74  // and there have been some internal reports.
75  // To avoid problems on default users and deployment of DPC++ on platforms
76  // where CUDA is available, the OpenCL support is disabled.
77  //
78  // There is also no support for the AMD HSA backend for OpenCL consumption,
79  // as well as reported problems with device queries, so AMD OpenCL support
80  // is disabled as well.
81  //
82  auto IsMatchingOpenCL = [](platform Platform, const std::string_view name) {
83  if (getSyclObjImpl(Platform)->is_host())
84  return false;
85 
86  const bool HasNameMatch = Platform.get_info<info::platform::name>().find(
87  name) != std::string::npos;
88  const auto Backend =
89  detail::getSyclObjImpl(Platform)->getPlugin().getBackend();
90  const bool IsMatchingOCL = (HasNameMatch && Backend == backend::opencl);
92  IsMatchingOCL) {
93  std::cout << "SYCL_PI_TRACE[all]: " << name
94  << " OpenCL platform found but is not compatible." << std::endl;
95  }
96  return IsMatchingOCL;
97  };
98  return IsMatchingOpenCL(Platform, "NVIDIA CUDA") ||
99  IsMatchingOpenCL(Platform, "AMD Accelerated Parallel Processing");
100 }
101 
102 // This routine has the side effect of registering each platform's last device
103 // id into each plugin, which is used for device counting.
104 std::vector<platform> platform_impl::get_platforms() {
105  std::vector<platform> Platforms;
106  std::vector<plugin> &Plugins = RT::initialize();
107  for (plugin &Plugin : Plugins) {
108  pi_uint32 NumPlatforms = 0;
109  // Move to the next plugin if the plugin fails to initialize.
110  // This way platforms from other plugins get a chance to be discovered.
111  if (Plugin.call_nocheck<PiApiKind::piPlatformsGet>(
112  0, nullptr, &NumPlatforms) != PI_SUCCESS)
113  continue;
114 
115  if (NumPlatforms) {
116  std::vector<RT::PiPlatform> PiPlatforms(NumPlatforms);
117  if (Plugin.call_nocheck<PiApiKind::piPlatformsGet>(
118  NumPlatforms, PiPlatforms.data(), nullptr) != PI_SUCCESS)
119  return Platforms;
120 
121  for (const auto &PiPlatform : PiPlatforms) {
122  platform Platform = detail::createSyclObjFromImpl<platform>(
123  getOrMakePlatformImpl(PiPlatform, Plugin));
124  if (IsBannedPlatform(Platform)) {
125  continue; // bail as early as possible, otherwise banned platforms may
126  // mess up device counting
127  }
128 
129  {
130  std::lock_guard<std::mutex> Guard(*Plugin.getPluginMutex());
131  // insert PiPlatform into the Plugin
132  Plugin.getPlatformId(PiPlatform);
133  }
134 
135  // The SYCL spec says that a platform has one or more devices. ( SYCL
136  // 2020 4.6.2 ) If we have an empty platform, we don't report it back
137  // from platform::get_platforms().
138  if (!Platform.get_devices(info::device_type::all).empty()) {
139  Platforms.push_back(Platform);
140  }
141  }
142  }
143  }
144 
145  // Register default context release handler after plugins have been loaded and
146  // after the first calls to each plugin. This initializes a function-local
147  // variable that should be destroyed before any global variables in the
148  // plugins are destroyed. This is done after the first call to the backends to
149  // ensure any lazy-loaded dependencies are loaded prior to the handler
150  // variable's initialization. Note: The default context release handler is not
151  // guaranteed to be destroyed before function-local static variables as they
152  // may be initialized after.
153  GlobalHandler::registerDefaultContextReleaseHandler();
154 
155  return Platforms;
156 }
157 
158 // Filter out the devices that are not compatible with SYCL_DEVICE_FILTER or
159 // ONEAPI_DEVICE_SELECTOR This function matches devices in the order of backend,
160 // device_type, and device_num. The device_filter and ods_target structs pun for
161 // each other, as do device_filter_list and ods_target_list.
162 // Since ONEAPI_DEVICE_SELECTOR admits negative filters, we use type traits
163 // to distinguish the case where we are working with ONEAPI_DEVICE_SELECTOR
164 // in the places where the functionality diverges between these two
165 // environment variables.
166 // The return value is a vector that represents the indices of the chosen
167 // devices.
168 template <typename ListT, typename FilterT>
169 static std::vector<int> filterDeviceFilter(std::vector<RT::PiDevice> &PiDevices,
170  RT::PiPlatform Platform,
171  ListT *FilterList) {
172 
173  constexpr bool is_ods_target = std::is_same_v<FilterT, ods_target>;
174  // There are some differences in implementation between SYCL_DEVICE_FILTER
175  // and ONEAPI_DEVICE_SELECTOR so we use if constexpr to select the
176  // appropriate execution path if we are dealing with the latter variable.
177 
178  if constexpr (is_ods_target) {
179 
180  // Since we are working with ods_target filters ,which can be negative,
181  // we sort the filters so that all the negative filters appear before
182  // all the positive filters. This enables us to have the full list of
183  // blacklisted devices by the time we get to the positive filters
184  // so that if a positive filter matches a blacklisted device we do
185  // not add it to the list of available devices.
186  std::sort(FilterList->get().begin(), FilterList->get().end(),
187  [](const ods_target &filter1, const ods_target &filter2) {
188  return filter1.IsNegativeTarget && !filter2.IsNegativeTarget;
189  });
190  }
191 
192  // this map keeps track of devices discarded by negative filters, it is only
193  // used in the ONEAPI_DEVICE_SELECTOR implemenation. It cannot be placed
194  // in the if statement above because it will then be out of scope in the rest
195  // of the function
196  std::map<int, bool> Blacklist;
197  // original indices keeps track of the device numbers of the chosen
198  // devices and is whats returned by the function
199  std::vector<int> original_indices;
200 
201  std::vector<plugin> &Plugins = RT::initialize();
202  auto It =
203  std::find_if(Plugins.begin(), Plugins.end(), [Platform](plugin &Plugin) {
204  return Plugin.containsPiPlatform(Platform);
205  });
206  if (It == Plugins.end()) {
207  return original_indices;
208  }
209  plugin &Plugin = *It;
210  backend Backend = Plugin.getBackend();
211  int InsertIDx = 0;
212  // DeviceIds should be given consecutive numbers across platforms in the same
213  // backend
214  std::lock_guard<std::mutex> Guard(*Plugin.getPluginMutex());
215  int DeviceNum = Plugin.getStartingDeviceId(Platform);
216  for (RT::PiDevice Device : PiDevices) {
217  RT::PiDeviceType PiDevType;
219  sizeof(RT::PiDeviceType),
220  &PiDevType, nullptr);
221  // Assumption here is that there is 1-to-1 mapping between PiDevType and
222  // Sycl device type for GPU, CPU, and ACC.
223  info::device_type DeviceType = pi::cast<info::device_type>(PiDevType);
224 
225  for (const FilterT &Filter : FilterList->get()) {
226  backend FilterBackend = Filter.Backend.value_or(backend::all);
227  // First, match the backend entry
228  if (FilterBackend == Backend || FilterBackend == backend::all) {
229  info::device_type FilterDevType =
230  Filter.DeviceType.value_or(info::device_type::all);
231  // Next, match the device_type entry
232  if (FilterDevType == info::device_type::all) {
233  // Last, match the device_num entry
234  if (!Filter.DeviceNum || DeviceNum == Filter.DeviceNum.value()) {
235  if constexpr (is_ods_target) { // dealing with ODS filters
236  if (!Blacklist[DeviceNum]) { // ensure it is not blacklisted
237  if (!Filter.IsNegativeTarget) { // is filter positive?
238  PiDevices[InsertIDx++] = Device;
239  original_indices.push_back(DeviceNum);
240  } else {
241  // Filter is negative and the device matches the filter so
242  // blacklist the device.
243  Blacklist[DeviceNum] = true;
244  }
245  }
246  } else { // dealing with SYCL_DEVICE_FILTER
247  PiDevices[InsertIDx++] = Device;
248  original_indices.push_back(DeviceNum);
249  }
250  break;
251  }
252 
253  } else if (FilterDevType == DeviceType) {
254  if (!Filter.DeviceNum || DeviceNum == Filter.DeviceNum.value()) {
255  if constexpr (is_ods_target) {
256  if (!Blacklist[DeviceNum]) {
257  if (!Filter.IsNegativeTarget) {
258  PiDevices[InsertIDx++] = Device;
259  original_indices.push_back(DeviceNum);
260  } else {
261  // Filter is negative and the device matches the filter so
262  // blacklist the device.
263  Blacklist[DeviceNum] = true;
264  }
265  }
266  } else {
267  PiDevices[InsertIDx++] = Device;
268  original_indices.push_back(DeviceNum);
269  }
270  break;
271  }
272  }
273  }
274  }
275  DeviceNum++;
276  }
277  PiDevices.resize(InsertIDx);
278  // remember the last backend that has gone through this filter function
279  // to assign a unique device id number across platforms that belong to
280  // the same backend. For example, opencl:cpu:0, opencl:acc:1, opencl:gpu:2
281  Plugin.setLastDeviceId(Platform, DeviceNum);
282  return original_indices;
283 }
284 
285 std::shared_ptr<device_impl>
286 platform_impl::getDeviceImpl(RT::PiDevice PiDevice) {
287  const std::lock_guard<std::mutex> Guard(MDeviceMapMutex);
288  return getDeviceImplHelper(PiDevice);
289 }
290 
291 std::shared_ptr<device_impl> platform_impl::getOrMakeDeviceImpl(
292  RT::PiDevice PiDevice, const std::shared_ptr<platform_impl> &PlatformImpl) {
293  const std::lock_guard<std::mutex> Guard(MDeviceMapMutex);
294  // If we've already seen this device, return the impl
295  std::shared_ptr<device_impl> Result = getDeviceImplHelper(PiDevice);
296  if (Result)
297  return Result;
298 
299  // Otherwise make the impl
300  Result = std::make_shared<device_impl>(PiDevice, PlatformImpl);
301  MDeviceCache.emplace_back(Result);
302 
303  return Result;
304 }
305 
306 static bool supportsAffinityDomain(const device &dev,
307  info::partition_property partitionProp,
309  if (partitionProp != info::partition_property::partition_by_affinity_domain) {
310  return true;
311  }
312  auto supported = dev.get_info<info::device::partition_affinity_domains>();
313  auto It = std::find(std::begin(supported), std::end(supported), domain);
314  return It != std::end(supported);
315 }
316 
317 static bool supportsPartitionProperty(const device &dev,
318  info::partition_property partitionProp) {
319  auto supported = dev.get_info<info::device::partition_properties>();
320  auto It =
321  std::find(std::begin(supported), std::end(supported), partitionProp);
322  return It != std::end(supported);
323 }
324 
325 static std::vector<device> amendDeviceAndSubDevices(
326  backend PlatformBackend, std::vector<device> &DeviceList,
327  ods_target_list *OdsTargetList, const std::vector<int> &original_indices,
328  PlatformImplPtr PlatformImpl) {
329  constexpr info::partition_property partitionProperty =
330  info::partition_property::partition_by_affinity_domain;
331  constexpr info::partition_affinity_domain affinityDomain =
332  info::partition_affinity_domain::next_partitionable;
333 
334  std::vector<device> FinalResult;
335  // (Only) when amending sub-devices for ONEAPI_DEVICE_SELECTOR, all
336  // sub-devices are treated as root.
337  TempAssignGuard<bool> TAG(PlatformImpl->MAlwaysRootDevice, true);
338 
339  for (unsigned i = 0; i < DeviceList.size(); i++) {
340  // device has already been screened. The question is whether it should be a
341  // top level device and/or is expected to add its sub-devices to the list.
342  device &dev = DeviceList[i];
343  bool deviceAdded = false;
344  for (ods_target target : OdsTargetList->get()) {
345  backend TargetBackend = target.Backend.value_or(backend::all);
346  if (PlatformBackend == TargetBackend || TargetBackend == backend::all) {
347  bool deviceMatch = target.HasDeviceWildCard; // opencl:*
348  if (target.DeviceType) { // opencl:gpu
349  deviceMatch = ((target.DeviceType == info::device_type::all) ||
351  target.DeviceType));
352 
353  } else if (target.DeviceNum) { // opencl:0
354  deviceMatch = (target.DeviceNum.value() == original_indices[i]);
355  }
356 
357  if (deviceMatch) {
358  // Top level matches. Do we add it, or subdevices, or sub-sub-devices?
359  bool wantSubDevice =
360  target.SubDeviceNum || target.HasSubDeviceWildCard;
361  bool supportsSubPartitioning =
362  (supportsPartitionProperty(dev, partitionProperty) &&
363  supportsAffinityDomain(dev, partitionProperty, affinityDomain));
364  bool wantSubSubDevice =
365  target.SubSubDeviceNum || target.HasSubSubDeviceWildCard;
366 
367  // -- Add top level device.
368  if (!wantSubDevice) {
369  if (!deviceAdded) {
370  FinalResult.push_back(dev);
371  deviceAdded = true;
372  }
373  } else {
374  if (!supportsSubPartitioning) {
375  if (target.DeviceNum ||
376  (target.DeviceType &&
377  (target.DeviceType.value() != info::device_type::all))) {
378  // This device was specifically requested and yet is not
379  // partitionable.
380  std::cout << "device is not partitionable: " << target
381  << std::endl;
382  }
383  continue;
384  }
385  // -- Add sub sub device.
386  if (wantSubSubDevice) {
387 
388  auto subDevicesToPartition =
389  dev.create_sub_devices<partitionProperty>(affinityDomain);
390  if (target.SubDeviceNum) {
391  if (subDevicesToPartition.size() >
392  target.SubDeviceNum.value()) {
393  subDevicesToPartition[0] =
394  subDevicesToPartition[target.SubDeviceNum.value()];
395  subDevicesToPartition.resize(1);
396  } else {
397  std::cout << "subdevice index out of bounds: " << target
398  << std::endl;
399  continue;
400  }
401  }
402  for (device subDev : subDevicesToPartition) {
403  bool supportsSubSubPartitioning =
404  (supportsPartitionProperty(subDev, partitionProperty) &&
405  supportsAffinityDomain(subDev, partitionProperty,
406  affinityDomain));
407  if (!supportsSubSubPartitioning) {
408  if (target.SubDeviceNum) {
409  // Parent subdevice was specifically requested, yet is not
410  // partitionable.
411  std::cout << "sub-device is not partitionable: " << target
412  << std::endl;
413  }
414  continue;
415  }
416  // Allright, lets get them sub-sub-devices.
417  auto subSubDevices =
418  subDev.create_sub_devices<partitionProperty>(
419  affinityDomain);
420  if (target.HasSubSubDeviceWildCard) {
421  FinalResult.insert(FinalResult.end(), subSubDevices.begin(),
422  subSubDevices.end());
423  } else {
424  if (subSubDevices.size() > target.SubSubDeviceNum.value()) {
425  FinalResult.push_back(
426  subSubDevices[target.SubSubDeviceNum.value()]);
427  } else {
428  std::cout
429  << "sub-sub-device index out of bounds: " << target
430  << std::endl;
431  }
432  }
433  }
434  } else if (wantSubDevice) {
435  auto subDevices = dev.create_sub_devices<
436  info::partition_property::partition_by_affinity_domain>(
437  affinityDomain);
438  if (target.HasSubDeviceWildCard) {
439  FinalResult.insert(FinalResult.end(), subDevices.begin(),
440  subDevices.end());
441  } else {
442  if (subDevices.size() > target.SubDeviceNum.value()) {
443  FinalResult.push_back(
444  subDevices[target.SubDeviceNum.value()]);
445  } else {
446  std::cout << "subdevice index out of bounds: " << target
447  << std::endl;
448  }
449  }
450  }
451  }
452  } // /if deviceMatch
453  }
454  } // /for
455  } // /for
456  return FinalResult;
457 }
458 
459 std::vector<device>
460 platform_impl::get_devices(info::device_type DeviceType) const {
461  std::vector<device> Res;
462  // Will we be filtering with SYCL_DEVICE_FILTER or ONEAPI_DEVICE_SELECTOR ?
463  // We do NOT attempt to support both simultaneously.
466 
467  if (is_host() && (DeviceType == info::device_type::host ||
468  DeviceType == info::device_type::all)) {
469  Res.push_back(
470  createSyclObjFromImpl<device>(device_impl::getHostDeviceImpl()));
471  }
472 
473  // If any DeviceType other than host was requested for host platform,
474  // an empty vector will be returned.
475  if (is_host() || DeviceType == info::device_type::host)
476  return Res;
477 
478  pi_uint32 NumDevices = 0;
479  const detail::plugin &Plugin = getPlugin();
481  MPlatform, pi::cast<RT::PiDeviceType>(DeviceType),
482  0, // CP info::device_type::all
483  pi::cast<RT::PiDevice *>(nullptr), &NumDevices);
484  const backend Backend = Plugin.getBackend();
485 
486  if (NumDevices == 0) {
487  // If platform doesn't have devices (even without filter)
488  // LastDeviceIds[PlatformId] stay 0 that affects next platform devices num
489  // analysis. Doing adjustment by simple copy of last device num from
490  // previous platform.
491  // Needs non const plugin reference.
492  std::vector<plugin> &Plugins = RT::initialize();
493  auto It = std::find_if(Plugins.begin(), Plugins.end(),
494  [&Platform = MPlatform](plugin &Plugin) {
495  return Plugin.containsPiPlatform(Platform);
496  });
497  if (It != Plugins.end()) {
498  std::lock_guard<std::mutex> Guard(*(It->getPluginMutex()));
499  (*It).adjustLastDeviceId(MPlatform);
500  }
501  return Res;
502  }
503 
504  std::vector<RT::PiDevice> PiDevices(NumDevices);
505  // TODO catch an exception and put it to list of asynchronous exceptions
507  MPlatform,
508  pi::cast<RT::PiDeviceType>(DeviceType), // CP info::device_type::all
509  NumDevices, PiDevices.data(), nullptr);
510 
511  // Some elements of PiDevices vector might be filtered out, so make a copy of
512  // handles to do a cleanup later
513  std::vector<RT::PiDevice> PiDevicesToCleanUp = PiDevices;
514 
515  // Filter out devices that are not present in the SYCL_DEVICE_ALLOWLIST
517  applyAllowList(PiDevices, MPlatform, Plugin);
518 
519  // The first step is to filter out devices that are not compatible with
520  // SYCL_DEVICE_FILTER or ONEAPI_DEVICE_SELECTOR. This is also the mechanism by
521  // which top level device ids are assigned.
522  std::vector<int> PlatformDeviceIndices;
523  if (OdsTargetList) {
524  if (FilterList) {
525  throw sycl::exception(sycl::make_error_code(errc::invalid),
526  "ONEAPI_DEVICE_SELECTOR cannot be used in "
527  "conjunction with SYCL_DEVICE_FILTER");
528  }
529  PlatformDeviceIndices = filterDeviceFilter<ods_target_list, ods_target>(
530  PiDevices, MPlatform, OdsTargetList);
531  } else if (FilterList) {
532  PlatformDeviceIndices =
533  filterDeviceFilter<device_filter_list, device_filter>(
534  PiDevices, MPlatform, FilterList);
535  }
536 
537  // The next step is to inflate the filtered PIDevices into SYCL Device
538  // objects.
539  PlatformImplPtr PlatformImpl = getOrMakePlatformImpl(MPlatform, Plugin);
540  std::transform(
541  PiDevices.begin(), PiDevices.end(), std::back_inserter(Res),
542  [PlatformImpl](const RT::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 (RT::PiDevice &PiDev : PiDevicesToCleanUp)
550  Plugin.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 
574 pi_native_handle platform_impl::getNative() const {
575  const auto &Plugin = getPlugin();
576  pi_native_handle Handle;
577  Plugin.call<PiApiKind::piextPlatformGetNativeHandle>(getHandleRef(), &Handle);
578  return Handle;
579 }
580 
581 template <typename Param>
582 typename Param::return_type platform_impl::get_info() const {
583  if (is_host())
584  return get_platform_info_host<Param>();
585 
586  return get_platform_info<Param>(this->getHandleRef(), getPlugin());
587 }
588 
589 // All devices on the platform must have the given aspect.
590 bool platform_impl::has(aspect Aspect) const {
591  for (const auto &dev : get_devices()) {
592  if (dev.has(Aspect) == false) {
593  return false;
594  }
595  }
596  return true;
597 }
598 
599 std::shared_ptr<device_impl>
600 platform_impl::getDeviceImplHelper(RT::PiDevice PiDevice) {
601  for (const std::weak_ptr<device_impl> &DeviceWP : MDeviceCache) {
602  if (std::shared_ptr<device_impl> Device = DeviceWP.lock()) {
603  if (Device->getHandleRef() == PiDevice)
604  return Device;
605  }
606  }
607  return nullptr;
608 }
609 
610 #define __SYCL_PARAM_TRAITS_SPEC(DescType, Desc, ReturnT, PiCode) \
611  template ReturnT platform_impl::get_info<info::platform::Desc>() const;
612 
613 #include <sycl/info/platform_traits.def>
614 #undef __SYCL_PARAM_TRAITS_SPEC
615 
616 } // namespace detail
617 } // __SYCL_INLINE_VER_NAMESPACE(_V1)
618 } // namespace sycl
sycl::_V1::info::partition_affinity_domain
partition_affinity_domain
Definition: info_desc.hpp:63
sycl::_V1::backend
backend
Definition: backend_types.hpp:21
sycl::_V1::opencl::has_extension
bool has_extension(const sycl::platform &SyclPlatform, const std::string &Extension)
Definition: opencl.cpp:54
sycl::_V1::info::partition_property
partition_property
Definition: info_desc.hpp:55
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:92
config.hpp
device.hpp
__SYCL_INLINE_VER_NAMESPACE
#define __SYCL_INLINE_VER_NAMESPACE(X)
Definition: defines_elementary.hpp:11
sycl::_V1::detail::applyAllowList
void applyAllowList(std::vector< RT::PiDevice > &PiDevices, RT::PiPlatform PiPlatform, const plugin &Plugin)
Definition: allowlist.cpp:336
sycl::_V1::detail::pi::PiDevice
::pi_device PiDevice
Definition: pi.hpp:124
sycl::_V1::detail::SYCLConfig
Definition: config.hpp:110
sycl::_V1::detail::ods_target
Definition: device_filter.hpp:34
PI_DEVICE_INFO_PLATFORM
@ PI_DEVICE_INFO_PLATFORM
Definition: pi.h:269
sycl
---— Error handling, matching OpenCL plugin semantics.
Definition: access.hpp:14
sycl::_V1::detail::PiInfoCode
Definition: info_desc_helpers.hpp:18
device_impl.hpp
sycl::_V1::detail::plugin::getBackend
backend getBackend(void) const
Definition: plugin.hpp:229
sycl::_V1::detail::pi::PiPlatform
::pi_platform PiPlatform
Definition: pi.hpp:123
sycl::_V1::detail::filterDeviceFilter
static std::vector< int > filterDeviceFilter(std::vector< RT::PiDevice > &PiDevices, RT::PiPlatform Platform, ListT *FilterList)
Definition: platform_impl.cpp:169
sycl::_V1::detail::pi::getPlugin
const plugin & getPlugin()
Definition: pi.cpp:506
sycl::_V1::detail::pi::PiDeviceType
::pi_device_type PiDeviceType
Definition: pi.hpp:125
std::get
constexpr tuple_element< I, tuple< Types... > >::type & get(sycl::detail::tuple< Types... > &Arg) noexcept
Definition: tuple.hpp:199
sycl::_V1::detail::plugin
The plugin class provides a unified interface to the underlying low-level runtimes for the device-agn...
Definition: plugin.hpp:90
pi_uint32
uint32_t pi_uint32
Definition: pi.h:129
platform_impl.hpp
sycl::_V1::detail::TempAssignGuard
Definition: util.hpp:38
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:325
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_esimd_emulator.cpp:592
sycl::_V1::detail::IsBannedPlatform
static bool IsBannedPlatform(platform Platform)
Definition: platform_impl.cpp:70
global_handler.hpp
sycl::_V1::device
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:49
sycl::_V1::access::target
target
Definition: access.hpp:18
platform_info.hpp
sycl::_V1::info::device_type
device_type
Definition: info_desc.hpp:44
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_esimd_emulator.cpp:582
pi_native_handle
uintptr_t pi_native_handle
Definition: pi.h:133
sycl::_V1::detail::pi::initialize
std::vector< plugin > & initialize()
Definition: pi.cpp:397
piPlatformsGet
pi_result piPlatformsGet(pi_uint32 num_entries, pi_platform *platforms, pi_uint32 *num_platforms)
Definition: pi_esimd_emulator.cpp:401
iostream_proxy.hpp
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
sycl::_V1::detail::plugin::call
void call(ArgsT... Args) const
Calls the API, traces the call, checks the result.
Definition: plugin.hpp:217
piextPlatformGetNativeHandle
pi_result piextPlatformGetNativeHandle(pi_platform platform, pi_native_handle *nativeHandle)
Gets the native handle of a PI platform object.
Definition: pi_esimd_emulator.cpp:476
sycl::_V1::detail::ods_target_list
Definition: device_filter.hpp:55
sycl::_V1::detail::get_platform_info_string_impl
std::string get_platform_info_string_impl(RT::PiPlatform Plt, const plugin &Plugin, pi_platform_info PiCode)
Definition: platform_info.hpp:21
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_esimd_emulator.cpp:484
sycl::_V1::detail::pi::PI_TRACE_ALL
@ PI_TRACE_ALL
Definition: pi.hpp:58
sycl::_V1::detail::ods_target_list::get
std::vector< ods_target > & get()
Definition: device_filter.hpp:61
sycl::_V1::detail::plugin::getStartingDeviceId
int getStartingDeviceId(RT::PiPlatform Platform)
Definition: plugin.hpp:252
sycl::_V1::detail::plugin::setLastDeviceId
void setLastDeviceId(RT::PiPlatform Platform, int Id)
Definition: plugin.hpp:261
sycl::_V1::detail::plugin::getPluginMutex
std::shared_ptr< std::mutex > getPluginMutex()
Definition: plugin.hpp:281
util.hpp
sycl::_V1::platform
Encapsulates a SYCL platform on which kernels may be executed.
Definition: platform.hpp:45
allowlist.hpp
PI_DEVICE_INFO_TYPE
@ PI_DEVICE_INFO_TYPE
Definition: pi.h:210
sycl::_V1::detail::pi::trace
bool trace(TraceLevel level)
Definition: pi.cpp:391
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:317
sycl::_V1::detail::supportsAffinityDomain
static bool supportsAffinityDomain(const device &dev, info::partition_property partitionProp, info::partition_affinity_domain domain)
Definition: platform_impl.cpp:306
sycl::_V1::detail::getSyclObjImpl
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: common.hpp:300