diff --git a/projects/amdsmi/.gitignore b/projects/amdsmi/.gitignore index 6f052a082c..9dae753e46 100644 --- a/projects/amdsmi/.gitignore +++ b/projects/amdsmi/.gitignore @@ -31,3 +31,6 @@ docBin/ # Simulated SYSFS - for early development or debug device/ + +# misc +esmi_ib_library/ diff --git a/projects/amdsmi/.gitmodules b/projects/amdsmi/.gitmodules deleted file mode 100644 index 78e8455b04..0000000000 --- a/projects/amdsmi/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "e_smi_library"] - path = e_smi_library - url = ssh://gerritgit/SYS-MGMT/er/HPC/e_smi_library - branch = amd-dev diff --git a/projects/amdsmi/CMakeLists.txt b/projects/amdsmi/CMakeLists.txt index c4b9421130..50683e7d81 100755 --- a/projects/amdsmi/CMakeLists.txt +++ b/projects/amdsmi/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("1.0.0" ${PKG_VERSION_GIT_TAG_PREFIX} GIT) +get_package_version_number("23.4.0" ${PKG_VERSION_GIT_TAG_PREFIX} GIT) message("Package version: ${PKG_VERSION_STR}") set(${AMD_SMI_LIBS_TARGET}_VERSION_MAJOR "${VERSION_MAJOR}") set(${AMD_SMI_LIBS_TARGET}_VERSION_MINOR "${VERSION_MINOR}") @@ -51,6 +51,7 @@ set(AMD_SMI_PACKAGE project(${AMD_SMI_LIBS_TARGET}) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) include(GNUInstallDirs) @@ -60,7 +61,7 @@ option(BUILD_WRAPPER "Rebuild AMDSMI-wrapper" OFF) option(BUILD_CLI "Build AMDSMI-CLI and install" ON) option(ENABLE_LDCONFIG "Set library links and caches using ldconfig." ON) option(ENABLE_ASAN_PACKAGING "" OFF) -option(ENABLE_ESMI_LIB "" OFF) +option(ENABLE_ESMI_LIB "" ON) # Set share path here because project name != amd_smi set(SHARE_INSTALL_PREFIX "share/${AMD_SMI}" CACHE STRING "Tests and Example install directory") @@ -95,16 +96,21 @@ set(AMDSMI_INC_DIR "${PROJECT_SOURCE_DIR}/include/amd_smi") set(ROCM_INC_DIR "${PROJECT_SOURCE_DIR}/rocm_smi/include/rocm_smi") set(SHR_MUTEX_DIR "${PROJECT_SOURCE_DIR}/third_party/shared_mutex") if(ENABLE_ESMI_LIB) -if((EXISTS ${PROJECT_SOURCE_DIR}/e_smi_library/src) AND (EXISTS ${PROJECT_SOURCE_DIR}/e_smi_library/src/e_smi_plat.c)) - set(ESMI_AVAILABLE TRUE) + if(NOT EXISTS ${PROJECT_SOURCE_DIR}/esmi_ib_library/src) + # TODO: use ExternalProject_Add instead or a submodule + # as of 2023.10.16 CI builds are broken with an updated submodule + execute_process(COMMAND git clone --depth=1 -b esmi_so_ver-3.0 https://github.com/amd/esmi_ib_library.git ${PROJECT_SOURCE_DIR}/esmi_ib_library) + endif() + if(NOT EXISTS ${PROJECT_SOURCE_DIR}/esmi_ib_library/include/asm/amd_hsmp.h) + file(DOWNLOAD + https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/plain/arch/x86/include/uapi/asm/amd_hsmp.h?h=review-ilpo + ${PROJECT_SOURCE_DIR}/esmi_ib_library/include/asm/amd_hsmp.h) + endif() add_definitions("-DENABLE_ESMI_LIB=1") -else() - message("E-smi source not found. Errors will be encountered during compilation!!!") -endif() -if(ESMI_AVAILABLE) - set(ESMI_INC_DIR "${PROJECT_SOURCE_DIR}/e_smi_library/include") - set(ESMI_SRC_DIR "${PROJECT_SOURCE_DIR}/e_smi_library/src") -endif() + set(ESMI_INC_DIR "${PROJECT_SOURCE_DIR}/esmi_ib_library/include") + set(ESMI_SRC_DIR "${PROJECT_SOURCE_DIR}/esmi_ib_library/src") + # esmi has a lot of write-strings warnings - silence them + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings") endif() pkg_check_modules(DRM REQUIRED libdrm) @@ -127,7 +133,7 @@ set(CMN_SRC_LIST "${ROCM_SRC_DIR}/rocm_smi_logger.cc" "${SHR_MUTEX_DIR}/shared_mutex.cc") -if(ESMI_AVAILABLE) +if(ENABLE_ESMI_LIB) list(APPEND CMN_SRC_LIST ${ESMI_SRC_DIR}/e_smi.c) list(APPEND CMN_SRC_LIST ${ESMI_SRC_DIR}/e_smi_monitor.c) list(APPEND CMN_SRC_LIST ${ESMI_SRC_DIR}/e_smi_plat.c) @@ -229,7 +235,7 @@ endif() #Debian package specific variables set(CPACK_DEBIAN_PACKAGE_PROVIDES "amd-smi") -set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "sudo, libdrm-dev") +set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "sudo, libdrm-dev, python3-yaml") set(CPACK_DEBIAN_ASAN_PACKAGE_RECOMMENDS ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) set(CPACK_DEBIAN_DEV_PACKAGE_RECOMMENDS ${CPACK_DEBIAN_PACKAGE_RECOMMENDS}) set(CPACK_DEBIAN_ASAN_PACKAGE_PROVIDES "${AMD_SMI_PACKAGE}-asan") diff --git a/projects/amdsmi/README.md b/projects/amdsmi/README.md index 7de1330296..4fa348f431 100755 --- a/projects/amdsmi/README.md +++ b/projects/amdsmi/README.md @@ -118,7 +118,7 @@ To build the documentation locally, run the commands below: ``` bash cd docs -pip3 install -r sphinx/requirements.txt +python3 -m pip install -r sphinx/requirements.txt python3 -m sphinx -T -E -b html -d _build/doctrees -D language=en . _build/html ``` @@ -132,7 +132,7 @@ For additional details, see the [ROCm Contributing Guide](https://rocm.docs.amd. ### Requirements * python 3.7+ 64-bit -* driver must be loaded for amdsmi_init() to pass +* amdgpu driver must be loaded for amdsmi_init() to pass ### CLI Installation @@ -147,7 +147,7 @@ python3 -m pip uninstall amdsmi * Install amd-smi-lib package through package manager * amd-smi --help -#### Install Example for Ubuntu 22.04 +### Install Example for Ubuntu 22.04 ``` bash python3 -m pip list | grep amd @@ -156,7 +156,7 @@ apt install amd-smi-lib amd-smi --help ``` -### Python Library Installation +### Python Development Library Installation This option is for users who want to develop their own scripts using amd-smi's python library @@ -171,11 +171,18 @@ Verify that your python version is 3.7+ to install the python library Warning: this will take precedence over the cli tool's library install, to avoid issues run these steps after every amd-smi-lib update. -#### RHEL 8 & SLES 15 +#### Older RPM Packaged OS's -The default python versions in RHEL 8 and SLES 15 are 3.6.8 and 3.6.15 +The default python versions in older RPM based OS's are not gauranteed to have the minium version. -While the CLI will work with these python versions, to install the python library you need to upgrade to python 3.7+ +For example RHEL 8 and SLES 15 are 3.6.8 and 3.6.15 . You will need to ensure the latest yaml package is installed ( pyyaml >= 5.1) pyyaml is installed to your pip instance: + +``` bash +python3 -m pip install pyyaml +amd-smi list +``` + +While the CLI will work with these older python versions, to install the python development library you need to upgrade to python 3.7+ #### Python Library Install Example for Ubuntu 22.04 @@ -203,15 +210,14 @@ The python wrapper (binding) is an auto-generated file `py-interface/amdsmi_wrap Wrapper should be re-generated on each C++ API change, by doing: ```bash -cmake .. -DBUILD_WRAPPER=on -make python_wrapper # or simply 'make' +./update_wrapper.sh ``` After this command, the file in `py-interface/amdsmi_wrapper.py` will be automatically updated on each compile. -Note: To be able to re-generate python wrapper you need several tools installed on your system: clang-14, clang-format, libclang-dev, and ***python3.7 or newer***. +Note: To be able to re-generate python wrapper you need **docker** installed. -Note: python_wrapper is NOT automatically re-generated. You must run `cmake` with `-DBUILD_WRAPPER=on` argument. +Note: python_wrapper is NOT automatically re-generated. You must run `./update_wrapper.sh`. ## Building AMD SMI @@ -219,14 +225,14 @@ Note: python_wrapper is NOT automatically re-generated. You must run `cmake` wit In order to build the AMD SMI library, the following components are required. Note that the software versions listed are what was used in development. Earlier versions are not guaranteed to work: -* CMake (v3.11.0) - `pip3 install cmake` +* CMake (v3.14.0) - `python3 -m pip install cmake` * g++ (5.4.0) In order to build the AMD SMI python package, the following components are required: * clang (14.0 or above) -* python (3.6 or above) -* virtualenv - `pip3 install virtualenv` +* python (3.7 or above) +* virtualenv - `python3 -m pip install virtualenv` In order to build the latest documentation, the following are required: diff --git a/projects/amdsmi/amdsmi_cli/README.md b/projects/amdsmi/amdsmi_cli/README.md index ccc75b416a..45281d39f1 100644 --- a/projects/amdsmi/amdsmi_cli/README.md +++ b/projects/amdsmi/amdsmi_cli/README.md @@ -26,7 +26,7 @@ python3 -m pip uninstall amdsmi * Install amd-smi-lib package through package manager * amd-smi --help -#### Install Example for Ubuntu 22.04 +### Install Example for Ubuntu 22.04 ``` bash python3 -m pip list | grep amd @@ -35,7 +35,7 @@ apt install amd-smi-lib amd-smi --help ``` -### Python Library Installation +### Python Development Library Installation This option is for users who want to develop their own scripts using amd-smi's python library @@ -50,11 +50,18 @@ Verify that your python version is 3.7+ to install the python library Warning: this will take precedence over the cli tool's library install, to avoid issues run these steps after every amd-smi-lib update. -#### RHEL 8 & SLES 15 +#### Older RPM Packaged OS's -The default python versions in RHEL 8 and SLES 15 are 3.6.8 and 3.6.15 +The default python versions in older RPM based OS's are not gauranteed to have the minium version. -While the CLI will work with these python versions, to install the python library you need to upgrade to python 3.7+ +For example RHEL 8 and SLES 15 are 3.6.8 and 3.6.15 . You will need to ensure the latest yaml package is installed ( pyyaml >= 5.1) pyyaml is installed to your pip instance: + +``` bash +python3 -m pip install pyyaml +amd-smi list +``` + +While the CLI will work with these older python versions, to install the python development library you need to upgrade to python 3.7+ #### Python Library Install Example for Ubuntu 22.04 @@ -67,7 +74,7 @@ python3 -m pip install --user . ``` ``` bash -python3 +~$ python3 Python 3.8.10 (default, May 26 2023, 14:05:08) [GCC 9.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. @@ -80,27 +87,27 @@ Type "help", "copyright", "credits" or "license" for more information. amd-smi will report the version and current platform detected when running the command without arguments: ``` bash -amd-smi +~$ amd-smi usage: amd-smi [-h] ... -AMD System Management Interface | Version: 23.3.1.0 | Platform: Linux Baremetal +AMD System Management Interface | Version: 23.4.0.0 | Platform: Linux Baremetal optional arguments: - -h, --help show this help message and exit + -h, --help show this help message and exit AMD-SMI Commands: - Descriptions: - version Display version information - list List GPU information - static Gets static information about the specified GPU - firmware Gets firmware information about the specified GPU - bad-pages - Gets bad page information about the specified GPU - metric Gets metric/performance information about the specified GPU - process Lists general process information running on the specified GPU - topology Displays topology information of the devices - set Set options for devices - reset Reset options for devices + Descriptions: + version Display version information + list List GPU information + static Gets static information about the specified GPU + firmware (ucode) Gets firmware information about the specified GPU + bad-pages Gets bad page information about the specified GPU + metric Gets metric/performance information about the specified GPU + process Lists general process information running on the specified GPU + event Displays event information for the given GPU + topology Displays topology information of the devices + set Set options for devices + reset Reset options for devices ``` More detailed verison information is available from `amd-smi version` @@ -112,255 +119,289 @@ Each command will have detailed information via `amd-smi [command] --help` For convenience, here is the help output for each command ``` bash -usage: amd-smi list [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-g GPU [GPU ...]] +~$ amd-smi list --help +usage: amd-smi list [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] + [-g GPU [GPU ...]] -Lists all the devices on the system and the links between devices. -Lists all the sockets and for each socket, GPUs and/or CPUs associated to -that socket alongside some basic information for each device. -In virtualization environments, it can also list VFs associated to each +Lists all the devices on the system and the links between devices. +Lists all the sockets and for each socket, GPUs and/or CPUs associated to +that socket alongside some basic information for each device. +In virtualization environments, it can also list VFs associated to each GPU with some basic information for each VF. optional arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL +``` + +```bash +~$ amd-smi static --help +usage: amd-smi static [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] + [-g GPU [GPU ...]] [-a] [-b] [-V] [-d] [-v] [-c] [-B] [-r] [-p] [-l] + [-u] + +If no GPU is specified, returns static information for all GPUs on the system. +If no static argument is provided, all static information will be displayed. + +Static Arguments: + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices + -a, --asic All asic information + -b, --bus All bus information + -V, --vbios All video bios information (if available) + -d, --driver Displays driver version + -v, --vram All vram information + -c, --cache All cache information + -B, --board All board information + -r, --ras Displays RAS features information + -p, --partition Partition information + -l, --limit All limit metric values (i.e. power and thermal limits) + -u, --numa All numa node information + +Command Modifiers: + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL ``` ``` bash -amd-smi firmware --help -usage: amd-smi firmware [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] +~$ amd-smi firmware --help +usage: amd-smi firmware [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] [-g GPU [GPU ...]] [-f] If no GPU is specified, return firmware information for all GPUs on the system. Firmware Arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -f, --ucode-list, --fw-list All FW list information + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices + -f, --ucode-list, --fw-list All FW list information Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL ``` ```bash -amd-smi static --help -usage: amd-smi static [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-g GPU [GPU ...]] - [-a] [-b] [-V] [-d] [-r] [-v] [-B] [-l] [-u] - -If no GPU is specified, returns static information for all GPUs on the system. -If no static argument is provided, all static information will be displayed. - -Static Arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -a, --asic All asic information - -b, --bus All bus information - -V, --vbios All video bios information (if available) - -d, --driver Displays driver version - -r, --ras Displays RAS features information - -v, --vram All vram information - -B, --board All board information - -l, --limit All limit metric values (i.e. power and thermal limits) - -u, --numa All numa node information - -Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). -``` - -```bash -amd-smi bad-pages --help -usage: amd-smi bad-pages [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] +~$ amd-smi bad-pages --help +usage: amd-smi bad-pages [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] [-g GPU [GPU ...]] [-p] [-r] [-u] If no GPU is specified, return bad page information for all GPUs on the system. Bad Pages Arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -p, --pending Displays all pending retired pages - -r, --retired Displays retired pages - -u, --un-res Displays unreservable pages + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices + -p, --pending Displays all pending retired pages + -r, --retired Displays retired pages + -u, --un-res Displays unreservable pages Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL ``` ```bash -amd-smi metric --help -usage: amd-smi metric [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-g GPU [GPU ...]] - [-w loop_time] [-W total_loop_time] [-i number_of_iterations] [-m] - [-u] [-p] [-c] [-t] [-e] [-k] [-P] [-f] [-C] [-o] [-l] [-x] [-E] +~$ amd-smi metric --help +usage: amd-smi metric [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] + [-g GPU [GPU ...]] [-w INTERVAL] [-W TIME] [-i ITERATIONS] [-m] [-u] + [-p] [-c] [-t] [-e] [-k] [-P] [-f] [-C] [-o] [-l] [-x] [-E] -If no GPU is specified, returns metric information for all GPUs on the system. +If no GPU is specified, returns metric information for all GPUs on the system. If no metric argument is provided all metric information will be displayed. Metric arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -w loop_time, --watch loop_time Reprint the command in a loop of Interval seconds - -W total_loop_time, --watch_time total_loop_time The total time to watch the given command - -i number_of_iterations, --iterations number_of_iterations Total number of iterations to loop on the given command - -m, --mem-usage Memory usage per block - -u, --usage Displays engine usage information - -p, --power Current power usage - -c, --clock Average, max, and current clock frequencies - -t, --temperature Current temperatures - -e, --ecc Number of ECC errors - -k, --ecc-block Number of ECC errors per block - -P, --pcie Current PCIe speed, width, and replay count - -f, --fan Current fan speed - -C, --voltage-curve Display voltage curve - -o, --overdrive Current GPU clock overdrive level - -l, --perf-level Current DPM performance level - -x, --xgmi-err XGMI error information since last read - -E, --energy Amount of energy consumed + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices + -w, --watch INTERVAL Reprint the command in a loop of INTERVAL seconds + -W, --watch_time TIME The total TIME to watch the given command + -i, --iterations ITERATIONS Total number of ITERATIONS to loop on the given command + -m, --mem-usage Memory usage per block + -u, --usage Displays engine usage information + -p, --power Current power usage + -c, --clock Average, max, and current clock frequencies + -t, --temperature Current temperatures + -e, --ecc Total number of ECC errors + -k, --ecc-block Number of ECC errors per block + -P, --pcie Current PCIe speed, width, and replay count + -f, --fan Current fan speed + -C, --voltage-curve Display voltage curve + -o, --overdrive Current GPU clock overdrive level + -l, --perf-level Current DPM performance level + -x, --xgmi-err XGMI error information since last read + -E, --energy Amount of energy consumed Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL ``` ```bash -amd-smi process --help -usage: amd-smi process [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-g GPU [GPU ...]] - [-w loop_time] [-W total_loop_time] [-i number_of_iterations] [-G] +~$ amd-smi process --help +usage: amd-smi process [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] + [-g GPU [GPU ...]] [-w INTERVAL] [-W TIME] [-i ITERATIONS] [-G] [-e] [-p PID] [-n NAME] If no GPU is specified, returns information for all GPUs on the system. If no process argument is provided all process information will be displayed. Process arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -w loop_time, --watch loop_time Reprint the command in a loop of Interval seconds - -W total_loop_time, --watch_time total_loop_time The total time to watch the given command - -i number_of_iterations, --iterations number_of_iterations Total number of iterations to loop on the given command - -G, --general pid, process name, memory usage - -e, --engine All engine usages - -p PID, --pid PID Gets all process information about the specified process based on Process ID - -n NAME, --name NAME Gets all process information about the specified process based on Process Name. - If multiple processes have the same name information is returned for all of them. + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices + -w, --watch INTERVAL Reprint the command in a loop of INTERVAL seconds + -W, --watch_time TIME The total TIME to watch the given command + -i, --iterations ITERATIONS Total number of ITERATIONS to loop on the given command + -G, --general pid, process name, memory usage + -e, --engine All engine usages + -p, --pid PID Gets all process information about the specified process based on Process ID + -n, --name NAME Gets all process information about the specified process based on Process Name. + If multiple processes have the same name information is returned for all of them. Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL ``` ```bash -amd-smi topology --help -usage: amd-smi topology [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] +~$ amd-smi event --help +usage: amd-smi event [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] + [-g GPU [GPU ...]] + +If no GPU is specified, returns event information for all GPUs on the system. + +Event Arguments: + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices + +Command Modifiers: + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL +``` + +```bash +~$ amd-smi topology --help +usage: amd-smi topology [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] [-g GPU [GPU ...]] [-a] [-w] [-o] [-t] [-b] If no GPU is specified, returns information for all GPUs on the system. If no topology argument is provided all topology information will be displayed. Topology arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -a, --access Displays link accessibility between GPUs - -w, --weight Displays relative weight between GPUs - -o, --hops Displays the number of hops between GPUs - -t, --link-type Displays the link type between GPUs - -b, --numa-bw Display max and min bandwidth between nodes + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID:0 | BDF:0000:23:00.0 | UUID:ffff73bf-0000-1000-80ff-ffffffffffff + all | Selects all devices + -a, --access Displays link accessibility between GPUs + -w, --weight Displays relative weight between GPUs + -o, --hops Displays the number of hops between GPUs + -t, --link-type Displays the link type between GPUs + -b, --numa-bw Display max and min bandwidth between nodes Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL + ``` ```bash -amd-smi set --help -usage: amd-smi set [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] -g GPU [GPU ...] - [-f %] [-l LEVEL] [-P SETPROFILE] [-d SCLKMAX] +~$ amd-smi set --help +usage: amd-smi set [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] -g GPU [GPU ...] + [-f %] [-l LEVEL] [-P SETPROFILE] [-d SCLKMAX] [-C PARTITION] + [-M PARTITION] A GPU must be specified to set a configuration. A set argument must be provided; Multiple set arguments are accepted Set Arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -f %, --fan % Sets GPU fan speed (0-255 or 0-100%) - -l LEVEL, --perflevel LEVEL Sets performance level - -P SETPROFILE, --profile SETPROFILE Set power profile level (#) or a quoted string of custom profile attributes - -d SCLKMAX, --perfdeterminism SCLKMAX Sets GPU clock frequency limit and performance level to determinism to get minimal performance variation + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID: 0 | BDF: 0000:23:00.0 | UUID: c4ff73bf-0000-1000-802e-0812b504ed69 + all | Selects all devices + -f, --fan % Set GPU fan speed (0-255 or 0-100%) + -l, --perf-level LEVEL Set performance level + -P, --profile SETPROFILE Set power profile level (#) or a quoted string of custom profile attributes + -d, --perf-determinism SCLKMAX Set GPU clock frequency limit and performance level to determinism to get minimal performance variation + -C, --compute-partition PARTITION Set one of the following the compute partition modes: + CPX, SPX, DPX, TPX, QPX + -M, --memory-partition PARTITION Set one of the following the memory partition modes: + NPS1, NPS2, NPS4, NPS8 Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL ``` ```bash -amd-smi reset --help -usage: amd-smi reset [-h] [--json | --csv] [--file FILE] - [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] -g GPU [GPU ...] - [-G] [-c] [-f] [-p] [-x] [-d] +~$ amd-smi reset --help +usage: amd-smi reset [-h] [--json | --csv] [--file FILE] [--loglevel LEVEL] -g GPU + [GPU ...] [-G] [-c] [-f] [-p] [-x] [-d] [-C] [-M] A GPU must be specified to reset a configuration. A reset argument must be provided; Multiple reset arguments are accepted Reset Arguments: - -h, --help show this help message and exit - -g GPU [GPU ...], --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: - ID:0 | BDF:0000:23:00.0 | UUID:c4ff73bf-0000-1000-80ff-ffffffffffff - all | Selects all devices - -G, --gpureset Reset the specified GPU - -c, --clocks Reset clocks and overdrive to default - -f, --fans Reset fans to automatic (driver) control - -p, --profile Reset power profile back to default - -x, --xgmierr Reset XGMI error counts - -d, --perfdeterminism Disable performance determinism + -h, --help show this help message and exit + -g, --gpu GPU [GPU ...] Select a GPU ID, BDF, or UUID from the possible choices: + ID: 0 | BDF: 0000:23:00.0 | UUID: c4ff73bf-0000-1000-802e-0812b504ed69 + all | Selects all devices + -G, --gpureset Reset the specified GPU + -c, --clocks Reset clocks and overdrive to default + -f, --fans Reset fans to automatic (driver) control + -p, --profile Reset power profile back to default + -x, --xgmierr Reset XGMI error counts + -d, --perf-determinism Disable performance determinism + -C, --compute-partition Reset compute partitions on the specified GPU + -M, --memory-partition Reset memory partitions on the specified GPU Command Modifiers: - --json Displays output in JSON format (human readable by default). - --csv Displays output in CSV format (human readable by default). - --file FILE Saves output into a file on the provided path (stdout by default). - --loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL} Set the logging level for the parser commands (ERROR by default). + --json Displays output in JSON format (human readable by default). + --csv Displays output in CSV format (human readable by default). + --file FILE Saves output into a file on the provided path (stdout by default). + --loglevel LEVEL Set the logging level from the possible choices: + DEBUG, INFO, WARNING, ERROR, CRITICAL ``` ### Example output from amd-smi static @@ -368,16 +409,17 @@ Command Modifiers: Here is some example output from the tool: ```bash -amd-smi static +~$ amd-smi static GPU: 0 ASIC: MARKET_NAME: 0x73bf VENDOR_ID: 0x1002 - VENDOR_NAME: Advanced Micro Devices, Inc. [AMD/ATI] + VENDOR_NAME: Advanced Micro Devices Inc. [AMD/ATI] SUBVENDOR_ID: 0 DEVICE_ID: 0x73bf REV_ID: 0xc3 ASIC_SERIAL: 0xffffffffffffffff + XGMI_PHYSICAL_ID: N/A BUS: BDF: 0000:23:00.0 MAX_PCIE_SPEED: 16 GT/s @@ -390,9 +432,11 @@ VBIOS: PART_NUMBER: 113-D4120900-101 VERSION: 020.001.000.038.015720 BOARD: - SERIAL_NUMBER: 0xffffffffffffffff - MODEL_NUMBER: ffffffffffffffff - PRODUCT_NAME: ffffffffffffffff + MODEL_NUMBER: N/A + PRODUCT_SERIAL: 0 + FRU_ID: N/A + MANUFACTURER_NAME: N/A + PRODUCT_NAME: N/A LIMIT: MAX_POWER: 203 W CURRENT_POWER: 203 W @@ -403,16 +447,30 @@ LIMIT: SHUTDOWN_HOTSPOT_TEMPERATURE: 115 °C SHUTDOWN_VRAM_TEMPERATURE: 105 °C DRIVER: + DRIVER_NAME: amdgpu DRIVER_VERSION: 6.1.10 DRIVER_DATE: 2015/01/01 00:00 -RAS: N/A VRAM: - VRAM_TYPE: MAX + VRAM_TYPE: GDDR6 VRAM_VENDOR: SAMSUNG VRAM_SIZE_MB: 16368 MB +CACHE: + CACHE 0: + CACHE_SIZE: 16 KB + CACHE_LEVEL: 1 +RAS: + EEPROM_VERSION: N/A + PARITY_SCHEMA: N/A + SINGLE_BIT_SCHEMA: N/A + DOUBLE_BIT_SCHEMA: N/A + POISON_SCHEMA: N/A + ECC_BLOCK_STATE: N/A +PARTITION: + COMPUTE_PARTITION: N/A + MEMORY_PARTITION: N/A NUMA: NODE: 0 - AFFINITY: -1 + AFFINITY: NONE ``` ## Disclaimer diff --git a/projects/amdsmi/amdsmi_cli/__init__.py b/projects/amdsmi/amdsmi_cli/__init__.py index 457ded273b..608c46bbe2 100644 --- a/projects/amdsmi/amdsmi_cli/__init__.py +++ b/projects/amdsmi/amdsmi_cli/__init__.py @@ -1 +1 @@ -__version__ = "23.3.1.0" +__version__ = "23.4.0.0" diff --git a/projects/amdsmi/amdsmi_cli/_version.py b/projects/amdsmi/amdsmi_cli/_version.py index 457ded273b..608c46bbe2 100644 --- a/projects/amdsmi/amdsmi_cli/_version.py +++ b/projects/amdsmi/amdsmi_cli/_version.py @@ -1 +1 @@ -__version__ = "23.3.1.0" +__version__ = "23.4.0.0" diff --git a/projects/amdsmi/amdsmi_cli/amdsmi_cli_exceptions.py b/projects/amdsmi/amdsmi_cli/amdsmi_cli_exceptions.py index c43f37379a..e42fc9f9f2 100644 --- a/projects/amdsmi/amdsmi_cli/amdsmi_cli_exceptions.py +++ b/projects/amdsmi/amdsmi_cli/amdsmi_cli_exceptions.py @@ -22,6 +22,7 @@ import json + AMDSMI_ERROR_MESSAGES = { 0: "Sucess", 1: "Invalid parameters", @@ -60,6 +61,7 @@ def _get_error_message(error_code): return AMDSMI_ERROR_MESSAGES[abs(error_code)] return "Generic error" + class AmdSmiException(Exception): def __init__(self): self.json_message = {} @@ -117,13 +119,14 @@ class AmdSmiDeviceNotFoundException(AmdSmiException): self.command = command self.output_format = outputformat - common_message = f"GPU Device with GPU_INDEX '{self.command}' cannot be found on the system." + common_message = f"Can not find a GPU with the corresponding identifier: '{self.command}'" self.json_message["error"] = common_message self.json_message["code"] = self.value self.csv_message = f"error,code\n{common_message}, {self.value}" self.stdout_message = f"{common_message} Error code: {self.value}" + class AmdSmiInvalidFilePathException(AmdSmiException): def __init__(self, command, outputformat): super().__init__() @@ -183,6 +186,22 @@ class AmdSmiParameterNotSupportedException(AmdSmiException): self.csv_message = f"error,code\n{common_message}, {self.value}" self.stdout_message = f"{common_message} Error code: {self.value}" + +class AmdSmiRequiredCommandException(AmdSmiException): + def __init__(self, command, outputformat): + super().__init__() + self.value = -9 + self.command = command + self.output_format = outputformat + + common_message = f"Command '{self.command}' requires a target argument. Run '--help' for more info." + + self.json_message["error"] = common_message + self.json_message["code"] = self.value + self.csv_message = f"error,code\n{common_message}, {self.value}" + self.stdout_message = f"{common_message} Error code: {self.value}" + + class AmdSmiUnknownErrorException(AmdSmiException): def __init__(self, command, outputformat): super().__init__() @@ -197,6 +216,7 @@ class AmdSmiUnknownErrorException(AmdSmiException): self.csv_message = f"error,code\n{common_message}, {self.value}" self.stdout_message = f"{common_message} Error code: {self.value}" + class AmdSmiAMDSMIErrorException(AmdSmiException): def __init__(self, outputformat, error_code): super().__init__() diff --git a/projects/amdsmi/amdsmi_cli/amdsmi_commands.py b/projects/amdsmi/amdsmi_cli/amdsmi_commands.py index b598a15d5c..e58adc7981 100644 --- a/projects/amdsmi/amdsmi_cli/amdsmi_commands.py +++ b/projects/amdsmi/amdsmi_cli/amdsmi_commands.py @@ -20,6 +20,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +import argparse import logging import sys import threading @@ -28,6 +29,7 @@ import time from _version import __version__ from amdsmi_helpers import AMDSMIHelpers from amdsmi_logger import AMDSMILogger +from amdsmi_cli_exceptions import AmdSmiRequiredCommandException from amdsmi import amdsmi_interface from amdsmi import amdsmi_exception @@ -130,8 +132,8 @@ class AMDSMICommands(): def static(self, args, multiple_devices=False, gpu=None, asic=None, - bus=None, vbios=None, limit=None, driver=None, - ras=None, board=None, numa=None, vram=None): + bus=None, vbios=None, limit=None, driver=None, ras=None, + board=None, numa=None, vram=None, cache=None, partition=None): """Get Static information for target gpu Args: @@ -147,6 +149,8 @@ class AMDSMICommands(): board (bool, optional): Value override for args.board. Defaults to None. numa (bool, optional): Value override for args.numa. Defaults to None. vram (bool, optional): Value override for args.vram. Defaults to None. + cache (bool, optional): Value override for args.cache. Defaults to None. + partition (bool, optional): Value override for args.partition. Defaults to None. Raises: IndexError: Index error if gpu list is empty @@ -171,9 +175,13 @@ class AMDSMICommands(): args.driver = driver if vram: args.vram = vram + if cache: + args.cache = cache if self.helpers.is_linux() and self.helpers.is_baremetal(): if ras: args.ras = ras + if partition: + args.partition = partition if limit: args.limit = limit @@ -189,11 +197,11 @@ class AMDSMICommands(): # If all arguments are False, it means that no argument was passed and the entire static should be printed if self.helpers.is_linux() and self.helpers.is_baremetal(): - if not any([args.asic, args.bus, args.vbios, args.limit, args.board, args.ras, args.driver, args.numa, args.vram]): - args.asic = args.bus = args.vbios = args.limit = args.board = args.ras = args.driver = args.numa = args.vram = self.all_arguments = True + if not any([args.asic, args.bus, args.vbios, args.limit, args.board, args.ras, args.driver, args.numa, args.vram, args.cache, args.partition]): + args.asic = args.bus = args.vbios = args.limit = args.board = args.ras = args.driver = args.numa = args.vram = args.cache = args.partition = self.all_arguments = True if self.helpers.is_linux() and self.helpers.is_virtual_os(): - if not any([args.asic, args.bus, args.vbios, args.board, args.driver, args.vram]): - args.asic = args.bus = args.vbios = args.board = args.driver = args.vram = self.all_arguments = True + if not any([args.asic, args.bus, args.vbios, args.board, args.driver, args.vram, args.cache]): + args.asic = args.bus = args.vbios = args.board = args.driver = args.vram = args.cache = self.all_arguments = True static_dict = {} @@ -434,6 +442,17 @@ class AMDSMICommands(): logging.debug("Failed to get vram info for gpu %s | %s", gpu_id, e.get_error_info()) static_dict['vram'] = vram_info + if args.cache: + try: + cache_info = amdsmi_interface.amdsmi_get_gpu_cache_info(args.gpu) + if self.logger.is_human_readable_format(): + for _ , cache_values in cache_info.items(): + cache_values['cache_size'] = f"{cache_values['cache_size']} KB" + except amdsmi_exception.AmdSmiLibraryException as e: + cache_info = "N/A" + logging.debug("Failed to get cache info for gpu %s | %s", gpu_id, e.get_error_info()) + + static_dict['cache'] = cache_info if self.helpers.is_hypervisor() or self.helpers.is_baremetal(): if args.ras: @@ -456,6 +475,22 @@ class AMDSMICommands(): logging.debug("Failed to get ras block features for gpu %s | %s", gpu_id, e.get_error_info()) static_dict["ras"] = ras_dict + if args.partition: + try: + compute_partition = amdsmi_interface.amdsmi_dev_compute_partition_get(args.gpu) + except amdsmi_exception.AmdSmiLibraryException as e: + compute_partition = "N/A" + logging.debug("Failed to get compute partition info for gpu %s | %s", gpu_id, e.get_error_info()) + + try: + memory_partition = amdsmi_interface.amdsmi_dev_memory_partition_get(args.gpu) + except amdsmi_exception.AmdSmiLibraryException as e: + memory_partition = "N/A" + logging.debug("Failed to get memory partition info for gpu %s | %s", gpu_id, e.get_error_info()) + + static_dict['partition'] = {"compute_partition": compute_partition, + "memory_partition": memory_partition} + if self.helpers.is_linux() and self.helpers.is_baremetal(): if args.numa: try: @@ -626,7 +661,6 @@ class AMDSMICommands(): args.retired = args.pending = args.un_res = True values_dict = {} - bad_page_err_output = '' # Get gpu_id for logging gpu_id = self.helpers.get_gpu_id_from_device_handle(args.gpu) @@ -1492,13 +1526,31 @@ class AMDSMICommands(): print('Not applicable to linux baremetal') - def event(self, args): + def event(self, args, gpu=None): + """ Get event information for target gpus + + Args: + args (Namespace): argparser args to pass to subcommand + gpu (device_handle, optional): device_handle for target device. Defaults to None. + + Return: + stdout event information for target gpus + """ + if args.gpu: + gpu = args.gpu + + if gpu == None: + args.gpu = self.device_handles + + if not isinstance(args.gpu, list): + args.gpu = [args.gpu] + print('EVENT LISTENING:\n') - print('Press q and hit ENTER when you want to stop (listening will stop inside 10 seconds)') + print('Press q and hit ENTER when you want to stop (listening will stop within 10 seconds)') threads = [] - for i in range(len(self.device_handles)): - x = threading.Thread(target=self._event_thread, args=(self, i)) + for gpu in range(len(args.gpu)): + x = threading.Thread(target=self._event_thread, args=(self, gpu)) threads.append(x) x.start() @@ -1698,8 +1750,9 @@ class AMDSMICommands(): self.logger.print_output(multiple_device_enabled=True) - def set_value(self, args, multiple_devices=False, gpu=None, fan=None, perflevel=None, - profile=None, perfdeterminism=None): + def set_value(self, args, multiple_devices=False, gpu=None, fan=None, perf_level=None, + profile=None, perf_determinism=None, compute_partition=None, + memory_partition=None): """Issue reset commands to target gpu(s) Args: @@ -1707,9 +1760,11 @@ class AMDSMICommands(): multiple_devices (bool, optional): True if checking for multiple devices. Defaults to False. gpu (device_handle, optional): device_handle for target device. Defaults to None. fan (int, optional): Value override for args.fan. Defaults to None. - perflevel (amdsmi_interface.AmdSmiDevPerfLevel, optional): Value override for args.perflevel. Defaults to None. + perf_level (amdsmi_interface.AmdSmiDevPerfLevel, optional): Value override for args.perf_level. Defaults to None. profile (bool, optional): Value override for args.profile. Defaults to None. - perfdeterminism (int, optional): Value override for args.perfdeterminism. Defaults to None. + perf_determinism (int, optional): Value override for args.perf_determinism. Defaults to None. + compute_partition (amdsmi_interface.AmdSmiComputePartitionType, optional): Value override for args.compute_partition. Defaults to None. + memory_partition (amdsmi_interface.AmdSmiMemoryPartitionType, optional): Value override for args.memory_partition. Defaults to None. Raises: ValueError: Value error if no gpu value is provided @@ -1723,12 +1778,16 @@ class AMDSMICommands(): args.gpu = gpu if fan: args.fan = fan - if perflevel: - args.perflevel = perflevel + if perf_level: + args.perf_level = perf_level if profile: args.profile = profile - if perfdeterminism: - args.perfdeterminism = perfdeterminism + if perf_determinism: + args.perf_determinism = perf_determinism + if compute_partition: + args.compute_partition = compute_partition + if memory_partition: + args.memory_partition = memory_partition # Handle No GPU passed if args.gpu == None: @@ -1741,6 +1800,11 @@ class AMDSMICommands(): args.gpu = device_handle + # Error if no subcommand args are passed + if not any([args.fan, args.perflevel, args.profile, args.perf_determinism]): + command = " ".join(sys.argv[1:]) + raise AmdSmiRequiredCommandException(command, self.logger.format) + # Build GPU string for errors try: gpu_bdf = amdsmi_interface.amdsmi_get_gpu_device_bdf(args.gpu) @@ -1762,28 +1826,43 @@ class AMDSMICommands(): raise ValueError(f"Unable to set fan speed {args.fan} on {gpu_string}") from e self.logger.store_output(args.gpu, 'fan', f"Successfully set fan speed {args.fan}") - if args.perflevel: - perf_level = amdsmi_interface.AmdSmiDevPerfLevel[args.perflevel] + if args.perf_level: + perf_level = amdsmi_interface.AmdSmiDevPerfLevel[args.perf_level] try: amdsmi_interface.amdsmi_set_gpu_perf_level(args.gpu, perf_level) 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 set performance level {args.perflevel} on {gpu_string}") from e + raise ValueError(f"Unable to set performance level {args.perf_level} on {gpu_string}") from e - self.logger.store_output(args.gpu, 'perflevel', f"Successfully set performance level {args.perflevel}") + self.logger.store_output(args.gpu, 'perflevel', f"Successfully set performance level {args.perf_level}") if args.profile: self.logger.store_output(args.gpu, 'profile', "Not Yet Implemented") - if isinstance(args.perfdeterminism, int): + if isinstance(args.perf_determinism, int): try: - amdsmi_interface.amdsmi_set_gpu_perf_determinism_mode(args.gpu, args.perfdeterminism) + amdsmi_interface.amdsmi_set_gpu_perf_determinism_mode(args.gpu, args.perf_determinism) 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 set performance determinism and clock frequency to {args.perfdeterminism} on {gpu_string}") from e - - self.logger.store_output(args.gpu, 'perfdeterminism', f"Successfully enabled performance determinism and set GFX clock frequency to {args.perfdeterminism}") + raise ValueError(f"Unable to set performance determinism and clock frequency to {args.perf_determinism} on {gpu_string}") from e + self.logger.store_output(args.gpu, 'perfdeterminism', f"Successfully enabled performance determinism and set GFX clock frequency to {args.perf_determinism}") + if args.compute_partition: + compute_partition = amdsmi_interface.AmdSmiComputePartitionType[args.compute_partition] + try: + amdsmi_interface.amdsmi_dev_compute_partition_set(args.gpu, compute_partition) + 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 set compute partition to {args.compute_partition} on {gpu_string}") from e + if args.memory_partition: + memory_partition = amdsmi_interface.AmdSmiMemoryPartitionType[args.memory_partition] + try: + amdsmi_interface.amdsmi_dev_memory_partition_set(args.gpu, memory_partition) + 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 set memory partition to {args.memory_partition} on {gpu_string}") from e if multiple_devices: self.logger.store_multiple_device_output() return # Skip printing when there are multiple devices @@ -1792,7 +1871,8 @@ class AMDSMICommands(): def reset(self, args, multiple_devices=False, gpu=None, gpureset=None, - clocks=None, fans=None, profile=None, xgmierr=None, perfdeterminism=None): + clocks=None, fans=None, profile=None, xgmierr=None, perf_determinism=None, + compute_partition=None, memory_partition=None): """Issue reset commands to target gpu(s) Args: @@ -1804,7 +1884,9 @@ class AMDSMICommands(): fans (bool, optional): Value override for args.fans. Defaults to None. profile (bool, optional): Value override for args.profile. Defaults to None. xgmierr (bool, optional): Value override for args.xgmierr. Defaults to None. - perfdeterminism (bool, optional): Value override for args.perfdeterminism. Defaults to None. + perf_determinism (bool, optional): Value override for args.perf_determinism. Defaults to None. + compute_partition (bool, optional): Value override for args.compute_partition. Defaults to None. + memory_partition (bool, optional): Value override for args.memory_partition. Defaults to None. Raises: ValueError: Value error if no gpu value is provided @@ -1826,8 +1908,12 @@ class AMDSMICommands(): args.profile = profile if xgmierr: args.xgmierr = xgmierr - if perfdeterminism: - args.perfdeterminism = perfdeterminism + if perf_determinism: + args.perf_determinism = perf_determinism + if compute_partition: + args.compute_partition = compute_partition + if memory_partition: + args.memory_partition = memory_partition # Handle No GPU passed if args.gpu == None: @@ -1843,6 +1929,11 @@ class AMDSMICommands(): # Get gpu_id for logging gpu_id = self.helpers.get_gpu_id_from_device_handle(args.gpu) + # Error if no subcommand args are passed + if not any([args.gpureset, args.clocks, args.fans, args.profile, args.xgmierr, args.perf_determinism]): + command = " ".join(sys.argv[1:]) + raise AmdSmiRequiredCommandException(command, self.logger.format) + if args.gpureset: if self.helpers.is_amd_device(args.gpu): try: @@ -1935,7 +2026,7 @@ class AMDSMICommands(): result = "N/A" logging.debug("Failed to reset xgmi error count on gpu %s | %s", gpu_id, e.get_error_info()) self.logger.store_output(args.gpu, 'reset_xgmi_err', result) - if args.perfdeterminism: + if args.perf_determinism: try: level_auto = amdsmi_interface.AmdSmiDevPerfLevel.AUTO amdsmi_interface.amdsmi_set_gpu_perf_level(args.gpu, level_auto) @@ -1945,8 +2036,27 @@ class AMDSMICommands(): raise PermissionError('Command requires elevation') from e result = "N/A" logging.debug("Failed to set perf level on gpu %s | %s", gpu_id, e.get_error_info()) - self.logger.store_output(args.gpu, 'reset_perf_determinism', result) + if args.compute_partition: + try: + amdsmi_interface.amdsmi_dev_compute_partition_reset(args.gpu) + result = 'Successfully reset compute partition' + 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 + result = "N/A" + logging.debug("Failed to reset compute partition on gpu %s | %s", gpu_id, e.get_error_info()) + self.logger.store_output(args.gpu, 'reset_compute_partition', result) + if args.memory_partition: + try: + amdsmi_interface.amdsmi_dev_memory_partition_reset(args.gpu) + result = 'Successfully reset memory partition' + 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 + result = "N/A" + logging.debug("Failed to reset memory partition on gpu %s | %s", gpu_id, e.get_error_info()) + self.logger.store_output(args.gpu, 'reset_memory_partition', result) if multiple_devices: self.logger.store_multiple_device_output() @@ -1966,8 +2076,8 @@ class AMDSMICommands(): return device = devices[i] - listener = amdsmi_interface.AmdSmiEventReader(device, amdsmi_interface.AmdSmiEvtNotificationType.GPU_PRE_RESET, - amdsmi_interface.AmdSmiEvtNotificationType.GPU_POST_RESET) + listener = amdsmi_interface.AmdSmiEventReader(device, + amdsmi_interface.AmdSmiEvtNotificationType) values_dict = {} while self.stop!='q': diff --git a/projects/amdsmi/amdsmi_cli/amdsmi_helpers.py b/projects/amdsmi/amdsmi_cli/amdsmi_helpers.py index f4914e01a4..2efb9a573b 100644 --- a/projects/amdsmi/amdsmi_cli/amdsmi_helpers.py +++ b/projects/amdsmi/amdsmi_cli/amdsmi_helpers.py @@ -21,12 +21,14 @@ # import logging +import math import platform import sys import time from subprocess import run from subprocess import PIPE, STDOUT +from typing import List from amdsmi_init import * from BDF import BDF @@ -132,7 +134,7 @@ class AMDSMIHelpers(): """Return dictionary of possible GPU choices and string of the output: Dictionary will be in format: gpus[ID] : (BDF, UUID, Device Handle) String output will be in format: - "ID:0 | BDF:0000:23:00.0 | UUID:ffffffff-0000-1000-0000-000000000000" + "ID: 0 | BDF: 0000:23:00.0 | UUID: ffffffff-0000-1000-0000-000000000000" params: None return: @@ -152,6 +154,9 @@ class AMDSMIHelpers(): else: raise e + # Handle spacing for the gpu_choices_str + max_padding = int(math.log10(len(device_handles))) + 1 + for gpu_id, device_handle in enumerate(device_handles): bdf = amdsmi_interface.amdsmi_get_gpu_device_bdf(device_handle) uuid = amdsmi_interface.amdsmi_get_gpu_device_uuid(device_handle) @@ -160,20 +165,25 @@ class AMDSMIHelpers(): "UUID": uuid, "Device Handle": device_handle, } - gpu_choices_str += f"ID:{gpu_id} | BDF:{bdf} | UUID:{uuid}\n" + + if gpu_id == 0: + id_padding = max_padding + else: + id_padding = max_padding - int(math.log10(gpu_id)) + gpu_choices_str += f"\tID: {gpu_id}{' ' * id_padding}| BDF: {bdf} | UUID: {uuid}\n" # Add the all option to the gpu_choices gpu_choices["all"] = "all" - gpu_choices_str += " all | Selects all devices\n" + gpu_choices_str += f"\t all{' ' * max_padding}| Selects all devices\n" return (gpu_choices, gpu_choices_str) - def get_device_handles_from_gpu_selections(self, gpu_selections, gpu_choices=None): + def get_device_handles_from_gpu_selections(self, gpu_selections: List[str], gpu_choices=None): """Convert provided gpu_selections to device_handles Args: - gpu_selections (list[str]): This will be the GPU ID, BDF, or UUID: + gpu_selections (list[str]): Selected GPU ID(s), BDF(s), or UUID(s): ex: ID:0 | BDF:0000:23:00.0 | UUID:ffffffff-0000-1000-0000-000000000000 gpu_choices (dict{gpu_choices}): This is a dictionary of the possible gpu_choices Returns: @@ -181,7 +191,7 @@ class AMDSMIHelpers(): amdsmi device_handles (False, str): Return False, and the first input that failed to be converted """ - if gpu_selections == ["all"]: + if 'all' in gpu_selections: return (True, amdsmi_interface.amdsmi_get_processor_handles()) if isinstance(gpu_selections, str): @@ -307,7 +317,9 @@ class AMDSMIHelpers(): for gpu_index, device_handle in enumerate(device_handles): if input_device_handle.value == device_handle.value: return gpu_index - raise IndexError("Unable to find gpu ID from device_handle") + raise amdsmi_exception.AmdSmiParameterException(input_device_handle, + amdsmi_interface.amdsmi_wrapper.amdsmi_processor_handle, + "Unable to find gpu ID from device_handle") def get_amd_gpu_bdfs(self): @@ -342,6 +354,20 @@ class AMDSMIHelpers(): return perf_levels_str, perf_levels_int + def get_compute_partition_types(self): + compute_partitions_str = [partition.name for partition in amdsmi_interface.AmdSmiComputePartitionType] + if 'INVALID' in compute_partitions_str: + compute_partitions_str.remove('INVALID') + return compute_partitions_str + + + def get_memory_partition_types(self): + memory_partitions_str = [partition.name for partition in amdsmi_interface.AmdSmiMemoryPartitionType] + if 'UNKNOWN' in memory_partitions_str: + memory_partitions_str.remove('UNKNOWN') + return memory_partitions_str + + def get_clock_types(self): clock_types_str = [clock.name for clock in amdsmi_interface.AmdSmiClkType] clock_types_int = list(set(clock.value for clock in amdsmi_interface.AmdSmiClkType)) diff --git a/projects/amdsmi/amdsmi_cli/amdsmi_parser.py b/projects/amdsmi/amdsmi_cli/amdsmi_parser.py index 85fda61d6f..455b793aa7 100644 --- a/projects/amdsmi/amdsmi_cli/amdsmi_parser.py +++ b/projects/amdsmi/amdsmi_cli/amdsmi_parser.py @@ -24,15 +24,39 @@ import argparse import errno import os -import time -from pathlib import Path import sys +import time + +from pathlib import Path from _version import __version__ from amdsmi_helpers import AMDSMIHelpers import amdsmi_cli_exceptions +# Custom Help Formatter for increasing the action max length +class AMDSMIParserHelpFormatter(argparse.HelpFormatter): + def __init__(self, prog): + super().__init__(prog=prog, + indent_increment=2, + max_help_position=24, + width=90) + self._action_max_length = 20 + + +# Custom Help Formatter for not duplicating the metavar in the subparsers +class AMDSMISubparserHelpFormatter(argparse.RawTextHelpFormatter): + def __init__(self, prog): + super().__init__(prog, max_help_position=80, width=90) + + def _format_action_invocation(self, action): + if not action.option_strings or action.nargs == 0: + return super()._format_action_invocation(action) + default = self._get_default_metavar_for_optional(action) + args_string = self._format_args(action, default) + return ', '.join(action.option_strings) + ' ' + args_string + + class AMDSMIParser(argparse.ArgumentParser): """Unified Parser for AMDSMI CLI. This parser doesn't access amdsmi's lib directly,but via AMDSMIHelpers, @@ -56,34 +80,32 @@ class AMDSMIParser(argparse.ArgumentParser): # Adjust argument parser options super().__init__( - formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, - max_help_position=80, - width=90), + formatter_class= lambda prog: AMDSMIParserHelpFormatter(prog), description=f"AMD System Management Interface | {version_string} | {platform_string}", add_help=True, prog=program_name) # Setup subparsers - subparsers = self.add_subparsers( + self.subparsers = self.add_subparsers( title="AMD-SMI Commands", parser_class=argparse.ArgumentParser, help="Descriptions:", metavar='') # Add all subparsers - self._add_version_parser(subparsers, version) - self._add_list_parser(subparsers, list) - self._add_static_parser(subparsers, static) - self._add_firmware_parser(subparsers, firmware) - self._add_bad_pages_parser(subparsers, bad_pages) - self._add_metric_parser(subparsers, metric) - self._add_process_parser(subparsers, process) - self._add_profile_parser(subparsers, profile) - self._add_event_parser(subparsers, event) - self._add_topology_parser(subparsers, topology) - self._add_set_value_parser(subparsers, set_value) - self._add_reset_parser(subparsers, reset) - self._add_rocm_smi_parser(subparsers, rocmsmi) + self._add_version_parser(self.subparsers, version) + self._add_list_parser(self.subparsers, list) + self._add_static_parser(self.subparsers, static) + self._add_firmware_parser(self.subparsers, firmware) + self._add_bad_pages_parser(self.subparsers, bad_pages) + self._add_metric_parser(self.subparsers, metric) + self._add_process_parser(self.subparsers, process) + self._add_profile_parser(self.subparsers, profile) + self._add_event_parser(self.subparsers, event) + self._add_topology_parser(self.subparsers, topology) + self._add_set_value_parser(self.subparsers, set_value) + self._add_reset_parser(self.subparsers, reset) + self._add_rocm_smi_parser(self.subparsers, rocmsmi) def _positive_int(self, int_value): @@ -184,6 +206,8 @@ class AMDSMIParser(argparse.ArgumentParser): ouputformat=self.helpers.get_output_format() # Checks the values def __call__(self, parser, args, values, option_string=None): + if "all" in gpu_choices: + del gpu_choices["all"] status, selected_device_handles = amdsmi_helpers.get_device_handles_from_gpu_selections(gpu_selections=values, gpu_choices=gpu_choices) if status: @@ -201,7 +225,9 @@ class AMDSMIParser(argparse.ArgumentParser): json_help = "Displays output in JSON format (human readable by default)." csv_help = "Displays output in CSV format (human readable by default)." file_help = "Saves output into a file on the provided path (stdout by default)." - loglevel_help = "Set the logging level for the parser commands (ERROR by default)." + loglevel_choices = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] + loglevel_choices_str = ", ".join(loglevel_choices) + loglevel_help = f"Set the logging level from the possible choices:\n\t{loglevel_choices_str}" command_modifier_group = subcommand_parser.add_argument_group('Command Modifiers') @@ -212,22 +238,22 @@ class AMDSMIParser(argparse.ArgumentParser): command_modifier_group.add_argument('--file', action=self._check_output_file_path(), type=str, required=False, help=file_help) # Placing loglevel outside the subcommands so it can be used with any subcommand - command_modifier_group.add_argument('--loglevel', action='store', required=False, help=loglevel_help, default='ERROR', - choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]) + command_modifier_group.add_argument('--loglevel', action='store', required=False, help=loglevel_help, default='ERROR', metavar='LEVEL', + choices=loglevel_choices) def _add_watch_arguments(self, subcommand_parser): # Device arguments help text - watch_help = "Reprint the command in a loop of Interval seconds" - watch_time_help = "The total time to watch the given command" - iterations_help = "Total number of iterations to loop on the given command" + watch_help = "Reprint the command in a loop of INTERVAL seconds" + watch_time_help = "The total TIME to watch the given command" + iterations_help = "Total number of ITERATIONS to loop on the given command" # Mutually Exclusive Args within the subparser - subcommand_parser.add_argument('-w', '--watch', action='store', metavar='loop_time', + subcommand_parser.add_argument('-w', '--watch', action='store', metavar='INTERVAL', type=self._positive_int, required=False, help=watch_help) - subcommand_parser.add_argument('-W', '--watch_time', action=self._check_watch_selected(), metavar='total_loop_time', + subcommand_parser.add_argument('-W', '--watch_time', action=self._check_watch_selected(), metavar='TIME', type=self._positive_int, required=False, help=watch_time_help) - subcommand_parser.add_argument('-i', '--iterations', action=self._check_watch_selected(), metavar='number_of_iterations', + subcommand_parser.add_argument('-i', '--iterations', action=self._check_watch_selected(), metavar='ITERATIONS', type=self._positive_int, required=False, help=iterations_help) @@ -254,8 +280,10 @@ class AMDSMIParser(argparse.ArgumentParser): # Create version subparser version_parser = subparsers.add_parser('version', help=version_help, description=None) version_parser._optionals.title = None - version_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + version_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) version_parser.set_defaults(func=func) + + # Add Universal Arguments self._add_command_modifiers(version_parser) @@ -270,13 +298,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create list subparser list_parser = subparsers.add_parser('list', help=list_help, description=list_subcommand_help) - list_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + list_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) list_parser.set_defaults(func=func) - # Add Command Modifiers + # Add Universal Arguments self._add_command_modifiers(list_parser) - - # Add Device args self._add_device_arguments(list_parser, required=False) @@ -293,12 +319,14 @@ class AMDSMIParser(argparse.ArgumentParser): vbios_help = "All video bios information (if available)" limit_help = "All limit metric values (i.e. power and thermal limits)" driver_help = "Displays driver version" + vram_help = "All vram information" + cache_help = "All cache information" + board_help = "All board information" # Options arguments help text for Hypervisors and Baremetal ras_help = "Displays RAS features information" - vram_help = "All vram information" - board_help = "All board information" # Linux Baremetal only numa_help = "All numa node information" # Linux Baremetal only + partition_help = "Partition information" # Options arguments help text for Hypervisors dfc_help = "All DFC FW table information" @@ -308,11 +336,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create static subparser static_parser = subparsers.add_parser('static', help=static_help, description=static_subcommand_help) static_parser._optionals.title = static_optionals_title - static_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + static_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) static_parser.set_defaults(func=func) - self._add_command_modifiers(static_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(static_parser) self._add_device_arguments(static_parser, required=False) # Optional Args @@ -321,11 +349,13 @@ class AMDSMIParser(argparse.ArgumentParser): static_parser.add_argument('-V', '--vbios', action='store_true', required=False, help=vbios_help) static_parser.add_argument('-d', '--driver', action='store_true', required=False, help=driver_help) static_parser.add_argument('-v', '--vram', action='store_true', required=False, help=vram_help) + static_parser.add_argument('-c', '--cache', action='store_true', required=False, help=cache_help) static_parser.add_argument('-B', '--board', action='store_true', required=False, help=board_help) # Options to display on Hypervisors and Baremetal if self.helpers.is_hypervisor() or self.helpers.is_baremetal(): static_parser.add_argument('-r', '--ras', action='store_true', required=False, help=ras_help) + static_parser.add_argument('-p', '--partition', action='store_true', required=False, help=partition_help) if self.helpers.is_linux(): static_parser.add_argument('-l', '--limit', action='store_true', required=False, help=limit_help) static_parser.add_argument('-u', '--numa', action='store_true', required=False, help=numa_help) @@ -350,11 +380,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create firmware subparser firmware_parser = subparsers.add_parser('firmware', help=firmware_help, description=firmware_subcommand_help, aliases=['ucode']) firmware_parser._optionals.title = firmware_optionals_title - firmware_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + firmware_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) firmware_parser.set_defaults(func=func) - self._add_command_modifiers(firmware_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(firmware_parser) self._add_device_arguments(firmware_parser, required=False) # Optional Args @@ -383,11 +413,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create bad_pages subparser bad_pages_parser = subparsers.add_parser('bad-pages', help=bad_pages_help, description=bad_pages_subcommand_help) bad_pages_parser._optionals.title = bad_pages_optionals_title - bad_pages_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + bad_pages_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) bad_pages_parser.set_defaults(func=func) - self._add_command_modifiers(bad_pages_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(bad_pages_parser) self._add_device_arguments(bad_pages_parser, required=False) # Optional Args @@ -433,11 +463,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create metric subparser metric_parser = subparsers.add_parser('metric', help=metric_help, description=metric_subcommand_help) metric_parser._optionals.title = metric_optionals_title - metric_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + metric_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) metric_parser.set_defaults(func=func) - self._add_command_modifiers(metric_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(metric_parser) self._add_device_arguments(metric_parser, required=False) # Add Watch args @@ -496,11 +526,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create process subparser process_parser = subparsers.add_parser('process', help=process_help, description=process_subcommand_help) process_parser._optionals.title = process_optionals_title - process_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + process_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) process_parser.set_defaults(func=func) - self._add_command_modifiers(process_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(process_parser) self._add_device_arguments(process_parser, required=False) # Add Watch args @@ -526,17 +556,17 @@ class AMDSMIParser(argparse.ArgumentParser): # Create profile subparser profile_parser = subparsers.add_parser('profile', help=profile_help, description=profile_subcommand_help) profile_parser._optionals.title = profile_optionals_title - profile_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + profile_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) profile_parser.set_defaults(func=func) - self._add_command_modifiers(profile_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(profile_parser) self._add_device_arguments(profile_parser, required=False) def _add_event_parser(self, subparsers, func): - if self.helpers.is_linux() and not self.helpers.is_virtual_os(): - # This subparser only applies to Linux Hypervisors, NOT Linux Guest + if self.helpers.is_virtual_os(): + # This subparser doesn't only apply to guest systems return # Subparser help text @@ -547,11 +577,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create event subparser event_parser = subparsers.add_parser('event', help=event_help, description=event_subcommand_help) event_parser._optionals.title = event_optionals_title - event_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + event_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) event_parser.set_defaults(func=func) - self._add_command_modifiers(event_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(event_parser) self._add_device_arguments(event_parser, required=False) @@ -576,11 +606,11 @@ class AMDSMIParser(argparse.ArgumentParser): # Create topology subparser topology_parser = subparsers.add_parser('topology', help=topology_help, description=topology_subcommand_help) topology_parser._optionals.title = topology_optionals_title - topology_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + topology_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) topology_parser.set_defaults(func=func) - self._add_command_modifiers(topology_parser) - # Add Device args + # Add Universal Arguments + self._add_command_modifiers(topology_parser) self._add_device_arguments(topology_parser, required=False) # Optional Args @@ -602,27 +632,34 @@ class AMDSMIParser(argparse.ArgumentParser): \nA set argument must be provided; Multiple set arguments are accepted" set_value_optionals_title = "Set Arguments" - # Help text for Arguments only on Guest and BM platforms - set_fan_help = "Sets GPU fan speed (0-255 or 0-100%%)" - set_perf_level_help = "Sets performance level" + # Help text for Arguments only on BM platforms + set_fan_help = "Set GPU fan speed (0-255 or 0-100%%)" + set_perf_level_help = "Set performance level" set_profile_help = "Set power profile level (#) or a quoted string of custom profile attributes" - set_perf_det_help = "Sets GPU clock frequency limit and performance level to determinism to get minimal performance variation" + set_perf_det_help = "Set GPU clock frequency limit and performance level to determinism to get minimal performance variation" + compute_partition_choices_str = ", ".join(self.helpers.get_compute_partition_types()) + memory_partition_choices_str = ", ".join(self.helpers.get_memory_partition_types()) + set_compute_partition_help = f"Set one of the following the compute partition modes:\n\t{compute_partition_choices_str}" + set_memory_partition_help = f"Set one of the following the memory partition modes:\n\t{memory_partition_choices_str}" # Create set_value subparser set_value_parser = subparsers.add_parser('set', help=set_value_help, description=set_value_subcommand_help) set_value_parser._optionals.title = set_value_optionals_title - set_value_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + set_value_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) set_value_parser.set_defaults(func=func) - self._add_command_modifiers(set_value_parser) + # Add Universal Arguments + self._add_command_modifiers(set_value_parser) # Device args are required as safeguard from the user applying the operation to all gpus unintentionally self._add_device_arguments(set_value_parser, required=True) # Optional Args set_value_parser.add_argument('-f', '--fan', action=self._validate_fan_speed(), required=False, help=set_fan_help, metavar='%') - set_value_parser.add_argument('-l', '--perflevel', action='store', choices=self.helpers.get_perf_levels()[0], type=str.upper, required=False, help=set_perf_level_help, metavar='LEVEL') + set_value_parser.add_argument('-l', '--perf-level', action='store', choices=self.helpers.get_perf_levels()[0], type=str.upper, required=False, help=set_perf_level_help, metavar='LEVEL') set_value_parser.add_argument('-P', '--profile', action='store', required=False, help=set_profile_help, metavar='SETPROFILE') - set_value_parser.add_argument('-d', '--perfdeterminism', action='store', type=self._positive_int, required=False, help=set_perf_det_help, metavar='SCLKMAX') + set_value_parser.add_argument('-d', '--perf-determinism', action='store', type=self._positive_int, required=False, help=set_perf_det_help, metavar='SCLKMAX') + set_value_parser.add_argument('-C', '--compute-partition', action='store', choices=self.helpers.get_compute_partition_types(), type=str.upper, required=False, help=set_compute_partition_help, metavar='PARTITION') + set_value_parser.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') def _validate_set_clock(self, validate_clock_type=True): @@ -731,29 +768,34 @@ class AMDSMIParser(argparse.ArgumentParser): # Help text for Arguments only on Guest and BM platforms gpureset_help = "Reset the specified GPU" - resetclocks_help = "Reset clocks and overdrive to default" - resetfans_help = "Reset fans to automatic (driver) control" - resetprofile_help = "Reset power profile back to default" - resetxgmierr_help = "Reset XGMI error counts" - resetperfdet_help = "Disable performance determinism" + reset_clocks_help = "Reset clocks and overdrive to default" + reset_fans_help = "Reset fans to automatic (driver) control" + reset_profile_help = "Reset power profile back to default" + reset_xgmierr_help = "Reset XGMI error counts" + reset_perf_det_help = "Disable performance determinism" + reset_compute_help = "Reset compute partitions on the specified GPU" + reset_memory_help = "Reset memory partitions on the specified GPU" # Create reset subparser reset_parser = subparsers.add_parser('reset', help=reset_help, description=reset_subcommand_help) reset_parser._optionals.title = reset_optionals_title - reset_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + reset_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) reset_parser.set_defaults(func=func) - self._add_command_modifiers(reset_parser) + # Add Universal Arguments + self._add_command_modifiers(reset_parser) # Device args are required as safeguard from the user applying the operation to all gpus unintentionally self._add_device_arguments(reset_parser, required=True) - # Optional Args + # Add reset arguments reset_parser.add_argument('-G', '--gpureset', action='store_true', required=False, help=gpureset_help) - reset_parser.add_argument('-c', '--clocks', action='store_true', required=False, help=resetclocks_help) - reset_parser.add_argument('-f', '--fans', action='store_true', required=False, help=resetfans_help) - reset_parser.add_argument('-p', '--profile', action='store_true', required=False, help=resetprofile_help) - reset_parser.add_argument('-x', '--xgmierr', action='store_true', required=False, help=resetxgmierr_help) - reset_parser.add_argument('-d', '--perfdeterminism', action='store_true', required=False, help=resetperfdet_help) + reset_parser.add_argument('-c', '--clocks', action='store_true', required=False, help=reset_clocks_help) + reset_parser.add_argument('-f', '--fans', action='store_true', required=False, help=reset_fans_help) + reset_parser.add_argument('-p', '--profile', action='store_true', required=False, help=reset_profile_help) + reset_parser.add_argument('-x', '--xgmierr', action='store_true', required=False, help=reset_xgmierr_help) + reset_parser.add_argument('-d', '--perf-determinism', action='store_true', required=False, help=reset_perf_det_help) + reset_parser.add_argument('-C', '--compute-partition', action='store_true', required=False, help=reset_compute_help) + reset_parser.add_argument('-M', '--memory-partition', action='store_true', required=False, help=reset_memory_help) def _add_rocm_smi_parser(self, subparsers, func): @@ -779,7 +821,7 @@ class AMDSMIParser(argparse.ArgumentParser): # Create rocm_smi subparser rocm_smi_parser = subparsers.add_parser('rocm-smi', help=rocm_smi_help, description=rocm_smi_subcommand_help) rocm_smi_parser._optionals.title = rocm_smi_optionals_title - rocm_smi_parser.formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog, max_help_position=80, width=90) + rocm_smi_parser.formatter_class=lambda prog: AMDSMISubparserHelpFormatter(prog) rocm_smi_parser.set_defaults(func=func) self._add_command_modifiers(rocm_smi_parser) diff --git a/projects/amdsmi/docs/doxygen/Doxyfile b/projects/amdsmi/docs/doxygen/Doxyfile index b90d176126..ca3cf2603d 100644 --- a/projects/amdsmi/docs/doxygen/Doxyfile +++ b/projects/amdsmi/docs/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = AMD SMI # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "23.3.1.0" +PROJECT_NUMBER = "23.4.0.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/projects/amdsmi/e_smi_library b/projects/amdsmi/e_smi_library deleted file mode 160000 index 1b2de9f700..0000000000 --- a/projects/amdsmi/e_smi_library +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1b2de9f700045ce83319e6a3b7193c3f4746a9d7 diff --git a/projects/amdsmi/example/amd_smi_nodrm_example.cc b/projects/amdsmi/example/amd_smi_nodrm_example.cc index ec02ec53d8..3b4adce76a 100644 --- a/projects/amdsmi/example/amd_smi_nodrm_example.cc +++ b/projects/amdsmi/example/amd_smi_nodrm_example.cc @@ -122,6 +122,16 @@ int main() { return AMDSMI_STATUS_NOT_SUPPORTED; } + amdsmi_ras_feature_t ras_feature; + ret = amdsmi_get_gpu_ras_feature_info( + processor_handles[j] ,&ras_feature); + if (ret != AMDSMI_STATUS_NOT_SUPPORTED) { + CHK_AMDSMI_RET(ret) + printf("\tras_feature: version: %x, schema: %x\n", + ras_feature.ras_eeprom_version, ras_feature.ecc_correction_schema_flag); + } + + amdsmi_bdf_t bdf = {}; ret = amdsmi_get_gpu_device_bdf(processor_handles[j], &bdf); CHK_AMDSMI_RET(ret) diff --git a/projects/amdsmi/example/amdsmi_esmi_intg_example.cc b/projects/amdsmi/example/amdsmi_esmi_intg_example.cc index 28d4784121..64114852b3 100644 --- a/projects/amdsmi/example/amdsmi_esmi_intg_example.cc +++ b/projects/amdsmi/example/amdsmi_esmi_intg_example.cc @@ -48,11 +48,10 @@ #include #include #include "amd_smi/amdsmi.h" +#include "asm/amd_hsmp.h" #include #include -using namespace std; - #define SHOWLINESZ 256 #define CHK_AMDSMI_RET(RET) \ @@ -68,11 +67,17 @@ using namespace std; } \ } +using std::cin; +using std::cout; +using std::endl; +using std::fixed; +using std::setprecision; +using std::vector; + int main(int argc, char **argv) { amdsmi_status_t ret; uint32_t proto_ver; amdsmi_smu_fw_version_t smu_fw = {}; - amdsmi_cpusocket_handle socket_handle; // Initialize esmi for AMD CPUs ret = amdsmi_init(AMDSMI_INIT_AMD_CPUS); @@ -94,9 +99,9 @@ int main(int argc, char **argv) { cout << "Total Socket: " << socket_count << endl; // For each socket, get identifier and cores - for (uint32_t i = 0; i < socket_count; i++) { + for (uint8_t i = 0; i < socket_count; i++) { // Get Socket info - uint32_t socket_info; + uint32_t socket_info = 0; ret = amdsmi_get_cpusocket_info(sockets[i], socket_info); CHK_AMDSMI_RET(ret) cout << "Socket " << socket_info << endl; @@ -134,27 +139,6 @@ int main(int argc, char **argv) { uint32_t err_bits = 0; - uint64_t pkg_input; - cout<<"\n-------------------------------------------------"; - cout<<"\n| Sensor Name\t\t\t |"; - for (uint32_t i = 0; i < socket_count; i++) { - cout<(pkg_input)/1000000000<<"\t|"; - } else { - err_bits |= 1 << ret; - cout<<" NA (Err:" <(core_input)/1000000<<" Joules\t\t|\n"; - cout<<"-------------------------------------------------\n"; - - core_input = 0; - cout<<"\n| CPU energies in Joules:\t\t\t\t\t\t\t\t\t|"; - for (uint32_t j = 0; j < core_count; j++) { - ret = amdsmi_get_cpu_core_energy(processor_handles[j], j, &core_input); - CHK_AMDSMI_RET(ret) - if(!(j % 8)) { - if(j < 10) - cout<<"\n| cpu [0"<(core_input)/1000000<<" "; - if (j % 8 == 7) - cout<<"\t|"; - } - cout<<"\n-------------------------------------------------\n"; - uint32_t c_clk = 0; ret = amdsmi_get_cpu_core_current_freq_limit(processor_handles[i], i, &c_clk); CHK_AMDSMI_RET(ret) @@ -243,7 +202,7 @@ int main(int argc, char **argv) { cout<<"\n| CPU["<(power)/1000<<"\t|"; + cout<(socket_power)/1000<<"\t|"; } else { err_bits |= 1 << ret; cout<<" NA (Err:" <(powerlimit)/1000<<"\t|"; + cout<(power_limit)/1000<<"\t|"; } else { err_bits |= 1 << ret; cout<<" NA (Err:" <(powermax)/1000<<"\t|"; + cout<(power_max)/1000<<"\t|"; } else { err_bits |= 1 << ret; cout<<" NA (Err:" <>input_power; - ret = amdsmi_get_cpu_socket_power_cap_max(sockets[i], i, &powermax); + ret = amdsmi_get_cpu_socket_power_cap_max(sockets[i], i, &power_max); CHK_AMDSMI_RET(ret) - if ((ret == AMDSMI_STATUS_SUCCESS) && (input_power > powermax)) { + if ((ret == AMDSMI_STATUS_SUCCESS) && (input_power > power_max)) { cout<<"Input power is more than max power limit," - " limiting to "<(powermax)/1000<<"Watts\n"; - input_power = powermax; + " limiting to "<(power_max)/1000<<"Watts\n"; + input_power = power_max; } ret = amdsmi_set_cpu_socket_power_cap(sockets[i], i, input_power); CHK_AMDSMI_RET(ret) @@ -422,7 +381,7 @@ int main(int argc, char **argv) { cout<<"\n-------------------------------------------------\n"; amdsmi_temp_range_refresh_rate_t rate; - uint8_t dimm_addr; + uint8_t dimm_addr = 0x80; cout<<"\n| Socket DIMM temp range and refresh rate\t\t |\n"; ret = amdsmi_get_cpu_dimm_temp_range_and_refresh_rate(sockets[i], i, dimm_addr, &rate); CHK_AMDSMI_RET(ret) @@ -436,15 +395,15 @@ int main(int argc, char **argv) { cout<<"\n-------------------------------------------------\n"; - amdsmi_dimm_power_t pow; + amdsmi_dimm_power_t dimm_power; cout<<"\n| Socket DIMM power consumption\t\t |\n"; - ret = amdsmi_get_cpu_dimm_power_consumption(sockets[i], i, dimm_addr, &pow); + ret = amdsmi_get_cpu_dimm_power_consumption(sockets[i], i, dimm_addr, &dimm_power); CHK_AMDSMI_RET(ret) if(ret) { - cout<<"\n| Power(mWatts)\t\t |"<>pstate; ret = amdsmi_cpu_apb_disable(sockets[i], i, pstate); @@ -555,7 +514,7 @@ int main(int argc, char **argv) { uint8_t rate_ctrl; uint8_t prev_mode; - string pcie_strings[] = { + std::string pcie_strings[] = { "automatically detect based on bandwidth utilisation", "limited to Gen4 rate", "limited to Gen5 rate" @@ -595,9 +554,9 @@ int main(int argc, char **argv) { amdsmi_link_id_bw_type_t io_link; uint32_t bw; - char *link = "P0"; + char* link = "P0"; io_link.link_name = link; - io_link.bw_type = static_cast(1) ; + io_link.bw_type = static_cast(1) ; ret = amdsmi_get_cpu_current_io_bandwidth(sockets[i], i, io_link, &bw); CHK_AMDSMI_RET(ret) @@ -611,10 +570,10 @@ int main(int argc, char **argv) { amdsmi_link_id_bw_type_t xgmi_link; uint32_t bw1; - char *link1 = "P0"; int bw_ind = 1; + char* link1 = "P1"; xgmi_link.link_name = link1; - xgmi_link.bw_type = static_cast(1<(1<:-e -DENABLE_ESMI_LIB>" -i amdsmi.h -l ${PROJECT_BINARY_DIR}/src/libamd_smi.so -o ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py COMMAND cp -f ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_wrapper.py ${CMAKE_CURRENT_BINARY_DIR}/ # hacky alternative to configure_file that will run at MAKE compile instead of CMake configure COMMAND sed -i diff --git a/projects/amdsmi/py-interface/Dockerfile b/projects/amdsmi/py-interface/Dockerfile new file mode 100644 index 0000000000..5218f76946 --- /dev/null +++ b/projects/amdsmi/py-interface/Dockerfile @@ -0,0 +1,43 @@ +FROM ubuntu:latest + +# do not prompt in apt +# https://github.com/moby/moby/issues/4032#issuecomment-163689851 +ARG DEBIAN_FRONTEND=noninteractive +ARG DEBCONF_NONINTERACTIVE_SEEN=true + +# set timezone +ENV TZ="America/Chicago" +RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezone + +RUN apt update --yes \ + && apt install --yes \ + build-essential \ + cmake \ + gnupg \ + libdrm-dev \ + libpython3-dev \ + lsb-release \ + pkg-config \ + pkg-config \ + python3-pip \ + software-properties-common \ + wget \ + && apt clean \ + && rm -rf /var/cache/apt/ /var/lib/apt/lists/* + +WORKDIR /var/tmp +RUN TEMPDIR=$(mktemp -d) \ + && cd $TEMPDIR \ + && wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh \ + && ./llvm.sh 16 \ + && update-alternatives --install /usr/bin/clang clang $(which clang-16) 91 --slave /usr/bin/clang++ clang++ $(which clang++-16) \ + && python3 -m pip install --no-cache-dir clang==16.0.1 ctypeslib2==2.3.4 -U \ + && rm -rf $TEMPDIR + +WORKDIR /src +CMD cp -r /src /tmp/src \ + && cd /tmp/src \ + && rm -rf build .cache \ + && cmake -B build -DBUILD_WRAPPER=ON \ + && make -C build -j $(nproc) \ + && cp /tmp/src/py-interface/amdsmi_wrapper.py /src/py-interface/amdsmi_wrapper.py diff --git a/projects/amdsmi/py-interface/README.md b/projects/amdsmi/py-interface/README.md index 8147ba1b6d..25845075c1 100644 --- a/projects/amdsmi/py-interface/README.md +++ b/projects/amdsmi/py-interface/README.md @@ -424,6 +424,85 @@ except AmdSmiException as e: print(e) ``` +### amdsmi_get_gpu_vram_info + +Description: Returns dictionary of vram information for the given GPU. + +Input parameters: + +* `processor_handle` device which to query + +Output: Dictionary with fields + +Field | Description +---|--- +`vram_type` | vram type +`vram_vendor` | vram vendor +`vram_size_mb` | vram size in mb + +Exceptions that can be thrown by `amdsmi_get_gpu_vram_info` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + vram_info = amdsmi_get_gpu_vram_info(device) + print(vram_info['vram_type']) + print(vram_info['vram_vendor']) + print(vram_info['vram_size_mb']) +except AmdSmiException as e: + print(e) +``` + +### amdsmi_get_gpu_cache_info + +Description: Returns dictionary of cache information for the given GPU. + +Input parameters: + +* `processor_handle` device which to query + +Output: Dictionary of Dictionaries containing cache information + +Field | Description +---|--- +`cache #` | upt 10 caches will be available +`cache_size` | size of cache in KB +`cache_level` | level of cache + +Exceptions that can be thrown by `amdsmi_get_gpu_cache_info` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + cache_info = amdsmi_get_gpu_cache_info(device) + for cache_index, cache_values in cache_info.items(): + print(cache_index) + print(cache_values['cache_size']) + print(cache_values['cache_level']) +except AmdSmiException as e: + print(e) +``` + ### amdsmi_get_gpu_vbios_info Description: Returns the static information for the VBIOS on the device. @@ -3189,6 +3268,193 @@ except AmdSmiException as e: print(e) ``` + +### amdsmi_dev_compute_partition_get + +Description: Get the compute partition from the given GPU + +Input parameters: + +* `processor_handle` the device handle + +Output: String of the partition type + +Exceptions that can be thrown by `amdsmi_dev_compute_partition_get` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + compute_partition_type = amdsmi_dev_compute_partition_get(device) + print(compute_partition_type) +except AmdSmiException as e: + print(e) +``` + +### amdsmi_dev_compute_partition_set + +Description: Set the compute partition to the given GPU + +Input parameters: + +* `processor_handle` the device handle +* `compute_partition` the type of compute_partition to set + +Output: String of the partition type + +Exceptions that can be thrown by `amdsmi_dev_compute_partition_set` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + compute_partition = AmdSmiComputePartitionType.SPX + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_compute_partition_set(device, compute_partition) +except AmdSmiException as e: + print(e) +``` + +### amdsmi_dev_compute_partition_reset + +Description: Reset the compute partitioning on the given GPU + +Input parameters: + +* `processor_handle` the device handle + +Output: String of the partition type + +Exceptions that can be thrown by `amdsmi_dev_compute_partition_reset` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_compute_partition_reset(device) +except AmdSmiException as e: + print(e) +``` + +### amdsmi_dev_memory_partition_get + +Description: Get the memory partition from the given GPU + +Input parameters: + +* `processor_handle` the device handle + +Output: String of the partition type + +Exceptions that can be thrown by `amdsmi_dev_memory_partition_get` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + memory_partition_type = amdsmi_dev_memory_partition_get(device) + print(memory_partition_type) +except AmdSmiException as e: + print(e) +``` + +### amdsmi_dev_memory_partition_set + +Description: Set the memory partition to the given GPU + +Input parameters: + +* `processor_handle` the device handle +* `memory_partition` the type of memory_partition to set + +Output: String of the partition type + +Exceptions that can be thrown by `amdsmi_dev_memory_partition_set` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + memory_partition = AmdSmiMemoryPartitionType.NPS1 + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_memory_partition_set(device, memory_partition) +except AmdSmiException as e: + print(e) +``` + +### amdsmi_dev_memory_partition_reset + +Description: Reset the memory partitioning on the given GPU + +Input parameters: + +* `processor_handle` the device handle + +Output: String of the partition type + +Exceptions that can be thrown by `amdsmi_dev_memory_partition_reset` function: + +* `AmdSmiLibraryException` +* `AmdSmiRetryException` +* `AmdSmiParameterException` + +Example: + +```python +try: + devices = amdsmi_get_processor_handles() + if len(devices) == 0: + print("No GPUs on machine") + else: + for device in devices: + amdsmi_dev_memory_partition_reset(device) +except AmdSmiException as e: + print(e) +``` + ### amdsmi_get_xgmi_info Description: Returns XGMI information for the GPU. diff --git a/projects/amdsmi/py-interface/__init__.py b/projects/amdsmi/py-interface/__init__.py index 22a13f7c95..54885114a4 100644 --- a/projects/amdsmi/py-interface/__init__.py +++ b/projects/amdsmi/py-interface/__init__.py @@ -23,12 +23,27 @@ from .amdsmi_interface import amdsmi_init from .amdsmi_interface import amdsmi_shut_down -# Device Descovery +# Device Discovery from .amdsmi_interface import amdsmi_get_processor_type from .amdsmi_interface import amdsmi_get_processor_handles from .amdsmi_interface import amdsmi_get_socket_handles from .amdsmi_interface import amdsmi_get_socket_info +from .amdsmi_interface import amdsmi_get_cpusocket_handles +from .amdsmi_interface import amdsmi_get_cpusocket_info +from .amdsmi_interface import amdsmi_get_cpucore_handles +from .amdsmi_interface import amdsmi_get_cpu_hsmp_proto_ver +from .amdsmi_interface import amdsmi_get_cpu_smu_fw_version +from .amdsmi_interface import amdsmi_get_cpu_core_energy +from .amdsmi_interface import amdsmi_get_cpu_socket_energy +from .amdsmi_interface import amdsmi_get_cpu_prochot_status +from .amdsmi_interface import amdsmi_get_cpu_fclk_mclk +from .amdsmi_interface import amdsmi_get_cpu_cclk_limit +from .amdsmi_interface import amdsmi_get_cpu_socket_current_active_freq_limit +from .amdsmi_interface import amdsmi_get_cpu_socket_freq_range +from .amdsmi_interface import amdsmi_get_cpu_core_current_freq_limit +from .amdsmi_interface import amdsmi_get_cpu_socket_power + from .amdsmi_interface import amdsmi_get_gpu_device_bdf from .amdsmi_interface import amdsmi_get_gpu_device_uuid from .amdsmi_interface import amdsmi_get_processor_handle_from_bdf @@ -40,6 +55,7 @@ from .amdsmi_interface import amdsmi_get_gpu_driver_info from .amdsmi_interface import amdsmi_get_gpu_asic_info from .amdsmi_interface import amdsmi_get_power_cap_info from .amdsmi_interface import amdsmi_get_gpu_vram_info +from .amdsmi_interface import amdsmi_get_gpu_cache_info # # Microcode and VBIOS Information from .amdsmi_interface import amdsmi_get_gpu_vbios_info diff --git a/projects/amdsmi/py-interface/amdsmi_interface.py b/projects/amdsmi/py-interface/amdsmi_interface.py index 98907c2708..2b832eb7cd 100644 --- a/projects/amdsmi/py-interface/amdsmi_interface.py +++ b/projects/amdsmi/py-interface/amdsmi_interface.py @@ -244,6 +244,23 @@ class AmdSmiVoltageType(IntEnum): INVALID = amdsmi_wrapper.AMDSMI_VOLT_TYPE_INVALID +class AmdSmiComputePartitionType(IntEnum): + CPX = amdsmi_wrapper.COMPUTE_PARTITION_CPX + SPX = amdsmi_wrapper.COMPUTE_PARTITION_SPX + DPX = amdsmi_wrapper.COMPUTE_PARTITION_DPX + TPX = amdsmi_wrapper.COMPUTE_PARTITION_TPX + QPX = amdsmi_wrapper.COMPUTE_PARTITION_QPX + INVALID = amdsmi_wrapper.COMPUTE_PARTITION_INVALID + + +class AmdSmiMemoryPartitionType(IntEnum): + NPS1 = amdsmi_wrapper.MEMORY_PARTITION_NPS1 + NPS2 = amdsmi_wrapper.MEMORY_PARTITION_NPS2 + NPS4 = amdsmi_wrapper.MEMORY_PARTITION_NPS4 + NPS8 = amdsmi_wrapper.MEMORY_PARTITION_NPS8 + UNKNOWN = amdsmi_wrapper.MEMORY_PARTITION_UNKNOWN + + class AmdSmiPowerProfilePresetMasks(IntEnum): CUSTOM_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_CUSTOM_MASK VIDEO_MASK = amdsmi_wrapper.AMDSMI_PWR_PROF_PRST_VIDEO_MASK @@ -331,7 +348,8 @@ class AmdSmiProcessorType(IntEnum): class AmdSmiEventReader: def __init__( - self, processor_handle: amdsmi_wrapper.amdsmi_processor_handle, *event_types + self, processor_handle: amdsmi_wrapper.amdsmi_processor_handle, + event_types: List[AmdSmiEvtNotificationType] ): if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): raise AmdSmiParameterException( @@ -358,8 +376,7 @@ class AmdSmiEventReader: processor_handle, ctypes.c_uint64(mask))) def read(self, timestamp, num_elem=10): - self.event_info = ( - amdsmi_wrapper.amdsmi_evt_notification_data_t * num_elem)() + self.event_info = (amdsmi_wrapper.amdsmi_evt_notification_data_t * num_elem)() _check_res( amdsmi_wrapper.amdsmi_get_gpu_event_notification( ctypes.c_int(timestamp), @@ -370,15 +387,12 @@ class AmdSmiEventReader: ret = list() for i in range(0, num_elem): - if self.event_info[i].event in set( - event.value for event in AmdSmiEvtNotificationType - ): + unique_event_values = set(event.value for event in AmdSmiEvtNotificationType) + if self.event_info[i].event in unique_event_values: ret.append( { "processor_handle": self.event_info[i].processor_handle, - "event": AmdSmiEvtNotificationType( - self.event_info[i].event - ).name, + "event": AmdSmiEvtNotificationType(self.event_info[i].event).name, "message": self.event_info[i].message.decode("utf-8"), } ) @@ -532,6 +546,34 @@ def amdsmi_get_socket_handles() -> List[amdsmi_wrapper.amdsmi_socket_handle]: return sockets +def amdsmi_get_cpusocket_handles() -> List[amdsmi_wrapper.amdsmi_cpusocket_handle]: + """ + Function that gets cpu socket handles. Wraps the same named function call. + + Parameters: + `None`. + + Returns: + `List`: List containing all of the found cpu socket handles. + """ + socket_count = ctypes.c_uint32(0) + null_ptr = ctypes.POINTER(amdsmi_wrapper.amdsmi_cpusocket_handle)() + _check_res( + amdsmi_wrapper.amdsmi_get_cpusocket_handles( + ctypes.byref(socket_count), null_ptr) + ) + socket_handles = (amdsmi_wrapper.amdsmi_cpusocket_handle * + socket_count.value)() + _check_res( + amdsmi_wrapper.amdsmi_get_cpusocket_handles( + ctypes.byref(socket_count), socket_handles) + ) + sockets = [ + amdsmi_wrapper.amdsmi_cpusocket_handle(socket_handles[sock_idx]) + for sock_idx in range(socket_count.value) + ] + + return sockets def amdsmi_get_socket_info(socket_handle): if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_socket_handle): @@ -546,6 +588,19 @@ def amdsmi_get_socket_info(socket_handle): return socket_info.value.decode() +def amdsmi_get_cpusocket_info(socket_handle): + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle) + + socket_id = ctypes.c_uint32() + _check_res( + amdsmi_wrapper.amdsmi_get_cpusocket_info( + socket_handle, socket_id) + ) + + return socket_id + def amdsmi_get_processor_handles() -> List[amdsmi_wrapper.amdsmi_processor_handle]: socket_handles = amdsmi_get_socket_handles() devices = [] @@ -577,6 +632,249 @@ def amdsmi_get_processor_handles() -> List[amdsmi_wrapper.amdsmi_processor_handl return devices +def amdsmi_get_cpucore_handles() -> List[amdsmi_wrapper.amdsmi_processor_handle]: + socket_handles = amdsmi_get_cpusocket_handles() + processors = [] + for socket in socket_handles: + processor_count = ctypes.c_uint32() + null_ptr = ctypes.POINTER(amdsmi_wrapper.amdsmi_processor_handle)() + _check_res( + amdsmi_wrapper.amdsmi_get_cpucore_handles( + socket, + ctypes.byref(processor_count), + null_ptr, + ) + ) + processor_handles = ( + amdsmi_wrapper.amdsmi_processor_handle * processor_count.value)() + _check_res( + amdsmi_wrapper.amdsmi_get_cpucore_handles( + socket, + ctypes.byref(processor_count), + processor_handles, + ) + ) + processors.extend( + [ + amdsmi_wrapper.amdsmi_processor_handle(processor_handles[dev_idx]) + for dev_idx in range(processor_count.value) + ] + ) + + return processors + +def amdsmi_get_cpu_hsmp_proto_ver( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, +) -> int: + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + + proto_ver = ctypes.c_uint32() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_hsmp_proto_ver( + socket_handle, ctypes.byref(proto_ver) + ) + ) + + return proto_ver.value + +def amdsmi_get_cpu_smu_fw_version(socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle): + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + + smu_fw = amdsmi_wrapper.amdsmi_smu_fw_version_t() + + _check_res(amdsmi_wrapper.amdsmi_get_cpu_smu_fw_version(socket_handle, smu_fw)) + + return { + "smu_fw_debug_ver_num": smu_fw.debug, + "smu_fw_minor_ver_num": smu_fw.minor, + "smu_fw_major_ver_num": smu_fw.major + } + +def amdsmi_get_cpu_core_energy( + processor_handle: amdsmi_wrapper.amdsmi_processor_handle, core_idx: int +) -> int: + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + if not isinstance(core_idx, int): + raise AmdSmiParameterException(core_idx, int) + + penergy = ctypes.c_uint64() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_core_energy( + processor_handle, core_idx, ctypes.byref(penergy) + ) + ) + + return penergy.value + +def amdsmi_get_cpu_socket_energy( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, sock_idx: int +) -> int: + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + if not isinstance(sock_idx, int): + raise AmdSmiParameterException(sock_idx, int) + + penergy = ctypes.c_uint64() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_socket_energy( + socket_handle, sock_idx, ctypes.byref(penergy) + ) + ) + + return penergy.value + +def amdsmi_get_cpu_prochot_status( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, sock_idx: int +) -> int: + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + if not isinstance(sock_idx, int): + raise AmdSmiParameterException(sock_idx, int) + + prochot = ctypes.c_uint32() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_socket_energy( + socket_handle, sock_idx, ctypes.byref(prochot) + ) + ) + + return prochot.value + +def amdsmi_get_cpu_fclk_mclk( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, sock_idx: int +): + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + if not isinstance(sock_idx, int): + raise AmdSmiParameterException(sock_idx, int) + + fclk = ctypes.c_uint32() + mclk = ctypes.c_uint32() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_fclk_mclk( + socket_handle, sock_idx, ctypes.byref(fclk), ctypes.byref(mclk) + ) + ) + + return { + "fclk": fclk.value, + "mclk": mclk.value + } + +def amdsmi_get_cpu_cclk_limit( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, sock_idx: int +) -> int: + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + if not isinstance(sock_idx, int): + raise AmdSmiParameterException(sock_idx, int) + + cclk = ctypes.c_uint32() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_cclk_limit( + socket_handle, sock_idx, ctypes.byref(cclk) + ) + ) + + return cclk.value + +def amdsmi_get_cpu_socket_current_active_freq_limit( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, sock_idx: int +) -> int: + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + if not isinstance(sock_idx, int): + raise AmdSmiParameterException(sock_idx, int) + + freq = ctypes.c_uint16() + src_type = ctypes.pointer(ctypes.pointer(ctypes.c_char())) + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_socket_current_active_freq_limit( + socket_handle, sock_idx, ctypes.byref(freq), src_type + ) + ) + + return freq.value + +def amdsmi_get_cpu_socket_freq_range( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, sock_idx: int +): + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + if not isinstance(sock_idx, int): + raise AmdSmiParameterException(sock_idx, int) + + freq_max = ctypes.c_uint16() + freq_min = ctypes.c_uint16() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_socket_freq_range( + socket_handle, sock_idx, ctypes.byref(freq_max), ctypes.byref(freq_min) + ) + ) + + return { + "max_socket_freq": freq_max.value, + "min_socket_freq": freq_min.value + } + +def amdsmi_get_cpu_core_current_freq_limit( + processor_handle: amdsmi_wrapper.amdsmi_processor_handle, core_idx: int +) -> int: + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + if not isinstance(core_idx, int): + raise AmdSmiParameterException(core_idx, int) + + freq = ctypes.c_uint32() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_core_current_freq_limit( + processor_handle, core_idx, ctypes.byref(freq) + ) + ) + + return freq.value + +def amdsmi_get_cpu_socket_power( + socket_handle: amdsmi_wrapper.amdsmi_cpusocket_handle, sock_idx: int +) -> int: + if not isinstance(socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle): + raise AmdSmiParameterException( + socket_handle, amdsmi_wrapper.amdsmi_cpusocket_handle + ) + if not isinstance(sock_idx, int): + raise AmdSmiParameterException(sock_idx, int) + + ppower = ctypes.c_uint32() + _check_res( + amdsmi_wrapper.amdsmi_get_cpu_socket_power( + socket_handle, sock_idx, ctypes.byref(ppower) + ) + ) + + return ppower.value def amdsmi_init(flag=AmdSmiInitFlags.INIT_AMD_GPUS): if not isinstance(flag, AmdSmiInitFlags): @@ -691,6 +989,30 @@ def amdsmi_get_gpu_vram_info( } +def amdsmi_get_gpu_cache_info( + processor_handle: amdsmi_wrapper.amdsmi_processor_handle, +) -> Dict[str, Any]: + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + cache_info = amdsmi_wrapper.amdsmi_gpu_cache_info_t() + _check_res( + amdsmi_wrapper.amdsmi_get_gpu_cache_info( + processor_handle, ctypes.byref(cache_info)) + ) + + cache_info_dict = {} + for cache_index in range(cache_info.num_cache_types): + cache_size = cache_info.cache[cache_index].cache_size_kb + cache_level = cache_info.cache[cache_index].cache_level + cache_info_dict[f"cache {cache_index}"] = {"cache_size": cache_size, + "cache_level": cache_level} + + return cache_info_dict + + def amdsmi_get_gpu_vbios_info( processor_handle: amdsmi_wrapper.amdsmi_processor_handle, ) -> Dict[str, Any]: @@ -839,14 +1161,22 @@ def amdsmi_get_gpu_ras_feature_info( raise AmdSmiParameterException( processor_handle, amdsmi_wrapper.amdsmi_processor_handle ) - # Dummy data waiting on population - ras_info = {"eeprom_version": "N/A", - "parity_schema" : "N/A", - "single_bit_schema" : "N/A", - "double_bit_schema" : "N/A", - "poison_schema" : "N/A"} - return ras_info + ras_feature = amdsmi_wrapper.amdsmi_ras_feature_t() + + _check_res( + amdsmi_wrapper.amdsmi_get_gpu_ras_feature_info( + processor_handle, ctypes.byref(ras_feature) + ) + ) + + return { + "eeprom_version": ras_feature.ras_eeprom_version, + "parity_schema" : bool(ras_feature.ecc_correction_schema_flag & 1), + "single_bit_schema" : bool(ras_feature.ecc_correction_schema_flag & 2), + "double_bit_schema" : bool(ras_feature.ecc_correction_schema_flag & 4), + "poison_schema" : bool(ras_feature.ecc_correction_schema_flag & 8) + } def amdsmi_get_gpu_ras_block_features_enabled( @@ -1342,6 +1672,98 @@ def amdsmi_is_P2P_accessible( return accessible.value +def amdsmi_dev_compute_partition_get(processor_handle: amdsmi_wrapper.amdsmi_processor_handle): + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + length = ctypes.c_uint32() + length.value = _AMDSMI_STRING_LENGTH + + compute_partition = ctypes.create_string_buffer(_AMDSMI_STRING_LENGTH) + + _check_res( + amdsmi_wrapper.amdsmi_dev_compute_partition_get( + processor_handle, compute_partition, length + ) + ) + + return compute_partition.value.decode("utf-8") + + +def amdsmi_dev_compute_partition_set(processor_handle: amdsmi_wrapper.amdsmi_processor_handle, + compute_partition: AmdSmiComputePartitionType): + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + if not isinstance(compute_partition, AmdSmiComputePartitionType): + raise AmdSmiParameterException(compute_partition, AmdSmiComputePartitionType) + + _check_res( + amdsmi_wrapper.amdsmi_dev_compute_partition_set( + processor_handle, compute_partition + ) + ) + + +def amdsmi_dev_compute_partition_reset(processor_handle: amdsmi_wrapper.amdsmi_processor_handle): + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + _check_res(amdsmi_wrapper.amdsmi_dev_compute_partition_reset(processor_handle)) + + +def amdsmi_dev_memory_partition_get(processor_handle: amdsmi_wrapper.amdsmi_processor_handle): + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + length = ctypes.c_uint32() + length.value = _AMDSMI_STRING_LENGTH + + memory_partition = ctypes.create_string_buffer(_AMDSMI_STRING_LENGTH) + + _check_res( + amdsmi_wrapper.amdsmi_dev_memory_partition_get( + processor_handle, memory_partition, length + ) + ) + + return memory_partition.value.decode("utf-8") + + +def amdsmi_dev_memory_partition_set(processor_handle: amdsmi_wrapper.amdsmi_processor_handle, + memory_partition: AmdSmiMemoryPartitionType): + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + if not isinstance(memory_partition, AmdSmiMemoryPartitionType): + raise AmdSmiParameterException(memory_partition, AmdSmiMemoryPartitionType) + + _check_res( + amdsmi_wrapper.amdsmi_dev_memory_partition_set( + processor_handle, memory_partition + ) + ) + + +def amdsmi_dev_memory_partition_reset(processor_handle: amdsmi_wrapper.amdsmi_processor_handle): + if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): + raise AmdSmiParameterException( + processor_handle, amdsmi_wrapper.amdsmi_processor_handle + ) + + _check_res(amdsmi_wrapper.amdsmi_dev_memory_partition_reset(processor_handle)) + + def amdsmi_get_xgmi_info(processor_handle: amdsmi_wrapper.amdsmi_processor_handle): if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle): raise AmdSmiParameterException( diff --git a/projects/amdsmi/py-interface/amdsmi_wrapper.py b/projects/amdsmi/py-interface/amdsmi_wrapper.py index 1e48cf7636..a7a16ce2de 100644 --- a/projects/amdsmi/py-interface/amdsmi_wrapper.py +++ b/projects/amdsmi/py-interface/amdsmi_wrapper.py @@ -23,7 +23,7 @@ import os # -*- coding: utf-8 -*- # -# TARGET arch is: ['-I/usr/lib64/clang/17/include'] +# TARGET arch is: ['-I/usr/lib/llvm-16/lib/clang/16/include', '-DENABLE_ESMI_LIB'] # WORD_SIZE is: 8 # POINTER_SIZE is: 8 # LONGDOUBLE_SIZE is: 16 @@ -230,6 +230,7 @@ CONTAINER_DOCKER = 1 amdsmi_container_types_t = ctypes.c_uint32 # enum amdsmi_processor_handle = ctypes.POINTER(None) amdsmi_socket_handle = ctypes.POINTER(None) +amdsmi_cpusocket_handle = ctypes.POINTER(None) # values for enumeration 'processor_type_t' processor_type_t__enumvalues = { @@ -368,6 +369,38 @@ CLK_TYPE_DCLK1 = 9 CLK_TYPE__MAX = 9 amdsmi_clk_type_t = ctypes.c_uint32 # enum +# values for enumeration 'amdsmi_compute_partition_type_t' +amdsmi_compute_partition_type_t__enumvalues = { + 0: 'COMPUTE_PARTITION_INVALID', + 1: 'COMPUTE_PARTITION_CPX', + 2: 'COMPUTE_PARTITION_SPX', + 3: 'COMPUTE_PARTITION_DPX', + 4: 'COMPUTE_PARTITION_TPX', + 5: 'COMPUTE_PARTITION_QPX', +} +COMPUTE_PARTITION_INVALID = 0 +COMPUTE_PARTITION_CPX = 1 +COMPUTE_PARTITION_SPX = 2 +COMPUTE_PARTITION_DPX = 3 +COMPUTE_PARTITION_TPX = 4 +COMPUTE_PARTITION_QPX = 5 +amdsmi_compute_partition_type_t = ctypes.c_uint32 # enum + +# values for enumeration 'amdsmi_memory_partition_type_t' +amdsmi_memory_partition_type_t__enumvalues = { + 0: 'MEMORY_PARTITION_UNKNOWN', + 1: 'MEMORY_PARTITION_NPS1', + 2: 'MEMORY_PARTITION_NPS2', + 3: 'MEMORY_PARTITION_NPS4', + 4: 'MEMORY_PARTITION_NPS8', +} +MEMORY_PARTITION_UNKNOWN = 0 +MEMORY_PARTITION_NPS1 = 1 +MEMORY_PARTITION_NPS2 = 2 +MEMORY_PARTITION_NPS4 = 3 +MEMORY_PARTITION_NPS8 = 4 +amdsmi_memory_partition_type_t = ctypes.c_uint32 # enum + # values for enumeration 'amdsmi_temperature_type_t' amdsmi_temperature_type_t__enumvalues = { 0: 'TEMPERATURE_TYPE_EDGE', @@ -1447,6 +1480,16 @@ struct_amdsmi_gpu_metrics_t._fields_ = [ ] amdsmi_gpu_metrics_t = struct_amdsmi_gpu_metrics_t +class struct_amdsmi_ras_feature_t(Structure): + pass + +struct_amdsmi_ras_feature_t._pack_ = 1 # source:False +struct_amdsmi_ras_feature_t._fields_ = [ + ('ras_eeprom_version', ctypes.c_uint32), + ('ecc_correction_schema_flag', ctypes.c_uint32), +] + +amdsmi_ras_feature_t = struct_amdsmi_ras_feature_t class struct_amdsmi_error_count_t(Structure): pass @@ -1499,6 +1542,101 @@ struct_amdsmi_process_info_t._fields_ = [ ] amdsmi_process_info_t = struct_amdsmi_process_info_t +class struct_amdsmi_smu_fw_version_t(Structure): + pass + +struct_amdsmi_smu_fw_version_t._pack_ = 1 # source:False +struct_amdsmi_smu_fw_version_t._fields_ = [ + ('debug', ctypes.c_ubyte), + ('minor', ctypes.c_ubyte), + ('major', ctypes.c_ubyte), + ('unused', ctypes.c_ubyte), +] + +amdsmi_smu_fw_version_t = struct_amdsmi_smu_fw_version_t +class struct_amdsmi_ddr_bw_metrics_t(Structure): + pass + +struct_amdsmi_ddr_bw_metrics_t._pack_ = 1 # source:False +struct_amdsmi_ddr_bw_metrics_t._fields_ = [ + ('max_bw', ctypes.c_uint32), + ('utilized_bw', ctypes.c_uint32), + ('utilized_pct', ctypes.c_uint32), +] + +amdsmi_ddr_bw_metrics_t = struct_amdsmi_ddr_bw_metrics_t +class struct_amdsmi_temp_range_refresh_rate_t(Structure): + pass + +struct_amdsmi_temp_range_refresh_rate_t._pack_ = 1 # source:False +struct_amdsmi_temp_range_refresh_rate_t._fields_ = [ + ('range', ctypes.c_ubyte, 3), + ('ref_rate', ctypes.c_ubyte, 1), + ('PADDING_0', ctypes.c_uint8, 4), +] + +amdsmi_temp_range_refresh_rate_t = struct_amdsmi_temp_range_refresh_rate_t +class struct_amdsmi_dimm_power_t(Structure): + pass + +struct_amdsmi_dimm_power_t._pack_ = 1 # source:False +struct_amdsmi_dimm_power_t._fields_ = [ + ('power', ctypes.c_uint16, 15), + ('PADDING_0', ctypes.c_uint8, 1), + ('update_rate', ctypes.c_uint16, 9), + ('PADDING_1', ctypes.c_uint8, 7), + ('dimm_addr', ctypes.c_uint16, 8), + ('PADDING_2', ctypes.c_uint8, 8), +] + +amdsmi_dimm_power_t = struct_amdsmi_dimm_power_t +class struct_amdsmi_dimm_thermal_t(Structure): + pass + +struct_amdsmi_dimm_thermal_t._pack_ = 1 # source:False +struct_amdsmi_dimm_thermal_t._fields_ = [ + ('sensor', ctypes.c_uint16, 11), + ('PADDING_0', ctypes.c_uint8, 5), + ('update_rate', ctypes.c_uint16, 9), + ('PADDING_1', ctypes.c_uint8, 7), + ('dimm_addr', ctypes.c_uint16, 8), + ('PADDING_2', ctypes.c_uint32, 24), + ('temp', ctypes.c_float), +] + +amdsmi_dimm_thermal_t = struct_amdsmi_dimm_thermal_t + +# values for enumeration 'amdsmi_io_bw_encoding_t' +amdsmi_io_bw_encoding_t__enumvalues = { + 1: 'AGG_BW0', + 2: 'RD_BW0', + 4: 'WR_BW0', +} +AGG_BW0 = 1 +RD_BW0 = 2 +WR_BW0 = 4 +amdsmi_io_bw_encoding_t = ctypes.c_uint32 # enum +class struct_amdsmi_link_id_bw_type_t(Structure): + pass + +struct_amdsmi_link_id_bw_type_t._pack_ = 1 # source:False +struct_amdsmi_link_id_bw_type_t._fields_ = [ + ('bw_type', amdsmi_io_bw_encoding_t), + ('PADDING_0', ctypes.c_ubyte * 4), + ('link_name', ctypes.POINTER(ctypes.c_char)), +] + +amdsmi_link_id_bw_type_t = struct_amdsmi_link_id_bw_type_t +class struct_amdsmi_dpm_level_t(Structure): + pass + +struct_amdsmi_dpm_level_t._pack_ = 1 # source:False +struct_amdsmi_dpm_level_t._fields_ = [ + ('max_dpm_level', ctypes.c_ubyte), + ('min_dpm_level', ctypes.c_ubyte), +] + +amdsmi_dpm_level_t = struct_amdsmi_dpm_level_t uint64_t = ctypes.c_uint64 amdsmi_init = _libraries['libamd_smi.so'].amdsmi_init amdsmi_init.restype = amdsmi_status_t @@ -1509,13 +1647,23 @@ amdsmi_shut_down.argtypes = [] amdsmi_get_socket_handles = _libraries['libamd_smi.so'].amdsmi_get_socket_handles amdsmi_get_socket_handles.restype = amdsmi_status_t amdsmi_get_socket_handles.argtypes = [ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.POINTER(None))] +amdsmi_get_cpusocket_handles = _libraries['libamd_smi.so'].amdsmi_get_cpusocket_handles +amdsmi_get_cpusocket_handles.restype = amdsmi_status_t +amdsmi_get_cpusocket_handles.argtypes = [ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.POINTER(None))] size_t = ctypes.c_uint64 amdsmi_get_socket_info = _libraries['libamd_smi.so'].amdsmi_get_socket_info amdsmi_get_socket_info.restype = amdsmi_status_t amdsmi_get_socket_info.argtypes = [amdsmi_socket_handle, size_t, ctypes.POINTER(ctypes.c_char)] +uint32_t = ctypes.c_uint32 +amdsmi_get_cpusocket_info = _libraries['libamd_smi.so'].amdsmi_get_cpusocket_info +amdsmi_get_cpusocket_info.restype = amdsmi_status_t +amdsmi_get_cpusocket_info.argtypes = [amdsmi_cpusocket_handle, uint32_t] amdsmi_get_processor_handles = _libraries['libamd_smi.so'].amdsmi_get_processor_handles amdsmi_get_processor_handles.restype = amdsmi_status_t amdsmi_get_processor_handles.argtypes = [amdsmi_socket_handle, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.POINTER(None))] +amdsmi_get_cpucore_handles = _libraries['libamd_smi.so'].amdsmi_get_cpucore_handles +amdsmi_get_cpucore_handles.restype = amdsmi_status_t +amdsmi_get_cpucore_handles.argtypes = [amdsmi_cpusocket_handle, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.POINTER(None))] amdsmi_get_processor_type = _libraries['libamd_smi.so'].amdsmi_get_processor_type amdsmi_get_processor_type.restype = amdsmi_status_t amdsmi_get_processor_type.argtypes = [amdsmi_processor_handle, ctypes.POINTER(processor_type_t)] @@ -1531,7 +1679,6 @@ amdsmi_get_gpu_revision.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctyp amdsmi_get_gpu_vendor_name = _libraries['libamd_smi.so'].amdsmi_get_gpu_vendor_name amdsmi_get_gpu_vendor_name.restype = amdsmi_status_t amdsmi_get_gpu_vendor_name.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_char), size_t] -uint32_t = ctypes.c_uint32 amdsmi_get_gpu_vram_vendor = _libraries['libamd_smi.so'].amdsmi_get_gpu_vram_vendor amdsmi_get_gpu_vram_vendor.restype = amdsmi_status_t amdsmi_get_gpu_vram_vendor.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_char), uint32_t] @@ -1577,6 +1724,9 @@ amdsmi_get_gpu_memory_usage.argtypes = [amdsmi_processor_handle, amdsmi_memory_t amdsmi_get_gpu_bad_page_info = _libraries['libamd_smi.so'].amdsmi_get_gpu_bad_page_info amdsmi_get_gpu_bad_page_info.restype = amdsmi_status_t amdsmi_get_gpu_bad_page_info.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(struct_amdsmi_retired_page_record_t)] +amdsmi_get_gpu_ras_feature_info = _libraries['libamd_smi.so'].amdsmi_get_gpu_ras_feature_info +amdsmi_get_gpu_ras_feature_info.restype = amdsmi_status_t +amdsmi_get_gpu_ras_feature_info.argtypes = [amdsmi_processor_handle, ctypes.POINTER(struct_amdsmi_ras_feature_t)] amdsmi_get_gpu_ras_block_features_enabled = _libraries['libamd_smi.so'].amdsmi_get_gpu_ras_block_features_enabled amdsmi_get_gpu_ras_block_features_enabled.restype = amdsmi_status_t amdsmi_get_gpu_ras_block_features_enabled.argtypes = [amdsmi_processor_handle, amdsmi_gpu_block_t, ctypes.POINTER(amdsmi_ras_err_state_t)] @@ -1724,6 +1874,24 @@ amdsmi_topo_get_link_type.argtypes = [amdsmi_processor_handle, amdsmi_processor_ amdsmi_is_P2P_accessible = _libraries['libamd_smi.so'].amdsmi_is_P2P_accessible amdsmi_is_P2P_accessible.restype = amdsmi_status_t amdsmi_is_P2P_accessible.argtypes = [amdsmi_processor_handle, amdsmi_processor_handle, ctypes.POINTER(ctypes.c_bool)] +amdsmi_dev_compute_partition_get = _libraries['libamd_smi.so'].amdsmi_dev_compute_partition_get +amdsmi_dev_compute_partition_get.restype = amdsmi_status_t +amdsmi_dev_compute_partition_get.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_char), uint32_t] +amdsmi_dev_compute_partition_set = _libraries['libamd_smi.so'].amdsmi_dev_compute_partition_set +amdsmi_dev_compute_partition_set.restype = amdsmi_status_t +amdsmi_dev_compute_partition_set.argtypes = [amdsmi_processor_handle, amdsmi_compute_partition_type_t] +amdsmi_dev_compute_partition_reset = _libraries['libamd_smi.so'].amdsmi_dev_compute_partition_reset +amdsmi_dev_compute_partition_reset.restype = amdsmi_status_t +amdsmi_dev_compute_partition_reset.argtypes = [amdsmi_processor_handle] +amdsmi_dev_memory_partition_get = _libraries['libamd_smi.so'].amdsmi_dev_memory_partition_get +amdsmi_dev_memory_partition_get.restype = amdsmi_status_t +amdsmi_dev_memory_partition_get.argtypes = [amdsmi_processor_handle, ctypes.POINTER(ctypes.c_char), uint32_t] +amdsmi_dev_memory_partition_set = _libraries['libamd_smi.so'].amdsmi_dev_memory_partition_set +amdsmi_dev_memory_partition_set.restype = amdsmi_status_t +amdsmi_dev_memory_partition_set.argtypes = [amdsmi_processor_handle, amdsmi_memory_partition_type_t] +amdsmi_dev_memory_partition_reset = _libraries['libamd_smi.so'].amdsmi_dev_memory_partition_reset +amdsmi_dev_memory_partition_reset.restype = amdsmi_status_t +amdsmi_dev_memory_partition_reset.argtypes = [amdsmi_processor_handle] amdsmi_init_gpu_event_notification = _libraries['libamd_smi.so'].amdsmi_init_gpu_event_notification amdsmi_init_gpu_event_notification.restype = amdsmi_status_t amdsmi_init_gpu_event_notification.argtypes = [amdsmi_processor_handle] @@ -1790,8 +1958,144 @@ amdsmi_get_gpu_process_info.argtypes = [amdsmi_processor_handle, amdsmi_process_ amdsmi_get_gpu_total_ecc_count = _libraries['libamd_smi.so'].amdsmi_get_gpu_total_ecc_count amdsmi_get_gpu_total_ecc_count.restype = amdsmi_status_t amdsmi_get_gpu_total_ecc_count.argtypes = [amdsmi_processor_handle, ctypes.POINTER(struct_amdsmi_error_count_t)] +amdsmi_get_cpu_core_energy = _libraries['libamd_smi.so'].amdsmi_get_cpu_core_energy +amdsmi_get_cpu_core_energy.restype = amdsmi_status_t +amdsmi_get_cpu_core_energy.argtypes = [amdsmi_processor_handle, uint32_t, ctypes.POINTER(ctypes.c_uint64)] +amdsmi_get_cpu_socket_energy = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_energy +amdsmi_get_cpu_socket_energy.restype = amdsmi_status_t +amdsmi_get_cpu_socket_energy.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint64)] +amdsmi_get_cpu_smu_fw_version = _libraries['libamd_smi.so'].amdsmi_get_cpu_smu_fw_version +amdsmi_get_cpu_smu_fw_version.restype = amdsmi_status_t +amdsmi_get_cpu_smu_fw_version.argtypes = [amdsmi_cpusocket_handle, ctypes.POINTER(struct_amdsmi_smu_fw_version_t)] +amdsmi_get_cpu_hsmp_proto_ver = _libraries['libamd_smi.so'].amdsmi_get_cpu_hsmp_proto_ver +amdsmi_get_cpu_hsmp_proto_ver.restype = amdsmi_status_t +amdsmi_get_cpu_hsmp_proto_ver.argtypes = [amdsmi_cpusocket_handle, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_prochot_status = _libraries['libamd_smi.so'].amdsmi_get_cpu_prochot_status +amdsmi_get_cpu_prochot_status.restype = amdsmi_status_t +amdsmi_get_cpu_prochot_status.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_fclk_mclk = _libraries['libamd_smi.so'].amdsmi_get_cpu_fclk_mclk +amdsmi_get_cpu_fclk_mclk.restype = amdsmi_status_t +amdsmi_get_cpu_fclk_mclk.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_cclk_limit = _libraries['libamd_smi.so'].amdsmi_get_cpu_cclk_limit +amdsmi_get_cpu_cclk_limit.restype = amdsmi_status_t +amdsmi_get_cpu_cclk_limit.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_socket_current_active_freq_limit = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_current_active_freq_limit +amdsmi_get_cpu_socket_current_active_freq_limit.restype = amdsmi_status_t +amdsmi_get_cpu_socket_current_active_freq_limit.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint16), ctypes.POINTER(ctypes.POINTER(ctypes.c_char))] +amdsmi_get_cpu_socket_freq_range = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_freq_range +amdsmi_get_cpu_socket_freq_range.restype = amdsmi_status_t +amdsmi_get_cpu_socket_freq_range.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint16), ctypes.POINTER(ctypes.c_uint16)] +amdsmi_get_cpu_core_current_freq_limit = _libraries['libamd_smi.so'].amdsmi_get_cpu_core_current_freq_limit +amdsmi_get_cpu_core_current_freq_limit.restype = amdsmi_status_t +amdsmi_get_cpu_core_current_freq_limit.argtypes = [amdsmi_processor_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +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_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_socket_power_cap = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_power_cap +amdsmi_get_cpu_socket_power_cap.restype = amdsmi_status_t +amdsmi_get_cpu_socket_power_cap.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_socket_power_cap_max = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_power_cap_max +amdsmi_get_cpu_socket_power_cap_max.restype = amdsmi_status_t +amdsmi_get_cpu_socket_power_cap_max.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_pwr_svi_telemetry_all_rails = _libraries['libamd_smi.so'].amdsmi_get_cpu_pwr_svi_telemetry_all_rails +amdsmi_get_cpu_pwr_svi_telemetry_all_rails.restype = amdsmi_status_t +amdsmi_get_cpu_pwr_svi_telemetry_all_rails.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_set_cpu_socket_power_cap = _libraries['libamd_smi.so'].amdsmi_set_cpu_socket_power_cap +amdsmi_set_cpu_socket_power_cap.restype = amdsmi_status_t +amdsmi_set_cpu_socket_power_cap.argtypes = [amdsmi_cpusocket_handle, uint32_t, uint32_t] +uint8_t = ctypes.c_uint8 +amdsmi_set_cpu_pwr_efficiency_mode = _libraries['libamd_smi.so'].amdsmi_set_cpu_pwr_efficiency_mode +amdsmi_set_cpu_pwr_efficiency_mode.restype = amdsmi_status_t +amdsmi_set_cpu_pwr_efficiency_mode.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t] +amdsmi_get_cpu_core_boostlimit = _libraries['libamd_smi.so'].amdsmi_get_cpu_core_boostlimit +amdsmi_get_cpu_core_boostlimit.restype = amdsmi_status_t +amdsmi_get_cpu_core_boostlimit.argtypes = [amdsmi_processor_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_socket_c0_residency = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_c0_residency +amdsmi_get_cpu_socket_c0_residency.restype = amdsmi_status_t +amdsmi_get_cpu_socket_c0_residency.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_set_cpu_core_boostlimit = _libraries['libamd_smi.so'].amdsmi_set_cpu_core_boostlimit +amdsmi_set_cpu_core_boostlimit.restype = amdsmi_status_t +amdsmi_set_cpu_core_boostlimit.argtypes = [amdsmi_processor_handle, uint32_t, uint32_t] +amdsmi_set_cpu_socket_boostlimit = _libraries['libamd_smi.so'].amdsmi_set_cpu_socket_boostlimit +amdsmi_set_cpu_socket_boostlimit.restype = amdsmi_status_t +amdsmi_set_cpu_socket_boostlimit.argtypes = [amdsmi_cpusocket_handle, uint32_t, uint32_t] +amdsmi_get_cpu_ddr_bw = _libraries['libamd_smi.so'].amdsmi_get_cpu_ddr_bw +amdsmi_get_cpu_ddr_bw.restype = amdsmi_status_t +amdsmi_get_cpu_ddr_bw.argtypes = [amdsmi_cpusocket_handle, ctypes.POINTER(struct_amdsmi_ddr_bw_metrics_t)] +amdsmi_get_cpu_socket_temperature = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_temperature +amdsmi_get_cpu_socket_temperature.restype = amdsmi_status_t +amdsmi_get_cpu_socket_temperature.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_dimm_temp_range_and_refresh_rate = _libraries['libamd_smi.so'].amdsmi_get_cpu_dimm_temp_range_and_refresh_rate +amdsmi_get_cpu_dimm_temp_range_and_refresh_rate.restype = amdsmi_status_t +amdsmi_get_cpu_dimm_temp_range_and_refresh_rate.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t, ctypes.POINTER(struct_amdsmi_temp_range_refresh_rate_t)] +amdsmi_get_cpu_dimm_power_consumption = _libraries['libamd_smi.so'].amdsmi_get_cpu_dimm_power_consumption +amdsmi_get_cpu_dimm_power_consumption.restype = amdsmi_status_t +amdsmi_get_cpu_dimm_power_consumption.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t, ctypes.POINTER(struct_amdsmi_dimm_power_t)] +amdsmi_get_cpu_dimm_thermal_sensor = _libraries['libamd_smi.so'].amdsmi_get_cpu_dimm_thermal_sensor +amdsmi_get_cpu_dimm_thermal_sensor.restype = amdsmi_status_t +amdsmi_get_cpu_dimm_thermal_sensor.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t, ctypes.POINTER(struct_amdsmi_dimm_thermal_t)] +amdsmi_set_cpu_xgmi_width = _libraries['libamd_smi.so'].amdsmi_set_cpu_xgmi_width +amdsmi_set_cpu_xgmi_width.restype = amdsmi_status_t +amdsmi_set_cpu_xgmi_width.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t] +amdsmi_set_cpu_gmi3_link_width_range = _libraries['libamd_smi.so'].amdsmi_set_cpu_gmi3_link_width_range +amdsmi_set_cpu_gmi3_link_width_range.restype = amdsmi_status_t +amdsmi_set_cpu_gmi3_link_width_range.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t, uint8_t] +amdsmi_cpu_apb_enable = _libraries['libamd_smi.so'].amdsmi_cpu_apb_enable +amdsmi_cpu_apb_enable.restype = amdsmi_status_t +amdsmi_cpu_apb_enable.argtypes = [amdsmi_cpusocket_handle, uint32_t] +amdsmi_cpu_apb_disable = _libraries['libamd_smi.so'].amdsmi_cpu_apb_disable +amdsmi_cpu_apb_disable.restype = amdsmi_status_t +amdsmi_cpu_apb_disable.argtypes = [amdsmi_cpusocket_handle, uint32_t, uint8_t] +amdsmi_set_cpu_socket_lclk_dpm_level = _libraries['libamd_smi.so'].amdsmi_set_cpu_socket_lclk_dpm_level +amdsmi_set_cpu_socket_lclk_dpm_level.restype = amdsmi_status_t +amdsmi_set_cpu_socket_lclk_dpm_level.argtypes = [amdsmi_cpusocket_handle, uint32_t, uint8_t, uint8_t, uint8_t] +amdsmi_get_cpu_socket_lclk_dpm_level = _libraries['libamd_smi.so'].amdsmi_get_cpu_socket_lclk_dpm_level +amdsmi_get_cpu_socket_lclk_dpm_level.restype = amdsmi_status_t +amdsmi_get_cpu_socket_lclk_dpm_level.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t, ctypes.POINTER(struct_amdsmi_dpm_level_t)] +amdsmi_set_cpu_pcie_link_rate = _libraries['libamd_smi.so'].amdsmi_set_cpu_pcie_link_rate +amdsmi_set_cpu_pcie_link_rate.restype = amdsmi_status_t +amdsmi_set_cpu_pcie_link_rate.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t, ctypes.POINTER(ctypes.c_ubyte)] +amdsmi_set_cpu_df_pstate_range = _libraries['libamd_smi.so'].amdsmi_set_cpu_df_pstate_range +amdsmi_set_cpu_df_pstate_range.restype = amdsmi_status_t +amdsmi_set_cpu_df_pstate_range.argtypes = [amdsmi_cpusocket_handle, uint8_t, uint8_t, uint8_t] +amdsmi_get_cpu_current_io_bandwidth = _libraries['libamd_smi.so'].amdsmi_get_cpu_current_io_bandwidth +amdsmi_get_cpu_current_io_bandwidth.restype = amdsmi_status_t +amdsmi_get_cpu_current_io_bandwidth.argtypes = [amdsmi_cpusocket_handle, uint8_t, amdsmi_link_id_bw_type_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_cpu_current_xgmi_bw = _libraries['libamd_smi.so'].amdsmi_get_cpu_current_xgmi_bw +amdsmi_get_cpu_current_xgmi_bw.restype = amdsmi_status_t +amdsmi_get_cpu_current_xgmi_bw.argtypes = [amdsmi_cpusocket_handle, amdsmi_link_id_bw_type_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_metrics_table_version = _libraries['libamd_smi.so'].amdsmi_get_metrics_table_version +amdsmi_get_metrics_table_version.restype = amdsmi_status_t +amdsmi_get_metrics_table_version.argtypes = [amdsmi_cpusocket_handle, ctypes.POINTER(ctypes.c_uint32)] +class struct_hsmp_metric_table(Structure): + pass + +amdsmi_get_metrics_table = _libraries['libamd_smi.so'].amdsmi_get_metrics_table +amdsmi_get_metrics_table.restype = amdsmi_status_t +amdsmi_get_metrics_table.argtypes = [amdsmi_cpusocket_handle, uint8_t, ctypes.POINTER(struct_hsmp_metric_table)] +amdsmi_get_cpu_family = _libraries['libamd_smi.so'].amdsmi_get_cpu_family +amdsmi_get_cpu_family.restype = amdsmi_status_t +amdsmi_get_cpu_family.argtypes = [uint32_t] +amdsmi_get_cpu_model = _libraries['libamd_smi.so'].amdsmi_get_cpu_model +amdsmi_get_cpu_model.restype = amdsmi_status_t +amdsmi_get_cpu_model.argtypes = [uint32_t] +amdsmi_get_cpu_threads_per_core = _libraries['libamd_smi.so'].amdsmi_get_cpu_threads_per_core +amdsmi_get_cpu_threads_per_core.restype = amdsmi_status_t +amdsmi_get_cpu_threads_per_core.argtypes = [uint32_t] +amdsmi_get_number_of_cpu_cores = _libraries['libamd_smi.so'].amdsmi_get_number_of_cpu_cores +amdsmi_get_number_of_cpu_cores.restype = amdsmi_status_t +amdsmi_get_number_of_cpu_cores.argtypes = [uint32_t] +amdsmi_get_number_of_cpu_sockets = _libraries['libamd_smi.so'].amdsmi_get_number_of_cpu_sockets +amdsmi_get_number_of_cpu_sockets.restype = amdsmi_status_t +amdsmi_get_number_of_cpu_sockets.argtypes = [uint32_t] +amdsmi_first_online_core_on_cpu_socket = _libraries['libamd_smi.so'].amdsmi_first_online_core_on_cpu_socket +amdsmi_first_online_core_on_cpu_socket.restype = amdsmi_status_t +amdsmi_first_online_core_on_cpu_socket.argtypes = [amdsmi_cpusocket_handle, uint32_t, ctypes.POINTER(ctypes.c_uint32)] +amdsmi_get_esmi_err_msg = _libraries['libamd_smi.so'].amdsmi_get_esmi_err_msg +amdsmi_get_esmi_err_msg.restype = ctypes.POINTER(ctypes.POINTER(ctypes.c_char)) +amdsmi_get_esmi_err_msg.argtypes = [amdsmi_status_t, ctypes.POINTER(ctypes.POINTER(ctypes.c_char))] __all__ = \ - ['AMDSMI_ARG_PTR_NULL', 'AMDSMI_AVERAGE_POWER', + ['AGG_BW0', 'AMDSMI_ARG_PTR_NULL', 'AMDSMI_AVERAGE_POWER', 'AMDSMI_CNTR_CMD_START', 'AMDSMI_CNTR_CMD_STOP', 'AMDSMI_COARSE_GRAIN_GFX_ACTIVITY', 'AMDSMI_COARSE_GRAIN_MEM_ACTIVITY', 'AMDSMI_CURRENT_POWER', @@ -1907,6 +2211,9 @@ __all__ = \ 'CLK_TYPE_DCLK1', 'CLK_TYPE_DF', 'CLK_TYPE_FIRST', 'CLK_TYPE_GFX', 'CLK_TYPE_MEM', 'CLK_TYPE_PCIE', 'CLK_TYPE_SOC', 'CLK_TYPE_SYS', 'CLK_TYPE_VCLK0', 'CLK_TYPE_VCLK1', 'CLK_TYPE__MAX', + 'COMPUTE_PARTITION_CPX', 'COMPUTE_PARTITION_DPX', + 'COMPUTE_PARTITION_INVALID', 'COMPUTE_PARTITION_QPX', + 'COMPUTE_PARTITION_SPX', 'COMPUTE_PARTITION_TPX', 'CONTAINER_DOCKER', 'CONTAINER_LXC', 'FW_ID_ASD', 'FW_ID_CP_CE', 'FW_ID_CP_ME', 'FW_ID_CP_MEC1', 'FW_ID_CP_MEC2', 'FW_ID_CP_MEC_JT1', 'FW_ID_CP_MEC_JT2', 'FW_ID_CP_MES', @@ -1934,30 +2241,66 @@ __all__ = \ 'FW_ID_SDMA6', 'FW_ID_SDMA7', 'FW_ID_SDMA_TH0', 'FW_ID_SDMA_TH1', 'FW_ID_SEC_POLICY_STAGE2', 'FW_ID_SMC', 'FW_ID_SMU', 'FW_ID_TA_RAS', 'FW_ID_UVD', 'FW_ID_VCE', 'FW_ID_VCN', - 'FW_ID_XGMI', 'FW_ID__MAX', 'NON_AMD_CPU', 'NON_AMD_GPU', - 'TEMPERATURE_TYPE_EDGE', 'TEMPERATURE_TYPE_FIRST', - 'TEMPERATURE_TYPE_HBM_0', 'TEMPERATURE_TYPE_HBM_1', - 'TEMPERATURE_TYPE_HBM_2', 'TEMPERATURE_TYPE_HBM_3', - 'TEMPERATURE_TYPE_HOTSPOT', 'TEMPERATURE_TYPE_JUNCTION', - 'TEMPERATURE_TYPE_PLX', 'TEMPERATURE_TYPE_VRAM', - 'TEMPERATURE_TYPE__MAX', 'UNKNOWN', 'VRAM_TYPE_DDR2', - 'VRAM_TYPE_DDR3', 'VRAM_TYPE_DDR4', 'VRAM_TYPE_GDDR1', - 'VRAM_TYPE_GDDR3', 'VRAM_TYPE_GDDR4', 'VRAM_TYPE_GDDR5', - 'VRAM_TYPE_GDDR6', 'VRAM_TYPE_HBM', 'VRAM_TYPE_UNKNOWN', - 'VRAM_TYPE__MAX', 'amd_metrics_table_header_t', - 'amdsmi_asic_info_t', 'amdsmi_bdf_t', 'amdsmi_bit_field_t', - 'amdsmi_board_info_t', 'amdsmi_clk_info_t', 'amdsmi_clk_type_t', - 'amdsmi_container_types_t', 'amdsmi_counter_command_t', - 'amdsmi_counter_value_t', 'amdsmi_dev_perf_level_t', - 'amdsmi_driver_info_t', 'amdsmi_engine_usage_t', - 'amdsmi_error_count_t', 'amdsmi_event_group_t', - 'amdsmi_event_handle_t', 'amdsmi_event_type_t', - 'amdsmi_evt_notification_data_t', - 'amdsmi_evt_notification_type_t', 'amdsmi_freq_ind_t', + 'FW_ID_XGMI', 'FW_ID__MAX', 'MEMORY_PARTITION_NPS1', + 'MEMORY_PARTITION_NPS2', 'MEMORY_PARTITION_NPS4', + 'MEMORY_PARTITION_NPS8', 'MEMORY_PARTITION_UNKNOWN', + 'NON_AMD_CPU', 'NON_AMD_GPU', 'RD_BW0', 'TEMPERATURE_TYPE_EDGE', + 'TEMPERATURE_TYPE_FIRST', 'TEMPERATURE_TYPE_HBM_0', + 'TEMPERATURE_TYPE_HBM_1', 'TEMPERATURE_TYPE_HBM_2', + 'TEMPERATURE_TYPE_HBM_3', 'TEMPERATURE_TYPE_HOTSPOT', + 'TEMPERATURE_TYPE_JUNCTION', 'TEMPERATURE_TYPE_PLX', + 'TEMPERATURE_TYPE_VRAM', 'TEMPERATURE_TYPE__MAX', 'UNKNOWN', + 'VRAM_TYPE_DDR2', 'VRAM_TYPE_DDR3', 'VRAM_TYPE_DDR4', + 'VRAM_TYPE_GDDR1', 'VRAM_TYPE_GDDR3', 'VRAM_TYPE_GDDR4', + 'VRAM_TYPE_GDDR5', 'VRAM_TYPE_GDDR6', 'VRAM_TYPE_HBM', + 'VRAM_TYPE_UNKNOWN', 'VRAM_TYPE__MAX', 'WR_BW0', + 'amd_metrics_table_header_t', 'amdsmi_asic_info_t', + 'amdsmi_bdf_t', 'amdsmi_bit_field_t', 'amdsmi_board_info_t', + 'amdsmi_clk_info_t', 'amdsmi_clk_type_t', + 'amdsmi_compute_partition_type_t', 'amdsmi_container_types_t', + 'amdsmi_counter_command_t', 'amdsmi_counter_value_t', + 'amdsmi_cpu_apb_disable', 'amdsmi_cpu_apb_enable', + 'amdsmi_cpusocket_handle', 'amdsmi_ddr_bw_metrics_t', + 'amdsmi_dev_compute_partition_get', + 'amdsmi_dev_compute_partition_reset', + 'amdsmi_dev_compute_partition_set', + 'amdsmi_dev_memory_partition_get', + 'amdsmi_dev_memory_partition_reset', + 'amdsmi_dev_memory_partition_set', 'amdsmi_dev_perf_level_t', + 'amdsmi_dimm_power_t', 'amdsmi_dimm_thermal_t', + 'amdsmi_dpm_level_t', 'amdsmi_driver_info_t', + 'amdsmi_engine_usage_t', 'amdsmi_error_count_t', + 'amdsmi_event_group_t', 'amdsmi_event_handle_t', + 'amdsmi_event_type_t', 'amdsmi_evt_notification_data_t', + 'amdsmi_evt_notification_type_t', + 'amdsmi_first_online_core_on_cpu_socket', 'amdsmi_freq_ind_t', 'amdsmi_freq_volt_region_t', 'amdsmi_frequencies_t', 'amdsmi_frequency_range_t', 'amdsmi_fw_block_t', 'amdsmi_fw_info_t', 'amdsmi_get_clk_freq', - 'amdsmi_get_clock_info', 'amdsmi_get_energy_count', + 'amdsmi_get_clock_info', 'amdsmi_get_cpu_cclk_limit', + 'amdsmi_get_cpu_core_boostlimit', + 'amdsmi_get_cpu_core_current_freq_limit', + 'amdsmi_get_cpu_core_energy', + 'amdsmi_get_cpu_current_io_bandwidth', + 'amdsmi_get_cpu_current_xgmi_bw', 'amdsmi_get_cpu_ddr_bw', + 'amdsmi_get_cpu_dimm_power_consumption', + 'amdsmi_get_cpu_dimm_temp_range_and_refresh_rate', + 'amdsmi_get_cpu_dimm_thermal_sensor', 'amdsmi_get_cpu_family', + 'amdsmi_get_cpu_fclk_mclk', 'amdsmi_get_cpu_hsmp_proto_ver', + 'amdsmi_get_cpu_model', 'amdsmi_get_cpu_prochot_status', + 'amdsmi_get_cpu_pwr_svi_telemetry_all_rails', + 'amdsmi_get_cpu_smu_fw_version', + 'amdsmi_get_cpu_socket_c0_residency', + 'amdsmi_get_cpu_socket_current_active_freq_limit', + 'amdsmi_get_cpu_socket_energy', + 'amdsmi_get_cpu_socket_freq_range', + 'amdsmi_get_cpu_socket_lclk_dpm_level', + 'amdsmi_get_cpu_socket_power', 'amdsmi_get_cpu_socket_power_cap', + 'amdsmi_get_cpu_socket_power_cap_max', + 'amdsmi_get_cpu_socket_temperature', + 'amdsmi_get_cpu_threads_per_core', 'amdsmi_get_cpucore_handles', + 'amdsmi_get_cpusocket_handles', 'amdsmi_get_cpusocket_info', + 'amdsmi_get_energy_count', 'amdsmi_get_esmi_err_msg', 'amdsmi_get_fw_info', 'amdsmi_get_gpu_activity', 'amdsmi_get_gpu_asic_info', 'amdsmi_get_gpu_available_counters', 'amdsmi_get_gpu_bad_page_info', 'amdsmi_get_gpu_bdf_id', @@ -1981,17 +2324,19 @@ __all__ = \ 'amdsmi_get_gpu_power_profile_presets', 'amdsmi_get_gpu_process_info', 'amdsmi_get_gpu_process_list', 'amdsmi_get_gpu_ras_block_features_enabled', - 'amdsmi_get_gpu_revision', 'amdsmi_get_gpu_subsystem_id', - 'amdsmi_get_gpu_subsystem_name', + 'amdsmi_get_gpu_ras_feature_info', 'amdsmi_get_gpu_revision', + 'amdsmi_get_gpu_subsystem_id', 'amdsmi_get_gpu_subsystem_name', 'amdsmi_get_gpu_topo_numa_affinity', 'amdsmi_get_gpu_total_ecc_count', 'amdsmi_get_gpu_vbios_info', 'amdsmi_get_gpu_vendor_name', 'amdsmi_get_gpu_volt_metric', 'amdsmi_get_gpu_vram_info', 'amdsmi_get_gpu_vram_usage', 'amdsmi_get_gpu_vram_vendor', 'amdsmi_get_lib_version', + 'amdsmi_get_metrics_table', 'amdsmi_get_metrics_table_version', 'amdsmi_get_minmax_bandwidth_between_processors', - 'amdsmi_get_pcie_link_caps', 'amdsmi_get_pcie_link_status', - 'amdsmi_get_power_cap_info', 'amdsmi_get_power_info', - 'amdsmi_get_processor_handle_from_bdf', + 'amdsmi_get_number_of_cpu_cores', + 'amdsmi_get_number_of_cpu_sockets', 'amdsmi_get_pcie_link_caps', + 'amdsmi_get_pcie_link_status', 'amdsmi_get_power_cap_info', + 'amdsmi_get_power_info', 'amdsmi_get_processor_handle_from_bdf', 'amdsmi_get_processor_handles', 'amdsmi_get_processor_type', 'amdsmi_get_socket_handles', 'amdsmi_get_socket_info', 'amdsmi_get_temp_metric', 'amdsmi_get_utilization_count', @@ -2001,10 +2346,11 @@ __all__ = \ 'amdsmi_gpu_destroy_counter', 'amdsmi_gpu_metrics_t', 'amdsmi_gpu_read_counter', 'amdsmi_gpu_xgmi_error_status', 'amdsmi_init', 'amdsmi_init_flags_t', - 'amdsmi_init_gpu_event_notification', 'amdsmi_io_link_type_t', - 'amdsmi_is_P2P_accessible', + 'amdsmi_init_gpu_event_notification', 'amdsmi_io_bw_encoding_t', + 'amdsmi_io_link_type_t', 'amdsmi_is_P2P_accessible', 'amdsmi_is_gpu_power_management_enabled', - 'amdsmi_memory_page_status_t', 'amdsmi_memory_type_t', + 'amdsmi_link_id_bw_type_t', 'amdsmi_memory_page_status_t', + 'amdsmi_memory_partition_type_t', 'amdsmi_memory_type_t', 'amdsmi_mm_ip_t', 'amdsmi_od_vddc_point_t', 'amdsmi_od_volt_curve_t', 'amdsmi_od_volt_freq_data_t', 'amdsmi_pcie_bandwidth_t', 'amdsmi_pcie_info_t', @@ -2013,9 +2359,18 @@ __all__ = \ 'amdsmi_power_profile_status_t', 'amdsmi_power_type_t', 'amdsmi_proc_info_t', 'amdsmi_process_handle_t', 'amdsmi_process_info_t', 'amdsmi_processor_handle', - 'amdsmi_range_t', 'amdsmi_ras_err_state_t', 'amdsmi_reset_gpu', + 'amdsmi_range_t', 'amdsmi_ras_err_state_t', + 'amdsmi_ras_feature_t', 'amdsmi_reset_gpu', 'amdsmi_reset_gpu_fan', 'amdsmi_reset_gpu_xgmi_error', 'amdsmi_retired_page_record_t', 'amdsmi_set_clk_freq', + 'amdsmi_set_cpu_core_boostlimit', + 'amdsmi_set_cpu_df_pstate_range', + 'amdsmi_set_cpu_gmi3_link_width_range', + 'amdsmi_set_cpu_pcie_link_rate', + 'amdsmi_set_cpu_pwr_efficiency_mode', + 'amdsmi_set_cpu_socket_boostlimit', + 'amdsmi_set_cpu_socket_lclk_dpm_level', + 'amdsmi_set_cpu_socket_power_cap', 'amdsmi_set_cpu_xgmi_width', 'amdsmi_set_gpu_clk_range', 'amdsmi_set_gpu_event_notification_mask', 'amdsmi_set_gpu_fan_speed', 'amdsmi_set_gpu_od_clk_info', @@ -2024,11 +2379,12 @@ __all__ = \ 'amdsmi_set_gpu_perf_determinism_mode', 'amdsmi_set_gpu_perf_level', 'amdsmi_set_gpu_power_profile', 'amdsmi_set_power_cap', 'amdsmi_shut_down', - 'amdsmi_socket_handle', 'amdsmi_status_code_to_string', - 'amdsmi_status_t', 'amdsmi_stop_gpu_event_notification', - 'amdsmi_temperature_metric_t', 'amdsmi_temperature_type_t', - 'amdsmi_topo_get_link_type', 'amdsmi_topo_get_link_weight', - 'amdsmi_topo_get_numa_node_number', + 'amdsmi_smu_fw_version_t', 'amdsmi_socket_handle', + 'amdsmi_status_code_to_string', 'amdsmi_status_t', + 'amdsmi_stop_gpu_event_notification', + 'amdsmi_temp_range_refresh_rate_t', 'amdsmi_temperature_metric_t', + 'amdsmi_temperature_type_t', 'amdsmi_topo_get_link_type', + 'amdsmi_topo_get_link_weight', 'amdsmi_topo_get_numa_node_number', 'amdsmi_utilization_counter_t', 'amdsmi_utilization_counter_type_t', 'amdsmi_vbios_info_t', 'amdsmi_version_t', 'amdsmi_voltage_metric_t', @@ -2038,23 +2394,29 @@ __all__ = \ 'amdsmi_xgmi_status_t', 'processor_type_t', 'size_t', 'struct_amd_metrics_table_header_t', 'struct_amdsmi_asic_info_t', 'struct_amdsmi_board_info_t', 'struct_amdsmi_clk_info_t', - 'struct_amdsmi_counter_value_t', 'struct_amdsmi_driver_info_t', + 'struct_amdsmi_counter_value_t', 'struct_amdsmi_ddr_bw_metrics_t', + 'struct_amdsmi_dimm_power_t', 'struct_amdsmi_dimm_thermal_t', + 'struct_amdsmi_dpm_level_t', 'struct_amdsmi_driver_info_t', 'struct_amdsmi_engine_usage_t', 'struct_amdsmi_error_count_t', 'struct_amdsmi_evt_notification_data_t', 'struct_amdsmi_freq_volt_region_t', 'struct_amdsmi_frequencies_t', 'struct_amdsmi_frequency_range_t', 'struct_amdsmi_fw_info_t', 'struct_amdsmi_gpu_cache_info_t', 'struct_amdsmi_gpu_metrics_t', + 'struct_amdsmi_link_id_bw_type_t', 'struct_amdsmi_od_vddc_point_t', 'struct_amdsmi_od_volt_curve_t', 'struct_amdsmi_od_volt_freq_data_t', 'struct_amdsmi_pcie_bandwidth_t', 'struct_amdsmi_pcie_info_t', 'struct_amdsmi_power_cap_info_t', 'struct_amdsmi_power_info_t', 'struct_amdsmi_power_profile_status_t', 'struct_amdsmi_proc_info_t', 'struct_amdsmi_process_info_t', - 'struct_amdsmi_range_t', 'struct_amdsmi_retired_page_record_t', + 'struct_amdsmi_range_t', 'struct_amdsmi_ras_feature_t', + 'struct_amdsmi_retired_page_record_t', + 'struct_amdsmi_smu_fw_version_t', + 'struct_amdsmi_temp_range_refresh_rate_t', 'struct_amdsmi_utilization_counter_t', 'struct_amdsmi_vbios_info_t', 'struct_amdsmi_version_t', 'struct_amdsmi_vram_info_t', 'struct_amdsmi_vram_usage_t', 'struct_amdsmi_xgmi_info_t', 'struct_cache_', 'struct_engine_usage_', 'struct_fields_', 'struct_fw_info_list_', - 'struct_memory_usage_', 'uint32_t', 'uint64_t', - 'union_amdsmi_bdf_t'] + 'struct_hsmp_metric_table', 'struct_memory_usage_', 'uint32_t', + 'uint64_t', 'uint8_t', 'union_amdsmi_bdf_t'] diff --git a/projects/amdsmi/py-interface/pyproject.toml b/projects/amdsmi/py-interface/pyproject.toml index 17ba948c13..fa2cb5d040 100644 --- a/projects/amdsmi/py-interface/pyproject.toml +++ b/projects/amdsmi/py-interface/pyproject.toml @@ -10,7 +10,7 @@ name = "amdsmi" authors = [ {name = "AMD", email = "amd-smi.support@amd.com"}, ] -version = "23.3.1.0" +version = "23.4.0.0" license = {file = "amdsmi/LICENSE"} readme = {file = "amdsmi/README.md", content-type = "text/markdown"} description = "AMDSMI Python LIB - AMD GPU Monitoring Library" diff --git a/projects/amdsmi/rocm_smi/example/rocm_smi_example.cc b/projects/amdsmi/rocm_smi/example/rocm_smi_example.cc index 7c061ddbf0..83d141dc74 100755 --- a/projects/amdsmi/rocm_smi/example/rocm_smi_example.cc +++ b/projects/amdsmi/rocm_smi/example/rocm_smi_example.cc @@ -58,8 +58,8 @@ #define PRINT_RSMI_ERR(RET) { \ if (RET != RSMI_STATUS_SUCCESS) { \ std::cout << "[ERROR] RSMI call returned " << (RET) \ - << " at line " << __LINE__ << std::endl; \ - std::cout << amd::smi::getRSMIStatusString(RET) << std::endl; \ + << " at line " << __LINE__ << "\n"; \ + std::cout << amd::smi::getRSMIStatusString(RET) << "\n"; \ } \ } @@ -718,7 +718,7 @@ int main() { rsmi_num_monitor_devices(&num_monitor_devs); for (uint32_t i = 0; i < num_monitor_devs; ++i) { - std::cout << "\t**Device #: " << std::dec << i << std::endl; + std::cout << "\t**Device #: " << std::dec << i << "\n"; ret = rsmi_dev_id_get(i, &val_ui16); CHK_RSMI_RET_I(ret) std::cout << "\t**Device ID: 0x" << std::hex << val_ui16 << "\n"; @@ -770,8 +770,9 @@ int main() { uint64_t max_bandwidth = 0; ret = rsmi_minmax_bandwidth_get(0, i, &min_bandwidth, &max_bandwidth); CHK_RSMI_NOT_SUPPORTED_OR_UNEXPECTED_DATA_RET(ret) - std::cout << "\nMinimum Bandwidth: " << min_bandwidth - << "\nMaximum Bandwidth: " << max_bandwidth; + std::cout << "\n\t**\tMinimum Bandwidth: " << std::dec << min_bandwidth + << "\n\t**\tMaximum Bandwidth: " << std::dec + << max_bandwidth << "\n"; } else { std::cout << "Not Supported\n"; } @@ -818,7 +819,7 @@ int main() { ret = rsmi_dev_temp_metric_get(i, RSMI_TEMP_TYPE_EDGE, rsmi_temperature_metric_t::RSMI_TEMP_CURRENT, &val_i64); if (ret == RSMI_STATUS_SUCCESS) { - std::cout << val_i64/1000 << "C" << "\n"; + std::cout << std::dec << val_i64/1000 << " C" << "\n"; } CHK_RSMI_NOT_SUPPORTED_RET(ret) @@ -826,7 +827,7 @@ int main() { ret = rsmi_dev_temp_metric_get(i, RSMI_TEMP_TYPE_JUNCTION, rsmi_temperature_metric_t::RSMI_TEMP_CURRENT, &val_i64); if (ret == RSMI_STATUS_SUCCESS) { - std::cout << (val_i64 / 1000) << "C" << std::endl; + std::cout << std::dec << (val_i64 / 1000) << " C" << "\n"; } CHK_RSMI_NOT_SUPPORTED_RET(ret) @@ -874,14 +875,14 @@ int main() { std::cout << "\t**Average Power Usage: "; ret = rsmi_dev_power_ave_get(i, 0, &val_ui64); if (ret == RSMI_STATUS_SUCCESS) { - std::cout << convert_mw_to_w(val_ui64) << " W" << std::endl; + std::cout << convert_mw_to_w(val_ui64) << " W" << "\n"; } CHK_RSMI_NOT_SUPPORTED_RET(ret) std::cout << "\t**Current Socket Power Usage: "; ret = rsmi_dev_current_socket_power_get(i, &val_ui64); if (ret == RSMI_STATUS_SUCCESS) { - std::cout << convert_mw_to_w(val_ui64) << " W" << std::endl; + std::cout << convert_mw_to_w(val_ui64) << " W" << "\n"; } CHK_RSMI_NOT_SUPPORTED_RET(ret) @@ -889,7 +890,7 @@ int main() { ret = rsmi_dev_power_get(i, &val_ui64, &power_type); if (ret == RSMI_STATUS_SUCCESS) { std::cout << "[" << amd::smi::power_type_string(power_type) << "] " - << convert_mw_to_w(val_ui64) << " W" << std::endl; + << convert_mw_to_w(val_ui64) << " W" << "\n"; } CHK_RSMI_NOT_SUPPORTED_RET(ret) std::cout << "\t=======" << "\n"; @@ -902,7 +903,7 @@ int main() { return 0; } - for (uint32_t i = 0; i< num_monitor_devs; ++i) { + for (uint32_t i = 0; i < num_monitor_devs; ++i) { ret = test_set_overdrive(i); CHK_AND_PRINT_RSMI_ERR_RET(ret) diff --git a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h index 3e2735f870..fef797cc5f 100755 --- a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h +++ b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi.h @@ -377,16 +377,16 @@ typedef rsmi_clk_type_t rsmi_clk_type; */ typedef enum { RSMI_COMPUTE_PARTITION_INVALID = 0, - RSMI_COMPUTE_PARTITION_CPX, //!< Core mode (CPX)- Per-chip XCC with - //!< shared memory - RSMI_COMPUTE_PARTITION_SPX, //!< Single GPU mode (SPX)- All XCCs work - //!< together with shared memory - RSMI_COMPUTE_PARTITION_DPX, //!< Dual GPU mode (DPX)- Half XCCs work - //!< together with shared memory - RSMI_COMPUTE_PARTITION_TPX, //!< Triple GPU mode (TPX)- One-third XCCs - //!< work together with shared memory - RSMI_COMPUTE_PARTITION_QPX //!< Quad GPU mode (QPX)- Quarter XCCs - //!< work together with shared memory + RSMI_COMPUTE_PARTITION_CPX, //!< Core mode (CPX)- Per-chip XCC with + //!< shared memory + RSMI_COMPUTE_PARTITION_SPX, //!< Single GPU mode (SPX)- All XCCs work + //!< together with shared memory + RSMI_COMPUTE_PARTITION_DPX, //!< Dual GPU mode (DPX)- Half XCCs work + //!< together with shared memory + RSMI_COMPUTE_PARTITION_TPX, //!< Triple GPU mode (TPX)- One-third XCCs + //!< work together with shared memory + RSMI_COMPUTE_PARTITION_QPX //!< Quad GPU mode (QPX)- Quarter XCCs + //!< work together with shared memory } rsmi_compute_partition_type_t; /// \cond Ignore in docs. typedef rsmi_compute_partition_type_t rsmi_compute_partition_type; @@ -1059,6 +1059,16 @@ typedef struct { uint64_t uncorrectable_err; //!< Accumulated uncorrectable errors } rsmi_error_count_t; +/** + * @brief This structure holds ras feature + */ +typedef struct { + uint32_t ras_eeprom_version; + // PARITY error(bit 0), Single Bit correctable (bit1), + // Double bit error detection (bit2), Poison (bit 3). + uint32_t ecc_correction_schema_flag; //!< ecc_correction_schema mask +} rsmi_ras_feature_info_t; + /** * @brief This structure contains information specific to a process. */ @@ -3279,6 +3289,33 @@ rsmi_status_t rsmi_dev_ecc_enabled_get(uint32_t dv_ind, */ rsmi_status_t rsmi_dev_ecc_status_get(uint32_t dv_ind, rsmi_gpu_block_t block, rsmi_ras_err_state_t *state); + + +/** + * @brief Returns RAS features info. + * + * @details Given a device index @p dv_ind, and + * a pointer to an ::rsmi_ras_feature_info_t @p ras_feature, this function will write + * the ras feature info to memory pointed to by @p ras_feature. + * + * @param[in] dv_ind a device index + * + * @param[inout] ras_feature A pointer to an ::rsmi_ras_feature_info_t to which the + * RAS info should be written + * If this parameter is nullptr, this function will return + * ::RSMI_STATUS_INVALID_ARGS if the function is supported with the provided, + * arguments and ::RSMI_STATUS_NOT_SUPPORTED if it is not supported with the + * provided arguments. + * + * @retval ::RSMI_STATUS_SUCCESS call was successful + * @retval ::RSMI_STATUS_NOT_SUPPORTED installed software or hardware does not + * support this function with the given arguments + * @retval ::RSMI_STATUS_INVALID_ARGS the provided arguments are not valid + */ +rsmi_status_t rsmi_ras_feature_info_get( + uint32_t dv_ind, rsmi_ras_feature_info_t *ras_feature); + + /** * @brief Get a description of a provided RSMI error status * @@ -3865,7 +3902,7 @@ rsmi_is_P2P_accessible(uint32_t dv_ind_src, uint32_t dv_ind_dst, /** @} */ // end of HWTopo /*****************************************************************************/ -/** @defgroup ComputePartition Compute Partition Functions +/** @defgroup compute_partition Compute Partition Functions * These functions are used to configure and query the device's * compute parition setting. * @{ @@ -3946,10 +3983,10 @@ rsmi_dev_compute_partition_set(uint32_t dv_ind, */ rsmi_status_t rsmi_dev_compute_partition_reset(uint32_t dv_ind); -/** @} */ // end of ComputePartition +/** @} */ // end of compute_partition /*****************************************************************************/ -/** @defgroup memory_partition The Memory Partition Functions +/** @defgroup memory_partition Memory Partition Functions * These functions are used to query and set the device's current memory * partition. * @{ diff --git a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_device.h b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_device.h index 6aedfb0c1a..c728326691 100755 --- a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_device.h +++ b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_device.h @@ -129,6 +129,8 @@ enum DevInfoTypes { kDevErrCntPCIEBIF, kDevErrCntHDP, kDevErrCntXGMIWAFL, + kDevErrTableVersion, + kDevErrRASSchema, kDevErrCntFeatures, kDevMemTotGTT, kDevMemTotVisVRAM, diff --git a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_main.h b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_main.h index 8b60324988..1cd2ec343f 100755 --- a/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_main.h +++ b/projects/amdsmi/rocm_smi/include/rocm_smi/rocm_smi_main.h @@ -128,7 +128,7 @@ class RocmSMI { std::map, std::shared_ptr> io_link_map_; std::map dev_ind_to_node_ind_map_; - void AddToDeviceList(std::string dev_name); + void AddToDeviceList(std::string dev_name, uint64_t bdfid = 0); void GetEnvVariables(void); std::shared_ptr FindMonitor(std::string monitor_path); diff --git a/projects/amdsmi/rocm_smi/src/rocm_smi.cc b/projects/amdsmi/rocm_smi/src/rocm_smi.cc index 521c615016..6fe0c41d26 100755 --- a/projects/amdsmi/rocm_smi/src/rocm_smi.cc +++ b/projects/amdsmi/rocm_smi/src/rocm_smi.cc @@ -849,6 +849,73 @@ get_id(uint32_t dv_ind, amd::smi::DevInfoTypes typ, uint16_t *id) { CATCH } +rsmi_status_t rsmi_ras_feature_info_get( + uint32_t dv_ind, rsmi_ras_feature_info_t *ras_feature) { + TRY + rsmi_status_t ret; + std::string feature_line; + std::string tmp_str; + std::ostringstream ss; + ss << __PRETTY_FUNCTION__ << " | ======= start ======="; + LOG_TRACE(ss); + + CHK_SUPPORT_NAME_ONLY(ras_feature) + + DEVICE_MUTEX + + ret = get_dev_value_line(amd::smi::kDevErrTableVersion, + dv_ind, &feature_line); + if (ret != RSMI_STATUS_SUCCESS) { + ss << __PRETTY_FUNCTION__ << " | ======= end =======" + << ", returning get_dev_value_line() response = " + << amd::smi::getRSMIStatusString(ret); + LOG_ERROR(ss); + return ret; + } + + // table version: 0x10000 + const char* version_key = "table version: "; + if (feature_line.rfind(version_key, 0) == 0) { + errno = 0; + auto eeprom_version = strtoul( + feature_line.substr(strlen(version_key)).c_str(), nullptr, 16); + if (errno == 0) { + ras_feature->ras_eeprom_version = eeprom_version; + } else { + return RSMI_STATUS_NOT_SUPPORTED; + } + } else { + return RSMI_STATUS_NOT_SUPPORTED; + } + + ret = get_dev_value_line(amd::smi::kDevErrRASSchema, + dv_ind, &feature_line); + if (ret != RSMI_STATUS_SUCCESS) { + ss << __PRETTY_FUNCTION__ << " | ======= end =======" + << ", returning get_dev_value_line() response = " + << amd::smi::getRSMIStatusString(ret); + LOG_ERROR(ss); + return ret; + } + // schema: 0xf + const char* schema_key = "schema: "; + if (feature_line.rfind(schema_key, 0) == 0) { + errno = 0; + auto schema = strtoul( + feature_line.substr(strlen(schema_key)).c_str(), nullptr, 16); + if (errno == 0) { + ras_feature->ecc_correction_schema_flag = schema; + } else { + return RSMI_STATUS_NOT_SUPPORTED; + } + } else { + return RSMI_STATUS_NOT_SUPPORTED; + } + + return RSMI_STATUS_SUCCESS; + CATCH +} + rsmi_status_t rsmi_dev_id_get(uint32_t dv_ind, uint16_t *id) { std::ostringstream ss; diff --git a/projects/amdsmi/rocm_smi/src/rocm_smi_device.cc b/projects/amdsmi/rocm_smi/src/rocm_smi_device.cc index 85aebef6f4..61fd9a3885 100755 --- a/projects/amdsmi/rocm_smi/src/rocm_smi_device.cc +++ b/projects/amdsmi/rocm_smi/src/rocm_smi_device.cc @@ -112,6 +112,8 @@ static const char *kDevErrCntPCIEBIFFName = "ras/pcie_bif_err_count"; static const char *kDevErrCntHDPFName = "ras/hdp_err_count"; static const char *kDevErrCntXGMIWAFLFName = "ras/xgmi_wafl_err_count"; static const char *kDevErrCntFeaturesFName = "ras/features"; +static const char *kDevErrRASSchemaFName = "ras/schema"; +static const char *kDevErrTableVersionFName = "ras/version"; static const char *kDevMemPageBadFName = "ras/gpu_vram_bad_pages"; static const char *kDevMemTotGTTFName = "mem_info_gtt_total"; static const char *kDevMemTotVisVRAMFName = "mem_info_vis_vram_total"; @@ -269,6 +271,8 @@ static const std::map kDevAttribNameMap = { {kDevErrCntHDP, kDevErrCntHDPFName}, {kDevErrCntXGMIWAFL, kDevErrCntXGMIWAFLFName}, {kDevErrCntFeatures, kDevErrCntFeaturesFName}, + {kDevErrTableVersion, kDevErrTableVersionFName}, + {kDevErrRASSchema, kDevErrRASSchemaFName}, {kDevMemTotGTT, kDevMemTotGTTFName}, {kDevMemTotVisVRAM, kDevMemTotVisVRAMFName}, {kDevMemBusyPercent, kDevMemBusyPercentFName}, @@ -432,6 +436,8 @@ static const std::map kDevFuncDependsMap = { {"rsmi_dev_od_volt_curve_regions_get", {{kDevPowerODVoltageFName}, {}}}, {"rsmi_dev_ecc_enabled_get", {{kDevErrCntFeaturesFName}, {}}}, {"rsmi_dev_ecc_status_get", {{kDevErrCntFeaturesFName}, {}}}, + {"rsmi_ras_feature_info_get", {{kDevErrRASSchemaFName, + kDevErrTableVersionFName}, {}}}, {"rsmi_dev_counter_group_supported", {{}, {}}}, {"rsmi_dev_counter_create", {{}, {}}}, {"rsmi_dev_xgmi_error_status", {{kDevXGMIErrorFName}, {}}}, @@ -933,6 +939,8 @@ int Device::readDevInfo(DevInfoTypes type, uint64_t *val) { case kDevPCieVendorID: case kDevErrCntFeatures: case kDevXGMIPhysicalID: + case kDevErrRASSchema: + case kDevErrTableVersion: ret = readDevInfoStr(type, &tempStr); RET_IF_NONZERO(ret); diff --git a/projects/amdsmi/rocm_smi/src/rocm_smi_kfd.cc b/projects/amdsmi/rocm_smi/src/rocm_smi_kfd.cc index 39e5e4791b..68fccb9a49 100755 --- a/projects/amdsmi/rocm_smi/src/rocm_smi_kfd.cc +++ b/projects/amdsmi/rocm_smi/src/rocm_smi_kfd.cc @@ -954,9 +954,12 @@ int KFDNode::get_cache_info(rsmi_gpu_cache_info_t *info) { int read_node_properties(uint32_t node, std::string property_name, uint64_t *val) { std::ostringstream ss; + std::string propertiesFullPath = "/sys/class/kfd/kfd/topology/nodes/" + + std::to_string(node) + "/properties"; int retVal = EINVAL; if (property_name.empty() || val == nullptr) { ss << __PRETTY_FUNCTION__ + << " | File: " << propertiesFullPath << " | Issue: Could not read node #" << std::to_string(node) << ", property_name is empty or *val is nullptr " << " | return = " << std::to_string(retVal) @@ -969,6 +972,7 @@ int read_node_properties(uint32_t node, std::string property_name, if (KFDNodeSupported(node)) { retVal = myNode->get_property_value(property_name, val); ss << __PRETTY_FUNCTION__ + << " | File: " << propertiesFullPath << " | Successfully read node #" << std::to_string(node) << " for property_name = " << property_name << " | Data (" << property_name << ") * val = " @@ -979,6 +983,7 @@ int read_node_properties(uint32_t node, std::string property_name, } else { retVal = 1; ss << __PRETTY_FUNCTION__ + << " | File: " << propertiesFullPath << " | Issue: Could not read node #" << std::to_string(node) << ", KFD node was an unsupported node." << " | return = " << std::to_string(retVal) @@ -991,9 +996,12 @@ int read_node_properties(uint32_t node, std::string property_name, // /sys/class/kfd/kfd/topology/nodes/*/gpu_id int get_gpu_id(uint32_t node, uint64_t *gpu_id) { std::ostringstream ss; + std::string gpu_id_FullPath = "/sys/class/kfd/kfd/topology/nodes/" + + std::to_string(node) + "/gpu_id"; int retVal = EINVAL; if (gpu_id == nullptr) { ss << __PRETTY_FUNCTION__ + << " | File: " << gpu_id_FullPath << " | Issue: Could not read node #" << std::to_string(node) << ", gpu_id is a nullptr " << " | return = " << std::to_string(retVal) @@ -1006,6 +1014,7 @@ int get_gpu_id(uint32_t node, uint64_t *gpu_id) { if (KFDNodeSupported(node)) { retVal = ReadKFDGpuId(node, gpu_id); ss << __PRETTY_FUNCTION__ + << " | File: " << gpu_id_FullPath << " | Successfully read node #" << std::to_string(node) << " for gpu_id" << " | Data (gpu_id) *gpu_id = " @@ -1016,6 +1025,7 @@ int get_gpu_id(uint32_t node, uint64_t *gpu_id) { } else { retVal = 1; ss << __PRETTY_FUNCTION__ + << " | File: " << gpu_id_FullPath << " | Issue: Could not read node #" << std::to_string(node) << ", KFD node was an unsupported node." << " | return = " << std::to_string(retVal) diff --git a/projects/amdsmi/rocm_smi/src/rocm_smi_main.cc b/projects/amdsmi/rocm_smi/src/rocm_smi_main.cc index 3b7293cd49..22200ea273 100755 --- a/projects/amdsmi/rocm_smi/src/rocm_smi_main.cc +++ b/projects/amdsmi/rocm_smi/src/rocm_smi_main.cc @@ -112,6 +112,8 @@ amd::smi::RocmSMI::devInfoTypesStrings = { {amd::smi::kDevErrCntHDP, amdSMI + "kDevErrCntHDP"}, {amd::smi::kDevErrCntXGMIWAFL, amdSMI + "kDevErrCntXGMIWAFL"}, {amd::smi::kDevErrCntFeatures, amdSMI + "kDevErrCntFeatures"}, + {amd::smi::kDevErrRASSchema, amdSMI + "kDevErrRASSchema"}, + {amd::smi::kDevErrTableVersion, amdSMI + "kDevErrTableVersion"}, {amd::smi::kDevMemTotGTT, amdSMI + "kDevMemTotGTT"}, {amd::smi::kDevMemTotVisVRAM, amdSMI + "kDevMemTotVisVRAM"}, {amd::smi::kDevMemTotVRAM, amdSMI + "kDevMemTotVRAM"}, @@ -315,6 +317,7 @@ RocmSMI::Initialize(uint64_t flags) { auto i = 0; uint32_t ret; int i_ret; + std::ostringstream ss; LOG_ALWAYS("=============== ROCM SMI initialize ================"); ROCmLogging::Logger::getInstance()->enableAllLogLevels(); @@ -358,9 +361,32 @@ RocmSMI::Initialize(uint64_t flags) { if (ConstructBDFID(device->path(), &bdfid) != 0) { std::cerr << "Failed to construct BDFID." << std::endl; ret = 1; + } else if (device->bdfid() != UINT64_MAX && device->bdfid() != bdfid) { + // handles secondary partitions - compute partition feature nodes + ss << __PRETTY_FUNCTION__ + << " | [before] device->path() = " << device->path() + << "\n | bdfid = " << bdfid + << "\n | device->bdfid() = " << device->bdfid() + << "\n | (xgmi node) setting to setting " + << "device->set_bdfid(device->bdfid())"; + LOG_TRACE(ss); + device->set_bdfid(device->bdfid()); } else { + // legacy & pcie card updates + ss << __PRETTY_FUNCTION__ + << " | [before] device->path() = " << device->path() + << "\n | bdfid = " << bdfid + << "\n | device->bdfid() = " << device->bdfid() + << "\n | (legacy/pcie card) setting device->set_bdfid(bdfid)"; + LOG_TRACE(ss); device->set_bdfid(bdfid); } + ss << __PRETTY_FUNCTION__ + << " | [after] device->path() = " << device->path() + << "\n | bdfid = " << bdfid + << "\n | device->bdfid() = " << device->bdfid() + << "\n | final update: device->bdfid() holds correct device bdf"; + LOG_TRACE(ss); } if (ret != 0) { throw amd::smi::rsmi_exception(RSMI_INITIALIZATION_ERROR, @@ -389,7 +415,6 @@ RocmSMI::Initialize(uint64_t flags) { // Remove any drm nodes that don't have a corresponding readable kfd node. // kfd nodes will not be added if their properties file is not readable. - std::ostringstream ss; auto dev_iter = devices_.begin(); while (dev_iter != devices_.end()) { uint64_t bdfid = (*dev_iter)->bdfid(); @@ -668,8 +693,8 @@ RocmSMI::FindMonitor(std::string monitor_path) { return m; } -void -RocmSMI::AddToDeviceList(std::string dev_name) { + +void RocmSMI::AddToDeviceList(std::string dev_name, uint64_t bdfid) { std::ostringstream ss; ss << __PRETTY_FUNCTION__ << " | ======= start ======="; LOG_TRACE(ss); @@ -687,10 +712,15 @@ RocmSMI::AddToDeviceList(std::string dev_name) { dev->set_drm_render_minor(GetDrmRenderMinor(dev_path)); dev->set_card_index(card_indx); GetSupportedEventGroups(card_indx, dev->supported_event_groups()); + if (bdfid != 0) { + dev->set_bdfid(bdfid); + } devices_.push_back(dev); - ss << __PRETTY_FUNCTION__ << " | Adding to device list dev_name = " - << dev_name << " | path = " << dev_path + ss << __PRETTY_FUNCTION__ + << " | Adding to device list dev_name = " << dev_name + << " | path = " << dev_path + << " | bdfid = " << bdfid << " | card index = " << std::to_string(card_indx) << " | "; LOG_DEBUG(ss); } @@ -771,19 +801,24 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { uint32_t s_node_id = 0; uint64_t s_gpu_id = 0; uint64_t s_unique_id = 0; + uint64_t s_location_id = 0; }; - // allSystemNodes[key = unique_id] => {node_id, gpu_id, unique_id} + // allSystemNodes[key = unique_id] => {node_id, gpu_id, unique_id, + // location_id} std::multimap allSystemNodes; uint32_t node_id = 0; while (true) { - uint64_t gpu_id = 0, unique_id = 0; + uint64_t gpu_id = 0, unique_id = 0, location_id = 0; int ret_gpu_id = get_gpu_id(node_id, &gpu_id); int ret_unique_id = read_node_properties(node_id, "unique_id", &unique_id); - if (ret_gpu_id == 0 || ret_unique_id == 0) { + int ret_loc_id = + read_node_properties(node_id, "location_id", &location_id); + if (ret_gpu_id == 0 || ret_unique_id == 0 || ret_loc_id == 0) { systemNode myNode; myNode.s_node_id = node_id; myNode.s_gpu_id = gpu_id; myNode.s_unique_id = unique_id; + myNode.s_location_id = location_id; if (gpu_id != 0) { // only add gpu nodes, 0 = CPU allSystemNodes.emplace(unique_id, myNode); } @@ -798,6 +833,7 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { ss << "\n[node_id = " << std::to_string(i.second.s_node_id) << "; gpu_id = " << std::to_string(i.second.s_gpu_id) << "; unique_id = " << std::to_string(i.second.s_unique_id) + << "; location_id = " << std::to_string(i.second.s_location_id) << "], "; } ss << "}"; @@ -810,6 +846,14 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { path += "/card"; path += std::to_string(cardId); uint64_t primary_unique_id = 0; + uint64_t device_uuid = 0; + bool doesDeviceSupportPartitions = false; + // get current partition + int kSize = 256; + char computePartition[kSize]; + std::string strCompPartition = "UNKNOWN"; + uint32_t numMonDevices = 0; + rsmi_num_monitor_devices(&numMonDevices); // each identified gpu card node is a primary node for // potential matching unique ids @@ -817,7 +861,25 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { (init_options_ & RSMI_INIT_FLAG_ALL_GPUS)) { std::string d_name = "card"; d_name += std::to_string(cardId); - AddToDeviceList(d_name); + uint32_t numMonDevices = 0; + rsmi_num_monitor_devices(&numMonDevices); + if (rsmi_dev_compute_partition_get(cardAdded, computePartition, kSize) + == RSMI_STATUS_SUCCESS) { + strCompPartition = computePartition; + doesDeviceSupportPartitions = true; + } + rsmi_status_t ret_unique_id = + rsmi_dev_unique_id_get(cardAdded, &device_uuid); + auto temp_numb_nodes = allSystemNodes.count(device_uuid); + auto primaryBdfId = + allSystemNodes.lower_bound(device_uuid)->second.s_location_id; + if (doesDeviceSupportPartitions && temp_numb_nodes > 1 + && ret_unique_id == RSMI_STATUS_SUCCESS) { + // helps identify xgmi nodes (secondary nodes) easier + AddToDeviceList(d_name, primaryBdfId); + } else { + AddToDeviceList(d_name, UINT64_MAX); + } ss << __PRETTY_FUNCTION__ << " | Ordered system nodes seen in lookup = {"; @@ -825,12 +887,14 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { ss << "\n[node_id = " << std::to_string(i.second.s_node_id) << "; gpu_id = " << std::to_string(i.second.s_gpu_id) << "; unique_id = " << std::to_string(i.second.s_unique_id) + << "; location_id = " << std::to_string(i.second.s_location_id) << "], "; } ss << "}"; LOG_DEBUG(ss); uint64_t temp_primary_unique_id = 0; + uint64_t primary_location_id = 0; if (allSystemNodes.empty()) { cardAdded++; ss << __PRETTY_FUNCTION__ @@ -840,16 +904,11 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { } // get current partition - const int kSize = 256; - char computePartition[kSize]; - std::string strCompPartition = "UNKNOWN"; - uint32_t numMonDevices = 0; rsmi_num_monitor_devices(&numMonDevices); if (rsmi_dev_compute_partition_get(cardAdded, computePartition, kSize) == RSMI_STATUS_SUCCESS) { strCompPartition = computePartition; } - uint64_t device_uuid = 0; if (rsmi_dev_unique_id_get(cardAdded, &device_uuid) != RSMI_STATUS_SUCCESS) { cardAdded++; @@ -863,7 +922,7 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { temp_primary_unique_id = allSystemNodes.find(device_uuid)->second.s_unique_id; - auto temp_numb_nodes = allSystemNodes.count(temp_primary_unique_id); + temp_numb_nodes = allSystemNodes.count(temp_primary_unique_id); ss << __PRETTY_FUNCTION__ << " | device/node id (cardId) = " << std::to_string(cardId) @@ -895,12 +954,46 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) { LOG_DEBUG(ss); while (numb_nodes > 1) { std::string secNode = "card"; - secNode += std::to_string(cardId); // add the primary node id - AddToDeviceList(secNode); + secNode += std::to_string(cardId); // maps the primary node card to + // secondary - allows get/sets + auto it = allSystemNodes.lower_bound(device_uuid); + auto it_end = allSystemNodes.upper_bound(device_uuid); + if (numb_nodes == temp_numb_nodes) { + auto removalNodeId = it->second.s_node_id; + auto removalGpuId = it->second.s_gpu_id; + auto removalUniqueId = it->second.s_unique_id; + auto removalLocId = it->second.s_location_id; + auto nodesErased = 1; + primary_location_id = removalLocId; + allSystemNodes.erase(it++); + ss << __PRETTY_FUNCTION__ + << "\nPRIMARY --> num_nodes == temp_numb_nodes; ERASING " + << std::to_string(nodesErased) << " node -> [node_id = " + << std::to_string(removalNodeId) + << "; gpu_id = " << std::to_string(removalGpuId) + << "; unique_id = " << std::to_string(removalUniqueId) + << "; location_id = " << std::to_string(removalLocId) + << "]"; + LOG_DEBUG(ss); + } + if (it == it_end) { + break; + } + auto myBdfId = it->second.s_location_id; + AddToDeviceList(secNode, myBdfId); + ss << __PRETTY_FUNCTION__ + << "\nSECONDARY --> After adding new node; ERASING -> [node_id = " + << std::to_string(it->second.s_node_id) + << "; gpu_id = " << std::to_string(it->second.s_gpu_id) + << "; unique_id = " << std::to_string(it->second.s_unique_id) + << "; location_id = " << std::to_string(it->second.s_location_id) + << "]"; + LOG_DEBUG(ss); + allSystemNodes.erase(it++); numb_nodes--; cardAdded++; } - // remove already added nodes associated with current card + // remove any remaining nodes associated with current card auto erasedNodes = allSystemNodes.erase(primary_unique_id); ss << __PRETTY_FUNCTION__ << " | After finding primary_unique_id = " << std::to_string(primary_unique_id) << " erased " diff --git a/projects/amdsmi/rocm_smi/src/rocm_smi_utils.cc b/projects/amdsmi/rocm_smi/src/rocm_smi_utils.cc index 3f9a8b874a..fd20783e89 100755 --- a/projects/amdsmi/rocm_smi/src/rocm_smi_utils.cc +++ b/projects/amdsmi/rocm_smi/src/rocm_smi_utils.cc @@ -539,7 +539,7 @@ std::vector readEntireFile(std::string path) { void displayAppTmpFilesContent() { std::vector tmpFiles = getListOfAppTmpFiles(); if (!tmpFiles.empty()) { - for (auto &x: tmpFiles) { + for (auto &x : tmpFiles) { std::string out = readFile(x); std::cout << __PRETTY_FUNCTION__ << " | Temporary file: " << x << "; Contained content: " << out << std::endl; @@ -558,7 +558,7 @@ std::string debugVectorContent(std::vector v) { for (auto it=v.begin(); it < v.end(); it++) { ss << *it; auto temp_it = it; - if(++temp_it != v.end()) { + if (++temp_it != v.end()) { ss << ", "; } } @@ -576,7 +576,7 @@ std::string displayAllDevicePaths(std::vector> v) { for (auto it=v.begin(); it < v.end(); it++) { ss << (*it)->path(); auto temp_it = it; - if(++temp_it != v.end()) { + if (++temp_it != v.end()) { ss << ", "; } } diff --git a/projects/amdsmi/src/CMakeLists.txt b/projects/amdsmi/src/CMakeLists.txt index 8b3891eb34..7e5d043e75 100644 --- a/projects/amdsmi/src/CMakeLists.txt +++ b/projects/amdsmi/src/CMakeLists.txt @@ -21,7 +21,7 @@ message("--------Proj Src Dir: " ${PROJECT_SOURCE_DIR}) include(utils) ################# Determine the library version ######################### -set(SO_VERSION_GIT_TAG_PREFIX "amd_smi_so_ver") +set(SO_VERSION_GIT_TAG_PREFIX "amdsmi_so_ver") set(SRC_DIR "amd_smi") set(INC_DIR "${PROJECT_SOURCE_DIR}/include/amd_smi") @@ -50,7 +50,7 @@ set(INC_LIST "${PROJECT_SOURCE_DIR}/rocm_smi/include/rocm_smi/rocm_smi.h" "${PROJECT_SOURCE_DIR}/rocm_smi/include/rocm_smi/rocm_smi_utils.h") -if(ESMI_AVAILABLE) +if(ENABLE_ESMI_LIB) list(APPEND INC_LIST ${ESMI_INC_DIR}/e_smi/e_smi.h) list(APPEND INC_LIST ${ESMI_INC_DIR}/e_smi/e_smi_monitor.h) list(APPEND INC_LIST ${ESMI_INC_DIR}/e_smi/e_smi_utils.h) @@ -60,7 +60,7 @@ message("Package version: ${PKG_VERSION_STR}") # Debian package specific variables # Set a default value for the package version -get_version_from_tag("1.0.0.0" ${SO_VERSION_GIT_TAG_PREFIX} GIT) +get_version_from_tag("${${AMD_SMI_LIBS_TARGET}_VERSION_MAJOR}.${${AMD_SMI_LIBS_TARGET}_VERSION_MINOR}.0.0" ${SO_VERSION_GIT_TAG_PREFIX} GIT) # VERSION_* variables should be set by get_version_from_tag if(${ROCM_PATCH_VERSION}) diff --git a/projects/amdsmi/src/amd_smi/amd_smi.cc b/projects/amdsmi/src/amd_smi/amd_smi.cc index ff5988c126..145f4e639b 100644 --- a/projects/amdsmi/src/amd_smi/amd_smi.cc +++ b/projects/amdsmi/src/amd_smi/amd_smi.cc @@ -823,14 +823,14 @@ amdsmi_init_gpu_event_notification(amdsmi_processor_handle processor_handle) { } amdsmi_status_t - amdsmi_set_gpu_event_notification_mask(amdsmi_processor_handle processor_handle, - uint64_t mask) { +amdsmi_set_gpu_event_notification_mask(amdsmi_processor_handle processor_handle, + uint64_t mask) { return rsmi_wrapper(rsmi_event_notification_mask_set, processor_handle, mask); } amdsmi_status_t - amdsmi_get_gpu_event_notification(int timeout_ms, - uint32_t *num_elem, amdsmi_evt_notification_data_t *data) { +amdsmi_get_gpu_event_notification(int timeout_ms, + uint32_t *num_elem, amdsmi_evt_notification_data_t *data) { AMDSMI_CHECK_INIT(); if (num_elem == nullptr || data == nullptr) { @@ -986,6 +986,52 @@ amdsmi_is_P2P_accessible(amdsmi_processor_handle processor_handle_src, return amd::smi::rsmi_to_amdsmi_status(rstatus); } +// Compute Partition functions +amdsmi_status_t +amdsmi_dev_compute_partition_get(amdsmi_processor_handle processor_handle, + char *compute_partition, uint32_t len) { + AMDSMI_CHECK_INIT(); + return rsmi_wrapper(rsmi_dev_compute_partition_get, processor_handle, + compute_partition, len); +} + +amdsmi_status_t +amdsmi_dev_compute_partition_set(amdsmi_processor_handle processor_handle, + amdsmi_compute_partition_type_t compute_partition) { + AMDSMI_CHECK_INIT(); + return rsmi_wrapper(rsmi_dev_compute_partition_set, processor_handle, + static_cast(compute_partition)); +} + +amdsmi_status_t +amdsmi_dev_compute_partition_reset(amdsmi_processor_handle processor_handle) { + AMDSMI_CHECK_INIT(); + return rsmi_wrapper(rsmi_dev_compute_partition_reset, processor_handle); +} + +// Memory Partition functions +amdsmi_status_t +amdsmi_dev_memory_partition_get(amdsmi_processor_handle processor_handle, + char *memory_partition, uint32_t len) { + AMDSMI_CHECK_INIT(); + return rsmi_wrapper(rsmi_dev_memory_partition_get, processor_handle, + memory_partition, len); +} + +amdsmi_status_t +amdsmi_dev_memory_partition_set(amdsmi_processor_handle processor_handle, + amdsmi_memory_partition_type_t memory_partition) { + AMDSMI_CHECK_INIT(); + return rsmi_wrapper(rsmi_dev_memory_partition_set, processor_handle, + static_cast(memory_partition)); +} + +amdsmi_status_t +amdsmi_dev_memory_partition_reset(amdsmi_processor_handle processor_handle) { + AMDSMI_CHECK_INIT(); + return rsmi_wrapper(rsmi_dev_memory_partition_reset, processor_handle); +} + // TODO(bliu) : other xgmi related information amdsmi_status_t amdsmi_get_xgmi_info(amdsmi_processor_handle processor_handle, amdsmi_xgmi_info_t *info) { @@ -1600,6 +1646,34 @@ amdsmi_get_gpu_bad_page_info(amdsmi_processor_handle processor_handle, uint32_t return AMDSMI_STATUS_SUCCESS; } +amdsmi_status_t amdsmi_get_gpu_ras_feature_info( + amdsmi_processor_handle processor_handle, amdsmi_ras_feature_t *ras_feature) { + AMDSMI_CHECK_INIT(); + + if (ras_feature == nullptr) { + return AMDSMI_STATUS_INVAL; + } + + amd::smi::AMDSmiGPUDevice* gpu_device = nullptr; + amdsmi_status_t r = get_gpu_device_from_handle(processor_handle, + &gpu_device); + if (r != AMDSMI_STATUS_SUCCESS) + return r; + + rsmi_ras_feature_info_t rsmi_ras_feature; + r = rsmi_wrapper(rsmi_ras_feature_info_get, processor_handle, + &rsmi_ras_feature); + + if (r != AMDSMI_STATUS_SUCCESS) + return r; + + ras_feature->ecc_correction_schema_flag + = rsmi_ras_feature.ecc_correction_schema_flag; + ras_feature->ras_eeprom_version = rsmi_ras_feature.ras_eeprom_version; + + return AMDSMI_STATUS_SUCCESS; +} + amdsmi_status_t amdsmi_get_gpu_total_ecc_count(amdsmi_processor_handle processor_handle, amdsmi_error_count_t *ec) { AMDSMI_CHECK_INIT(); @@ -2798,7 +2872,7 @@ amdsmi_status_t amdsmi_get_cpu_current_io_bandwidth(amdsmi_cpusocket_handle sock return status; link.link_name = io_link.link_name; - link.bw_type= io_link.bw_type; + link.bw_type = static_cast(io_link.bw_type); *io_bw = bw; return AMDSMI_STATUS_SUCCESS; @@ -2824,7 +2898,7 @@ amdsmi_status_t amdsmi_get_cpu_current_xgmi_bw(amdsmi_cpusocket_handle socket_ha return status; link.link_name = io_link.link_name; - link.bw_type= io_link.bw_type; + link.bw_type= static_cast(io_link.bw_type); *xgmi_bw = bw; return AMDSMI_STATUS_SUCCESS; diff --git a/projects/amdsmi/tests/amd_smi_test/functional/xgmi_read_write.cc b/projects/amdsmi/tests/amd_smi_test/functional/xgmi_read_write.cc index 756e793db3..d252cda1f8 100755 --- a/projects/amdsmi/tests/amd_smi_test/functional/xgmi_read_write.cc +++ b/projects/amdsmi/tests/amd_smi_test/functional/xgmi_read_write.cc @@ -85,6 +85,7 @@ void TestXGMIReadWrite::Close() { void TestXGMIReadWrite::Run(void) { + GTEST_SKIP_("Temporarily disabled"); amdsmi_status_t err; amdsmi_xgmi_status_t err_stat; uint64_t hive_id; diff --git a/projects/amdsmi/tools/generator.py b/projects/amdsmi/tools/generator.py index 31b824ecfd..18383ee118 100644 --- a/projects/amdsmi/tools/generator.py +++ b/projects/amdsmi/tools/generator.py @@ -63,9 +63,11 @@ def parseArgument(): help='The input file name') parser.add_argument('-l', '--library', type=str, required=True, help='Loading dynamic link libraries') + parser.add_argument('-e', '--extra-args', type=str, required=False, + help='Parse extra arguments to clang') args = vars(parser.parse_args()) - return args['output'], args['input'], args['library'] + return args['output'], args['input'], args['library'], args['extra_args'] def replace_line(full_path_file_name, string_to_repalce, new_string): @@ -82,7 +84,13 @@ def replace_line(full_path_file_name, string_to_repalce, new_string): def main(): - output_file, input_file, library = parseArgument() + output_file, input_file, library, clang_extra_args = parseArgument() + + # make args string easy to append + if clang_extra_args is None: + clang_extra_args = "" + else: + clang_extra_args = " " + clang_extra_args library_name = os.path.basename(library) @@ -131,7 +139,7 @@ except OSError as error: print("Unknown operating system. It is only supporing Linux and Windows.") return - arguments.append("--clang-args=-I" + clang_include_dir) + arguments.append("--clang-args=-I" + clang_include_dir + clang_extra_args) clangToPy(arguments) replace_line(output_file, line_to_replace, new_line) diff --git a/projects/amdsmi/update_wrapper.sh b/projects/amdsmi/update_wrapper.sh new file mode 100755 index 0000000000..0a836f5405 --- /dev/null +++ b/projects/amdsmi/update_wrapper.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash + +# this program generates py-interface/amdsmi_wrapper.py + +set -eu + +# get current dir +DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# override by calling this script with: +# DOCKER_NAME=yourdockername ./update_wrapper.sh +DOCKER_NAME="${DOCKER_NAME:-dmitriigalantsev/amdsmi_wrapper_updater}" + +command -v docker &>/dev/null || { + echo "Please install docker!" >&2 + exit 1 +} + +does_image_exist () { + docker images | grep -q "$DOCKER_NAME" +} + +if ! does_image_exist; then + # if you prefer to not generate it yourself: + # pull from https://hub.docker.com/r/dmitriigalantsev/amdsmi_wrapper_updater + # using the following command: + # docker pull dmitriigalantsev/amdsmi_wrapper_updater + echo "No docker image found! Generating one" + # set to 0 because it's compatible with more systems + DOCKER_BUILDKIT="${DOCKER_BUILDKIT:0}" docker build "$DIR/py-interface" -t "$DOCKER_NAME":latest +fi + +ENABLE_ESMI_LIB="" +# source ENABLE_ESMI_LIB variable from the previous build if it exists +if [ -e 'build/CMakeCache.txt' ]; then + GREP_RESULT=$(grep "ENABLE_ESMI_LIB" "${DIR}/build/CMakeCache.txt" | cut -d = -f 2) + ENABLE_ESMI_LIB="-DENABLE_ESMI_LIB=$GREP_RESULT" + echo "ENABLE_ESMI_LIB: [$ENABLE_ESMI_LIB]" +fi + +docker run --rm -ti --volume "$DIR":/src:rw "$DOCKER_NAME":latest bash -c " +cp -r /src /tmp/src \ + && cd /tmp/src \ + && rm -rf build .cache \ + && cmake -B build -DBUILD_WRAPPER=ON $ENABLE_ESMI_LIB \ + && make -C build -j $(nproc) \ + && cp /tmp/src/py-interface/amdsmi_wrapper.py /src/py-interface/amdsmi_wrapper.py" + +echo -e "Generated new wrapper! +[$DIR/py-interface/amdsmi_wrapper.py]"