-
Notifications
You must be signed in to change notification settings - Fork 68
(sysman): Enabled multi process power get/set test #264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -6,13 +6,22 @@ | |||||||||||
* | ||||||||||||
*/ | ||||||||||||
|
||||||||||||
#include <boost/process.hpp> | ||||||||||||
#include <boost/filesystem.hpp> | ||||||||||||
#include <boost/interprocess/shared_memory_object.hpp> | ||||||||||||
#include <boost/interprocess/mapped_region.hpp> | ||||||||||||
|
||||||||||||
#include "gtest/gtest.h" | ||||||||||||
#include <thread> | ||||||||||||
#include "logging/logging.hpp" | ||||||||||||
#include "utils/utils.hpp" | ||||||||||||
#include "test_harness/test_harness.hpp" | ||||||||||||
#include <chrono> | ||||||||||||
|
||||||||||||
namespace lzt = level_zero_tests; | ||||||||||||
namespace bp = boost::process; | ||||||||||||
namespace fs = boost::filesystem; | ||||||||||||
namespace bi = boost::interprocess; | ||||||||||||
|
||||||||||||
#include <level_zero/zes_api.h> | ||||||||||||
|
||||||||||||
|
@@ -183,6 +192,130 @@ LZT_TEST_F( | |||||||||||
} | ||||||||||||
} | ||||||||||||
} | ||||||||||||
struct powerInfo { | ||||||||||||
uint32_t interval; | ||||||||||||
uint32_t limit; | ||||||||||||
bool limitValueLocked; | ||||||||||||
}; | ||||||||||||
struct powerDomains { | ||||||||||||
zes_uuid_t uuid; | ||||||||||||
std::vector<powerInfo> power_info_list; | ||||||||||||
}; | ||||||||||||
LZT_TEST_F( | ||||||||||||
POWER_TEST, | ||||||||||||
MultiProcessTestSetValidPowerLimitInParentProcessAndReadInChildProcess) { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please follow a Given..When..Then.. way of naming a test case? |
||||||||||||
// run test for all available devices | ||||||||||||
std::vector<powerDomains> pd(devices.size()); | ||||||||||||
for (size_t d = 0; d < devices.size(); ++d) { | ||||||||||||
uint32_t count = 0; | ||||||||||||
auto p_power_handles = lzt::get_power_handles(devices[d], count); | ||||||||||||
if (count == 0) { | ||||||||||||
FAIL() << "No handles found: " | ||||||||||||
<< _ze_result_t(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); | ||||||||||||
} | ||||||||||||
|
||||||||||||
// loop through all power domains and set the power limit | ||||||||||||
|
||||||||||||
//step 1: i) Preserve initial power limit descriptors for restoration later | ||||||||||||
// ii) Set the power limit and verify the setting | ||||||||||||
std::vector<std::vector<zes_power_limit_ext_desc_t>> power_limits_descriptors_initial(p_power_handles.size()); | ||||||||||||
for (size_t p = 0; p < p_power_handles.size(); ++p) { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless you're modifying the elements of the vector |
||||||||||||
EXPECT_NE(nullptr, p_power_handles[p]); | ||||||||||||
|
||||||||||||
uint32_t count_power = 0; | ||||||||||||
std::vector<zes_power_limit_ext_desc_t> power_limits_descriptors; | ||||||||||||
auto status = lzt::get_power_limits_ext( | ||||||||||||
p_power_handles[p], &count_power, | ||||||||||||
power_limits_descriptors); | ||||||||||||
if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { | ||||||||||||
continue; | ||||||||||||
} | ||||||||||||
EXPECT_ZE_RESULT_SUCCESS(status); | ||||||||||||
// set power limit | ||||||||||||
zes_power_limit_ext_desc_t power_peak_set = {}; | ||||||||||||
for (auto &power_limits_descriptor : power_limits_descriptors) { | ||||||||||||
power_limits_descriptors_initial[p].push_back(power_limits_descriptor); | ||||||||||||
if (power_limits_descriptor.level == ZES_POWER_LEVEL_PEAK) { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason you're implementing this test only for PEAK power limit? |
||||||||||||
power_peak_set = power_limits_descriptor; | ||||||||||||
power_peak_set.limit = power_limits_descriptor.limit - 1000; | ||||||||||||
power_limits_descriptor.limit = power_peak_set.limit; | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
if (power_peak_set.limitValueLocked == false) { | ||||||||||||
// store power info into the list for sharing it with child process | ||||||||||||
powerInfo p_info; | ||||||||||||
p_info.limit = power_peak_set.limit; | ||||||||||||
p_info.interval = power_peak_set.interval; | ||||||||||||
p_info.limitValueLocked = power_peak_set.limitValueLocked; | ||||||||||||
pd[d].power_info_list.push_back(p_info); | ||||||||||||
|
||||||||||||
status = lzt::set_power_limits_ext(p_power_handles[p], &count_power, | ||||||||||||
power_limits_descriptors.data()); | ||||||||||||
if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { | ||||||||||||
continue; | ||||||||||||
} | ||||||||||||
EXPECT_ZE_RESULT_SUCCESS(status); | ||||||||||||
|
||||||||||||
// Read power limits to confirm power limit is set | ||||||||||||
zes_power_limit_ext_desc_t power_peak_get = {}; | ||||||||||||
std::vector<zes_power_limit_ext_desc_t> power_limits_descriptors_get; | ||||||||||||
status = lzt::get_power_limits_ext(p_power_handles[p], &count_power, | ||||||||||||
power_limits_descriptors_get); | ||||||||||||
if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { | ||||||||||||
continue; | ||||||||||||
} | ||||||||||||
EXPECT_ZE_RESULT_SUCCESS(status); | ||||||||||||
for (const auto &p_power_limits_descriptor_get : | ||||||||||||
power_limits_descriptors_get) { | ||||||||||||
if (p_power_limits_descriptor_get.level == ZES_POWER_LEVEL_PEAK) { | ||||||||||||
power_peak_get = p_power_limits_descriptor_get; | ||||||||||||
} | ||||||||||||
} | ||||||||||||
EXPECT_EQ(power_peak_get.limitValueLocked, power_peak_set.limitValueLocked); | ||||||||||||
EXPECT_EQ(power_peak_get.interval, power_peak_set.interval); | ||||||||||||
EXPECT_EQ(power_peak_get.limit, power_peak_set.limit); | ||||||||||||
} | ||||||||||||
} | ||||||||||||
|
||||||||||||
// step 2: Launch child process and share power limits set | ||||||||||||
// create named shared object and copy all power settings | ||||||||||||
zes_uuid_t uuid = lzt::get_sysman_device_uuid(devices[d]); | ||||||||||||
|
||||||||||||
bi::shared_memory_object::remove("MultiProcPowerLimitSharedMemory"); | ||||||||||||
bi::shared_memory_object power_limit_shm(bi::create_only, "MultiProcPowerLimitSharedMemory", bi::read_write); | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The shared memory object name 'MultiProcPowerLimitSharedMemory' is hardcoded in multiple places. Consider defining it as a constant to improve maintainability.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||
power_limit_shm.truncate(ZES_MAX_UUID_SIZE+pd[d].power_info_list.size()*sizeof(powerInfo)); | ||||||||||||
bi::mapped_region mapped_region(power_limit_shm, bi::read_write); | ||||||||||||
std::memcpy(mapped_region.get_address(), uuid.id, ZES_MAX_UUID_SIZE); | ||||||||||||
std::memcpy(((char*)mapped_region.get_address())+ZES_MAX_UUID_SIZE, pd[d].power_info_list.data(), pd[d].power_info_list.size()*sizeof(powerInfo)); | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] The pointer arithmetic and casting make this line complex and hard to read. Consider using a more explicit approach with offset variables or helper functions.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||
|
||||||||||||
// launch child process with power_handle_count | ||||||||||||
auto env = boost::this_process::environment(); | ||||||||||||
fs::path helper_path(fs::current_path() / "process"); | ||||||||||||
bp::environment child_env = env; | ||||||||||||
std::vector<fs::path> paths; | ||||||||||||
paths.push_back(helper_path); | ||||||||||||
fs::path helper = bp::search_path("test_sysman_power_process_helper", paths); | ||||||||||||
bp::child get_power_limit_in_child_proc(helper,bp::args({std::to_string(p_power_handles.size())}), child_env); | ||||||||||||
get_power_limit_in_child_proc.wait(); | ||||||||||||
|
||||||||||||
// check child process return status to decide test pass/fail. | ||||||||||||
EXPECT_EQ(get_power_limit_in_child_proc.exit_code(), 0); | ||||||||||||
|
||||||||||||
// Step 3 : Restore power limits back to original | ||||||||||||
for (size_t p = 0; p < p_power_handles.size(); ++p) { | ||||||||||||
EXPECT_NE(nullptr, p_power_handles[p]); | ||||||||||||
uint32_t count_power = 0; | ||||||||||||
auto status = lzt::set_power_limits_ext( | ||||||||||||
p_power_handles[p], &count_power, | ||||||||||||
power_limits_descriptors_initial[p].data()); // restore initial limits | ||||||||||||
if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { | ||||||||||||
continue; | ||||||||||||
} | ||||||||||||
EXPECT_ZE_RESULT_SUCCESS(status); | ||||||||||||
} | ||||||||||||
} | ||||||||||||
} | ||||||||||||
LZT_TEST_F( | ||||||||||||
POWER_TEST, | ||||||||||||
GivenValidPowerHandleWhenRequestingPowerLimitsThenExpectzesSysmanPowerGetLimitsToReturnSameValuesTwice) { | ||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,108 @@ | ||||||
/* | ||||||
* | ||||||
* Copyright (C) 2020-2025 Intel Corporation | ||||||
* | ||||||
* SPDX-License-Identifier: MIT | ||||||
* | ||||||
*/ | ||||||
|
||||||
#include <boost/interprocess/shared_memory_object.hpp> | ||||||
#include <boost/interprocess/mapped_region.hpp> | ||||||
|
||||||
#include "utils/utils.hpp" | ||||||
#include "test_harness/test_harness.hpp" | ||||||
#include "logging/logging.hpp" | ||||||
|
||||||
namespace lzt = level_zero_tests; | ||||||
namespace bp = boost::process; | ||||||
namespace bi = boost::interprocess; | ||||||
|
||||||
struct powerInfo { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 'powerInfo' struct is duplicated between this file and test_sysman_power.cpp. Consider moving this shared structure to a common header file to avoid code duplication and ensure consistency. Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
uint32_t interval; | ||||||
uint32_t limit; | ||||||
bool limitValueLocked; | ||||||
}; | ||||||
|
||||||
void GetPowerLimitsSetByParentProcess(uint32_t power_handle_size, bool &test_result) { | ||||||
//1. read shared object | ||||||
bi::shared_memory_object power_limit_shm(bi::open_only, "MultiProcPowerLimitSharedMemory", bi::read_only); | ||||||
bi::mapped_region region(power_limit_shm, bi::read_only); | ||||||
char* data = static_cast<char*>(region.get_address()); | ||||||
std::vector<powerInfo> power_limits_set; | ||||||
power_limits_set.resize(power_handle_size); | ||||||
zes_uuid_t uuid; | ||||||
memcpy(uuid.id, data, ZES_MAX_UUID_SIZE); | ||||||
memcpy(power_limits_set.data(), data+ZES_MAX_UUID_SIZE, power_handle_size*sizeof(powerInfo)); | ||||||
|
||||||
//2. read power limits set for the device | ||||||
auto driver = lzt::get_default_zes_driver(); | ||||||
auto dev_count = lzt::get_zes_device_count(driver); | ||||||
auto devices = lzt::get_zes_devices(dev_count, driver); | ||||||
for (auto device : devices) { | ||||||
zes_uuid_t id = lzt::get_sysman_device_uuid(device); | ||||||
if (lzt::is_uuid_pair_equal(id.id, uuid.id)) { | ||||||
uint32_t count = 0; | ||||||
auto p_power_handles = lzt::get_power_handles(device, count); | ||||||
if (count == 0) { | ||||||
FAIL() << "No handles found: " | ||||||
<< _ze_result_t(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); | ||||||
test_result = false; | ||||||
} | ||||||
|
||||||
for (size_t p = 0; p < p_power_handles.size(); ++p) { | ||||||
EXPECT_NE(nullptr, p_power_handles[p]); | ||||||
uint32_t count_power = 0; | ||||||
zes_power_limit_ext_desc_t power_peak_get = {}; | ||||||
std::vector<zes_power_limit_ext_desc_t> power_limits_descriptors; | ||||||
auto status = lzt::get_power_limits_ext( | ||||||
p_power_handles[p], &count_power, | ||||||
power_limits_descriptors); // get power limits for all descriptors | ||||||
if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { | ||||||
continue; | ||||||
} | ||||||
EXPECT_ZE_RESULT_SUCCESS(status); | ||||||
for (const auto &p_power_limits_descriptor : power_limits_descriptors) { | ||||||
if (p_power_limits_descriptor.level == ZES_POWER_LEVEL_PEAK) { | ||||||
power_peak_get = p_power_limits_descriptor; | ||||||
} | ||||||
} | ||||||
|
||||||
EXPECT_EQ(power_peak_get.limitValueLocked, | ||||||
power_limits_set[p].limitValueLocked); | ||||||
EXPECT_EQ(power_peak_get.interval, | ||||||
power_limits_set[p].interval); | ||||||
EXPECT_EQ(power_peak_get.limit, power_limits_set[p].limit); | ||||||
|
||||||
// Need to notify parent process about failure | ||||||
if (power_peak_get.limitValueLocked != power_limits_set[p].limitValueLocked || | ||||||
power_peak_get.interval != power_limits_set[p].interval || | ||||||
power_peak_get.limit != (power_limits_set[p].limit)) { | ||||||
test_result = false; | ||||||
return; | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
int main(int argc, char **argv) { | ||||||
if (argc != 2) { | ||||||
LOG_INFO << "Insufficient argument count " <<argc; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing space before '<<argc' in the log message. Should be 'LOG_INFO << "Insufficient argument count " << argc;'
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
return 1; | ||||||
} | ||||||
|
||||||
// Parent thread should pass number of power handles as argument | ||||||
uint32_t power_handle_size = std::stoi(argv[1]); | ||||||
|
||||||
ze_result_t result = zesInit(0); | ||||||
if (result != ZE_RESULT_SUCCESS) { | ||||||
exit(1); | ||||||
} | ||||||
|
||||||
bool test_result = true; | ||||||
GetPowerLimitsSetByParentProcess(power_handle_size, test_result); | ||||||
if (test_result == false) { | ||||||
return 1; // test failed, report the same to parent process | ||||||
} | ||||||
return 0; | ||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The 'powerInfo' struct is duplicated between files. Consider defining it in a shared header file to avoid code duplication and ensure consistency.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems valid comment. @Sarbojit2019 Could you please address this?