16 #include <string_view>
19 inline namespace _V1 {
22 std::vector<std::string_view>
tokenize(
const std::string_view &Filter,
23 const std::string &Delim,
24 bool ProhibitEmptyTokens =
false) {
25 std::vector<std::string_view> Tokens;
29 while ((Pos = Filter.find(Delim, LastPos)) != std::string::npos) {
30 std::string_view Tok(Filter.data() + LastPos, (Pos - LastPos));
33 Tokens.push_back(Tok);
34 }
else if (ProhibitEmptyTokens) {
37 "ONEAPI_DEVICE_SELECTOR parsing error. Empty input before '" + Delim +
38 "' delimiter is not allowed.");
45 if (LastPos < Filter.size()) {
46 std::string_view Tok(Filter.data() + LastPos, Filter.size() - LastPos);
47 Tokens.push_back(Tok);
48 }
else if ((LastPos != 0) && ProhibitEmptyTokens) {
52 "ONEAPI_DEVICE_SELECTOR parsing error. Empty input after '" + Delim +
53 "' delimiter is not allowed.");
62 const std::string_view &FullEntry) {
68 std::find_if(std::begin(SyclBeMap), std::end(SyclBeMap),
69 [&](
auto BePair) {
return BackendStr == BePair.first; });
71 if (It == SyclBeMap.end()) {
74 ss <<
"ONEAPI_DEVICE_SELECTOR parsing error. Backend is required but "
84 const std::string_view &DeviceStr) {
86 std::vector<std::string_view> DeviceSubTuple =
88 if (DeviceSubTuple.empty())
91 "ONEAPI_DEVICE_SELECTOR parsing error. Device must be specified.");
93 std::string_view TopDeviceStr = DeviceSubTuple[0];
99 std::find_if(std::begin(DeviceTypeMap), std::end(DeviceTypeMap),
100 [&](
auto DtPair) {
return TopDeviceStr == DtPair.first; });
101 if (It != DeviceTypeMap.end()) {
104 if (TopDeviceStr[0] ==
'*') {
109 std::string TDS(TopDeviceStr);
114 "error parsing device number: " + TDS);
118 if (DeviceSubTuple.size() >= 2) {
128 "sub-devices can only be requested when parent device is specified "
129 "by number or wildcard, not a device type like 'gpu'");
131 std::string_view SubDeviceStr = DeviceSubTuple[1];
133 if (SubDeviceStr[0] ==
'*') {
140 "sub-device can't be requested by number if "
141 "parent device is specified by a wildcard.");
143 std::string SDS(SubDeviceStr);
148 "error parsing sub-device index: " + SDS);
152 if (DeviceSubTuple.size() == 3) {
156 std::string_view SubSubDeviceStr = DeviceSubTuple[2];
157 if (SubSubDeviceStr[0] ==
'*') {
164 "sub-sub-device can't be requested by number if "
165 "sub-device before is specified by a wildcard.");
167 std::string SSDS(SubSubDeviceStr);
172 "error parsing sub-sub-device index: " + SSDS);
175 }
else if (DeviceSubTuple.size() > 3) {
176 std::stringstream ss;
177 ss <<
"error parsing " << DeviceStr
178 <<
" Only two levels of sub-devices supported at this time";
183 std::vector<ods_target>
186 std::string envStr = envString;
187 std::transform(envStr.begin(), envStr.end(), envStr.begin(), ::tolower);
189 std::vector<ods_target> Result;
190 if (envStr.empty()) {
192 Result.push_back(acceptAnything);
196 std::vector<std::string_view> Entries =
tokenize(envStr,
";");
197 unsigned int negative_filters = 0;
200 for (
const auto Entry : Entries) {
201 std::vector<std::string_view> Pair =
207 std::stringstream ss;
208 ss <<
"Incomplete selector! Backend and device must be specified.";
210 }
else if (Pair.size() == 1) {
211 std::stringstream ss;
212 ss <<
"Incomplete selector! Try '" << Pair[0]
213 <<
":*' if all devices under the backend was original intention.";
215 }
else if (Pair.size() > 2) {
216 std::stringstream ss;
217 ss <<
"Error parsing selector string \"" << Entry
218 <<
"\" Too many colons (:)";
226 std::string_view input_be = Pair[0];
227 if (Pair[0][0] ==
'!')
228 input_be = Pair[0].substr(1);
233 std::vector<std::string_view> Targets =
tokenize(Pair[1],
",");
234 for (
auto TargetStr : Targets) {
236 if (Entry[0] ==
'!') {
243 if (negative_filters > 0) {
244 std::stringstream ss;
245 ss <<
"All negative(discarding) filters must appear after all "
246 "positive(accepting) filters!";
252 Result.push_back(DeviceTarget);
266 if (!Result.empty() && negative_filters == Result.size()) {
269 Result.push_back(acceptAll);
278 auto Match = std::find_if(
279 DeviceTypeMap.begin(), DeviceTypeMap.end(),
280 [&](
auto Pair) { return (Pair.second == Target.DeviceType); });
281 if (Match != DeviceTypeMap.end()) {
282 Out <<
":" << Match->first;
309 TargetList.begin(), TargetList.end(), [&](
ods_target &Target) {
310 backend TargetBackend = Target.Backend.value_or(backend::all);
311 return (TargetBackend == Backend) || (TargetBackend == backend::all);
bool backendCompatible(backend Backend)
static void Parse_ODS_Device(ods_target &Target, const std::string_view &DeviceStr)
static backend Parse_ODS_Backend(const std::string_view &BackendStr, const std::string_view &FullEntry)
std::ostream & operator<<(std::ostream &os, std::optional< T > const &opt)
const std::array< std::pair< std::string, info::device_type >, 6 > & getSyclDeviceTypeMap()
std::vector< ods_target > Parse_ONEAPI_DEVICE_SELECTOR(const std::string &envStr)
std::vector< std::string_view > tokenize(const std::string_view &Filter, const std::string &Delim, bool ProhibitEmptyTokens=false)
const std::array< std::pair< std::string, backend >, 7 > & getSyclBeMap()
std::error_code make_error_code(sycl::errc E) noexcept
Constructs an error code using e and sycl_category()
bool any_of(const simd_mask< _Tp, _Abi > &) noexcept
std::optional< backend > Backend
std::optional< int > DeviceNum
std::optional< unsigned > SubDeviceNum
bool HasSubSubDeviceWildCard
std::optional< info::device_type > DeviceType
std::optional< unsigned > SubSubDeviceNum
bool HasSubDeviceWildCard