SWDEV-380688 - Added CSV Format

Change-Id: I609bc9837132fd674bf54480a3220c911b2909d2
Signed-off-by: Maisam Arif <Maisam.Arif@amd.com>


[ROCm/amdsmi commit: 8ad410f6af]
This commit is contained in:
Maisam Arif
2023-04-19 23:58:33 -05:00
parent a1c2a246b1
commit 1de2329c18
6 changed files with 361 additions and 236 deletions
+1 -1
View File
@@ -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)
@@ -40,7 +41,6 @@ def _print_error(e, destination):
str(destination) + " file")
if __name__ == "__main__":
# Set compatability mode based on which cli mapping user selects
if 'gpuv-smi' in sys.argv[0]:
+116 -16
View File
@@ -395,8 +395,7 @@ class AMDSMICommands():
args.gpu = device_handle
values_dict = {}
fw_list = {}
if args.fw_list:
try:
fw_info = amdsmi_interface.amdsmi_get_fw_info(args.gpu)
@@ -421,18 +420,32 @@ class AMDSMICommands():
if self.logger.is_gpuvsmi_compatibility():
fw_info['ucode_list'] = fw_info.pop('fw_list')
values_dict.update(fw_info)
fw_list.update(fw_info)
except amdsmi_exception.AmdSmiLibraryException as e:
raise e
# Store values in logger.output
self.logger.store_output(args.gpu, 'values', values_dict)
multiple_devices_csv_override = False
# Convert and store output by pid for csv format
if self.logger.is_csv_format():
if self.logger.is_gpuvsmi_compatibility():
fw_key = 'ucode_list'
else:
fw_key = 'fw_list'
for fw_info_dict in fw_list[fw_key]:
for key, value in fw_info_dict.items():
multiple_devices_csv_override = True
self.logger.store_output(args.gpu, key, value)
self.logger.store_multiple_device_output()
else:
# Store values in logger.output
self.logger.store_output(args.gpu, 'values', fw_list)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output()
self.logger.print_output(multiple_device_output=multiple_devices_csv_override)
def bad_pages(self, args, multiple_devices=False, gpu=None, retired=None, pending=None, un_res=None):
@@ -817,7 +830,9 @@ class AMDSMICommands():
ecc_dict[state['block']] = {'correctable' : ecc_count['correctable_count'],
'uncorrectable': ecc_count['uncorrectable_count']}
if ecc_dict == {}:
ecc_dict = 'No RAS Blocks Enabled'
ecc_dict['correctable'] = 'N/A'
ecc_dict['uncorrectable'] = 'N/A'
values_dict['ecc'] = ecc_dict
except amdsmi_exception.AmdSmiLibraryException as e:
values_dict['ecc'] = e.get_error_info()
@@ -1159,21 +1174,30 @@ class AMDSMICommands():
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'})
multiple_devices_csv_override = False
# Convert and store output by pid for csv format
if self.logger.is_csv_format():
for process_info in filtered_process_values:
for key, value in process_info['process_info'].items():
multiple_devices_csv_override = True
self.logger.store_output(args.gpu, key, value)
self.logger.store_multiple_device_output()
else:
self.logger.store_output(args.gpu, 'values', filtered_process_values)
# 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()
self.logger.print_output(multiple_device_output=multiple_devices_csv_override)
if watching_output: # End of single gpu add to watch_output
self.logger.store_watch_output(multiple_devices=False)
@@ -1372,23 +1396,31 @@ class AMDSMICommands():
try:
perf_level = amdsmi_interface.amdsmi_dev_get_perf_level(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get performance level of {gpu_string}") from e
if 'manual' in perf_level.lower():
try:
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, amdsmi_interface.AmdSmiDevPerfLevel.MANUAL)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the performance level of {gpu_string} to manual") from e
if clock_type != amdsmi_interface.AmdSmiClkType.PCIE:
try:
amdsmi_interface.amdsmi_dev_set_clk_freq(args.gpu, clock_type, freq_bitmask)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the {clock_type} clock frequency on {gpu_string}") from e
else:
try:
amdsmi_interface.amdsmi_dev_set_pci_bandwidth(args.gpu, freq_bitmask)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the {clock_type} clock frequency on {gpu_string}") from e
self.logger.store_output(args.gpu, 'clock', f'Successfully set clock frequency bitmask for {clock_type}')
@@ -1400,17 +1432,23 @@ class AMDSMICommands():
try:
perf_level = amdsmi_interface.amdsmi_dev_get_perf_level(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get performance level of {gpu_string}") from e
if 'manual' in perf_level.lower():
try:
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, amdsmi_interface.AmdSmiDevPerfLevel.MANUAL)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the performance level of {gpu_string} to manual") from e
try:
amdsmi_interface.amdsmi_dev_set_clk_freq(args.gpu, clock_type, freq_bitmask)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the {clock_type} clock frequency on {gpu_string}") from e
self.logger.store_output(args.gpu, 'sclk', 'Successfully set clock frequency bitmask')
@@ -1421,17 +1459,23 @@ class AMDSMICommands():
try:
perf_level = amdsmi_interface.amdsmi_dev_get_perf_level(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get performance level of {gpu_string}") from e
if 'manual' in perf_level.lower():
try:
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, amdsmi_interface.AmdSmiDevPerfLevel.MANUAL)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the performance level of {gpu_string} to manual") from e
try:
amdsmi_interface.amdsmi_dev_set_clk_freq(args.gpu, clock_type, freq_bitmask)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the {clock_type} clock frequency on {gpu_string}") from e
self.logger.store_output(args.gpu, 'mclk', 'Successfully set clock frequency bitmask')
@@ -1442,16 +1486,22 @@ class AMDSMICommands():
try:
perf_level = amdsmi_interface.amdsmi_dev_get_perf_level(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get performance level of {gpu_string}") from e
if 'manual' in perf_level.lower():
try:
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, amdsmi_interface.AmdSmiDevPerfLevel.MANUAL)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the performance level of {gpu_string} to manual") from e
try:
amdsmi_interface.amdsmi_dev_set_pci_bandwidth(args.gpu, freq_bitmask)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the {clock_type} clock frequency on {gpu_string}") from e
self.logger.store_output(args.gpu, 'pcie', 'Successfully set clock frequency bitmask')
@@ -1462,6 +1512,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_od_clk_info(args.gpu, level, value, clock_type)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to change the {clock_type} clock frequency in the PowerPlay table on {gpu_string}") from e
self.logger.store_output(args.gpu, 'slevel', 'Successfully changed clock frequency')
@@ -1472,6 +1524,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_od_clk_info(args.gpu, level, value, clock_type)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to change the {clock_type} clock frequency in the PowerPlay table on {gpu_string}") from e
self.logger.store_output(args.gpu, 'mlevel', 'Successfully changed clock frequency')
@@ -1480,6 +1534,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_od_volt_info(args.gpu, point, clk, volt)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the Voltage Curve point {point} to {clk}(MHz) {volt}(mV) on {gpu_string}") from e
self.logger.store_output(args.gpu, 'vc', f'Successfully set voltage point {point} to {clk}(MHz) {volt}(mV)')
@@ -1489,6 +1545,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_clk_range(args.gpu, min_value, max_value, clock_type)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set {clock_type} from {min_value}(MHz) to {max_value}(MHz) on {gpu_string}") from e
self.logger.store_output(args.gpu, 'srange', f"Successfully set {clock_type} from {min_value}(MHz) to {max_value}(MHz)")
@@ -1498,6 +1556,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_clk_range(args.gpu, min_value, max_value, clock_type)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set {clock_type} from {min_value}(MHz) to {max_value}(MHz) on {gpu_string}") from e
self.logger.store_output(args.gpu, 'mrange', f"Successfully set {clock_type} from {min_value}(MHz) to {max_value}(MHz)")
@@ -1505,6 +1565,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_fan_speed(args.gpu, 0, args.fan)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set fan speed {args.fan} on {gpu_string}") from e
self.logger.store_output(args.gpu, 'fan', f"Successfully set fan speed {args.fan}")
@@ -1513,6 +1575,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, perf_level)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set performance level {args.perflevel} on {gpu_string}") from e
self.logger.store_output(args.gpu, 'perflevel', f"Successfully set performance level {args.perflevel}")
@@ -1521,17 +1585,23 @@ class AMDSMICommands():
try:
perf_level = amdsmi_interface.amdsmi_dev_get_perf_level(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get performance level of {gpu_string}") from e
if 'manual' in perf_level.lower():
try:
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, amdsmi_interface.AmdSmiDevPerfLevel.MANUAL)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the performance level of {gpu_string} to manual") from e
try:
amdsmi_interface.amdsmi_dev_set_overdrive_level_v1(args.gpu, args.overdrive)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set overdrive {args.overdrive} to {gpu_string}") from e
self.logger.store_output(args.gpu, 'overdrive', f"Successfully to set overdrive level to {args.overdrive}")
@@ -1540,12 +1610,16 @@ class AMDSMICommands():
try:
perf_level = amdsmi_interface.amdsmi_dev_get_perf_level(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get performance level of {gpu_string}") from e
if 'manual' in perf_level.lower():
try:
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, amdsmi_interface.AmdSmiDevPerfLevel.MANUAL)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set the performance level of {gpu_string} to manual") from e
self.logger.store_output(args.gpu, 'memoverdrive', f"Successfully to set memoverdrive level to {args.memoverdrive}")
@@ -1554,6 +1628,8 @@ class AMDSMICommands():
try:
power_caps = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get the power cap info for {gpu_string}") from e
if overdrive_power_cap == 0:
overdrive_power_cap = power_caps['power_cap_default']
@@ -1572,11 +1648,15 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_dev_set_power_cap(args.gpu, 0, overdrive_power_cap)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set power cap to {overdrive_power_cap} on {gpu_string}") from e
try:
power_caps = amdsmi_interface.amdsmi_get_power_cap_info(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to get the power cap info for {gpu_string} post set") from e
if power_caps['power_cap'] == overdrive_power_cap:
@@ -1589,6 +1669,8 @@ class AMDSMICommands():
try:
amdsmi_interface.amdsmi_set_perf_determinism_mode(args.gpu, args.perfdeterminism)
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
raise ValueError(f"Unable to set performance determinism and clock frequency to {args.perfdeterminism} on {gpu_string}") from e
self.logger.store_output(args.gpu, 'perfdeterminism', f"Successfully enabled performance determinism and set GFX clock frequency to {args.perfdeterminism}")
@@ -1659,6 +1741,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_reset_gpu(args.gpu)
result = 'Successfully reset GPU'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
result = e.get_error_info()
else:
result = 'Unable to reset non-amd GPU'
@@ -1673,6 +1757,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_set_overdrive_level_v1(args.gpu, 0)
reset_clocks_results['overdrive'] = 'Overdrive set to 0'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
reset_clocks_results['overdrive'] = e.get_error_info()
try:
@@ -1680,6 +1766,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
reset_clocks_results['clocks'] = 'Successfully reset clocks'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
reset_clocks_results['clocks'] = e.get_error_info()
try:
@@ -1687,6 +1775,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
reset_clocks_results['performance'] = 'Performance level reset to auto'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
reset_clocks_results['performance'] = e.get_error_info()
self.logger.store_output(args.gpu, 'reset_clocks', reset_clocks_results)
@@ -1695,6 +1785,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_reset_fan(args.gpu, 0)
result = 'Successfully reset fan speed to driver control'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
result = e.get_error_info()
self.logger.store_output(args.gpu, 'reset_fans', result)
@@ -1706,6 +1798,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_set_power_profile(args.gpu, 0, power_profile_mask)
reset_profile_results['power_profile'] = 'Successfully reset Power Profile'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
reset_profile_results['power_profile'] = e.get_error_info()
try:
@@ -1713,6 +1807,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
reset_profile_results['performance_level'] = 'Successfully reset Performance Level'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
reset_profile_results['performance_level'] = e.get_error_info()
self.logger.store_output(args.gpu, 'reset_profile', reset_profile_results)
@@ -1721,6 +1817,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_reset_xgmi_error(args.gpu)
result = 'Successfully reset XGMI Error count'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
result = e.get_error_info()
self.logger.store_output(args.gpu, 'reset_xgmi_err', result)
if args.perfdeterminism:
@@ -1729,6 +1827,8 @@ class AMDSMICommands():
amdsmi_interface.amdsmi_dev_set_perf_level_v1(args.gpu, level_auto)
result = 'Successfully disabled performance determinism'
except amdsmi_exception.AmdSmiLibraryException as e:
if e.get_error_code() == amdsmi_exception.AmdSmiRetCode.ERR_NO_PERM:
raise PermissionError('Command requires elevation')
result = e.get_error_info()
self.logger.store_output(args.gpu, 'reset_perf_determinism', result)
+234 -215
View File
@@ -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',
@@ -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,6 +145,180 @@ class AMDSMILogger():
return clean_yaml_output
def flatten_dict(self, target_dict):
"""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:
value_with_parent_key = {}
for parent_key, child_dict in value.items():
if isinstance(child_dict, dict):
for child_key, value1 in child_dict.items():
value_with_parent_key[parent_key + '_' + child_key] = value1
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.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)
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():
# 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 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
self.multiple_device_output.append(self.output)
self.output = {}
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
"""
values = self.output
if multiple_devices:
values = self.multiple_device_output
self.watch_output.append({'timestamp': int(time.time()),
'values': values})
def print_output(self, multiple_device_output=False, watch_output=False):
""" Print current output acording to format and then destination
params:
@@ -324,70 +340,73 @@ class AMDSMILogger():
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)
if multiple_device_output:
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)
json_std_output = json.dumps(json_output, indent = 4)
print(json_std_output)
else: # Write output to file
if watch_output:
if watch_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 watch_output: # Don't print output if it's for watch
return
if multiple_device_output:
stored_csv_output = self.multiple_device_output
else:
if not isinstance(self.output, list):
stored_csv_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:
pass
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)
if self.is_gpuvsmi_compatibility():
print(str(csv_stdout_output).replace('"',''))
else:
pass
else: # Write output to file
if watch_output:
pass
elif multiple_device_output:
pass
else:
pass
print(str(csv_stdout_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_output=False, watch_output=False):
if watch_output: # Don't print output if it's for watch
return
if multiple_device_output:
human_readable = ''
human_readable_output = ''
for output in self.multiple_device_output:
human_readable += (self.convert_json_to_human_readable(output))
human_readable_output += (self._convert_json_to_human_readable(output))
else:
human_readable = self.convert_json_to_human_readable(self.output)
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
output_file.write(human_readable_output)
+9 -2
View File
@@ -59,7 +59,7 @@ class AMDSMIParser(argparse.ArgumentParser):
width=90),
description=f"AMD System Management Interface | {version_string} | {platform_string}",
add_help=True,
prog="amdsmi_cli")
prog="amd-smi")
# Setup subparsers
subparsers = self.add_subparsers(
@@ -112,7 +112,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():
-1
View File
@@ -1 +0,0 @@
__version__ = "0.0.3"
@@ -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