Skip to content

Commit 78d9957

Browse files
Alexander Batashevbader
Alexander Batashev
authored andcommitted
[SYCL] Refactor device and device_impl classes (#755)
This patch is a part of effort to decouple SYCL Runtime library interface from its actual implementation. The goal is to improve SYCL ABI/API compatibility between different versions of library. The following modifications were applied to device and device_impl classes: 1. Removed include of device_impl header from device.hpp and replaced it with forward declaration. 2. Move member function implementations from device.hpp to device.cpp 3. std::shared_ptr was replaced with shared_ptr_class for device class 4. Documentation was improved for both device and device_impl 5. device_impl now tries to follow LLVM code style 6. Merge device_impl_pi and device_host Applying aforementioned changes requires modifying other header files. While some of those may seem as a regression, affected classes will be covered by future patches. Signed-off-by: Alexander Batashev <[email protected]>
1 parent b3ee6a2 commit 78d9957

16 files changed

+525
-553
lines changed

sycl/include/CL/sycl/detail/context_impl.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#pragma once
1010
#include <CL/sycl/detail/common.hpp>
11+
#include <CL/sycl/detail/device_impl.hpp>
1112
#include <CL/sycl/detail/os_util.hpp>
1213
#include <CL/sycl/detail/pi.hpp>
1314
#include <CL/sycl/detail/usm_dispatch.hpp>

sycl/include/CL/sycl/detail/device_impl.hpp

+140-188
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <CL/sycl/detail/device_info.hpp>
1212
#include <CL/sycl/detail/pi.hpp>
1313
#include <CL/sycl/stl.hpp>
14-
#include <algorithm>
1514
#include <memory>
1615

1716
namespace cl {
@@ -21,44 +20,141 @@ namespace sycl {
2120
class platform;
2221

2322
namespace detail {
24-
// TODO: 4.6.4 Partitioning into multiple SYCL devices
25-
// TODO: 4.6.4.2 Device information descriptors
23+
24+
// Forward declaration
25+
class platform_impl;
26+
class platform_impl_pi;
27+
2628
// TODO: Make code thread-safe
2729
class device_impl {
2830
public:
29-
virtual ~device_impl() = default;
30-
31-
virtual cl_device_id get() const = 0;
32-
33-
// Returns underlying native device object (if any) w/o reference count
34-
// modification. Caller must ensure the returned object lives on stack only.
35-
// It can also be safely passed to the underlying native runtime API.
36-
// Warning. Returned reference will be invalid if device_impl was destroyed.
37-
//
38-
virtual RT::PiDevice &getHandleRef() = 0;
39-
virtual const RT::PiDevice &getHandleRef() const = 0;
40-
41-
virtual bool is_host() const = 0;
42-
43-
virtual bool is_cpu() const = 0;
44-
45-
virtual bool is_gpu() const = 0;
46-
47-
virtual bool is_accelerator() const = 0;
48-
49-
virtual platform get_platform() const = 0;
31+
/// Constructs a SYCL device instance as a host device.
32+
device_impl();
33+
/// Constructs a SYCL device instance using the provided
34+
/// PI device instance.
35+
explicit device_impl(RT::PiDevice Device);
36+
37+
~device_impl();
38+
39+
/// Get instance of OpenCL device
40+
///
41+
/// @return a valid cl_device_id instance in accordance with the requirements
42+
/// described in 4.3.1.
43+
cl_device_id get() const;
44+
45+
/// Get reference to PI device
46+
///
47+
/// For host device an exception is thrown
48+
///
49+
/// @return non-constant reference to PI device
50+
RT::PiDevice &getHandleRef() {
51+
if (MIsHostDevice)
52+
throw invalid_object_error("This instance of device is a host instance");
53+
54+
return MDevice;
55+
}
56+
57+
/// Get constant reference to PI device
58+
///
59+
/// For host device an exception is thrown
60+
///
61+
/// @return constant reference to PI device
62+
const RT::PiDevice &getHandleRef() const {
63+
if (MIsHostDevice)
64+
throw invalid_object_error("This instance of device is a host instance");
65+
66+
return MDevice;
67+
}
68+
69+
/// Check if SYCL device is a host device
70+
///
71+
/// @return true if SYCL device is a host device
72+
bool is_host() const { return MIsHostDevice; }
73+
74+
/// Check if device is a CPU device
75+
///
76+
/// @return true if SYCL device is a CPU device
77+
bool is_cpu() const { return (MType == PI_DEVICE_TYPE_CPU); }
78+
79+
/// Check if device is a GPU device
80+
///
81+
/// @return true if SYCL device is a GPU device
82+
bool is_gpu() const { return (MType == PI_DEVICE_TYPE_GPU); }
83+
84+
/// Check if device is an accelerator device
85+
///
86+
/// @return true if SYCL device is an accelerator device
87+
bool is_accelerator() const { return (MType == PI_DEVICE_TYPE_ACC); }
88+
89+
/// Get associated SYCL platform
90+
///
91+
/// If this SYCL device is an OpenCL device then the SYCL platform
92+
/// must encapsulate the OpenCL cl_plaform_id associated with the
93+
/// underlying OpenCL cl_device_id of this SYCL device. If this SYCL device
94+
/// is a host device then the SYCL platform must be a host platform.
95+
/// The value returned must be equal to that returned
96+
/// by get_info<info::device::platform>().
97+
///
98+
/// @return The associated SYCL platform.
99+
platform get_platform() const;
100+
101+
/// Check SYCL extension support by device
102+
///
103+
/// @param ExtensionName is a name of queried extension.
104+
/// @return true if SYCL device supports the extension.
105+
bool has_extension(const string_class &ExtensionName) const;
50106

51-
virtual vector_class<device> create_sub_devices(size_t nbSubDev) const = 0;
52-
53-
virtual vector_class<device>
54-
create_sub_devices(const vector_class<size_t> &counts) const = 0;
55-
56-
virtual vector_class<device>
57-
create_sub_devices(info::partition_affinity_domain affinityDomain) const = 0;
58-
59-
static vector_class<device>
60-
get_devices(info::device_type deviceType = info::device_type::all);
107+
vector_class<device>
108+
create_sub_devices(const cl_device_partition_property *Properties,
109+
size_t SubDevicesCount) const;
61110

111+
/// Partition device into sub devices
112+
///
113+
/// If this SYCL device does not support info::partition_property::partition_equally
114+
/// a feature_not_supported exception must be thrown.
115+
///
116+
/// @param ComputeUnits is a desired count of compute units in each sub device.
117+
/// @return A vector class of sub devices partitioned equally from this
118+
/// SYCL device based on the ComputeUnits parameter.
119+
vector_class<device> create_sub_devices(size_t ComputeUnits) const;
120+
121+
/// Partition device into sub devices
122+
///
123+
/// If this SYCL device does not support info::partition_property::partition_by_counts
124+
/// a feature_not_supported exception must be thrown.
125+
///
126+
/// @param Counts is a vector_class of desired compute units in sub devices.
127+
/// @return a vector_class of sub devices partitioned from this SYCL device
128+
/// by count sizes based on the Counts parameter.
129+
vector_class<device>
130+
create_sub_devices(const vector_class<size_t> &Counts) const;
131+
132+
/// Partition device into sub devices
133+
///
134+
/// If this SYCL device does not support info::partition_property::partition_by_affinity_domain
135+
/// or the SYCL device does not support info::affinity_domain provided
136+
/// a feature_not_supported exception must be thrown.
137+
///
138+
/// @param AffinityDomain is one of the values described in Table 4.20 of SYCL Spec
139+
/// @return a vector class of sub devices partitioned from this SYCL device
140+
/// by affinity domain based on the AffinityDomain parameter
141+
vector_class<device>
142+
create_sub_devices(info::partition_affinity_domain AffinityDomain) const;
143+
144+
/// Check if desired partition property supported by device
145+
///
146+
/// @param Prop is one of info::partition_property::(partition_equally,
147+
/// partition_by_counts, partition_by_affinity_domain)
148+
/// @return true if Prop is supported by device.
149+
bool is_partition_supported(info::partition_property Prop) const;
150+
151+
/// Queries this SYCL device for information requested by the template parameter param
152+
///
153+
/// Specializations of info::param_traits must be defined in accordance
154+
/// with the info parameters in Table 4.20 of SYCL Spec to facilitate
155+
/// returning the type associated with the param parameter.
156+
///
157+
/// @return device info of type described in Table 4.20.
62158
template <info::device param>
63159
typename info::param_traits<info::device, param>::return_type
64160
get_info() const {
@@ -70,163 +166,19 @@ class device_impl {
70166
param>::_(this->getHandleRef());
71167
}
72168

73-
bool is_partition_supported(info::partition_property Prop) const {
74-
auto SupportedProperties = get_info<info::device::partition_properties>();
75-
return std::find(SupportedProperties.begin(), SupportedProperties.end(),
76-
Prop) != SupportedProperties.end();
77-
}
78-
169+
/// Check if affinity partitioning by specified domain is supported by device
170+
///
171+
/// @param AffinityDomain is one of the values described in Table 4.20 of SYCL Spec
172+
/// @return true if AffinityDomain is supported by device.
79173
bool
80-
is_affinity_supported(info::partition_affinity_domain AffinityDomain) const {
81-
auto SupportedDomains =
82-
get_info<info::device::partition_affinity_domains>();
83-
return std::find(SupportedDomains.begin(), SupportedDomains.end(),
84-
AffinityDomain) != SupportedDomains.end();
85-
}
86-
87-
virtual bool has_extension(const string_class &extension_name) const = 0;
88-
};
89-
90-
// TODO: 4.6.4 Partitioning into multiple SYCL devices
91-
// TODO: 4.6.4.2 Device information descriptors
92-
// TODO: Make code thread-safe
93-
class device_impl_pi : public device_impl {
94-
public:
95-
explicit device_impl_pi(RT::PiDevice a_device) : m_device(a_device) {
96-
// TODO catch an exception and put it to list of asynchronous exceptions
97-
PI_CALL(RT::piDeviceGetInfo(
98-
m_device, PI_DEVICE_INFO_TYPE, sizeof(RT::PiDeviceType), &m_type, 0));
99-
100-
RT::PiDevice parent;
101-
// TODO catch an exception and put it to list of asynchronous exceptions
102-
PI_CALL(RT::piDeviceGetInfo(
103-
m_device, PI_DEVICE_INFO_PARENT, sizeof(RT::PiDevice), &parent, 0));
104-
105-
m_isRootDevice = (nullptr == parent);
106-
if (!m_isRootDevice) {
107-
// TODO catch an exception and put it to list of asynchronous exceptions
108-
PI_CALL(RT::piDeviceRetain(m_device));
109-
}
110-
}
111-
112-
~device_impl_pi() {
113-
if (!m_isRootDevice) {
114-
// TODO catch an exception and put it to list of asynchronous exceptions
115-
CHECK_OCL_CODE_NO_EXC(RT::piDeviceRelease(m_device));
116-
}
117-
}
118-
119-
cl_device_id get() const override {
120-
if (!m_isRootDevice) {
121-
// TODO catch an exception and put it to list of asynchronous exceptions
122-
PI_CALL(RT::piDeviceRetain(m_device));
123-
}
124-
// TODO: check that device is an OpenCL interop one
125-
return pi::cast<cl_device_id>(m_device);
126-
}
127-
128-
RT::PiDevice &getHandleRef() override { return m_device; }
129-
const RT::PiDevice &getHandleRef() const override { return m_device; }
130-
131-
bool is_host() const override { return false; }
132-
133-
bool is_cpu() const override { return (m_type == PI_DEVICE_TYPE_CPU); }
134-
135-
bool is_gpu() const override { return (m_type == PI_DEVICE_TYPE_GPU); }
136-
137-
bool is_accelerator() const override {
138-
return (m_type == PI_DEVICE_TYPE_ACC);
139-
}
140-
141-
platform get_platform() const override {
142-
RT::PiPlatform plt;
143-
// TODO catch an exception and put it to list of asynchronous exceptions
144-
PI_CALL(RT::piDeviceGetInfo(
145-
m_device, PI_DEVICE_INFO_PLATFORM, sizeof(plt), &plt, 0));
146-
147-
// TODO: this possibly will violate common reference semantics,
148-
// particularly, equality comparison may fail for two consecutive
149-
// get_platform() on the same device, as it compares impl objects.
150-
return createSyclObjFromImpl<platform>(
151-
std::make_shared<platform_impl_pi>(plt));
152-
}
153-
154-
bool has_extension(const string_class &extension_name) const override {
155-
string_class all_extension_names =
156-
get_device_info<string_class, info::device::extensions>::_(m_device);
157-
return (all_extension_names.find(extension_name) != std::string::npos);
158-
}
159-
160-
vector_class<device>
161-
create_sub_devices(const cl_device_partition_property *Properties,
162-
size_t SubDevicesCount) const;
163-
164-
vector_class<device>
165-
create_sub_devices(size_t ComputeUnits) const override;
166-
167-
vector_class<device>
168-
create_sub_devices(const vector_class<size_t> &Counts) const override;
169-
170-
vector_class<device>
171-
create_sub_devices(info::partition_affinity_domain AffinityDomain) const override;
174+
is_affinity_supported(info::partition_affinity_domain AffinityDomain) const;
172175

173176
private:
174-
RT::PiDevice m_device = 0;
175-
RT::PiDeviceType m_type;
176-
bool m_isRootDevice = false;
177-
}; // class device_impl_pi
178-
179-
// TODO: 4.6.4 Partitioning into multiple SYCL devices
180-
// TODO: 4.6.4.2 Device information descriptors
181-
// TODO: Make code thread-safe
182-
class device_host : public device_impl {
183-
public:
184-
device_host() = default;
185-
cl_device_id get() const override {
186-
throw invalid_object_error("This instance of device is a host instance");
187-
}
188-
RT::PiDevice &getHandleRef() override {
189-
throw invalid_object_error("This instance of device is a host instance");
190-
}
191-
const RT::PiDevice &getHandleRef() const override {
192-
throw invalid_object_error("This instance of device is a host instance");
193-
}
194-
195-
bool is_host() const override { return true; }
196-
197-
bool is_cpu() const override { return false; }
198-
199-
bool is_gpu() const override { return false; }
200-
201-
bool is_accelerator() const override { return false; }
202-
203-
platform get_platform() const override { return platform(); }
204-
205-
bool has_extension(const string_class &extension_name) const override {
206-
// TODO: implement extension management;
207-
return false;
208-
}
209-
210-
vector_class<device> create_sub_devices(size_t nbSubDev) const override {
211-
// TODO: implement host device partitioning
212-
throw runtime_error(
213-
"Partitioning to subdevices of the host device is not implemented yet");
214-
}
215-
216-
vector_class<device>
217-
create_sub_devices(const vector_class<size_t> &counts) const override {
218-
// TODO: implement host device partitioning
219-
throw runtime_error(
220-
"Partitioning to subdevices of the host device is not implemented yet");
221-
}
222-
223-
vector_class<device>
224-
create_sub_devices(info::partition_affinity_domain affinityDomain) const override {
225-
// TODO: implement host device partitioning
226-
throw runtime_error(
227-
"Partitioning to subdevices of the host device is not implemented yet");
228-
}
229-
}; // class device_host
177+
RT::PiDevice MDevice = 0;
178+
RT::PiDeviceType MType;
179+
bool MIsRootDevice = false;
180+
bool MIsHostDevice;
181+
}; // class device_impl
230182

231183
} // namespace detail
232184
} // namespace sycl

0 commit comments

Comments
 (0)