SWDEV-467848-[catch2][dtest] Functional tests for HIP_VISIBLE_DEVICES compatibility with UUIDs
Change-Id: I45eccecee2fd9fdb157be46fad2a37e675acd19c
[ROCm/hip-tests commit: 7348d05b1d]
This commit is contained in:
committed by
Srinivasarao Gollamandala
parent
9592dfe6f1
commit
90cfd75650
@@ -1115,6 +1115,10 @@
|
||||
"=== SWDEV-475482 : Disable tests to merge clr change 08/02/24 ===",
|
||||
"Unit_hipCreateTextureObject_LinearResource",
|
||||
"Unit_hipCreateTextureObject_Pitch2DResource",
|
||||
"=== Following tests disabled due to SWDEV-483110",
|
||||
"Unit_UUID_setEnv_Thread",
|
||||
"Unit_UUID_setEnv_Thread_Lock",
|
||||
"====================================================",
|
||||
#endif
|
||||
#if defined gfx1200 || defined gfx1201
|
||||
"=== SWDEV-470751 : Fine Grain memory is MTYPE_NC due to HW bug.",
|
||||
|
||||
@@ -50,9 +50,27 @@ set_source_files_properties(hipDeviceGetUuid.cc PROPERTIES COMPILE_FLAGS -std=c+
|
||||
add_executable(getDeviceCount EXCLUDE_FROM_ALL getDeviceCount_exe.cc)
|
||||
set_property(GLOBAL APPEND PROPERTY G_INSTALL_EXE_TARGETS getDeviceCount)
|
||||
|
||||
add_executable(chkUUIDFrmChildProc_Exe EXCLUDE_FROM_ALL chkUUIDFrmChildProc_Exe.cc)
|
||||
add_executable(chkUUIDInGrandChild_Exe EXCLUDE_FROM_ALL chkUUIDInGrandChild_Exe.cc)
|
||||
add_executable(setuuidGetDevCount EXCLUDE_FROM_ALL setuuidGetDevCount_Exe.cc)
|
||||
if(UNIX)
|
||||
add_executable(getUUIDfrmRocinfo EXCLUDE_FROM_ALL getUUIDfrmRocinfo_Exe.cc)
|
||||
add_dependencies(build_tests getUUIDfrmRocinfo)
|
||||
endif()
|
||||
add_executable(multipleUUID EXCLUDE_FROM_ALL multipleUUID_Exe.cc)
|
||||
add_executable(setEnvInChildProc EXCLUDE_FROM_ALL setEnvInChildProc_Exe.cc)
|
||||
add_executable(uuidList EXCLUDE_FROM_ALL uuidList.cc)
|
||||
#Disabled below two executable due to the defect ticket SWDEV-467665
|
||||
if(0)
|
||||
add_executable(passUUIDToGrandChild_Exe EXCLUDE_FROM_ALL passUUIDToGrandChild_Exe.cc)
|
||||
add_executable(ResetUUIDInChild_Exe EXCLUDE_FROM_ALL ResetUUIDInChild_Exe.cc)
|
||||
endif()
|
||||
hip_add_exe_to_target(NAME DeviceTest
|
||||
TEST_SRC ${TEST_SRC}
|
||||
TEST_TARGET_NAME build_tests
|
||||
COMPILE_OPTIONS -std=c++17)
|
||||
|
||||
add_dependencies(build_tests getDeviceCount)
|
||||
add_dependencies(build_tests getDeviceCount chkUUIDFrmChildProc_Exe chkUUIDInGrandChild_Exe setuuidGetDevCount multipleUUID setEnvInChildProc uuidList)
|
||||
#Disabled below two executable due to the defect ticket SWDEV-467665
|
||||
if(0)
|
||||
add_dependencies(build_tests passUUIDToGrandChild_Exe ResetUUIDInChild_Exe)
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip_test_process.hh>
|
||||
|
||||
#ifdef _WIN64
|
||||
#define setenv(x, y, z) _putenv_s(x, y)
|
||||
#endif
|
||||
|
||||
int main() {
|
||||
int testPassed = 0;
|
||||
setenv("HIP_VISIBLE_DEVICES", "", 1);
|
||||
hip::SpawnProc proc("setuuidGetDevCount", true);
|
||||
if (proc.run() == 0) {
|
||||
testPassed = 1;
|
||||
} else {
|
||||
testPassed = 0;
|
||||
}
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
return testPassed;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 0) {
|
||||
return -1;
|
||||
}
|
||||
int testPassed = 0;
|
||||
hipDevice_t device;
|
||||
hipError_t localError;
|
||||
localError = hipSetDevice(0);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
localError = hipDeviceGet(&device, 0);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
hipUUID d_uuid{0};
|
||||
localError = hipDeviceGetUuid(&d_uuid, device);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
if (memcmp(d_uuid.bytes, argv[1], 16) == 0) {
|
||||
testPassed = 1;
|
||||
} else {
|
||||
testPassed = 0;
|
||||
}
|
||||
return testPassed;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 0) {
|
||||
return -1;
|
||||
}
|
||||
int testPassed = 0;
|
||||
hipDevice_t device;
|
||||
std::string uuid = argv[1];
|
||||
hipError_t localError;
|
||||
localError = hipSetDevice(0);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
localError = hipDeviceGet(&device, 0);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
hipUUID d_uuid{0};
|
||||
localError = hipDeviceGetUuid(&d_uuid, device);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
if (memcmp(d_uuid.bytes, argv[1], 16) == 0) {
|
||||
testPassed = 1;
|
||||
} else {
|
||||
testPassed = 0;
|
||||
}
|
||||
return testPassed;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#ifdef __linux__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#define COMMAND_LEN 256
|
||||
#define BUFFER_LEN 512
|
||||
|
||||
#ifdef __linux__
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 0) {
|
||||
return -1;
|
||||
}
|
||||
int testPassed = 0;
|
||||
FILE* fpipe;
|
||||
char command[COMMAND_LEN] = "";
|
||||
const char* rocmInfo = "rocminfo";
|
||||
|
||||
snprintf(command, COMMAND_LEN, "%s", rocmInfo);
|
||||
strncat(command, " | grep -i Uuid:", COMMAND_LEN);
|
||||
// Execute the rocminfo command and extract the UUID info
|
||||
fpipe = popen(command, "r");
|
||||
if (fpipe == nullptr) {
|
||||
printf("Unable to create command file\n");
|
||||
return -1;
|
||||
}
|
||||
char command_op[BUFFER_LEN];
|
||||
int j = 0;
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
while (fgets(command_op, BUFFER_LEN, fpipe)) {
|
||||
std::string rocminfo_line(command_op);
|
||||
if (std::string::npos != rocminfo_line.find("CPU-")) {
|
||||
continue;
|
||||
} else if (auto loc = rocminfo_line.find("GPU-");
|
||||
loc != std::string::npos) {
|
||||
if (std::string::npos ==
|
||||
rocminfo_line.find("GPU-XX")) {
|
||||
std::vector<char> t_uuid(20, 0);
|
||||
std::memcpy(t_uuid.data(), &rocminfo_line[loc], 20);
|
||||
uuid_map[j] = t_uuid;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
std::string s = argv[1];
|
||||
std::string delimiter = ",";
|
||||
size_t pos = 0;
|
||||
std::vector<std::string>token;
|
||||
while ((pos = s.find(delimiter)) != std::string::npos) {
|
||||
token.push_back(s.substr(4, 16));
|
||||
s.erase(0, pos + delimiter.length());
|
||||
}
|
||||
token.push_back(s.substr(4, 16));
|
||||
int devCount = 0;
|
||||
hipError_t localError;
|
||||
localError = hipGetDeviceCount(&devCount);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
for (int i = 0; i < devCount; i++) {
|
||||
std::string uuid = token[i];
|
||||
std::string mapVal = uuid_map[i].data();
|
||||
if (memcmp(mapVal.substr(4, 16).c_str(), uuid.c_str(), 16) == 0) {
|
||||
testPassed += 1;
|
||||
}
|
||||
}
|
||||
if (testPassed == devCount) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Copyright (c) 2022-2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
@@ -18,15 +18,27 @@ THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <hip_test_common.hh>
|
||||
#include <hip_test_process.hh>
|
||||
#ifdef __linux__
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef _WIN64
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <thread> // NOLINT
|
||||
#include <mutex> //NOLINT
|
||||
|
||||
#ifdef _WIN64
|
||||
#define setenv(x, y, z) _putenv_s(x, y)
|
||||
#define unsetenv(x) _putenv(x)
|
||||
#endif
|
||||
#define COMMAND_LEN 256
|
||||
#define BUFFER_LEN 512
|
||||
/**
|
||||
* @addtogroup hipDeviceGetUuid hipDeviceGetUuid
|
||||
* @{
|
||||
@@ -99,9 +111,6 @@ TEST_CASE("Unit_hipDeviceGetUuid_Negative") {
|
||||
}
|
||||
#ifdef __linux__
|
||||
#if HT_AMD
|
||||
#define COMMAND_LEN 256
|
||||
#define BUFFER_LEN 512
|
||||
|
||||
/**
|
||||
* Test Description
|
||||
* ------------------------
|
||||
@@ -137,9 +146,10 @@ TEST_CASE("Unit_hipDeviceGetUuid_From_RocmInfo") {
|
||||
std::string rocminfo_line(command_op);
|
||||
if (std::string::npos != rocminfo_line.find("CPU-")) {
|
||||
continue;
|
||||
} else if (auto loc = rocminfo_line.find("GPU-"); loc != std::string::npos) {
|
||||
} else if (auto loc = rocminfo_line.find("GPU-");
|
||||
loc != std::string::npos) {
|
||||
if (std::string::npos ==
|
||||
rocminfo_line.find("GPU-XX")) { // Only make an entry if the device is not an iGPU
|
||||
rocminfo_line.find("GPU-XX")) { // Only make an entry if the device is not an iGPU // NOLINT
|
||||
std::vector<char> t_uuid(16, 0);
|
||||
std::memcpy(t_uuid.data(), &rocminfo_line[loc + 4], 16);
|
||||
uuid_map[j] = t_uuid;
|
||||
@@ -193,6 +203,356 @@ TEST_CASE("Unit_hipDeviceGetUuid_VerifyUuidFrm_hipGetDeviceProperties") {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HT_AMD
|
||||
#ifdef __linux__
|
||||
auto getUUIDlistFromRocmInfo() {
|
||||
FILE* fpipe;
|
||||
char command[COMMAND_LEN] = "";
|
||||
const char* rocmInfo = "rocminfo";
|
||||
|
||||
snprintf(command, COMMAND_LEN, "%s", rocmInfo);
|
||||
strncat(command, " | grep -i Uuid:", COMMAND_LEN);
|
||||
// Execute the rocminfo command and extract the UUID info
|
||||
fpipe = popen(command, "r");
|
||||
if (fpipe == nullptr) {
|
||||
printf("Unable to create command file\n");
|
||||
assert(false);
|
||||
}
|
||||
char command_op[BUFFER_LEN];
|
||||
int j = 0;
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
while (fgets(command_op, BUFFER_LEN, fpipe)) {
|
||||
std::string rocminfo_line(command_op);
|
||||
if (std::string::npos != rocminfo_line.find("CPU-")) {
|
||||
continue;
|
||||
} else if (auto loc = rocminfo_line.find("GPU-");
|
||||
loc != std::string::npos) {
|
||||
if (std::string::npos ==
|
||||
rocminfo_line.find("GPU-XX")) {
|
||||
std::vector<char> t_uuid(20, 0);
|
||||
std::memcpy(t_uuid.data(), &rocminfo_line[loc], 20);
|
||||
uuid_map[j] = t_uuid;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return uuid_map;
|
||||
}
|
||||
#endif
|
||||
|
||||
auto getUUIDlistWithoutRocmInfo() {
|
||||
hip::SpawnProc proc("uuidList", true);
|
||||
REQUIRE(proc.run() == 0);
|
||||
std::string strList = proc.getOutput();
|
||||
std::string delimiter = ",";
|
||||
size_t pos = 0;
|
||||
int first = 0;
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
while ((pos = strList.find(delimiter)) != std::string::npos) {
|
||||
std::vector<char> t_uuid(20, 0);
|
||||
std::memcpy(t_uuid.data(), &strList[0], 20);
|
||||
uuid_map[first] = t_uuid;
|
||||
first++;
|
||||
strList.erase(0, pos + delimiter.length());
|
||||
}
|
||||
std::vector<char> tmp_uuid(20, 0);
|
||||
std::memcpy(tmp_uuid.data(), &strList[0], 20);
|
||||
uuid_map[first] = tmp_uuid;
|
||||
return uuid_map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Description
|
||||
* ------------------------
|
||||
* - All the tests contains the various cases of setting the Env
|
||||
* - var HIP_VISIBLE_DEVICES in different process (parent/child)
|
||||
* - and verifies the Env functionality by checking UUID'S in
|
||||
* - different process.
|
||||
* Test source
|
||||
* ------------------------
|
||||
* - unit/device/hipDeviceGetUuid.cc
|
||||
* Test requirements
|
||||
* ------------------------
|
||||
* - HIP_VERSION >= 6.2
|
||||
*/
|
||||
TEST_CASE("Unit_Uuid_FntlTstsFor_SetEnv_HIP_VISIBLE_DEVICES") {
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
#ifdef __linux__
|
||||
uuid_map = getUUIDlistFromRocmInfo();
|
||||
#else
|
||||
uuid_map = getUUIDlistWithoutRocmInfo();
|
||||
#endif
|
||||
if (uuid_map.size() > 0) {
|
||||
SECTION("Set Env in parent and verify UUID in child ") {
|
||||
// Set Env Var with first GPU
|
||||
std::string uuid = uuid_map[0].data();
|
||||
std::string uuidEnv = uuid.substr(0, 20);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuidEnv.c_str(), 1);
|
||||
hip::SpawnProc proc("chkUUIDFrmChildProc_Exe", true);
|
||||
std::string t_uuid = uuidEnv.substr(4, 19);
|
||||
REQUIRE(proc.run(t_uuid) == 1);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
}
|
||||
#if 0 // Disabling below 2 tests due to the defect SWDEV-467665
|
||||
SECTION("Set Env in parent and verify UUID in Grand child") {
|
||||
std::string uuid = uuid_map[0].data();
|
||||
std::string uuidEnv = uuid.substr(0, 20);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuidEnv.c_str(), 1);
|
||||
hip::SpawnProc proc("passUUIDToGrandChild_Exe", true);
|
||||
REQUIRE(proc.run(uuidEnv)== 1);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
}
|
||||
|
||||
SECTION("Reset Env in child and verify UUID in Grand child") {
|
||||
if (uuid_map.size() >= 2) {
|
||||
std::string uuid = uuid_map[1].data();
|
||||
std::string uuidEnv = uuid.substr(0, 20);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuidEnv.c_str(), 1);
|
||||
hip::SpawnProc proc("ResetUUIDInChild_Exe", true);
|
||||
REQUIRE(proc.run()== 1);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
} else {
|
||||
HipTest::HIP_SKIP_TEST("Skipping because this machine has total GPUs < 2"); // NOLINT
|
||||
}
|
||||
}
|
||||
#endif
|
||||
SECTION("Get Dev Count from Child") {
|
||||
if (uuid_map.size() >= 2) {
|
||||
std::string uuid = uuid_map[0].data();
|
||||
std::string uuidEnv = uuid.substr(0, 20);
|
||||
std::string uuid1 = uuid_map[1].data();
|
||||
std::string uuidEnv1 = uuid1.substr(0, 20);
|
||||
std::string totalString = uuidEnv + "," + uuidEnv1;
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", totalString.c_str(), 1);
|
||||
hip::SpawnProc proc("setuuidGetDevCount", true);
|
||||
REQUIRE(proc.run() == 2);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
} else {
|
||||
HipTest::HIP_SKIP_TEST("Skipping because this machine has total GPUs < 2"); // NOLINT
|
||||
}
|
||||
}
|
||||
#ifdef __linux__
|
||||
SECTION("Get UUID from Child proc rocminfo") {
|
||||
std::string setUuid = uuid_map[0].data();
|
||||
std::string uuidEnv = setUuid.substr(0, 20);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuidEnv.c_str(), 1);
|
||||
std::string wholeString;
|
||||
std::string uuid;
|
||||
std::string finalUuid = "";
|
||||
for (auto it = uuid_map.cbegin(); it != uuid_map.cend(); ++it) {
|
||||
if (it->second.size() == 0) {
|
||||
continue;
|
||||
} else {
|
||||
wholeString = it->second.data();
|
||||
uuid = wholeString.substr(0, 20);
|
||||
if (it->first == uuid_map.size() - 1) {
|
||||
finalUuid = finalUuid + uuid;
|
||||
} else {
|
||||
finalUuid = finalUuid + uuid + ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
hip::SpawnProc proc("getUUIDfrmRocinfo", true);
|
||||
REQUIRE(proc.run(finalUuid) == 1);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
}
|
||||
#endif
|
||||
SECTION("Set multiple uuid") {
|
||||
std::string wholeString;
|
||||
std::string uuid;
|
||||
std::string finalUuid = "";
|
||||
for (auto it = uuid_map.cbegin(); it != uuid_map.cend(); ++it) {
|
||||
if (it->second.size() == 0) {
|
||||
continue;
|
||||
} else {
|
||||
wholeString = it->second.data();
|
||||
uuid = wholeString.substr(0, 20);
|
||||
if (it->first == uuid_map.size() - 1) {
|
||||
finalUuid = finalUuid + uuid;
|
||||
} else {
|
||||
finalUuid = finalUuid + uuid + ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", finalUuid.c_str(), 1);
|
||||
hip::SpawnProc proc("multipleUUID", true);
|
||||
REQUIRE(proc.run(finalUuid) == 1);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
}
|
||||
SECTION("Set mix Env variables") {
|
||||
if (uuid_map.size() >= 2) {
|
||||
std::string uuid = "0";
|
||||
std::string uuid1 = uuid_map[1].data();
|
||||
std::string uuidEnv1 = uuid1.substr(0, 20);
|
||||
std::string totalString = uuid + "," + uuidEnv1;
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", totalString.c_str(), 1);
|
||||
hip::SpawnProc proc("setuuidGetDevCount", true);
|
||||
REQUIRE(proc.run() == 2);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
} else {
|
||||
HipTest::HIP_SKIP_TEST("Skipping because this machine has total GPUs < 2"); // NOLINT
|
||||
}
|
||||
}
|
||||
SECTION("Set Same UUID/Device ordinal more than once ") {
|
||||
if (uuid_map.size() >= 2) {
|
||||
std::string uuid = "0";
|
||||
std::string uuid1 = uuid_map[0].data();
|
||||
std::string uuidEnv1 = uuid1.substr(0, 20);
|
||||
std::string uuid2 = uuid_map[1].data();
|
||||
std::string uuidEnv2 = uuid2.substr(0, 20);
|
||||
std::string totalString = uuid + "," + uuidEnv2 + ","
|
||||
+ uuidEnv1 + "," + uuid;
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", totalString.c_str(), 1);
|
||||
hip::SpawnProc proc("setuuidGetDevCount", true);
|
||||
REQUIRE(proc.run() == 2);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
} else {
|
||||
HipTest::HIP_SKIP_TEST("Skipping because this machine has total GPUs < 2"); // NOLINT
|
||||
}
|
||||
}
|
||||
SECTION("Set Env Variable in child process") {
|
||||
std::string uuid = uuid_map[0].data();
|
||||
std::string uuidEnv = uuid.substr(0, 20);
|
||||
hip::SpawnProc proc("setEnvInChildProc", true);
|
||||
REQUIRE(proc.run(uuidEnv) == 1);
|
||||
int devCount = 0;
|
||||
HIP_CHECK(hipGetDeviceCount(&devCount));
|
||||
REQUIRE(devCount == uuid_map.size());
|
||||
}
|
||||
#ifdef __linux__
|
||||
SECTION("Chk RocmInfo Uuid list before and after set Env") {
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
uuid_map = getUUIDlistFromRocmInfo();
|
||||
std::string uuid = uuid_map[0].data();
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuid.c_str(), 1);
|
||||
std::map<int, std::vector<char>> uuid_map1;
|
||||
uuid_map1 = getUUIDlistFromRocmInfo();
|
||||
REQUIRE(uuid_map.size() == uuid_map1.size());
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
HipTest::HIP_SKIP_TEST("Skipping because this machine has total GPUs < 1"); // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
void ChkUUID() {
|
||||
int devCount = 0;
|
||||
HIP_CHECK(hipGetDeviceCount(&devCount));
|
||||
REQUIRE(devCount == 1);
|
||||
hipDevice_t device;
|
||||
HIP_CHECK(hipSetDevice(0));
|
||||
HIP_CHECK(hipDeviceGet(&device, 0));
|
||||
hipUUID d_uuid{0};
|
||||
HIP_CHECK(hipDeviceGetUuid(&d_uuid, device));
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
#ifdef __linux__
|
||||
uuid_map = getUUIDlistFromRocmInfo();
|
||||
#else
|
||||
uuid_map = getUUIDlistWithoutRocmInfo();
|
||||
#endif
|
||||
std::string uuid = uuid_map[0].data();
|
||||
std::string t_uuid = uuid.substr(4, 19);
|
||||
if (memcmp(d_uuid.bytes, t_uuid.c_str(), 16) == 0) {
|
||||
REQUIRE(true);
|
||||
}
|
||||
}
|
||||
|
||||
void setEnv() {
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
#ifdef __linux__
|
||||
uuid_map = getUUIDlistFromRocmInfo();
|
||||
#else
|
||||
uuid_map = getUUIDlistWithoutRocmInfo();
|
||||
#endif
|
||||
if (uuid_map.size() >= 2) {
|
||||
std::string uuid = uuid_map[1].data();
|
||||
std::string uuidEnv = uuid.substr(0, 20);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuidEnv.c_str(), 1);
|
||||
} else {
|
||||
HipTest::HIP_SKIP_TEST("Skipping because this machine has total GPUs < 2"); // NOLINT
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex setLock;
|
||||
void setEnvLock() {
|
||||
setLock.lock();
|
||||
std::map<int, std::vector<char>> uuid_map;
|
||||
#ifdef __linux__
|
||||
uuid_map = getUUIDlistFromRocmInfo();
|
||||
#else
|
||||
uuid_map = getUUIDlistWithoutRocmInfo();
|
||||
#endif
|
||||
if (uuid_map.size() >= 2) {
|
||||
std::string uuid = uuid_map[1].data();
|
||||
std::string uuidEnv = uuid.substr(0, 20);
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuidEnv.c_str(), 1);
|
||||
} else {
|
||||
HipTest::HIP_SKIP_TEST("Skipping because this machine has total GPUs < 2"); // NOLINT
|
||||
}
|
||||
setLock.unlock();
|
||||
}
|
||||
/**
|
||||
* Test Description
|
||||
* ------------------------
|
||||
* - Multi thread scenario.
|
||||
* - Set Env var HIP_VISIBLE_DEVICES in one thread
|
||||
* - Verify the followed by functionality in another thread
|
||||
* Test source
|
||||
* ------------------------
|
||||
* - unit/device/hipDeviceGetUuid.cc
|
||||
* Test requirements
|
||||
* ------------------------
|
||||
* - HIP_VERSION >= 6.2
|
||||
*/
|
||||
|
||||
TEST_CASE("Unit_UUID_setEnv_Thread") {
|
||||
// Create Thread one
|
||||
std::thread t1(setEnv);
|
||||
t1.join();
|
||||
// Create Thread two
|
||||
std::thread t2(ChkUUID);
|
||||
t2.join();
|
||||
}
|
||||
/**
|
||||
* Test Description
|
||||
* ------------------------
|
||||
* - Multi thread scenario.
|
||||
* - Set Env var HIP_VISIBLE_DEVICES in one thread
|
||||
* - Meanwhile hold the second thread. Release the 2nd thread.
|
||||
* - Verify the followed by functionality in another thread
|
||||
* Test source
|
||||
* ------------------------
|
||||
* - unit/device/hipDeviceGetUuid.cc
|
||||
* Test requirements
|
||||
* ------------------------
|
||||
* - HIP_VERSION >= 6.2
|
||||
*/
|
||||
|
||||
TEST_CASE("Unit_UUID_setEnv_Thread_Lock") {
|
||||
// Create Thread one
|
||||
std::thread t1(setEnvLock);
|
||||
#ifdef __linux__
|
||||
sleep(2);
|
||||
#else
|
||||
_sleep(2);
|
||||
#endif
|
||||
// Create Thread two
|
||||
std::thread t2(ChkUUID);
|
||||
t2.join();
|
||||
t1.join();
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* End doxygen group DriverTest.
|
||||
* @}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 0) {
|
||||
return -1;
|
||||
}
|
||||
int testPassed = 0;
|
||||
std::string s = argv[1];
|
||||
std::string delimiter = ",";
|
||||
|
||||
size_t pos = 0;
|
||||
std::vector<std::string>token;
|
||||
while ((pos = s.find(delimiter)) != std::string::npos) {
|
||||
token.push_back(s.substr(4, 16));
|
||||
s.erase(0, pos + delimiter.length());
|
||||
}
|
||||
token.push_back(s.substr(4, 16));
|
||||
int devCount = 0;
|
||||
hipError_t localError;
|
||||
localError = hipGetDeviceCount(&devCount);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
hipDevice_t device;
|
||||
for (int i = 0; i < devCount; i++) {
|
||||
localError = hipSetDevice(i);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
localError = hipDeviceGet(&device, i);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
hipUUID d_uuid{0};
|
||||
localError = hipDeviceGetUuid(&d_uuid, device);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
std::string uuid = token[i];
|
||||
if (memcmp(d_uuid.bytes, uuid.c_str(), 16) == 0) {
|
||||
testPassed += 1;
|
||||
}
|
||||
}
|
||||
if (testPassed == devCount) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return testPassed;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip_test_process.hh>
|
||||
#include <cstring>
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 0) {
|
||||
return -1;
|
||||
}
|
||||
int testPassed = 0;
|
||||
std::string uuid = argv[1];
|
||||
hip::SpawnProc proc("chkUUIDInGrandChild_Exe", true);
|
||||
std::string t_uuid = uuid.substr(4, 19);
|
||||
if (proc.run(t_uuid) == 1) {
|
||||
testPassed = 1;
|
||||
} else {
|
||||
testPassed = 0;
|
||||
}
|
||||
return testPassed;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include <cstring>
|
||||
#ifdef _WIN64
|
||||
#define setenv(x, y, z) _putenv_s(x, y)
|
||||
#define unsetenv(x) _putenv(x)
|
||||
#endif
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 0) {
|
||||
return -1;
|
||||
}
|
||||
std::string uuid = argv[1];
|
||||
unsetenv("HIP_VISIBLE_DEVICES");
|
||||
setenv("HIP_VISIBLE_DEVICES", uuid.c_str(), 1);
|
||||
int devCount = 0;
|
||||
hipError_t localError;
|
||||
localError = hipGetDeviceCount(&devCount);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
return devCount;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
int main() {
|
||||
int devCount = 0;
|
||||
hipError_t localError;
|
||||
localError = hipGetDeviceCount(&devCount);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
return devCount;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright (c) 2024 Advanced Micro Devices, Inc. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANNTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INNCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANNY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER INN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR INN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
#include <hip/hip_runtime.h>
|
||||
#include<iostream>
|
||||
#include<string>
|
||||
int main() {
|
||||
hipDevice_t device;
|
||||
int devCount;
|
||||
hipError_t localError;
|
||||
localError = hipGetDeviceCount(&devCount);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
std::string uuid;
|
||||
for (int i = 0; i < devCount; i++) {
|
||||
localError = hipSetDevice(i);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
localError = hipDeviceGet(&device, i);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
hipUUID d_uuid{0};
|
||||
localError = hipDeviceGetUuid(&d_uuid, device);
|
||||
if (localError == hipSuccess) {
|
||||
printf("HIP Api returned hipSuccess");
|
||||
}
|
||||
char preStr[16] = "GPU-";
|
||||
strcat(preStr, d_uuid.bytes);
|
||||
if (i == devCount - 1) {
|
||||
uuid = uuid + preStr;
|
||||
} else {
|
||||
uuid = uuid + preStr + ",";
|
||||
}
|
||||
}
|
||||
std::cout<< uuid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user