[SYCL] Add sycl::device initial implementation (#176972)
This is part of the SYCL support upstreaming effort. The relevant RFCs can be found here: https://discourse.llvm.org/t/rfc-add-full-support-for-the-sycl-programming-model/74080 https://discourse.llvm.org/t/rfc-sycl-runtime-upstreaming/74479 Plan for next PR: E2E lit configs & test for get_platforms & get_devices impl context & USM free functions impl --------- Signed-off-by: Tikhomirova, Kseniya <kseniya.tikhomirova@intel.com>
This commit is contained in:
parent
4a6697f393
commit
debff92649
@ -1,6 +1,6 @@
|
||||
=====================
|
||||
===========================
|
||||
SYCL runtime implementation
|
||||
=====================
|
||||
===========================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
@ -8,7 +8,7 @@ SYCL runtime implementation
|
||||
.. _index:
|
||||
|
||||
Current Status
|
||||
========
|
||||
==============
|
||||
|
||||
The implementation is in the very early stages of upstreaming. The first
|
||||
milestone is to get
|
||||
@ -59,7 +59,7 @@ libsycl side:
|
||||
from the multi-architectural binaries
|
||||
|
||||
Build steps
|
||||
========
|
||||
===========
|
||||
|
||||
To build LLVM with libsycl runtime enabled the following script can be used.
|
||||
|
||||
@ -87,7 +87,22 @@ To build LLVM with libsycl runtime enabled the following script can be used.
|
||||
|
||||
|
||||
Limitations
|
||||
========
|
||||
===========
|
||||
|
||||
Libsycl is not currently supported on Windows because it depends on liboffload
|
||||
which doesn't currently support Windows.
|
||||
|
||||
TODO for added SYCL classes
|
||||
===========================
|
||||
|
||||
* ``exception``: methods with context are not implemented, to add once context is ready
|
||||
* ``platform``: deprecated info descriptor is not implemented (info::platform::extensions), to implement on RT level with ``device::get_info<info::device::aspects>()``
|
||||
* ``device``:
|
||||
|
||||
* ``get_info``: to find an efficient way to map descriptors to liboffload types, add other descriptors, add cache of info data
|
||||
* ``has(aspect)``: same as get_info
|
||||
* ``create_sub_devices``: partitioning is not supported by liboffload now, blocked
|
||||
* ``has_extension``: deprecated API, to implement on RT level with ``device::has``
|
||||
|
||||
* device selection: to add compatibility with old SYCL 1.2.1 device selectors, still part of SYCL 2020 specification
|
||||
|
||||
|
||||
43
libsycl/include/sycl/__impl/aspect.hpp
Normal file
43
libsycl/include/sycl/__impl/aspect.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBSYCL___IMPL_ASPECT_HPP
|
||||
#define _LIBSYCL___IMPL_ASPECT_HPP
|
||||
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
// SYCL 2020 4.6.4.5. Aspects.
|
||||
enum class aspect : std::uint32_t {
|
||||
cpu,
|
||||
gpu,
|
||||
accelerator,
|
||||
custom,
|
||||
emulated,
|
||||
host_debuggable,
|
||||
fp16,
|
||||
fp64,
|
||||
atomic64,
|
||||
image,
|
||||
online_compiler,
|
||||
online_linker,
|
||||
queue_profiling,
|
||||
usm_device_allocations,
|
||||
usm_host_allocations,
|
||||
usm_atomic_host_allocations,
|
||||
usm_shared_allocations,
|
||||
usm_atomic_shared_allocations,
|
||||
usm_system_allocations
|
||||
};
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
|
||||
#endif // _LIBSYCL___IMPL_ASPECT_HPP
|
||||
183
libsycl/include/sycl/__impl/device.hpp
Normal file
183
libsycl/include/sycl/__impl/device.hpp
Normal file
@ -0,0 +1,183 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains the declaration of the SYCL 2020 device class, which
|
||||
/// represents a single SYCL device on which kernels can be executed.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBSYCL___IMPL_DEVICE_HPP
|
||||
#define _LIBSYCL___IMPL_DEVICE_HPP
|
||||
|
||||
#include <sycl/__impl/aspect.hpp>
|
||||
#include <sycl/__impl/backend.hpp>
|
||||
#include <sycl/__impl/device_selector.hpp>
|
||||
#include <sycl/__impl/info/device.hpp>
|
||||
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
#include <sycl/__impl/detail/obj_utils.hpp>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
class platform;
|
||||
|
||||
namespace detail {
|
||||
class DeviceImpl;
|
||||
} // namespace detail
|
||||
|
||||
// SYCL 2020 4.6.4. Device class.
|
||||
class _LIBSYCL_EXPORT device {
|
||||
public:
|
||||
device(const device &rhs) = default;
|
||||
|
||||
device(device &&rhs) = default;
|
||||
|
||||
device &operator=(const device &rhs) = default;
|
||||
|
||||
device &operator=(device &&rhs) = default;
|
||||
|
||||
friend bool operator==(const device &lhs, const device &rhs) {
|
||||
return lhs.impl == rhs.impl;
|
||||
}
|
||||
|
||||
friend bool operator!=(const device &lhs, const device &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/// Constructs a SYCL device instance using the default device (device chosen
|
||||
/// by default device selector).
|
||||
device();
|
||||
|
||||
/// Constructs a SYCL device instance using the device
|
||||
/// identified by the provided device selector.
|
||||
/// \param DeviceSelector is SYCL 2020 device selector, a simple callable that
|
||||
/// takes a device and returns an int.
|
||||
template <
|
||||
typename DeviceSelector,
|
||||
// `DeviceImpl` (used as a parameter in private ctor) is incomplete
|
||||
// so would result in a error trying to instantiate
|
||||
// `EnableIfDeviceSelectorIsInvocable` below. Filter it out
|
||||
// before trying to do that.
|
||||
typename =
|
||||
std::enable_if_t<!std::is_same_v<DeviceSelector, detail::DeviceImpl>>,
|
||||
typename = detail::EnableIfDeviceSelectorIsInvocable<DeviceSelector>>
|
||||
explicit device(const DeviceSelector &deviceSelector)
|
||||
: device(detail::SelectDevice(deviceSelector)) {}
|
||||
|
||||
/// Returns the backend associated with this device.
|
||||
///
|
||||
/// \return the backend associated with this device.
|
||||
backend get_backend() const noexcept;
|
||||
|
||||
/// Check if device is a CPU device.
|
||||
///
|
||||
/// \return true if SYCL device is a CPU device.
|
||||
bool is_cpu() const;
|
||||
|
||||
/// Check if device is a GPU device.
|
||||
///
|
||||
/// \return true if SYCL device is a GPU device.
|
||||
bool is_gpu() const;
|
||||
|
||||
/// Check if device is an accelerator device.
|
||||
///
|
||||
/// \return true if SYCL device is an accelerator device.
|
||||
bool is_accelerator() const;
|
||||
|
||||
/// Get associated SYCL platform.
|
||||
///
|
||||
/// \return The associated SYCL platform.
|
||||
platform get_platform() const;
|
||||
|
||||
/// Queries this SYCL device for information requested by the template
|
||||
/// parameter param.
|
||||
///
|
||||
/// \return device info of type described in 4.6.4.4.
|
||||
template <typename Param>
|
||||
detail::is_device_info_desc_t<Param> get_info() const;
|
||||
|
||||
/// Queries this SYCL device for SYCL backend-specific information.
|
||||
///
|
||||
/// The return type depends on information being queried.
|
||||
template <typename Param>
|
||||
typename detail::is_backend_info_desc<Param>::return_type
|
||||
get_backend_info() const;
|
||||
|
||||
/// Queries which optional features this device supports (if any).
|
||||
///
|
||||
/// \return true if this device has the given aspect.
|
||||
bool has(aspect asp) const;
|
||||
|
||||
/// Partition device into sub devices.
|
||||
///
|
||||
/// Available only when prop is info::partition_property::partition_equally.
|
||||
/// If this SYCL device does not support
|
||||
/// info::partition_property::partition_equally a feature_not_supported
|
||||
/// exception will be thrown.
|
||||
///
|
||||
/// \param ComputeUnits is a desired count of compute units in each sub
|
||||
/// device.
|
||||
/// \return sub devices partitioned from this SYCL device equally based on the
|
||||
/// ComputeUnits parameter.
|
||||
template <info::partition_property prop>
|
||||
std::vector<device> create_sub_devices(size_t ComputeUnits) const;
|
||||
|
||||
/// Partition device into sub devices.
|
||||
///
|
||||
/// Available only when prop is info::partition_property::partition_by_counts.
|
||||
/// If this SYCL device does not support
|
||||
/// info::partition_property::partition_by_counts a feature_not_supported
|
||||
/// exception will be thrown.
|
||||
///
|
||||
/// \param Counts is a std::vector of desired compute units in sub devices.
|
||||
/// \return sub devices partitioned from this SYCL device by count sizes based
|
||||
/// on the Counts parameter.
|
||||
template <info::partition_property prop>
|
||||
std::vector<device>
|
||||
create_sub_devices(const std::vector<size_t> &Counts) const;
|
||||
|
||||
/// Partition device into sub devices.
|
||||
///
|
||||
/// Available only when prop is
|
||||
/// info::partition_property::partition_by_affinity_domain. If this SYCL
|
||||
/// device does not support
|
||||
/// info::partition_property::partition_by_affinity_domain or the SYCL device
|
||||
/// does not support provided info::affinity_domain provided a
|
||||
/// feature_not_supported exception will be thrown.
|
||||
///
|
||||
/// \param AffinityDomain is one of the values described in Table 4.20 of the
|
||||
/// SYCL 2020 specification.
|
||||
/// \return sub devices partitioned from this SYCL device by affinity domain
|
||||
/// based on the AffinityDomain parameter.
|
||||
template <info::partition_property prop>
|
||||
std::vector<device>
|
||||
create_sub_devices(info::partition_affinity_domain AffinityDomain) const;
|
||||
|
||||
/// Query available SYCL devices.
|
||||
///
|
||||
/// \param deviceType is one of the values described in A.3 of the SYCL 2020
|
||||
/// specification.
|
||||
/// \return all SYCL devices available in the system of the device type
|
||||
/// specified.
|
||||
static std::vector<device>
|
||||
get_devices(info::device_type deviceType = info::device_type::all);
|
||||
|
||||
private:
|
||||
device(detail::DeviceImpl &Impl) : impl(&Impl) {}
|
||||
detail::DeviceImpl *impl;
|
||||
|
||||
friend sycl::detail::ImplUtils;
|
||||
}; // class device
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
|
||||
template <>
|
||||
struct std::hash<sycl::device> : public sycl::detail::HashBase<sycl::device> {};
|
||||
|
||||
#endif // _LIBSYCL___IMPL_DEVICE_HPP
|
||||
122
libsycl/include/sycl/__impl/device_selector.hpp
Normal file
122
libsycl/include/sycl/__impl/device_selector.hpp
Normal file
@ -0,0 +1,122 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains the declaration of the standard device selectors
|
||||
/// (SYCL 2020 4.6.1.1. Device selector).
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBSYCL___IMPL_DEVICE_SELECTOR_HPP
|
||||
#define _LIBSYCL___IMPL_DEVICE_SELECTOR_HPP
|
||||
|
||||
#include <sycl/__impl/aspect.hpp>
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
|
||||
#include <functional>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
class device;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// SYCL 2020 4.6.1.1. Device selector:
|
||||
// The interface for a device selector is any object that meets the C++ named
|
||||
// requirement Callable, taking a parameter of type const device & and returning
|
||||
// a value that is implicitly convertible to int.
|
||||
using DeviceSelectorInvocableType = std::function<int(const sycl::device &)>;
|
||||
|
||||
template <typename DeviceSelector>
|
||||
using EnableIfDeviceSelectorIsInvocable = std::enable_if_t<
|
||||
std::is_invocable_r_v<int, DeviceSelector &, const device &>>;
|
||||
|
||||
/// Returns a SYCL device instance chosen by the device selector provided.
|
||||
///
|
||||
/// \param DeviceSelector is SYCL 2020 device selector, a simple callable that
|
||||
/// takes a device and returns an int.
|
||||
/// \return device chosen by selector.
|
||||
_LIBSYCL_EXPORT device
|
||||
SelectDevice(const DeviceSelectorInvocableType &DeviceSelector);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Standard device selector to select SYCL device from any supported SYCL
|
||||
/// backend based on an implementation-defined heuristic.
|
||||
///
|
||||
/// \param Dev device to calculate the score for.
|
||||
/// \return score value for the provided device. Further device selection is
|
||||
/// based on score values.
|
||||
_LIBSYCL_EXPORT int default_selector_v(const device &Dev);
|
||||
|
||||
/// Standard device selector to select SYCL device from any supported SYCL
|
||||
/// backend for which the device type is info::device_type::gpu.
|
||||
///
|
||||
/// \param Dev device to calculate the score for.
|
||||
/// \return score value for the provided device. Further device selection is
|
||||
/// based on score values.
|
||||
_LIBSYCL_EXPORT int gpu_selector_v(const device &Dev);
|
||||
|
||||
/// Standard device selector to select SYCL device from any supported SYCL
|
||||
/// backend for which the device type is info::device_type::cpu.
|
||||
///
|
||||
/// \param Dev device to calculate the score for.
|
||||
/// \return score value for the provided device. Further device selection is
|
||||
/// based on score values.
|
||||
_LIBSYCL_EXPORT int cpu_selector_v(const device &Dev);
|
||||
|
||||
/// Standard device selector to select SYCL device from any supported SYCL
|
||||
/// backend for which the device type is info::device_type::accelerator.
|
||||
///
|
||||
/// \param Dev device to calculate the score for.
|
||||
/// \return score value for the provided device. Further device selection is
|
||||
/// based on score values.
|
||||
_LIBSYCL_EXPORT int accelerator_selector_v(const device &Dev);
|
||||
|
||||
/// Returns a selector object that selects a SYCL device from any supported SYCL
|
||||
/// backend which contains all the requested aspects.
|
||||
///
|
||||
/// \param RequireList requested aspects, i.e. for the specific device dev and
|
||||
/// each aspect devAspect from RequireList dev.has(devAspect) equals true.
|
||||
/// \param DenyList all the aspects that have to be avoided, i.e. for the
|
||||
/// specific device dev and each aspect devAspect from denyList
|
||||
/// dev.has(devAspect) equals false.
|
||||
/// \return a selector object
|
||||
_LIBSYCL_EXPORT detail::DeviceSelectorInvocableType
|
||||
aspect_selector(const std::vector<aspect> &RequireList,
|
||||
const std::vector<aspect> &DenyList = {});
|
||||
|
||||
/// Returns a selector object that selects a SYCL device from any supported SYCL
|
||||
/// backend which contains all the requested aspects.
|
||||
///
|
||||
/// \param AspectList requested aspects, i.e. for the specific device dev and
|
||||
/// each aspect devAspect from AspectList dev.has(devAspect) equals true.
|
||||
/// \return a selector object
|
||||
template <typename... AspectListT>
|
||||
detail::DeviceSelectorInvocableType aspect_selector(AspectListT... AspectList) {
|
||||
std::vector<aspect> RequireList;
|
||||
RequireList.reserve(sizeof...(AspectList));
|
||||
(RequireList.emplace_back(AspectList), ...);
|
||||
|
||||
return aspect_selector(RequireList, {});
|
||||
}
|
||||
|
||||
/// Returns a selector object that selects a SYCL device from any supported SYCL
|
||||
/// backend which contains all the requested aspects.
|
||||
///
|
||||
/// \param AspectList requested aspects, i.e. for the specific device dev and
|
||||
/// each aspect devAspect from AspectList dev.has(devAspect) equals true.
|
||||
/// \return a selector object
|
||||
template <aspect... AspectList>
|
||||
detail::DeviceSelectorInvocableType aspect_selector() {
|
||||
return aspect_selector({AspectList...}, {});
|
||||
}
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
|
||||
#endif //_LIBSYCL___IMPL_DEVICE_SELECTOR_HPP
|
||||
79
libsycl/include/sycl/__impl/info/device.hpp
Normal file
79
libsycl/include/sycl/__impl/info/device.hpp
Normal file
@ -0,0 +1,79 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains the declaration of SYCL 2020 device info types.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBSYCL___IMPL_INFO_DEVICE_HPP
|
||||
#define _LIBSYCL___IMPL_INFO_DEVICE_HPP
|
||||
|
||||
#include <sycl/__impl/aspect.hpp>
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
#include <sycl/__impl/info/desc_base.hpp>
|
||||
#include <sycl/__impl/info/device_type.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
class device;
|
||||
class platform;
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
using is_device_info_desc_t = typename is_info_desc<T, device>::return_type;
|
||||
} // namespace detail
|
||||
|
||||
// SYCL 2020 A.3. Device information descriptors.
|
||||
namespace info {
|
||||
|
||||
enum class partition_property : std::uint32_t {
|
||||
no_partition = 0,
|
||||
partition_equally,
|
||||
partition_by_counts,
|
||||
partition_by_affinity_domain
|
||||
};
|
||||
|
||||
enum class partition_affinity_domain : std::uint32_t {
|
||||
not_applicable = 0,
|
||||
numa,
|
||||
L4_cache,
|
||||
L3_cache,
|
||||
L2_cache,
|
||||
L1_cache,
|
||||
next_partitionable
|
||||
};
|
||||
|
||||
namespace device {
|
||||
// SYCL 2020 4.6.4.4. Information descriptors.
|
||||
|
||||
struct device_type : detail::info_desc_tag<device_type, sycl::device> {
|
||||
using return_type = sycl::info::device_type;
|
||||
};
|
||||
struct name : detail::info_desc_tag<name, sycl::device> {
|
||||
using return_type = std::string;
|
||||
};
|
||||
struct vendor : detail::info_desc_tag<vendor, sycl::device> {
|
||||
using return_type = std::string;
|
||||
};
|
||||
struct driver_version : detail::info_desc_tag<driver_version, sycl::device> {
|
||||
using return_type = std::string;
|
||||
};
|
||||
struct platform : detail::info_desc_tag<platform, sycl::device> {
|
||||
using return_type = sycl::platform;
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
} // namespace info
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
|
||||
#endif // _LIBSYCL___IMPL_INFO_DEVICE_HPP
|
||||
35
libsycl/include/sycl/__impl/info/device_type.hpp
Normal file
35
libsycl/include/sycl/__impl/info/device_type.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBSYCL___IMPL_INFO_DEVICE_TYPE_HPP
|
||||
#define _LIBSYCL___IMPL_INFO_DEVICE_TYPE_HPP
|
||||
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
namespace info {
|
||||
|
||||
// SYCL 2020 4.6.4.7.1. Device type.
|
||||
enum class device_type : std::uint32_t {
|
||||
cpu = 0,
|
||||
gpu,
|
||||
accelerator,
|
||||
custom,
|
||||
automatic,
|
||||
host, // Deprecated by SYCL 2020
|
||||
all
|
||||
};
|
||||
|
||||
} // namespace info
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
|
||||
#endif // _LIBSYCL___IMPL_INFO_DEVICE_TYPE_HPP
|
||||
@ -15,9 +15,11 @@
|
||||
#ifndef _LIBSYCL___IMPL_PLATFORM_HPP
|
||||
#define _LIBSYCL___IMPL_PLATFORM_HPP
|
||||
|
||||
#include <sycl/__impl/aspect.hpp>
|
||||
#include <sycl/__impl/backend.hpp>
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
#include <sycl/__impl/detail/obj_utils.hpp>
|
||||
#include <sycl/__impl/info/device_type.hpp>
|
||||
#include <sycl/__impl/info/platform.hpp>
|
||||
|
||||
#include <memory>
|
||||
@ -25,6 +27,8 @@
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
class device;
|
||||
|
||||
namespace detail {
|
||||
class PlatformImpl;
|
||||
} // namespace detail
|
||||
@ -56,6 +60,16 @@ public:
|
||||
/// \return the backend associated with this platform.
|
||||
backend get_backend() const noexcept;
|
||||
|
||||
/// Returns all SYCL devices associated with this platform.
|
||||
///
|
||||
/// If there are no devices that match given device
|
||||
/// type, resulting vector is empty.
|
||||
///
|
||||
/// \param DeviceType is a SYCL device type.
|
||||
/// \return a vector of SYCL devices matching given device type.
|
||||
std::vector<device>
|
||||
get_devices(info::device_type DeviceType = info::device_type::all) const;
|
||||
|
||||
/// Queries this SYCL platform for info.
|
||||
///
|
||||
/// The return type depends on information being queried.
|
||||
@ -69,6 +83,15 @@ public:
|
||||
typename detail::is_backend_info_desc<Param>::return_type
|
||||
get_backend_info() const;
|
||||
|
||||
/// Indicates if all of the SYCL devices on this platform have the
|
||||
/// given aspect.
|
||||
///
|
||||
/// \param Aspect is one of the values defined in SYCL 2020 Section 4.6.4.5.
|
||||
///
|
||||
/// \return true if all of the SYCL devices on this platform have the
|
||||
/// given aspect.
|
||||
bool has(aspect Aspect) const;
|
||||
|
||||
/// Returns all SYCL platforms from all backends that are available in the
|
||||
/// system.
|
||||
///
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
#ifndef _LIBSYCL_SYCL_HPP
|
||||
#define _LIBSYCL_SYCL_HPP
|
||||
|
||||
#include <sycl/__impl/device.hpp>
|
||||
#include <sycl/__impl/device_selector.hpp>
|
||||
#include <sycl/__impl/exception.hpp>
|
||||
#include <sycl/__impl/platform.hpp>
|
||||
|
||||
|
||||
@ -83,7 +83,10 @@ endfunction(add_sycl_rt_library)
|
||||
set(LIBSYCL_SOURCES
|
||||
"exception.cpp"
|
||||
"exception_list.cpp"
|
||||
"device.cpp"
|
||||
"device_selector.cpp"
|
||||
"platform.cpp"
|
||||
"detail/device_impl.cpp"
|
||||
"detail/global_objects.cpp"
|
||||
"detail/platform_impl.cpp"
|
||||
"detail/offload/offload_utils.cpp"
|
||||
|
||||
55
libsycl/src/detail/device_impl.cpp
Normal file
55
libsycl/src/detail/device_impl.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <detail/device_impl.hpp>
|
||||
#include <detail/platform_impl.hpp>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
namespace detail {
|
||||
|
||||
bool DeviceImpl::has(aspect Aspect) const {
|
||||
switch (Aspect) {
|
||||
case (aspect::cpu):
|
||||
return isCPU();
|
||||
case (aspect::gpu):
|
||||
return isGPU();
|
||||
case (aspect::accelerator):
|
||||
return isAccelerator();
|
||||
case (aspect::custom):
|
||||
return false;
|
||||
case (aspect::emulated):
|
||||
return false;
|
||||
case (aspect::host_debuggable):
|
||||
return false;
|
||||
default:
|
||||
// Other aspects are not implemented yet
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
info::device_type DeviceImpl::getDeviceType() const {
|
||||
return getInfo<info::device::device_type>();
|
||||
}
|
||||
|
||||
bool DeviceImpl::isCPU() const {
|
||||
return getDeviceType() == info::device_type::cpu;
|
||||
}
|
||||
|
||||
bool DeviceImpl::isGPU() const {
|
||||
return getDeviceType() == info::device_type::gpu;
|
||||
}
|
||||
|
||||
bool DeviceImpl::isAccelerator() const {
|
||||
return getDeviceType() == info::device_type::accelerator;
|
||||
}
|
||||
|
||||
backend DeviceImpl::getBackend() const { return MPlatform.getBackend(); }
|
||||
|
||||
} // namespace detail
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
127
libsycl/src/detail/device_impl.hpp
Normal file
127
libsycl/src/detail/device_impl.hpp
Normal file
@ -0,0 +1,127 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBSYCL_DEVICE_IMPL
|
||||
#define _LIBSYCL_DEVICE_IMPL
|
||||
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
#include <sycl/__impl/device.hpp>
|
||||
|
||||
#include <detail/offload/offload_utils.hpp>
|
||||
#include <detail/platform_impl.hpp>
|
||||
|
||||
#include <OffloadAPI.h>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
namespace detail {
|
||||
|
||||
class DeviceImpl {
|
||||
// Helper to limit DeviceImpl creation. It must be created in platform ctor
|
||||
// only. Using tag instead of private ctor + friend class to allow make_unique
|
||||
// usage and to align with classes which impl is shared_ptr<>.
|
||||
struct PrivateTag {
|
||||
explicit PrivateTag() = default;
|
||||
};
|
||||
friend class PlatformImpl;
|
||||
|
||||
public:
|
||||
/// Constructs a SYCL device instance using the provided
|
||||
/// offload device instance.
|
||||
///
|
||||
/// \param Device is a raw offload library handle representing device.
|
||||
/// \param Platform is a platform this device belongs to.
|
||||
/// All device impls must be created in corresponding platform ctor.
|
||||
explicit DeviceImpl(ol_device_handle_t Device, PlatformImpl &Platform,
|
||||
PrivateTag)
|
||||
: MOffloadDevice(Device), MPlatform(Platform) {}
|
||||
|
||||
~DeviceImpl() = default;
|
||||
|
||||
/// Queries device type from offloading runtime
|
||||
///
|
||||
/// \return device type of the device
|
||||
info::device_type getDeviceType() const;
|
||||
|
||||
/// Check if device is a CPU device
|
||||
///
|
||||
/// \return true if SYCL device is a CPU device
|
||||
bool isCPU() const;
|
||||
|
||||
/// Check if device is a GPU device
|
||||
///
|
||||
/// \return true if SYCL device is a GPU device
|
||||
bool isGPU() const;
|
||||
|
||||
/// Check if device is an accelerator device
|
||||
///
|
||||
/// \return true if SYCL device is an accelerator device
|
||||
bool isAccelerator() const;
|
||||
|
||||
/// Returns the backend associated with this device.
|
||||
///
|
||||
/// \return the sycl::backend associated with this device.
|
||||
backend getBackend() const;
|
||||
|
||||
/// Returns the implementation class object of platform associated with this
|
||||
/// device.
|
||||
///
|
||||
/// \return platform implementation object this device belongs to.
|
||||
PlatformImpl &getPlatformImpl() const { return MPlatform; }
|
||||
|
||||
/// Checks if this device supports aspect.
|
||||
///
|
||||
/// \param Aspect to perform a check of.
|
||||
/// \return true if this device has the given aspect.
|
||||
bool has(aspect Aspect) const;
|
||||
|
||||
/// Queries this device for information requested by the template parameter
|
||||
/// param.
|
||||
/// The return type depends on information being queried.
|
||||
template <typename Param> typename Param::return_type getInfo() const {
|
||||
using namespace info::device;
|
||||
using Map = info_ol_mapping<ol_device_info_t>;
|
||||
|
||||
constexpr ol_device_info_t olInfo = map_info_desc<Param, ol_device_info_t>(
|
||||
Map::M<device_type>{OL_DEVICE_INFO_TYPE},
|
||||
Map::M<name>{OL_DEVICE_INFO_NAME},
|
||||
Map::M<vendor>{OL_DEVICE_INFO_VENDOR},
|
||||
Map::M<driver_version>{OL_DEVICE_INFO_DRIVER_VERSION});
|
||||
|
||||
size_t ExpectedSize = 0;
|
||||
callAndThrow(olGetDeviceInfoSize, MOffloadDevice, olInfo, &ExpectedSize);
|
||||
|
||||
if constexpr (std::is_same_v<typename Param::return_type, std::string>) {
|
||||
std::string Result;
|
||||
// liboffload counts null terminator in the size while std::string
|
||||
// doesn't.
|
||||
Result.resize(ExpectedSize - 1);
|
||||
callAndThrow(olGetDeviceInfo, MOffloadDevice, olInfo, ExpectedSize,
|
||||
Result.data());
|
||||
return Result;
|
||||
} else if constexpr (olInfo == OL_DEVICE_INFO_TYPE) {
|
||||
assert((sizeof(typename Param::return_type) == ExpectedSize) &&
|
||||
"Size of info descriptor reported by backend doesn't match with "
|
||||
"expected.");
|
||||
ol_device_type_t olType{};
|
||||
callAndThrow(olGetDeviceInfo, MOffloadDevice, olInfo, sizeof(olType),
|
||||
&olType);
|
||||
return convertDeviceTypeToSYCL(olType);
|
||||
} else
|
||||
static_assert(false && "Info descriptor is not properly supported");
|
||||
}
|
||||
|
||||
private:
|
||||
ol_device_handle_t MOffloadDevice = {};
|
||||
PlatformImpl &MPlatform;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
|
||||
#endif // _LIBSYCL_DEVICE_IMPL
|
||||
@ -29,7 +29,7 @@ std::vector<PlatformImplUPtr> &getPlatformCache() {
|
||||
return PlatformCache;
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
static void shutdown() {
|
||||
// No error reporting in shutdown
|
||||
std::ignore = olShutDown();
|
||||
}
|
||||
|
||||
@ -11,18 +11,57 @@
|
||||
#include <detail/offload/offload_utils.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Platforms for this backend
|
||||
range_view<const ol_platform_handle_t> OffloadTopology::getPlatforms() const {
|
||||
return {MPlatforms.data(), MPlatforms.size()};
|
||||
}
|
||||
|
||||
// Devices for a specific platform (PlatformId is index into Platforms)
|
||||
range_view<ol_device_handle_t>
|
||||
OffloadTopology::getDevices(size_t PlatformId) const {
|
||||
if (PlatformId >= MDeviceRange.size()) {
|
||||
return {nullptr, 0};
|
||||
}
|
||||
return MDeviceRange[PlatformId];
|
||||
}
|
||||
|
||||
void OffloadTopology::registerNewPlatformsAndDevices(
|
||||
Platform2DevContainer &PlatformsAndDev) {
|
||||
if (!PlatformsAndDev.size())
|
||||
return;
|
||||
|
||||
// MDeviceRange is populated with iterators of MDevices. Allocate required
|
||||
// space in advance to keep them valid.
|
||||
MDevices.reserve(PlatformsAndDev.size());
|
||||
|
||||
for (auto &[Platform, NewDev] : PlatformsAndDev) {
|
||||
MDevices.push_back(NewDev);
|
||||
|
||||
// Platform is not unique within PlatformsAndDev but the container is sorted
|
||||
if (MPlatforms.empty() || MPlatforms.back() != Platform) {
|
||||
MPlatforms.push_back(Platform);
|
||||
range_view<ol_device_handle_t> R{&MDevices.back(), 1 /*Size == 1*/};
|
||||
MDeviceRange.push_back(R);
|
||||
} else {
|
||||
// Device is inserted already, just increment device count for the current
|
||||
// platform
|
||||
MDeviceRange.back().len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void discoverOffloadDevices() {
|
||||
callAndThrow(olInit);
|
||||
|
||||
// liboffload returns devices sorted by backend + platform. We rely on this
|
||||
// behavior during device enumeration.
|
||||
using PerBackendDataType =
|
||||
std::array<std::pair<PlatformWithDevStorageType, size_t /*DevCount*/>,
|
||||
OL_PLATFORM_BACKEND_LAST>;
|
||||
std::array<Platform2DevContainer, OL_PLATFORM_BACKEND_LAST>;
|
||||
|
||||
PerBackendDataType Mapping;
|
||||
// olIterateDevices() calls the lambda for each device. Devices that fail
|
||||
@ -31,17 +70,19 @@ void discoverOffloadDevices() {
|
||||
// first failure and interrupt iteration.
|
||||
callNoCheck(
|
||||
olIterateDevices,
|
||||
[](ol_device_handle_t Dev, void *User) -> bool {
|
||||
auto *Data = static_cast<PerBackendDataType *>(User);
|
||||
ol_platform_handle_t Plat = nullptr;
|
||||
ol_result_t Res = callNoCheck(
|
||||
olGetDeviceInfo, Dev, OL_DEVICE_INFO_PLATFORM, sizeof(Plat), &Plat);
|
||||
[](ol_device_handle_t Dev, void *UserData) -> bool {
|
||||
auto *Data = static_cast<PerBackendDataType *>(UserData);
|
||||
|
||||
ol_platform_handle_t Platform = nullptr;
|
||||
ol_result_t Res =
|
||||
callNoCheck(olGetDeviceInfo, Dev, OL_DEVICE_INFO_PLATFORM,
|
||||
sizeof(Platform), &Platform);
|
||||
// If an error occurs, ignore the device and continue iteration.
|
||||
if (Res != OL_SUCCESS)
|
||||
return true;
|
||||
|
||||
ol_platform_backend_t OlBackend = OL_PLATFORM_BACKEND_UNKNOWN;
|
||||
Res = callNoCheck(olGetPlatformInfo, Plat, OL_PLATFORM_INFO_BACKEND,
|
||||
Res = callNoCheck(olGetPlatformInfo, Platform, OL_PLATFORM_INFO_BACKEND,
|
||||
sizeof(OlBackend), &OlBackend);
|
||||
// If an error occurs, ignore the device and continue iteration.
|
||||
if (Res != OL_SUCCESS)
|
||||
@ -58,9 +99,7 @@ void discoverOffloadDevices() {
|
||||
if (OlBackend >= OL_PLATFORM_BACKEND_LAST)
|
||||
return true;
|
||||
|
||||
auto &[Map, DevCount] = (*Data)[static_cast<size_t>(OlBackend)];
|
||||
Map[Plat].push_back(Dev);
|
||||
DevCount++;
|
||||
(*Data)[static_cast<size_t>(OlBackend)].push_back({Platform, Dev});
|
||||
return true;
|
||||
},
|
||||
&Mapping);
|
||||
@ -69,7 +108,7 @@ void discoverOffloadDevices() {
|
||||
for (size_t I = 0; I < OL_PLATFORM_BACKEND_LAST; ++I) {
|
||||
OffloadTopology &Topo = OffloadTopologies[I];
|
||||
Topo.setBackend(static_cast<ol_platform_backend_t>(I));
|
||||
Topo.registerNewPlatformsAndDevices(Mapping[I].first, Mapping[I].second);
|
||||
Topo.registerNewPlatformsAndDevices(Mapping[I]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
#include <OffloadAPI.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
@ -31,8 +30,8 @@ template <class T> struct range_view {
|
||||
size_t size() const { return len; }
|
||||
};
|
||||
|
||||
using PlatformWithDevStorageType =
|
||||
std::unordered_map<ol_platform_handle_t, std::vector<ol_device_handle_t>>;
|
||||
using Platform2DevContainer =
|
||||
std::vector<std::pair<ol_platform_handle_t, ol_device_handle_t>>;
|
||||
|
||||
/// Contiguous global storage of platform handlers and device handles (grouped
|
||||
/// by platform) for a backend.
|
||||
@ -45,71 +44,42 @@ struct OffloadTopology {
|
||||
/// \param B new backend value.
|
||||
void setBackend(ol_platform_backend_t B) { MBackend = B; }
|
||||
|
||||
/// Queries backend of this topology.
|
||||
///
|
||||
/// \returns backend of this topology.
|
||||
ol_platform_backend_t getBackend() const { return MBackend; }
|
||||
|
||||
/// Returns all platforms associated with this topology.
|
||||
///
|
||||
/// \returns minimal span-like view to platforms associated with this
|
||||
/// topology.
|
||||
range_view<const ol_platform_handle_t> platforms() const {
|
||||
return {MPlatforms.data(), MPlatforms.size()};
|
||||
}
|
||||
range_view<const ol_platform_handle_t> getPlatforms() const;
|
||||
|
||||
/// Returns all devices associated with specific platform.
|
||||
///
|
||||
/// \param PlatformId platform_id is index into MPlatforms.
|
||||
/// \param PlatformId is index into MPlatforms.
|
||||
///
|
||||
/// \returns minimal span-like view to devices associated with specified
|
||||
/// platform.
|
||||
range_view<const ol_device_handle_t>
|
||||
devicesForPlatform(size_t PlatformId) const {
|
||||
if (PlatformId >= MDevRangePerPlatformId.size()) {
|
||||
assert(false && "Platform index exceeds number of platforms.");
|
||||
return {nullptr, 0};
|
||||
}
|
||||
return MDevRangePerPlatformId[PlatformId];
|
||||
}
|
||||
range_view<ol_device_handle_t> getDevices(size_t PlatformId) const;
|
||||
|
||||
/// Register new platform and devices into this topology.
|
||||
///
|
||||
/// \param PlatformsAndDev associative container with platforms & devices.
|
||||
/// \param TotalDevCount total device count for the platform.
|
||||
void
|
||||
registerNewPlatformsAndDevices(PlatformWithDevStorageType &PlatformsAndDev,
|
||||
size_t TotalDevCount) {
|
||||
if (!PlatformsAndDev.size())
|
||||
return;
|
||||
|
||||
MPlatforms.reserve(PlatformsAndDev.size());
|
||||
MDevRangePerPlatformId.reserve(MPlatforms.size());
|
||||
MDevices.reserve(TotalDevCount);
|
||||
|
||||
for (auto &[NewPlatform, NewDevs] : PlatformsAndDev) {
|
||||
MPlatforms.push_back(NewPlatform);
|
||||
range_view<const ol_device_handle_t> R{MDevices.data() + MDevices.size(),
|
||||
NewDevs.size()};
|
||||
MDevices.insert(MDevices.end(), NewDevs.begin(), NewDevs.end());
|
||||
MDevRangePerPlatformId.push_back(R);
|
||||
}
|
||||
|
||||
assert(TotalDevCount == MDevices.size());
|
||||
}
|
||||
|
||||
/// Queries backend of this topology.
|
||||
///
|
||||
/// \returns backend of this topology.
|
||||
ol_platform_backend_t backend() const { return MBackend; }
|
||||
/// \param PlatformsAndDev collection of platforms & devices.
|
||||
void registerNewPlatformsAndDevices(Platform2DevContainer &PlatformsAndDev);
|
||||
|
||||
private:
|
||||
ol_platform_backend_t MBackend = OL_PLATFORM_BACKEND_UNKNOWN;
|
||||
|
||||
// Platforms and devices belonging to this backend (flattened)
|
||||
std::vector<ol_platform_handle_t> MPlatforms;
|
||||
std::vector<ol_device_handle_t> MDevices; // sorted by platform
|
||||
|
||||
// Devices are sorted by platform (guarantee from liboffload)
|
||||
std::vector<ol_device_handle_t> MDevices;
|
||||
|
||||
// Vector holding range of devices for each platform (index is platform index
|
||||
// within MPlatforms)
|
||||
std::vector<range_view<const ol_device_handle_t>>
|
||||
MDevRangePerPlatformId; // MDevRangePerPlatformId.size() ==
|
||||
// MPlatforms.size()
|
||||
// within Platforms), so MDeviceRange.size() == MPlatforms.size()
|
||||
std::vector<range_view<ol_device_handle_t>> MDeviceRange;
|
||||
};
|
||||
|
||||
// Initialize the topologies by calling olIterateDevices.
|
||||
|
||||
@ -56,8 +56,35 @@ backend convertBackend(ol_platform_backend_t Backend) {
|
||||
case OL_PLATFORM_BACKEND_AMDGPU:
|
||||
return backend::hip;
|
||||
default:
|
||||
throw exception(make_error_code(errc::runtime),
|
||||
"convertBackend: Unsupported backend");
|
||||
throw exception(make_error_code(errc::runtime), "Unsupported backend");
|
||||
}
|
||||
}
|
||||
|
||||
ol_device_type_t convertDeviceTypeToOL(info::device_type DeviceType) {
|
||||
switch (DeviceType) {
|
||||
case info::device_type::all:
|
||||
return OL_DEVICE_TYPE_ALL;
|
||||
case info::device_type::gpu:
|
||||
return OL_DEVICE_TYPE_GPU;
|
||||
case info::device_type::cpu:
|
||||
return OL_DEVICE_TYPE_CPU;
|
||||
case info::device_type::automatic:
|
||||
return OL_DEVICE_TYPE_DEFAULT;
|
||||
default:
|
||||
throw exception(sycl::make_error_code(sycl::errc::runtime),
|
||||
"Device type is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
info::device_type convertDeviceTypeToSYCL(ol_device_type_t DeviceType) {
|
||||
switch (DeviceType) {
|
||||
case OL_DEVICE_TYPE_GPU:
|
||||
return info::device_type::gpu;
|
||||
case OL_DEVICE_TYPE_CPU:
|
||||
return info::device_type::cpu;
|
||||
default:
|
||||
throw exception(sycl::make_error_code(sycl::errc::runtime),
|
||||
"Device type is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include <sycl/__impl/backend.hpp>
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
#include <sycl/__impl/exception.hpp>
|
||||
#include <sycl/__impl/info/device_type.hpp>
|
||||
|
||||
#include <OffloadAPI.h>
|
||||
|
||||
@ -85,6 +86,20 @@ void callAndThrow(FunctionType &Function, ArgsT &&...Args) {
|
||||
/// \returns sycl::backend matching specified liboffload backend.
|
||||
backend convertBackend(ol_platform_backend_t Backend);
|
||||
|
||||
/// Converts SYCL device type to liboffload type.
|
||||
///
|
||||
/// \param DeviceType SYCL device type.
|
||||
///
|
||||
/// \returns ol_device_type_t matching specified SYCL device type.
|
||||
ol_device_type_t convertDeviceTypeToOL(info::device_type DeviceType);
|
||||
|
||||
/// Converts liboffload device type to SYCL type.
|
||||
///
|
||||
/// \param DeviceType liboffload device type.
|
||||
///
|
||||
/// \returns SYCL device type matching specified liboffload device type.
|
||||
info::device_type convertDeviceTypeToSYCL(ol_device_type_t DeviceType);
|
||||
|
||||
/// Helper to map SYCL information descriptors to OL_<HANDLE>_INFO_<SMTH>.
|
||||
///
|
||||
/// Typical usage:
|
||||
|
||||
@ -9,9 +9,13 @@
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
#include <sycl/__impl/detail/obj_utils.hpp>
|
||||
|
||||
#include <detail/device_impl.hpp>
|
||||
#include <detail/global_objects.hpp>
|
||||
#include <detail/platform_impl.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
namespace detail {
|
||||
@ -19,6 +23,7 @@ namespace detail {
|
||||
PlatformImpl &PlatformImpl::getPlatformImpl(ol_platform_handle_t Platform) {
|
||||
auto &PlatformCache = getPlatformCache();
|
||||
for (auto &PlatImpl : PlatformCache) {
|
||||
assert(PlatImpl && "Platform impl can not be nullptr");
|
||||
if (PlatImpl->getHandleRef() == Platform)
|
||||
return *PlatImpl;
|
||||
}
|
||||
@ -32,10 +37,11 @@ PlatformImpl &PlatformImpl::getPlatformImpl(ol_platform_handle_t Platform) {
|
||||
const std::vector<PlatformImplUPtr> &PlatformImpl::getPlatforms() {
|
||||
[[maybe_unused]] static auto InitPlatformsOnce = []() {
|
||||
discoverOffloadDevices();
|
||||
|
||||
auto &PlatformCache = getPlatformCache();
|
||||
for (const auto &Topo : getOffloadTopologies()) {
|
||||
size_t PlatformIndex = 0;
|
||||
for (const auto &OffloadPlatform : Topo.platforms()) {
|
||||
for (const auto &OffloadPlatform : Topo.getPlatforms()) {
|
||||
PlatformCache.emplace_back(std::make_unique<PlatformImpl>(
|
||||
OffloadPlatform, PlatformIndex++, PrivateTag{}));
|
||||
}
|
||||
@ -53,6 +59,65 @@ PlatformImpl::PlatformImpl(ol_platform_handle_t Platform, size_t PlatformIndex,
|
||||
sizeof(Backend), &Backend);
|
||||
MBackend = convertBackend(Backend);
|
||||
MOffloadBackend = Backend;
|
||||
|
||||
const auto &Topologies = getOffloadTopologies();
|
||||
auto RootTopologyIt = std::find_if(
|
||||
Topologies.begin(), Topologies.end(), [&](const OffloadTopology &Topo) {
|
||||
return Topo.getBackend() == MOffloadBackend;
|
||||
});
|
||||
|
||||
assert(RootTopologyIt != Topologies.end() &&
|
||||
"Root topology for platform must always exist");
|
||||
auto DevRange = RootTopologyIt->getDevices(MOffloadPlatformIndex);
|
||||
MRootDevices.reserve(DevRange.size());
|
||||
std::for_each(DevRange.begin(), DevRange.end(),
|
||||
[&](const ol_device_handle_t &Device) {
|
||||
MRootDevices.emplace_back(std::make_unique<DeviceImpl>(
|
||||
Device, *this, DeviceImpl::PrivateTag{}));
|
||||
});
|
||||
}
|
||||
|
||||
const std::vector<DeviceImplUPtr> &PlatformImpl::getRootDevices() const {
|
||||
return MRootDevices;
|
||||
}
|
||||
|
||||
bool PlatformImpl::has(aspect Aspect) const {
|
||||
const auto &Devices = getRootDevices();
|
||||
return std::all_of(
|
||||
Devices.begin(), Devices.end(),
|
||||
[&Aspect](const DeviceImplUPtr &Device) { return Device->has(Aspect); });
|
||||
}
|
||||
|
||||
void PlatformImpl::iterateDevices(
|
||||
info::device_type DeviceType,
|
||||
std::function<void(DeviceImpl *)> callback) const {
|
||||
// Early exit if host/custom/accelerator device is requested:
|
||||
// - host device is deprecated and not required by the SYCL 2020
|
||||
// specification.
|
||||
// - accelerator and custom devices are unsupported by liboffload.
|
||||
if ((DeviceType == info::device_type::host) ||
|
||||
(DeviceType == info::device_type::custom) ||
|
||||
(DeviceType == info::device_type::accelerator))
|
||||
return;
|
||||
|
||||
const auto &DeviceImpls = getRootDevices();
|
||||
assert(!DeviceImpls.empty() &&
|
||||
"Platform can't exist without at least one device.");
|
||||
|
||||
// TODO: Need a way to get default device from liboffload.
|
||||
// As a temporal solution just return the first device for DeviceType ==
|
||||
// automatic.
|
||||
if (DeviceType == info::device_type::automatic) {
|
||||
callback(DeviceImpls[0].get());
|
||||
return;
|
||||
}
|
||||
|
||||
bool KeepAll = DeviceType == info::device_type::all;
|
||||
for (auto &Impl : DeviceImpls) {
|
||||
if (KeepAll || DeviceType == Impl->getDeviceType())
|
||||
callback(Impl.get());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
|
||||
@ -13,10 +13,12 @@
|
||||
#include <sycl/__impl/detail/config.hpp>
|
||||
#include <sycl/__impl/platform.hpp>
|
||||
|
||||
#include <detail/device_impl.hpp>
|
||||
#include <detail/offload/offload_utils.hpp>
|
||||
|
||||
#include <OffloadAPI.h>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
@ -26,9 +28,15 @@ _LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
namespace detail {
|
||||
|
||||
class DeviceImpl;
|
||||
|
||||
using PlatformImplUPtr = std::unique_ptr<PlatformImpl>;
|
||||
using DeviceImplUPtr = std::unique_ptr<DeviceImpl>;
|
||||
|
||||
class PlatformImpl {
|
||||
// Helper to limit PlatformImpl creation. It must be created in getPlatforms
|
||||
// only. Using tag instead of private ctor + friend class to allow make_unique
|
||||
// usage and to align with classes which impl is shared_ptr<>.
|
||||
struct PrivateTag {
|
||||
explicit PrivateTag() = default;
|
||||
};
|
||||
@ -73,7 +81,16 @@ public:
|
||||
/// \return the PlatformImpl representing the offloading RT platform.
|
||||
static PlatformImpl &getPlatformImpl(ol_platform_handle_t Platform);
|
||||
|
||||
/// Queries this platform for info.
|
||||
/// Indicates if all of the SYCL devices on this platform have the
|
||||
/// given aspect.
|
||||
///
|
||||
/// \param Aspect is one of the values defined in SYCL 2020 Section 4.6.4.5.
|
||||
///
|
||||
/// \return true all of the SYCL devices on this platform have the
|
||||
/// given aspect.
|
||||
bool has(aspect Aspect) const;
|
||||
|
||||
/// Queries this SYCL platform for info.
|
||||
///
|
||||
/// The return type depends on information being queried.
|
||||
template <typename Param> typename Param::return_type getInfo() const {
|
||||
@ -99,11 +116,20 @@ public:
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// Calls "callback" with every root device of type == DeviceType associated
|
||||
/// with this platform
|
||||
void iterateDevices(info::device_type DeviceType,
|
||||
std::function<void(DeviceImpl *)> callback) const;
|
||||
|
||||
private:
|
||||
const std::vector<DeviceImplUPtr> &getRootDevices() const;
|
||||
|
||||
ol_platform_handle_t MOffloadPlatform{};
|
||||
size_t MOffloadPlatformIndex{};
|
||||
ol_platform_backend_t MOffloadBackend{OL_PLATFORM_BACKEND_UNKNOWN};
|
||||
backend MBackend{};
|
||||
|
||||
std::vector<DeviceImplUPtr> MRootDevices;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
104
libsycl/src/device.cpp
Normal file
104
libsycl/src/device.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <sycl/__impl/device.hpp>
|
||||
|
||||
#include <detail/device_impl.hpp>
|
||||
#include <detail/platform_impl.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
device::device() : device(default_selector_v) {}
|
||||
|
||||
bool device::is_cpu() const { return impl->isCPU(); }
|
||||
|
||||
bool device::is_gpu() const { return impl->isGPU(); }
|
||||
|
||||
bool device::is_accelerator() const { return impl->isAccelerator(); }
|
||||
|
||||
platform device::get_platform() const {
|
||||
return detail::createSyclObjFromImpl<platform>(impl->getPlatformImpl());
|
||||
}
|
||||
|
||||
backend device::get_backend() const noexcept { return impl->getBackend(); }
|
||||
|
||||
std::vector<device> device::get_devices(info::device_type DeviceType) {
|
||||
std::vector<device> Devices;
|
||||
|
||||
// Not calling platform::get_devices to avoid multiple vector packing
|
||||
for (auto &PlatformImpl : detail::PlatformImpl::getPlatforms()) {
|
||||
assert(PlatformImpl && "PlatformImpl can not be nullptr");
|
||||
PlatformImpl->iterateDevices(
|
||||
DeviceType, [&Devices](detail::DeviceImpl *DevImpl) {
|
||||
assert(DevImpl && "Device impl can't be nullptr");
|
||||
Devices.push_back(detail::createSyclObjFromImpl<device>(*DevImpl));
|
||||
});
|
||||
}
|
||||
|
||||
return Devices;
|
||||
}
|
||||
|
||||
template <info::partition_property prop>
|
||||
std::vector<device> device::create_sub_devices(size_t ComputeUnits) const {
|
||||
throw exception(make_error_code(errc::feature_not_supported),
|
||||
"Partitioning is not supported.");
|
||||
}
|
||||
|
||||
template _LIBSYCL_EXPORT std::vector<device>
|
||||
device::create_sub_devices<info::partition_property::partition_equally>(
|
||||
size_t ComputeUnits) const;
|
||||
|
||||
template <info::partition_property prop>
|
||||
std::vector<device>
|
||||
device::create_sub_devices(const std::vector<size_t> &Counts) const {
|
||||
throw exception(make_error_code(errc::feature_not_supported),
|
||||
"Partitioning is not supported.");
|
||||
}
|
||||
|
||||
template _LIBSYCL_EXPORT std::vector<device>
|
||||
device::create_sub_devices<info::partition_property::partition_by_counts>(
|
||||
const std::vector<size_t> &Counts) const;
|
||||
|
||||
template <info::partition_property prop>
|
||||
std::vector<device> device::create_sub_devices(
|
||||
info::partition_affinity_domain AffinityDomain) const {
|
||||
throw exception(make_error_code(errc::feature_not_supported),
|
||||
"Partitioning is not supported.");
|
||||
}
|
||||
|
||||
template _LIBSYCL_EXPORT std::vector<device> device::create_sub_devices<
|
||||
info::partition_property::partition_by_affinity_domain>(
|
||||
info::partition_affinity_domain AffinityDomain) const;
|
||||
|
||||
bool device::has(aspect Aspect) const { return impl->has(Aspect); }
|
||||
|
||||
template <typename Param>
|
||||
detail::is_device_info_desc_t<Param> device::get_info() const {
|
||||
return impl->getInfo<Param>();
|
||||
}
|
||||
|
||||
template <>
|
||||
_LIBSYCL_EXPORT detail::is_device_info_desc_t<info::device::platform>
|
||||
device::get_info<info::device::platform>() const {
|
||||
static_assert(
|
||||
std::is_same_v<info::device::platform::return_type, sycl::platform>);
|
||||
return get_platform();
|
||||
}
|
||||
|
||||
#define _LIBSYCL_EXPORT_GET_INFO(Desc) \
|
||||
template _LIBSYCL_EXPORT detail::is_device_info_desc_t<info::device::Desc> \
|
||||
device::get_info<info::device::Desc>() const;
|
||||
_LIBSYCL_EXPORT_GET_INFO(device_type)
|
||||
_LIBSYCL_EXPORT_GET_INFO(name)
|
||||
_LIBSYCL_EXPORT_GET_INFO(vendor)
|
||||
_LIBSYCL_EXPORT_GET_INFO(driver_version)
|
||||
#undef _LIBSYCL_EXPORT_GET_INFO
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
118
libsycl/src/device_selector.cpp
Normal file
118
libsycl/src/device_selector.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <sycl/__impl/device.hpp>
|
||||
#include <sycl/__impl/device_selector.hpp>
|
||||
|
||||
#include <detail/device_impl.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
static constexpr int MatchedTypeDefaultScore = 1000;
|
||||
static constexpr int GPUDeviceDefaultScore = 500;
|
||||
static constexpr int CPUDeviceDefaultScore = 300;
|
||||
static constexpr int AccDeviceDefaultScore = 75;
|
||||
static constexpr int RejectDeviceScore = -1;
|
||||
|
||||
static int getDevicePreference(const device &Device) {
|
||||
int Score = 0;
|
||||
const auto &DeviceImpl = detail::getSyclObjImpl(Device);
|
||||
|
||||
// TODO: increase score for devices with compatible program images.
|
||||
|
||||
if (DeviceImpl->getBackend() == backend::level_zero)
|
||||
Score += 50;
|
||||
|
||||
return Score;
|
||||
}
|
||||
|
||||
_LIBSYCL_EXPORT int default_selector_v(const device &dev) {
|
||||
int Score = getDevicePreference(dev);
|
||||
|
||||
if (dev.is_gpu())
|
||||
Score += GPUDeviceDefaultScore;
|
||||
else if (dev.is_cpu())
|
||||
Score += CPUDeviceDefaultScore;
|
||||
else if (dev.is_accelerator())
|
||||
Score += AccDeviceDefaultScore;
|
||||
|
||||
return Score;
|
||||
}
|
||||
|
||||
_LIBSYCL_EXPORT int gpu_selector_v(const device &Dev) {
|
||||
return Dev.is_gpu() ? MatchedTypeDefaultScore + getDevicePreference(Dev)
|
||||
: RejectDeviceScore;
|
||||
}
|
||||
|
||||
_LIBSYCL_EXPORT int cpu_selector_v(const device &Dev) {
|
||||
return Dev.is_cpu() ? MatchedTypeDefaultScore + getDevicePreference(Dev)
|
||||
: RejectDeviceScore;
|
||||
}
|
||||
|
||||
_LIBSYCL_EXPORT int accelerator_selector_v(const device &Dev) {
|
||||
return Dev.is_accelerator()
|
||||
? MatchedTypeDefaultScore + getDevicePreference(Dev)
|
||||
: RejectDeviceScore;
|
||||
}
|
||||
|
||||
_LIBSYCL_EXPORT detail::DeviceSelectorInvocableType
|
||||
aspect_selector(const std::vector<aspect> &RequireList,
|
||||
const std::vector<aspect> &DenyList) {
|
||||
return [=](const sycl::device &Dev) {
|
||||
// 4.6.1.1. Device selector:
|
||||
// If no aspects are passed in, the generated selector behaves like
|
||||
// default_selector_v.
|
||||
if (RequireList.empty() && DenyList.empty())
|
||||
return default_selector_v(Dev);
|
||||
|
||||
auto HasAspect = [&Dev](const aspect &Aspect) -> bool {
|
||||
return Dev.has(Aspect);
|
||||
};
|
||||
if (!std::all_of(RequireList.begin(), RequireList.end(), HasAspect))
|
||||
return RejectDeviceScore;
|
||||
|
||||
if (std::any_of(DenyList.begin(), DenyList.end(), HasAspect))
|
||||
return RejectDeviceScore;
|
||||
|
||||
return MatchedTypeDefaultScore + getDevicePreference(Dev);
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
_LIBSYCL_EXPORT device
|
||||
SelectDevice(const DeviceSelectorInvocableType &DeviceSelector) {
|
||||
int ChosenDeviceScore = RejectDeviceScore;
|
||||
const device *ChosenDevice = nullptr;
|
||||
|
||||
std::vector<device> Devices = device::get_devices();
|
||||
for (const auto &Device : Devices) {
|
||||
int CurrentDevScore = DeviceSelector(Device);
|
||||
if (CurrentDevScore < 0)
|
||||
continue;
|
||||
|
||||
if ((ChosenDeviceScore < CurrentDevScore) ||
|
||||
((ChosenDeviceScore == CurrentDevScore) &&
|
||||
(getDevicePreference(*ChosenDevice) < getDevicePreference(Device)))) {
|
||||
ChosenDevice = &Device;
|
||||
ChosenDeviceScore = CurrentDevScore;
|
||||
}
|
||||
}
|
||||
|
||||
if (ChosenDevice != nullptr)
|
||||
return *ChosenDevice;
|
||||
|
||||
throw exception(make_error_code(errc::runtime),
|
||||
"No device of requested type is available");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
_LIBSYCL_END_NAMESPACE_SYCL
|
||||
@ -8,10 +8,9 @@
|
||||
|
||||
#include <sycl/__impl/platform.hpp>
|
||||
|
||||
#include <detail/device_impl.hpp>
|
||||
#include <detail/platform_impl.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
_LIBSYCL_BEGIN_NAMESPACE_SYCL
|
||||
|
||||
backend platform::get_backend() const noexcept { return impl->getBackend(); }
|
||||
@ -21,12 +20,24 @@ std::vector<platform> platform::get_platforms() {
|
||||
std::vector<platform> Platforms;
|
||||
Platforms.reserve(PlatformImpls.size());
|
||||
for (auto &PlatformImpl : PlatformImpls) {
|
||||
platform Platform = detail::createSyclObjFromImpl<platform>(*PlatformImpl);
|
||||
Platforms.push_back(std::move(Platform));
|
||||
Platforms.emplace_back(
|
||||
detail::createSyclObjFromImpl<platform>(*PlatformImpl.get()));
|
||||
}
|
||||
return Platforms;
|
||||
}
|
||||
|
||||
std::vector<device> platform::get_devices(info::device_type DeviceType) const {
|
||||
std::vector<device> Devices;
|
||||
impl->iterateDevices(DeviceType, [&Devices](detail::DeviceImpl *DevImpl) {
|
||||
assert(DevImpl && "Device impl can't be nullptr");
|
||||
Devices.push_back(detail::createSyclObjFromImpl<device>(*DevImpl));
|
||||
});
|
||||
|
||||
return Devices;
|
||||
}
|
||||
|
||||
bool platform::has(aspect Aspect) const { return impl->has(Aspect); }
|
||||
|
||||
template <typename Param>
|
||||
detail::is_platform_info_desc_t<Param> platform::get_info() const {
|
||||
return impl->getInfo<Param>();
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The "sycl-ls" utility lists all platforms discovered by SYCL.
|
||||
// The "sycl-ls" utility lists all platforms and devices discovered by SYCL.
|
||||
//
|
||||
// There are two types of output:
|
||||
// concise (default) and
|
||||
@ -36,14 +36,69 @@ inline std::string_view getBackendName(const backend &Backend) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string getDeviceTypeName(const device &Device) {
|
||||
auto DeviceType = Device.get_info<info::device::device_type>();
|
||||
switch (DeviceType) {
|
||||
case info::device_type::cpu:
|
||||
return "cpu";
|
||||
case info::device_type::gpu:
|
||||
return "gpu";
|
||||
case info::device_type::host:
|
||||
return "host";
|
||||
case info::device_type::accelerator:
|
||||
return "accelerator";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void printDeviceInfo(const device &Device, bool Verbose,
|
||||
const std::string &Prepend) {
|
||||
auto DeviceName = Device.get_info<info::device::name>();
|
||||
auto DeviceVendor = Device.get_info<info::device::vendor>();
|
||||
auto DeviceDriverVersion = Device.get_info<info::device::driver_version>();
|
||||
|
||||
if (Verbose) {
|
||||
std::cout << Prepend << "Type : " << getDeviceTypeName(Device)
|
||||
<< std::endl;
|
||||
std::cout << Prepend << "Name : " << DeviceName << std::endl;
|
||||
std::cout << Prepend << "Vendor : " << DeviceVendor << std::endl;
|
||||
std::cout << Prepend << "Driver : " << DeviceDriverVersion
|
||||
<< std::endl;
|
||||
} else {
|
||||
std::cout << Prepend << ", " << DeviceName << " [" << DeviceDriverVersion
|
||||
<< "]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
printSelectorChoice(const detail::DeviceSelectorInvocableType &Selector,
|
||||
const std::string &Prepend) {
|
||||
try {
|
||||
const auto &Device = device(Selector);
|
||||
std::string DeviceTypeName = getDeviceTypeName(Device);
|
||||
auto Platform = Device.get_info<info::device::platform>();
|
||||
auto PlatformName = Platform.get_info<info::platform::name>();
|
||||
printDeviceInfo(Device, false /*Verbose*/,
|
||||
Prepend + DeviceTypeName + ", " + PlatformName);
|
||||
} catch (const sycl::exception &Exception) {
|
||||
std::string What = Exception.what();
|
||||
constexpr size_t MaxLength = 80;
|
||||
// Truncate long string so it can fit in one-line
|
||||
if (What.length() > MaxLength)
|
||||
What = What.substr(0, MaxLength) + "...";
|
||||
std::cout << Prepend << What << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
llvm::cl::opt<bool> Verbose(
|
||||
"verbose",
|
||||
llvm::cl::desc("Verbosely prints all the discovered platforms"));
|
||||
"verbose", llvm::cl::desc("Verbosely prints all the discovered devices"));
|
||||
llvm::cl::alias VerboseShort("v", llvm::cl::desc("Alias for -verbose"),
|
||||
llvm::cl::aliasopt(Verbose));
|
||||
llvm::cl::ParseCommandLineOptions(
|
||||
argc, argv, "This program lists all backends discovered by SYCL");
|
||||
argc, argv,
|
||||
"This program lists all backends and devices discovered by SYCL");
|
||||
|
||||
try {
|
||||
const auto &Platforms = platform::get_platforms();
|
||||
@ -55,8 +110,17 @@ int main(int argc, char **argv) {
|
||||
|
||||
for (const auto &Platform : Platforms) {
|
||||
backend Backend = Platform.get_backend();
|
||||
std::cout << "[" << getBackendName(Backend) << ":"
|
||||
<< "unknown" << "]" << std::endl;
|
||||
auto PlatformName = Platform.get_info<info::platform::name>();
|
||||
const auto &Devices = Platform.get_devices();
|
||||
|
||||
for (const auto &Device : Devices) {
|
||||
std::cout << "[" << getBackendName(Backend) << ":"
|
||||
<< getDeviceTypeName(Device) << "]";
|
||||
std::cout << " ";
|
||||
// Verbose parameter is set to false to print regular devices output
|
||||
// first
|
||||
printDeviceInfo(Device, false, PlatformName);
|
||||
}
|
||||
}
|
||||
|
||||
if (Verbose) {
|
||||
@ -71,8 +135,19 @@ int main(int argc, char **argv) {
|
||||
std::cout << " Version : " << PlatformVersion << std::endl;
|
||||
std::cout << " Name : " << PlatformName << std::endl;
|
||||
std::cout << " Vendor : " << PlatformVendor << std::endl;
|
||||
std::cout << " Devices : " << "unknown" << std::endl;
|
||||
|
||||
const auto &Devices = Platform.get_devices();
|
||||
std::cout << " Devices : " << Devices.size() << std::endl;
|
||||
for (const auto &Device : Devices) {
|
||||
printDeviceInfo(Device, true, " ");
|
||||
}
|
||||
}
|
||||
|
||||
// Print built-in device selectors choice
|
||||
printSelectorChoice(default_selector_v, "default_selector() : ");
|
||||
printSelectorChoice(accelerator_selector_v, "accelerator_selector() : ");
|
||||
printSelectorChoice(cpu_selector_v, "cpu_selector() : ");
|
||||
printSelectorChoice(gpu_selector_v, "gpu_selector() : ");
|
||||
}
|
||||
} catch (sycl::exception &e) {
|
||||
std::cerr << "SYCL Exception encountered: " << e.what() << std::endl
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user