Added support for configuring PPT1 power cap
- Updated python integration test to account for PPT1 support changes - Updated set/reset power-cap input format - Adjusted python API and updated C++ API test Signed-off-by: gabrpham_amdeng <Gabriel.Pham@amd.com> Change-Id: Ia9d02868b6e91c88c10a9772d9e2d9f37c3c352f
Tento commit je obsažen v:
+33
-1
@@ -55,9 +55,41 @@ Full documentation for amd_smi_lib is available at [https://rocm.docs.amd.com/pr
|
||||
- `amd-smi static --vram` & `amdsmi_get_gpu_vram_info()` now support the following types:
|
||||
- DDR5, LPDDR4, LPDDR5, and HBM3E
|
||||
|
||||
- **Added support for PPT1 power limit information**.
|
||||
- Support has been added for querying and setting the PPT (Package Power Tracking) limits
|
||||
- There are two PPT limits, PPT0 has lower limit and tracks a filtered version of the input power and PPT1 has higher limit but tracks the raw input power. This is to catch spikes in the raw data.
|
||||
- See the Changed section for changes made to the `set` and `static` commands regarding support for PPT1.
|
||||
|
||||
### Changed
|
||||
|
||||
- N/A
|
||||
- **`amd-smi set --power-cap` now requires sepcification of the power cap type**.
|
||||
- command now takes the form: `amd-smi set --power-cap <power-cap-type> <new-cap>`
|
||||
- acceptable power cap types are "ppt0" and "ppt1"
|
||||
|
||||
```console
|
||||
$ sudo amd-smi set --power-cap ppt1 1150
|
||||
GPU: 0
|
||||
POWERCAP: Successfully set ppt1 power cap to 1150W
|
||||
...
|
||||
```
|
||||
|
||||
- **`amd-smi static --limit` now has a PPT1 section when PPT1 is available**.
|
||||
|
||||
```console
|
||||
$ amd-smi static --limit
|
||||
GPU: 0
|
||||
LIMIT:
|
||||
PPT0:
|
||||
MAX_POWER_LIMIT: 1000
|
||||
MIN_POWER_LIMIT: 0
|
||||
SOCKET_POWER_LIMIT: 1000
|
||||
PPT1:
|
||||
MAX_POWER_LIMIT: 1300
|
||||
MIN_POWER_LIMIT: 1100
|
||||
SOCKET_POWER_LIMIT: 1250
|
||||
SLOWDOWN_EDGE_TEMPERATURE: N/A
|
||||
...
|
||||
```
|
||||
|
||||
### Removed
|
||||
|
||||
|
||||
@@ -606,20 +606,36 @@ class AMDSMICommands():
|
||||
if 'limit' in current_platform_args:
|
||||
if args.limit:
|
||||
# Power limits
|
||||
|
||||
power_limit_types = {}
|
||||
for power_type in amdsmi_interface.AmdSmiPowerCapType:
|
||||
# Strip 'AMDSMI_POWER_CAP_TYPE_' prefix and convert to lowercase
|
||||
key = power_type.name.replace('AMDSMI_POWER_CAP_TYPE_', '').lower()
|
||||
power_limit_types[key] = "N/A"
|
||||
|
||||
try:
|
||||
power_limit_error = False
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu)
|
||||
max_power_limit = power_cap_info['max_power_cap']
|
||||
max_power_limit = self.helpers.convert_SI_unit(max_power_limit, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
min_power_limit = power_cap_info['min_power_cap']
|
||||
min_power_limit = self.helpers.convert_SI_unit(min_power_limit, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
socket_power_limit = power_cap_info['power_cap']
|
||||
socket_power_limit = self.helpers.convert_SI_unit(socket_power_limit, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
power_cap_types = amdsmi_interface.amdsmi_get_supported_power_cap(args.gpu)
|
||||
for sensor in power_cap_types['sensor_inds']:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu, sensor)
|
||||
max_power_limit = power_cap_info['max_power_cap']
|
||||
max_power_limit = self.helpers.convert_SI_unit(max_power_limit, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
min_power_limit = power_cap_info['min_power_cap']
|
||||
min_power_limit = self.helpers.convert_SI_unit(min_power_limit, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
socket_power_limit = power_cap_info['power_cap']
|
||||
socket_power_limit = self.helpers.convert_SI_unit(socket_power_limit, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
ppt = {
|
||||
"max_power_limit" : max_power_limit,
|
||||
"min_power_limit" : min_power_limit,
|
||||
"socket_power_limit" : socket_power_limit
|
||||
}
|
||||
|
||||
sensor_name = power_cap_types['sensor_types'][sensor]
|
||||
# Strip 'AMDSMI_POWER_CAP_TYPE_' prefix and convert to lowercase
|
||||
sensor_key = sensor_name.name.replace('AMDSMI_POWER_CAP_TYPE_', '').lower()
|
||||
power_limit_types[sensor_key] = ppt
|
||||
except amdsmi_exception.AmdSmiLibraryException as e:
|
||||
power_limit_error = True
|
||||
max_power_limit = "N/A"
|
||||
min_power_limit = "N/A"
|
||||
socket_power_limit = "N/A"
|
||||
logging.debug("Failed to get power cap info for gpu %s | %s", gpu_id, e.get_error_info())
|
||||
|
||||
# Edge temperature limits
|
||||
@@ -740,9 +756,8 @@ class AMDSMICommands():
|
||||
|
||||
limit_info = {}
|
||||
# Power limits
|
||||
limit_info['max_power'] = max_power_limit
|
||||
limit_info['min_power'] = min_power_limit
|
||||
limit_info['socket_power'] = socket_power_limit
|
||||
limit_info['ppt0'] = power_limit_types['ppt0']
|
||||
limit_info['ppt1'] = power_limit_types['ppt1']
|
||||
|
||||
# Shutdown limits
|
||||
limit_info['slowdown_edge_temperature'] = slowdown_temp_edge_limit
|
||||
@@ -4909,9 +4924,13 @@ class AMDSMICommands():
|
||||
self.logger.clear_multiple_devices_output()
|
||||
return
|
||||
# Universal args
|
||||
if isinstance(args.power_cap, int):
|
||||
if isinstance(args.power_cap, tuple):
|
||||
pwr_type = args.power_cap.pwr_type
|
||||
pwr_type_as_int = (0 if pwr_type == "ppt0" else 1 if pwr_type == "ppt1" else None)
|
||||
pwr_type = pwr_type.upper()
|
||||
requested_power_cap = args.power_cap.watts
|
||||
try:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu)
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu, pwr_type_as_int)
|
||||
logging.debug(f"Power cap info for gpu {gpu_id} | {power_cap_info}")
|
||||
min_power_cap = power_cap_info["min_power_cap"]
|
||||
min_power_cap = self.helpers.convert_SI_unit(min_power_cap, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
@@ -4923,29 +4942,29 @@ class AMDSMICommands():
|
||||
min_power_cap = "N/A"
|
||||
max_power_cap = "N/A"
|
||||
current_power_cap = "N/A"
|
||||
self.logger.store_output(args.gpu, 'powercap', f"[{e.get_error_info(detailed=False)}] Unable to set power cap to {args.power_cap}W")
|
||||
self.logger.store_output(args.gpu, 'powercap', f"[{e.get_error_info(detailed=False)}] Unable to set {pwr_type} power cap to {requested_power_cap}W")
|
||||
self.logger.print_output()
|
||||
self.logger.clear_multiple_devices_output()
|
||||
return
|
||||
|
||||
if args.power_cap == current_power_cap:
|
||||
self.logger.store_output(args.gpu, 'powercap', f"Power cap is already set to {args.power_cap}W")
|
||||
if requested_power_cap == current_power_cap:
|
||||
self.logger.store_output(args.gpu, 'powercap', f"{pwr_type} power cap is already set to {requested_power_cap}W")
|
||||
elif current_power_cap == 0:
|
||||
self.logger.store_output(args.gpu, 'powercap', f"Unable to set power cap to {args.power_cap}W, current value is {current_power_cap}W")
|
||||
elif args.power_cap >= min_power_cap and args.power_cap <= max_power_cap:
|
||||
self.logger.store_output(args.gpu, 'powercap', f"Unable to set {pwr_type} power cap to {requested_power_cap}W, current value is {current_power_cap}W")
|
||||
elif requested_power_cap >= min_power_cap and requested_power_cap <= max_power_cap and requested_power_cap > 0:
|
||||
try:
|
||||
new_power_cap = self.helpers.convert_SI_unit(args.power_cap, AMDSMIHelpers.SI_Unit.BASE,
|
||||
new_power_cap = self.helpers.convert_SI_unit(requested_power_cap, AMDSMIHelpers.SI_Unit.BASE,
|
||||
AMDSMIHelpers.SI_Unit.MICRO)
|
||||
amdsmi_interface.amdsmi_set_power_cap(args.gpu, 0, new_power_cap)
|
||||
amdsmi_interface.amdsmi_set_power_cap(args.gpu, pwr_type_as_int, new_power_cap)
|
||||
except amdsmi_exception.AmdSmiLibraryException as e:
|
||||
if e.get_error_code() == amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NO_PERM:
|
||||
raise PermissionError('Command requires elevation') from e
|
||||
self.logger.store_output(args.gpu, 'powercap', f"[{e.get_error_info(detailed=False)}] Unable to set power cap to {args.power_cap}W")
|
||||
self.logger.store_output(args.gpu, 'powercap', f"[{e.get_error_info(detailed=False)}] Unable to set {pwr_type} power cap to {requested_power_cap}W")
|
||||
self.logger.print_output()
|
||||
self.logger.clear_multiple_devices_output()
|
||||
return
|
||||
|
||||
self.logger.store_output(args.gpu, 'powercap', f"Successfully set power cap to {args.power_cap}W")
|
||||
self.logger.store_output(args.gpu, 'powercap', f"Successfully set {pwr_type} power cap to {requested_power_cap}W")
|
||||
else:
|
||||
# setting power cap to 0 will return the current power cap so the technical minimum value is 1
|
||||
if min_power_cap == 0:
|
||||
@@ -5469,32 +5488,66 @@ class AMDSMICommands():
|
||||
self.logger.clear_multiple_devices_output()
|
||||
return
|
||||
if args.power_cap:
|
||||
power_limit_types = {}
|
||||
for power_type in amdsmi_interface.AmdSmiPowerCapType:
|
||||
# Strip 'AMDSMI_POWER_CAP_TYPE_' prefix and convert to lowercase
|
||||
key = power_type.name.replace('AMDSMI_POWER_CAP_TYPE_', '').lower()
|
||||
power_limit_types[key] = "N/A"
|
||||
|
||||
try:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu)
|
||||
logging.debug(f"Power cap info for gpu {gpu_id} | {power_cap_info}")
|
||||
default_power_cap_in_w = power_cap_info["default_power_cap"]
|
||||
default_power_cap_in_w = self.helpers.convert_SI_unit(default_power_cap_in_w, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
current_power_cap_in_w = power_cap_info["power_cap"]
|
||||
current_power_cap_in_w = self.helpers.convert_SI_unit(current_power_cap_in_w, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
power_cap_types = amdsmi_interface.amdsmi_get_supported_power_cap(args.gpu)
|
||||
for sensor in power_cap_types['sensor_inds']:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu, sensor)
|
||||
logging.debug(f"Power cap info for gpu {gpu_id} ppt{sensor} | {power_cap_info}")
|
||||
default_power_cap_in_w = power_cap_info["default_power_cap"]
|
||||
default_power_cap_in_w = self.helpers.convert_SI_unit(default_power_cap_in_w, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
current_power_cap_in_w = power_cap_info["power_cap"]
|
||||
current_power_cap_in_w = self.helpers.convert_SI_unit(current_power_cap_in_w, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
sensor_name = power_cap_types['sensor_types'][sensor]
|
||||
# Strip 'AMDSMI_POWER_CAP_TYPE_' prefix and convert to lowercase
|
||||
sensor_key = sensor_name.name.replace('AMDSMI_POWER_CAP_TYPE_', '').lower()
|
||||
power_limit_types[sensor_key] = (default_power_cap_in_w, current_power_cap_in_w)
|
||||
except amdsmi_exception.AmdSmiLibraryException as e:
|
||||
self.logger.store_output(args.gpu, 'powercap', f"[{e.get_error_info(detailed=False)}] Unable to reset power cap to default")
|
||||
self.logger.print_output()
|
||||
self.logger.clear_multiple_devices_output()
|
||||
return
|
||||
|
||||
if current_power_cap_in_w == default_power_cap_in_w:
|
||||
self.logger.store_output(args.gpu, 'powercap', f"Power cap is already set to {default_power_cap_in_w}W")
|
||||
# TODO Make agnostic to number of power cap types
|
||||
final_output = {"ppt0": "", "ppt1": ""}
|
||||
if power_limit_types['ppt0'] == "N/A":
|
||||
final_output['ppt0'] = f"PPT0 Power cap information is not available"
|
||||
elif power_limit_types['ppt0'][1] == power_limit_types['ppt0'][0]:
|
||||
final_output['ppt0'] = f"PPT0 Power cap is already set to {power_limit_types['ppt0'][0]}W"
|
||||
else:
|
||||
try:
|
||||
default_power_cap_in_uw = self.helpers.convert_SI_unit(default_power_cap_in_w,
|
||||
AMDSMIHelpers.SI_Unit.BASE,
|
||||
AMDSMIHelpers.SI_Unit.MICRO)
|
||||
amdsmi_interface.amdsmi_set_power_cap(args.gpu, 0, default_power_cap_in_uw)
|
||||
default_ppt0_power_cap_in_uw = self.helpers.convert_SI_unit(power_limit_types['ppt0'][0],
|
||||
AMDSMIHelpers.SI_Unit.BASE,
|
||||
AMDSMIHelpers.SI_Unit.MICRO)
|
||||
amdsmi_interface.amdsmi_set_power_cap(args.gpu, 0, default_ppt0_power_cap_in_uw)
|
||||
except amdsmi_exception.AmdSmiLibraryException as e:
|
||||
if e.get_error_code() == amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NO_PERM:
|
||||
raise PermissionError('Command requires elevation') from e
|
||||
raise ValueError(f"Unable to reset power cap to {default_power_cap_in_w} on GPU {gpu_id}") from e
|
||||
self.logger.store_output(args.gpu, 'powercap', f"Successfully set power cap to {default_power_cap_in_w}W")
|
||||
raise ValueError(f"Unable to reset PPT0 power cap to {power_limit_types['ppt0'][0]} on GPU {gpu_id}") from e
|
||||
final_output['ppt0'] = f"Successfully reset PPT0 power cap to {power_limit_types['ppt0'][0]}W"
|
||||
|
||||
if power_limit_types['ppt1'] == "N/A":
|
||||
final_output['ppt1'] = f"PPT1 Power cap information is not available"
|
||||
elif power_limit_types['ppt1'][1] == power_limit_types['ppt1'][0]:
|
||||
final_output['ppt1'] = f"PPT1 Power cap is already set to {power_limit_types['ppt1'][0]}W"
|
||||
else:
|
||||
try:
|
||||
default_ppt1_power_cap_in_uw = self.helpers.convert_SI_unit(power_limit_types['ppt1'][0],
|
||||
AMDSMIHelpers.SI_Unit.BASE,
|
||||
AMDSMIHelpers.SI_Unit.MICRO)
|
||||
amdsmi_interface.amdsmi_set_power_cap(args.gpu, 1, default_ppt1_power_cap_in_uw)
|
||||
except amdsmi_exception.AmdSmiLibraryException as e:
|
||||
if e.get_error_code() == amdsmi_interface.amdsmi_wrapper.AMDSMI_STATUS_NO_PERM:
|
||||
raise PermissionError('Command requires elevation') from e
|
||||
raise ValueError(f"Unable to reset PPT1 power cap to {power_limit_types['ppt1'][0]} on GPU {gpu_id}") from e
|
||||
final_output['ppt1'] = f"Successfully reset PPT1 power cap to {power_limit_types['ppt1'][0]}W"
|
||||
|
||||
self.logger.store_output(args.gpu, 'powercap', final_output)
|
||||
self.logger.print_output()
|
||||
self.logger.clear_multiple_devices_output()
|
||||
return
|
||||
@@ -5822,7 +5875,8 @@ class AMDSMICommands():
|
||||
if args.power_usage and not args.default_output:
|
||||
# Get Current Power Cap
|
||||
try:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu)
|
||||
# assume that we're always asking for ppt0 for quick checks like this
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu, 0)
|
||||
monitor_values['max_power'] = power_cap_info['power_cap'] # Get current power cap (`power_cap`) socket is set to
|
||||
# `max_power_cap`, is the maximum value it can be set to
|
||||
monitor_values['max_power'] = self.helpers.convert_SI_unit(monitor_values['max_power'], AMDSMIHelpers.SI_Unit.MICRO)
|
||||
@@ -7340,9 +7394,9 @@ class AMDSMICommands():
|
||||
gpu_info_dict.update({"temp": temperature})
|
||||
|
||||
|
||||
# rest of power usage info
|
||||
# rest of power usage info; Will assume we're always trying to get PPT0 for now
|
||||
try:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(processor)
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(processor, 0)
|
||||
socket_power_limit = self.helpers.convert_SI_unit(power_cap_info['power_cap'], AMDSMIHelpers.SI_Unit.MICRO)
|
||||
power_usage = {"current_power": current_power, "power_limit": socket_power_limit}
|
||||
except amdsmi_exception.AmdSmiLibraryException as e:
|
||||
|
||||
@@ -815,26 +815,50 @@ class AMDSMIHelpers():
|
||||
|
||||
def get_power_caps(self):
|
||||
device_handles = amdsmi_interface.amdsmi_get_processor_handles()
|
||||
power_cap_min = amdsmi_interface.MaxUIntegerTypes.UINT64_T # start out at max and min and then find real min and max
|
||||
power_cap_max = 0
|
||||
power_limit_types = {
|
||||
'ppt0': {
|
||||
'power_cap_min': amdsmi_interface.MaxUIntegerTypes.UINT64_T,
|
||||
'power_cap_max': 0
|
||||
},
|
||||
'ppt1': {
|
||||
'power_cap_min': amdsmi_interface.MaxUIntegerTypes.UINT64_T,
|
||||
'power_cap_max': 0
|
||||
}
|
||||
}
|
||||
|
||||
for dev in device_handles:
|
||||
try:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(dev)
|
||||
if power_cap_info['max_power_cap'] > power_cap_max:
|
||||
power_cap_max = power_cap_info['max_power_cap']
|
||||
if power_cap_info['min_power_cap'] < power_cap_max:
|
||||
power_cap_min = power_cap_info['min_power_cap']
|
||||
except amdsmi_interface.AmdSmiLibraryException as e:
|
||||
power_cap_types = amdsmi_interface.amdsmi_get_supported_power_cap(dev)
|
||||
for sensor in power_cap_types['sensor_inds']:
|
||||
power_cap_info = amdsmi_interface.amdsmi_get_power_cap_info(dev, sensor)
|
||||
if power_cap_info['max_power_cap'] > power_limit_types[f'ppt{sensor}']['power_cap_max']:
|
||||
power_limit_types[f'ppt{sensor}']['power_cap_max'] = power_cap_info['max_power_cap']
|
||||
if power_cap_info['min_power_cap'] < power_limit_types[f'ppt{sensor}']['power_cap_min']:
|
||||
power_limit_types[f'ppt{sensor}']['power_cap_min'] = power_cap_info['min_power_cap']
|
||||
except (amdsmi_interface.AmdSmiLibraryException, KeyError) as e:
|
||||
logging.debug(f"AMDSMIHelpers.get_power_caps - Unable to get power cap info for device {dev}: {str(e)}")
|
||||
continue
|
||||
|
||||
# If we never found a real min or max, set them to N/A
|
||||
if power_cap_min == amdsmi_interface.MaxUIntegerTypes.UINT64_T:
|
||||
power_cap_min = "N/A"
|
||||
if power_cap_max == 0:
|
||||
power_cap_max = "N/A"
|
||||
for ppt_key in ['ppt0', 'ppt1']:
|
||||
if power_limit_types[ppt_key]['power_cap_min'] == amdsmi_interface.MaxUIntegerTypes.UINT64_T:
|
||||
power_limit_types[ppt_key]['power_cap_min'] = "N/A"
|
||||
if power_limit_types[ppt_key]['power_cap_max'] == 0:
|
||||
power_limit_types[ppt_key]['power_cap_max'] = "N/A"
|
||||
|
||||
return (power_cap_min, power_cap_max)
|
||||
ppt0_power_cap_max = self.format_power_cap(power_limit_types['ppt0']['power_cap_min'])
|
||||
ppt0_power_cap_min = self.format_power_cap(power_limit_types['ppt0']['power_cap_max'])
|
||||
ppt1_power_cap_max = self.format_power_cap(power_limit_types['ppt1']['power_cap_max'])
|
||||
ppt1_power_cap_min = self.format_power_cap(power_limit_types['ppt1']['power_cap_min'])
|
||||
|
||||
return (ppt0_power_cap_min, ppt0_power_cap_min, ppt1_power_cap_max, ppt1_power_cap_min)
|
||||
|
||||
|
||||
def format_power_cap(self, value):
|
||||
if value != "N/A":
|
||||
converted = self.convert_SI_unit(value, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
return f"{converted} W"
|
||||
return value
|
||||
|
||||
|
||||
def get_soc_pstates(self):
|
||||
|
||||
@@ -288,6 +288,30 @@ class AMDSMIParser(argparse.ArgumentParser):
|
||||
return AMDSMIFreqArgs
|
||||
|
||||
|
||||
def _power_cap_options(self):
|
||||
"""Custom action for setting power cap options"""
|
||||
output_format = self.helpers.get_output_format()
|
||||
|
||||
class AMDSMIPowerCapArgs(argparse.Action):
|
||||
def __call__(self, parser: AMDSMIParser, namespace: argparse.Namespace,
|
||||
values: list, option_string: Optional[str] = None) -> None:
|
||||
if len(values) != 2:
|
||||
raise amdsmi_cli_exceptions.AmdSmiInvalidParameterException(sys.argv[1], values, output_format)
|
||||
|
||||
power_cap_type = values[0]
|
||||
power_cap_value = values[1]
|
||||
|
||||
if power_cap_type not in ['ppt0', 'ppt1']:
|
||||
raise amdsmi_cli_exceptions.AmdSmiInvalidParameterException(sys.argv[1], power_cap_type, output_format)
|
||||
|
||||
if not power_cap_value.isdigit():
|
||||
raise amdsmi_cli_exceptions.AmdSmiInvalidParameterValueException(sys.argv[1], power_cap_value, output_format)
|
||||
|
||||
power_cap_args = collections.namedtuple('power_cap_args', ['pwr_type', 'watts'])
|
||||
setattr(namespace, self.dest, power_cap_args(power_cap_type, int(power_cap_value)))
|
||||
return AMDSMIPowerCapArgs
|
||||
|
||||
|
||||
def _check_folder_path(self):
|
||||
""" Argument action validator:
|
||||
Returns a path to folder from the folder path provided.
|
||||
@@ -1235,14 +1259,8 @@ class AMDSMIParser(argparse.ArgumentParser):
|
||||
xgmi_plpd_help_info = ", ".join(self.helpers.get_xgmi_plpd_policies())
|
||||
set_xgmi_plpd_help = f"Set the GPU XGMI per-link power down policy using policy id, an integer. Valid id's include:\n\t{xgmi_plpd_help_info}"
|
||||
set_clock_freq_help = "Set one or more sclk (aka gfxclk), mclk, fclk, pcie, or socclk frequency levels.\n\tUse `amd-smi static --clock` to find acceptable levels.\n\tUse `amd-smi static --bus` to find acceptable pcie levels."
|
||||
power_cap_min, power_cap_max = self.helpers.get_power_caps()
|
||||
if power_cap_max != "N/A":
|
||||
power_cap_max = self.helpers.convert_SI_unit(power_cap_max, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
power_cap_max = str(power_cap_max) + ' W'
|
||||
if power_cap_min != "N/A":
|
||||
power_cap_min = self.helpers.convert_SI_unit(power_cap_min, AMDSMIHelpers.SI_Unit.MICRO)
|
||||
power_cap_min = str(power_cap_min) + ' W'
|
||||
set_power_cap_help = f"Set power capacity limit:\n\tmin cap: {power_cap_min}, max cap: {power_cap_max}"
|
||||
ppt0_power_cap_min, ppt0_power_cap_max, ppt1_power_cap_min, ppt1_power_cap_max = self.helpers.get_power_caps()
|
||||
set_power_cap_help = f"Set either PPT0 or PPT1 power capacity limit:\n\tex: amd-smi set -o ppt0 1300\n\tPPT0 min cap: {ppt0_power_cap_min}, PPT0 max cap: {ppt0_power_cap_max}\n\tPPT1 min cap: {ppt1_power_cap_min}, PPT1 max cap: {ppt1_power_cap_max}"
|
||||
set_clk_limit_help = "Sets the sclk (aka gfxclk) or mclk minimum and maximum frequencies. \n\tex: amd-smi set -L (sclk | mclk) (min | max) value"
|
||||
set_process_isolation_help = "Enable or disable the GPU process isolation on a per partition basis:\n 0 for disable and 1 for enable.\n"
|
||||
|
||||
@@ -1281,7 +1299,7 @@ class AMDSMIParser(argparse.ArgumentParser):
|
||||
required=False, help=set_compute_partition_help, metavar=('TYPE/INDEX'))
|
||||
set_value_exclusive_group.add_argument('-M', '--memory-partition', action='store', choices=self.helpers.get_memory_partition_types(), type=str.upper, required=False, help=set_memory_partition_help, metavar='PARTITION')
|
||||
# Power cap is enabled on guest, maintain order
|
||||
set_value_exclusive_group.add_argument('-o', '--power-cap', action='store', type=lambda value: self._positive_int(value, '--power-cap'), required=False, help=set_power_cap_help, metavar='WATTS')
|
||||
set_value_exclusive_group.add_argument('-o', '--power-cap', action=self._power_cap_options(), nargs=2, required=False, help=set_power_cap_help, metavar=('PWR_TYPE', 'WATTS'))
|
||||
if self.helpers.is_baremetal():
|
||||
set_value_exclusive_group.add_argument('-p', '--soc-pstate', action='store', required=False, type=lambda value: self._not_negative_int(value, '--soc-pstate'), help=set_soc_pstate_help, metavar='POLICY_ID')
|
||||
set_value_exclusive_group.add_argument('-x', '--xgmi-plpd', action='store', required=False, type=lambda value: self._not_negative_int(value, '--xgmi-plpd'), help=set_xgmi_plpd_help, metavar='POLICY_ID')
|
||||
@@ -1338,7 +1356,7 @@ class AMDSMIParser(argparse.ArgumentParser):
|
||||
reset_profile_help = "Reset power profile back to default"
|
||||
reset_xgmierr_help = "Reset XGMI error counts"
|
||||
reset_perf_det_help = "Disable performance determinism"
|
||||
reset_power_cap_help = "Reset power capacity limit to max capable"
|
||||
reset_power_cap_help = "Reset the PPT0 and PPT1 power capacity limit to max capable"
|
||||
reset_gpu_clean_local_data_help = "Clean up local data in LDS/GPRs on a per partition basis"
|
||||
reset_gpu_driver_help = "Reset (reload) AMD GPU driver"
|
||||
|
||||
|
||||
@@ -434,6 +434,7 @@ on the given GPU. It is not supported on virtual machine guest
|
||||
Input parameters:
|
||||
|
||||
* `processor_handle` device which to query
|
||||
* `sensor_ind` The Package Power Tracking (PPT) type to query
|
||||
|
||||
Output: Dictionary with fields
|
||||
|
||||
@@ -460,7 +461,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
power_cap_info = amdsmi_get_power_cap_info(device)
|
||||
power_cap_info = amdsmi_get_power_cap_info(device, 0)
|
||||
print(power_cap_info['power_cap'])
|
||||
print(power_cap_info['dpm_cap'])
|
||||
print(power_cap_info['default_power_cap'])
|
||||
@@ -470,6 +471,43 @@ except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
|
||||
### amdsmi_get_supported_power_cap
|
||||
|
||||
Description: Returns dictionary of Package Power Tracking (PPT) types as currently
|
||||
configured on the given GPU. It is not supported on virtual machine guest
|
||||
|
||||
Input parameters:
|
||||
|
||||
* `processor_handle` device which to query
|
||||
|
||||
Output: Dictionary with fields
|
||||
|
||||
Field | Description | Units
|
||||
---|---
|
||||
`sensor_inds` | List of integer indices of the supported ppt types. 0 indicates PPT0 and 1 indicates PPT1. Should be used as input for `amdsmi_get_power_cap_info` and `amdsmi_set_power_cap_info`.
|
||||
`sensor_types` | Enum `AmdSmiPowerCapType` that corresponds to the ppt types that are supported on the device.
|
||||
|
||||
Exceptions that can be thrown by `amdsmi_get_supported_power_cap` function:
|
||||
|
||||
* `AmdSmiLibraryException`
|
||||
* `AmdSmiParameterException`
|
||||
|
||||
Example:
|
||||
|
||||
```python
|
||||
try:
|
||||
devices = amdsmi_get_processor_handles()
|
||||
if len(devices) == 0:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
power_cap_types = amdsmi_get_supported_power_cap(device)
|
||||
print(power_cap_types['sensor_inds'])
|
||||
print(power_cap_types['sensor_types'])
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
|
||||
### amdsmi_get_gpu_vram_info
|
||||
|
||||
Description: Returns dictionary of vram information for the given GPU.
|
||||
|
||||
@@ -833,6 +833,16 @@ typedef struct {
|
||||
uint64_t reserved[3];
|
||||
} amdsmi_power_cap_info_t;
|
||||
|
||||
/**
|
||||
* @brief Power Cap Package Power Tracking (PPT) type
|
||||
*
|
||||
* @cond @tag{gpu_bm_linux} @tag{host} @endcond
|
||||
*/
|
||||
typedef enum {
|
||||
AMDSMI_POWER_CAP_TYPE_PPT0, //!< PPT0 power cap; lower limit, filtered input
|
||||
AMDSMI_POWER_CAP_TYPE_PPT1, //!< PPT1 power cap; higher limit, raw input
|
||||
} amdsmi_power_cap_type_t;
|
||||
|
||||
/**
|
||||
* @brief VBios Information
|
||||
*
|
||||
@@ -3277,6 +3287,29 @@ amdsmi_status_t
|
||||
amdsmi_set_gpu_power_profile(amdsmi_processor_handle processor_handle, uint32_t reserved,
|
||||
amdsmi_power_profile_preset_masks_t profile);
|
||||
|
||||
/**
|
||||
* @brief Query the supported power cap sensors and their types for a device.
|
||||
*
|
||||
* @ingroup tagPowerControl
|
||||
*
|
||||
* @platform{gpu_bm_linux} @platform{host}
|
||||
*
|
||||
* @details This function returns the list of supported power cap sensors for the given device,
|
||||
* including their sensor indices and types (e.g., PPT0, PPT1).
|
||||
*
|
||||
* @param[in] processor_handle A processor handle.
|
||||
* @param[out] sensor_count Pointer to a uint32_t that will be set to the number of supported sensors.
|
||||
* @param[out] sensor_inds Pointer to an array of uint32_t to be filled with sensor indices.
|
||||
* The array must be allocated by the caller with enough space.
|
||||
* @param[out] sensor_types Pointer to an array of amdsmi_power_cap_type_t to be filled with sensor types.
|
||||
* The array must be allocated by the caller with enough space.
|
||||
*
|
||||
* @return ::amdsmi_status_t | ::AMDSMI_STATUS_SUCCESS on success, non-zero on fail.
|
||||
*/
|
||||
amdsmi_status_t
|
||||
amdsmi_get_supported_power_cap(amdsmi_processor_handle processor_handle, uint32_t *sensor_count,
|
||||
uint32_t *sensor_inds, amdsmi_power_cap_type_t *sensor_types);
|
||||
|
||||
/**
|
||||
* @brief Get the socket power.
|
||||
*
|
||||
|
||||
@@ -45,7 +45,7 @@ extern "C" {
|
||||
|
||||
amdsmi_status_t smi_amdgpu_find_hwmon_dir(amd::smi::AMDSmiGPUDevice* device, std::string* full_path);
|
||||
amdsmi_status_t smi_amdgpu_get_board_info(amd::smi::AMDSmiGPUDevice* device, amdsmi_board_info_t *info);
|
||||
amdsmi_status_t smi_amdgpu_get_power_cap(amd::smi::AMDSmiGPUDevice* device, int *cap);
|
||||
amdsmi_status_t smi_amdgpu_get_power_cap(amd::smi::AMDSmiGPUDevice* device, uint32_t sensor_ind, int *cap);
|
||||
amdsmi_status_t smi_amdgpu_get_ranges(amd::smi::AMDSmiGPUDevice* device, amdsmi_clk_type_t domain, int *max_freq, int *min_freq, int *num_dpm, int *sleep_state_freq);
|
||||
amdsmi_status_t smi_amdgpu_get_enabled_blocks(amd::smi::AMDSmiGPUDevice* device, uint64_t *enabled_blocks);
|
||||
amdsmi_status_t smi_amdgpu_get_bad_page_info(amd::smi::AMDSmiGPUDevice* device, uint32_t *num_pages, amdsmi_retired_page_record_t *info);
|
||||
|
||||
@@ -168,6 +168,7 @@ from .amdsmi_interface import amdsmi_get_xgmi_plpd
|
||||
from .amdsmi_interface import amdsmi_clean_gpu_local_data
|
||||
from .amdsmi_interface import amdsmi_get_gpu_process_isolation
|
||||
from .amdsmi_interface import amdsmi_set_gpu_process_isolation
|
||||
from .amdsmi_interface import amdsmi_get_supported_power_cap
|
||||
|
||||
# # Physical State Queries
|
||||
from .amdsmi_interface import amdsmi_get_gpu_fan_rpms
|
||||
|
||||
@@ -605,6 +605,11 @@ class AmdSmiAffinityScope(IntEnum):
|
||||
SOCKET_SCOPE = amdsmi_wrapper.AMDSMI_AFFINITY_SCOPE_SOCKET
|
||||
|
||||
|
||||
class AmdSmiPowerCapType(IntEnum):
|
||||
PPT0 = amdsmi_wrapper.AMDSMI_POWER_CAP_TYPE_PPT0
|
||||
PPT1 = amdsmi_wrapper.AMDSMI_POWER_CAP_TYPE_PPT1
|
||||
|
||||
|
||||
class AmdSmiEventReader:
|
||||
def __init__(
|
||||
self,
|
||||
@@ -2154,9 +2159,32 @@ def amdsmi_get_gpu_kfd_info(
|
||||
|
||||
return kfd_info
|
||||
|
||||
def amdsmi_get_supported_power_cap(
|
||||
processor_handle: processor_handle_t) ->Dict[str, Any]:
|
||||
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
||||
raise AmdSmiParameterException(
|
||||
processor_handle, amdsmi_wrapper.amdsmi_processor_handle
|
||||
)
|
||||
CONST_AMDSMI_MAX_POWER_SENSORS = 2
|
||||
|
||||
sensor_count = ctypes.c_uint32()
|
||||
sensor_ind = (ctypes.c_uint32 * CONST_AMDSMI_MAX_POWER_SENSORS)()
|
||||
sensor_types = (amdsmi_wrapper.amdsmi_power_cap_type_t * CONST_AMDSMI_MAX_POWER_SENSORS)()
|
||||
|
||||
_check_res(
|
||||
amdsmi_wrapper.amdsmi_get_supported_power_cap(
|
||||
processor_handle, ctypes.byref(sensor_count), sensor_ind, sensor_types
|
||||
)
|
||||
)
|
||||
|
||||
return {
|
||||
"sensor_inds": [sensor_ind[i] for i in range(sensor_count.value)],
|
||||
"sensor_types": [AmdSmiPowerCapType(sensor_types[i]) for i in range(sensor_count.value)]
|
||||
}
|
||||
|
||||
def amdsmi_get_power_cap_info(
|
||||
processor_handle: processor_handle_t,
|
||||
sensor_ind: int = 0
|
||||
) -> Dict[str, Any]:
|
||||
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
||||
raise AmdSmiParameterException(
|
||||
@@ -2166,7 +2194,7 @@ def amdsmi_get_power_cap_info(
|
||||
power_cap_info = amdsmi_wrapper.amdsmi_power_cap_info_t()
|
||||
_check_res(
|
||||
amdsmi_wrapper.amdsmi_get_power_cap_info(
|
||||
processor_handle, ctypes.c_uint32(0), ctypes.byref(power_cap_info)
|
||||
processor_handle, sensor_ind, ctypes.byref(power_cap_info)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -2176,7 +2204,6 @@ def amdsmi_get_power_cap_info(
|
||||
"min_power_cap": power_cap_info.min_power_cap,
|
||||
"max_power_cap": power_cap_info.max_power_cap}
|
||||
|
||||
|
||||
def _get_name_value(num, data) -> List[Dict[str, int]]:
|
||||
"""
|
||||
Extracts a list of name-value pairs from a ctypes array buffer.
|
||||
|
||||
@@ -1034,6 +1034,15 @@ struct_amdsmi_power_cap_info_t._fields_ = [
|
||||
]
|
||||
|
||||
amdsmi_power_cap_info_t = struct_amdsmi_power_cap_info_t
|
||||
|
||||
# values for enumeration 'amdsmi_power_cap_type_t'
|
||||
amdsmi_power_cap_type_t__enumvalues = {
|
||||
0: 'AMDSMI_POWER_CAP_TYPE_PPT0',
|
||||
1: 'AMDSMI_POWER_CAP_TYPE_PPT1',
|
||||
}
|
||||
AMDSMI_POWER_CAP_TYPE_PPT0 = 0
|
||||
AMDSMI_POWER_CAP_TYPE_PPT1 = 1
|
||||
amdsmi_power_cap_type_t = ctypes.c_uint32 # enum
|
||||
class struct_amdsmi_vbios_info_t(Structure):
|
||||
pass
|
||||
|
||||
@@ -2550,6 +2559,9 @@ amdsmi_set_power_cap.argtypes = [amdsmi_processor_handle, uint32_t, uint64_t]
|
||||
amdsmi_set_gpu_power_profile = _libraries['libamd_smi.so'].amdsmi_set_gpu_power_profile
|
||||
amdsmi_set_gpu_power_profile.restype = amdsmi_status_t
|
||||
amdsmi_set_gpu_power_profile.argtypes = [amdsmi_processor_handle, uint32_t, amdsmi_power_profile_preset_masks_t]
|
||||
amdsmi_get_supported_power_cap = _libraries['libamd_smi.so'].amdsmi_get_supported_power_cap
|
||||
amdsmi_get_supported_power_cap.restype = amdsmi_status_t
|
||||
amdsmi_get_supported_power_cap.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(amdsmi_power_cap_type_t)]
|
||||
amdsmi_get_cpu_socket_power = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_power
|
||||
amdsmi_get_cpu_socket_power.restype = amdsmi_status_t
|
||||
amdsmi_get_cpu_socket_power.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_uint32)]
|
||||
@@ -3219,7 +3231,8 @@ __all__ = \
|
||||
'AMDSMI_MEM_TYPE_GTT', 'AMDSMI_MEM_TYPE_LAST',
|
||||
'AMDSMI_MEM_TYPE_VIS_VRAM', 'AMDSMI_MEM_TYPE_VRAM',
|
||||
'AMDSMI_MM_UVD', 'AMDSMI_MM_VCE', 'AMDSMI_MM_VCN',
|
||||
'AMDSMI_MM__MAX', 'AMDSMI_PROCESSOR_TYPE_AMD_APU',
|
||||
'AMDSMI_MM__MAX', 'AMDSMI_POWER_CAP_TYPE_PPT0',
|
||||
'AMDSMI_POWER_CAP_TYPE_PPT1', 'AMDSMI_PROCESSOR_TYPE_AMD_APU',
|
||||
'AMDSMI_PROCESSOR_TYPE_AMD_CPU',
|
||||
'AMDSMI_PROCESSOR_TYPE_AMD_CPU_CORE',
|
||||
'AMDSMI_PROCESSOR_TYPE_AMD_GPU',
|
||||
@@ -3466,11 +3479,12 @@ __all__ = \
|
||||
'amdsmi_get_processor_handles_by_type',
|
||||
'amdsmi_get_processor_info', 'amdsmi_get_processor_type',
|
||||
'amdsmi_get_soc_pstate', 'amdsmi_get_socket_handles',
|
||||
'amdsmi_get_socket_info', 'amdsmi_get_temp_metric',
|
||||
'amdsmi_get_threads_per_core', 'amdsmi_get_utilization_count',
|
||||
'amdsmi_get_violation_status', 'amdsmi_get_xgmi_info',
|
||||
'amdsmi_get_xgmi_plpd', 'amdsmi_gpu_block_t',
|
||||
'amdsmi_gpu_cache_info_t', 'amdsmi_gpu_control_counter',
|
||||
'amdsmi_get_socket_info', 'amdsmi_get_supported_power_cap',
|
||||
'amdsmi_get_temp_metric', 'amdsmi_get_threads_per_core',
|
||||
'amdsmi_get_utilization_count', 'amdsmi_get_violation_status',
|
||||
'amdsmi_get_xgmi_info', 'amdsmi_get_xgmi_plpd',
|
||||
'amdsmi_gpu_block_t', 'amdsmi_gpu_cache_info_t',
|
||||
'amdsmi_gpu_control_counter',
|
||||
'amdsmi_gpu_counter_group_supported', 'amdsmi_gpu_create_counter',
|
||||
'amdsmi_gpu_destroy_counter', 'amdsmi_gpu_driver_reload',
|
||||
'amdsmi_gpu_metrics_t', 'amdsmi_gpu_read_counter',
|
||||
@@ -3489,8 +3503,8 @@ __all__ = \
|
||||
'amdsmi_od_vddc_point_t', 'amdsmi_od_volt_curve_t',
|
||||
'amdsmi_od_volt_freq_data_t', 'amdsmi_p2p_capability_t',
|
||||
'amdsmi_pcie_bandwidth_t', 'amdsmi_pcie_info_t',
|
||||
'amdsmi_power_cap_info_t', 'amdsmi_power_info_t',
|
||||
'amdsmi_power_profile_preset_masks_t',
|
||||
'amdsmi_power_cap_info_t', 'amdsmi_power_cap_type_t',
|
||||
'amdsmi_power_info_t', 'amdsmi_power_profile_preset_masks_t',
|
||||
'amdsmi_power_profile_status_t', 'amdsmi_proc_info_t',
|
||||
'amdsmi_process_handle_t', 'amdsmi_process_info_t',
|
||||
'amdsmi_processor_handle', 'amdsmi_range_t',
|
||||
|
||||
@@ -668,6 +668,17 @@ typedef enum {
|
||||
typedef rsmi_power_profile_preset_masks_t rsmi_power_profile_preset_masks;
|
||||
/// \endcond
|
||||
|
||||
/**
|
||||
* @brief Power Cap Package Power Tracking (PPT) type
|
||||
*/
|
||||
typedef enum {
|
||||
RSMI_POWER_CAP_TYPE_PPT0, //!< PPT0 power cap; lower limit, filtered input
|
||||
RSMI_POWER_CAP_TYPE_PPT1, //!< PPT1 power cap; higher limit, raw input
|
||||
} rsmi_power_cap_type_t;
|
||||
/// \cond Ignore in docs.
|
||||
typedef rsmi_power_cap_type_t rsmi_power_cap_type;
|
||||
/// \endcond
|
||||
|
||||
/**
|
||||
* @brief This enum is used to identify different GPU blocks.
|
||||
*/
|
||||
@@ -2510,6 +2521,9 @@ rsmi_dev_power_cap_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *cap);
|
||||
*
|
||||
* @param[in] dv_ind a device index
|
||||
*
|
||||
* @param[in] sensor_ind a 0-based sensor index. Normally, this will be 0.
|
||||
* If a device has more than one sensor, it could be greater than 0.
|
||||
*
|
||||
* @param[inout] default_cap a pointer to a uint64_t that indicates the default
|
||||
* power cap, in microwatts
|
||||
* If this parameter is nullptr, this function will return
|
||||
@@ -2523,7 +2537,7 @@ rsmi_dev_power_cap_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *cap);
|
||||
* @retval ::RSMI_STATUS_INVALID_ARGS the provided arguments are not valid
|
||||
*/
|
||||
rsmi_status_t
|
||||
rsmi_dev_power_cap_default_get(uint32_t dv_ind, uint64_t *default_cap);
|
||||
rsmi_dev_power_cap_default_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *default_cap);
|
||||
|
||||
/**
|
||||
* @brief Get the range of valid values for the power cap
|
||||
@@ -2612,6 +2626,29 @@ rsmi_dev_power_cap_set(uint32_t dv_ind, uint32_t sensor_ind, uint64_t cap);
|
||||
rsmi_status_t
|
||||
rsmi_dev_power_profile_set(uint32_t dv_ind, uint32_t reserved,
|
||||
rsmi_power_profile_preset_masks_t profile);
|
||||
|
||||
/**
|
||||
* @brief Query the supported power cap sensors and their types for a device.
|
||||
*
|
||||
* @ingroup tagPowerControl
|
||||
*
|
||||
* @platform{gpu_bm_linux} @platform{host}
|
||||
*
|
||||
* @details This function returns the number of supported power cap sensors for the given device,
|
||||
* including their sensor indices and types (e.g., PPT0, PPT1).
|
||||
*
|
||||
* @param[in] dv_ind A device index.
|
||||
* @param[out] sensor_count Pointer to a uint32_t that will be set to the number of supported sensors.
|
||||
* @param[out] sensor_inds Pointer to an array of uint32_t to be filled with sensor indices.
|
||||
* The array must be allocated by the caller with enough space.
|
||||
* @param[out] sensor_types Pointer to an array of rsmi_power_cap_type_t to be filled with sensor types.
|
||||
* The array must be allocated by the caller with enough space.
|
||||
*
|
||||
* @return ::rsmi_status_t | ::RSMI_STATUS_SUCCESS on success, non-zero on fail.
|
||||
*/
|
||||
rsmi_status_t
|
||||
rsmi_dev_supported_power_cap_get(uint32_t dv_ind, uint32_t *sensor_count,
|
||||
uint32_t *sensor_inds, rsmi_power_cap_type_t *sensor_types);
|
||||
/** @} */ // end of PowerCont
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@@ -3970,19 +3970,19 @@ rsmi_dev_energy_count_get(uint32_t dv_ind, uint64_t *power,
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_dev_power_cap_default_get(uint32_t dv_ind, uint64_t *default_cap) {
|
||||
rsmi_dev_power_cap_default_get(uint32_t dv_ind, uint32_t sensor_ind, uint64_t *default_cap) {
|
||||
TRY
|
||||
std::ostringstream ss;
|
||||
ss << __PRETTY_FUNCTION__ << "| ======= start =======";
|
||||
LOG_TRACE(ss);
|
||||
|
||||
uint32_t sensor_ind = 1; // power sysfs files have 1-based indices
|
||||
CHK_SUPPORT_SUBVAR_ONLY(default_cap, sensor_ind)
|
||||
uint32_t sensor_ind_adjust = sensor_ind + 1; // power sysfs files have 1-based indices
|
||||
CHK_SUPPORT_SUBVAR_ONLY(default_cap, sensor_ind_adjust)
|
||||
|
||||
rsmi_status_t ret;
|
||||
|
||||
DEVICE_MUTEX
|
||||
ret = get_dev_mon_value(amd::smi::kMonPowerCapDefault, dv_ind, sensor_ind, default_cap);
|
||||
ret = get_dev_mon_value(amd::smi::kMonPowerCapDefault, dv_ind, sensor_ind_adjust, default_cap);
|
||||
|
||||
return ret;
|
||||
CATCH
|
||||
@@ -4105,6 +4105,58 @@ rsmi_dev_power_profile_set(uint32_t dv_ind, uint32_t dummy,
|
||||
CATCH
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_dev_supported_power_cap_get(uint32_t dv_ind, uint32_t *sensor_count,
|
||||
uint32_t *sensor_inds, rsmi_power_cap_type_t *sensor_types) {
|
||||
TRY
|
||||
std::ostringstream ss;
|
||||
ss << __PRETTY_FUNCTION__ << "| ======= start =======";
|
||||
LOG_TRACE(ss);
|
||||
|
||||
if (!sensor_count || !sensor_inds || !sensor_types) {
|
||||
return RSMI_STATUS_INVALID_ARGS;
|
||||
}
|
||||
GET_DEV_FROM_INDX
|
||||
DEVICE_MUTEX
|
||||
|
||||
const uint8_t RSMI_MAX_POWER_CAP_SENSORS = 2;
|
||||
uint32_t sensor_count_local = 0;
|
||||
// try to read the power*_label file. If the read succeeds, that indicates that exists and update the sensor count and sensor indices accordingly
|
||||
for (uint32_t i = 0; i < RSMI_MAX_POWER_CAP_SENSORS; ++i) {
|
||||
// skip if monitor doesn't exist (e.g., in virtualized/partitioned environments)
|
||||
if (dev->monitor() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string val;
|
||||
// sensor_ind for power starts at 1
|
||||
uint32_t adjusted_index = i + 1;
|
||||
rsmi_status_t ret = amd::smi::ErrnoToRsmiStatus(dev->monitor()->readMonitor(amd::smi::kMonPowerLabel, adjusted_index, &val));
|
||||
if (ret != RSMI_STATUS_SUCCESS) {
|
||||
// if the read fails, then the sensor does not exist or is otherwise inaccessible for some reason
|
||||
continue;
|
||||
}
|
||||
// if val is PPT, then sensor_type is PPT0. If val is PPT1 then sensor_type is PPT1
|
||||
if (val == "PPT") {
|
||||
sensor_types[sensor_count_local] = RSMI_POWER_CAP_TYPE_PPT0;
|
||||
}
|
||||
else if (val == "PPT1") {
|
||||
sensor_types[sensor_count_local] = RSMI_POWER_CAP_TYPE_PPT1;
|
||||
}
|
||||
sensor_inds[sensor_count_local] = i;
|
||||
sensor_count_local++;
|
||||
}
|
||||
|
||||
// If no sensors were found, return not supported
|
||||
if (sensor_count_local == 0) {
|
||||
return RSMI_STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
*sensor_count = sensor_count_local;
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
CATCH
|
||||
}
|
||||
|
||||
rsmi_status_t
|
||||
rsmi_dev_memory_total_get(uint32_t dv_ind, rsmi_memory_type_t mem_type,
|
||||
uint64_t *total) {
|
||||
|
||||
@@ -3435,39 +3435,21 @@ amdsmi_get_power_cap_info(amdsmi_processor_handle processor_handle,
|
||||
|
||||
int power_cap = 0;
|
||||
int dpm = 0;
|
||||
auto smi_power_cap_status = smi_amdgpu_get_power_cap(gpudevice, &power_cap);
|
||||
if ((smi_power_cap_status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
|
||||
set_ret_success = true;
|
||||
info->power_cap = power_cap;
|
||||
auto smi_power_cap_status = rsmi_wrapper(rsmi_dev_power_cap_get, processor_handle, 0,
|
||||
sensor_ind, &(info->power_cap));
|
||||
|
||||
status = smi_amdgpu_get_ranges(gpudevice, AMDSMI_CLK_TYPE_GFX,
|
||||
NULL, NULL, &dpm, NULL);
|
||||
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
|
||||
set_ret_success = true;
|
||||
info->dpm_cap = dpm;
|
||||
|
||||
if (smi_power_cap_status != AMDSMI_STATUS_SUCCESS) {
|
||||
status = rsmi_wrapper(rsmi_dev_power_cap_get, processor_handle, 0,
|
||||
sensor_ind, &(info->power_cap));
|
||||
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
|
||||
set_ret_success = true;
|
||||
}
|
||||
|
||||
// Get other information from rocm-smi
|
||||
status = rsmi_wrapper(rsmi_dev_power_cap_default_get, processor_handle, 0,
|
||||
&(info->default_power_cap));
|
||||
|
||||
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
|
||||
set_ret_success = true;
|
||||
|
||||
sensor_ind, &(info->default_power_cap));
|
||||
|
||||
status = rsmi_wrapper(rsmi_dev_power_cap_range_get, processor_handle, 0,
|
||||
sensor_ind, &(info->max_power_cap), &(info->min_power_cap));
|
||||
|
||||
|
||||
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
|
||||
set_ret_success = true;
|
||||
|
||||
return set_ret_success ? AMDSMI_STATUS_SUCCESS : AMDSMI_STATUS_NOT_SUPPORTED;
|
||||
return smi_power_cap_status;
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
@@ -3478,6 +3460,19 @@ amdsmi_set_power_cap(amdsmi_processor_handle processor_handle,
|
||||
sensor_ind, cap);
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_supported_power_cap(amdsmi_processor_handle processor_handle, uint32_t *sensor_count,
|
||||
uint32_t *sensor_inds, amdsmi_power_cap_type_t *sensor_types) {
|
||||
AMDSMI_CHECK_INIT();
|
||||
if (!sensor_count || !sensor_inds || !sensor_types) {
|
||||
return AMDSMI_STATUS_INVAL;
|
||||
}
|
||||
|
||||
return rsmi_wrapper(rsmi_dev_supported_power_cap_get, processor_handle, 0,
|
||||
sensor_count, sensor_inds,
|
||||
reinterpret_cast<rsmi_power_cap_type_t*>(sensor_types));
|
||||
}
|
||||
|
||||
amdsmi_status_t
|
||||
amdsmi_get_gpu_power_profile_presets(amdsmi_processor_handle processor_handle,
|
||||
uint32_t sensor_ind,
|
||||
@@ -4482,7 +4477,8 @@ amdsmi_get_power_info(amdsmi_processor_handle processor_handle, amdsmi_power_inf
|
||||
}
|
||||
|
||||
int power_limit = 0;
|
||||
amdsmi_status_t status2 = smi_amdgpu_get_power_cap(gpu_device, &power_limit);
|
||||
// default the sensor_ind here to 0
|
||||
amdsmi_status_t status2 = smi_amdgpu_get_power_cap(gpu_device, 0, &power_limit);
|
||||
if (status2 == AMDSMI_STATUS_SUCCESS) {
|
||||
info->power_limit = power_limit;
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ amdsmi_status_t smi_amdgpu_get_board_info(amd::smi::AMDSmiGPUDevice* device, amd
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
amdsmi_status_t smi_amdgpu_get_power_cap(amd::smi::AMDSmiGPUDevice* device, int *cap)
|
||||
amdsmi_status_t smi_amdgpu_get_power_cap(amd::smi::AMDSmiGPUDevice* device, uint32_t sensor_ind, int *cap)
|
||||
{
|
||||
constexpr int DATA_SIZE = 16;
|
||||
char val[DATA_SIZE];
|
||||
@@ -257,7 +257,7 @@ amdsmi_status_t smi_amdgpu_get_power_cap(amd::smi::AMDSmiGPUDevice* device, int
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fullpath += "/power1_cap";
|
||||
fullpath += "/power" + std::to_string(sensor_ind + 1) + "_cap";
|
||||
std::ifstream file(fullpath.c_str(), std::ifstream::in);
|
||||
if (!file.is_open()) {
|
||||
return AMDSMI_STATUS_API_FAILED;
|
||||
|
||||
@@ -66,7 +66,7 @@ void TestPowerCapReadWrite::Close() {
|
||||
TestBase::Close();
|
||||
}
|
||||
|
||||
void TestPowerCapReadWrite::SetCheckPowerCap(std::string msg, uint32_t dv_ind, uint64_t &curr_cap,
|
||||
void TestPowerCapReadWrite::SetCheckPowerCap(std::string msg, uint32_t dv_ind, uint32_t sensor_ind, uint64_t &curr_cap,
|
||||
uint64_t &new_cap, amdsmi_status_t &ret) {
|
||||
amdsmi_status_t ret_expected;
|
||||
amdsmi_power_cap_info_t info;
|
||||
@@ -81,7 +81,7 @@ void TestPowerCapReadWrite::SetCheckPowerCap(std::string msg, uint32_t dv_ind, u
|
||||
std::cout << "[Before Set] Setting new cap to " << new_cap << "..." << std::endl;
|
||||
}
|
||||
start = clock();
|
||||
ret = amdsmi_set_power_cap(processor_handles_[dv_ind], 0, new_cap);
|
||||
ret = amdsmi_set_power_cap(processor_handles_[dv_ind], sensor_ind, new_cap);
|
||||
end = clock();
|
||||
cpu_time_used = (static_cast<double>(end - start)) * 1000000UL / CLOCKS_PER_SEC;
|
||||
|
||||
@@ -98,7 +98,7 @@ void TestPowerCapReadWrite::SetCheckPowerCap(std::string msg, uint32_t dv_ind, u
|
||||
return;
|
||||
}
|
||||
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], 0, &info);
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], sensor_ind, &info);
|
||||
CHK_ERR_ASRT(ret)
|
||||
|
||||
curr_cap = info.power_cap;
|
||||
@@ -133,170 +133,190 @@ void TestPowerCapReadWrite::Run(void) {
|
||||
for (uint32_t dv_ind = 0; dv_ind < num_monitor_devs(); ++dv_ind) {
|
||||
PrintDeviceHeader(processor_handles_[dv_ind]);
|
||||
|
||||
// verify amdsmi_get_supported_power_cap_info() works
|
||||
amdsmi_power_cap_info_t info;
|
||||
// Verify api support checking functionality is working
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], 0, nullptr);
|
||||
uint32_t sensor_count = 0;
|
||||
uint32_t sensor_inds[2];
|
||||
amdsmi_power_cap_type_t sensor_types[2];
|
||||
ret = amdsmi_get_supported_power_cap(processor_handles_[dv_ind], &sensor_count, sensor_inds, nullptr);
|
||||
ASSERT_EQ(ret, AMDSMI_STATUS_INVAL);
|
||||
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], 0, &info);
|
||||
if (ret == AMDSMI_STATUS_NOT_SUPPORTED) {
|
||||
std::cout << "\t**amdsmi_get_power_cap_info(): Not supported on this machine" << std::endl;
|
||||
ASSERT_EQ(ret, AMDSMI_STATUS_NOT_SUPPORTED);
|
||||
continue;
|
||||
}
|
||||
min_cap = info.min_power_cap;
|
||||
max_cap = info.max_power_cap;
|
||||
default_cap = info.default_power_cap;
|
||||
curr_cap = info.power_cap;
|
||||
orig_cap = curr_cap;
|
||||
|
||||
new_cap = (max_cap + min_cap)/2;
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "[Before Set] Default Power Cap: " << default_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Power Cap Range [max to min]: "
|
||||
<< max_cap << " uW to " << min_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Setting new cap to " << new_cap << "..." << std::endl;
|
||||
ret = amdsmi_get_supported_power_cap(processor_handles_[dv_ind], &sensor_count, sensor_inds, sensor_types);
|
||||
if (ret != AMDSMI_STATUS_SUCCESS) {
|
||||
ASSERT_EQ(ret, AMDSMI_STATUS_NOT_SUPPORTED);
|
||||
std::cout << "\t**amdsmi_get_supported_power_cap(): No supported Package Power Tracking Types on this machine" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if power cap is within the range
|
||||
// skip the test otherwise
|
||||
if (new_cap < min_cap || new_cap > max_cap || curr_cap == 0) {
|
||||
std::cout << "\t** Requested Power cap (" << new_cap
|
||||
<< " uW) cannot be changed for device #" << dv_ind << "."
|
||||
<< "\nCurrent Power Cap: " << curr_cap
|
||||
<< " uW, Min Power Cap: " << min_cap
|
||||
<< " uW, Max Power Cap: " << max_cap
|
||||
<< " uW.\n[WARN] If current power cap is 0 uW, this means we cannot change"
|
||||
<< " this device's current power cap. Skipping test for this device."
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
ret = AMDSMI_STATUS_SUCCESS;
|
||||
SetCheckPowerCap("Setting to Average Power Cap", dv_ind, curr_cap, new_cap, ret);
|
||||
if (ret == AMDSMI_STATUS_NOT_SUPPORTED) {
|
||||
continue;
|
||||
}
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
for (uint32_t i = 0; i < sensor_count; ++i) {
|
||||
std::cout << "\tPower Cap Sensor Index: " << sensor_inds[i]
|
||||
<< ", Type: ppt" << (sensor_types[i]) << std::endl;
|
||||
|
||||
if (min_cap > 0) {
|
||||
new_cap = min_cap;
|
||||
amdsmi_power_cap_info_t info;
|
||||
// Verify api support checking functionality is working
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], sensor_inds[i], nullptr);
|
||||
ASSERT_EQ(ret, AMDSMI_STATUS_INVAL);
|
||||
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], sensor_inds[i], &info);
|
||||
if (ret == AMDSMI_STATUS_NOT_SUPPORTED) {
|
||||
std::cout << "\t**amdsmi_get_power_cap_info(): Not supported on this machine" << std::endl;
|
||||
ASSERT_EQ(ret, AMDSMI_STATUS_NOT_SUPPORTED);
|
||||
continue;
|
||||
}
|
||||
min_cap = info.min_power_cap;
|
||||
max_cap = info.max_power_cap;
|
||||
default_cap = info.default_power_cap;
|
||||
curr_cap = info.power_cap;
|
||||
orig_cap = curr_cap;
|
||||
|
||||
new_cap = (max_cap + min_cap)/2;
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "[Before Set] Default Power Cap: " << default_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Power Cap Range [max to min]: "
|
||||
<< max_cap << " uW to " << min_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Setting new cap to " << new_cap << "..." << std::endl;
|
||||
}
|
||||
|
||||
// Check if power cap is within the range
|
||||
// skip the test otherwise
|
||||
if (new_cap < min_cap || new_cap > max_cap || curr_cap == 0) {
|
||||
std::cout << "\t** Requested Power cap (" << new_cap
|
||||
<< " uW) cannot be changed for device #" << dv_ind << "."
|
||||
<< "\nCurrent Power Cap: " << curr_cap
|
||||
<< " uW, Min Power Cap: " << min_cap
|
||||
<< " uW, Max Power Cap: " << max_cap
|
||||
<< " uW.\n[WARN] If current power cap is 0 uW, this means we cannot change"
|
||||
<< " this device's current power cap. Skipping test for this device."
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
ret = AMDSMI_STATUS_SUCCESS;
|
||||
SetCheckPowerCap("Setting to Min Power Cap", dv_ind, curr_cap, new_cap, ret);
|
||||
SetCheckPowerCap("Setting to Average Power Cap", dv_ind, sensor_inds[i], curr_cap, new_cap, ret);
|
||||
if (ret == AMDSMI_STATUS_NOT_SUPPORTED) {
|
||||
continue;
|
||||
}
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
|
||||
new_cap = uint64_t(min_cap - 1);
|
||||
if (min_cap > 0) {
|
||||
new_cap = min_cap;
|
||||
ret = AMDSMI_STATUS_SUCCESS;
|
||||
SetCheckPowerCap("Setting to Min Power Cap", dv_ind, sensor_inds[i], curr_cap, new_cap, ret);
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
|
||||
new_cap = uint64_t(min_cap - 1);
|
||||
ret = AMDSMI_STATUS_INVAL;
|
||||
SetCheckPowerCap("Setting to Min Power Cap - 1", dv_ind, sensor_inds[i], curr_cap, new_cap, ret);
|
||||
if (ret != AMDSMI_STATUS_INVAL) {
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
new_cap = uint64_t(static_cast<float>(min_cap) * 0.10F);
|
||||
ret = AMDSMI_STATUS_INVAL;
|
||||
SetCheckPowerCap("Setting to Min Power Cap * 0.10", dv_ind, sensor_inds[i], curr_cap, new_cap, ret);
|
||||
if (ret != AMDSMI_STATUS_INVAL) {
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap << " uW) is failed to set for "
|
||||
<< dv_ind << std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "\tPower cap requested is less than or equal to 0, skipping test for device #"
|
||||
<< dv_ind << std::endl;
|
||||
}
|
||||
|
||||
new_cap = max_cap;
|
||||
ret = AMDSMI_STATUS_SUCCESS;
|
||||
SetCheckPowerCap("Setting to Max Power Cap", dv_ind, sensor_inds[i], curr_cap, new_cap, ret);
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
|
||||
new_cap = uint64_t(max_cap + 1);
|
||||
ret = AMDSMI_STATUS_INVAL;
|
||||
SetCheckPowerCap("Setting to Min Power Cap - 1", dv_ind, curr_cap, new_cap, ret);
|
||||
SetCheckPowerCap("Setting to Max Power Cap + 1", dv_ind, sensor_inds[i], curr_cap, new_cap, ret);
|
||||
if (ret != AMDSMI_STATUS_INVAL) {
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
<< " uW) failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
new_cap = uint64_t(static_cast<float>(min_cap) * 0.10F);
|
||||
new_cap = uint64_t(max_cap * 10);
|
||||
ret = AMDSMI_STATUS_INVAL;
|
||||
SetCheckPowerCap("Setting to Min Power Cap * 0.10", dv_ind, curr_cap, new_cap, ret);
|
||||
SetCheckPowerCap("Setting to Max Power Cap * 10", dv_ind, sensor_inds[i], curr_cap, new_cap, ret);
|
||||
if (ret != AMDSMI_STATUS_INVAL) {
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap << " uW) is failed to set for "
|
||||
<< dv_ind << std::endl;
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "\tPower cap requested is less than or equal to 0, skipping test for device #"
|
||||
<< dv_ind << std::endl;
|
||||
}
|
||||
|
||||
new_cap = max_cap;
|
||||
ret = AMDSMI_STATUS_SUCCESS;
|
||||
SetCheckPowerCap("Setting to Max Power Cap", dv_ind, curr_cap, new_cap, ret);
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
}
|
||||
|
||||
new_cap = uint64_t(max_cap + 1);
|
||||
ret = AMDSMI_STATUS_INVAL;
|
||||
SetCheckPowerCap("Setting to Max Power Cap + 1", dv_ind, curr_cap, new_cap, ret);
|
||||
if (ret != AMDSMI_STATUS_INVAL) {
|
||||
// Reset to default power cap -> which is typically the same as the max power cap
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) failed to set for " << dv_ind << std::endl;
|
||||
std::cout << "Setting to default power Cap" << std::endl;
|
||||
std::cout << "[Before Set] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Default Power Cap (default_cap): "
|
||||
<< default_cap << "..." << std::endl;
|
||||
}
|
||||
}
|
||||
ret = amdsmi_set_power_cap(processor_handles_[dv_ind], sensor_inds[i], default_cap);
|
||||
CHK_ERR_ASRT(ret)
|
||||
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], sensor_inds[i], &info);
|
||||
CHK_ERR_ASRT(ret)
|
||||
curr_cap = info.power_cap;
|
||||
|
||||
new_cap = uint64_t(max_cap * 10);
|
||||
ret = AMDSMI_STATUS_INVAL;
|
||||
SetCheckPowerCap("Setting to Max Power Cap * 10", dv_ind, curr_cap, new_cap, ret);
|
||||
if (ret != AMDSMI_STATUS_INVAL) {
|
||||
IF_VERB(STANDARD) {
|
||||
if (!new_cap)
|
||||
std::cout << "\t** Power cap requested (" << new_cap
|
||||
<< " uW) is failed to set for " << dv_ind << std::endl;
|
||||
std::cout << "[After Set] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[After Set] Requested Power Cap (default_cap): " << default_cap << " uW"
|
||||
<< std::endl;
|
||||
std::cout << "[After Set] Power Cap Range [max to min]: " << max_cap << " uW to "
|
||||
<< min_cap << " uW" << std::endl;
|
||||
}
|
||||
// Confirm in watts the values are equal
|
||||
ASSERT_EQ(default_cap/MICRO_CONVERSION, curr_cap/MICRO_CONVERSION);
|
||||
|
||||
// Reset to system's original power cap before the test started
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "Resetting Power Cap to original power cap" << std::endl;
|
||||
std::cout << "[Before Reset] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Reset] Original Power Cap (orig_cap): "
|
||||
<< orig_cap << "..." << std::endl;
|
||||
}
|
||||
ret = amdsmi_set_power_cap(processor_handles_[dv_ind], sensor_inds[i], orig_cap);
|
||||
CHK_ERR_ASRT(ret)
|
||||
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], sensor_inds[i], &info);
|
||||
CHK_ERR_ASRT(ret)
|
||||
curr_cap = info.power_cap;
|
||||
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "[After Reset] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[After Reset] Requested Power Cap (orig_cap): " << orig_cap << " uW"
|
||||
<< std::endl;
|
||||
std::cout << "[After Reset] Power Cap Range [max to min]: " << max_cap << " uW to "
|
||||
<< min_cap << " uW" << std::endl;
|
||||
}
|
||||
|
||||
// Confirm in watts the values are equal
|
||||
ASSERT_EQ(orig_cap/MICRO_CONVERSION, curr_cap/MICRO_CONVERSION);
|
||||
}
|
||||
|
||||
// Reset to default power cap -> which is typically the same as the max power cap
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "Setting to default power Cap" << std::endl;
|
||||
std::cout << "[Before Set] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Set] Default Power Cap (default_cap): "
|
||||
<< default_cap << "..." << std::endl;
|
||||
}
|
||||
ret = amdsmi_set_power_cap(processor_handles_[dv_ind], 0, default_cap);
|
||||
CHK_ERR_ASRT(ret)
|
||||
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], 0, &info);
|
||||
CHK_ERR_ASRT(ret)
|
||||
curr_cap = info.power_cap;
|
||||
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "[After Set] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[After Set] Requested Power Cap (default_cap): " << default_cap << " uW"
|
||||
<< std::endl;
|
||||
std::cout << "[After Set] Power Cap Range [max to min]: " << max_cap << " uW to "
|
||||
<< min_cap << " uW" << std::endl;
|
||||
}
|
||||
// Confirm in watts the values are equal
|
||||
ASSERT_EQ(default_cap/MICRO_CONVERSION, curr_cap/MICRO_CONVERSION);
|
||||
|
||||
// Reset to system's original power cap before the test started
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "Resetting Power Cap to original power cap" << std::endl;
|
||||
std::cout << "[Before Reset] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[Before Reset] Original Power Cap (orig_cap): "
|
||||
<< orig_cap << "..." << std::endl;
|
||||
}
|
||||
ret = amdsmi_set_power_cap(processor_handles_[dv_ind], 0, orig_cap);
|
||||
CHK_ERR_ASRT(ret)
|
||||
|
||||
ret = amdsmi_get_power_cap_info(processor_handles_[dv_ind], 0, &info);
|
||||
CHK_ERR_ASRT(ret)
|
||||
curr_cap = info.power_cap;
|
||||
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "[After Reset] Current Power Cap: " << curr_cap << " uW" << std::endl;
|
||||
std::cout << "[After Reset] Requested Power Cap (orig_cap): " << orig_cap << " uW"
|
||||
<< std::endl;
|
||||
std::cout << "[After Reset] Power Cap Range [max to min]: " << max_cap << " uW to "
|
||||
<< min_cap << " uW" << std::endl;
|
||||
}
|
||||
|
||||
// Confirm in watts the values are equal
|
||||
ASSERT_EQ(orig_cap/MICRO_CONVERSION, curr_cap/MICRO_CONVERSION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class TestPowerCapReadWrite : public TestBase {
|
||||
public:
|
||||
TestPowerCapReadWrite();
|
||||
|
||||
void SetCheckPowerCap(std::string msg, uint32_t dv_ind, uint64_t &curr_cap,
|
||||
void SetCheckPowerCap(std::string msg, uint32_t dv_ind, uint32_t sensor_ind, uint64_t &curr_cap,
|
||||
uint64_t &new_cap, amdsmi_status_t &ret);
|
||||
|
||||
// @Brief: Destructor for test case of TestPowerCapReadWrite
|
||||
|
||||
@@ -733,7 +733,7 @@ class TestAmdSmiPythonInterface(unittest.TestCase):
|
||||
power_info['power_limit']))
|
||||
try:
|
||||
print("\n###Test amdsmi_get_power_cap_info \n")
|
||||
power_cap_info = amdsmi.amdsmi_get_power_cap_info(processors[i])
|
||||
power_cap_info = amdsmi.amdsmi_get_power_cap_info(processors[i], 0)
|
||||
except amdsmi.AmdSmiLibraryException as e:
|
||||
self._check_exception(e)
|
||||
continue
|
||||
|
||||
Odkázat v novém úkolu
Zablokovat Uživatele