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:
gabrpham_amdeng
2025-10-30 09:48:35 -05:00
odevzdal Arif, Maisam
rodič 4dfe74eb72
revize 18faddf6f3
17 změnil soubory, kde provedl 591 přidání a 245 odebrání
+33 -1
Zobrazit soubor
@@ -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
+95 -41
Zobrazit soubor
@@ -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:
+37 -13
Zobrazit soubor
@@ -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):
+28 -10
Zobrazit soubor
@@ -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"
+39 -1
Zobrazit soubor
@@ -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.
+33
Zobrazit soubor
@@ -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.
*
+1 -1
Zobrazit soubor
@@ -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);
+1
Zobrazit soubor
@@ -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
+29 -2
Zobrazit soubor
@@ -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.
+22 -8
Zobrazit soubor
@@ -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',
+38 -1
Zobrazit soubor
@@ -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
/*****************************************************************************/
+56 -4
Zobrazit soubor
@@ -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) {
+20 -24
Zobrazit soubor
@@ -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;
}
+2 -2
Zobrazit soubor
@@ -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;
+155 -135
Zobrazit soubor
@@ -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);
}
}
+1 -1
Zobrazit soubor
@@ -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
+1 -1
Zobrazit soubor
@@ -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