Files
rocm-systems/amdsmi_cli/amdsmi_commands.py
T
Maisam Arif aa70b77ec5 AMDSMI_CLI version 0.0.1
Change-Id: I0b02ddf1cc22753635062475cccadcc235e3a603
Signed-off-by: Maisam Arif <Maisam.Arif@amd.com>
2023-03-20 08:51:35 -05:00

1201 lines
53 KiB
Python

#!/usr/bin/python3
#
# Copyright (C) 2023 Advanced Micro Devices. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
"""AMDSMICommands
This class contains all the commands corresponding to AMDSMIParser
Each command function will interact with AMDSMILogger to handle
displaying the output to the specified compatibility, format, and
destination.
"""
from _version import __version__
from amdsmi_helpers import *
from amdsmi_logger import AMDSMILogger
class AMDSMICommands():
def __init__(self, compatibility='amdsmi',
format='human_readable',
destination='stdout') -> None:
self.helpers = AMDSMIHelpers()
self.logger = AMDSMILogger(compatibility=compatibility,
format=format,
destination=destination)
self.device_handles = amdsmi_interface.amdsmi_get_device_handles()
def version(self, args):
"""Print Version String
Args:
args (Namespace): Namespace containing the parsed CLI args
"""
kernel_component = amdsmi_interface.AmdSmiSwComponent.DRIVER
kernel_version = amdsmi_interface.amdsmi_get_version_str(sw_component=kernel_component)
amdsmi_lib_version = amdsmi_interface.amdsmi_get_version()
major = amdsmi_lib_version["major"]
minor = amdsmi_lib_version["minor"]
patch = amdsmi_lib_version["patch"]
amdsmi_lib_version_str = f'{major}.{minor}.{patch}'
self.logger.output['tool'] = 'AMDSMI Tool'
self.logger.output['version'] = f'{__version__}'
self.logger.output['amdsmi_library_version'] = f'{amdsmi_lib_version_str}'
self.logger.output['kernel_version'] = f'{kernel_version}'
if self.logger.is_human_readable_format():
print(f'AMDSMI Tool: {__version__} | '\
f'AMDSMI Library version: {amdsmi_lib_version_str} | '\
f'Kernel version: {kernel_version}')
elif self.logger.is_json_format() or self.logger.is_csv_format():
self.logger.print_output()
def discovery(self, args, multiple_devices=False, gpu=None):
"""Get Discovery information for target gpu
Args:
args (Namespace): Namespace containing the parsed CLI args
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.
Raises:
IndexError: Index error if gpu list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# Set args.* to passed in arguments
if gpu:
args.gpu = gpu
# Handle No GPU passed
if args.gpu is None:
args.gpu = self.device_handles
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
self.discovery(args, multiple_devices=True, gpu=device_handle)
self.logger.print_output(multiple_device_output=True)
return
if len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
bdf = amdsmi_interface.amdsmi_get_device_bdf(args.gpu)
uuid = amdsmi_interface.amdsmi_get_device_uuid(args.gpu)
# Store values based on format
if self.logger.is_human_readable_format():
self.logger.store_output(args.gpu, 'AMDSMI_SPACING_REMOVAL', {'bdf':bdf, 'uuid':uuid})
else:
self.logger.store_output(args.gpu, 'bdf', bdf)
self.logger.store_output(args.gpu, 'uuid', uuid)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
# compatibility with gpuvsmi needs a list for single gpu
if self.logger.is_gpuvsmi_compatibility() and not multiple_devices:
self.logger.store_multiple_device_output()
self.logger.print_output(multiple_device_output=True)
else:
self.logger.print_output()
def static(self, args, multiple_devices=False, gpu=None, asic=None,
bus=None, vbios=None, limit=None, driver=None, caps=None,
ras=None, board=None):
"""Get Static information for target gpu
Args:
args (Namespace): Namespace containing the parsed CLI args
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.
asic (bool, optional): Value override for args.asic. Defaults to None.
bus (bool, optional): Value override for args.bus. Defaults to None.
vbios (bool, optional): Value override for args.vbios. Defaults to None.
limit (bool, optional): Value override for args.limit. Defaults to None.
driver (bool, optional): Value override for args.driver. Defaults to None.
caps (bool, optional): Value override for args.caps. Defaults to None.
ras (bool, optional): Value override for args.ras. Defaults to None.
board (bool, optional): Value override for args.board. Defaults to None.
Raises:
IndexError: Index error if gpu list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# Set args.* to passed in arguments
if gpu:
args.gpu = gpu
if asic:
args.asic = asic
if bus:
args.bus = bus
if vbios:
args.vbios = vbios
if limit:
args.limit = limit
if driver:
args.driver = driver
if caps:
args.caps = caps
if ras:
args.ras = ras
if board:
args.board = board
# Handle No GPU passed
if args.gpu is None:
args.gpu = self.device_handles
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
self.static(args, multiple_devices=True, gpu=device_handle)
self.logger.print_output(multiple_device_output=True)
return
if len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
# If all arguments are False, it means that no argument was passed and the entire static should be printed
if not any([args.asic, args.bus, args.vbios, args.limit, args.driver, args.caps, args.ras, args.board]):
args.asic = args.bus = args.vbios = args.limit = args.driver = args.caps = args.ras = args.board = True
values_dict = {}
if args.asic:
asic_info = amdsmi_interface.amdsmi_get_asic_info(args.gpu)
asic_info['family'] = hex(asic_info['family'])
asic_info['vendor_id'] = hex(asic_info['vendor_id'])
asic_info['device_id'] = hex(asic_info['device_id'])
asic_info['rev_id'] = hex(asic_info['rev_id'])
if asic_info['asic_serial'] != '':
asic_info['asic_serial'] = '0x' + asic_info['asic_serial']
values_dict['asic'] = asic_info
if args.bus:
bus_info = amdsmi_interface.amdsmi_get_pcie_link_caps(args.gpu)
if self.logger.is_human_readable_format():
unit ='MT/s'
bus_info['pcie_speed'] = f"{bus_info['pcie_speed']} {unit}"
bus_output_info = {}
bus_output_info['bdf'] = amdsmi_interface.amdsmi_get_device_bdf(args.gpu)
bus_output_info.update(bus_info)
values_dict['bus'] = bus_output_info
if args.vbios:
vbios_info = amdsmi_interface.amdsmi_get_vbios_info(args.gpu)
if self.logger.is_gpuvsmi_compatibility():
vbios_info['version'] = vbios_info.pop('vbios_version_string')
vbios_info['build_date'] = vbios_info.pop('build_date')
vbios_info['part_number'] = vbios_info.pop('part_number')
vbios_info['vbios_version'] = vbios_info.pop('vbios_version')
values_dict['vbios'] = vbios_info
if args.board:
board_info = amdsmi_interface.amdsmi_get_board_info(args.gpu)
board_info['serial_number'] = hex(board_info['serial_number'])
board_info['product_serial'] = '0x' + board_info['product_serial']
if self.logger.is_gpuvsmi_compatibility():
board_info['product_number'] = board_info.pop('product_serial')
board_info['product_name'] = board_info.pop('product_name')
values_dict['board'] = board_info
if args.limit:
power_limit = amdsmi_interface.amdsmi_get_power_measure(args.gpu)['power_limit']
temp_edge_limit = amdsmi_interface.amdsmi_dev_get_temp_metric(args.gpu,
amdsmi_interface.AmdSmiTemperatureType.EDGE, amdsmi_interface.AmdSmiTemperatureMetric.CRITICAL)
temp_junction_limit = amdsmi_interface.amdsmi_dev_get_temp_metric(args.gpu,
amdsmi_interface.AmdSmiTemperatureType.JUNCTION, amdsmi_interface.AmdSmiTemperatureMetric.CRITICAL)
temp_vram_limit = amdsmi_interface.amdsmi_dev_get_temp_metric(args.gpu,
amdsmi_interface.AmdSmiTemperatureType.VRAM, amdsmi_interface.AmdSmiTemperatureMetric.CRITICAL)
if self.logger.is_human_readable_format():
unit = 'W'
power_limit = f"{power_limit} {unit}"
unit = 'C'
temp_edge_limit = f"{temp_edge_limit} {unit}"
temp_junction_limit = f"{temp_junction_limit} {unit}"
temp_vram_limit = f"{temp_vram_limit} {unit}"
limit_info = {}
limit_info['power'] = power_limit
limit_info['temperature_edge'] = temp_edge_limit
limit_info['temperature_junction'] = temp_junction_limit
limit_info['temperature_vram'] = temp_vram_limit
values_dict['limit'] = limit_info
if args.driver:
driver_info = {}
driver_info['driver_version'] = amdsmi_interface.amdsmi_get_driver_version(args.gpu)
values_dict['driver'] = driver_info
if args.ras:
try:
ras_info = amdsmi_interface.amdsmi_get_ras_block_features_enabled(args.gpu)
values_dict['ras'] = ras_info
except amdsmi_interface.AmdSmiLibraryException as err:
values_dict['ras'] = err.get_error_info()
if args.caps:
caps_info = amdsmi_interface.amdsmi_get_caps_info(args.gpu)
if self.logger.is_gpuvsmi_compatibility():
del caps_info['ras_supported']
caps_info['gfx'] = caps_info.pop('gfx')
if self.logger.is_human_readable_format():
for capability_name, capability_value in caps_info.items():
if isinstance(capability_value, list):
caps_info[capability_name] = f"{capability_value}"
values_dict['caps'] = caps_info
# Store values in logger.output
self.logger.store_output(args.gpu, 'values', values_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output()
def firmware(self, args, multiple_devices=False, gpu=None, fw_list=True):
""" Get Firmware information for target gpu
Args:
args (Namespace): Namespace containing the parsed CLI args
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.
fw_list (bool, optional): True to get list of all firmware information
Raises:
IndexError: Index error if gpu list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
if gpu:
args.gpu = gpu
if fw_list: # Currently a compatiblity option of gpuv-smi
args.fw_list = fw_list
# Handle No GPU passed
if args.gpu is None:
args.gpu = self.device_handles
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
self.firmware(args, multiple_devices=True, gpu=device_handle)
self.logger.print_output(multiple_device_output=True)
return
if len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
values_dict = {}
if args.fw_list:
fw_info = amdsmi_interface.amdsmi_get_fw_info(args.gpu)
for fw_index, fw_entry in enumerate(fw_info['fw_list']):
# Change fw_name to fw_id
fw_entry['fw_id'] = fw_entry.pop('fw_name').name.strip('FW_ID_')
fw_entry['fw_version'] = fw_entry.pop('fw_version')
firmware_identifier = 'FW'
if self.logger.is_gpuvsmi_compatibility():
firmware_identifier = 'UCODE'
fw_entry['name'] = fw_entry.pop('fw_id')
fw_entry['version'] = fw_entry.pop('fw_version')
# Add custom human readable formatting
if self.logger.is_human_readable_format():
fw_info['fw_list'][fw_index] = {f'{firmware_identifier} {fw_index}': fw_entry}
else:
fw_info['fw_list'][fw_index] = fw_entry
if self.logger.is_gpuvsmi_compatibility():
fw_info['ucode_list'] = fw_info.pop('fw_list')
values_dict.update(fw_info)
# Store values in logger.output
self.logger.store_output(args.gpu, 'values', values_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output()
def bad_pages(self, args, multiple_devices=False, gpu=None, retired=None, pending=None, un_res=None):
""" Get bad pages information for target gpu
Args:
args (Namespace): Namespace containing the parsed CLI args
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.
retired (bool, optional) - Value override for args.retired
pending (bool, optional) - Value override for args.pending
un_res (bool, optional) - Value override for args.un_res
Raises:
IndexError: Index error if gpu list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# Set args.* to passed in arguments
if gpu:
args.gpu = gpu
if retired:
args.retired = retired
if pending:
args.pending = pending
if un_res:
args.un_res = un_res
# Handle No GPU passed
if args.gpu is None:
args.gpu = self.device_handles
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
self.bad_pages(args, multiple_devices=True, gpu=device_handle)
self.logger.print_output(multiple_device_output=True)
return
if len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
# If all arguments are False, the print all bad_page information
if not any([args.retired, args.pending, args.un_res]):
args.retired = args.pending = args.un_res = True
values_dict = {}
bad_page_err_output = ''
try:
bad_page_info = amdsmi_interface.amdsmi_get_bad_page_info(args.gpu)
bad_page_error = False
except amdsmi_interface.AmdSmiLibraryException as err:
bad_page_err_output = err.get_error_info()
bad_page_error = True
if isinstance(bad_page_info, str):
pass
else:
if args.retired:
if bad_page_error:
bad_page_info_output = bad_page_err_output
else:
bad_page_info_output = []
for bad_page in bad_page_info:
if bad_page["status"] == amdsmi_interface.AmdSmiMemoryPageStatus.RESERVED:
bad_page_info_entry = {}
bad_page_info_entry["page_address"] = bad_page["page_address"]
bad_page_info_entry["page_size"] = bad_page["page_size"]
bad_page_info_entry["status"] = bad_page["status"].name
bad_page_info_output.append(bad_page_info_entry)
# Remove brackets if there is only one value
if len(bad_page_info_output) == 1:
bad_page_info_output = bad_page_info_output[0]
values_dict['retired'] = bad_page_info_output
if args.pending:
if bad_page_error:
bad_page_info_output = bad_page_err_output
else:
bad_page_info_output = []
for bad_page in bad_page_info:
if bad_page["status"] == amdsmi_interface.AmdSmiMemoryPageStatus.PENDING:
bad_page_info_entry = {}
bad_page_info_entry["page_address"] = bad_page["page_address"]
bad_page_info_entry["page_size"] = bad_page["page_size"]
bad_page_info_entry["status"] = bad_page["status"].name
bad_page_info_output.append(bad_page_info_entry)
# Remove brackets if there is only one value
if len(bad_page_info_output) == 1:
bad_page_info_output = bad_page_info_output[0]
values_dict['pending'] = bad_page_info_output
if args.un_res:
if bad_page_error:
bad_page_info_output = bad_page_err_output
else:
bad_page_info_output = []
for bad_page in bad_page_info:
if bad_page["status"] == amdsmi_interface.AmdSmiMemoryPageStatus.UNRESERVABLE:
bad_page_info_entry = {}
bad_page_info_entry["page_address"] = bad_page["page_address"]
bad_page_info_entry["page_size"] = bad_page["page_size"]
bad_page_info_entry["status"] = bad_page["status"].name
bad_page_info_output.append(bad_page_info_entry)
# Remove brackets if there is only one value
if len(bad_page_info_output) == 1:
bad_page_info_output = bad_page_info_output[0]
values_dict['un_res'] = bad_page_info_output
# Store values in logger.output
self.logger.store_output(args.gpu, 'values', values_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output()
def metric(self, args, multiple_devices=False, watching_output=False, gpu=None,
usage=None, watch=None, watch_time=None, iterations=None, fb_usage=None, power=None,
clock=None, temperature=None, ecc=None, pcie=None, voltage=None, fan=None,
pcie_usage=None, voltage_curve=None, overdrive=None, mem_overdrive=None,
perf_level=None, replay_count=None, xgmi_err=None, energy=None, mem_usage=None):
"""Get Metric information for target gpu
Args:
args (Namespace): Namespace containing the parsed CLI args
multiple_devices (bool, optional): True if checking for multiple devices. Defaults to False.
watching_output (bool, optional): True if watch option has been set. Defaults to False.
gpu (device_handle, optional): device_handle for target device. Defaults to None.
usage (bool, optional): Value override for args.usage. Defaults to None.
watch (Positive int, optional): Value override for args.watch. Defaults to None.
watch_time (Positive int, optional): Value override for args.watch_time. Defaults to None.
iterations (Positive int, optional): Value override for args.iterations. Defaults to None.
fb_usage (bool, optional): Value override for args.fb_usage. Defaults to None.
power (bool, optional): Value override for args.power. Defaults to None.
clock (bool, optional): Value override for args.clock. Defaults to None.
temperature (bool, optional): Value override for args.temperature. Defaults to None.
ecc (bool, optional): Value override for args.ecc. Defaults to None.
pcie (bool, optional): Value override for args.pcie. Defaults to None.
voltage (bool, optional): Value override for args.voltage. Defaults to None.
fan (bool, optional): Value override for args.fan. Defaults to None.
pcie_usage (bool, optional): Value override for args.pcie_usage. Defaults to None.
voltage_curve (bool, optional): Value override for args.voltage_curve. Defaults to None.
overdrive (bool, optional): Value override for args.overdrive. Defaults to None.
mem_overdrive (bool, optional): Value override for args.mem_overdrive. Defaults to None.
perf_level (bool, optional): Value override for args.perf_level. Defaults to None.
replay_count (bool, optional): Value override for args.replay_count. Defaults to None.
xgmi_err (bool, optional): Value override for args.xgmi_err. Defaults to None.
energy (bool, optional): Value override for args.energy. Defaults to None.
mem_usage (bool, optional): Value override for args.mem_usage. Defaults to None.
Raises:
IndexError: Index error if gpu list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# Set args.* to passed in arguments
if gpu:
args.gpu = gpu
if usage:
args.usage = usage
if watch:
args.watch = watch
if watch_time:
args.watch_time = watch_time
if iterations:
args.iterations = iterations
if fb_usage:
args.fb_usage = fb_usage
if power:
args.power = power
if clock:
args.clock = clock
if temperature:
args.temperature = temperature
if ecc:
args.ecc = ecc
if pcie:
args.pcie = pcie
if voltage:
args.voltage = voltage
if fan:
args.fan = fan
if pcie_usage:
args.pcie_usage = pcie_usage
if voltage_curve:
args.voltage_curve = voltage_curve
if overdrive:
args.overdrive = overdrive
if mem_overdrive:
args.mem_overdrive = mem_overdrive
if perf_level:
args.perf_level = perf_level
if replay_count:
args.replay_count = replay_count
if xgmi_err:
args.xgmi_err = xgmi_err
if energy:
args.energy = energy
if mem_usage:
args.mem_usage = mem_usage
# Handle No GPU passed
if args.gpu is None:
args.gpu = self.device_handles
# Handle watch logic, will only enter this block once
if args.watch:
args = self.helpers.handle_watch(args=args, subcommand=self.metric)
self.logger.print_output(watch_output=True) # Print at the end of watch ( final flush )
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
self.metric(args, multiple_devices=True, watching_output=False, gpu=device_handle)
self.logger.print_output(multiple_device_output=True)
# End of multiple gpus add to watch_output
if watching_output:
self.logger.store_watch_output(multiple_devices=True)
return
if len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
# Check if any of the options have been set, if not then set them all to true
if not any([args.usage, args.fb_usage, args.power, args.clock, args.temperature, args.ecc, args.pcie, args.voltage, args.fan,
args.pcie_usage, args.voltage_curve, args.overdrive, args.mem_overdrive, args.perf_level,
args.replay_count, args.xgmi_err, args.energy, mem_usage]):
args.usage = args.fb_usage = args.power = args.clock = args.temperature = args.ecc = args.pcie = args.voltage = args.fan = \
args.pcie_usage = args.voltage_curve = args.overdrive = args.mem_overdrive = args.perf_level = \
args.replay_count = args.xgmi_err = args.energy = mem_usage = True
# Add timestamp and store values for specified arguments
values_dict = {}
if args.usage:
engine_usage = amdsmi_interface.amdsmi_get_gpu_activity(args.gpu)
if self.logger.is_gpuvsmi_compatibility():
engine_usage['gfx_usage'] = engine_usage.pop('gfx_activity')
engine_usage['mem_usage'] = engine_usage.pop('umc_activity')
engine_usage['mm_usage_list'] = engine_usage.pop('mm_activity')
if self.logger.is_human_readable_format():
unit = '%'
for usage_name, usage_value in engine_usage.items():
engine_usage[usage_name] = f"{usage_value} {unit}"
values_dict['usage'] = engine_usage
if args.fb_usage:
vram_usage = amdsmi_interface.amdsmi_get_vram_usage(args.gpu)
if self.logger.is_gpuvsmi_compatibility():
vram_usage['fb_total'] = vram_usage.pop('vram_total')
vram_usage['fb_used'] = vram_usage.pop('vram_used')
if self.logger.is_human_readable_format():
unit = 'MB'
for vram_name, vram_value in vram_usage.items():
vram_usage[vram_name] = f"{vram_value} {unit}"
values_dict['fb_usage'] = vram_usage
if args.power:
average_socket_power = amdsmi_interface.amdsmi_get_power_measure(args.gpu)['average_socket_power']
if self.logger.is_gpuvsmi_compatibility():
pass
if self.logger.is_human_readable_format():
unit = 'W'
average_socket_power = f"{average_socket_power} {unit}"
values_dict['power'] = average_socket_power
if args.clock:
clock_gfx = amdsmi_interface.amdsmi_get_clock_measure(args.gpu, amdsmi_interface.AmdSmiClkType.GFX)
clock_mem = amdsmi_interface.amdsmi_get_clock_measure(args.gpu, amdsmi_interface.AmdSmiClkType.MEM)
clocks = {'gfx': clock_gfx,
'mem': clock_mem}
if self.logger.is_human_readable_format():
unit = 'MHz'
for clock_target, clock_metric_values in clocks.items():
for clock_type, clock_value in clock_metric_values.items():
clocks[clock_target][clock_type] = f"{clock_value} {unit}"
values_dict['clock'] = clocks
if args.temperature:
temperature_edge_current = amdsmi_interface.amdsmi_dev_get_temp_metric(
args.gpu, amdsmi_interface.AmdSmiTemperatureType.EDGE, amdsmi_interface.AmdSmiTemperatureMetric.CURRENT)
temperature_junction_current = amdsmi_interface.amdsmi_dev_get_temp_metric(
args.gpu, amdsmi_interface.AmdSmiTemperatureType.JUNCTION, amdsmi_interface.AmdSmiTemperatureMetric.CURRENT)
temperature_vram_current = amdsmi_interface.amdsmi_dev_get_temp_metric(
args.gpu, amdsmi_interface.AmdSmiTemperatureType.VRAM, amdsmi_interface.AmdSmiTemperatureMetric.CURRENT)
temperatures = { 'edge': temperature_edge_current,
'hotspot': temperature_junction_current,
'mem': temperature_vram_current}
if self.logger.is_gpuvsmi_compatibility():
temperatures = { 'edge_temperature': temperature_edge_current,
'hotspot_temperature': temperature_junction_current,
'mem_temperature': temperature_vram_current}
if self.logger.is_human_readable_format():
unit = '\N{DEGREE SIGN}C'
for temperature_value in temperatures:
temperatures[temperature_value] = f"{temperatures[temperature_value]} {unit}"
values_dict['temperature'] = temperatures
if args.ecc:
try:
values_dict['ecc'] = amdsmi_interface.amdsmi_get_ecc_error_count(args.gpu)
except amdsmi_interface.AmdSmiLibraryException as err:
values_dict['ecc'] = err.get_error_info()
if args.pcie:
pcie_link_status = amdsmi_interface.amdsmi_get_pcie_link_caps(args.gpu)
if self.logger.is_human_readable_format():
unit ='MT/s'
pcie_link_status['pcie_speed'] = f"{pcie_link_status['pcie_speed']} {unit}"
if self.logger.is_gpuvsmi_compatibility():
pcie_link_status['current_width'] = pcie_link_status.pop('pcie_lanes')
pcie_link_status['current_speed'] = pcie_link_status.pop('pcie_speed')
values_dict['pcie'] = pcie_link_status
if args.voltage:
volt_metric = amdsmi_interface.amdsmi_dev_get_volt_metric(
args.gpu, amdsmi_interface.AmdSmiVoltageType.VDDGFX, amdsmi_interface.AmdSmiVoltageMetric.CURRENT)
if self.logger.is_human_readable_format():
unit = 'mV'
volt_metric = f"{volt_metric} {unit}"
values_dict['voltage'] = volt_metric
if args.fan:
fan_speed = amdsmi_interface.amdsmi_dev_get_fan_speed(args.gpu, 0)
fan_max = amdsmi_interface.amdsmi_dev_get_fan_speed_max(args.gpu, 0)
fan_rpm = amdsmi_interface.amdsmi_dev_get_fan_rpms(args.gpu, 0)
if fan_max <= 0:
fan_percent = 'Unable to detect fan speed'
else:
fan_percent = round((float(fan_speed) / float(fan_max)) * 100, 2)
if self.logger.is_human_readable_format():
unit = '%'
fan_percent = f"{fan_percent} {unit}"
values_dict['fan'] = {'speed': fan_speed,
'max' : fan_max,
'rpm' : fan_rpm,
'usage' : fan_percent}
if args.pcie_usage:
pcie_link_status = amdsmi_interface.amdsmi_get_pcie_link_status(args.gpu)
if self.logger.is_human_readable_format():
unit ='MT/s'
pcie_link_status['pcie_speed'] = f"{pcie_link_status['pcie_speed']} {unit}"
values_dict['pcie_usage'] = pcie_link_status
if args.voltage_curve:
try:
od_volt = amdsmi_interface.amdsmi_dev_get_od_volt_info(args.gpu)
voltage_curve_error = False
except amdsmi_interface.AmdSmiLibraryException as err:
values_dict["voltage_curve"] = err.get_error_info()
voltage_curve_error = True
if not voltage_curve_error:
voltage_point_dict = {}
for point in range(3):
frequency = int(od_volt["curve.vc_points"][point].frequency / 1000000)
voltage = int(od_volt["curve.vc_points"][point].voltage)
voltage_point_dict[f'voltage_point_{point}'] = f"{frequency}Mhz {voltage}mV"
values_dict['voltage_curve'] = voltage_point_dict
if args.overdrive:
overdrive_level = amdsmi_interface.amdsmi_dev_get_overdrive_level(args.gpu)
if self.logger.is_human_readable_format():
unit = '%'
overdrive_level = f"{overdrive_level} {unit}"
values_dict['overdrive'] = overdrive_level
if args.mem_overdrive:
values_dict['mem_overdrive'] = amdsmi_interface.AmdSmiRetCode.NOT_IMPLEMENTED
if args.perf_level:
perf_level = amdsmi_interface.amdsmi_dev_get_perf_level(args.gpu)
values_dict['perf_level'] = perf_level
if args.replay_count:
pci_replay_counter = amdsmi_interface.amdsmi_dev_get_pci_replay_counter(args.gpu)
values_dict['replay_count'] = pci_replay_counter
if args.xgmi_err:
try:
values_dict['xgmi_err'] = amdsmi_interface.amdsmi_dev_xgmi_error_status(args.gpu)
except amdsmi_interface.AmdSmiLibraryException as err:
values_dict['xgmi_err'] = err.get_error_info()
if args.energy:
energy = amdsmi_interface.amdsmi_get_power_measure(args.gpu)['energy_accumulator']
if self.logger.is_human_readable_format():
unit = 'J'
energy = f"{energy} {unit}"
values_dict['energy'] = energy
if args.mem_usage:
memory_total_vram = amdsmi_interface.amdsmi_dev_get_memory_total(args.gpu, amdsmi_interface.AmdSmiMemoryType.VRAM)
memory_total_vis_vram = amdsmi_interface.amdsmi_dev_get_memory_total(args.gpu, amdsmi_interface.AmdSmiMemoryType.VIS_VRAM)
memory_total_gtt = amdsmi_interface.amdsmi_dev_get_memory_total(args.gpu, amdsmi_interface.AmdSmiMemoryType.GTT)
memory_total = {}
# Convert mem_usage to megabytes
memory_total['vram'] = memory_total_vram // (1024*1024)
memory_total['vis_vram'] = memory_total_vis_vram // (1024*1024)
memory_total['gtt'] = memory_total_gtt // (1024*1024)
if self.logger.is_human_readable_format():
unit = 'MB'
energy = f"{energy} {unit}"
memory_total['vram'] = f"{memory_total['vram']} {unit}"
memory_total['vis_vram'] = f"{memory_total['vis_vram']} {unit}"
memory_total['gtt'] = f"{memory_total['gtt']} {unit}"
values_dict['mem_usage'] = memory_total
# Store values in logger.output
self.logger.store_output(args.gpu, 'values', values_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output()
if watching_output: # End of single gpu add to watch_output
self.logger.store_watch_output(multiple_devices=False)
def process(self, args, multiple_devices=False, watching_output=False,
gpu=None, general=None, engine=None, pid=None, name=None,
watch=None, watch_time=None, iterations=None):
"""Get Process Information from the target GPU
Args:
args (Namespace): Namespace containing the parsed CLI args
multiple_devices (bool, optional): True if checking for multiple devices. Defaults to False.
watching_output (bool, optional): True if watch option has been set. Defaults to False.
gpu (device_handle, optional): device_handle for target device. Defaults to None.
general (bool, optional): Value override for args.general. Defaults to None.
engine (bool, optional): Value override for args.engine. Defaults to None.
pid (Positive int, optional): Value override for args.pid. Defaults to None.
name (str, optional): Value override for args.name. Defaults to None.
watch (Positive int, optional): Value override for args.watch. Defaults to None.
watch_time (Positive int, optional): Value override for args.watch_time. Defaults to None.
iterations (Positive int, optional): Value override for args.iterations. Defaults to None.
Raises:
IndexError: Index error if gpu list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# Set args.* to passed in arguments
if gpu:
args.gpu = gpu
if general:
args.general = general
if engine:
args.engine = engine
if pid:
args.pid = pid
if name:
args.name = name
if watch:
args.watch = watch
if watch_time:
args.watch_time = watch_time
if iterations:
args.iterations = iterations
# Handle No GPU passed
if args.gpu is None:
args.gpu = self.device_handles
# Handle watch logic, will only enter this block once
if args.watch:
args = self.helpers.handle_watch(args=args, subcommand=self.process)
self.logger.print_output(watch_output=True) # Print at the end of watch ( final flush )
return
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
self.process(args, multiple_devices=True, watching_output=False, gpu=device_handle)
self.logger.print_output(multiple_device_output=True)
# End of multiple gpus add to watch_output
if watching_output:
self.logger.store_watch_output(multiple_devices=True)
return
if len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
# Populate initial processes
process_list = amdsmi_interface.amdsmi_get_process_list(args.gpu)
filtered_process_values = []
for process_handle in process_list:
process_info = amdsmi_interface.amdsmi_get_process_info(args.gpu, process_handle)
process_info['mem_usage'] = process_info.pop('mem')
process_info['usage'] = process_info.pop('engine_usage')
# Convert mem_usage to megabytes
mem_usage_mb = (process_info['mem_usage']//1024) // 1024
if mem_usage_mb < 0:
process_info['mem_usage'] = (process_info['mem_usage']//1024)
mem_usage_unit = 'B'
else:
process_info['mem_usage'] = mem_usage_mb
if self.logger.is_human_readable_format():
mem_usage_unit = 'MB'
engine_usage_unit = '%'
process_info['mem_usage'] = f"{process_info['mem_usage']} {mem_usage_unit}"
for usage_metric in process_info['usage']:
process_info['usage'][usage_metric] = f"{process_info['usage'][usage_metric]} {engine_usage_unit}"
for usage_metric in process_info['memory_usage']:
process_info['memory_usage'][usage_metric] = f"{process_info['memory_usage'][usage_metric]} {engine_usage_unit}"
filtered_process_values.append({'process_info': process_info})
# Arguments will filter the populated processes
# General and Engine to expose process_info values
if args.general or args.engine:
for process_info in filtered_process_values:
if args.general and args.engine:
del process_info['process_info']['memory_usage']
elif args.general:
del process_info['process_info']['memory_usage']
del process_info['process_info']['usage'] # Used in engine
elif args.engine:
del process_info['process_info']['memory_usage']
del process_info['process_info']['mem_usage'] # Used in general
# Filter out non specified pids
if args.pid:
process_pids = []
for process_info in filtered_process_values:
pid = str(process_info['process_info']['pid'])
if str(args.pid) == pid:
process_pids.append(process_info)
filtered_process_values = process_pids
# Filter out non specified process names
if args.name:
process_names = []
for process_info in filtered_process_values:
process_name = str(process_info['process_info']['name']).lower()
if str(args.name).lower() == process_name:
process_names.append(process_info)
filtered_process_values = process_names
# Remove brackets if there is only one value
if len(filtered_process_values) == 1:
filtered_process_values = filtered_process_values[0]
# Store values in logger.output
if filtered_process_values == []:
self.logger.store_output(args.gpu, 'values', {'process_info': 'Not Found'})
else:
self.logger.store_output(args.gpu, 'values', filtered_process_values)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output()
if watching_output: # End of single gpu add to watch_output
self.logger.store_watch_output(multiple_devices=False)
def profile(self, args):
"""Not applicable to linux baremetal"""
print('Profile test')
def event(self, args):
print('event test')
def topology(self, args, multiple_devices=False, gpu=None, topo_access=None,
topo_weight=None, topo_hops=None, topo_type=None, topo_numa=None):
""" Get topology information for target gpus
The compatibility mode for this will only be in amdsmi & rocm-smi
params:
args - argparser args to pass to subcommand
multiple_devices (bool) - True if checking for multiple devices
gpu (device_handle) - device_handle for target device
topo_access (bool) - Value override for args.topo_access
topo_weight (bool) - Value override for args.topo_weight
topo_hops (bool) - Value override for args.topo_hops
topo_type (bool) - Value override for args.topo_type
topo_numa (bool) - Value override for args.topo_numa
return:
Nothing
"""
# Set args.* to passed in arguments
if gpu:
args.gpu = gpu
if topo_access: args.topo_access = topo_access
if topo_weight: args.topo_weight = topo_weight
if topo_hops: args.topo_hops = topo_hops
if topo_type: args.topo_type = topo_type
if topo_numa: args.topo_numa = topo_numa
# Handle No GPU passed
if args.gpu is None:
args.gpu = self.device_handles
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
pass
if len(args.gpu) == 1:
# args.gpu = args.gpu[0]
pass
else:
raise IndexError("args.gpu should not be an empty list")
# Handle all args being false
# If all arguments are False, it means that no argument was passed and the entire topology should be printed
# if not any([args.asic, args.bus, args.vbios, args.limit, args.driver, args.caps, args.ras, args.board]):
# args.asic = args.bus = args.vbios = args.limit = args.driver = args.caps = args.ras = args.board = True
topo_json = {}
topo_table = []
if args.topo_access:
pass
if args.topo_weight:
pass
if args.topo_hops:
pass
if args.topo_type:
pass
if args.topo_numa:
pass
def set_value(self, args, multiple_devices=False, gpu=None, clk=None, sclk=None, mclk=None,
pcie=None, slevel=None, mlevel=None, vc=None, srange=None, mrange=None,
fan=None, perflevel=None, overdrive=None, memoverdrive=None,
poweroverdrive=None, profile=None, perfdet=None, rasenable=None,
rasdisable=None):
pass
def reset(self, args, multiple_devices=False, gpu=None, gpureset=None,
resetclocks=None, resetfans=None, resetprofile=None,
resetpoweroverdrive=None, resetxgmierr=None, resetperfdet=None):
"""Issue reset commands to target gpu(s)
Args:
args (Namespace): Namespace containing the parsed CLI args
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.
gpureset (bool, optional): Value over ride for args.gpureset. Defaults to None.
resetclocks (bool, optional): Value over ride for args.resetclocks. Defaults to None.
resetfans (bool, optional): Value over ride for args.resetfans. Defaults to None.
resetprofile (bool, optional): Value over ride for args.resetprofile. Defaults to None.
resetpoweroverdrive (bool, optional): Value over ride for args.resetpoweroverdrive. Defaults to None.
resetxgmierr (bool, optional): Value over ride for args.resetxgmierr. Defaults to None.
resetperfdet (bool, optional): Value over ride for args.resetperfdet. Defaults to None.
Raises:
ValueError: Value error if no gpu value is provided
IndexError: Index error if gpu list is empty
Return:
Nothing
"""
# Set args.* to passed in arguments
if gpu: args.gpu = gpu
if gpureset: args.gpureset = gpureset
if resetclocks: args.resetclocks = resetclocks
if resetfans: args.resetfans = resetfans
if resetprofile: args.resetprofile = resetprofile
if resetpoweroverdrive: args.resetpoweroverdrive = resetpoweroverdrive
if resetxgmierr: args.resetxgmierr = resetxgmierr
if resetperfdet: args.resetperfdet = resetperfdet
# Handle No GPU passed
if args.gpu is None:
raise ValueError('No GPU provided, specific GPU target(s) are needed')
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
for device_handle in args.gpu:
# Handle multiple_devices to print all output at once
self.bad_pages(args, multiple_devices=True, gpu=device_handle)
self.logger.print_output(multiple_device_output=True)
return
if len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
if args.gpureset:
if self.helpers.is_amd_device(args.gpu):
try:
amdsmi_interface.amdsmi_dev_reset_gpu(args.gpu)
result = 'Successfully reset GPU'
except amdsmi_interface.AmdSmiLibraryException as err:
result = err.get_error_info()
else:
result = 'Unable to reset non-amd GPU'
self.logger.store_output(args.gpu, 'gpu_reset', result)
if args.resetclocks:
# rsmi_string = ' Reset Clocks '
reset_clocks_results = {'overdrive' : '',
'clocks' : '',
'performance': ''}
try:
amdsmi_interface.amdsmi_dev_set_overdrive_level_v1(args.gpu, 0)
reset_clocks_results['overdrive'] = 'Overdrive set to 0'
except amdsmi_interface.AmdSmiLibraryException as err:
reset_clocks_results['overdrive'] = err.get_error_info()
try:
level_auto = amdsmi_interface.AmdSmiDevPerfLevel.AUTO
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
reset_clocks_results['clocks'] = 'Successfully reset clocks'
except amdsmi_interface.AmdSmiLibraryException as err:
reset_clocks_results['clocks'] = err.get_error_info()
try:
level_auto = amdsmi_interface.AmdSmiDevPerfLevel.AUTO
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
reset_clocks_results['performance'] = 'Performance level reset to auto'
except amdsmi_interface.AmdSmiLibraryException as err:
reset_clocks_results['performance'] = err.get_error_info()
self.logger.store_output(args.gpu, 'reset_clocks', reset_clocks_results)
if args.resetfans:
try:
amdsmi_interface.amdsmi_dev_reset_fan(args.gpu, 0)
result = 'Successfully reset fan speed to driver control'
except amdsmi_interface.AmdSmiLibraryException as err:
result = err.get_error_info()
self.logger.store_output(args.gpu, 'reset_fans', result)
if args.resetprofile:
reset_profile_results = {'power_profile' : '',
'performance_level': ''}
try:
power_profile_mask = amdsmi_interface.AmdSmiPowerProfilePresetMasks.BOOTUP_DEFAULT
amdsmi_interface.amdsmi_dev_set_power_profile(args.gpu, 0, power_profile_mask)
result = 'Successfully reset Power Profile'
except amdsmi_interface.AmdSmiLibraryException as err:
result = err.get_error_info()
try:
level_auto = amdsmi_interface.AmdSmiDevPerfLevel.AUTO
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
reset_clocks_results['performance'] = 'Successfully reset Performance Level'
except amdsmi_interface.AmdSmiLibraryException as err:
reset_clocks_results['performance'] = err.get_error_info()
self.logger.store_output(args.gpu, 'reset_profile', reset_profile_results)
if args.resetxgmierr:
try:
amdsmi_interface.amdsmi_dev_reset_xgmi_error(args.gpu)
result = 'Successfully reset XGMI Error count'
except amdsmi_interface.AmdSmiLibraryException as err:
result = err.get_error_info()
self.logger.store_output(args.gpu, 'reset_xgmi_err', result)
if args.resetprefdet:
try:
level_auto = amdsmi_interface.AmdSmiDevPerfLevel.AUTO
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
result = 'Successfully disabled performance determinism'
except amdsmi_interface.AmdSmiLibraryException as err:
result = err.get_error_info()
self.logger.store_output(args.gpu, 'reset_pref_det', result)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output()
def rocm_smi(self, args):
print("rocmsmi test")