16 #include <string_view>
22 std::vector<std::string_view>
tokenize(
const std::string_view &Filter,
23 const std::string &Delim) {
24 std::vector<std::string_view> Tokens;
28 while ((Pos = Filter.find(Delim, LastPos)) != std::string::npos) {
29 std::string_view Tok(Filter.data() + LastPos, (Pos - LastPos));
32 Tokens.push_back(Tok);
39 if (LastPos < Filter.size()) {
40 std::string_view Tok(Filter.data() + LastPos, Filter.size() - LastPos);
41 Tokens.push_back(Tok);
50 const std::string_view &FullEntry) {
55 auto It = std::find_if(
56 std::begin(SyclBeMap), std::end(SyclBeMap), [&](
auto BePair) {
57 return std::string::npos != BackendStr.find(BePair.first);
60 if (It == SyclBeMap.end()) {
63 ss <<
"ONEAPI_DEVICE_SELECTOR parsing error. Backend is required but "
73 const std::string_view &DeviceStr) {
75 std::vector<std::string_view> DeviceSubTuple =
tokenize(DeviceStr,
".");
76 std::string_view TopDeviceStr = DeviceSubTuple[0];
82 auto It = std::find_if(
83 std::begin(DeviceTypeMap), std::end(DeviceTypeMap), [&](
auto DtPair) {
84 return std::string::npos != TopDeviceStr.find(DtPair.first);
86 if (It != DeviceTypeMap.end()) {
89 if (TopDeviceStr[0] ==
'*') {
94 std::string TDS(TopDeviceStr);
99 "error parsing device number: " + TDS);
103 if (DeviceSubTuple.size() >= 2) {
111 throw sycl::exception(
113 "sub-devices can only be requested when parent device is specified "
114 "by number or wildcard, not a device type like 'gpu'");
116 std::string_view SubDeviceStr = DeviceSubTuple[1];
118 if (SubDeviceStr[0] ==
'*') {
125 "sub-device can't be requested by number if "
126 "parent device is specified by a wildcard.");
128 std::string SDS(SubDeviceStr);
133 "error parsing sub-device index: " + SDS);
137 if (DeviceSubTuple.size() == 3) {
141 std::string_view SubSubDeviceStr = DeviceSubTuple[2];
142 if (SubSubDeviceStr[0] ==
'*') {
149 "sub-sub-device can't be requested by number if "
150 "sub-device before is specified by a wildcard.");
152 std::string SSDS(SubSubDeviceStr);
157 "error parsing sub-sub-device index: " + SSDS);
160 }
else if (DeviceSubTuple.size() > 3) {
161 std::stringstream ss;
162 ss <<
"error parsing " << DeviceStr
163 <<
" Only two levels of sub-devices supported at this time";
168 std::vector<ods_target>
171 std::string envStr = envString;
172 std::transform(envStr.begin(), envStr.end(), envStr.begin(), ::tolower);
174 std::vector<ods_target> Result;
175 if (envStr.empty()) {
177 Result.push_back(acceptAnything);
181 std::vector<std::string_view> Entries =
tokenize(envStr,
";");
182 unsigned int negative_filters = 0;
185 for (
const auto Entry : Entries) {
186 std::vector<std::string_view> Pair =
tokenize(Entry,
":");
189 if (Pair.size() == 1) {
190 std::stringstream ss;
191 ss <<
"Incomplete selector! Try '" << Pair[0]
192 <<
":*' if all devices under the backend was original intention.";
194 }
else if (Pair.size() == 2) {
195 std::vector<std::string_view> Targets =
tokenize(Pair[1],
",");
196 for (
auto TargetStr : Targets) {
198 if (Entry[0] ==
'!') {
205 if (negative_filters > 0) {
206 std::stringstream ss;
207 ss <<
"All negative(discarding) filters must appear after all "
208 "positive(accepting) filters!";
214 Result.push_back(DeviceTarget);
216 }
else if (Pair.size() > 2) {
217 std::stringstream ss;
218 ss <<
"Error parsing selector string \"" << Entry
219 <<
"\" Too many colons (:)";
233 if (!Result.empty() && negative_filters == Result.size()) {
235 acceptAll.
DeviceType = info::device_type::all;
236 Result.push_back(acceptAll);
245 auto Match = std::find_if(
246 DeviceTypeMap.begin(), DeviceTypeMap.end(),
247 [&](
auto Pair) { return (Pair.second == Target.DeviceType); });
248 if (Match != DeviceTypeMap.end()) {
249 Out <<
":" << Match->first;
266 ods_target_list::ods_target_list(
const std::string &envStr) {
273 bool ods_target_list::backendCompatible(
backend Backend) {
275 bool isESIMD = Backend == backend::ext_intel_esimd_emulator;
277 TargetList.begin(), TargetList.end(), [&](
ods_target &Target) {
278 backend TargetBackend = Target.Backend.value_or(backend::all);
279 return (TargetBackend == Backend) ||
280 (TargetBackend == backend::all && !isESIMD);
287 device_filter::device_filter(
const std::string &FilterString) {
288 std::vector<std::string_view> Tokens =
tokenize(FilterString,
":");
289 size_t TripleValueID = 0;
291 auto FindElement = [&](
auto Element) {
292 return std::string::npos != Tokens[TripleValueID].find(Element.first);
302 Backend = backend::all;
304 Backend = It->second;
307 if (Backend == backend::host)
308 std::cerr <<
"WARNING: The 'host' backend type is no longer supported in "
315 if (TripleValueID >= Tokens.size()) {
316 DeviceType = info::device_type::all;
323 DeviceType = info::device_type::all;
325 DeviceType = Iter->second;
328 if (DeviceType == info::device_type::host)
329 std::cerr <<
"WARNING: The 'host' device type is no longer supported "
338 if (TripleValueID < Tokens.size()) {
340 DeviceNum = std::stoi(Tokens[TripleValueID].data());
342 std::string Message =
343 std::string(
"Invalid device filter: ") + FilterString +
344 "\nPossible backend values are "
345 "{opencl,level_zero,cuda,hip,esimd_emulator,*}.\n"
346 "Possible device types are {cpu,gpu,acc,*}.\n"
347 "Device number should be an non-negative integer.\n";
348 throw sycl::invalid_parameter_error(Message, PI_ERROR_INVALID_VALUE);
353 device_filter_list::device_filter_list(
const std::string &FilterStr) {
356 std::string FilterString = FilterStr;
357 std::transform(FilterString.begin(), FilterString.end(), FilterString.begin(),
362 while (Pos < FilterString.size()) {
363 size_t CommaPos = FilterString.find(
",", Pos);
364 if (CommaPos == std::string::npos) {
365 CommaPos = FilterString.size();
367 std::string SubString = FilterString.substr(Pos, CommaPos - Pos);
374 FilterList.push_back(Filter);
378 FilterList.push_back(Filter);
384 bool device_filter_list::backendCompatible(
backend Backend) {
386 FilterList.begin(), FilterList.end(), [&](
device_filter &Filter) {
387 backend FilterBackend = Filter.Backend.value_or(backend::all);
388 return (FilterBackend == Backend) || (FilterBackend == backend::all);
393 return std::any_of(FilterList.begin(), FilterList.end(),
395 info::device_type FilterDevType =
396 Filter.DeviceType.value_or(info::device_type::all);
397 return (FilterDevType == DeviceType) ||
398 (FilterDevType == info::device_type::all);
402 bool device_filter_list::deviceNumberCompatible(
int DeviceNum) {
404 FilterList.begin(), FilterList.end(), [&](
device_filter &Filter) {
405 return (!Filter.DeviceNum) || (Filter.DeviceNum.value() == DeviceNum);