DPC++ Runtime
Runtime libraries for oneAPI DPC++
device_filter.cpp
Go to the documentation of this file.
1 //==------------------- device_filter.cpp ----------------------------------==//
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 <detail/config.hpp>
12 #include <detail/device_impl.hpp>
13 
14 #include <cstring>
15 #include <string_view>
16 
18 namespace sycl {
19 namespace detail {
20 
21 std::vector<std::string_view> tokenize(const std::string &Filter,
22  const std::string &Delim) {
23  std::vector<std::string_view> Tokens;
24  size_t Pos = 0;
25  size_t LastPos = 0;
26 
27  while ((Pos = Filter.find(Delim, LastPos)) != std::string::npos) {
28  std::string_view Tok(Filter.data() + LastPos, (Pos - LastPos));
29 
30  if (!Tok.empty()) {
31  Tokens.push_back(Tok);
32  }
33  // move the search starting index
34  LastPos = Pos + 1;
35  }
36 
37  // Add remainder if any
38  if (LastPos < Filter.size()) {
39  std::string_view Tok(Filter.data() + LastPos, Filter.size() - LastPos);
40  Tokens.push_back(Tok);
41  }
42  return Tokens;
43 }
44 
45 device_filter::device_filter(const std::string &FilterString) {
46  std::vector<std::string_view> Tokens = tokenize(FilterString, ":");
47  size_t TripleValueID = 0;
48 
49  auto FindElement = [&](auto Element) {
50  return std::string::npos != Tokens[TripleValueID].find(Element.first);
51  };
52 
53  // Handle the optional 1st field of the filter, backend
54  // Check if the first entry matches with a known backend type
55  auto It = std::find_if(std::begin(getSyclBeMap()), std::end(getSyclBeMap()),
56  FindElement);
57  // If no match is found, set the backend type backend::all
58  // which actually means 'any backend' will be a match.
59  if (It == getSyclBeMap().end())
60  Backend = backend::all;
61  else {
62  Backend = It->second;
63  TripleValueID++;
64  }
65 
66  // Handle the optional 2nd field of the filter - device type.
67  // Check if the 2nd entry matches with any known device type.
68  if (TripleValueID >= Tokens.size()) {
69  DeviceType = info::device_type::all;
70  } else {
71  auto Iter = std::find_if(std::begin(getSyclDeviceTypeMap()),
72  std::end(getSyclDeviceTypeMap()), FindElement);
73  // If no match is found, set device_type 'all',
74  // which actually means 'any device_type' will be a match.
75  if (Iter == getSyclDeviceTypeMap().end())
76  DeviceType = info::device_type::all;
77  else {
78  DeviceType = Iter->second;
79  TripleValueID++;
80  }
81  }
82 
83  // Handle the optional 3rd field of the filter, device number
84  // Try to convert the remaining string to an integer.
85  // If succeessful, the converted integer is the desired device num.
86  if (TripleValueID < Tokens.size()) {
87  try {
88  DeviceNum = std::stoi(Tokens[TripleValueID].data());
89  HasDeviceNum = true;
90  } catch (...) {
91  std::string Message =
92  std::string("Invalid device filter: ") + FilterString +
93  "\nPossible backend values are "
94  "{host,opencl,level_zero,cuda,hip,esimd_emulator,*}.\n"
95  "Possible device types are {host,cpu,gpu,acc,*}.\n"
96  "Device number should be an non-negative integer.\n";
97  throw cl::sycl::invalid_parameter_error(Message, PI_INVALID_VALUE);
98  }
99  }
100 }
101 
102 device_filter_list::device_filter_list(const std::string &FilterStr) {
103  // First, change the string in all lowercase.
104  // This means we allow the user to use both uppercase and lowercase strings.
105  std::string FilterString = FilterStr;
106  std::transform(FilterString.begin(), FilterString.end(), FilterString.begin(),
107  ::tolower);
108  // SYCL_DEVICE_FILTER can set multiple filters separated by commas.
109  // convert each filter triple string into an istance of device_filter class.
110  size_t Pos = 0;
111  while (Pos < FilterString.size()) {
112  size_t CommaPos = FilterString.find(",", Pos);
113  if (CommaPos == std::string::npos) {
114  CommaPos = FilterString.size();
115  }
116  std::string SubString = FilterString.substr(Pos, CommaPos - Pos);
117  FilterList.push_back(device_filter(SubString));
118  Pos = CommaPos + 1;
119  }
120 }
121 
122 device_filter_list::device_filter_list(device_filter &Filter) {
123  FilterList.push_back(Filter);
124 }
125 
126 void device_filter_list::addFilter(device_filter &Filter) {
127  FilterList.push_back(Filter);
128 }
129 
130 // Backend is compatible with the SYCL_DEVICE_FILTER in the following cases.
131 // 1. Filter backend is '*' which means ANY backend.
132 // 2. Filter backend match exactly with the given 'Backend'
133 bool device_filter_list::backendCompatible(backend Backend) {
134  for (const device_filter &Filter : FilterList) {
135  backend FilterBackend = Filter.Backend;
136  if (FilterBackend == Backend || FilterBackend == backend::all)
137  return true;
138  }
139  return false;
140 }
141 
142 bool device_filter_list::deviceTypeCompatible(info::device_type DeviceType) {
143  for (const device_filter &Filter : FilterList) {
144  info::device_type FilterDevType = Filter.DeviceType;
145  if (FilterDevType == DeviceType || FilterDevType == info::device_type::all)
146  return true;
147  }
148  return false;
149 }
150 
151 bool device_filter_list::deviceNumberCompatible(int DeviceNum) {
152  for (const device_filter &Filter : FilterList) {
153  int FilterDevNum = Filter.DeviceNum;
154  if (!Filter.HasDeviceNum || FilterDevNum == DeviceNum)
155  return true;
156  }
157  return false;
158 }
159 
160 bool device_filter_list::containsHost() {
161  for (const device_filter &Filter : FilterList) {
162  if (Filter.Backend == backend::host || Filter.Backend == backend::all)
163  if (Filter.DeviceType == info::device_type::host ||
164  Filter.DeviceType == info::device_type::all)
165  // SYCL RT never creates more than one HOST device.
166  // All device numbers other than 0 are rejected.
167  if (!Filter.HasDeviceNum || Filter.DeviceNum == 0)
168  return true;
169  }
170  return false;
171 }
172 
173 } // namespace detail
174 } // namespace sycl
175 } // __SYCL_INLINE_NAMESPACE(cl)
cl::sycl::backend
backend
Definition: backend_types.hpp:21
device_filter.hpp
cl::sycl::detail::device_filter
Definition: device_filter.hpp:22
config.hpp
cl::sycl::info::device_type
device_type
Definition: info_desc.hpp:180
cl::sycl::detail::tokenize
std::vector< std::string_view > tokenize(const std::string &Filter, const std::string &Delim)
Definition: device_filter.cpp:21
sycl
Definition: invoke_simd.hpp:68
device_impl.hpp
cl::sycl::detail::getSyclBeMap
const std::array< std::pair< std::string, backend >, 7 > & getSyclBeMap()
Definition: config.cpp:172
cl
We provide new interfaces for matrix muliply in this patch:
Definition: access.hpp:13
cl::sycl::detail::getSyclDeviceTypeMap
const std::array< std::pair< std::string, info::device_type >, 5 > & getSyclDeviceTypeMap()
Definition: config.cpp:161
PI_INVALID_VALUE
@ PI_INVALID_VALUE
Definition: pi.h:91
cl::sycl::all
detail::enable_if_t< detail::is_sigeninteger< T >::value, int > all(T x) __NOEXC
Definition: builtins.hpp:1297
info_desc.hpp
__SYCL_INLINE_NAMESPACE
#define __SYCL_INLINE_NAMESPACE(X)
Definition: defines_elementary.hpp:12