DPC++ Runtime
Runtime libraries for oneAPI DPC++
filter_selector_impl.cpp
Go to the documentation of this file.
1 //==------ filter_selector.cpp - oneapi filter 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 
9 #include <detail/device_impl.hpp>
11 #include <sycl/backend_types.hpp>
12 #include <sycl/device.hpp>
13 #include <sycl/device_selector.hpp>
14 #include <sycl/exception.hpp>
15 
16 #include <cctype>
17 #include <regex>
18 #include <string>
19 #include <vector>
20 
21 namespace sycl {
22 inline namespace _V1 {
23 namespace ext::oneapi::detail {
24 
25 std::vector<std::string> tokenize(const std::string &Filter,
26  const std::string &Delim) {
27  std::vector<std::string> Tokens;
28  size_t Pos = 0;
29  std::string Input = Filter;
30  std::string Tok;
31 
32  while ((Pos = Input.find(Delim)) != std::string::npos) {
33  Tok = Input.substr(0, Pos);
34  Input.erase(0, Pos + Delim.length());
35 
36  if (!Tok.empty()) {
37  Tokens.push_back(std::move(Tok));
38  }
39  }
40 
41  // Add remainder
42  if (!Input.empty())
43  Tokens.push_back(std::move(Input));
44 
45  return Tokens;
46 }
47 
48 filter create_filter(const std::string &Input) {
49  filter Result;
50  constexpr auto Error = "Invalid filter string! Valid strings conform to "
51  "BE:DeviceType:DeviceNum, where any are optional";
52 
53  std::vector<std::string> Tokens = tokenize(Input, ":");
54  std::regex IntegerExpr("[[:digit:]]+");
55 
56  // There should only be up to 3 tokens.
57  // BE:Device Type:Device Num
58  if (Tokens.size() > 3)
59  throw sycl::runtime_error(Error, PI_ERROR_INVALID_VALUE);
60 
61  for (const std::string &Token : Tokens) {
62  if (Token == "cpu" && !Result.DeviceType) {
63  Result.DeviceType = sycl::info::device_type::cpu;
64  } else if (Token == "gpu" && !Result.DeviceType) {
65  Result.DeviceType = sycl::info::device_type::gpu;
66  } else if (Token == "accelerator" && !Result.DeviceType) {
67  Result.DeviceType = sycl::info::device_type::accelerator;
68  } else if (Token == "opencl" && !Result.Backend) {
69  Result.Backend = backend::opencl;
70  } else if (Token == "level_zero" && !Result.Backend) {
71  Result.Backend = backend::ext_oneapi_level_zero;
72  } else if (Token == "cuda" && !Result.Backend) {
73  Result.Backend = backend::ext_oneapi_cuda;
74  } else if (Token == "hip" && !Result.Backend) {
75  Result.Backend = backend::ext_oneapi_hip;
76  } else if (std::regex_match(Token, IntegerExpr) && !Result.DeviceNum) {
77  try {
78  Result.DeviceNum = std::stoi(Token);
79  } catch (std::logic_error &) {
80  throw sycl::runtime_error(Error, PI_ERROR_INVALID_VALUE);
81  }
82  } else {
83  throw sycl::runtime_error(Error, PI_ERROR_INVALID_VALUE);
84  }
85  }
86 
87  return Result;
88 }
89 
91  : mFilters(), mNumDevicesSeen(0), mMatchFound(false) {
92  std::vector<std::string> Filters = detail::tokenize(Input, ",");
93  mNumTotalDevices = device::get_devices().size();
94 
95  for (const std::string &Filter : Filters) {
97  mFilters.push_back(std::move(F));
98  }
99 }
100 
102  assert(!sycl::detail::getSyclObjImpl(Dev)->is_host() &&
103  "filter_selector_impl should not be used with host.");
104 
105  int Score = REJECT_DEVICE_SCORE;
106 
107  for (auto &Filter : mFilters) {
108  bool BackendOK = true;
109  bool DeviceTypeOK = true;
110  bool DeviceNumOK = true;
111 
112  if (Filter.Backend) {
113  backend BE = sycl::detail::getSyclObjImpl(Dev)->getBackend();
114  // Backend is okay if the filter BE is set 'all'.
115  if (Filter.Backend.value() == backend::all)
116  BackendOK = true;
117  else
118  BackendOK = (BE == Filter.Backend.value());
119  }
120  if (Filter.DeviceType) {
123  // DeviceType is okay if the filter is set 'all'.
124  if (Filter.DeviceType == sycl::info::device_type::all)
125  DeviceTypeOK = true;
126  else
127  DeviceTypeOK = (DT == Filter.DeviceType);
128  }
129  if (Filter.DeviceNum) {
130  // Only check device number if we're good on the previous matches
131  if (BackendOK && DeviceTypeOK) {
132  // Do we match?
133  DeviceNumOK = (Filter.MatchesSeen == Filter.DeviceNum.value());
134  // Safe to increment matches even if we find it
135  Filter.MatchesSeen++;
136  }
137  }
138  if (BackendOK && DeviceTypeOK && DeviceNumOK) {
139  Score = default_selector_v(Dev);
140  mMatchFound = true;
141  break;
142  }
143  }
144 
145  mNumDevicesSeen++;
146  if ((mNumDevicesSeen == mNumTotalDevices) && !mMatchFound) {
147  throw sycl::runtime_error(
148  "Could not find a device that matches the specified filter(s)!",
149  PI_ERROR_DEVICE_NOT_FOUND);
150  }
151 
152  return Score;
153 }
154 
156  // This is a bit of an abuse of "const" method...
157  // Reset state if you want to reuse this selector.
158  for (auto &Filter : mFilters) {
159  Filter.MatchesSeen = 0;
160  }
161  mMatchFound = false;
162  mNumDevicesSeen = 0;
163 }
164 
165 } // namespace ext::oneapi::detail
166 
167 namespace __SYCL2020_DEPRECATED("use 'ext::oneapi' instead") ONEAPI {
168 using namespace ext::oneapi;
169 }
170 } // namespace _V1
171 } // namespace sycl
The SYCL device class encapsulates a single SYCL device on which kernels may be executed.
Definition: device.hpp:64
static std::vector< device > get_devices(info::device_type deviceType=info::device_type::all)
Query available SYCL devices.
Definition: device.cpp:51
detail::is_device_info_desc< Param >::return_type get_info() const
Queries this SYCL device for information requested by the template parameter param.
Definition: device.hpp:223
class __SYCL2020_DEPRECATED("Host device is no longer supported.") host_selector int default_selector_v(const device &dev)
Selects SYCL host device.
decltype(Obj::impl) getSyclObjImpl(const Obj &SyclObject)
Definition: impl_utils.hpp:30
filter create_filter(const std::string &Input)
std::vector< std::string > tokenize(const std::string &Filter, const std::string &Delim)
signed char __SYCL2020_DEPRECATED
Definition: aliases.hpp:94
std::uint8_t instead
Definition: aliases.hpp:93
Definition: access.hpp:18