-
Notifications
You must be signed in to change notification settings - Fork 769
/
Copy pathdevice_impl.hpp
305 lines (255 loc) · 10.8 KB
/
device_impl.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
//==----------------- device_impl.hpp - SYCL device ------------------------==//
//
// 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
//
//===----------------------------------------------------------------------===//
#pragma once
#include <detail/platform_impl.hpp>
#include <sycl/aspects.hpp>
#include <sycl/detail/cl.h>
#include <sycl/detail/ur.hpp>
#include <sycl/ext/oneapi/experimental/device_architecture.hpp>
#include <sycl/ext/oneapi/experimental/forward_progress.hpp>
#include <sycl/kernel_bundle.hpp>
#include <memory>
#include <mutex>
#include <utility>
namespace sycl {
inline namespace _V1 {
// Forward declaration
class platform;
namespace detail {
// Forward declaration
class platform_impl;
// TODO: Make code thread-safe
class device_impl {
public:
/// Constructs a SYCL device instance using the provided
/// UR device instance.
explicit device_impl(ur_device_handle_t Device, platform_impl &Platform);
~device_impl();
/// Get instance of OpenCL device
///
/// \return a valid cl_device_id instance in accordance with the
/// requirements described in 4.3.1.
cl_device_id get() const;
/// Get reference to UR device
///
/// For host device an exception is thrown
///
/// \return non-constant reference to UR device
ur_device_handle_t &getHandleRef() { return MDevice; }
/// Get constant reference to UR device
///
/// For host device an exception is thrown
///
/// \return constant reference to UR device
const ur_device_handle_t &getHandleRef() const { return MDevice; }
/// Check if device is a CPU device
///
/// \return true if SYCL device is a CPU device
bool is_cpu() const { return MType == UR_DEVICE_TYPE_CPU; }
/// Check if device is a GPU device
///
/// \return true if SYCL device is a GPU device
bool is_gpu() const { return MType == UR_DEVICE_TYPE_GPU; }
/// Check if device is an accelerator device
///
/// \return true if SYCL device is an accelerator device
bool is_accelerator() const { return MType == UR_DEVICE_TYPE_FPGA; }
/// Return device type
///
/// \return the type of the device
ur_device_type_t get_device_type() const { return MType; }
/// Get associated SYCL platform
///
/// If this SYCL device is an OpenCL device then the SYCL platform
/// must encapsulate the OpenCL cl_plaform_id associated with the
/// underlying OpenCL cl_device_id of this SYCL device. If this SYCL device
/// is a host device then the SYCL platform must be a host platform.
/// The value returned must be equal to that returned
/// by get_info<info::device::platform>().
///
/// \return The associated SYCL platform.
platform get_platform() const;
/// \return the associated adapter with this device.
const AdapterPtr &getAdapter() const { return MPlatform->getAdapter(); }
/// Check SYCL extension support by device
///
/// \param ExtensionName is a name of queried extension.
/// \return true if SYCL device supports the extension.
bool has_extension(const std::string &ExtensionName) const;
std::vector<device>
create_sub_devices(const ur_device_partition_properties_t *Properties,
size_t SubDevicesCount) const;
/// Partition device into sub devices
///
/// If this SYCL device does not support
/// info::partition_property::partition_equally a feature_not_supported
/// exception must be thrown.
///
/// \param ComputeUnits is a desired count of compute units in each sub
/// device.
/// \return A vector class of sub devices partitioned equally from this
/// SYCL device based on the ComputeUnits parameter.
std::vector<device> create_sub_devices(size_t ComputeUnits) const;
/// Partition device into sub devices
///
/// If this SYCL device does not support
/// info::partition_property::partition_by_counts a feature_not_supported
/// exception must be thrown.
///
/// \param Counts is a std::vector of desired compute units in sub devices.
/// \return a std::vector of sub devices partitioned from this SYCL device
/// by count sizes based on the Counts parameter.
std::vector<device>
create_sub_devices(const std::vector<size_t> &Counts) const;
/// Partition device into sub devices
///
/// If this SYCL device does not support
/// info::partition_property::partition_by_affinity_domain or the SYCL
/// device does not support info::affinity_domain provided a
/// feature_not_supported exception must be thrown.
///
/// \param AffinityDomain is one of the values described in Table 4.20 of
/// SYCL Spec
/// \return a vector class of sub devices partitioned from this SYCL device
/// by affinity domain based on the AffinityDomain parameter
std::vector<device>
create_sub_devices(info::partition_affinity_domain AffinityDomain) const;
/// Partition device into sub devices
///
/// If this SYCL device does not support
/// info::partition_property::ext_intel_partition_by_cslice a
/// feature_not_supported exception must be thrown.
///
/// \return a vector class of sub devices partitioned from this SYCL
/// device at a granularity of "cslice" (compute slice).
std::vector<device> create_sub_devices() const;
/// Check if desired partition property supported by device
///
/// \param Prop is one of info::partition_property::(partition_equally,
/// partition_by_counts, partition_by_affinity_domain)
/// \return true if Prop is supported by device.
bool is_partition_supported(info::partition_property Prop) const;
/// Queries this SYCL device for information requested by the template
/// parameter param
///
/// Specializations of info::param_traits must be defined in accordance
/// with the info parameters in Table 4.20 of SYCL Spec to facilitate
/// returning the type associated with the param parameter.
///
/// \return device info of type described in Table 4.20.
template <typename Param> typename Param::return_type get_info() const;
/// Queries SYCL queue for SYCL backend-specific information.
///
/// The return type depends on information being queried.
template <typename Param>
typename Param::return_type get_backend_info() const;
/// Check if affinity partitioning by specified domain is supported by
/// device
///
/// \param AffinityDomain is one of the values described in Table 4.20 of
/// SYCL Spec
/// \return true if AffinityDomain is supported by device.
bool
is_affinity_supported(info::partition_affinity_domain AffinityDomain) const;
/// Gets the native handle of the SYCL device.
///
/// \return a native handle.
ur_native_handle_t getNative() const;
/// Indicates if the SYCL device has the given feature.
///
/// \param Aspect is one of the values in Table 4.20 of the SYCL 2020
/// Provisional Spec.
//
/// \return true if the SYCL device has the given feature.
bool has(aspect Aspect) const;
/// Indicates the SYCL device prefers to use its native assert
/// implementation.
///
/// If this is false we will use the fallback assert implementation,
/// as detailed in doc/design/Assert.md
bool useNativeAssert() const;
bool isRootDevice() const { return MRootDevice == nullptr; }
std::string getDeviceName() const;
bool
extOneapiArchitectureIs(ext::oneapi::experimental::architecture Arch) const {
return Arch == getDeviceArch();
}
bool extOneapiArchitectureIs(
ext::oneapi::experimental::arch_category Category) const {
std::optional<ext::oneapi::experimental::architecture> CategoryMinArch =
get_category_min_architecture(Category);
std::optional<ext::oneapi::experimental::architecture> CategoryMaxArch =
get_category_max_architecture(Category);
if (CategoryMinArch.has_value() && CategoryMaxArch.has_value())
return CategoryMinArch <= getDeviceArch() &&
getDeviceArch() <= CategoryMaxArch;
return false;
}
bool extOneapiCanCompile(ext::oneapi::experimental::source_language Language);
// Returns all guarantees that are either equal to guarantee or weaker than
// it. E.g if guarantee == parallel, it returns the vector {weakly_parallel,
// parallel}.
template <typename ReturnT>
static ReturnT getProgressGuaranteesUpTo(
ext::oneapi::experimental::forward_progress_guarantee guarantee) {
const int forwardProgressGuaranteeSize = 3;
int guaranteeVal = static_cast<int>(guarantee);
ReturnT res;
res.reserve(forwardProgressGuaranteeSize - guaranteeVal);
for (int currentGuarantee = forwardProgressGuaranteeSize - 1;
currentGuarantee >= guaranteeVal; --currentGuarantee) {
res.emplace_back(
static_cast<ext::oneapi::experimental::forward_progress_guarantee>(
currentGuarantee));
}
return res;
}
static sycl::ext::oneapi::experimental::forward_progress_guarantee
getHostProgressGuarantee(
sycl::ext::oneapi::experimental::execution_scope threadScope,
sycl::ext::oneapi::experimental::execution_scope coordinationScope);
sycl::ext::oneapi::experimental::forward_progress_guarantee
getProgressGuarantee(
ext::oneapi::experimental::execution_scope threadScope,
ext::oneapi::experimental::execution_scope coordinationScope) const;
bool supportsForwardProgress(
ext::oneapi::experimental::forward_progress_guarantee guarantee,
ext::oneapi::experimental::execution_scope threadScope,
ext::oneapi::experimental::execution_scope coordinationScope) const;
ext::oneapi::experimental::forward_progress_guarantee
getImmediateProgressGuarantee(
ext::oneapi::experimental::execution_scope coordination_scope) const;
/// Gets the current device timestamp
/// @throw sycl::feature_not_supported if feature is not supported on device
uint64_t getCurrentDeviceTime();
/// Check clGetDeviceAndHostTimer is available for fallback profiling
bool isGetDeviceAndHostTimerSupported();
/// Get the backend of this device
backend getBackend() const { return MPlatform->getBackend(); }
// TODO: const-correctness
/// @brief Get the platform impl serving this device
platform_impl &getPlatformImpl() const { return *MPlatform; }
/// Get device info string
std::string get_device_info_string(ur_device_info_t InfoCode) const;
/// Get device architecture
ext::oneapi::experimental::architecture getDeviceArch() const;
private:
ur_device_handle_t MDevice = 0;
ur_device_type_t MType;
ur_device_handle_t MRootDevice = nullptr;
platform_impl *MPlatform = nullptr;
bool MUseNativeAssert = false;
mutable std::string MDeviceName;
mutable std::once_flag MDeviceNameFlag;
mutable ext::oneapi::experimental::architecture MDeviceArch{};
mutable std::once_flag MDeviceArchFlag;
std::pair<uint64_t, uint64_t> MDeviceHostBaseTime{0, 0};
}; // class device_impl
} // namespace detail
} // namespace _V1
} // namespace sycl