Merge amd-dev into amd-master 20230425

Change-Id: I4e5a86dec46db2db5e012e0cf68214c15fe6c56a
Signed-off-by: Galantsev, Dmitrii <dmitrii.galantsev@amd.com>
Этот коммит содержится в:
Galantsev, Dmitrii
2023-04-25 12:46:17 -05:00
родитель 779d96459b f8e7d93a69
Коммит 10bfe16916
12 изменённых файлов: 1461 добавлений и 754 удалений
+5 -2
Просмотреть файл
@@ -21,6 +21,7 @@ add_custom_command(
${PY_PACKAGE_DIR}/amdsmi_parser.py
${PY_PACKAGE_DIR}/amdsmi_cli_exceptions.py
${PY_PACKAGE_DIR}/BDF.py
${PY_PACKAGE_DIR}/README.md
DEPENDS amdsmi_cli
COMMAND mkdir -p ${PY_PACKAGE_DIR}/
COMMAND ln -Pf ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${PY_PACKAGE_DIR}/
@@ -32,7 +33,8 @@ add_custom_command(
COMMAND ln -Pf ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_logger.py ${PY_PACKAGE_DIR}/
COMMAND ln -Pf ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_parser.py ${PY_PACKAGE_DIR}/
COMMAND ln -Pf ${CMAKE_CURRENT_SOURCE_DIR}/amdsmi_cli_exceptions.py ${PY_PACKAGE_DIR}/
COMMAND ln -Pf ${CMAKE_CURRENT_SOURCE_DIR}/BDF.py ${PY_PACKAGE_DIR}/)
COMMAND ln -Pf ${CMAKE_CURRENT_SOURCE_DIR}/BDF.py ${PY_PACKAGE_DIR}/
COMMAND ln -Pf ${CMAKE_CURRENT_SOURCE_DIR}/README.md ${PY_PACKAGE_DIR}/)
# The CLI requires the python amdsmi wrapper to be installed
add_custom_target(
@@ -47,7 +49,8 @@ add_custom_target(
${PY_PACKAGE_DIR}/amdsmi_logger.py
${PY_PACKAGE_DIR}/amdsmi_parser.py
${PY_PACKAGE_DIR}/amdsmi_cli_exceptions.py
${PY_PACKAGE_DIR}/BDF.py)
${PY_PACKAGE_DIR}/BDF.py
${PY_PACKAGE_DIR}/README.md)
install(
DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PY_PACKAGE_DIR}
+333
Просмотреть файл
@@ -0,0 +1,333 @@
# AMD System Management Interface
This tool acts as a command line interface for manipulating
and monitoring the amdgpu kernel, and is intended to replace
and deprecate the existing rocm_smi CLI tool & gpuv-smi tool.
It uses Ctypes to call the amd_smi_lib API.
Recommended: At least one AMD GPU with AMD driver installed
## Requirements
* python 3.7+ 64-bit
* driver must be loaded for amdsmi_init() to pass
## Installation
- Install amdgpu driver
- Through package manager install amd-smi-lib
- cd /opt/<rocm_instance>/share/amd_smi
- pip install .
- /opt/<rocm_instance>/bin/amd-smi
### Example of Ubuntu 22.04 post amdgpu driver install
``` shell
apt install amd-smi-lib
cd /opt/rocm/share/amd_smi
pip install .
/opt/rocm/bin/amd-smi
```
Add /opt/rocm/bin to your local path to access amd-smi via the cmdline
## Usage
amd-smi will report the version and current platform detected when running the command without arguments:
``` bash
amd-smi
usage: amd-smi [-h] ...
AMD System Management Interface | Version: 0.0.4 | Platform: Linux Baremetal
optional arguments:
-h, --help show this help message and exit
AMD-SMI Commands:
Descriptions:
version Display version information
discovery (list)
Display discovery 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
topology Displays topology information of the devices.
set Set options for devices.
reset Reset options for devices.
```
More detailed verison information can be give when running `amd-smi version`
Each command will have detailed information via `amd-smi [command] --help`
## Commands
For convenience, here is the help output for each command
``` bash
amd-smi discovery --help
usage: amd-smi discovery [-h] [--json | --csv] [--file FILE]
[--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
[-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
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:ffffffff-ffff-ffff-ffff-ffffffffffff
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
```
``` bash
amd-smi firmware --help
usage: amd-smi firmware [-h] [--json | --csv] [--file FILE]
[--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
[-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:ffffffff-ffff-ffff-ffff-ffffffffffff
-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
```
```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] [-l] [-d] [-c] [-r] [-B] [-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:ffffffff-ffff-ffff-ffff-ffffffffffff
-a, --asic All asic information
-b, --bus All bus information
-V, --vbios All video bios information (if available)
-l, --limit All limit metric values (i.e. power and thermal limits)
-d, --driver Displays driver version
-c, --caps All caps information
-r, --ras Displays RAS features information
-B, --board All board information
-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
```
```bash
amd-smi bad-pages --help
usage: amd-smi bad-pages [-h] [--json | --csv] [--file FILE]
[--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
[-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:ffffffff-ffff-ffff-ffff-ffffffffffff
-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
```
```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] [-u]
[-b] [-p] [-c] [-t] [-e] [-P] [-V] [-f] [-C] [-o] [-M] [-l] [-r]
[-x] [-E] [-m]
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:ffffffff-ffff-ffff-ffff-ffffffffffff
-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
-u, --usage Displays engine usage information
-b, --fb-usage Total and used framebuffer
-p, --power Current power usage
-c, --clock Average, max, and current clock frequencies
-t, --temperature Current temperatures
-e, --ecc Number of ECC errors
-P, --pcie Current PCIe speed and width
-V, --voltage Current GPU voltages
-f, --fan Current fan speed
-C, --voltage-curve Display voltage curve
-o, --overdrive Current GPU clock overdrive level
-M, --mem-overdrive Current memory clock overdrive level
-l, --perf-level Current DPM performance level
-r, --replay-count PCIe replay count
-x, --xgmi-err XGMI error information since last read
-E, --energy Amount of energy consumed
-m, --mem-usage Memory usage per block
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
```
```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]
[-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:ffffffff-ffff-ffff-ffff-ffffffffffff
-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.
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
```
```bash
amd-smi topology --help
usage: amd-smi topology [-h] [--json | --csv] [--file FILE]
[--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
[-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:ffffffff-ffff-ffff-ffff-ffffffffffff
-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
```
```bash
amd-smi set --help
usage: amd-smi set [-h] [--json | --csv] [--file FILE]
[--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] -g GPU [GPU ...]
[-c CLK_TYPE [CLK_LEVELS ...]] [-s CLK_LEVELS [CLK_LEVELS ...]]
[-m CLK_LEVELS [CLK_LEVELS ...]] [-p CLK_LEVELS [CLK_LEVELS ...]]
[-S SCLKLEVEL SCLK] [-M MCLKLEVEL MCLK] [-V POINT SCLK SVOLT]
[-r SCLKMIN SCLKMAX] [-R MCLKMIN MCLKMAX] [-f %] [-l LEVEL] [-o %]
[-O %] [-w WATTS] [-P SETPROFILE] [-d SCLKMAX]
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:ffffffff-ffff-ffff-ffff-ffffffffffff
-c CLK_TYPE [CLK_LEVELS ...], --clock CLK_TYPE [CLK_LEVELS ...] Sets clock frequency levels for specified clocks
-s CLK_LEVELS [CLK_LEVELS ...], --sclk CLK_LEVELS [CLK_LEVELS ...] Sets GPU clock frequency levels
-m CLK_LEVELS [CLK_LEVELS ...], --mclk CLK_LEVELS [CLK_LEVELS ...] Sets memory clock frequency levels
-p CLK_LEVELS [CLK_LEVELS ...], --pcie CLK_LEVELS [CLK_LEVELS ...] Sets PCIe Bandwith
-S SCLKLEVEL SCLK, --slevel SCLKLEVEL SCLK Change GPU clock frequency and voltage for a specific level
-M MCLKLEVEL MCLK, --mlevel MCLKLEVEL MCLK Change GPU memory frequency and voltage for a specific level
-V POINT SCLK SVOLT, --vc POINT SCLK SVOLT Change SCLK voltage curve for a specified point
-r SCLKMIN SCLKMAX, --srange SCLKMIN SCLKMAX Sets min and max SCLK speed
-R MCLKMIN MCLKMAX, --mrange MCLKMIN MCLKMAX Sets min and max MCLK speed
-f %, --fan % Sets GPU fan speed (0-255 or 0-100%)
-l LEVEL, --perflevel LEVEL Sets performance level
-o %, --overdrive % Set GPU overdrive (0-20%) ***DEPRECATED IN NEWER KERNEL VERSIONS (use --slevel instead)***
-O %, --memoverdrive % Set memory overclock overdrive level ***DEPRECATED IN NEWER KERNEL VERSIONS (use --mlevel instead)***
-w WATTS, --poweroverdrive WATTS Set the maximum GPU power using power overdrive in Watts
-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
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
```
```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] [-o] [-x] [-d]
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:ffffffff-ffff-ffff-ffff-ffffffffffff
-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
-o, --poweroverdrive Set the maximum GPU power back to the device default state
-x, --xgmierr Reset XGMI error counts
-d, --perfdeterminism Disable performance determinism
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
```
## Disclaimer
The information contained herein is for informational purposes only, and is subject to change without notice. While every precaution has been taken in the preparation of this document, it may contain technical inaccuracies, omissions and typographical errors, and AMD is under no obligation to update or otherwise correct this information. Advanced Micro Devices, Inc. makes no representations or warranties with respect to the accuracy or completeness of the contents of this document, and assumes no liability of any kind, including the implied warranties of noninfringement, merchantability or fitness for particular purposes, with respect to the operation or use of AMD hardware, software or other products described herein.
AMD, the AMD Arrow logo, and combinations thereof are trademarks of Advanced Micro Devices, Inc. Other product names used in this publication are for identification purposes only and may be trademarks of their respective companies.
Copyright (c) 2014-2023 Advanced Micro Devices, Inc. All rights reserved.
+1 -1
Просмотреть файл
@@ -1 +1 @@
__version__ = "0.0.3"
__version__ = "0.0.4"
+2 -3
Просмотреть файл
@@ -29,6 +29,7 @@ from amdsmi_logger import AMDSMILogger
import amdsmi_cli_exceptions
from amdsmi import amdsmi_interface
def _print_error(e, destination):
if destination == 'stdout':
print(e)
@@ -36,9 +37,7 @@ def _print_error(e, destination):
f = open(destination, "w")
f.write(e)
f.close()
print("Error occured. Result written to " +
str(destination) + " file")
print("Error occured. Result written to " + str(destination) + " file")
if __name__ == "__main__":
Разница между файлами не показана из-за своего большого размера Загрузить разницу
+26 -16
Просмотреть файл
@@ -26,6 +26,8 @@ import sys
import time
from pathlib import Path
from subprocess import run
from subprocess import PIPE, STDOUT
from amdsmi_init import *
from BDF import BDF
@@ -53,18 +55,11 @@ class AMDSMIHelpers():
self._is_linux = True
logging.debug(f"AMDSMIHelpers: Platform is linux:{self._is_linux}")
product_name = ""
product_name_path = Path("/sys/class/dmi/id/product_name")
if product_name_path.exists():
product_name = product_name_path.read_text().strip()
if product_name == "":
# Unable to determine product_name default to baremetal
output = run(["lscpu"], stdout=PIPE, stderr=STDOUT, encoding="UTF-8").stdout
if "hypervisor" not in output:
self._is_baremetal = True
# Determine if a system is baremetal by deduction
self._is_baremetal = not self._is_hypervisor and not self._is_virtual_os
else:
self._is_virtual_os = True
def os_info(self, string_format=True):
"""Return operating_system and type information ex. (Linux, Baremetal)
@@ -229,7 +224,7 @@ class AMDSMIHelpers():
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
subcommand(args, multiple_devices=True, gpu=device_handle)
logger.print_output(multiple_device_output=True)
logger.print_output(multiple_device_enabled=True)
return True, args.gpu
elif len(args.gpu) == 1:
args.gpu = args.gpu[0]
@@ -240,13 +235,14 @@ class AMDSMIHelpers():
return False, args.gpu
def handle_watch(self, args, subcommand):
def handle_watch(self, args, subcommand, logger):
"""This function will run the subcommand multiple times based
on the passed watch, watch_time, and iterations passed in.
params:
args - argparser args to pass to subcommand
subcommand (AMDSMICommands) - Function that can handle
watching output (Currently: metric & process)
logger (AMDSMILogger) - Logger for accessing config values
return:
Nothing
"""
@@ -260,6 +256,8 @@ class AMDSMIHelpers():
args.watch_time = None
args.iterations = None
# Set the signal handler to flush a delmiter to file if the format is json
print("'CTRL' + 'C' to stop watching output:")
if watch_time: # Run for set amount of time
iterations_ran = 0
end_time = time.time() + watch_time
@@ -267,11 +265,11 @@ class AMDSMIHelpers():
subcommand(args, watching_output=True)
# Handle iterations limit
iterations_ran += 1
if iterations:
if iterations >= iterations_ran:
if iterations is not None:
if iterations <= iterations_ran:
break
time.sleep(watch)
elif iterations: # Run for a set amount of iterations
elif iterations is not None: # Run for a set amount of iterations
for iteration in range(iterations):
subcommand(args, watching_output=True)
if iteration == iterations - 1: # Break on iteration completion
@@ -386,3 +384,15 @@ class AMDSMIHelpers():
return True, profile_presets[profile]
else:
return False, profile_presets.values()
def has_ras_support(self, device_handle):
try:
caps_info = amdsmi_interface.amdsmi_get_caps_info(device_handle)
if caps_info['ras_supported']:
return True
else:
return False
except amdsmi_exception.AmdSmiLibraryException:
return False
+283 -238
Просмотреть файл
@@ -20,13 +20,15 @@
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
import csv
import json
import re
import time
import yaml
import re
from enum import Enum
from amdsmi_helpers import AMDSMIHelpers
import amdsmi_cli_exceptions
class AMDSMILogger():
def __init__(self, compatibility='amdsmi', format='human_readable',
@@ -37,7 +39,7 @@ class AMDSMILogger():
self.compatibility = compatibility # amd-smi, gpuv-smi, or rocm-smi
self.format = format # csv, json, or human_readable
self.destination = destination # stdout, path to a file (append)
self.amd_smi_helpers = AMDSMIHelpers()
self.helpers = AMDSMIHelpers()
class LoggerFormat(Enum):
@@ -77,178 +79,18 @@ class AMDSMILogger():
return self.compatibility == self.LoggerCompatibility.gpuvsmi.value
def store_output(self, device_handle, argument, data):
""" Store the argument and device handle according to the compatibility.
Each compatibility function will handle the output format and
populate the output
params:
device_handle - device handle object to the target device output
argument (str) - key to store data
data (dict | list) - Data store against argument
return:
Nothing
"""
gpu_id = self.amd_smi_helpers.get_gpu_id_from_device_handle(device_handle)
if self.is_amdsmi_compatibility():
self._store_output_amdsmi(gpu_id=gpu_id, argument=argument, data=data)
elif self.is_rocmsmi_compatibility():
self._store_output_rocmsmi(gpu_id=gpu_id, argument=argument, data=data)
elif self.is_gpuvsmi_compatibility():
self._store_output_gpuvsmi(gpu_id=gpu_id, argument=argument, data=data)
class CsvStdoutBuilder(object):
def __init__(self):
self.csv_string = []
def write(self, row):
self.csv_string.append(row)
def __str__(self):
return ''.join(self.csv_string)
def _store_output_amdsmi(self, gpu_id, argument, data):
if self.is_json_format() or self.is_human_readable_format():
self.output['gpu'] = int(gpu_id)
if argument == 'values' and isinstance(data, dict):
self.output.update(data)
else:
self.output[argument] = data
elif self.is_csv_format():
# put output into self.csv_output
pass
else:
raise "err"
def _store_output_rocmsmi(self, gpu_id, argument, data):
if self.is_json_format():
# put output into self.json_output
pass
elif self.is_csv_format():
# put output into self.csv_output
pass
elif self.is_human_readable_format():
# put output into self.human_readable_output
pass
else:
raise "err"
def _store_output_gpuvsmi(self, gpu_id, argument, data):
if self.is_json_format() or self.is_human_readable_format():
self.output['gpu'] = int(gpu_id)
self.output[argument] = data
elif self.is_csv_format():
# put output into self.csv_output
pass
else:
raise "err"
def store_multiple_device_output(self):
""" Store the current output into the multiple_device_output
then clear the current output
params:
None
return:
Nothing
"""
if self.is_amdsmi_compatibility():
self._store_multiple_device_output_amdsmi()
elif self.is_rocmsmi_compatibility():
self._store_multiple_device_output_rocmsmi()
elif self.is_gpuvsmi_compatibility():
self._store_multiple_device_output_gpuvsmi()
def _store_multiple_device_output_amdsmi(self):
if self.is_json_format() or self.is_human_readable_format():
self.multiple_device_output.append(self.output)
self.output = {}
elif self.is_csv_format():
# put output into self.csv_output
pass
else:
raise "err"
def _store_multiple_device_output_rocmsmi(self):
if self.is_json_format():
# put output into self.json_output
pass
elif self.is_csv_format():
# put output into self.csv_output
pass
elif self.is_human_readable_format():
# put output into self.human_readable_output
pass
else:
raise "err"
def _store_multiple_device_output_gpuvsmi(self):
if self.is_json_format() or self.is_human_readable_format():
self.multiple_device_output.append(self.output)
self.output = {}
elif self.is_csv_format():
# put output into self.csv_output
pass
else:
raise "err"
def store_watch_output(self, multiple_devices=False):
""" Add the current output or multiple_devices_output
params:
multiple_devices (bool) - True if watching multiple devices
return:
Nothing
"""
if self.is_amdsmi_compatibility():
self._store_watch_output_amdsmi(multiple_devices=multiple_devices)
elif self.is_rocmsmi_compatibility():
self._store_watch_output_rocmsmi(multiple_devices=multiple_devices)
elif self.is_gpuvsmi_compatibility():
self._store_watch_output_gpuvsmi(multiple_devices=multiple_devices)
def _store_watch_output_amdsmi(self, multiple_devices):
if self.is_json_format() or self.is_human_readable_format():
values = self.output
if multiple_devices:
values = self.multiple_device_output
self.watch_output.append({'timestamp': int(time.time()),
'values': values})
elif self.is_csv_format():
# put output into self.csv_output
pass
else:
raise "err"
def _store_watch_output_rocmsmi(self, multiple_devices):
if self.is_json_format():
# put output into self.json_output
pass
elif self.is_csv_format():
# put output into self.csv_output
pass
elif self.is_human_readable_format():
# put output into self.human_readable_output
pass
else:
raise "err"
def _store_watch_output_gpuvsmi(self, multiple_devices):
if self.is_json_format() or self.is_human_readable_format():
values = self.output
if multiple_devices:
values = self.multiple_device_output
self.watch_output.append({'timestamp': int(time.time()),
'values': values})
elif self.is_csv_format():
# put output into self.csv_output
pass
else:
raise "err"
def capitalize_keys(self, input_dict):
def _capitalize_keys(self, input_dict):
output_dict = {}
for key in input_dict.keys():
# Capitalize key if it is a string
@@ -258,12 +100,12 @@ class AMDSMILogger():
cap_key = key
if isinstance(input_dict[key], dict):
output_dict[cap_key] = self.capitalize_keys(input_dict[key])
output_dict[cap_key] = self._capitalize_keys(input_dict[key])
elif isinstance(input_dict[key], list):
cap_key_list = []
for data in input_dict[key]:
if isinstance(data, dict):
cap_key_list.append(self.capitalize_keys(data))
cap_key_list.append(self._capitalize_keys(data))
else:
cap_key_list.append(data)
output_dict[cap_key] = cap_key_list
@@ -273,9 +115,9 @@ class AMDSMILogger():
return output_dict
def convert_json_to_human_readable(self, json_object):
def _convert_json_to_human_readable(self, json_object):
# First Capitalize all keys in the json object
capitalized_json = self.capitalize_keys(json_object)
capitalized_json = self._capitalize_keys(json_object)
json_string = json.dumps(capitalized_json, indent=4)
yaml_data = yaml.safe_load(json_string)
yaml_output = yaml.dump(yaml_data, sort_keys=False, allow_unicode=True)
@@ -303,91 +145,294 @@ class AMDSMILogger():
return clean_yaml_output
def print_output(self, multiple_device_output=False, watch_output=False):
def flatten_dict(self, target_dict, topology_override=False):
"""This will flatten a dictionary out to a single level of key value stores
removing key's with dictionaries and wrapping each value to in a list
ex:
{
'usage': {
'gfx_usage': 0,
'mem_usage': 0,
'mm_usage_list': [22,0,0]
}
}
to:
{
'gfx_usage': 0,
'mem_usage': 0,
'mm_usage_list': [22,0,0]}
}
Args:
target_dict (dict): Dictionary to flatten
parent_key (str):
"""
# print(target_dict)
output_dict = {}
# First flatten out values
# separetly handle ras and process and firmware
# If there are multi values, and the values are all dicts
# Then flatten the sub values with parent key
for key, value in target_dict.items():
if isinstance(value, dict):
# Check number of items in the dict
if len(value.values()) > 1 or topology_override:
value_with_parent_key = {}
for parent_key, child_dict in value.items():
if isinstance(child_dict, dict):
if parent_key in ('gfx'):
for child_key, value1 in child_dict.items():
value_with_parent_key[child_key] = value1
else:
for child_key, value1 in child_dict.items():
value_with_parent_key[parent_key + '_' + child_key] = value1
else:
if topology_override:
value_with_parent_key[key + '_' + parent_key] = child_dict
else:
value_with_parent_key[parent_key] = child_dict
value = value_with_parent_key
if self.is_gpuvsmi_compatibility():
if key in ('asic', 'bus', 'pcie', 'vbios','board', 'limit'):
value_with_parent_key = {}
for child_key, child_value in value.items():
value_with_parent_key[key + '_' + child_key] = child_value
value = value_with_parent_key
output_dict.update(self.flatten_dict(value).items())
else:
output_dict[key] = value
return output_dict
def store_output(self, device_handle, argument, data):
""" Store the argument and device handle according to the compatibility.
Each compatibility function will handle the output format and
populate the output
params:
device_handle - device handle object to the target device output
argument (str) - key to store data
data (dict | list) - Data store against argument
return:
Nothing
"""
gpu_id = self.helpers.get_gpu_id_from_device_handle(device_handle)
if self.is_amdsmi_compatibility():
self._store_output_amdsmi(gpu_id=gpu_id, argument=argument, data=data)
elif self.is_rocmsmi_compatibility():
self._store_output_rocmsmi(gpu_id=gpu_id, argument=argument, data=data)
elif self.is_gpuvsmi_compatibility():
self._store_output_gpuvsmi(gpu_id=gpu_id, argument=argument, data=data)
def _store_output_amdsmi(self, gpu_id, argument, data):
if argument == 'timestamp': # Make sure timestamp is the first element in the output
self.output['timestamp'] = int(time.time())
if self.is_json_format() or self.is_human_readable_format():
self.output['gpu'] = int(gpu_id)
if argument == 'values' and isinstance(data, dict):
self.output.update(data)
else:
self.output[argument] = data
elif self.is_csv_format():
# New way is in gpuvsmi func
self.output['gpu'] = int(gpu_id)
if argument == 'values' or isinstance(data, dict):
flat_dict = self.flatten_dict(data)
self.output.update(flat_dict)
else:
self.output[argument] = data
else:
raise amdsmi_cli_exceptions(self, "Invalid output format given, only json, csv, and human_readable supported")
def _store_output_rocmsmi(self, gpu_id, argument, data):
if self.is_json_format():
# put output into self.json_output
pass
elif self.is_csv_format():
# put output into self.csv_output
pass
elif self.is_human_readable_format():
# put output into self.human_readable_output
pass
else:
raise amdsmi_cli_exceptions(self, "Invalid output format given, only json, csv, and human_readable supported")
def _store_output_gpuvsmi(self, gpu_id, argument, data):
if argument == 'timestamp': # Make sure timestamp is the first element in the output
self.output['timestamp'] = int(time.time())
if self.is_json_format() or self.is_human_readable_format():
self.output['gpu'] = int(gpu_id)
self.output[argument] = data
elif self.is_csv_format():
self.output['gpu'] = int(gpu_id)
if argument == 'values' or isinstance(data, dict):
flat_dict = self.flatten_dict(data)
self.output.update(flat_dict)
else:
self.output[argument] = data
gpuv_flat_dict = {}
for key, value in self.output.items():
gpuv_flat_dict[key] = value
# Change AMDSMI_STATUS strings to N/A for gpuv compatability
if isinstance(value, str):
if 'AMDSMI_STATUS' in value:
gpuv_flat_dict[key] = 'N/A'
# Change bdf and uuid keys for gpuv compatability
if isinstance(key, str):
if key in ('bdf','uuid'):
gpuv_flat_dict['gpu_' + key] = gpuv_flat_dict.pop(key)
self.output = gpuv_flat_dict
else:
raise amdsmi_cli_exceptions(self, "Invalid output format given, only json, csv, and human_readable supported")
def store_multiple_device_output(self):
""" Store the current output into the multiple_device_output
then clear the current output
params:
None
return:
Nothing
"""
if not self.output:
return
output = {}
for key, value in self.output.items():
output[key] = value
self.multiple_device_output.append(output)
self.output = {}
def store_watch_output(self, multiple_device_enabled=False):
""" Add the current output or multiple_devices_output
params:
multiple_device_enabled (bool) - True if watching multiple devices
return:
Nothing
"""
if multiple_device_enabled:
for output in self.multiple_device_output:
self.watch_output.append(output)
self.multiple_device_output = []
else:
output = {}
for key, value in self.output.items():
output[key] = value
self.watch_output.append(output)
self.output = {}
def print_output(self, multiple_device_enabled=False, watching_output=False):
""" Print current output acording to format and then destination
params:
multiple_device_output (bool) - True if printing output from
multiple_device_enabled (bool) - True if printing output from
multiple devices
watch_output (bool) - True if printing watch output
watching_output (bool) - True if printing watch output
return:
Nothing
"""
if self.is_json_format():
self._print_json_output(multiple_device_output=multiple_device_output,
watch_output=watch_output)
self._print_json_output(multiple_device_enabled=multiple_device_enabled,
watching_output=watching_output)
elif self.is_csv_format():
self._print_csv_output(multiple_device_output=multiple_device_output,
watch_output=watch_output)
self._print_csv_output(multiple_device_enabled=multiple_device_enabled,
watching_output=watching_output)
elif self.is_human_readable_format():
self._print_human_readable_output(multiple_device_output=multiple_device_output,
watch_output=watch_output)
self._print_human_readable_output(multiple_device_enabled=multiple_device_enabled,
watching_output=watching_output)
def _print_json_output(self, multiple_device_output=False, watch_output=False):
json_output = json.dumps(self.output, indent = 4)
json_multiple_device_output = json.dumps(self.multiple_device_output, indent = 4)
def _print_json_output(self, multiple_device_enabled=False, watching_output=False):
if multiple_device_enabled:
json_output = self.multiple_device_output
else:
json_output = self.output
if self.destination == 'stdout':
if watch_output:
return # We don't need to print to stdout at the end of watch
elif multiple_device_output:
print(json_multiple_device_output)
else:
print(json_output)
if json_output:
json_std_output = json.dumps(json_output, indent=4)
print(json_std_output)
else: # Write output to file
if watch_output:
if watching_output: # Flush the full JSON output to the file on watch command completion
with self.destination.open('w') as output_file:
json.dump(self.watch_output, output_file, indent=4)
elif multiple_device_output:
with self.destination.open('a') as output_file:
json.dump(self.multiple_device_output, output_file, indent=4)
else:
with self.destination.open('a') as output_file:
json.dump(self.output, output_file, indent=4)
json.dump(json_output, output_file, indent=4)
def _print_csv_output(self, multiple_device_output=False, watch_output=False):
if self.destination == 'stdout':
if watch_output:
return # We don't need to print to stdout at the end of watch
elif multiple_device_output:
pass
else:
pass
else: # Write output to file
if watch_output:
pass
elif multiple_device_output:
pass
else:
pass
def _print_human_readable_output(self, multiple_device_output=False, watch_output=False):
if multiple_device_output:
human_readable = ''
for output in self.multiple_device_output:
human_readable += (self.convert_json_to_human_readable(output))
def _print_csv_output(self, multiple_device_enabled=False, watching_output=False):
if multiple_device_enabled:
stored_csv_output = self.multiple_device_output
else:
human_readable = self.convert_json_to_human_readable(self.output)
if not isinstance(self.output, list):
stored_csv_output = [self.output]
if self.destination == 'stdout':
if stored_csv_output:
csv_header = stored_csv_output[0].keys()
csv_stdout_output = self.CsvStdoutBuilder()
writer = csv.DictWriter(csv_stdout_output, csv_header)
writer.writeheader()
writer.writerows(stored_csv_output)
print(str(csv_stdout_output))
else:
if watching_output:
with self.destination.open('w', newline = '') as output_file:
if self.watch_output:
csv_header = self.watch_output[0].keys()
writer = csv.DictWriter(output_file, csv_header)
writer.writeheader()
writer.writerows(self.watch_output)
else:
with self.destination.open('a', newline = '') as output_file:
csv_header = stored_csv_output[0].keys()
writer = csv.DictWriter(output_file, csv_header)
writer.writeheader()
writer.writerows(stored_csv_output)
def _print_human_readable_output(self, multiple_device_enabled=False, watching_output=False):
if multiple_device_enabled:
human_readable_output = ''
for output in self.multiple_device_output:
human_readable_output += self._convert_json_to_human_readable(output)
else:
human_readable_output = self._convert_json_to_human_readable(self.output)
if self.destination == 'stdout':
if watch_output:
# print_output may need another value: flush_output vs watch_output
return
# printing as unicode may fail if locale is not set properly
# see: https://stackoverflow.com/questions/9942594/unicodeencodeerror-ascii-codec-cant-encode-character-u-xa0-in-position-20
# export PYTHONIOENCODING=utf8
try:
# print as unicode
print(human_readable)
# printing as unicode may fail if locale is not set properly
print(human_readable_output)
except UnicodeEncodeError:
# print as ascii, ignore incompatible characters
print(human_readable.encode('ascii', 'ignore').decode('ascii'))
print(human_readable_output.encode('ascii', 'ignore').decode('ascii'))
else:
if watch_output:
return
with self.destination.open('a') as output_file:
output_file.write(human_readable)
return
if watching_output:
with self.destination.open('w') as output_file:
human_readable_output = ''
for output in self.watch_output:
human_readable_output += self._convert_json_to_human_readable(output)
output_file.write(human_readable_output)
else:
with self.destination.open('a') as output_file:
output_file.write(human_readable_output)
+43 -31
Просмотреть файл
@@ -52,6 +52,10 @@ class AMDSMIParser(argparse.ArgumentParser):
version_string = f"Version: {__version__}"
platform_string = f"Platform: {self.helpers.os_info()}"
program_name = 'amd-smi'
if 'gpuv-smi' in sys.argv[0]:
program_name = 'gpuv-smi'
# Adjust argument parser options
super().__init__(
formatter_class=lambda prog: argparse.RawTextHelpFormatter(prog,
@@ -59,14 +63,14 @@ class AMDSMIParser(argparse.ArgumentParser):
width=90),
description=f"AMD System Management Interface | {version_string} | {platform_string}",
add_help=True,
prog="amdsmi_cli")
prog=program_name)
# Setup subparsers
subparsers = self.add_subparsers(
title="AMD-SMI Commands",
parser_class=argparse.ArgumentParser,
help="Descriptions:",
metavar="")
metavar='')
# Add all subparsers
self._add_version_parser(subparsers, version)
@@ -112,7 +116,14 @@ class AMDSMIParser(argparse.ArgumentParser):
raise amdsmi_cli_exceptions.AmdSmiInvalidFilePathException(path, CheckOutputFilePath.outputformat)
if path.is_dir():
path = path / f"{int(time.time())}-amdsmi-output.txt"
file_name = f"{int(time.time())}-amdsmi-output"
if args.json:
file_name += ".json"
elif args.csv:
file_name += ".csv"
else:
file_name += ".txt"
path = path / file_name
path.touch()
setattr(args, self.dest, path)
elif path.is_file():
@@ -162,6 +173,7 @@ class AMDSMIParser(argparse.ArgumentParser):
setattr(args, self.dest, values)
return WatchSelectedAction
def _gpu_select(self, gpu_choices):
""" Custom argparse action to return the device handle(s) for the gpu(s) selected
This will set the destination (args.gpu) to a list of 1 or more device handles
@@ -254,7 +266,7 @@ class AMDSMIParser(argparse.ArgumentParser):
discovery_subcommand_help = "Lists all the devices on the system and the links between devices.\
\nLists all the sockets and for each socket, GPUs and/or CPUs associated to\
\nthat socket alongside some basic information for each device.\
\nIn virtualization environment, it can also list VFs associated to each\
\nIn virtualization environments, it can also list VFs associated to each\
\nGPU with some basic information for each VF."
# Create discovery subparser
@@ -272,8 +284,8 @@ class AMDSMIParser(argparse.ArgumentParser):
def _add_static_parser(self, subparsers, func):
# Subparser help text
static_help = "Gets static information about the specified GPU"
static_subcommand_help = "If no argument is provided, return static information for all GPUs on the system.\
\nIf no static argument is specified all static information will be displayed."
static_subcommand_help = "If no GPU is specified, returns static information for all GPUs on the system.\
\nIf no static argument is provided, all static information will be displayed."
static_optionals_title = "Static Arguments"
# Optional arguments help text
@@ -287,6 +299,7 @@ class AMDSMIParser(argparse.ArgumentParser):
# Options arguments help text for Hypervisors and Baremetal
ras_help = "Displays RAS features information"
board_help = "All board information" # Linux Baremetal only
numa_help = "All numa node information" # Linux Baremetal only
# Options arguments help text for Hypervisors
dfc_help = "All DFC FW table information"
@@ -307,7 +320,6 @@ class AMDSMIParser(argparse.ArgumentParser):
static_parser.add_argument('-a', '--asic', action='store_true', required=False, help=asic_help)
static_parser.add_argument('-b', '--bus', action='store_true', required=False, help=bus_help)
static_parser.add_argument('-V', '--vbios', action='store_true', required=False, help=vbios_help)
static_parser.add_argument('-l', '--limit', action='store_true', required=False, help=limit_help)
static_parser.add_argument('-d', '--driver', action='store_true', required=False, help=driver_help)
static_parser.add_argument('-c', '--caps', action='store_true', required=False, help=caps_help)
@@ -316,6 +328,8 @@ class AMDSMIParser(argparse.ArgumentParser):
static_parser.add_argument('-r', '--ras', action='store_true', required=False, help=ras_help)
if self.helpers.is_linux():
static_parser.add_argument('-B', '--board', action='store_true', required=False, help=board_help)
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)
# Options to only display on a Hypervisor
if self.helpers.is_hypervisor():
@@ -327,7 +341,7 @@ class AMDSMIParser(argparse.ArgumentParser):
def _add_firmware_parser(self, subparsers, func):
# Subparser help text
firmware_help = "Gets firmware information about the specified GPU"
firmware_subcommand_help = "If no argument is provided, return firmware information for all GPUs on the system."
firmware_subcommand_help = "If no GPU is specified, return firmware information for all GPUs on the system."
firmware_optionals_title = "Firmware Arguments"
# Optional arguments help text
@@ -359,8 +373,8 @@ class AMDSMIParser(argparse.ArgumentParser):
# Subparser help text
bad_pages_help = "Gets bad page information about the specified GPU"
bad_pages_subcommand_help = "If no argument is provided, return bad page information for all GPUs on the system."
bad_pages_optionals_title = "Bad pages Arguments"
bad_pages_subcommand_help = "If no GPU is specified, return bad page information for all GPUs on the system."
bad_pages_optionals_title = "Bad Pages Arguments"
# Optional arguments help text
pending_help = "Displays all pending retired pages"
@@ -386,8 +400,8 @@ class AMDSMIParser(argparse.ArgumentParser):
def _add_metric_parser(self, subparsers, func):
# Subparser help text
metric_help = "Gets metric/performance information about the specified GPU"
metric_subcommand_help = "If no argument is provided, return metric information for all GPUs on the system.\
\nIf no metric argument is specified all metric information will be displayed."
metric_subcommand_help = "If no GPU is specified, returns metric information for all GPUs on the system.\
\nIf no metric argument is provided all metric information will be displayed."
metric_optionals_title = "Metric arguments"
# Optional arguments help text
@@ -433,12 +447,11 @@ class AMDSMIParser(argparse.ArgumentParser):
# Add Watch args
self._add_watch_arguments(metric_parser)
# Optional Args
metric_parser.add_argument('-u', '--usage', action='store_true', required=False, help=usage_help)
# Optional Args for Virtual OS and Baremetal systems
if self.helpers.is_virtual_os() or self.helpers.is_baremetal():
metric_parser.add_argument('-b', '--fb-usage', action='store_true', required=False, help=fb_usage_help)
metric_parser.add_argument('-m', '--mem-usage', action='store_true', required=False, help=mem_usage_help)
metric_parser.add_argument('-r', '--replay-count', action='store_true', required=False, help=replay_count_help)
# Optional Args for Hypervisors and Baremetal systems
if self.helpers.is_hypervisor() or self.helpers.is_baremetal():
@@ -448,6 +461,7 @@ class AMDSMIParser(argparse.ArgumentParser):
metric_parser.add_argument('-e', '--ecc', action='store_true', required=False, help=ecc_help)
metric_parser.add_argument('-P', '--pcie', action='store_true', required=False, help=pcie_help)
metric_parser.add_argument('-V', '--voltage', action='store_true', required=False, help=voltage_help)
metric_parser.add_argument('-u', '--usage', action='store_true', required=False, help=usage_help)
# Optional Args for Linux Baremetal Systems
if self.helpers.is_baremetal() and self.helpers.is_linux():
@@ -456,10 +470,8 @@ class AMDSMIParser(argparse.ArgumentParser):
metric_parser.add_argument('-o', '--overdrive', action='store_true', required=False, help=overdrive_help)
metric_parser.add_argument('-M', '--mem-overdrive', action='store_true', required=False, help=mo_help)
metric_parser.add_argument('-l', '--perf-level', action='store_true', required=False, help=perf_level_help)
metric_parser.add_argument('-r', '--replay-count', action='store_true', required=False, help=replay_count_help)
metric_parser.add_argument('-x', '--xgmi-err', action='store_true', required=False, help=xgmi_err_help)
metric_parser.add_argument('-E', '--energy', action='store_true', required=False, help=energy_help)
metric_parser.add_argument('-m', '--mem-usage', action='store_true', required=False, help=mem_usage_help)
# Options to only display to Hypervisors
if self.helpers.is_hypervisor():
@@ -476,8 +488,8 @@ class AMDSMIParser(argparse.ArgumentParser):
# Subparser help text
process_help = "Lists general process information running on the specified GPU"
process_subcommand_help = "If no argument is provided, returns information for all GPUs on the system.\
\nIf no argument is provided all process information will be displayed."
process_subcommand_help = "If no GPU is specified, returns information for all GPUs on the system.\
\nIf no process argument is provided all process information will be displayed."
process_optionals_title = "Process arguments"
# Optional Arguments help text
@@ -515,7 +527,7 @@ class AMDSMIParser(argparse.ArgumentParser):
# Subparser help text
profile_help = "Displays information about all profiles and current profile"
profile_subcommand_help = "If no argument is provided, returns information for all GPUs on the system."
profile_subcommand_help = "If no GPU is specified, returns information for all GPUs on the system."
profile_optionals_title = "Profile Arguments"
# Create profile subparser
@@ -536,7 +548,7 @@ class AMDSMIParser(argparse.ArgumentParser):
# Subparser help text
event_help = "Displays event information for the given GPU"
event_subcommand_help = "If no argument is provided, returns event information for all GPUs on the system."
event_subcommand_help = "If no GPU is specified, returns event information for all GPUs on the system."
event_optionals_title = "Event Arguments"
# Create event subparser
@@ -551,22 +563,21 @@ class AMDSMIParser(argparse.ArgumentParser):
def _add_topology_parser(self, subparsers, func):
return
if not(self.helpers.is_baremetal() and self.helpers.is_linux()):
# This subparser is only applicable to Baremetal Linux
return
# Subparser help text
topology_help = "Displays topology information of the devices."
topology_subcommand_help = "If no argument is provided, returns information for all GPUs on the system."
topology_subcommand_help = "If no GPU is specified, returns information for all GPUs on the system.\
\nIf no topology argument is provided all topology information will be displayed."
topology_optionals_title = "Topology arguments"
# Help text for Arguments only on Guest and BM platforms
access_help = "Displays link accessibility between GPUs"
weight_help = "Displays relative weight between GPUs"
hops_help = "Displays the number of hops between GPUs"
type_help = "Displays the link type between GPUs"
numa_help = "Display the HW Topology Information for numa nodes"
link_type_help = "Displays the link type between GPUs"
numa_bw_help = "Display max and min bandwidth between nodes"
# Create topology subparser
@@ -583,8 +594,7 @@ class AMDSMIParser(argparse.ArgumentParser):
topology_parser.add_argument('-a', '--access', action='store_true', required=False, help=access_help)
topology_parser.add_argument('-w', '--weight', action='store_true', required=False, help=weight_help)
topology_parser.add_argument('-o', '--hops', action='store_true', required=False, help=hops_help)
topology_parser.add_argument('-t', '--type', action='store_true', required=False, help=type_help)
topology_parser.add_argument('-n', '--numa', action='store_true', required=False, help=numa_help)
topology_parser.add_argument('-t', '--link-type', action='store_true', required=False, help=link_type_help)
topology_parser.add_argument('-b', '--numa-bw', action='store_true', required=False, help=numa_bw_help)
@@ -595,7 +605,8 @@ class AMDSMIParser(argparse.ArgumentParser):
# Subparser help text
set_value_help = "Set options for devices."
set_value_subcommand_help = "The user must specify one of the options for the set configuration."
set_value_subcommand_help = "A GPU must be specified to set a configuration.\
\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
@@ -642,7 +653,7 @@ class AMDSMIParser(argparse.ArgumentParser):
set_value_parser.add_argument('-O', '--memoverdrive', action=self._validate_overdrive_percent(), required=False, help=set_mem_overdrive_help, metavar='%')
set_value_parser.add_argument('-w', '--poweroverdrive', action=self._prompt_spec_warning(), type=self._positive_int, required=False, help=set_power_overdrive_help, metavar="WATTS")
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='SCLK')
set_value_parser.add_argument('-d', '--perfdeterminism', action='store', type=self._positive_int, required=False, help=set_perf_det_help, metavar='SCLKMAX')
def _validate_set_clock(self, validate_clock_type=True):
@@ -745,7 +756,8 @@ class AMDSMIParser(argparse.ArgumentParser):
# Subparser help text
reset_help = "Reset options for devices."
reset_subcommand_help = "The user must specify one of the options to reset devices."
reset_subcommand_help = "A GPU must be specified to reset a configuration.\
\nA reset argument must be provided; Multiple reset arguments are accepted"
reset_optionals_title = "Reset Arguments"
# Help text for Arguments only on Guest and BM platforms
@@ -781,7 +793,7 @@ class AMDSMIParser(argparse.ArgumentParser):
return
# Subparser help text
rocm_smi_help = "Legacy rocm_smi commands ported for backward compatibility"
rocm_smi_subcommand_help = "If no argument is provided, return showall and print the information for all\
rocm_smi_subcommand_help = "If no GPU is specified, returns showall and print the information for all\
GPUs on the system."
rocm_smi_optionals_title = "rocm_smi Arguments"
-1
Просмотреть файл
@@ -1 +0,0 @@
__version__ = "0.0.3"
+1 -1
Просмотреть файл
@@ -823,7 +823,7 @@ def amdsmi_get_board_info(
def amdsmi_get_ras_block_features_enabled(
device_handle: amdsmi_wrapper.amdsmi_device_handle,
) -> Dict[str, Any]:
) -> List[Dict[str, str]]:
if not isinstance(device_handle, amdsmi_wrapper.amdsmi_device_handle):
raise AmdSmiParameterException(
device_handle, amdsmi_wrapper.amdsmi_device_handle
+25 -10
Просмотреть файл
@@ -1069,13 +1069,15 @@ amdsmi_get_power_cap_info(amdsmi_device_handle device_handle,
if (info == nullptr)
return AMDSMI_STATUS_INVAL;
bool set_ret_success = false;
amd::smi::AMDSmiGPUDevice* gpudevice = nullptr;
amdsmi_status_t r = get_gpu_device_from_handle(device_handle, &gpudevice);
if (r != AMDSMI_STATUS_SUCCESS)
return r;
amdsmi_status_t status;
status = get_gpu_device_from_handle(device_handle, &gpudevice);
if (status != AMDSMI_STATUS_SUCCESS)
{
return status;
}
// Ignore errors to get as much as possible info.
memset(info, 0, sizeof(amdsmi_power_cap_info_t));
@@ -1084,24 +1086,37 @@ amdsmi_get_power_cap_info(amdsmi_device_handle device_handle,
int power_cap = 0;
int dpm = 0;
status = smi_amdgpu_get_power_cap(gpudevice, &power_cap);
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
set_ret_success = true;
info->power_cap = power_cap;
status = smi_amdgpu_get_ranges(gpudevice, CLK_TYPE_GFX,
NULL, NULL, &dpm);
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
set_ret_success = true;
info->dpm_cap = dpm;
}
else {
auto rsmi_status = rsmi_dev_power_cap_get(gpudevice->get_gpu_id(),
status = rsmi_wrapper(rsmi_dev_power_cap_get, device_handle,
sensor_ind, &(info->power_cap));
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
set_ret_success = true;
}
// Get other information from rocm-smi
auto rsmi_status = rsmi_dev_power_cap_default_get(gpudevice->get_gpu_id(),
&(info->default_power_cap));
rsmi_status = rsmi_dev_power_cap_range_get(gpudevice->get_gpu_id(),
sensor_ind, &(info->max_power_cap), &(info->min_power_cap));
status = rsmi_wrapper(rsmi_dev_power_cap_default_get, device_handle,
&(info->default_power_cap));
return AMDSMI_STATUS_SUCCESS;
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
set_ret_success = true;
status = rsmi_wrapper(rsmi_dev_power_cap_range_get, device_handle, sensor_ind,
&(info->max_power_cap), &(info->min_power_cap));
if ((status == AMDSMI_STATUS_SUCCESS) && !set_ret_success)
set_ret_success = true;
return set_ret_success ? AMDSMI_STATUS_SUCCESS : AMDSMI_STATUS_NOT_SUPPORTED;
}
amdsmi_status_t
-5
Просмотреть файл
@@ -171,7 +171,6 @@ amdsmi_status_t smi_amdgpu_get_power_cap(amd::smi::AMDSmiGPUDevice* device, int
fullpath += "/power1_cap_max";
std::ifstream file(fullpath.c_str(), std::ifstream::in);
if (!file.is_open()) {
printf("Failed to open file: %s \n", fullpath.c_str());
return AMDSMI_STATUS_API_FAILED;
}
@@ -218,7 +217,6 @@ amdsmi_status_t smi_amdgpu_get_ranges(amd::smi::AMDSmiGPUDevice* device, amdsmi_
std::ifstream ranges(fullpath.c_str());
if (ranges.fail()) {
printf("Failed to open file: %s \n", fullpath.c_str());
return AMDSMI_STATUS_API_FAILED;
}
@@ -259,7 +257,6 @@ amdsmi_status_t smi_amdgpu_get_enabled_blocks(amd::smi::AMDSmiGPUDevice* device,
std::string tmp_str;
if (f.fail()) {
printf("Failed to open file: %s \n", fullpath.c_str());
return AMDSMI_STATUS_API_FAILED;
}
@@ -295,7 +292,6 @@ amdsmi_status_t smi_amdgpu_get_bad_page_info(amd::smi::AMDSmiGPUDevice* device,
std::ifstream fs(fullpath.c_str());
if (fs.fail()) {
printf("Failed to open file: %s \n", fullpath.c_str());
return AMDSMI_STATUS_NOT_SUPPORTED;
}
@@ -365,7 +361,6 @@ amdsmi_status_t smi_amdgpu_get_ecc_error_count(amd::smi::AMDSmiGPUDevice* device
std::ifstream f(fullpath.c_str());
if (f.fail()) {
printf("Failed to open file: %s \n", fullpath.c_str());
return AMDSMI_STATUS_NOT_SUPPORTED;
}