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