diff --git a/sycl/doc/EnvironmentVariables.md b/sycl/doc/EnvironmentVariables.md index 0a1dcd0a03198..8811d6cd354bf 100644 --- a/sycl/doc/EnvironmentVariables.md +++ b/sycl/doc/EnvironmentVariables.md @@ -22,7 +22,7 @@ subject to change. Do not rely on these variables in production code. | SYCL_DISABLE_EXECUTION_GRAPH_CLEANUP | Any(\*) | Disable cleanup of finished command nodes at host-device synchronization points. | | SYCL_THROW_ON_BLOCK | Any(\*) | Throw an exception on attempt to wait for a blocked command. | | SYCL_DEVICELIB_INHIBIT_NATIVE | String of device library extensions (separated by a whitespace) | Do not rely on device native support for devicelib extensions listed in this option. | -| SYCL_DEVICE_ALLOWLIST | A list of devices and their minimum driver version following the pattern: DeviceName:{{XXX}},DriverVersion:{{X.Y.Z.W}}. Also may contain PlatformName and PlatformVersion | Filter out devices that do not match the pattern specified. Regular expression can be passed and the DPC++ runtime will select only those devices which satisfy the regex. | +| SYCL_DEVICE_ALLOWLIST | A list of devices and their driver version following the pattern: DeviceName:{{XXX}},DriverVersion:{{X.Y.Z.W}}. Also may contain PlatformName and PlatformVersion | Filter out devices that do not match the pattern specified. Regular expression can be passed and the DPC++ runtime will select only those devices which satisfy the regex. Special characters, such as parenthesis, must be escaped. More than one device can be specified using the piping symbol "\|".| | SYCL_QUEUE_THREAD_POOL_SIZE | Positive integer | Number of threads in thread pool of queue. | | SYCL_DEVICELIB_NO_FALLBACK | Any(\*) | Disable loading and linking of device library images | | SYCL_PI_LEVEL0_MAX_COMMAND_LIST_CACHE | Positive integer | Maximum number of oneAPI Level Zero Command lists that can be allocated with no reuse before throwing an "out of resources" error. Default is 20000, threshold may be increased based on resource availabilty and workload demand. | diff --git a/sycl/source/detail/platform_impl.cpp b/sycl/source/detail/platform_impl.cpp index 34fc9bd09e119..cc0c01f5a8779 100644 --- a/sycl/source/detail/platform_impl.cpp +++ b/sycl/source/detail/platform_impl.cpp @@ -16,6 +16,7 @@ #include #include #include +#include __SYCL_INLINE_NAMESPACE(cl) { namespace sycl { @@ -120,104 +121,106 @@ vector_class platform_impl::get_platforms() { return Platforms; } -struct DevDescT { - const char *devName = nullptr; - int devNameSize = 0; - const char *devDriverVer = nullptr; - int devDriverVerSize = 0; +std::string getValue(const std::string &AllowList, size_t &Pos, + unsigned long int Size) { + size_t Prev = Pos; + if ((Pos = AllowList.find("{{", Pos)) == std::string::npos) { + throw sycl::runtime_error("Malformed syntax in SYCL_DEVICE_ALLOWLIST", + PI_INVALID_VALUE); + } + if (Pos > Prev + Size) { + throw sycl::runtime_error("Malformed syntax in SYCL_DEVICE_ALLOWLIST", + PI_INVALID_VALUE); + } - const char *platformName = nullptr; - int platformNameSize = 0; + Pos = Pos + 2; + size_t Start = Pos; + if ((Pos = AllowList.find("}}", Pos)) == std::string::npos) { + throw sycl::runtime_error("Malformed syntax in SYCL_DEVICE_ALLOWLIST", + PI_INVALID_VALUE); + } + std::string Value = AllowList.substr(Start, Pos - Start); + Pos = Pos + 2; + return Value; +} - const char *platformVer = nullptr; - int platformVerSize = 0; +struct DevDescT { + std::string DevName; + std::string DevDriverVer; + std::string PlatName; + std::string PlatVer; }; static std::vector getAllowListDesc() { - const char *str = SYCLConfig::get(); - if (!str) + std::string AllowList(SYCLConfig::get()); + if (AllowList.empty()) return {}; - std::vector decDescs; - const char devNameStr[] = "DeviceName"; - const char driverVerStr[] = "DriverVersion"; - const char platformNameStr[] = "PlatformName"; - const char platformVerStr[] = "PlatformVersion"; - decDescs.emplace_back(); - while ('\0' != *str) { - const char **valuePtr = nullptr; - int *size = nullptr; - - // -1 to avoid comparing null terminator - if (0 == strncmp(devNameStr, str, sizeof(devNameStr) - 1)) { - valuePtr = &decDescs.back().devName; - size = &decDescs.back().devNameSize; - str += sizeof(devNameStr) - 1; - } else if (0 == - strncmp(platformNameStr, str, sizeof(platformNameStr) - 1)) { - valuePtr = &decDescs.back().platformName; - size = &decDescs.back().platformNameSize; - str += sizeof(platformNameStr) - 1; - } else if (0 == strncmp(platformVerStr, str, sizeof(platformVerStr) - 1)) { - valuePtr = &decDescs.back().platformVer; - size = &decDescs.back().platformVerSize; - str += sizeof(platformVerStr) - 1; - } else if (0 == strncmp(driverVerStr, str, sizeof(driverVerStr) - 1)) { - valuePtr = &decDescs.back().devDriverVer; - size = &decDescs.back().devDriverVerSize; - str += sizeof(driverVerStr) - 1; - } else { - throw sycl::runtime_error("Unrecognized key in device allowlist", - PI_INVALID_VALUE); + std::string DeviceName("DeviceName:"); + std::string DriverVersion("DriverVersion:"); + std::string PlatformName("PlatformName:"); + std::string PlatformVersion("PlatformVersion:"); + std::vector DecDescs; + DecDescs.emplace_back(); + + size_t Pos = 0; + while (Pos < AllowList.size()) { + if ((AllowList.compare(Pos, DeviceName.size(), DeviceName)) == 0) { + DecDescs.back().DevName = getValue(AllowList, Pos, DeviceName.size()); + if (AllowList[Pos] == ',') { + Pos++; + } } - if (':' != *str) - throw sycl::runtime_error("Malformed device allowlist", PI_INVALID_VALUE); - - // Skip ':' - str += 1; - - if ('{' != *str || '{' != *(str + 1)) - throw sycl::runtime_error("Malformed device allowlist", PI_INVALID_VALUE); - - // Skip opening sequence "{{" - str += 2; - - *valuePtr = str; - - // Increment until closing sequence is encountered - while (('\0' != *str) && ('}' != *str || '}' != *(str + 1))) - ++str; - - if ('\0' == *str) - throw sycl::runtime_error("Malformed device allowlist", PI_INVALID_VALUE); - - *size = str - *valuePtr; - - // Skip closing sequence "}}" - str += 2; - - if ('\0' == *str) - break; + else if ((AllowList.compare(Pos, DriverVersion.size(), DriverVersion)) == + 0) { + DecDescs.back().DevDriverVer = + getValue(AllowList, Pos, DriverVersion.size()); + if (AllowList[Pos] == ',') { + Pos++; + } + } - // '|' means that the is another filter - if ('|' == *str) - decDescs.emplace_back(); - else if (',' != *str) - throw sycl::runtime_error("Malformed device allowlist", PI_INVALID_VALUE); + else if ((AllowList.compare(Pos, PlatformName.size(), PlatformName)) == 0) { + DecDescs.back().PlatName = getValue(AllowList, Pos, PlatformName.size()); + if (AllowList[Pos] == ',') { + Pos++; + } + } - ++str; - } + else if ((AllowList.compare(Pos, PlatformVersion.size(), + PlatformVersion)) == 0) { + DecDescs.back().PlatVer = + getValue(AllowList, Pos, PlatformVersion.size()); + } else if (AllowList.find('|', Pos) != std::string::npos) { + Pos = AllowList.find('|') + 1; + while (AllowList[Pos] == ' ') { + Pos++; + } + DecDescs.emplace_back(); + } - return decDescs; + else { + throw sycl::runtime_error("Unrecognized key in device allowlist", + PI_INVALID_VALUE); + } + } // while (Pos <= AllowList.size()) + return DecDescs; } +enum MatchState { UNKNOWN, MATCH, NOMATCH }; + static void filterAllowList(vector_class &PiDevices, RT::PiPlatform PiPlatform, const plugin &Plugin) { const std::vector AllowList(getAllowListDesc()); if (AllowList.empty()) return; + MatchState DevNameState = UNKNOWN; + MatchState DevVerState = UNKNOWN; + MatchState PlatNameState = UNKNOWN; + MatchState PlatVerState = UNKNOWN; + const string_class PlatformName = sycl::detail::get_platform_info::get( PiPlatform, Plugin); @@ -237,33 +240,55 @@ static void filterAllowList(vector_class &PiDevices, string_class, info::device::driver_version>::get(Device, Plugin); for (const DevDescT &Desc : AllowList) { - if (nullptr != Desc.platformName && - !std::regex_match(PlatformName, - std::regex(std::string(Desc.platformName, - Desc.platformNameSize)))) - continue; - - if (nullptr != Desc.platformVer && - !std::regex_match( - PlatformVer, - std::regex(std::string(Desc.platformVer, Desc.platformVerSize)))) - continue; - - if (nullptr != Desc.devName && - !std::regex_match(DeviceName, std::regex(std::string( - Desc.devName, Desc.devNameSize)))) - continue; - - if (nullptr != Desc.devDriverVer && - !std::regex_match(DeviceDriverVer, - std::regex(std::string(Desc.devDriverVer, - Desc.devDriverVerSize)))) - continue; + if (!Desc.PlatName.empty()) { + if (!std::regex_match(PlatformName, std::regex(Desc.PlatName))) { + PlatNameState = MatchState::NOMATCH; + continue; + } else { + PlatNameState = MatchState::MATCH; + } + } + + if (!Desc.PlatVer.empty()) { + if (!std::regex_match(PlatformVer, std::regex(Desc.PlatVer))) { + PlatVerState = MatchState::NOMATCH; + continue; + } else { + PlatVerState = MatchState::MATCH; + } + } + + if (!Desc.DevName.empty()) { + if (!std::regex_match(DeviceName, std::regex(Desc.DevName))) { + DevNameState = MatchState::NOMATCH; + continue; + } else { + DevNameState = MatchState::MATCH; + } + } + + if (!Desc.DevDriverVer.empty()) { + if (!std::regex_match(DeviceDriverVer, std::regex(Desc.DevDriverVer))) { + DevVerState = MatchState::NOMATCH; + continue; + } else { + DevVerState = MatchState::MATCH; + } + } PiDevices[InsertIDx++] = Device; break; } } + if (DevNameState == MatchState::MATCH && DevVerState == MatchState::NOMATCH) { + throw sycl::runtime_error("Requested SYCL device not found", + PI_DEVICE_NOT_FOUND); + } + if (PlatNameState == MatchState::MATCH && + PlatVerState == MatchState::NOMATCH) { + throw sycl::runtime_error("Requested SYCL platform not found", + PI_DEVICE_NOT_FOUND); + } PiDevices.resize(InsertIDx); } diff --git a/sycl/test/config/select_device.cpp b/sycl/test/config/select_device.cpp new file mode 100644 index 0000000000000..d8b1ec97d5a8d --- /dev/null +++ b/sycl/test/config/select_device.cpp @@ -0,0 +1,878 @@ +// RUN: %clangxx -fsycl %s -o %t.out +// +// RUN: env WRITE_DEVICE_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_DEVICE_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_PLATFORM_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_PLATFORM_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_DEVICE_ERROR_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_DEVICE_ERROR_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_PLATFORM_ERROR_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_PLATFORM_ERROR_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_REG_EX_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_REG_EX_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_DEVICE_NAME_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_DEVICE_NAME_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_PLATFORM_NAME_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_PLATFORM_NAME_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_DEVICE_MULTI_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_DEVICE_MULTI_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_DEVICE_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_DEVICE_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_DRIVER_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_DRIVER_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_PLATFORM_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_PLATFORM_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// RUN: env WRITE_PLATVER_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// RUN: env READ_PLATVER_MALFORMED_INFO=1 %GPU_RUN_PLACEHOLDER %t.out +// +// REQUIRES: gpu +// +// XFAIL: cuda +// +// TODO: Update this test when SYCL_DEVICE_FILTER support in enabled. + +//==------------ select_device.cpp - SYCL_DEVICE_ALLOWLIST test ------------==// +// +// This test is unusual because it occurs in two phases. The first phase +// will find the GPU platforms, and write them to a file. The second phase +// will read the file, set SYCL_DEVICE_ALLOWLIST, and then find the correct +// platform. SYCL_DEVICE_ALLOWLIST is only evaluated once, the first time +// get_platforms() is called. Setting it later in the application has no +// effect. +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +using namespace cl::sycl; + +#ifdef _WIN32 +#define setenv(name, value, overwrite) _putenv_s(name, value) +#endif + +struct DevDescT { + std::string devName; + std::string devDriverVer; + std::string platName; + std::string platVer; +}; + +static void replaceSpecialCharacters(std::string &str) { + std::string lparen("("); + std::string rparen(")"); + std::string esclparen("\\("); + std::string escrparen("\\)"); + std::string period("."); + std::string escperiod("\\."); + + size_t pos = 0; + while ((pos = str.find(lparen, pos)) != std::string::npos) { + str.replace(pos, lparen.size(), esclparen); + pos += esclparen.size(); + } + pos = 0; + while ((pos = str.find(rparen, pos)) != std::string::npos) { + str.replace(pos, rparen.size(), escrparen); + pos += escrparen.size(); + } + pos = 0; + while ((pos = str.find(period, pos)) != std::string::npos) { + str.replace(pos, period.size(), escperiod); + pos += escperiod.size(); + } +} + +static std::vector getAllowListDesc(std::string allowList) { + if (allowList.empty()) + return {}; + + std::string deviceName("DeviceName:"); + std::string driverVersion("DriverVersion:"); + std::string platformName("PlatformName:"); + std::string platformVersion("PlatformVersion:"); + std::vector decDescs; + decDescs.emplace_back(); + + size_t pos = 0; + while (pos < allowList.size()) { + if ((allowList.compare(pos, deviceName.size(), deviceName)) == 0) { + if ((pos = allowList.find("{{", pos)) == std::string::npos) { + throw std::runtime_error("Malformed device allowlist"); + } + size_t start = pos + 2; + if ((pos = allowList.find("}}", pos)) == std::string::npos) { + throw std::runtime_error("Malformed device allowlist"); + } + decDescs.back().devName = allowList.substr(start, pos - start); + pos = pos + 2; + + if (allowList[pos] == ',') { + pos++; + } + } + + else if ((allowList.compare(pos, driverVersion.size(), driverVersion)) == + 0) { + if ((pos = allowList.find("{{", pos)) == std::string::npos) { + throw std::runtime_error("Malformed device allowlist"); + } + size_t start = pos + 2; + if ((pos = allowList.find("}}", pos)) == std::string::npos) { + throw std::runtime_error("Malformed device allowlist"); + } + decDescs.back().devDriverVer = allowList.substr(start, pos - start); + pos = pos + 3; + } + + else if ((allowList.compare(pos, platformName.size(), platformName)) == 0) { + if ((pos = allowList.find("{{", pos)) == std::string::npos) { + throw std::runtime_error("Malformed platform allowlist"); + } + size_t start = pos + 2; + if ((pos = allowList.find("}}", pos)) == std::string::npos) { + throw std::runtime_error("Malformed platform allowlist"); + } + decDescs.back().platName = allowList.substr(start, pos - start); + pos = pos + 2; + if (allowList[pos] == ',') { + pos++; + } + } + + else if ((allowList.compare(pos, platformVersion.size(), + platformVersion)) == 0) { + if ((pos = allowList.find("{{", pos)) == std::string::npos) { + throw std::runtime_error("Malformed platform allowlist"); + } + size_t start = pos + 2; + if ((pos = allowList.find("}}", pos)) == std::string::npos) { + throw std::runtime_error("Malformed platform allowlist"); + } + decDescs.back().platVer = allowList.substr(start, pos - start); + pos = pos + 2; + } + + else if (allowList.find('|', pos) != std::string::npos) { + pos = allowList.find('|') + 1; + while (allowList[pos] == ' ') { + pos++; + } + decDescs.emplace_back(); + } else { + throw std::runtime_error("Malformed platform allowlist"); + } + } // while (pos <= allowList.size()) + return decDescs; +} + +int main() { + bool passed = false; + std::string sycl_be("PI_OPENCL"); + if (getenv("SYCL_BE")) { + sycl_be = getenv("SYCL_BE"); + } + + // Test the GPU devices name and version number. + if (getenv("WRITE_DEVICE_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (!plt.has(aspect::host)) { + for (const auto &dev : plt.get_devices()) { + if (dev.has(aspect::gpu)) { + std::string name = dev.get_info(); + replaceSpecialCharacters(name); + std::string ver = dev.get_info(); + if ((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) { + fs << "DeviceName:{{" << name << "}},DriverVersion:{{" << ver + << "}}" << std::endl; + passed = true; + break; + } else if ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos)) { + fs << "DeviceName:{{" << name << "}},DriverVersion:{{" << ver + << "}}" << std::endl; + passed = true; + break; + } + } + } + } + } + fs.close(); + } + } else if (getenv("READ_DEVICE_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + for (const DevDescT &desc : components) { + if ((std::regex_match(dev.get_info(), + std::regex(desc.devName))) && + (std::regex_match(dev.get_info(), + std::regex(desc.devDriverVer)))) { + passed = true; + } + std::cout << "Device: " << dev.get_info() + << std::endl; + std::cout << "DriverVersion: " + << dev.get_info() + << std::endl; + } + } + fs.close(); + } + } + + // Test the platform name and version number. + if (getenv("WRITE_PLATFORM_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (plt.has(aspect::gpu)) { + std::string name = plt.get_info(); + replaceSpecialCharacters(name); + std::string ver = plt.get_info(); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "PlatformName:{{" << name << "}},PlatformVersion:{{" << ver + << "}}" << std::endl; + passed = true; + break; + } + } + } + fs.close(); + } + } else if (getenv("READ_PLATFORM_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt", std::fstream::in); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + for (const DevDescT &desc : components) { + if ((std::regex_match(plt.get_info(), + std::regex(desc.platName))) && + (std::regex_match(plt.get_info(), + std::regex(desc.platVer)))) { + passed = true; + } + } + std::cout << "Platform: " << plt.get_info() + << std::endl; + std::cout << "Platform Version: " + << plt.get_info() << std::endl; + } + fs.close(); + } + } + + // Test error handling. + if (getenv("WRITE_DEVICE_ERROR_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (!plt.has(aspect::host)) { + for (const auto &dev : plt.get_devices()) { + if (dev.has(aspect::gpu)) { + std::string name = dev.get_info(); + replaceSpecialCharacters(name); + std::string ver("98.76.54321"); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "DeviceName:{{" << name << "}},DriverVersion:{{" << ver + << "}}" << std::endl; + passed = true; + break; + } + } + } + } + } + fs.close(); + } + } else if (getenv("READ_DEVICE_ERROR_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + try { + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + } catch (sycl::runtime_error &E) { + const std::string expectedMsg("Requested SYCL device not found"); + const std::string gotMessage(E.what()); + if (gotMessage.find(expectedMsg) != std::string::npos) { + passed = true; + } else { + passed = false; + } + } + } + fs.close(); + } + } + + // Test error condition when version number is not found. + if (getenv("WRITE_PLATFORM_ERROR_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (plt.has(aspect::gpu)) { + std::string name = plt.get_info(); + replaceSpecialCharacters(name); + if ((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) { + std::string ver("OpenCL 12.34"); + fs << "PlatformName:{{" << name << "}},PlatformVersion:{{" << ver + << "}}" << std::endl; + passed = true; + break; + } else if ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos)) { + std::string ver("12.34"); + fs << "PlatformName:{{" << name << "}},PlatformVersion:{{" << ver + << "}}" << std::endl; + passed = true; + break; + } + } + } + } + fs.close(); + } else if (getenv("READ_PLATFORM_ERROR_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt", std::fstream::in); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + try { + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + } catch (sycl::runtime_error &E) { + const std::string expectedMsg("Requested SYCL platform not found"); + const std::string gotMessage(E.what()); + if (gotMessage.find(expectedMsg) != std::string::npos) { + passed = true; + } else { + passed = false; + } + } + } + fs.close(); + } + } + + // Test handling a regular expression in the device driver version number. + if (getenv("WRITE_REG_EX_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (!plt.has(aspect::host)) { + for (const auto &dev : plt.get_devices()) { + if (dev.has(aspect::gpu)) { + std::string name = dev.get_info(); + replaceSpecialCharacters(name); + std::string ver = dev.get_info(); + size_t pos = 0; + if ((pos = ver.find(".")) == std::string::npos) { + throw std::runtime_error("Malformed syntax in version string"); + } + pos++; + size_t start = pos; + if ((pos = ver.find(".", pos)) == std::string::npos) { + throw std::runtime_error("Malformed syntax in version string"); + } + ver.replace(start, pos - start, "*"); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "DeviceName:{{" << name << "}},DriverVersion:{{" << ver + << "}}" << std::endl; + passed = true; + break; + } + } + } + } + } + fs.close(); + } + } else if (getenv("READ_REG_EX_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + for (const DevDescT &desc : components) { + if ((std::regex_match(dev.get_info(), + std::regex(desc.devName))) && + (std::regex_match(dev.get_info(), + std::regex(desc.devDriverVer)))) { + passed = true; + } + std::cout << "Device: " << dev.get_info() + << std::endl; + std::cout << "DriverVersion: " + << dev.get_info() + << std::endl; + } + } + fs.close(); + } + } + + // Test providing only the device name. + if (getenv("WRITE_DEVICE_NAME_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (!plt.has(aspect::host)) { + for (const auto &dev : plt.get_devices()) { + if (dev.has(aspect::gpu)) { + std::string name = dev.get_info(); + replaceSpecialCharacters(name); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "DeviceName:{{" << name << "}}" << std::endl; + passed = true; + break; + } + } + } + } + } + fs.close(); + } + } else if (getenv("READ_DEVICE_NAME_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + for (const DevDescT &desc : components) { + if (std::regex_match(dev.get_info(), + std::regex(desc.devName))) { + passed = true; + } + std::cout << "Device: " << dev.get_info() + << std::endl; + } + } + fs.close(); + } + } + + // Test providing the platform name only. + if (getenv("WRITE_PLATFORM_NAME_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (plt.has(aspect::gpu)) { + std::string name = plt.get_info(); + replaceSpecialCharacters(name); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "PlatformName:{{" << name << "}}" << std::endl; + passed = true; + break; + } + } + } + } + fs.close(); + } else if (getenv("READ_PLATFORM_NAME_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt", std::fstream::in); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + for (const DevDescT &desc : components) { + if (std::regex_match(plt.get_info(), + std::regex(desc.platName))) { + passed = true; + } + std::cout << "Platform: " << plt.get_info() + << std::endl; + } + } + fs.close(); + } + } + + // Test the GPU multiple devices option. + if (getenv("WRITE_DEVICE_MULTI_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::stringstream ss; + int count = 0; + for (const auto &plt : platform::get_platforms()) { + if (!plt.has(aspect::host)) { + for (const auto &dev : plt.get_devices()) { + if (dev.has(aspect::gpu)) { + std::string name = dev.get_info(); + replaceSpecialCharacters(name); + std::string ver = dev.get_info(); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + if (count > 0) { + ss << " | "; + } + ss << "DeviceName:{{" << name << "}},DriverVersion:{{" << ver + << "}}"; + count++; + passed = true; + break; + } + } + } + } + } + fs << ss.str() << std::endl; + fs.close(); + } + } else if (getenv("READ_DEVICE_MULTI_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + for (const DevDescT &desc : components) { + if ((std::regex_match(dev.get_info(), + std::regex(desc.devName))) && + (std::regex_match(dev.get_info(), + std::regex(desc.devDriverVer)))) { + passed = true; + std::cout << "Device: " << dev.get_info() + << std::endl; + std::cout << "DriverVersion: " + << dev.get_info() + << std::endl; + } + } + } + fs.close(); + } + } + + // Test providing malformed syntax in the device name. + if (getenv("WRITE_DEVICE_MALFORMED_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (!plt.has(aspect::host)) { + for (const auto &dev : plt.get_devices()) { + if (dev.has(aspect::gpu)) { + std::string name = dev.get_info(); + replaceSpecialCharacters(name); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "DeviceName:HAHA{{" << name << "}}" << std::endl; + passed = true; + break; + } + } + } + } + } + fs.close(); + } + } else if (getenv("READ_DEVICE_MALFORMED_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + try { + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + } catch (sycl::runtime_error &E) { + const std::string expectedMsg( + "Malformed syntax in SYCL_DEVICE_ALLOWLIST"); + const std::string gotMessage(E.what()); + if (gotMessage.find(expectedMsg) != std::string::npos) { + passed = true; + } else { + passed = false; + } + } + } + fs.close(); + } + } + + // Test providing the platform name only. + if (getenv("WRITE_PLATFORM_MALFORMED_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (plt.has(aspect::gpu)) { + std::string name = plt.get_info(); + replaceSpecialCharacters(name); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "PlatformName:HAHA{{" << name << "}}" << std::endl; + passed = true; + break; + } + } + } + } + fs.close(); + } else if (getenv("READ_PLATFORM_MALFORMED_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt", std::fstream::in); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + try { + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + } catch (sycl::runtime_error &E) { + const std::string expectedMsg( + "Malformed syntax in SYCL_DEVICE_ALLOWLIST"); + const std::string gotMessage(E.what()); + if (gotMessage.find(expectedMsg) != std::string::npos) { + passed = true; + } else { + passed = false; + } + } + } + fs.close(); + } + } + + // Test a malformed device version number. + if (getenv("WRITE_DRIVER_MALFORMED_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (!plt.has(aspect::host)) { + for (const auto &dev : plt.get_devices()) { + if (dev.has(aspect::gpu)) { + std::string name = dev.get_info(); + replaceSpecialCharacters(name); + std::string ver = dev.get_info(); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "DeviceName:{{" << name << "}},DriverVersion:HAHA{{" + << ver << "}}" << std::endl; + passed = true; + break; + } + } + } + } + } + fs.close(); + } + } else if (getenv("READ_DRIVER_MALFORMED_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + try { + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + } catch (sycl::runtime_error &E) { + const std::string expectedMsg( + "Malformed syntax in SYCL_DEVICE_ALLOWLIST"); + const std::string gotMessage(E.what()); + if (gotMessage.find(expectedMsg) != std::string::npos) { + passed = true; + } else { + passed = false; + } + } + } + fs.close(); + } + } + + // Test the platform name and version number. + if (getenv("WRITE_PLATVER_MALFORMED_INFO")) { + std::ofstream fs; + fs.open("select_device_config.txt"); + if (fs.is_open()) { + for (const auto &plt : platform::get_platforms()) { + if (plt.has(aspect::gpu)) { + std::string name = plt.get_info(); + replaceSpecialCharacters(name); + std::string ver = plt.get_info(); + if (((plt.get_backend() == backend::opencl) && + (sycl_be.find("OPENCL") != std::string::npos)) || + ((plt.get_backend() == backend::level_zero) && + (sycl_be.find("LEVEL_ZERO") != std::string::npos))) { + fs << "PlatformName:{{" << name << "}},PlatformVersion:HAHA{{" + << ver << "}}" << std::endl; + passed = true; + break; + } + } + } + } + fs.close(); + } else if (getenv("READ_PLATVER_MALFORMED_INFO")) { + std::ifstream fs; + fs.open("select_device_config.txt", std::fstream::in); + if (fs.is_open()) { + std::string allowlist; + std::getline(fs, allowlist); + if (!allowlist.empty()) { + setenv("SYCL_DEVICE_ALLOWLIST", allowlist.c_str(), 0); + std::vector components(getAllowListDesc(allowlist)); + std::cout << "SYCL_DEVICE_ALLOWLIST=" << allowlist << std::endl; + + try { + cl::sycl::queue deviceQueue(gpu_selector{}); + device dev = deviceQueue.get_device(); + const auto &plt = dev.get_platform(); + } catch (sycl::runtime_error &E) { + const std::string expectedMsg( + "Malformed syntax in SYCL_DEVICE_ALLOWLIST"); + const std::string gotMessage(E.what()); + if (gotMessage.find(expectedMsg) != std::string::npos) { + passed = true; + } else { + passed = false; + } + } + } + fs.close(); + } + } + + if (passed) { + std::cout << "Passed." << std::endl; + return 0; + } else { + std::cout << "Failed." << std::endl; + return 1; + } +}