DPC++ Runtime
Runtime libraries for oneAPI DPC++
device_selector.cpp
Go to the documentation of this file.
1 //==------ device_selector.cpp - SYCL device selector ----------------------==//
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 
11 #include <CL/sycl/device.hpp>
13 #include <CL/sycl/exception.hpp>
14 #include <CL/sycl/stl.hpp>
15 #include <detail/config.hpp>
16 #include <detail/device_impl.hpp>
18 #include <detail/force_device.hpp>
21 // 4.6.1 Device selection class
22 
23 #include <algorithm>
24 #include <cctype>
25 #include <regex>
26 
28 namespace sycl {
29 
30 // Utility function to check if device is of the preferred backend.
31 // Currently preference is given to the level_zero backend.
32 static bool isDeviceOfPreferredSyclBe(const device &Device) {
33  if (Device.is_host())
34  return false;
35 
36  return detail::getSyclObjImpl(Device)->getPlugin().getBackend() ==
37  backend::ext_oneapi_level_zero;
38 }
39 
40 device device_selector::select_device() const {
41  std::vector<device> devices = device::get_devices();
42  int score = REJECT_DEVICE_SCORE;
43  const device *res = nullptr;
44 
45  for (const auto &dev : devices) {
46  int dev_score = (*this)(dev);
47 
49  std::string PlatformName = dev.get_info<info::device::platform>()
50  .get_info<info::platform::name>();
51  std::string DeviceName = dev.get_info<info::device::name>();
52  std::cout << "SYCL_PI_TRACE[all]: "
53  << "select_device(): -> score = " << dev_score
54  << ((dev_score < 0) ? " (REJECTED)" : "") << std::endl
55  << "SYCL_PI_TRACE[all]: "
56  << " platform: " << PlatformName << std::endl
57  << "SYCL_PI_TRACE[all]: "
58  << " device: " << DeviceName << std::endl;
59  }
60 
61  // A negative score means that a device must not be selected.
62  if (dev_score < 0)
63  continue;
64 
65  // SYCL spec says: "If more than one device receives the high score then
66  // one of those tied devices will be returned, but which of the devices
67  // from the tied set is to be returned is not defined". Here we give a
68  // preference to the device of the preferred BE.
69  //
70  if ((score < dev_score) ||
71  (score == dev_score && isDeviceOfPreferredSyclBe(dev))) {
72  res = &dev;
73  score = dev_score;
74  }
75  }
76 
77  if (res != nullptr) {
79  std::string PlatformName = res->get_info<info::device::platform>()
80  .get_info<info::platform::name>();
81  std::string DeviceName = res->get_info<info::device::name>();
82  std::cout << "SYCL_PI_TRACE[all]: "
83  << "Selected device ->" << std::endl
84  << "SYCL_PI_TRACE[all]: "
85  << " platform: " << PlatformName << std::endl
86  << "SYCL_PI_TRACE[all]: "
87  << " device: " << DeviceName << std::endl;
88  }
89  return *res;
90  }
91 
92  throw cl::sycl::runtime_error("No device of requested type available.",
94 }
95 
100 int default_selector::operator()(const device &dev) const {
101 
102  int Score = REJECT_DEVICE_SCORE;
103 
104  // Give preference to device of SYCL BE.
105  if (isDeviceOfPreferredSyclBe(dev))
106  Score = 50;
107 
108  // If SYCL_DEVICE_FILTER is set, filter device gets a high point.
109  // All unmatched devices should never be selected.
110  detail::device_filter_list *FilterList =
112  // device::get_devices returns filtered list of devices.
113  // Keep 1000 for default score when filters were applied.
114  if (FilterList)
115  Score = 1000;
116 
118  Score += 1000;
119 
120  if (dev.is_gpu())
121  Score += 500;
122 
123  if (dev.is_cpu())
124  Score += 300;
125 
126  if (dev.is_host())
127  Score += 100;
128 
129  // Since we deprecate SYCL_BE and SYCL_DEVICE_TYPE,
130  // we should not disallow accelerator to be chosen.
131  // But this device type gets the lowest heuristic point.
132  if (dev.is_accelerator())
133  Score += 75;
134 
135  return Score;
136 }
137 
138 int gpu_selector::operator()(const device &dev) const {
139  int Score = REJECT_DEVICE_SCORE;
140 
141  if (dev.is_gpu()) {
142  // device::get_devices returns filtered list of devices.
143  Score = 1000;
144  // Give preference to device of SYCL BE.
145  if (isDeviceOfPreferredSyclBe(dev))
146  Score += 50;
147  }
148  return Score;
149 }
150 
151 int cpu_selector::operator()(const device &dev) const {
152  int Score = REJECT_DEVICE_SCORE;
153 
154  if (dev.is_cpu()) {
155  // device::get_devices returns filtered list of devices.
156  Score = 1000;
157 
158  // Give preference to device of SYCL BE.
159  if (isDeviceOfPreferredSyclBe(dev))
160  Score += 50;
161  }
162  return Score;
163 }
164 
165 int accelerator_selector::operator()(const device &dev) const {
166  int Score = REJECT_DEVICE_SCORE;
167 
168  if (dev.is_accelerator()) {
169  // device::get_devices returns filtered list of devices.
170  Score = 1000;
171 
172  // Give preference to device of SYCL BE.
173  if (isDeviceOfPreferredSyclBe(dev))
174  Score += 50;
175  }
176  return Score;
177 }
178 
179 int host_selector::operator()(const device &dev) const {
180  int Score = REJECT_DEVICE_SCORE;
181 
182  if (dev.is_host()) {
183  Score = 1000;
184  // Give preference to device of SYCL BE.
185  if (isDeviceOfPreferredSyclBe(dev))
186  Score += 50;
187  }
188  return Score;
189 }
190 
191 namespace ext {
192 namespace oneapi {
193 
194 filter_selector::filter_selector(const std::string &Input)
195  : impl(std::make_shared<detail::filter_selector_impl>(Input)) {}
196 
197 int filter_selector::operator()(const device &Dev) const {
198  return impl->operator()(Dev);
199 }
200 
201 void filter_selector::reset() const { impl->reset(); }
202 
204  std::lock_guard<std::mutex> Guard(
205  sycl::detail::GlobalHandler::instance().getFilterMutex());
206 
208 
209  reset();
210 
211  return Result;
212 }
213 
214 } // namespace oneapi
215 } // namespace ext
216 
217 namespace __SYCL2020_DEPRECATED("use 'ext::oneapi' instead") ONEAPI {
218  using namespace ext::oneapi;
219  filter_selector::filter_selector(const std::string &Input)
220  : ext::oneapi::filter_selector(Input) {}
221 
222  int filter_selector::operator()(const device &Dev) const {
224  }
225 
227 
230  }
231 } // namespace ONEAPI
232 } // namespace sycl
233 } // __SYCL_INLINE_NAMESPACE(cl)
cl::sycl::ext::oneapi::filter_selector::operator()
int operator()(const device &dev) const override
Definition: device_selector.cpp:197
cl::sycl::info::device
device
Definition: info_desc.hpp:53
cl::sycl::detail::GlobalHandler::instance
static GlobalHandler & instance()
Definition: global_handler.cpp:35
cl::sycl::device_selector::select_device
virtual device select_device() const
Definition: device_selector.cpp:40
device_filter.hpp
config.hpp
cl::sycl::device::is_cpu
bool is_cpu() const
Check if device is a CPU device.
Definition: device.cpp:104
stl.hpp
device_selector.hpp
cl::sycl::detail::pi::PI_TRACE_ALL
@ PI_TRACE_ALL
Definition: pi.hpp:58
device.hpp
cl::sycl::device::is_gpu
bool is_gpu() const
Check if device is a GPU device.
Definition: device.cpp:106
cl::sycl::info::device_type
device_type
Definition: info_desc.hpp:180
cl::sycl::detail::pi::PI_TRACE_BASIC
@ PI_TRACE_BASIC
Definition: pi.hpp:56
sycl
Definition: invoke_simd.hpp:68
device_impl.hpp
cl::sycl::device::is_accelerator
bool is_accelerator() const
Check if device is an accelerator device.
Definition: device.cpp:108
filter_selector.hpp
cl::sycl::detail::get_forced_type
info::device_type get_forced_type()
Definition: force_device.cpp:24
cl::sycl::device
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:35
cl::sycl::__SYCL2020_DEPRECATED
class __SYCL2020_DEPRECATED("sycl::atomic is deprecated since SYCL 2020") atomic
Definition: atomic.hpp:171
cl::sycl::detail::device_filter_list
Definition: device_filter.hpp:37
PI_DEVICE_NOT_FOUND
@ PI_DEVICE_NOT_FOUND
Definition: pi.h:111
force_device.hpp
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
global_handler.hpp
cl::sycl::ext::oneapi::filter_selector::select_device
device select_device() const override
Definition: device_selector.cpp:203
cl::sycl::isDeviceOfPreferredSyclBe
static bool isDeviceOfPreferredSyclBe(const device &Device)
Definition: device_selector.cpp:32
std::get
constexpr tuple_element< I, tuple< Types... > >::type & get(cl::sycl::detail::tuple< Types... > &Arg) noexcept
Definition: tuple.hpp:199
cl::sycl::device::get_info
info::param_traits< info::device, param >::return_type get_info() const
Queries this SYCL device for information requested by the template parameter param.
Definition: device.cpp:147
cl::sycl::detail::getSyclObjImpl
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: common.hpp:204
backend_types.hpp
exception.hpp
std
Definition: accessor.hpp:2616
cl::sycl::info::platform
platform
Definition: info_desc.hpp:31
cl::sycl::instead
std::uint8_t instead
Definition: aliases.hpp:68
cl::sycl::detail::pi::trace
bool trace(TraceLevel level)
Definition: pi.cpp:368
filter_selector_impl.hpp
cl::sycl::ext::oneapi::filter_selector::reset
void reset() const
Definition: device_selector.cpp:201
cl::sycl::device::is_host
bool is_host() const
Get instance of device.
Definition: device.cpp:102
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12