diff --git a/CHANGELOG.md b/CHANGELOG.md index da6bd5d8a6..95dccc8593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,26 @@ Full documentation for amd_smi_lib is available at [https://rocm.docs.amd.com/pr ***All information listed below is for reference and subject to change.*** +## amd_smi_lib for ROCm 6.2.1 + +### Additions + +- N/A + +### Optimizations + +- N/A + +### Fixes + +- **Fixed TypeError in `amd-smi process -G`**. + +- **Updated CLI error strings to handle empty and invalid GPU/CPU inputs**. + +### Known Issues + +- N/A + ## amd_smi_lib for ROCm 6.2.0 ### Additions diff --git a/CMakeLists.txt b/CMakeLists.txt index 882ab7a183..ba6636a658 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ find_program(GIT NAMES git) ## Setup the package version based on git tags. set(PKG_VERSION_GIT_TAG_PREFIX "amdsmi_pkg_ver") -get_package_version_number("24.6.2" ${PKG_VERSION_GIT_TAG_PREFIX} GIT) +get_package_version_number("24.6.3" ${PKG_VERSION_GIT_TAG_PREFIX} GIT) message("Package version: ${PKG_VERSION_STR}") set(${AMD_SMI_LIBS_TARGET}_VERSION_MAJOR "${CPACK_PACKAGE_VERSION_MAJOR}") set(${AMD_SMI_LIBS_TARGET}_VERSION_MINOR "${CPACK_PACKAGE_VERSION_MINOR}") @@ -286,6 +286,9 @@ set(CPACK_RPM_ASAN_PACKAGE_REQUIRES ${CPACK_RPM_PACKAGE_REQUIRES}) # don't terminate if bytecompile of python files fails set(CPACK_RPM_SPEC_MORE_DEFINE "%define _python_bytecompile_errors_terminate_build 0") +# Cpack converts !/usr/bin/env python3 to /usr/libexec/platform-python in RHEL8. +# prevent the BRP(buildroot policy) script from checking and modifying interpreter directives +string( APPEND CPACK_RPM_SPEC_MORE_DEFINE "\n%undefine __brp_mangle_shebangs") # Add rocm-core dependency if -DROCM_DEP_ROCMCORE=ON is passed if(ROCM_DEP_ROCMCORE) diff --git a/amdsmi_cli/README.md b/amdsmi_cli/README.md index 12af1461cc..7ae27c8df8 100644 --- a/amdsmi_cli/README.md +++ b/amdsmi_cli/README.md @@ -79,7 +79,7 @@ AMD-SMI reports the version and current platform detected when running the comma ~$ amd-smi usage: amd-smi [-h] ... -AMD System Management Interface | Version: 24.6.2.0 | ROCm version: 6.2.0 | Platform: Linux Baremetal +AMD System Management Interface | Version: 24.6.3.0 | ROCm version: 6.2.1 | Platform: Linux Baremetal options: -h, --help show this help message and exit diff --git a/amdsmi_cli/amdsmi_cli.py b/amdsmi_cli/amdsmi_cli.py index a5eeded872..0cf7aaa80b 100755 --- a/amdsmi_cli/amdsmi_cli.py +++ b/amdsmi_cli/amdsmi_cli.py @@ -24,19 +24,43 @@ import logging import sys +import os try: import argcomplete except ImportError: logging.debug("argcomplete module not found. Autocomplete will not work.") - -from amdsmi_commands import AMDSMICommands -from amdsmi_parser import AMDSMIParser -from amdsmi_logger import AMDSMILogger -import amdsmi_cli_exceptions -from amdsmi import amdsmi_interface -from amdsmi import amdsmi_exception - +from typing import TYPE_CHECKING +# only used for type checking +# pyright trips up and cannot find amdsmi scripts without it +if TYPE_CHECKING: + from amdsmi_commands import AMDSMICommands + from amdsmi_parser import AMDSMIParser + from amdsmi_logger import AMDSMILogger + import amdsmi_cli_exceptions + from amdsmi import amdsmi_interface + from amdsmi import amdsmi_exception +try: + from amdsmi_commands import AMDSMICommands + from amdsmi_parser import AMDSMIParser + from amdsmi_logger import AMDSMILogger + import amdsmi_cli_exceptions + from amdsmi import amdsmi_interface + from amdsmi import amdsmi_exception +except ImportError: + current_path = os.path.dirname(os.path.abspath(__file__)) + additional_path = f"{current_path}/../libexec/amdsmi_cli" + sys.path.append(additional_path) + try: + from amdsmi_commands import AMDSMICommands + from amdsmi_parser import AMDSMIParser + from amdsmi_logger import AMDSMILogger + import amdsmi_cli_exceptions + from amdsmi import amdsmi_interface + from amdsmi import amdsmi_exception + except ImportError: + print(f"Still couldn't import 'amdsmi related scripts'. Make sure it's installed in {additional_path}") + sys.exit(1) def _print_error(e, destination): if destination in ['stdout', 'json', 'csv']: diff --git a/amdsmi_cli/amdsmi_commands.py b/amdsmi_cli/amdsmi_commands.py index d376401ac9..9d4e7ebc07 100644 --- a/amdsmi_cli/amdsmi_commands.py +++ b/amdsmi_cli/amdsmi_commands.py @@ -422,11 +422,11 @@ class AMDSMICommands(): 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 = AMDSMIHelpers.convert_SI_unit(max_power_limit, AMDSMIHelpers.SI_Unit.MICRO) + 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 = AMDSMIHelpers.convert_SI_unit(min_power_limit, AMDSMIHelpers.SI_Unit.MICRO) + 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 = AMDSMIHelpers.convert_SI_unit(socket_power_limit, AMDSMIHelpers.SI_Unit.MICRO) + socket_power_limit = self.helpers.convert_SI_unit(socket_power_limit, AMDSMIHelpers.SI_Unit.MICRO) except amdsmi_exception.AmdSmiLibraryException as e: power_limit_error = True max_power_limit = "N/A" @@ -2679,14 +2679,15 @@ class AMDSMICommands(): # General and Engine to expose process_info values if args.general or args.engine: for process_info in filtered_process_values: - if args.general and args.engine: - del process_info['process_info']['memory_usage'] - elif args.general: - del process_info['process_info']['memory_usage'] - del process_info['process_info']['usage'] # Used in engine - elif args.engine: - del process_info['process_info']['memory_usage'] - del process_info['process_info']['mem_usage'] # Used in general + if not process_info['process_info'] == "N/A": + if args.general and args.engine: + del process_info['process_info']['memory_usage'] + elif args.general: + del process_info['process_info']['memory_usage'] + del process_info['process_info']['usage'] # Used in engine + elif args.engine: + del process_info['process_info']['memory_usage'] + del process_info['process_info']['mem_usage'] # Used in general # Filter out non specified pids if args.pid: @@ -3529,11 +3530,11 @@ class AMDSMICommands(): 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}") min_power_cap = power_cap_info["min_power_cap"] - min_power_cap = AMDSMIHelpers.convert_SI_unit(min_power_cap, AMDSMIHelpers.SI_Unit.MICRO) + min_power_cap = self.helpers.convert_SI_unit(min_power_cap, AMDSMIHelpers.SI_Unit.MICRO) max_power_cap = power_cap_info["max_power_cap"] - max_power_cap = AMDSMIHelpers.convert_SI_unit(max_power_cap, AMDSMIHelpers.SI_Unit.MICRO) + max_power_cap = self.helpers.convert_SI_unit(max_power_cap, AMDSMIHelpers.SI_Unit.MICRO) current_power_cap = power_cap_info["power_cap"] - current_power_cap = AMDSMIHelpers.convert_SI_unit(current_power_cap, AMDSMIHelpers.SI_Unit.MICRO) + current_power_cap = self.helpers.convert_SI_unit(current_power_cap, AMDSMIHelpers.SI_Unit.MICRO) except amdsmi_exception.AmdSmiLibraryException as e: raise ValueError(f"Unable to get power cap info from {gpu_string}") from e @@ -3541,7 +3542,7 @@ class AMDSMICommands(): self.logger.store_output(args.gpu, 'powercap', f"Power cap is already set to {args.power_cap}") elif args.power_cap >= min_power_cap and args.power_cap <= max_power_cap: try: - new_power_cap = AMDSMIHelpers.convert_SI_unit(args.power_cap, AMDSMIHelpers.SI_Unit.BASE, + new_power_cap = self.helpers.convert_SI_unit(args.power_cap, AMDSMIHelpers.SI_Unit.BASE, AMDSMIHelpers.SI_Unit.MICRO) amdsmi_interface.amdsmi_set_power_cap(args.gpu, 0, new_power_cap) except amdsmi_exception.AmdSmiLibraryException as e: @@ -3932,9 +3933,9 @@ class AMDSMICommands(): 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 = AMDSMIHelpers.convert_SI_unit(default_power_cap_in_w, AMDSMIHelpers.SI_Unit.MICRO) + 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 = AMDSMIHelpers.convert_SI_unit(current_power_cap_in_w, AMDSMIHelpers.SI_Unit.MICRO) + current_power_cap_in_w = self.helpers.convert_SI_unit(current_power_cap_in_w, AMDSMIHelpers.SI_Unit.MICRO) except amdsmi_exception.AmdSmiLibraryException as e: raise ValueError(f"Unable to get power cap info from {gpu_id}") from e @@ -3942,7 +3943,7 @@ class AMDSMICommands(): self.logger.store_output(args.gpu, 'powercap', f"Power cap is already set to {default_power_cap_in_w}") else: try: - default_power_cap_in_uw = AMDSMIHelpers.convert_SI_unit(default_power_cap_in_w, + 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) diff --git a/amdsmi_cli/amdsmi_helpers.py b/amdsmi_cli/amdsmi_helpers.py index b1e6308724..10c91824a3 100644 --- a/amdsmi_cli/amdsmi_helpers.py +++ b/amdsmi_cli/amdsmi_helpers.py @@ -28,9 +28,7 @@ import sys import time import re -from subprocess import run -from subprocess import PIPE, STDOUT -from typing import List +from typing import List, Union from enum import Enum from typing import Set @@ -333,7 +331,7 @@ class AMDSMIHelpers(): (False, valid_gpu_format, str): Return False, whether the format of the GPU input is valid, and the first input that failed to be converted """ if 'all' in gpu_selections: - return (True, amdsmi_interface.amdsmi_get_processor_handles()) + return True, True, amdsmi_interface.amdsmi_get_processor_handles() if isinstance(gpu_selections, str): gpu_selections = [gpu_selections] @@ -389,7 +387,7 @@ class AMDSMIHelpers(): (False, str): Return False, and the first input that failed to be converted """ if 'all' in cpu_selections: - return (True, amdsmi_interface.amdsmi_get_cpusocket_handles()) + return True, True, amdsmi_interface.amdsmi_get_cpusocket_handles() if isinstance(cpu_selections, str): cpu_selections = [cpu_selections] @@ -430,7 +428,7 @@ class AMDSMIHelpers(): (False, str): Return False, and the first input that failed to be converted """ if 'all' in core_selections: - return (True, amdsmi_interface.amdsmi_get_cpucore_handles()) + return True, True, amdsmi_interface.amdsmi_get_cpucore_handles() if isinstance(core_selections, str): core_selections = [core_selections] @@ -786,35 +784,24 @@ class AMDSMIHelpers(): MICRO = 0.000001 # 10^-6 NANO = 0.000000001 # 10^-9 - def convert_SI_unit(val: float, unit_in: SI_Unit, unit_out = SI_Unit.BASE) -> float: + def convert_SI_unit(self, val: Union[int, float], unit_in: SI_Unit, unit_out = SI_Unit.BASE) -> Union[int, float]: """This function will convert a value into another scientific (SI) unit. Defaults unit_out to SI_Unit.BASE - This function returns a float. params: - val: float unit to convert + val: int or float unit to convert unit_in: Requires using SI_Unit to set current value's SI unit (eg. SI_Unit.MICRO) unit_out - Requires using SI_Unit to set current value's SI unit default value is SI_Unit.BASE (eg. SI_Unit.MICRO) return: - float : converted SI unit of value requested + int or float : converted SI unit of value requested """ - return val * unit_in / unit_out - - def convert_SI_unit(val: int, unit_in: SI_Unit, unit_out=SI_Unit.BASE) -> int: - """This function will convert a value into another - scientific (SI) unit. Defaults unit_out to SI_Unit.BASE - This function returns a int. - - params: - val: int unit to convert - unit_in: Requires using SI_Unit to set current value's SI unit (eg. SI_Unit.MICRO) - unit_out - Requires using SI_Unit to set current value's SI unit - default value is SI_Unit.BASE (eg. SI_Unit.MICRO) - return: - int : converted SI unit of value requested - """ - return int(float(val) * unit_in / unit_out) + if isinstance(val, float): + return val * unit_in / unit_out + elif isinstance(val, int): + return int(float(val) * unit_in / unit_out) + else: + raise TypeError("val must be an int or float") def get_pci_device_ids(self) -> Set[str]: pci_devices_path = "/sys/bus/pci/devices" diff --git a/amdsmi_cli/amdsmi_parser.py b/amdsmi_cli/amdsmi_parser.py index 4f97ad8f7c..04721427db 100644 --- a/amdsmi_cli/amdsmi_parser.py +++ b/amdsmi_cli/amdsmi_parser.py @@ -171,6 +171,7 @@ class AMDSMIParser(argparse.ArgumentParser): else: raise amdsmi_cli_exceptions.AmdSmiInvalidParameterValueException(string_value, outputformat) + def _check_output_file_path(self): """ Argument action validator: Returns a path to a file from the output file path provided. @@ -375,6 +376,9 @@ class AMDSMIParser(argparse.ArgumentParser): def _validate_cpu_core(self, value): + if value == '': + outputformat = self.helpers.get_output_format() + raise amdsmi_cli_exceptions.AmdSmiMissingParameterValueException(value, outputformat) if isinstance(value, str): if value.lower() == "all": return value diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index ed6ff05aa1..0b62c6bc91 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = AMD SMI # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "24.6.2.0" +PROJECT_NUMBER = "24.6.3.0" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/docs/how-to/using-AMD-SMI-CLI-tool.md b/docs/how-to/using-AMD-SMI-CLI-tool.md index 4438c3219f..952d15bf49 100644 --- a/docs/how-to/using-AMD-SMI-CLI-tool.md +++ b/docs/how-to/using-AMD-SMI-CLI-tool.md @@ -6,7 +6,7 @@ AMD-SMI reports the version and current platform detected when running the comma ~$ amd-smi usage: amd-smi [-h] ... -AMD System Management Interface | Version: 24.6.2.0 | ROCm version: 6.2.0 | Platform: Linux Baremetal +AMD System Management Interface | Version: 24.6.3.0 | ROCm version: 6.2.1 | Platform: Linux Baremetal options: -h, --help show this help message and exit diff --git a/include/amd_smi/amdsmi.h b/include/amd_smi/amdsmi.h index 2ab20a5b92..5a3ff936ab 100644 --- a/include/amd_smi/amdsmi.h +++ b/include/amd_smi/amdsmi.h @@ -154,7 +154,7 @@ typedef enum { #define AMDSMI_LIB_VERSION_MAJOR 6 //! Minor version should be updated for each API change, but without changing headers -#define AMDSMI_LIB_VERSION_MINOR 2 +#define AMDSMI_LIB_VERSION_MINOR 3 //! Release version should be set to 0 as default and can be updated by the PMs for each CSP point release #define AMDSMI_LIB_VERSION_RELEASE 0 diff --git a/py-interface/amdsmi_exception.py b/py-interface/amdsmi_exception.py index ae07cdbe44..e77e9a9d88 100644 --- a/py-interface/amdsmi_exception.py +++ b/py-interface/amdsmi_exception.py @@ -107,6 +107,7 @@ class AmdSmiTimeoutException(AmdSmiLibraryException): class AmdSmiParameterException(AmdSmiException): def __init__(self, receivedValue, expectedType, msg=None): super().__init__(msg) + self.err_code = None self.actualType = type(receivedValue) self.expectedType = expectedType self.set_err_msg()