Files
TheRock/rocm-systems/projects/amdsmi/amdsmi_cli/subcommands/metric.py
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

4143 lines
200 KiB
Python

#!/usr/bin/env python3
#
# Copyright (C) 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.
import json
import logging
import time
from amdsmi import amdsmi_exception, amdsmi_interface
from amdsmi.amdsmi_interface import AMDSMI_MAX_RAIL_INDEX
class MetricCommands:
def metric_gpu(
self,
args,
multiple_devices=False,
watching_output=False,
gpu=None,
usage=None,
watch=None,
watch_time=None,
iterations=None,
power=None,
clock=None,
temperature=None,
ecc=None,
ecc_blocks=None,
pcie=None,
fan=None,
voltage_curve=None,
overdrive=None,
perf_level=None,
xgmi_err=None,
energy=None,
mem_usage=None,
voltage=None,
schedule=None,
guard=None,
guest_data=None,
fb_usage=None,
xgmi=None,
throttle=None,
base_board=None,
gpu_board=None,
partition=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 argument 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.
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.
ecc_blocks (bool, optional): Value override for args.ecc. Defaults to None.
pcie (bool, optional): Value override for args.pcie. Defaults to None.
fan (bool, optional): Value override for args.fan. 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.
perf_level (bool, optional): Value override for args.perf_level. 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.
voltage (bool, optional): Value override for args.voltage. Defaults to None.
schedule (bool, optional): Value override for args.schedule. Defaults to None.
guard (bool, optional): Value override for args.guard. Defaults to None.
guest_data (bool, optional): Value override for args.guest_data. Defaults to None.
fb_usage (bool, optional): Value override for args.fb_usage. Defaults to None.
xgmi (bool, optional): Value override for args.xgmi. Defaults to None.
throttle (bool, optional): Value override for args.throttle. Defaults to None.
partition (bool, optional): Value override for args.partition. 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 watch:
args.watch = watch
if watch_time:
args.watch_time = watch_time
if iterations:
args.iterations = iterations
# Store args that are applicable to the current platform
current_platform_args = []
current_platform_values = []
if not self.helpers.is_hypervisor() and not self.helpers.is_windows():
if mem_usage:
args.mem_usage = mem_usage
current_platform_args += ["mem_usage"]
current_platform_values += [args.mem_usage]
if self.helpers.is_hypervisor() or self.helpers.is_baremetal() or self.helpers.is_linux():
if usage:
args.usage = usage
if base_board:
args.base_board = base_board
if gpu_board:
args.gpu_board = gpu_board
if power:
args.power = power
if clock:
args.clock = clock
if temperature:
args.temperature = temperature
if voltage:
args.voltage = voltage
if pcie:
args.pcie = pcie
if ecc:
args.ecc = ecc
if ecc_blocks:
args.ecc_blocks = ecc_blocks
current_platform_args += [
"usage",
"power",
"clock",
"temperature",
"voltage",
"pcie",
"ecc",
"ecc_blocks",
"base_board",
"gpu_board",
]
current_platform_values += [
args.usage,
args.power,
args.clock,
args.temperature,
args.voltage,
args.pcie,
]
current_platform_values += [args.ecc, args.ecc_blocks, args.base_board, args.gpu_board]
if self.helpers.is_baremetal() and self.helpers.is_linux():
if fan:
args.fan = fan
if voltage_curve:
args.voltage_curve = voltage_curve
if overdrive:
args.overdrive = overdrive
if perf_level:
args.perf_level = perf_level
if xgmi_err:
args.xgmi_err = xgmi_err
if energy:
args.energy = energy
if throttle:
args.violation = throttle
args.throttle = throttle
if partition:
args.partition = partition
current_platform_args += [
"fan",
"voltage_curve",
"overdrive",
"perf_level",
"xgmi_err",
"energy",
"throttle",
]
current_platform_values += [
args.fan,
args.voltage_curve,
args.overdrive,
args.perf_level,
args.xgmi_err,
args.energy,
args.throttle,
]
if self.helpers.is_hypervisor():
if schedule:
args.schedule = schedule
if guard:
args.guard = guard
if guest_data:
args.guest_data = guest_data
if fb_usage:
args.fb_usage = fb_usage
if xgmi:
args.xgmi = xgmi
current_platform_args += ["schedule", "guard", "guest_data", "fb_usage", "xgmi"]
current_platform_values += [
args.schedule,
args.guard,
args.guest_data,
args.fb_usage,
args.xgmi,
]
# Handle No GPU passed
if args.gpu == None:
args.gpu = self.device_handles
if not self.group_check_printed:
self.helpers.check_required_groups()
self.group_check_printed = True
# Handle watch logic, will only enter this block once
if args.watch:
self.helpers.handle_watch(args=args, subcommand=self.metric_gpu, logger=self.logger)
return
# Handle multiple GPUs
if isinstance(args.gpu, list):
if len(args.gpu) > 1:
# Deepcopy gpus as recursion will destroy the gpu list
stored_gpus = []
for gpu in args.gpu:
stored_gpus.append(gpu)
# Store output from multiple devices
for device_handle in args.gpu:
self.metric_gpu(
args,
multiple_devices=True,
watching_output=watching_output,
gpu=device_handle,
)
# Reload original gpus
args.gpu = stored_gpus
# Print multiple device output
if not self.logger.is_json_format() or watching_output:
self.logger.print_output(
multiple_device_enabled=True, watching_output=watching_output
)
# Add output to total watch output and clear multiple device output
if watching_output:
self.logger.store_watch_output(multiple_device_enabled=True)
return
elif len(args.gpu) == 1:
args.gpu = args.gpu[0]
else:
raise IndexError("args.gpu should not be an empty list")
# Get gpu_id for logging
gpu_id = self.helpers.get_gpu_id_from_device_handle(args.gpu)
if args.loglevel == "DEBUG":
try:
# Get GPU Metrics table version
gpu_metric_version_info = amdsmi_interface.amdsmi_get_gpu_metrics_header_info(
args.gpu
)
gpu_metric_version_str = json.dumps(gpu_metric_version_info, indent=4)
logging.debug(
"GPU Metrics table Version for GPU %s | %s", gpu_id, gpu_metric_version_str
)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"#1 - Unable to load GPU Metrics table version for %s | %s",
gpu_id,
e.get_error_info(),
)
try:
# Get GPU Metrics table
gpu_metric_debug_info = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)
gpu_metric_str = json.dumps(gpu_metric_debug_info, indent=4)
logging.debug("GPU Metrics table for GPU %s | %s", gpu_id, str(gpu_metric_str))
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"#2 - Unable to load GPU Metrics table for %s | %s", gpu_id, e.get_error_info()
)
logging.debug(f"Metric Arg information for GPU {gpu_id} on {self.helpers.os_info()}")
logging.debug(f"Args: {current_platform_args}")
logging.debug(f"Values: {current_platform_values}")
# Set the platform applicable args to True if no args are set
if not any(current_platform_values):
for arg in current_platform_args:
setattr(args, arg, True)
# Add timestamp and store values for specified arguments
values_dict = {}
is_partition_metrics = False # True if we get the metrics from xcp_metrics file (amdsmi_get_gpu_partition_metrics_info)
# get metric info only once per gpu, this will speed up data output
try:
# Get GPU Metrics table
gpu_metric = amdsmi_interface.amdsmi_get_gpu_metrics_info(args.gpu)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"#3 - Unable to load GPU Metrics table for %s | %s", gpu_id, e.get_error_info()
)
gpu_metric = amdsmi_interface._NA_amdsmi_get_gpu_metrics_info()
# Detect APU system
show_apu = bool(gpu_metric.get("is_apu", False))
if show_apu:
# APUs lack these discrete-GPU sensors, so their sections are omitted.
logging.debug(
"APU detected for gpu %s; omitting pcie, ecc_blocks, "
"voltage_curve, overdrive, xgmi_err, and energy sections",
gpu_id,
)
# Workaround for XCP (partition) metrics not providing num_partition in v1.9+/v1.1+
# Provides original formatting for earlier metric versions
partition_metric_info = self.helpers._get_metric_version_and_partition_info(
gpu_metric, is_partition_metrics, gpu_id, args.gpu
)
num_partition = partition_metric_info["num_partition"]
# Fetch partition metrics once per GPU; the sections below reuse this result.
# --partition is only registered on baremetal Linux, so gate on the same
# platform condition before reading args.partition.
gpu_partition_metrics = None
if self.helpers.is_baremetal() and self.helpers.is_linux() and args.partition:
try:
gpu_partition_metrics = amdsmi_interface.amdsmi_get_gpu_partition_metrics_info(
args.gpu
)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get partition metrics for gpu %s | %s", gpu_id, e.get_error_info()
)
if self.logger.is_json_format():
values_dict["gpu"] = int(gpu_id)
# Populate the pcie_dict first due to multiple gpu metrics calls incorrectly increasing bandwidth
if "pcie" in current_platform_args:
if args.pcie and not show_apu:
pcie_dict = {
"width": "N/A",
"speed": "N/A",
"bandwidth": "N/A",
"replay_count": "N/A",
"l0_to_recovery_count": "N/A",
"replay_roll_over_count": "N/A",
"nak_sent_count": "N/A",
"nak_received_count": "N/A",
"current_bandwidth_sent": "N/A",
"current_bandwidth_received": "N/A",
"max_packet_size": "N/A",
"lc_perf_other_end_recovery_count": "N/A",
}
try:
pcie_metric = amdsmi_interface.amdsmi_get_pcie_info(args.gpu)["pcie_metric"]
logging.debug("PCIE Metric for %s | %s", gpu_id, pcie_metric)
pcie_dict["width"] = pcie_metric["pcie_width"]
if pcie_metric["pcie_speed"] != "N/A":
if pcie_metric["pcie_speed"] % 1000 != 0:
pcie_speed_GTs_value = round(pcie_metric["pcie_speed"] / 1000, 1)
else:
pcie_speed_GTs_value = round(pcie_metric["pcie_speed"] / 1000)
pcie_dict["speed"] = pcie_speed_GTs_value
pcie_dict["bandwidth"] = pcie_metric["pcie_bandwidth"]
pcie_dict["replay_count"] = pcie_metric["pcie_replay_count"]
if pcie_dict["replay_count"] == "N/A":
try:
pcie_replay = amdsmi_interface.amdsmi_get_gpu_pci_replay_counter(
args.gpu
)
pcie_dict["replay_count"] = pcie_replay
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get sysfs pcie replay counter on gpu %s | %s",
gpu_id,
e.get_error_info(),
)
pcie_dict["l0_to_recovery_count"] = pcie_metric["pcie_l0_to_recovery_count"]
pcie_dict["replay_roll_over_count"] = pcie_metric["pcie_replay_roll_over_count"]
pcie_dict["nak_received_count"] = pcie_metric["pcie_nak_received_count"]
pcie_dict["nak_sent_count"] = pcie_metric["pcie_nak_sent_count"]
pcie_dict["lc_perf_other_end_recovery_count"] = pcie_metric[
"pcie_lc_perf_other_end_recovery_count"
]
pcie_speed_unit = "GT/s"
pcie_bw_unit = "Mb/s"
if self.logger.is_human_readable_format():
if pcie_dict["speed"] != "N/A":
pcie_dict["speed"] = f"{pcie_dict['speed']} {pcie_speed_unit}"
if pcie_dict["bandwidth"] != "N/A":
pcie_dict["bandwidth"] = f"{pcie_dict['bandwidth']} {pcie_bw_unit}"
if self.logger.is_json_format():
if pcie_dict["speed"] != "N/A":
pcie_dict["speed"] = {
"value": pcie_dict["speed"],
"unit": pcie_speed_unit,
}
if pcie_dict["bandwidth"] != "N/A":
pcie_dict["bandwidth"] = {
"value": pcie_dict["bandwidth"],
"unit": pcie_bw_unit,
}
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get pcie link status for gpu %s | %s", gpu_id, e.get_error_info()
)
try:
pcie_bw = amdsmi_interface.amdsmi_get_gpu_pci_throughput(args.gpu)
sent = pcie_bw["sent"] * pcie_bw["max_pkt_sz"]
received = pcie_bw["received"] * pcie_bw["max_pkt_sz"]
bw_unit = "Mb/s"
packet_size_unit = "B"
if sent > 0:
sent = sent // 1024 // 1024
if received > 0:
received = received // 1024 // 1024
if self.logger.is_human_readable_format():
sent = f"{sent} {bw_unit}"
received = f"{received} {bw_unit}"
pcie_bw["max_pkt_sz"] = f"{pcie_bw['max_pkt_sz']} {packet_size_unit}"
if self.logger.is_json_format():
sent = {"value": sent, "unit": bw_unit}
received = {"value": received, "unit": bw_unit}
pcie_bw["max_pkt_sz"] = {
"value": pcie_bw["max_pkt_sz"],
"unit": packet_size_unit,
}
pcie_dict["current_bandwidth_sent"] = sent
pcie_dict["current_bandwidth_received"] = received
pcie_dict["max_packet_size"] = pcie_bw["max_pkt_sz"]
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get pcie bandwidth for gpu %s | %s", gpu_id, e.get_error_info()
)
if "usage" in current_platform_args:
if args.usage:
try:
engine_usage = amdsmi_interface.amdsmi_get_gpu_activity(args.gpu)
logging.debug(f"engine_usage dictionary = {engine_usage}")
# TODO: move vcn_activity and jpeg_activity into amdsmi_get_gpu_activity
engine_usage["vcn_activity"] = gpu_metric["vcn_activity"]
engine_usage["jpeg_activity"] = gpu_metric["jpeg_activity"]
engine_usage["gfx_busy_inst"] = "N/A"
engine_usage["jpeg_busy"] = "N/A"
engine_usage["vcn_busy"] = "N/A"
# Use partition-scoped data when partition metrics were fetched.
if gpu_partition_metrics is not None:
xcp_gfx_busy = gpu_partition_metrics.get("xcp_stats.gfx_busy_inst", [])
xcp_jpeg_busy = gpu_partition_metrics.get("xcp_stats.jpeg_busy", [])
xcp_vcn_busy = gpu_partition_metrics.get("xcp_stats.vcn_busy", [])
if xcp_gfx_busy != "N/A" and isinstance(xcp_gfx_busy, list):
new_xcp_dict = {}
for xcp_idx, gfx_busy in enumerate(xcp_gfx_busy):
new_xcp_dict[f"xcp_{xcp_idx}"] = (
list(gfx_busy) if isinstance(gfx_busy, list) else gfx_busy
)
engine_usage["gfx_busy_inst"] = new_xcp_dict
if xcp_jpeg_busy != "N/A" and isinstance(xcp_jpeg_busy, list):
new_xcp_dict = {}
for xcp_idx, jpeg_busy in enumerate(xcp_jpeg_busy):
new_xcp_dict[f"xcp_{xcp_idx}"] = (
list(jpeg_busy) if isinstance(jpeg_busy, list) else jpeg_busy
)
engine_usage["jpeg_busy"] = new_xcp_dict
if xcp_vcn_busy != "N/A" and isinstance(xcp_vcn_busy, list):
new_xcp_dict = {}
for xcp_idx, vcn_busy in enumerate(xcp_vcn_busy):
new_xcp_dict[f"xcp_{xcp_idx}"] = (
list(vcn_busy) if isinstance(vcn_busy, list) else vcn_busy
)
engine_usage["vcn_busy"] = new_xcp_dict
elif num_partition != "N/A":
# Socket-level metrics with partition support (existing behavior)
new_xcp_dict = {}
for current_xcp in range(num_partition):
new_xcp_dict[f"xcp_{current_xcp}"] = gpu_metric[
"xcp_stats.gfx_busy_inst"
][current_xcp]
engine_usage["gfx_busy_inst"] = new_xcp_dict
new_xcp_dict = {}
for current_xcp in range(num_partition):
new_xcp_dict[f"xcp_{current_xcp}"] = gpu_metric["xcp_stats.jpeg_busy"][
current_xcp
]
engine_usage["jpeg_busy"] = new_xcp_dict
new_xcp_dict = {}
for current_xcp in range(num_partition):
new_xcp_dict[f"xcp_{current_xcp}"] = gpu_metric["xcp_stats.vcn_busy"][
current_xcp
]
engine_usage["vcn_busy"] = new_xcp_dict
else:
# On devices without XCP partitions (e.g. Navi), vcn_busy_percent
# is available via sysfs; there is no equivalent sysfs for gfx_busy_inst
# or jpeg_busy on these devices.
try:
engine_usage["vcn_busy"] = amdsmi_interface.amdsmi_get_vcn_busy_percent(
args.gpu
)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get vcn busy percent for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
engine_usage["vcn_busy"] = "N/A"
logging.debug(f"After updates to engine_usage dictionary = {engine_usage}")
for key, value in engine_usage.items():
activity_unit = "%"
if self.logger.is_human_readable_format():
if isinstance(value, list):
for index, activity in enumerate(value):
if activity != "N/A":
engine_usage[key][index] = f"{activity} {activity_unit}"
# Convert list to a string for human readable format
engine_usage[key] = (
"[" + ", ".join(str(x) for x in engine_usage[key]) + "]"
)
elif isinstance(value, dict):
for k, v in value.items():
if isinstance(v, list):
for index, activity in enumerate(v):
if activity != "N/A" and not isinstance(activity, str):
value[k][index] = f"{activity} {activity_unit}"
# Convert list to a string for human readable format
value[k] = "[" + ", ".join(str(x) for x in value[k]) + "]"
elif v != "N/A" and not isinstance(v, str):
value[k] = f"{v} {activity_unit}"
elif value != "N/A":
engine_usage[key] = f"{value} {activity_unit}"
if self.logger.is_json_format():
if isinstance(value, list):
for index, activity in enumerate(value):
if activity != "N/A":
engine_usage[key][index] = {
"value": activity,
"unit": activity_unit,
}
elif isinstance(value, dict):
for k, v in value.items():
if isinstance(v, list):
for index, activity in enumerate(v):
if activity != "N/A":
value[k][index] = {
"value": activity,
"unit": activity_unit,
}
elif v != "N/A":
value[k] = {"value": v, "unit": activity_unit}
elif value != "N/A":
engine_usage[key] = {"value": value, "unit": activity_unit}
values_dict["usage"] = engine_usage
except Exception as e:
values_dict["usage"] = "N/A"
logging.debug("Failed to get gpu activity for gpu %s | %s", gpu_id, e)
# APU-specific activity data
if show_apu and isinstance(values_dict.get("usage"), dict):
apu_usage_fields = {
"apu_average_gfx_activity": gpu_metric.get(
"apu_metrics.average_gfx_activity", "N/A"
),
"apu_average_mm_activity": gpu_metric.get(
"apu_metrics.average_mm_activity", "N/A"
),
"apu_average_vcn_activity": gpu_metric.get(
"apu_metrics.average_vcn_activity", "N/A"
),
"apu_average_ipu_activity": gpu_metric.get(
"apu_metrics.average_ipu_activity", "N/A"
),
"apu_average_core_c0_activity": gpu_metric.get(
"apu_metrics.average_core_c0_activity", "N/A"
),
"apu_average_dram_reads": gpu_metric.get(
"apu_metrics.average_dram_reads", "N/A"
),
"apu_average_dram_writes": gpu_metric.get(
"apu_metrics.average_dram_writes", "N/A"
),
"apu_average_ipu_reads": gpu_metric.get(
"apu_metrics.average_ipu_reads", "N/A"
),
"apu_average_ipu_writes": gpu_metric.get(
"apu_metrics.average_ipu_writes", "N/A"
),
}
for key, value in apu_usage_fields.items():
activity_unit = "%"
if value != "N/A":
if "dram" in key:
values_dict["usage"][key] = self.helpers.unit_format(
self.logger, value, "MB/s"
)
elif "reads" in key or "writes" in key:
values_dict["usage"][key] = value
elif isinstance(value, list):
if self.logger.is_human_readable_format():
formatted = [
f"{v} {activity_unit}" if v != "N/A" else "N/A"
for v in value
]
values_dict["usage"][key] = "[" + ", ".join(formatted) + "]"
elif self.logger.is_json_format():
values_dict["usage"][key] = [
{"value": v, "unit": activity_unit} if v != "N/A" else "N/A"
for v in value
]
else:
values_dict["usage"][key] = value
else:
values_dict["usage"][key] = self.helpers.unit_format(
self.logger, value, activity_unit
)
if "power" in current_platform_args:
if args.power:
power_dict = {
"socket_power": "N/A",
"gfx_voltage": "N/A",
"soc_voltage": "N/A",
"mem_voltage": "N/A",
"throttle_status": "N/A",
"power_management": "N/A",
"ubb_power": "N/A",
}
try:
voltage_unit = "mV"
power_unit = "W"
power_info = amdsmi_interface.amdsmi_get_power_info(args.gpu)
for key, value in power_info.items():
if "voltage" in key:
power_info[key] = self.helpers.unit_format(
self.logger, value, voltage_unit
)
elif "power" in key:
power_info[key] = self.helpers.unit_format(
self.logger, value, power_unit
)
power_dict["socket_power"] = power_info["socket_power"]
power_dict["gfx_voltage"] = power_info["gfx_voltage"]
power_dict["soc_voltage"] = power_info["soc_voltage"]
power_dict["mem_voltage"] = power_info["mem_voltage"]
power_dict["ubb_power"] = power_info.get("ubb_power", "N/A")
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get power info for gpu %s | %s", gpu_id, e.get_error_info()
)
try:
is_power_management_enabled = (
amdsmi_interface.amdsmi_is_gpu_power_management_enabled(args.gpu)
)
if is_power_management_enabled:
power_dict["power_management"] = "ENABLED"
else:
power_dict["power_management"] = "DISABLED"
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get power management status for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
try:
power_dict["throttle_status"] = "N/A"
throttle_status = gpu_metric["throttle_status"]
if throttle_status != "N/A":
if throttle_status:
power_dict["throttle_status"] = "THROTTLED"
else:
power_dict["throttle_status"] = "UNTHROTTLED"
except Exception as e:
logging.debug("Failed to get throttle status for gpu %s | %s", gpu_id, e)
# APU-specific power data
if show_apu:
apu_power_fields = {
"apu_average_socket_power": gpu_metric.get(
"apu_metrics.average_socket_power", "N/A"
),
"apu_average_gfx_power": gpu_metric.get(
"apu_metrics.average_gfx_power", "N/A"
),
"apu_average_cpu_power": gpu_metric.get(
"apu_metrics.average_cpu_power", "N/A"
),
"apu_average_soc_power": gpu_metric.get(
"apu_metrics.average_soc_power", "N/A"
),
"apu_average_core_power": gpu_metric.get(
"apu_metrics.average_core_power", "N/A"
),
"apu_average_ipu_power": gpu_metric.get(
"apu_metrics.average_ipu_power", "N/A"
),
"apu_average_apu_power": gpu_metric.get(
"apu_metrics.average_apu_power", "N/A"
),
"apu_average_dgpu_power": gpu_metric.get(
"apu_metrics.average_dgpu_power", "N/A"
),
"apu_average_all_core_power": gpu_metric.get(
"apu_metrics.average_all_core_power", "N/A"
),
"apu_average_sys_power": gpu_metric.get(
"apu_metrics.average_sys_power", "N/A"
),
"apu_stapm_power_limit": gpu_metric.get(
"apu_metrics.stapm_power_limit", "N/A"
),
"apu_current_stapm_power_limit": gpu_metric.get(
"apu_metrics.current_stapm_power_limit", "N/A"
),
}
power_unit = "W"
for key, value in apu_power_fields.items():
if value != "N/A":
if isinstance(value, list):
if self.logger.is_human_readable_format():
formatted = [
f"{v} {power_unit}" if v != "N/A" else "N/A" for v in value
]
power_dict[key] = "[" + ", ".join(formatted) + "]"
elif self.logger.is_json_format():
power_dict[key] = [
{"value": v, "unit": power_unit} if v != "N/A" else "N/A"
for v in value
]
else:
power_dict[key] = value
else:
power_dict[key] = self.helpers.unit_format(
self.logger, value, power_unit
)
values_dict["power"] = power_dict
if "clock" in current_platform_args:
if args.clock:
# Populate Skeleton output with N/A
clocks = {}
for clock_index in range(amdsmi_interface.AMDSMI_MAX_NUM_GFX_CLKS):
gfx_index = f"gfx_{clock_index}"
clocks[gfx_index] = {
"clk": "N/A",
"min_clk": "N/A",
"max_clk": "N/A",
"clk_locked": "N/A",
"deep_sleep": "N/A",
}
clocks["mem_0"] = {
"clk": "N/A",
"min_clk": "N/A",
"max_clk": "N/A",
"clk_locked": "N/A",
"deep_sleep": "N/A",
}
for clock_index in range(amdsmi_interface.AMDSMI_MAX_NUM_CLKS):
vclk_index = f"vclk_{clock_index}"
clocks[vclk_index] = {
"clk": "N/A",
"min_clk": "N/A",
"max_clk": "N/A",
"clk_locked": "N/A",
"deep_sleep": "N/A",
}
for clock_index in range(amdsmi_interface.AMDSMI_MAX_NUM_CLKS):
dclk_index = f"dclk_{clock_index}"
clocks[dclk_index] = {
"clk": "N/A",
"min_clk": "N/A",
"max_clk": "N/A",
"clk_locked": "N/A",
"deep_sleep": "N/A",
}
clocks["fclk_0"] = {
"clk": "N/A",
"min_clk": "N/A",
"max_clk": "N/A",
"clk_locked": "N/A",
"deep_sleep": "N/A",
}
clocks["socclk_0"] = {
"clk": "N/A",
"min_clk": "N/A",
"max_clk": "N/A",
"clk_locked": "N/A",
"deep_sleep": "N/A",
}
clocks["uclk_aid"] = "N/A"
clocks["socclks_mid"] = "N/A"
clock_unit = "MHz"
# Use partition-scoped data when partition metrics were fetched.
partition_metrics_used = False
if gpu_partition_metrics is not None:
try:
partition_metrics_used = True
# Use partition metrics for GFX/VCLK/DCLK/SOCCLK instead of socket metrics
# Populate GFX clocks from partition metrics
current_gfx_clocks = gpu_partition_metrics.get("current_gfxclks", "N/A")
if current_gfx_clocks != "N/A" and isinstance(current_gfx_clocks, list):
for clk_idx, clk in enumerate(current_gfx_clocks):
if clk != "N/A":
gfx_index = f"gfx_{clk_idx}"
if gfx_index in clocks:
clocks[gfx_index]["clk"] = self.helpers.unit_format(
self.logger, clk, clock_unit
)
# GFX clock lock status from partition metrics; annotate only
# slots that carry a clock value so an empty skeleton entry never
# gets a lock state. A missing key is unknown ("N/A"); 0 is a valid
# "all unlocked" reading.
gfxclk_lock_status = gpu_partition_metrics.get("gfxclk_lock_status", "N/A")
if gfxclk_lock_status != "N/A":
for idx in range(amdsmi_interface.AMDSMI_MAX_NUM_GFX_CLKS):
gfx_index = f"gfx_{idx}"
if gfx_index in clocks and clocks[gfx_index]["clk"] != "N/A":
if (gfxclk_lock_status >> idx) & 1:
clocks[gfx_index]["clk_locked"] = "ENABLED"
else:
clocks[gfx_index]["clk_locked"] = "DISABLED"
# Populate VCLK from partition metrics
current_vclk_clocks = gpu_partition_metrics.get("current_vclk0s", "N/A")
if current_vclk_clocks != "N/A" and isinstance(current_vclk_clocks, list):
for clock_index, current_vclk_clock in enumerate(current_vclk_clocks):
if current_vclk_clock != "N/A":
vclk_index = f"vclk_{clock_index}"
if vclk_index in clocks:
clocks[vclk_index]["clk"] = self.helpers.unit_format(
self.logger, current_vclk_clock, clock_unit
)
# Populate DCLK from partition metrics
current_dclk_clocks = gpu_partition_metrics.get("current_dclk0s", "N/A")
if current_dclk_clocks != "N/A" and isinstance(current_dclk_clocks, list):
for clock_index, current_dclk_clock in enumerate(current_dclk_clocks):
if current_dclk_clock != "N/A":
dclk_index = f"dclk_{clock_index}"
if dclk_index in clocks:
clocks[dclk_index]["clk"] = self.helpers.unit_format(
self.logger, current_dclk_clock, clock_unit
)
# Populate SOCCLK from partition metrics (AID level)
current_socclks = gpu_partition_metrics.get("current_socclks", "N/A")
if current_socclks != "N/A" and isinstance(current_socclks, list):
for idx, socclk in enumerate(current_socclks):
if socclk != "N/A":
clocks["socclk_0"]["clk"] = self.helpers.unit_format(
self.logger, socclk, clock_unit
)
break # Use first valid value
# Populate MID SOC clocks from partition metrics
current_socclks_mid = gpu_partition_metrics.get(
"current_socclks_mid", "N/A"
)
if current_socclks_mid != "N/A" and isinstance(current_socclks_mid, list):
clocks["socclks_mid"] = {
f"mid_{index}": self.helpers.unit_format(
self.logger, clk, clock_unit
)
for index, clk in enumerate(current_socclks_mid)
if clk != "N/A"
}
# Add AID-level clock data (VCLK, DCLK, SOCCLK per AID)
# Iterate every VCLK position; per-field "N/A" guards skip holes,
# so counting only non-"N/A" entries would drop trailing valid AIDs
num_aids = 0
if isinstance(current_vclk_clocks, list) and current_vclk_clocks != "N/A":
num_aids = len(current_vclk_clocks)
# Get clock limits for AID clocks
try:
vclk0_limits = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.VCLK0
)
dclk0_limits = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.DCLK0
)
soc_limits = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.SOC
)
except amdsmi_exception.AmdSmiLibraryException:
vclk0_limits = None
dclk0_limits = None
soc_limits = None
for aid_idx in range(num_aids):
aid_key = f"aid_{aid_idx}"
aid_clocks = {}
# VCLK for this AID
if (
aid_idx < len(current_vclk_clocks)
and current_vclk_clocks[aid_idx] != "N/A"
):
aid_clocks["vclk"] = self.helpers.unit_format(
self.logger, current_vclk_clocks[aid_idx], clock_unit
)
if vclk0_limits:
aid_clocks["vclk_min_limit"] = self.helpers.unit_format(
self.logger, vclk0_limits["min_clk"], clock_unit
)
aid_clocks["vclk_max_limit"] = self.helpers.unit_format(
self.logger, vclk0_limits["max_clk"], clock_unit
)
# DCLK for this AID
if isinstance(current_dclk_clocks, list) and aid_idx < len(
current_dclk_clocks
):
if current_dclk_clocks[aid_idx] != "N/A":
aid_clocks["dclk"] = self.helpers.unit_format(
self.logger, current_dclk_clocks[aid_idx], clock_unit
)
if dclk0_limits:
aid_clocks["dclk_min_limit"] = self.helpers.unit_format(
self.logger, dclk0_limits["min_clk"], clock_unit
)
aid_clocks["dclk_max_limit"] = self.helpers.unit_format(
self.logger, dclk0_limits["max_clk"], clock_unit
)
# SOCCLK for this AID
if isinstance(current_socclks, list) and aid_idx < len(current_socclks):
if current_socclks[aid_idx] != "N/A":
aid_clocks["socclk"] = self.helpers.unit_format(
self.logger, current_socclks[aid_idx], clock_unit
)
if soc_limits:
aid_clocks["socclk_min_limit"] = self.helpers.unit_format(
self.logger, soc_limits["min_clk"], clock_unit
)
aid_clocks["socclk_max_limit"] = self.helpers.unit_format(
self.logger, soc_limits["max_clk"], clock_unit
)
if aid_clocks:
clocks[aid_key] = aid_clocks
# Add XCP-level GFX clock data (gfx_clk per XCP with limits and lock status)
# Determine number of XCPs
num_xcps = 0
if isinstance(current_gfx_clocks, list) and current_gfx_clocks != "N/A":
num_xcps = len(current_gfx_clocks)
# Get GFX clock limits
try:
gfx_limits = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.GFX
)
except amdsmi_exception.AmdSmiLibraryException:
gfx_limits = None
for xcp_idx in range(num_xcps):
xcp_key = f"xcp_{xcp_idx}"
xcp_clocks = {}
# GFX clock for this XCP (could be single value or array of engine clocks)
if xcp_idx < len(current_gfx_clocks):
gfx_clk_data = current_gfx_clocks[xcp_idx]
if gfx_clk_data != "N/A":
if isinstance(gfx_clk_data, list):
# Array of engine clocks - take first valid value
for clk in gfx_clk_data:
if clk != "N/A":
xcp_clocks["gfx_clk"] = self.helpers.unit_format(
self.logger, clk, clock_unit
)
break
else:
# Single clock value
xcp_clocks["gfx_clk"] = self.helpers.unit_format(
self.logger, gfx_clk_data, clock_unit
)
# Only annotate limits/lock for an XCP that reports a real gfx
# clock; otherwise the entry would carry limits with no value
if "gfx_clk" in xcp_clocks:
# GFX min/max limits (same for all XCPs)
if gfx_limits:
xcp_clocks["gfx_min_clk"] = self.helpers.unit_format(
self.logger, gfx_limits["min_clk"], clock_unit
)
xcp_clocks["gfx_max_clk"] = self.helpers.unit_format(
self.logger, gfx_limits["max_clk"], clock_unit
)
# GFX clock lock status for this XCP's gfx domain; missing
# status is unknown ("N/A"), 0 is a valid "unlocked" reading
if gfxclk_lock_status != "N/A":
is_locked = (gfxclk_lock_status >> xcp_idx) & 1
xcp_clocks["gfx_clk_locked"] = (
"ENABLED" if is_locked else "DISABLED"
)
else:
xcp_clocks["gfx_clk_locked"] = "N/A"
if xcp_clocks:
clocks[xcp_key] = xcp_clocks
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get partition clock metrics for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
partition_metrics_used = False
# Populate clock values from gpu_metrics_info (socket-level or fallback)
if not partition_metrics_used:
# Populate GFX clock values
try:
current_gfx_clocks = gpu_metric["current_gfxclks"]
if current_gfx_clocks != "N/A":
for clock_index, current_gfx_clock in enumerate(current_gfx_clocks):
# If the current clock is N/A then nothing else applies
if current_gfx_clock == "N/A":
continue
gfx_index = f"gfx_{clock_index}"
clocks[gfx_index]["clk"] = self.helpers.unit_format(
self.logger, current_gfx_clock, clock_unit
)
# Populate clock locked status
if gpu_metric["gfxclk_lock_status"] != "N/A":
gfx_clock_lock_flag = (
1 << clock_index
) # This is the position of the clock lock flag
if gpu_metric["gfxclk_lock_status"] & gfx_clock_lock_flag:
clocks[gfx_index]["clk_locked"] = "ENABLED"
else:
clocks[gfx_index]["clk_locked"] = "DISABLED"
except Exception as e:
logging.debug("Failed to get current_gfxclks for gpu %s | %s", gpu_id, e)
# Populate MEM clock value
try:
current_mem_clock = gpu_metric["current_uclk"] # single value
if current_mem_clock != "N/A":
clocks["mem_0"]["clk"] = self.helpers.unit_format(
self.logger, current_mem_clock, clock_unit
)
except Exception as e:
logging.debug("Failed to get current_uclk for gpu %s | %s", gpu_id, e)
# Populate VCLK clock values
try:
current_vclk_clocks = gpu_metric["current_vclk0s"]
# If the current vclk clocks are not available, we cannot proceed further
if current_vclk_clocks != "N/A":
for clock_index, current_vclk_clock in enumerate(current_vclk_clocks):
# If the current clock is N/A then nothing else applies
if current_vclk_clock == "N/A":
continue
vclk_index = f"vclk_{clock_index}"
clocks[vclk_index]["clk"] = self.helpers.unit_format(
self.logger, current_vclk_clock, clock_unit
)
except Exception as e:
logging.debug("Failed to get current_vclk0s for gpu %s | %s", gpu_id, e)
# Populate DCLK clock values
try:
current_dclk_clocks = gpu_metric["current_dclk0s"]
# If the current dclk clocks are not available, we cannot proceed further
if current_dclk_clocks != "N/A":
for clock_index, current_dclk_clock in enumerate(current_dclk_clocks):
# If the current clock is N/A then nothing else applies
if current_dclk_clock == "N/A":
continue
dclk_index = f"dclk_{clock_index}"
clocks[dclk_index]["clk"] = self.helpers.unit_format(
self.logger, current_dclk_clock, clock_unit
)
except Exception as e:
logging.debug("Failed to get current_dclk0s for gpu %s | %s", gpu_id, e)
# Populate FCLK clock value; fclk not present in gpu_metrics so use amdsmi_get_clk_freq
try:
frequency_dict = amdsmi_interface.amdsmi_get_clk_freq(
args.gpu, amdsmi_interface.AmdSmiClkType.DF
)
# The C library reports current = (uint32_t)-1 when the
# kernel exposes pp_dpm_fclk without a '*' current-level
# marker (e.g. SMU power-gated DF on gfx1151 APUs at idle).
# Treat that as "no current frequency" so we don't index
# out of range.
current_fclk_index = frequency_dict["current"]
if current_fclk_index == 0xFFFFFFFF or current_fclk_index >= len(
frequency_dict["frequency"]
):
raise IndexError("no current fclk level reported by kernel")
current_fclk_clock = frequency_dict["frequency"][current_fclk_index]
current_fclk_clock = self.helpers.convert_SI_unit(
current_fclk_clock, self.helpers.SI_Unit.MICRO
)
clocks["fclk_0"]["clk"] = self.helpers.unit_format(
self.logger, current_fclk_clock, clock_unit
)
except (KeyError, IndexError, amdsmi_exception.AmdSmiLibraryException) as e:
logging.debug("Failed to get fclk info for gpu %s | %s", gpu_id, e)
# Populate SOCCLK clock value
try:
current_socclk_clock = gpu_metric["current_socclk"]
# If the current socclk clocks are not available, we cannot proceed further
if current_socclk_clock != "N/A":
clocks["socclk_0"]["clk"] = self.helpers.unit_format(
self.logger, current_socclk_clock, clock_unit
)
except KeyError as e:
logging.debug("Failed to get current_socclk for gpu %s | %s", gpu_id, e)
try:
current_uclk_aid = gpu_metric.get("current_uclk_aid", "N/A")
if current_uclk_aid != "N/A":
clocks["uclk_aid"] = {
f"aid_{index}": self.helpers.unit_format(
self.logger, clk, clock_unit
)
if clk != "N/A"
else "N/A"
for index, clk in enumerate(current_uclk_aid)
}
except Exception as e:
logging.debug("Failed to get current_uclk_aid for gpu %s | %s", gpu_id, e)
try:
current_socclks_mid = gpu_metric.get("current_socclks_mid", "N/A")
if current_socclks_mid != "N/A":
clocks["socclks_mid"] = {
f"mid_{index}": self.helpers.unit_format(
self.logger, clk, clock_unit
)
if clk != "N/A"
else "N/A"
for index, clk in enumerate(current_socclks_mid)
}
except Exception as e:
logging.debug(
"Failed to get current_socclks_mid for gpu %s | %s", gpu_id, e
)
# Populate the max and min clock values from sysfs.
# Min and Max values are per clock type, not per clock engine.
# Populate the deep sleep value from amdsmi_get_clock_info
# GFX min and max clocks
try:
gfx_clock_info_dict = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.GFX
)
for clock_index in range(amdsmi_interface.AMDSMI_MAX_NUM_GFX_CLKS):
gfx_index = f"gfx_{clock_index}"
if clocks[gfx_index]["clk"] == "N/A":
# if the current clock is N/A then we shouldn't populate the max and min values
continue
clocks[gfx_index]["min_clk"] = self.helpers.unit_format(
self.logger, gfx_clock_info_dict["min_clk"], clock_unit
)
clocks[gfx_index]["max_clk"] = self.helpers.unit_format(
self.logger, gfx_clock_info_dict["max_clk"], clock_unit
)
# Add the clk_deep_sleep
clocks[gfx_index]["deep_sleep"] = gfx_clock_info_dict["clk_deep_sleep"]
except (KeyError, amdsmi_exception.AmdSmiLibraryException) as e:
logging.debug("Failed to get gfx clock info for gpu %s | %s", gpu_id, e)
# MEM min and max clocks
try:
mem_clock_info_dict = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.MEM
)
# if the current clock is N/A then we shouldn't populate the max and min values
if clocks["mem_0"]["clk"] != "N/A":
clocks["mem_0"]["min_clk"] = self.helpers.unit_format(
self.logger, mem_clock_info_dict["min_clk"], clock_unit
)
clocks["mem_0"]["max_clk"] = self.helpers.unit_format(
self.logger, mem_clock_info_dict["max_clk"], clock_unit
)
# Add the clk_deep_sleep
clocks["mem_0"]["deep_sleep"] = mem_clock_info_dict["clk_deep_sleep"]
except (KeyError, amdsmi_exception.AmdSmiLibraryException) as e:
logging.debug("Failed to get mem clock info for gpu %s | %s", gpu_id, e)
# VCLK min and max clocks
try:
# Retrieve clock information for VCLK0 (Video Clock 0)
vclk_clock_info_dict = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.VCLK0
)
# Iterate through the maximum number of VCLK clocks supported
for index in range(amdsmi_interface.AMDSMI_MAX_NUM_CLKS):
vclk_index = f"vclk_{index}" # Construct the index key for the clock
# Check if the current clock value is not "N/A"
if clocks[vclk_index]["clk"] != "N/A":
# Format and assign the minimum clock value for the current VCLK
clocks[vclk_index]["min_clk"] = self.helpers.unit_format(
self.logger, vclk_clock_info_dict["min_clk"], clock_unit
)
# Format and assign the maximum clock value for the current VCLK
clocks[vclk_index]["max_clk"] = self.helpers.unit_format(
self.logger, vclk_clock_info_dict["max_clk"], clock_unit
)
# Add the clk_deep_sleep
clocks[vclk_index]["deep_sleep"] = vclk_clock_info_dict[
"clk_deep_sleep"
]
except (KeyError, amdsmi_exception.AmdSmiLibraryException) as e:
# Log a debug message if retrieving VCLK clock information fails
logging.debug("Failed to get vclk clock info for gpu %s | %s", gpu_id, e)
# DCLK min and max clocks
try:
# Retrieve clock information for DCLK0 (Display Clock 0)
dclk_clock_info_dict = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.DCLK0
)
# Iterate through the maximum number of DCLK clocks supported
for index in range(amdsmi_interface.AMDSMI_MAX_NUM_CLKS):
dclk_index = f"dclk_{index}" # Construct the index key for the clock
# Check if the current clock value is not "N/A"
if clocks[dclk_index]["clk"] != "N/A":
# Format and assign the minimum clock value for the current DCLK
clocks[dclk_index]["min_clk"] = self.helpers.unit_format(
self.logger, dclk_clock_info_dict["min_clk"], clock_unit
)
# Format and assign the maximum clock value for the current DCLK
clocks[dclk_index]["max_clk"] = self.helpers.unit_format(
self.logger, dclk_clock_info_dict["max_clk"], clock_unit
)
# Add the clk_deep_sleep
clocks[dclk_index]["deep_sleep"] = dclk_clock_info_dict[
"clk_deep_sleep"
]
except (KeyError, amdsmi_exception.AmdSmiLibraryException) as e:
logging.debug("Failed to get dclk clock info for gpu %s | %s", gpu_id, e)
# FCLK min and max clocks
try:
fclk_clk_info_dict = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.DF
)
# if the current clock is N/A then we shouldn't populate the max and min values
if clocks["fclk_0"]["clk"] != "N/A":
clocks["fclk_0"]["min_clk"] = self.helpers.unit_format(
self.logger, fclk_clk_info_dict["min_clk"], clock_unit
)
clocks["fclk_0"]["max_clk"] = self.helpers.unit_format(
self.logger, fclk_clk_info_dict["max_clk"], clock_unit
)
# Add the clk_deep_sleep
clocks["fclk_0"]["deep_sleep"] = fclk_clk_info_dict["clk_deep_sleep"]
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get fclk info for gpu %s | %s", gpu_id, e.get_error_info()
)
# SOCCLK min and max clocks
try:
socclk_clk_info_dict = amdsmi_interface.amdsmi_get_clock_info(
args.gpu, amdsmi_interface.AmdSmiClkType.SOC
)
# if the current clock is N/A then we shouldn't populate the max and min values
if clocks["socclk_0"]["clk"] != "N/A":
clocks["socclk_0"]["min_clk"] = self.helpers.unit_format(
self.logger, socclk_clk_info_dict["min_clk"], clock_unit
)
clocks["socclk_0"]["max_clk"] = self.helpers.unit_format(
self.logger, socclk_clk_info_dict["max_clk"], clock_unit
)
# Add the clk_deep_sleep
clocks["socclk_0"]["deep_sleep"] = socclk_clk_info_dict["clk_deep_sleep"]
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get socclk info for gpu %s | %s", gpu_id, e.get_error_info()
)
# Iterate over each clock and its data to determine if deep sleep is enabled
# based on the comparison between the current clock value and the minimum clock value.
for clock, clock_data in clocks.items():
clk_value = 0
min_clk_value = 0
try:
clk = clock_data["clk"]
min_clk = clock_data["min_clk"]
if clk == "N/A" or min_clk == "N/A":
continue
# Extract numeric value if clk/min_clk is a dict, else use as is
if isinstance(clk, dict):
clk_value = int(clk.get("value", 0))
else:
if isinstance(clk, str):
clk_value = int(str(clk).split()[0])
else:
clk_value = int(clk)
if isinstance(min_clk, dict):
min_clk_value = int(min_clk.get("value", 0))
else:
if isinstance(min_clk, str):
min_clk_value = int(str(min_clk).split()[0])
else:
min_clk_value = int(min_clk)
# If the clk value is less than the min_clk value, then deep sleep is enabled
if clk_value < min_clk_value:
clock_data["deep_sleep"] = "ENABLED"
else:
clock_data["deep_sleep"] = "DISABLED"
except Exception as e:
logging.debug("Failed to get deep sleep status for gpu %s | %s", gpu_id, e)
# APU-specific clock data
if show_apu:
clock_unit = "MHz"
apu_clock_fields = {
"apu_current_coreclk": gpu_metric.get("apu_metrics.current_coreclk", "N/A"),
"apu_current_l3clk": gpu_metric.get("apu_metrics.current_l3clk", "N/A"),
"apu_current_core_maxfreq": gpu_metric.get(
"apu_metrics.current_core_maxfreq", "N/A"
),
"apu_current_gfx_maxfreq": gpu_metric.get(
"apu_metrics.current_gfx_maxfreq", "N/A"
),
"apu_average_gfxclk_frequency": gpu_metric.get(
"apu_metrics.average_gfxclk_frequency", "N/A"
),
"apu_average_socclk_frequency": gpu_metric.get(
"apu_metrics.average_socclk_frequency", "N/A"
),
"apu_average_uclk_frequency": gpu_metric.get(
"apu_metrics.average_uclk_frequency", "N/A"
),
"apu_average_fclk_frequency": gpu_metric.get(
"apu_metrics.average_fclk_frequency", "N/A"
),
"apu_average_vclk_frequency": gpu_metric.get(
"apu_metrics.average_vclk_frequency", "N/A"
),
"apu_average_vpeclk_frequency": gpu_metric.get(
"apu_metrics.average_vpeclk_frequency", "N/A"
),
"apu_average_ipuclk_frequency": gpu_metric.get(
"apu_metrics.average_ipuclk_frequency", "N/A"
),
"apu_average_mpipu_frequency": gpu_metric.get(
"apu_metrics.average_mpipu_frequency", "N/A"
),
}
for key, value in apu_clock_fields.items():
if value != "N/A":
if isinstance(value, list):
if self.logger.is_human_readable_format():
formatted = [
f"{v} {clock_unit}" if v != "N/A" else "N/A" for v in value
]
clocks[key] = "[" + ", ".join(formatted) + "]"
elif self.logger.is_json_format():
clocks[key] = [
{"value": v, "unit": clock_unit} if v != "N/A" else "N/A"
for v in value
]
else:
clocks[key] = value
else:
clocks[key] = self.helpers.unit_format(
self.logger, value, clock_unit
)
values_dict["clock"] = clocks
if "temperature" in current_platform_args:
if args.temperature:
try:
temperature_edge_current = amdsmi_interface.amdsmi_get_temp_metric(
args.gpu,
amdsmi_interface.AmdSmiTemperatureType.EDGE,
amdsmi_interface.AmdSmiTemperatureMetric.CURRENT,
)
except amdsmi_exception.AmdSmiLibraryException as e:
temperature_edge_current = "N/A"
logging.debug(
"Failed to get current edge temperature for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
try:
temperature_edge_limit = amdsmi_interface.amdsmi_get_temp_metric(
args.gpu,
amdsmi_interface.AmdSmiTemperatureType.EDGE,
amdsmi_interface.AmdSmiTemperatureMetric.CRITICAL,
)
except amdsmi_exception.AmdSmiLibraryException as e:
temperature_edge_limit = "N/A"
logging.debug(
"Failed to get edge temperature limit for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
# If edge limit is reporting 0 then set the current edge temp to N/A
if temperature_edge_limit == 0:
temperature_edge_current = "N/A"
try:
temperature_hotspot_current = amdsmi_interface.amdsmi_get_temp_metric(
args.gpu,
amdsmi_interface.AmdSmiTemperatureType.HOTSPOT,
amdsmi_interface.AmdSmiTemperatureMetric.CURRENT,
)
except amdsmi_exception.AmdSmiLibraryException as e:
temperature_hotspot_current = "N/A"
logging.debug(
"Failed to get current hotspot temperature for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
try:
temperature_vram_current = amdsmi_interface.amdsmi_get_temp_metric(
args.gpu,
amdsmi_interface.AmdSmiTemperatureType.VRAM,
amdsmi_interface.AmdSmiTemperatureMetric.CURRENT,
)
except amdsmi_exception.AmdSmiLibraryException as e:
temperature_vram_current = "N/A"
logging.debug(
"Failed to get current vram temperature for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
# Use partition-scoped data when partition metrics were fetched.
if gpu_partition_metrics is not None:
temperatures = {
"edge": temperature_edge_current,
"hotspot": temperature_hotspot_current,
"mem": temperature_vram_current,
"hbm_stacks": "N/A",
"mid": gpu_partition_metrics.get("temperature_mid", "N/A"),
"aid": "N/A", # AID temps not in partition metrics
"xcd": "N/A",
}
# MID temperatures from partition metrics
if temperatures["mid"] != "N/A":
temperatures["mid"] = list(temperatures["mid"])
# XCP/XCD temperatures from partition metrics
xcp_temp_xcd = gpu_partition_metrics.get("xcp_stats.temperature_xcd", "N/A")
if xcp_temp_xcd != "N/A" and isinstance(xcp_temp_xcd, list):
temperatures["xcd"] = {
f"xcp_{idx}": xcp_temp_xcd[idx] for idx in range(len(xcp_temp_xcd))
}
else:
# Socket-level metrics (existing behavior)
temperatures = {
"edge": temperature_edge_current,
"hotspot": temperature_hotspot_current,
"mem": temperature_vram_current,
"hbm_stacks": gpu_metric.get("temperature_hbm_stacks", "N/A"),
"mid": gpu_metric.get("temperature_mid", "N/A"),
"aid": gpu_metric.get("temperature_aid", "N/A"),
"xcd": "N/A",
}
if temperatures["hbm_stacks"] != "N/A":
temperatures["hbm_stacks"] = list(temperatures["hbm_stacks"])
if temperatures["mid"] != "N/A":
temperatures["mid"] = list(temperatures["mid"])
if temperatures["aid"] != "N/A":
temperatures["aid"] = list(temperatures["aid"])
if num_partition != "N/A":
xcp_temp_xcd = gpu_metric.get("xcp_stats.temperature_xcd", "N/A")
if xcp_temp_xcd != "N/A":
available_partition = min(num_partition, len(xcp_temp_xcd))
temperatures["xcd"] = {
f"xcp_{current_xcp}": xcp_temp_xcd[current_xcp]
for current_xcp in range(available_partition)
}
temp_unit_human_readable = "\N{DEGREE SIGN}C"
temp_unit_json = "C"
for temperature_key, temperature_value in temperatures.items():
if isinstance(temperature_value, list):
if self.logger.is_human_readable_format():
formatted_values = [
f"{value} {temp_unit_human_readable}" if value != "N/A" else "N/A"
for value in temperature_value
]
temperatures[temperature_key] = "[" + ", ".join(formatted_values) + "]"
if self.logger.is_json_format():
temperatures[temperature_key] = [
{"value": value, "unit": temp_unit_json}
if value != "N/A"
else "N/A"
for value in temperature_value
]
elif isinstance(temperature_value, dict):
for key, value in temperature_value.items():
if isinstance(value, list):
if self.logger.is_human_readable_format():
formatted_values = [
f"{item} {temp_unit_human_readable}"
if item != "N/A"
else "N/A"
for item in value
]
temperature_value[key] = "[" + ", ".join(formatted_values) + "]"
if self.logger.is_json_format():
temperature_value[key] = [
{"value": item, "unit": temp_unit_json}
if item != "N/A"
else "N/A"
for item in value
]
elif value != "N/A":
if self.logger.is_human_readable_format():
temperature_value[key] = f"{value} {temp_unit_human_readable}"
if self.logger.is_json_format():
temperature_value[key] = {
"value": value,
"unit": temp_unit_json,
}
else:
if temperature_value == "N/A":
continue
if self.logger.is_human_readable_format():
temperatures[temperature_key] = (
f"{temperature_value} {temp_unit_human_readable}"
)
if self.logger.is_json_format():
temperatures[temperature_key] = {
"value": temperature_value,
"unit": temp_unit_json,
}
# APU-specific temperature data
if show_apu:
temp_unit_human_readable = "\N{DEGREE SIGN}C"
temp_unit_json = "C"
apu_temp_fields = {
"apu_temperature_gfx": gpu_metric.get("apu_metrics.temperature_gfx", "N/A"),
"apu_temperature_soc": gpu_metric.get("apu_metrics.temperature_soc", "N/A"),
"apu_temperature_core": gpu_metric.get(
"apu_metrics.temperature_core", "N/A"
),
"apu_temperature_l3": gpu_metric.get("apu_metrics.temperature_l3", "N/A"),
"apu_temperature_skin": gpu_metric.get(
"apu_metrics.temperature_skin", "N/A"
),
"apu_average_temperature_gfx": gpu_metric.get(
"apu_metrics.average_temperature_gfx", "N/A"
),
"apu_average_temperature_soc": gpu_metric.get(
"apu_metrics.average_temperature_soc", "N/A"
),
"apu_average_temperature_core": gpu_metric.get(
"apu_metrics.average_temperature_core", "N/A"
),
"apu_average_temperature_l3": gpu_metric.get(
"apu_metrics.average_temperature_l3", "N/A"
),
}
for key, value in apu_temp_fields.items():
if value != "N/A":
if isinstance(value, list):
if self.logger.is_human_readable_format():
formatted = [
f"{v} {temp_unit_human_readable}" if v != "N/A" else "N/A"
for v in value
]
temperatures[key] = "[" + ", ".join(formatted) + "]"
elif self.logger.is_json_format():
temperatures[key] = [
{"value": v, "unit": temp_unit_json}
if v != "N/A"
else "N/A"
for v in value
]
else:
temperatures[key] = value
else:
if self.logger.is_human_readable_format():
temperatures[key] = f"{value} {temp_unit_human_readable}"
elif self.logger.is_json_format():
temperatures[key] = {"value": value, "unit": temp_unit_json}
else:
temperatures[key] = value
values_dict["temperature"] = temperatures
# Since pcie bw may increase based on frequent metrics calls, we add it to the output here, but the populate the values first
if "pcie" in current_platform_args:
if args.pcie and not show_apu:
values_dict["pcie"] = pcie_dict
if "gpu_board" in current_platform_args:
if args.gpu_board:
gpu_board_temp_dict = self.helpers.get_gpu_board_temperatures(
args.gpu, gpu_id, self.logger
)
# if every value is N/A, then we don't want to display the values unless explicitly told to
# all args_list being True indicates that this gpu_board is not explicitly called itself
args_list = [getattr(args, arg) for arg in current_platform_args]
if all(value == "N/A" for value in gpu_board_temp_dict.values()) and all(
arg == True for arg in args_list
):
gpu_board_temp_dict = {}
if gpu_board_temp_dict:
values_dict["gpu_board"] = {"temperature": gpu_board_temp_dict}
if "base_board" in current_platform_args:
if args.base_board:
base_board_temp_dict = self.helpers.get_base_board_temperatures(
args.gpu, gpu_id, self.logger
)
# if every value is N/A, then we don't want to display the values unless explicitly told to
# all args_list being True indicates that this base_board is not explicitly called itself
args_list = [getattr(args, arg) for arg in current_platform_args]
if all(value == "N/A" for value in base_board_temp_dict.values()) and all(
arg == True for arg in args_list
):
base_board_temp_dict = {}
if base_board_temp_dict:
values_dict["base_board"] = {"temperature": base_board_temp_dict}
if "ecc" in current_platform_args:
if args.ecc:
ecc_count = {}
try:
ecc_count = amdsmi_interface.amdsmi_get_gpu_total_ecc_count(args.gpu)
ecc_count["total_correctable_count"] = ecc_count.pop("correctable_count")
ecc_count["total_uncorrectable_count"] = ecc_count.pop("uncorrectable_count")
ecc_count["total_deferred_count"] = ecc_count.pop("deferred_count")
except amdsmi_exception.AmdSmiLibraryException as e:
ecc_count["total_correctable_count"] = "N/A"
ecc_count["total_uncorrectable_count"] = "N/A"
ecc_count["cache_correctable_count"] = "N/A"
ecc_count["cache_uncorrectable_count"] = "N/A"
logging.debug(
"Failed to get total ecc count for gpu %s | %s", gpu_id, e.get_error_info()
)
if ecc_count["total_correctable_count"] != "N/A":
# Get the UMC error count for getting total cache correctable errors
umc_block = amdsmi_interface.AmdSmiGpuBlock["UMC"]
try:
umc_count = amdsmi_interface.amdsmi_get_gpu_ecc_count(args.gpu, umc_block)
ecc_count["cache_correctable_count"] = (
ecc_count["total_correctable_count"] - umc_count["correctable_count"]
)
ecc_count["cache_uncorrectable_count"] = (
ecc_count["total_uncorrectable_count"]
- umc_count["uncorrectable_count"]
)
except amdsmi_exception.AmdSmiLibraryException as e:
ecc_count["cache_correctable_count"] = "N/A"
ecc_count["cache_uncorrectable_count"] = "N/A"
logging.debug(
"Failed to get cache ecc count for gpu %s at block %s | %s",
gpu_id,
umc_block,
e.get_error_info(),
)
values_dict["ecc"] = ecc_count
if "ecc_blocks" in current_platform_args:
if args.ecc_blocks and not show_apu:
ecc_dict = {}
sysfs_blocks = ["UMC", "SDMA", "GFX", "MMHUB", "PCIE_BIF", "HDP", "XGMI_WAFL"]
try:
ras_states = amdsmi_interface.amdsmi_get_gpu_ras_block_features_enabled(
args.gpu
)
for state in ras_states:
# Only add enabled blocks that are also in sysfs
if state["status"] == amdsmi_interface.AmdSmiRasErrState.ENABLED.name:
gpu_block = amdsmi_interface.AmdSmiGpuBlock[state["block"]]
# if the blocks are uncountable do not add them at all.
if gpu_block.name in sysfs_blocks:
try:
ecc_count = amdsmi_interface.amdsmi_get_gpu_ecc_count(
args.gpu, gpu_block
)
ecc_dict[state["block"]] = {
"correctable_count": ecc_count["correctable_count"],
"uncorrectable_count": ecc_count["uncorrectable_count"],
"deferred_count": ecc_count["deferred_count"],
}
except amdsmi_exception.AmdSmiLibraryException as e:
ecc_dict[state["block"]] = {
"correctable_count": "N/A",
"uncorrectable_count": "N/A",
"deferred_count": "N/A",
}
logging.debug(
"Failed to get ecc count for gpu %s at block %s | %s",
gpu_id,
gpu_block,
e.get_error_info(),
)
values_dict["ecc_blocks"] = ecc_dict
except amdsmi_exception.AmdSmiLibraryException as e:
values_dict["ecc_blocks"] = "N/A"
logging.debug(
"Failed to get ecc block features for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
if "fan" in current_platform_args:
if args.fan and not show_apu:
fan_dict = {"speed": "N/A", "max": "N/A", "rpm": "N/A", "usage": "N/A"}
try:
fan_speed = amdsmi_interface.amdsmi_get_gpu_fan_speed(args.gpu, 0)
fan_dict["speed"] = fan_speed
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get fan speed for gpu %s | %s", args.gpu, e.get_error_info()
)
try:
fan_max = amdsmi_interface.amdsmi_get_gpu_fan_speed_max(args.gpu, 0)
fan_usage = "N/A"
if fan_max > 0 and fan_dict["speed"] != "N/A":
fan_usage = round((float(fan_speed) / float(fan_max)) * 100, 2)
fan_usage_unit = "%"
if self.logger.is_human_readable_format():
fan_usage = f"{fan_usage} {fan_usage_unit}"
if self.logger.is_json_format():
fan_usage = {"value": fan_usage, "unit": fan_usage_unit}
fan_dict["max"] = fan_max
fan_dict["usage"] = fan_usage
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get fan max speed for gpu %s | %s", args.gpu, e.get_error_info()
)
try:
fan_rpm = amdsmi_interface.amdsmi_get_gpu_fan_rpms(args.gpu, 0)
fan_dict["rpm"] = fan_rpm
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get fan rpms for gpu %s | %s", args.gpu, e.get_error_info()
)
values_dict["fan"] = fan_dict
elif args.fan and show_apu:
# fan_pwm reported as a duty-cycle percentage
apu_fan_pwm = gpu_metric.get("apu_metrics.fan_pwm", "N/A")
if apu_fan_pwm != "N/A":
values_dict["fan"] = {
"apu_fan_pwm": self.helpers.unit_format(self.logger, apu_fan_pwm, "%")
}
if "voltage_curve" in current_platform_args:
if args.voltage_curve and not show_apu:
# Populate N/A values per voltage point
voltage_point_dict = {}
for point in range(amdsmi_interface.AMDSMI_NUM_VOLTAGE_CURVE_POINTS):
voltage_point_dict[f"point_{point}_frequency"] = "N/A"
voltage_point_dict[f"point_{point}_voltage"] = "N/A"
try:
od_volt = amdsmi_interface.amdsmi_get_gpu_od_volt_info(args.gpu)
logging.debug(f"OD Voltage info: {od_volt}")
except amdsmi_exception.AmdSmiLibraryException as e:
od_volt = "N/A" # Value not used, but needs to not be a dict
logging.debug(
"Failed to get voltage curve for gpu %s | %s", gpu_id, e.get_error_info()
)
# Populate voltage point values
for point in range(amdsmi_interface.AMDSMI_NUM_VOLTAGE_CURVE_POINTS):
if isinstance(od_volt, dict):
logging.debug(
f"point_{point} frequency: {od_volt['curve.vc_points'][point]['frequency']}"
)
logging.debug(
f"point_{point} voltage: {od_volt['curve.vc_points'][point]['voltage']}"
)
frequency = int(od_volt["curve.vc_points"][point]["frequency"] / 1000000)
voltage = int(od_volt["curve.vc_points"][point]["voltage"])
else:
frequency = "N/A"
voltage = "N/A"
if frequency == 0:
frequency = "N/A"
if voltage == 0:
voltage = "N/A"
if frequency != "N/A":
frequency = self.helpers.unit_format(self.logger, frequency, "Mhz")
if voltage != "N/A":
voltage = self.helpers.unit_format(self.logger, voltage, "mV")
voltage_point_dict[f"point_{point}_frequency"] = frequency
voltage_point_dict[f"point_{point}_voltage"] = voltage
values_dict["voltage_curve"] = voltage_point_dict
if "overdrive" in current_platform_args:
if args.overdrive and not show_apu:
try:
overdrive_level = amdsmi_interface.amdsmi_get_gpu_overdrive_level(args.gpu)
od_unit = "%"
values_dict["overdrive"] = self.helpers.unit_format(
self.logger, overdrive_level, od_unit
)
except amdsmi_exception.AmdSmiLibraryException as e:
values_dict["overdrive"] = "N/A"
logging.debug(
"Failed to get gpu overdrive level for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
try:
mem_overdrive_level = amdsmi_interface.amdsmi_get_gpu_mem_overdrive_level(
args.gpu
)
od_unit = "%"
values_dict["mem_overdrive"] = self.helpers.unit_format(
self.logger, mem_overdrive_level, od_unit
)
except amdsmi_exception.AmdSmiLibraryException as e:
values_dict["mem_overdrive"] = "N/A"
logging.debug(
"Failed to get mem overdrive level for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
if "perf_level" in current_platform_args:
if args.perf_level:
try:
perf_level = amdsmi_interface.amdsmi_get_gpu_perf_level(args.gpu)
values_dict["perf_level"] = perf_level
except amdsmi_exception.AmdSmiLibraryException as e:
values_dict["perf_level"] = "N/A"
logging.debug(
"Failed to get perf level for gpu %s | %s", gpu_id, e.get_error_info()
)
if "xgmi_err" in current_platform_args:
if args.xgmi_err and not show_apu:
try:
xgmi_err_status = amdsmi_interface.amdsmi_gpu_xgmi_error_status(args.gpu)
values_dict["xgmi_err"] = (
amdsmi_interface.amdsmi_wrapper.amdsmi_xgmi_status_t__enumvalues[
xgmi_err_status
]
)
except amdsmi_exception.AmdSmiLibraryException as e:
values_dict["xgmi_err"] = "N/A"
logging.debug(
"Failed to get xgmi error status for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
if "voltage" in current_platform_args:
if args.voltage:
voltage_dict = {}
all_voltage = {"vddboard": amdsmi_interface.AmdSmiVoltageType.VDDBOARD}
for volt_type, volt_metric in all_voltage.items():
try:
voltage = amdsmi_interface.amdsmi_get_gpu_volt_metric(
args.gpu, volt_metric, amdsmi_interface.AmdSmiVoltageMetric.CURRENT
)
if voltage == 0:
voltage = "N/A"
voltage_dict[volt_type] = self.helpers.unit_format(
self.logger, voltage, "mV"
)
except amdsmi_exception.AmdSmiLibraryException as e:
voltage_dict[volt_type] = "N/A"
logging.debug(
"Failed to get voltage for gpu %s | %s", gpu_id, e.get_error_info()
)
# APU-specific voltage/current data
if show_apu:
apu_volt_unit = "mV"
apu_curr_unit = "mA"
apu_voltage_fields = {
"apu_average_cpu_voltage": (
gpu_metric.get("apu_metrics.average_cpu_voltage", "N/A"),
apu_volt_unit,
),
"apu_average_soc_voltage": (
gpu_metric.get("apu_metrics.average_soc_voltage", "N/A"),
apu_volt_unit,
),
"apu_average_gfx_voltage": (
gpu_metric.get("apu_metrics.average_gfx_voltage", "N/A"),
apu_volt_unit,
),
"apu_average_cpu_current": (
gpu_metric.get("apu_metrics.average_cpu_current", "N/A"),
apu_curr_unit,
),
"apu_average_soc_current": (
gpu_metric.get("apu_metrics.average_soc_current", "N/A"),
apu_curr_unit,
),
"apu_average_gfx_current": (
gpu_metric.get("apu_metrics.average_gfx_current", "N/A"),
apu_curr_unit,
),
}
for key, (value, unit) in apu_voltage_fields.items():
if value != "N/A":
voltage_dict[key] = self.helpers.unit_format(self.logger, value, unit)
values_dict["voltage"] = voltage_dict
if "energy" in current_platform_args:
if args.energy and not show_apu:
try:
energy_dict = amdsmi_interface.amdsmi_get_energy_count(args.gpu)
energy = round(
energy_dict["energy_accumulator"] * energy_dict["counter_resolution"], 3
)
energy /= 1000000
energy = round(energy, 3)
energy_unit = "J"
if self.logger.is_human_readable_format():
energy = f"{energy} {energy_unit}"
if self.logger.is_json_format():
energy = {"value": energy, "unit": energy_unit}
values_dict["energy"] = {"total_energy_consumption": energy}
except amdsmi_interface.AmdSmiLibraryException as e:
values_dict["energy"] = "N/A"
logging.debug(
"Failed to get energy usage for gpu %s | %s", args.gpu, e.get_error_info()
)
if "mem_usage" in current_platform_args:
if args.mem_usage:
memory_usage = {
"total_vram": "N/A",
"used_vram": "N/A",
"free_vram": "N/A",
"total_visible_vram": "N/A",
"used_visible_vram": "N/A",
"free_visible_vram": "N/A",
"total_gtt": "N/A",
"used_gtt": "N/A",
"free_gtt": "N/A",
}
# Total VRAM
try:
total_vram = amdsmi_interface.amdsmi_get_gpu_memory_total(
args.gpu, amdsmi_interface.AmdSmiMemoryType.VRAM
)
memory_usage["total_vram"] = total_vram // (1024 * 1024)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get total VRAM memory for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
try:
total_visible_vram = amdsmi_interface.amdsmi_get_gpu_memory_total(
args.gpu, amdsmi_interface.AmdSmiMemoryType.VIS_VRAM
)
memory_usage["total_visible_vram"] = total_visible_vram // (1024 * 1024)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get total VIS VRAM memory for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
try:
total_gtt = amdsmi_interface.amdsmi_get_gpu_memory_total(
args.gpu, amdsmi_interface.AmdSmiMemoryType.GTT
)
memory_usage["total_gtt"] = total_gtt // (1024 * 1024)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get total GTT memory for gpu %s | %s", gpu_id, e.get_error_info()
)
# Used VRAM
try:
used_vram = amdsmi_interface.amdsmi_get_gpu_memory_usage(
args.gpu, amdsmi_interface.AmdSmiMemoryType.VRAM
)
memory_usage["used_vram"] = used_vram // (1024 * 1024)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get used VRAM memory for gpu %s | %s", gpu_id, e.get_error_info()
)
try:
used_visible_vram = amdsmi_interface.amdsmi_get_gpu_memory_usage(
args.gpu, amdsmi_interface.AmdSmiMemoryType.VIS_VRAM
)
memory_usage["used_visible_vram"] = used_visible_vram // (1024 * 1024)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get used VIS VRAM memory for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
try:
used_gtt = amdsmi_interface.amdsmi_get_gpu_memory_usage(
args.gpu, amdsmi_interface.AmdSmiMemoryType.GTT
)
memory_usage["used_gtt"] = used_gtt // (1024 * 1024)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug(
"Failed to get used GTT memory for gpu %s | %s", gpu_id, e.get_error_info()
)
# Free VRAM
if memory_usage["total_vram"] != "N/A" and memory_usage["used_vram"] != "N/A":
memory_usage["free_vram"] = (
memory_usage["total_vram"] - memory_usage["used_vram"]
)
if (
memory_usage["total_visible_vram"] != "N/A"
and memory_usage["used_visible_vram"] != "N/A"
):
memory_usage["free_visible_vram"] = (
memory_usage["total_visible_vram"] - memory_usage["used_visible_vram"]
)
if memory_usage["total_gtt"] != "N/A" and memory_usage["used_gtt"] != "N/A":
memory_usage["free_gtt"] = memory_usage["total_gtt"] - memory_usage["used_gtt"]
memory_unit = "MB"
for key, value in memory_usage.items():
if value != "N/A":
if self.logger.is_human_readable_format():
memory_usage[key] = f"{value} {memory_unit}"
if self.logger.is_json_format():
memory_usage[key] = {"value": value, "unit": memory_unit}
values_dict["mem_usage"] = memory_usage
if "throttle" in current_platform_args:
if args.throttle:
throttle_status = {
# Current values - counter/accumulated
"accumulation_counter": "N/A",
"prochot_accumulated": "N/A",
"ppt_accumulated": "N/A",
"socket_thermal_accumulated": "N/A",
"vr_thermal_accumulated": "N/A",
"hbm_thermal_accumulated": "N/A",
"gfx_clk_below_host_limit_accumulated": "N/A", # deprecated
"gfx_clk_below_host_limit_power_accumulated": "N/A",
"gfx_clk_below_host_limit_thermal_accumulated": "N/A",
"total_gfx_clk_below_host_limit_accumulated": "N/A",
"low_utilization_accumulated": "N/A",
# violation status values - active/not active
"prochot_violation_status": "N/A",
"ppt_violation_status": "N/A",
"socket_thermal_violation_status": "N/A",
"vr_thermal_violation_status": "N/A",
"hbm_thermal_violation_status": "N/A",
"gfx_clk_below_host_limit_violation_status": "N/A", # deprecated
"gfx_clk_below_host_limit_power_violation_status": "N/A",
"gfx_clk_below_host_limit_thermal_violation_status": "N/A",
"total_gfx_clk_below_host_limit_violation_status": "N/A",
"low_utilization_violation_status": "N/A",
# violation activity values - percent
"prochot_violation_activity": "N/A",
"ppt_violation_activity": "N/A",
"socket_thermal_violation_activity": "N/A",
"vr_thermal_violation_activity": "N/A",
"hbm_thermal_violation_activity": "N/A",
"gfx_clk_below_host_limit_violation_activity": "N/A", # deprecated
"gfx_clk_below_host_limit_power_violation_activity": "N/A",
"gfx_clk_below_host_limit_thermal_violation_activity": "N/A",
"total_gfx_clk_below_host_limit_violation_activity": "N/A",
"low_utilization_violation_activity": "N/A",
}
try:
violation_status = amdsmi_interface.amdsmi_get_violation_status(args.gpu)
throttle_status["accumulation_counter"] = violation_status["acc_counter"]
throttle_status["prochot_accumulated"] = violation_status["acc_prochot_thrm"]
throttle_status["ppt_accumulated"] = violation_status["acc_ppt_pwr"]
throttle_status["socket_thermal_accumulated"] = violation_status[
"acc_socket_thrm"
]
throttle_status["vr_thermal_accumulated"] = violation_status["acc_vr_thrm"]
throttle_status["hbm_thermal_accumulated"] = violation_status["acc_hbm_thrm"]
throttle_status["gfx_clk_below_host_limit_accumulated"] = violation_status[
"acc_gfx_clk_below_host_limit"
] # deprecated
throttle_status["gfx_clk_below_host_limit_power_accumulated"] = (
self.helpers.build_xcp_dict(
"acc_gfx_clk_below_host_limit_pwr", violation_status, num_partition
)
)
throttle_status["gfx_clk_below_host_limit_thermal_accumulated"] = (
self.helpers.build_xcp_dict(
"acc_gfx_clk_below_host_limit_thm", violation_status, num_partition
)
)
throttle_status["total_gfx_clk_below_host_limit_accumulated"] = (
self.helpers.build_xcp_dict(
"acc_gfx_clk_below_host_limit_total", violation_status, num_partition
)
)
throttle_status["low_utilization_accumulated"] = self.helpers.build_xcp_dict(
"acc_low_utilization", violation_status, num_partition
)
throttle_status["prochot_violation_status"] = self.helpers.build_xcp_dict(
"active_prochot_thrm", violation_status, num_partition
)
throttle_status["ppt_violation_status"] = self.helpers.build_xcp_dict(
"active_ppt_pwr", violation_status, num_partition
)
throttle_status["socket_thermal_violation_status"] = (
self.helpers.build_xcp_dict(
"active_socket_thrm", violation_status, num_partition
)
)
throttle_status["vr_thermal_violation_status"] = self.helpers.build_xcp_dict(
"active_vr_thrm", violation_status, num_partition
)
throttle_status["hbm_thermal_violation_status"] = self.helpers.build_xcp_dict(
"active_hbm_thrm", violation_status, num_partition
)
throttle_status["gfx_clk_below_host_limit_violation_status"] = (
self.helpers.build_xcp_dict(
"active_gfx_clk_below_host_limit", violation_status, num_partition
)
) # deprecated
throttle_status["gfx_clk_below_host_limit_power_violation_status"] = (
self.helpers.build_xcp_dict(
"active_gfx_clk_below_host_limit_pwr", violation_status, num_partition
)
)
throttle_status["gfx_clk_below_host_limit_thermal_violation_status"] = (
self.helpers.build_xcp_dict(
"active_gfx_clk_below_host_limit_thm", violation_status, num_partition
)
)
throttle_status["total_gfx_clk_below_host_limit_violation_status"] = (
self.helpers.build_xcp_dict(
"active_gfx_clk_below_host_limit_total", violation_status, num_partition
)
)
throttle_status["low_utilization_violation_status"] = (
self.helpers.build_xcp_dict(
"active_low_utilization", violation_status, num_partition
)
)
throttle_status["prochot_violation_activity"] = violation_status[
"per_prochot_thrm"
]
throttle_status["ppt_violation_activity"] = violation_status["per_ppt_pwr"]
throttle_status["socket_thermal_violation_activity"] = violation_status[
"per_socket_thrm"
]
throttle_status["vr_thermal_violation_activity"] = violation_status[
"per_vr_thrm"
]
throttle_status["hbm_thermal_violation_activity"] = violation_status[
"per_hbm_thrm"
]
throttle_status["gfx_clk_below_host_limit_violation_activity"] = (
violation_status["per_gfx_clk_below_host_limit"]
) # deprecated
throttle_status["gfx_clk_below_host_limit_power_violation_activity"] = (
self.helpers.build_xcp_dict(
"per_gfx_clk_below_host_limit_pwr", violation_status, num_partition
)
)
throttle_status["gfx_clk_below_host_limit_thermal_violation_activity"] = (
self.helpers.build_xcp_dict(
"per_gfx_clk_below_host_limit_thm", violation_status, num_partition
)
)
throttle_status["total_gfx_clk_below_host_limit_violation_activity"] = (
self.helpers.build_xcp_dict(
"per_gfx_clk_below_host_limit_total", violation_status, num_partition
)
)
throttle_status["low_utilization_violation_activity"] = (
self.helpers.build_xcp_dict(
"per_low_utilization", violation_status, num_partition
)
)
except amdsmi_exception.AmdSmiLibraryException as e:
values_dict["throttle"] = throttle_status
logging.debug(
"Failed to get violation status' for gpu %s | %s",
gpu_id,
e.get_error_info(),
)
for key, value in throttle_status.items():
activity_unit = ""
if "_activity" in key:
activity_unit = "%"
if self.logger.is_human_readable_format():
if isinstance(value, (list, dict)):
for k, v in value.items():
for index, activity in enumerate(v):
value[k][index] = self.helpers.unit_format(
self.logger, activity, activity_unit
)
value[k] = "[" + ", ".join(value[k]) + "]"
elif value != "N/A":
throttle_status[key] = self.helpers.unit_format(
self.logger, value, activity_unit
)
if self.logger.is_json_format():
if isinstance(value, (list, dict)):
for k, v in value.items():
for index, activity in enumerate(v):
value[k][index] = self.helpers.unit_format(
self.logger, activity, activity_unit
)
elif value != "N/A":
throttle_status[key] = self.helpers.unit_format(
self.logger, value, activity_unit
)
# APU-specific throttle data
if show_apu:
apu_throttle_fields = {
"apu_throttle_status": gpu_metric.get("apu_metrics.throttle_status", "N/A"),
"apu_indep_throttle_status": gpu_metric.get(
"apu_metrics.indep_throttle_status", "N/A"
),
"apu_throttle_residency_prochot": gpu_metric.get(
"apu_metrics.throttle_residency_prochot", "N/A"
),
"apu_throttle_residency_spl": gpu_metric.get(
"apu_metrics.throttle_residency_spl", "N/A"
),
"apu_throttle_residency_fppt": gpu_metric.get(
"apu_metrics.throttle_residency_fppt", "N/A"
),
"apu_throttle_residency_sppt": gpu_metric.get(
"apu_metrics.throttle_residency_sppt", "N/A"
),
"apu_throttle_residency_thm_core": gpu_metric.get(
"apu_metrics.throttle_residency_thm_core", "N/A"
),
"apu_throttle_residency_thm_gfx": gpu_metric.get(
"apu_metrics.throttle_residency_thm_gfx", "N/A"
),
"apu_throttle_residency_thm_soc": gpu_metric.get(
"apu_metrics.throttle_residency_thm_soc", "N/A"
),
}
for key, value in apu_throttle_fields.items():
if value != "N/A":
if "throttle_status" in key:
throttle_status[key] = "THROTTLED" if value else "UNTHROTTLED"
else:
throttle_status[key] = self.helpers.unit_format(
self.logger, value, ""
)
values_dict["throttle"] = throttle_status
# On APU systems, drop only the N/A standard sensors from APU-relevant
# sections; a standard field that reports a real value is preserved.
if show_apu:
apu_only_sections = {"usage", "power", "clock", "temperature", "voltage", "throttle"}
for section_key in list(values_dict.keys()):
section_val = values_dict[section_key]
if isinstance(section_val, dict):
if section_key in apu_only_sections:
non_apu_keys = [
k
for k in section_val
if not k.startswith("apu_") and section_val[k] == "N/A"
]
for k in non_apu_keys:
del section_val[k]
if not section_val:
del values_dict[section_key]
elif section_val == "N/A":
del values_dict[section_key]
# Store timestamp first if watching_output is enabled
if watching_output:
self.logger.store_output(args.gpu, "timestamp", int(time.time()))
self.logger.store_output(args.gpu, "values", values_dict)
self.logger.store_gpu_json_output.append(values_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
if not self.logger.is_json_format() or watching_output:
self.logger.print_output(watching_output=watching_output)
if watching_output: # End of single gpu add to watch_output
self.logger.store_watch_output(multiple_device_enabled=False)
def metric_cpu(
self,
args,
multiple_devices=False,
cpu=None,
cpu_power_metrics=None,
cpu_prochot=None,
cpu_freq_metrics=None,
cpu_c0_res=None,
cpu_lclk_dpm_level=None,
cpu_pwr_svi_telemetry_rails=None,
cpu_io_bandwidth=None,
cpu_xgmi_bandwidth=None,
cpu_pwr_eff_mode=None,
cpu_metrics_ver=None,
cpu_metrics_table=None,
cpu_socket_energy=None,
cpu_ddr_bandwidth=None,
cpu_temp=None,
cpu_dimm_temp_range_rate=None,
cpu_dimm_pow_consumption=None,
cpu_dimm_thermal_sensor=None,
cpu_xgmi_pstate_range=None,
cpu_railisofreq_policy=None,
cpu_dfcstate_ctrl=None,
cpu_pc6_enable=None,
cpu_cc6_enable=None,
cpu_dimm_sb_reg=None,
cpu_tdelta=None,
cpu_svi3_vr_controller_temp=None,
cpu_enabled_commands=None,
cpu_sdps_limit=None,
):
"""Get Metric information for target cpu
Args:
args (Namespace): Namespace containing the parsed CLI args
multiple_devices (bool, optional): True if checking for multiple devices. Defaults to False.
cpu (cpu_handle, optional): device_handle for target device. Defaults to None.
cpu_power_metrics (bool, optional): Value override for args.cpu_power_metrics. Defaults to None
cpu_prochot (bool, optional): Value override for args.cpu_prochot. Defaults to None.
cpu_freq_metrics (bool, optional): Value override for args.cpu_freq_metrics. Defaults to None.
cpu_c0_res (bool, optional): Value override for args.cpu_c0_res. Defaults to None
cpu_lclk_dpm_level (list, optional): Value override for args.cpu_lclk_dpm_level. Defaults to None
cpu_pwr_svi_telemetry_rails (list, optional): value override for args.cpu_pwr_svi_telemetry_rails. Defaults to None
cpu_io_bandwidth (list, optional): value override for args.cpu_io_bandwidth. Defaults to None
cpu_xgmi_bandwidth (list, optional): value override for args.cpu_xgmi_bandwidth. Defaults to None
cpu_pwr_eff_mode (bool, optional): Value override for args.cpu_pwr_eff_mode. Defaults to None
cpu_metrics_ver (bool, optional): Value override for args.cpu_metrics_ver. Defaults to None
cpu_metrics_table (bool, optional): Value override for args.cpu_metrics_table. Defaults to None
cpu_socket_energy (bool, optional): Value override for args.cpu_socket_energy. Defaults to None
cpu_ddr_bandwidth (bool, optional): Value override for args.cpu_ddr_bandwidth. Defaults to None
cpu_temp (bool, optional): Value override for args.cpu_temp. Defaults to None
cpu_dimm_temp_range_rate (list, optional): Dimm address. Value override for args.cpu_dimm_temp_range_rate. Defaults to None
cpu_dimm_pow_consumption (list, optional): Dimm address. Value override for args.cpu_dimm_pow_consumption. Defaults to None
cpu_dimm_thermal_sensor (list, optional): Dimm address. Value override for args.cpu_dimm_thermal_sensor. Defaults to None
cpu_xgmi_pstate_range (bool, optional): Value override for args.cpu_xgmi_pstate_range. Defaults to None
cpu_railisofreq_policy (bool, optional): Value override for args.cpu_railisofreq_policy. Defaults to None
cpu_dfcstate_ctrl (bool, optional): Value override for args.cpu_dfcstate_ctrl. Defaults to None
cpu_pc6_enable (bool, optional): Value override for args.cpu_pc6_enable. Defaults to None
cpu_cc6_enable (bool, optional): Value override for args.cpu_cc6_enable. Defaults to None
cpu_dimm_sb_reg (list, optional): DIMM sideband register parameters [dimm_addr, lid, reg_offset, reg_space] for read. Value override for args.cpu_dimm_sb_reg. Defaults to None
cpu_tdelta (bool, optional): Value override for args.cpu_tdelta. Defaults to None
cpu_svi3_vr_controller_temp (list, optional): TYPE and optional RAIL_INDEX. Value override for args.cpu_svi3_vr_controller_temp. Defaults to None
cpu_enabled_commands (bool, optional): Value override for args.cpu_enabled_commands. Defaults to None
cpu_sdps_limit (bool, optional): Value override for args.cpu_sdps_limit. Defaults to None
Returns:
None: Print output via AMDSMILogger to destination
"""
if cpu:
args.cpu = cpu
if cpu_power_metrics:
args.cpu_power_metrics = cpu_power_metrics
if cpu_prochot:
args.cpu_prochot = cpu_prochot
if cpu_freq_metrics:
args.cpu_freq_metrics = cpu_freq_metrics
if cpu_c0_res:
args.cpu_c0_res = cpu_c0_res
if cpu_lclk_dpm_level:
args.cpu_lclk_dpm_level = cpu_lclk_dpm_level
if cpu_pwr_svi_telemetry_rails:
args.cpu_pwr_svi_telemetry_rails = cpu_pwr_svi_telemetry_rails
if cpu_io_bandwidth:
args.cpu_io_bandwidth = cpu_io_bandwidth
if cpu_xgmi_bandwidth:
args.cpu_xgmi_bandwidth = cpu_xgmi_bandwidth
if cpu_pwr_eff_mode:
args.cpu_pwr_eff_mode = cpu_pwr_eff_mode
if cpu_metrics_ver:
args.cpu_metrics_ver = cpu_metrics_ver
if cpu_metrics_table:
args.cpu_metrics_table = cpu_metrics_table
if cpu_socket_energy:
args.cpu_socket_energy = cpu_socket_energy
if cpu_ddr_bandwidth:
args.cpu_ddr_bandwidth = cpu_ddr_bandwidth
if cpu_temp:
args.cpu_temp = cpu_temp
if cpu_dimm_temp_range_rate:
args.cpu_dimm_temp_range_rate = cpu_dimm_temp_range_rate
if cpu_dimm_pow_consumption:
args.cpu_dimm_pow_consumption = cpu_dimm_pow_consumption
if cpu_dimm_thermal_sensor:
args.cpu_dimm_thermal_sensor = cpu_dimm_thermal_sensor
if cpu_xgmi_pstate_range:
args.cpu_xgmi_pstate_range = cpu_xgmi_pstate_range
if cpu_railisofreq_policy:
args.cpu_railisofreq_policy = cpu_railisofreq_policy
if cpu_dfcstate_ctrl:
args.cpu_dfcstate_ctrl = cpu_dfcstate_ctrl
if cpu_pc6_enable:
args.cpu_pc6_enable = cpu_pc6_enable
if cpu_cc6_enable:
args.cpu_cc6_enable = cpu_cc6_enable
if cpu_dimm_sb_reg:
args.cpu_dimm_sb_reg = cpu_dimm_sb_reg
if cpu_tdelta:
args.cpu_tdelta = cpu_tdelta
if cpu_svi3_vr_controller_temp:
args.cpu_svi3_vr_controller_temp = cpu_svi3_vr_controller_temp
if cpu_enabled_commands:
args.cpu_enabled_commands = cpu_enabled_commands
if cpu_sdps_limit:
args.cpu_sdps_limit = cpu_sdps_limit
# store cpu args that are applicable to the current platform
curr_platform_cpu_args = [
"cpu_power_metrics",
"cpu_prochot",
"cpu_freq_metrics",
"cpu_c0_res",
"cpu_lclk_dpm_level",
"cpu_pwr_svi_telemetry_rails",
"cpu_io_bandwidth",
"cpu_xgmi_bandwidth",
"cpu_pwr_eff_mode",
"cpu_metrics_ver",
"cpu_metrics_table",
"cpu_socket_energy",
"cpu_ddr_bandwidth",
"cpu_temp",
"cpu_dimm_temp_range_rate",
"cpu_dimm_pow_consumption",
"cpu_dimm_thermal_sensor",
"cpu_xgmi_pstate_range",
"cpu_railisofreq_policy",
"cpu_dfcstate_ctrl",
"cpu_pc6_enable",
"cpu_cc6_enable",
"cpu_dimm_sb_reg",
"cpu_tdelta",
"cpu_svi3_vr_controller_temp",
"cpu_enabled_commands",
"cpu_sdps_limit",
]
curr_platform_cpu_values = [
args.cpu_power_metrics,
args.cpu_prochot,
args.cpu_freq_metrics,
args.cpu_c0_res,
args.cpu_lclk_dpm_level,
args.cpu_pwr_svi_telemetry_rails,
args.cpu_io_bandwidth,
args.cpu_xgmi_bandwidth,
args.cpu_pwr_eff_mode,
args.cpu_metrics_ver,
args.cpu_metrics_table,
args.cpu_socket_energy,
args.cpu_ddr_bandwidth,
args.cpu_temp,
args.cpu_dimm_temp_range_rate,
args.cpu_dimm_pow_consumption,
args.cpu_dimm_thermal_sensor,
args.cpu_xgmi_pstate_range,
args.cpu_railisofreq_policy,
args.cpu_dfcstate_ctrl,
args.cpu_pc6_enable,
args.cpu_cc6_enable,
args.cpu_dimm_sb_reg,
args.cpu_tdelta,
args.cpu_svi3_vr_controller_temp,
args.cpu_enabled_commands,
args.cpu_sdps_limit,
]
# Handle No CPU passed (fall back as this should be defined in metric())
if args.cpu == None:
args.cpu = self.cpu_handles
if not any(curr_platform_cpu_values):
for arg in curr_platform_cpu_args:
if arg not in (
"cpu_lclk_dpm_level",
"cpu_io_bandwidth",
"cpu_xgmi_bandwidth",
"cpu_dimm_temp_range_rate",
"cpu_dimm_pow_consumption",
"cpu_dimm_thermal_sensor",
"cpu_dimm_sb_reg",
"cpu_svi3_vr_controller_temp",
):
setattr(args, arg, True)
handled_multiple_cpus, device_handle = self.helpers.handle_cpus(
args, self.logger, self.metric_cpu
)
if handled_multiple_cpus:
return # This function is recursive
args.cpu = device_handle
# get cpu id for logging
cpu_id = self.helpers.get_cpu_id_from_device_handle(args.cpu)
logging.debug(f"Metric Arg information for CPU {cpu_id} on {self.helpers.os_info()}")
static_dict = {}
if self.logger.is_json_format():
static_dict["cpu"] = int(cpu_id)
if args.cpu_power_metrics:
static_dict["power_metrics"] = {}
try:
soc_pow = amdsmi_interface.amdsmi_get_cpu_socket_power(args.cpu)
soc_pow = self.helpers.convert_SI_unit(float(soc_pow), self.helpers.SI_Unit.MILLI)
static_dict["power_metrics"]["socket power"] = f"{soc_pow:.3f} W"
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["power_metrics"]["socket power"] = "N/A"
logging.debug(
"Failed to get socket power for cpu %s | %s", cpu_id, e.get_error_info()
)
try:
soc_pwr_limit = amdsmi_interface.amdsmi_get_cpu_socket_power_cap(args.cpu)
soc_pwr_limit = self.helpers.convert_SI_unit(
float(soc_pwr_limit), self.helpers.SI_Unit.MILLI
)
static_dict["power_metrics"]["socket power limit"] = f"{soc_pwr_limit:.3f} W"
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["power_metrics"]["socket power limit"] = "N/A"
logging.debug(
"Failed to get socket power limit for cpu %s | %s", cpu_id, e.get_error_info()
)
try:
soc_max_pwr_limit = amdsmi_interface.amdsmi_get_cpu_socket_power_cap_max(args.cpu)
soc_max_pwr_limit = self.helpers.convert_SI_unit(
float(soc_max_pwr_limit), self.helpers.SI_Unit.MILLI
)
static_dict["power_metrics"]["socket max power limit"] = (
f"{soc_max_pwr_limit:.3f} W"
)
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["power_metrics"]["socket max power limit"] = "N/A"
logging.debug(
"Failed to get max socket power limit for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_prochot:
static_dict["prochot"] = {}
try:
proc_status = amdsmi_interface.amdsmi_get_cpu_prochot_status(args.cpu)
static_dict["prochot"]["prochot_status"] = proc_status
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["prochot"]["prochot_status"] = "N/A"
logging.debug(
"Failed to get prochot status for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_freq_metrics:
static_dict["freq_metrics"] = {}
try:
fclk_mclk = amdsmi_interface.amdsmi_get_cpu_fclk_mclk(args.cpu)
static_dict["freq_metrics"]["fclkmemclk"] = fclk_mclk
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["freq_metrics"]["fclkmemclk"] = "N/A"
logging.debug(
"Failed to get current fclkmemclk freq for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
try:
cclk_freq = amdsmi_interface.amdsmi_get_cpu_cclk_limit(args.cpu)
static_dict["freq_metrics"]["cclkfreqlimit"] = cclk_freq
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["freq_metrics"]["cclkfreqlimit"] = "N/A"
logging.debug(
"Failed to get current cclk freq for cpu %s | %s", cpu_id, e.get_error_info()
)
try:
soc_cur_freq_limit = (
amdsmi_interface.amdsmi_get_cpu_socket_current_active_freq_limit(args.cpu)
)
static_dict["freq_metrics"]["soc_current_active_freq_limit"] = soc_cur_freq_limit
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["freq_metrics"]["soc_current_active_freq_limit"] = "N/A"
logging.debug(
"Failed to get socket current freq limit for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
try:
soc_freq_range = amdsmi_interface.amdsmi_get_cpu_socket_freq_range(args.cpu)
static_dict["freq_metrics"]["soc_freq_range"] = soc_freq_range
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["freq_metrics"]["soc_freq_range"] = "N/A"
logging.debug(
"Failed to get socket freq range for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_c0_res:
static_dict["c0_residency"] = {}
try:
residency = amdsmi_interface.amdsmi_get_cpu_socket_c0_residency(args.cpu)
static_dict["c0_residency"]["residency"] = residency
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["c0_residency"]["residency"] = "N/A"
logging.debug(
"Failed to get C0 residency for cpu %s | %s", cpu_id, e.get_error_info()
)
if isinstance(args.cpu_lclk_dpm_level, list) and args.cpu_lclk_dpm_level:
static_dict["socket_dpm"] = {}
try:
dpm_val = amdsmi_interface.amdsmi_get_cpu_socket_lclk_dpm_level(
args.cpu, args.cpu_lclk_dpm_level[0][0]
)
static_dict["socket_dpm"]["dpml_level_range"] = dpm_val
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["socket_dpm"]["dpml_level_range"] = "N/A"
logging.debug(
"Failed to get socket dpm level range for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_pwr_svi_telemetry_rails:
static_dict["svi_telemetry_all_rails"] = {}
try:
power = amdsmi_interface.amdsmi_get_cpu_pwr_svi_telemetry_all_rails(args.cpu)
static_dict["svi_telemetry_all_rails"]["power"] = power
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["c0_residency"]["residency"] = "N/A"
logging.debug(
"Failed to get svi telemetry all rails for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if isinstance(args.cpu_io_bandwidth, list) and args.cpu_io_bandwidth:
static_dict["io_bandwidth"] = {}
try:
bandwidth = amdsmi_interface.amdsmi_get_cpu_current_io_bandwidth(
args.cpu, int(args.cpu_io_bandwidth[0][0]), args.cpu_io_bandwidth[0][1].upper()
)
static_dict["io_bandwidth"]["band_width"] = bandwidth
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["io_bandwidth"]["band_width"] = "N/A"
logging.debug(
"Failed to get io bandwidth for cpu %s | %s", cpu_id, e.get_error_info()
)
if isinstance(args.cpu_xgmi_bandwidth, list) and args.cpu_xgmi_bandwidth:
static_dict["xgmi_bandwidth"] = {}
try:
bandwidth = amdsmi_interface.amdsmi_get_cpu_current_xgmi_bw(
args.cpu,
int(args.cpu_xgmi_bandwidth[0][0]),
args.cpu_xgmi_bandwidth[0][1].upper(),
)
static_dict["xgmi_bandwidth"]["band_width"] = bandwidth
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["xgmi_bandwidth"]["band_width"] = "N/A"
logging.debug(
"Failed to get xgmi bandwidth for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_pwr_eff_mode:
static_dict["pwr_eff_mode"] = {}
try:
mode, util, ppt_limit = amdsmi_interface.amdsmi_get_cpu_pwr_efficiency_mode(
args.cpu
)
ppt_limit = self.helpers.convert_SI_unit(
float(ppt_limit), self.helpers.SI_Unit.MILLI
)
# Always show mode
static_dict["pwr_eff_mode"]["mode"] = f"{mode}"
# Only show util and ppt_limit for modes 4 and 5
if mode in [4, 5]:
static_dict["pwr_eff_mode"]["util"] = f"{util}%"
static_dict["pwr_eff_mode"]["ppt_limit"] = f"{ppt_limit:.3f} W"
else:
# For modes 0-3, util and ppt_limit are not displayed
pass
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["pwr_eff_mode"]["mode"] = "N/A"
static_dict["pwr_eff_mode"]["util"] = "N/A"
static_dict["pwr_eff_mode"]["ppt_limit"] = "N/A"
logging.debug(
"Failed to get power efficiency mode for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_metrics_ver:
static_dict["metric_version"] = {}
try:
version = amdsmi_interface.amdsmi_get_hsmp_metrics_table_version(args.cpu)
static_dict["metric_version"]["version"] = version
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["metric_version"]["version"] = "N/A"
logging.debug(
"Failed to get metrics table version for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_metrics_table:
static_dict["metrics_table"] = {}
try:
cpu_fam = amdsmi_interface.amdsmi_get_cpu_family()
static_dict["metrics_table"]["cpu_family"] = cpu_fam
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["metrics_table"]["cpu_family"] = "N/A"
logging.debug("Failed to get cpu family | %s", e.get_error_info())
try:
cpu_mod = amdsmi_interface.amdsmi_get_cpu_model()
static_dict["metrics_table"]["cpu_model"] = cpu_mod
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["metrics_table"]["cpu_model"] = "N/A"
logging.debug("Failed to get cpu model | %s", e.get_error_info())
try:
cpu_metrics_table = amdsmi_interface.amdsmi_get_hsmp_metrics_table(args.cpu)
static_dict["metrics_table"]["response"] = cpu_metrics_table
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["metrics_table"]["response"] = "N/A"
logging.debug(
"Failed to get metrics table for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_socket_energy:
static_dict["socket_energy"] = {}
try:
energy = amdsmi_interface.amdsmi_get_cpu_socket_energy(args.cpu)
static_dict["socket_energy"]["response"] = energy
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["socket_energy"]["response"] = "N/A"
logging.debug(
"Failed to get socket energy for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_ddr_bandwidth:
static_dict["ddr_bandwidth"] = {}
try:
resp = amdsmi_interface.amdsmi_get_cpu_ddr_bw(args.cpu)
static_dict["ddr_bandwidth"]["response"] = resp
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["ddr_bandwidth"]["response"] = "N/A"
logging.debug(
"Failed to get ddr bandwidth for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_temp:
static_dict["cpu_temp"] = {}
try:
resp = amdsmi_interface.amdsmi_get_cpu_socket_temperature(args.cpu)
static_dict["cpu_temp"]["response"] = resp
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["cpu_temp"]["response"] = "N/A"
logging.debug(
"Failed to get cpu temperature for cpu %s | %s", cpu_id, e.get_error_info()
)
if isinstance(args.cpu_dimm_temp_range_rate, list) and args.cpu_dimm_temp_range_rate:
static_dict["dimm_temp_range_rate"] = {}
try:
resp = amdsmi_interface.amdsmi_get_cpu_dimm_temp_range_and_refresh_rate(
args.cpu, args.cpu_dimm_temp_range_rate[0][0]
)
static_dict["dimm_temp_range_rate"]["response"] = resp
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["dimm_temp_range_rate"]["response"] = "N/A"
logging.debug(
"Failed to get dimm temperature range and refresh rate for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if isinstance(args.cpu_dimm_pow_consumption, list) and args.cpu_dimm_pow_consumption:
static_dict["dimm_pow_consumption"] = {}
try:
resp = amdsmi_interface.amdsmi_get_cpu_dimm_power_consumption(
args.cpu, args.cpu_dimm_pow_consumption[0][0]
)
static_dict["dimm_pow_consumption"]["response"] = resp
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["dimm_pow_consumption"]["response"] = "N/A"
logging.debug(
"Failed to get dimm temperature range and refresh rate for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if isinstance(args.cpu_dimm_thermal_sensor, list) and args.cpu_dimm_thermal_sensor:
static_dict["dimm_thermal_sensor"] = {}
try:
resp = amdsmi_interface.amdsmi_get_cpu_dimm_thermal_sensor(
args.cpu, args.cpu_dimm_thermal_sensor[0][0]
)
static_dict["dimm_thermal_sensor"]["response"] = resp
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["dimm_thermal_sensor"]["response"] = "N/A"
logging.debug(
"Failed to get dimm temperature range and refresh rate for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_xgmi_pstate_range:
static_dict["xgmi_pstate_range"] = {}
try:
pstate_range = amdsmi_interface.amdsmi_get_cpu_xgmi_pstate_range(args.cpu)
static_dict["xgmi_pstate_range"]["min_pstate"] = pstate_range["min_pstate"]
static_dict["xgmi_pstate_range"]["max_pstate"] = pstate_range["max_pstate"]
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["xgmi_pstate_range"]["min_pstate"] = "N/A"
static_dict["xgmi_pstate_range"]["max_pstate"] = "N/A"
logging.debug(
"Failed to get xgmi pstate range for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_railisofreq_policy:
static_dict["railisofreq_policy"] = {}
try:
cpurailisofreq_policy = amdsmi_interface.amdsmi_get_cpu_rail_isofreq_policy(
args.cpu
)
static_dict["railisofreq_policy"]["value"] = cpurailisofreq_policy
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["railisofreq_policy"]["value"] = "N/A"
logging.debug(
"Failed to get cpurailiso frequency policy for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_dfcstate_ctrl:
static_dict["dfcstate_ctrl"] = {}
try:
dfcstatectrl_status = amdsmi_interface.amdsmi_get_cpu_dfc_ctrl(args.cpu)
static_dict["dfcstate_ctrl"]["value"] = dfcstatectrl_status
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["dfcstate_ctrl"]["value"] = "N/A"
logging.debug(
"Failed to get dfcstate control status for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_pc6_enable:
static_dict["pc6_enable"] = {}
try:
pc6_enable_status = amdsmi_interface.amdsmi_get_cpu_pc6_enable(args.cpu)
static_dict["pc6_enable"]["value"] = pc6_enable_status
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["pc6_enable"]["value"] = "N/A"
logging.debug(
"Failed to get PC6 enable status for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_cc6_enable:
static_dict["cc6_enable"] = {}
try:
cc6_enable_status = amdsmi_interface.amdsmi_get_cpu_cc6_enable(args.cpu)
static_dict["cc6_enable"]["value"] = cc6_enable_status
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["cc6_enable"]["value"] = "N/A"
logging.debug(
"Failed to get CC6 enable status for cpu %s | %s", cpu_id, e.get_error_info()
)
if isinstance(args.cpu_dimm_sb_reg, list) and args.cpu_dimm_sb_reg:
static_dict["dimm_sb_reg"] = {}
try:
dimm_addr = args.cpu_dimm_sb_reg[0][0]
lid = args.cpu_dimm_sb_reg[0][1]
reg_offset = args.cpu_dimm_sb_reg[0][2]
reg_space = args.cpu_dimm_sb_reg[0][3]
dimm_sb_data = amdsmi_interface.amdsmi_get_cpu_dimm_sb_reg(
args.cpu, dimm_addr, lid, reg_offset, reg_space
)
static_dict["dimm_sb_reg"]["DimmAddress"] = f"0x{dimm_addr:02X}"
static_dict["dimm_sb_reg"]["Lid"] = f"0x{lid:02X}"
static_dict["dimm_sb_reg"]["Offset"] = f"0x{reg_offset:04X}"
static_dict["dimm_sb_reg"]["RegSpace"] = reg_space
static_dict["dimm_sb_reg"]["Data"] = f"0x{dimm_sb_data:08X}"
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["dimm_sb_reg"]["DimmAddress"] = f"0x{args.cpu_dimm_sb_reg[0][0]:02X}"
static_dict["dimm_sb_reg"]["Lid"] = f"0x{args.cpu_dimm_sb_reg[0][1]:02X}"
static_dict["dimm_sb_reg"]["Offset"] = f"0x{args.cpu_dimm_sb_reg[0][2]:04X}"
static_dict["dimm_sb_reg"]["RegSpace"] = args.cpu_dimm_sb_reg[0][3]
static_dict["dimm_sb_reg"]["Data"] = "N/A"
logging.debug(
"Failed to read DIMM sideband register for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_tdelta:
static_dict["tdelta"] = {}
try:
tdelta_value = amdsmi_interface.amdsmi_get_cpu_tdelta(args.cpu)
static_dict["tdelta"]["value"] = tdelta_value
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["tdelta"]["value"] = "N/A"
logging.debug(
"Failed to get thermal delta (TDELTA) for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if isinstance(args.cpu_svi3_vr_controller_temp, list) and args.cpu_svi3_vr_controller_temp:
static_dict["svi3_vr_controller_temp"] = {}
try:
rail_type = args.cpu_svi3_vr_controller_temp[0][0]
rail_index = (
args.cpu_svi3_vr_controller_temp[0][1]
if len(args.cpu_svi3_vr_controller_temp[0]) > 1
else AMDSMI_MAX_RAIL_INDEX
)
resp = amdsmi_interface.amdsmi_get_cpu_svi3_vr_controller_temp(
args.cpu, rail_type, rail_index
)
static_dict["svi3_vr_controller_temp"]["RAIL_SELECTION"] = resp["rail_selection"]
static_dict["svi3_vr_controller_temp"]["RAIL_INDEX"] = resp["rail_index"]
temp_celsius = resp["temperature"]
static_dict["svi3_vr_controller_temp"]["TEMPERATURE"] = (
f"{temp_celsius:.1f} Degree C"
)
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["svi3_vr_controller_temp"]["RAIL_SELECTION"] = "N/A"
static_dict["svi3_vr_controller_temp"]["RAIL_INDEX"] = "N/A"
static_dict["svi3_vr_controller_temp"]["TEMPERATURE"] = "N/A"
logging.debug(
"Failed to get SVI3 VR controller temperature for cpu %s | %s",
cpu_id,
e.get_error_info(),
)
if args.cpu_enabled_commands:
static_dict["enabled_commands"] = {}
try:
enabled_cmds = amdsmi_interface.amdsmi_get_cpu_enabled_commands(args.cpu)
static_dict["enabled_commands"]["READ_ENABLED_COMMANDS_BITMASK0"] = (
f"0x{enabled_cmds['ReadEnabledCommandsBitMask0']:08X}"
)
static_dict["enabled_commands"]["READ_ENABLED_COMMANDS_BITMASK1"] = (
f"0x{enabled_cmds['ReadEnabledCommandsBitMask1']:08X}"
)
static_dict["enabled_commands"]["READ_ENABLED_COMMANDS_BITMASK2"] = (
f"0x{enabled_cmds['ReadEnabledCommandsBitMask2']:08X}"
)
static_dict["enabled_commands"]["WRITE_ENABLED_COMMANDS_BITMASK0"] = (
f"0x{enabled_cmds['WriteEnabledCommandsBitMask0']:08X}"
)
static_dict["enabled_commands"]["WRITE_ENABLED_COMMANDS_BITMASK1"] = (
f"0x{enabled_cmds['WriteEnabledCommandsBitMask1']:08X}"
)
static_dict["enabled_commands"]["WRITE_ENABLED_COMMANDS_BITMASK2"] = (
f"0x{enabled_cmds['WriteEnabledCommandsBitMask2']:08X}"
)
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["enabled_commands"]["READ_ENABLED_COMMANDS_BITMASK0"] = "N/A"
static_dict["enabled_commands"]["READ_ENABLED_COMMANDS_BITMASK1"] = "N/A"
static_dict["enabled_commands"]["READ_ENABLED_COMMANDS_BITMASK2"] = "N/A"
static_dict["enabled_commands"]["WRITE_ENABLED_COMMANDS_BITMASK0"] = "N/A"
static_dict["enabled_commands"]["WRITE_ENABLED_COMMANDS_BITMASK1"] = "N/A"
static_dict["enabled_commands"]["WRITE_ENABLED_COMMANDS_BITMASK2"] = "N/A"
logging.debug(
"Failed to get enabled commands for cpu %s | %s", cpu_id, e.get_error_info()
)
if args.cpu_sdps_limit:
static_dict["sdps_limit"] = {}
try:
sdps_limit = amdsmi_interface.amdsmi_get_cpu_sdps_limit(args.cpu)
sdps_limit = self.helpers.convert_SI_unit(
float(sdps_limit), self.helpers.SI_Unit.MILLI
)
static_dict["sdps_limit"]["value"] = f"{sdps_limit:.3f} W"
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["sdps_limit"]["value"] = "N/A"
logging.debug(
"Failed to get socket SDPS limit for cpu %s | %s", cpu_id, e.get_error_info()
)
multiple_devices_csv_override = False
if not self.logger.is_json_format():
self.logger.store_cpu_output(args.cpu, "values", static_dict)
else:
self.logger.store_cpu_json_output.append(static_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
if not self.logger.is_json_format():
self.logger.print_output(multiple_device_enabled=multiple_devices_csv_override)
def metric_core(
self,
args,
multiple_devices=False,
core=None,
core_boost_limit=None,
core_curr_active_freq_core_limit=None,
core_energy=None,
core_ccd_power=None,
core_floor_limit=None,
core_eff_floor_limit=None,
):
"""Get Static information for target core
Args:
args (Namespace): Namespace containing the parsed CLI args
multiple_devices (bool, optional): True if checking for multiple devices. Defaults to False.
core (device_handle, optional): device_handle for target core. Defaults to None.
core_boost_limit (bool, optional): Value override for args.core_boost_limit. Defaults to None
core_curr_active_freq_core_limit (bool, optional): Value override for args.core_curr_active_freq_core_limit. Defaults to None
core_energy (bool, optional): Value override for args.core_energy. Defaults to None
core_ccd_power (bool, optional): Value override for args.core_ccd_power. Defaults to None
core_floor_limit (bool, optional): Value override for args.core_floor_limit. Defaults to None
core_eff_floor_limit (bool, optional): Value override for args.core_eff_floor_limit. Defaults to None
Returns:
None: Print output via AMDSMILogger to destination
"""
if core:
args.core = core
if core_boost_limit:
args.core_boost_limit = core_boost_limit
if core_curr_active_freq_core_limit:
args.core_curr_active_freq_core_limit = core_curr_active_freq_core_limit
if core_energy:
args.core_energy = core_energy
if core_ccd_power:
args.core_ccd_power = core_ccd_power
if core_floor_limit:
args.core_floor_limit = core_floor_limit
if core_eff_floor_limit:
args.core_eff_floor_limit = core_eff_floor_limit
# store core args that are applicable to the current platform
curr_platform_core_args = [
"core_boost_limit",
"core_curr_active_freq_core_limit",
"core_energy",
"core_ccd_power",
"core_floor_limit",
"core_eff_floor_limit",
]
curr_platform_core_values = [
args.core_boost_limit,
args.core_curr_active_freq_core_limit,
args.core_energy,
args.core_ccd_power,
args.core_floor_limit,
args.core_eff_floor_limit,
]
# Handle No cores passed
if args.core == None:
args.core = self.core_handles
if not any(curr_platform_core_values):
for arg in curr_platform_core_args:
setattr(args, arg, True)
handled_multiple_cores, device_handle = self.helpers.handle_cores(
args, self.logger, self.metric_core
)
if handled_multiple_cores:
return # This function is recursive
args.core = device_handle
# get core id for logging
core_id = self.helpers.get_core_id_from_device_handle(args.core)
logging.debug(f"Static Arg information for Core {core_id} on {self.helpers.os_info()}")
static_dict = {}
if self.logger.is_json_format():
static_dict["core"] = int(core_id)
if args.core_boost_limit:
static_dict["boost_limit"] = {}
try:
core_boost_limit = amdsmi_interface.amdsmi_get_cpu_core_boostlimit(args.core)
static_dict["boost_limit"]["value"] = core_boost_limit
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["boost_limit"]["value"] = "N/A"
logging.debug(
"Failed to get core boost limit for core %s | %s", core_id, e.get_error_info()
)
if args.core_curr_active_freq_core_limit:
static_dict["curr_active_freq_core_limit"] = {}
try:
freq = amdsmi_interface.amdsmi_get_cpu_core_current_freq_limit(args.core)
static_dict["curr_active_freq_core_limit"]["value"] = freq
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["curr_active_freq_core_limit"]["value"] = "N/A"
logging.debug(
"Failed to get current active frequency core for core %s | %s",
core_id,
e.get_error_info(),
)
if args.core_energy:
static_dict["core_energy"] = {}
try:
energy = amdsmi_interface.amdsmi_get_cpu_core_energy(args.core)
static_dict["core_energy"]["value"] = energy
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["core_energy"]["value"] = "N/A"
logging.debug(
"Failed to get core energy for core %s | %s", core_id, e.get_error_info()
)
if args.core_ccd_power:
static_dict["ccd_power"] = {}
try:
power = amdsmi_interface.amdsmi_get_cpu_core_ccd_power(args.core)
power = self.helpers.convert_SI_unit(float(power), self.helpers.SI_Unit.MILLI)
static_dict["ccd_power"]["value"] = f"{power:.3f} W"
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["ccd_power"]["value"] = "N/A"
logging.debug(
"Failed to get CCD power for core %s | %s", core_id, e.get_error_info()
)
if args.core_floor_limit:
static_dict["floor_limit"] = {}
try:
core_floor_limit = amdsmi_interface.amdsmi_get_cpu_core_floor_freq_limit(args.core)
static_dict["floor_limit"]["value"] = f"{core_floor_limit} MHz"
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["floor_limit"]["value"] = "N/A"
logging.debug(
"Failed to get core floor limit for core %s | %s", core_id, e.get_error_info()
)
if args.core_eff_floor_limit:
static_dict["eff_floor_limit"] = {}
try:
core_eff_floor_limit = amdsmi_interface.amdsmi_get_cpu_core_eff_floor_freq_limit(
args.core
)
static_dict["eff_floor_limit"]["value"] = f"{core_eff_floor_limit} MHz"
except amdsmi_exception.AmdSmiLibraryException as e:
static_dict["eff_floor_limit"]["value"] = "N/A"
logging.debug(
"Failed to get core effective floor limit for core %s | %s",
core_id,
e.get_error_info(),
)
multiple_devices_csv_override = False
if not self.logger.is_json_format():
self.logger.store_core_output(args.core, "values", static_dict)
else:
self.logger.store_core_json_output.append(static_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
if not self.logger.is_json_format():
self.logger.print_output(multiple_device_enabled=multiple_devices_csv_override)
def metric_nic(
self,
args,
multiple_devices=False,
watching_output=False,
watch=None,
watch_time=None,
iterations=None,
nic=None,
nic_power=None,
nic_temperature=None,
nic_errors=None,
):
"""Get Metric information for target nic
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 argument has been set. Defaults to False.
nic_power (bool, optional): Value override for args.nic_power. Defaults to None.
nic_temperature (bool, optional): Value override for args.nic_temperature. Defaults to None.
nic_errors (bool, optional): Value override for args.nic_errors. Defaults to None.
Raises:
IndexError: Index error if nic list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# Set args.* to passed in arguments
if nic:
args.nic = nic
if watch:
args.watch = watch
if watch_time:
args.watch_time = watch_time
if iterations:
args.iterations = iterations
# TODO: Need to add OS wise condition for the parameters
if nic_power:
args.nic_power = nic_power
if nic_temperature:
args.nic_temperature = nic_temperature
if nic_errors:
args.nic_errors = nic_errors
# Maintaining format as per other metric functions so above TODO can be resolved easily
current_platform_args = ["nic_power", "nic_temperature", "nic_errors"]
current_platform_values = [args.nic_power, args.nic_temperature, args.nic_errors]
# Handle No NIC passed
if args.nic == None:
args.nic = self.device_handles_brcm_nics
# Handle watch logic, will only enter this block once
if args.watch:
self.helpers.handle_watch(args=args, subcommand=self.metric_nic, logger=self.logger)
return
# Handle multiple NICs
if isinstance(args.nic, list):
if len(args.nic) > 1:
# Deepcopy nics as recursion will destroy the nic list
stored_nics = []
for nic in args.nic:
stored_nics.append(nic)
# Store output from multiple devices
for device_handle in args.nic:
self.metric_nic(
args,
multiple_devices=True,
watching_output=watching_output,
nic=device_handle,
)
# Reload original nics
args.nic = stored_nics
# Print multiple device output
self.logger.print_output(
multiple_device_enabled=True, watching_output=watching_output
)
# Add output to total watch output and clear multiple device output
if watching_output:
self.logger.store_watch_output(multiple_device_enabled=True)
# Flush the watching output
self.logger.print_output(
multiple_device_enabled=True, watching_output=watching_output
)
return
elif len(args.nic) == 1:
args.nic = args.nic[0]
else:
raise IndexError("args.nic should not be an empty list")
# Get nic_id for logging
nic_id = self.helpers.get_nic_id_from_device_handle(args.nic)
# Put the metrics table in the debug logs
nic_metric_info = {}
try:
nic_metric_info = amdsmi_interface.amdsmi_get_nic_metrics_info(args.nic)
nic_metric_str = json.dumps(nic_metric_info, indent=4)
logging.debug("NIC Metrics table for %s | %s", nic_id, nic_metric_str)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug("Unable to load NIC Metrics table for %s | %s", nic_id, e.err_info)
logging.debug(f"Metric Arg information for NIC {nic_id} on {self.helpers.os_info()}")
logging.debug(f"Args: {current_platform_args}")
logging.debug(f"Values: {current_platform_values}")
# Set the platform applicable args to True if no args are set
if not any(current_platform_values):
for arg in current_platform_args:
setattr(args, arg, True)
# Add timestamp and store values for specified arguments
values_dict = {}
if "nic_power" in current_platform_args:
if args.nic_power:
power_dict = {}
sysfs_blocks = {
"nic_power_async": "",
"nic_power_control": "",
"nic_power_runtime_active_time": "",
"nic_power_runtime_status": "",
"nic_power_runtime_usage": "",
"nic_power_runtime_active_kids": "",
"nic_power_runtime_enabled": "",
"nic_power_runtime_suspended_time": "",
}
for key in nic_metric_info.keys():
if key in sysfs_blocks.keys():
if isinstance(nic_metric_info[key], int):
value = nic_metric_info[key]
else:
value = (nic_metric_info[key].split("\n")[0]).upper()
if value == "" or value == 65535:
value = "N/A"
power_dict[key] = self.helpers.unit_format(
self.logger, value, sysfs_blocks[key]
)
values_dict["nic_power"] = power_dict
if "nic_temperature" in current_platform_args:
if args.nic_temperature:
temp_dict = {}
sysfs_blocks = {
"nic_temp_crit_alarm": "",
"nic_temp_emergency_alarm": "",
"nic_temp_shutdown_alarm": "",
"nic_temp_max_alarm": "",
"nic_temp_crit": "\N{DEGREE SIGN}C",
"nic_temp_emergency": "\N{DEGREE SIGN}C",
"nic_temp_input": "\N{DEGREE SIGN}C",
"nic_temp_max": "\N{DEGREE SIGN}C",
"nic_temp_shutdown": "\N{DEGREE SIGN}C",
}
for key in nic_metric_info.keys():
if key in sysfs_blocks.keys():
if isinstance(nic_metric_info[key], int):
value = nic_metric_info[key]
else:
value = (nic_metric_info[key].split("\n")[0]).upper()
if value == "" or value == 65535:
value = "N/A"
temp_dict[key] = self.helpers.unit_format(
self.logger, value, sysfs_blocks[key]
)
values_dict["nic_temperature"] = temp_dict
if "nic_errors" in current_platform_args:
if args.nic_errors:
err_dict = {}
sysfs_blocks = ["nic_dev_correctable", "nic_dev_fatal", "nic_dev_nonfatal"]
for key in nic_metric_info.keys():
if key in sysfs_blocks:
err_dict[key] = {}
content_list = nic_metric_info[key].split("\n")
for content in content_list:
if content != "" and content.lower() != "n/a":
err_dict[key][content.split(" ")[0]] = content.split(" ")[1]
values_dict["nic_errors"] = err_dict
# Store timestamp first if watching_output is enabled
if watching_output:
self.logger.store_nic_output(args.nic, "timestamp", int(time.time()))
self.logger.store_nic_output(args.nic, "values", values_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output(watching_output=watching_output)
if watching_output: # End of single gpu add to watch_output
self.logger.store_watch_output(multiple_device_enabled=False)
def metric_switch(
self,
args,
multiple_devices=False,
watching_output=False,
watch=None,
watch_time=None,
iterations=None,
switch=None,
switch_power=None,
switch_errors=None,
):
"""Get Metric information for target switch
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 argument has been set. Defaults to False.
switch_power (bool, optional): Value override for args.switch_power. Defaults to None.
switch_errors (bool, optional): Value override for args.switch_errors. Defaults to None.
Raises:
IndexError: Index error if switch list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# Set args.* to passed in arguments
if switch:
args.switch = switch
if watch:
args.watch = watch
if watch_time:
args.watch_time = watch_time
if iterations:
args.iterations = iterations
# TODO: Need to add OS wise condition for the parameters
if switch_power:
args.switch_power = switch_power
if switch_errors:
args.switch_errors = switch_errors
# Maintaining format as per other metric functions so above TODO can be resolved easily
current_platform_args = ["switch_power", "switch_errors"]
current_platform_values = [args.switch_power, args.switch_errors]
# Handle No SWITCH passed
if args.switch == None:
args.switch = self.device_handles_switchs
# Handle watch logic, will only enter this block once
if args.watch:
self.helpers.handle_watch(args=args, subcommand=self.metric_switch, logger=self.logger)
return
# Handle multiple Switches
if isinstance(args.switch, list):
if len(args.switch) > 1:
# Deepcopy switches as recursion will destroy the switch list
stored_switches = []
for switch in args.switch:
stored_switches.append(switch)
# Store output from multiple devices
for device_handle in args.switch:
self.metric_switch(
args,
multiple_devices=True,
watching_output=watching_output,
switch=device_handle,
)
# Reload original switches
args.switch = stored_switches
# Print multiple device output
self.logger.print_output(
multiple_device_enabled=True, watching_output=watching_output
)
# Add output to total watch output and clear multiple device output
if watching_output:
self.logger.store_watch_output(multiple_device_enabled=True)
# Flush the watching output
self.logger.print_output(
multiple_device_enabled=True, watching_output=watching_output
)
return
elif len(args.switch) == 1:
args.switch = args.switch[0]
else:
return # intermittent issue with args.switch being an empty list. raise IndexError("args.switch should not be an empty list")
# Get switch_id for logging
switch_id = self.helpers.get_switch_id_from_device_handle(args.switch)
# Put the metrics table in the debug logs
switch_metric_info = {}
try:
switch_metric_info = amdsmi_interface.amdsmi_get_switch_metrics_info(args.switch)
switch_metric_str = json.dumps(switch_metric_info, indent=4)
logging.debug("SWITCH Metrics table for %s | %s", switch_id, switch_metric_str)
except amdsmi_exception.AmdSmiLibraryException as e:
logging.debug("Unable to load SWITCH Metrics table for %s | %s", switch_id, e.err_info)
logging.debug(f"Metric Arg information for SWITCH {switch_id} on {self.helpers.os_info()}")
logging.debug(f"Args: {current_platform_args}")
logging.debug(f"Values: {current_platform_values}")
# Set the platform applicable args to True if no args are set
if not any(current_platform_values):
for arg in current_platform_args:
setattr(args, arg, True)
# Add timestamp and store values for specified arguments
values_dict = {}
if "switch_power" in current_platform_args:
if args.switch_power:
power_dict = {}
sysfs_blocks = {
"brcm_power_async": "",
"brcm_power_control": "",
"brcm_power_runtime_active_kids": "",
"brcm_power_runtime_active_time": "",
"brcm_power_runtime_enabled": "",
"brcm_power_runtime_status": "",
"brcm_power_runtime_suspended_time": "",
"brcm_power_runtime_usage": "",
"brcm_power_wakeup": "",
"brcm_power_wakeup_abort_count": "",
"brcm_power_wakeup_active": "",
"brcm_power_wakeup_active_count": "",
"brcm_power_wakeup_count": "",
"brcm_power_wakeup_last_time_ms": "",
"brcm_power_wakeup_max_time_ms": "",
"brcm_power_wakeup_total_time_ms": "",
}
for key in switch_metric_info.keys():
if key in sysfs_blocks.keys():
if isinstance(switch_metric_info[key], int):
value = switch_metric_info[key]
else:
value = (switch_metric_info[key].split("\n")[0]).upper()
if value == "":
value = "N/A"
power_dict[key] = self.helpers.unit_format(
self.logger, value, sysfs_blocks[key]
)
values_dict["switch_power"] = power_dict
if "switch_errors" in current_platform_args:
if args.switch_errors:
err_dict = {}
sysfs_blocks = [
"brcm_device_aer_dev_correctable",
"brcm_device_aer_dev_fatal",
"brcm_device_aer_dev_nonfatal",
]
for key in switch_metric_info.keys():
if key in sysfs_blocks:
err_dict[key] = {}
if switch_metric_info[key] == "N/A":
continue
content_list = switch_metric_info[key].split("\n")
for content in content_list:
if content != "":
err_dict[key][content.split(" ")[0]] = content.split(" ")[1]
values_dict["switch_errors"] = err_dict
# TODO: ADD "NA" conditions in interface file
# Store timestamp first if watching_output is enabled
if watching_output:
self.logger.store_switch_output(args.switch, "timestamp", int(time.time()))
self.logger.store_switch_output(args.switch, "values", values_dict)
if multiple_devices:
self.logger.store_multiple_device_output()
return # Skip printing when there are multiple devices
self.logger.print_output(watching_output=watching_output)
if watching_output: # End of single gpu add to watch_output
self.logger.store_watch_output(multiple_device_enabled=False)
def metric(
self,
args,
multiple_devices=False,
watching_output=False,
gpu=None,
nic=None,
nic_power=None,
nic_temperature=None,
nic_errors=None,
brcm_nic=None,
switch=None,
switch_power=None,
switch_errors=None,
brcm_switch=None,
usage=None,
watch=None,
watch_time=None,
iterations=None,
power=None,
clock=None,
temperature=None,
ecc=None,
ecc_blocks=None,
pcie=None,
fan=None,
voltage_curve=None,
overdrive=None,
perf_level=None,
xgmi_err=None,
energy=None,
mem_usage=None,
voltage=None,
schedule=None,
guard=None,
guest_data=None,
fb_usage=None,
xgmi=None,
cpu=None,
cpu_power_metrics=None,
cpu_prochot=None,
cpu_freq_metrics=None,
cpu_c0_res=None,
cpu_lclk_dpm_level=None,
cpu_pwr_svi_telemetry_rails=None,
cpu_io_bandwidth=None,
cpu_xgmi_bandwidth=None,
cpu_pwr_eff_mode=None,
cpu_metrics_ver=None,
cpu_metrics_table=None,
cpu_socket_energy=None,
cpu_ddr_bandwidth=None,
cpu_temp=None,
cpu_dimm_temp_range_rate=None,
cpu_dimm_pow_consumption=None,
cpu_dimm_thermal_sensor=None,
cpu_xgmi_pstate_range=None,
cpu_railisofreq_policy=None,
cpu_dfcstate_ctrl=None,
cpu_pc6_enable=None,
cpu_cc6_enable=None,
cpu_dimm_sb_reg=None,
cpu_tdelta=None,
cpu_svi3_vr_controller_temp=None,
cpu_enabled_commands=None,
cpu_sdps_limit=None,
core=None,
core_boost_limit=None,
core_curr_active_freq_core_limit=None,
core_energy=None,
core_ccd_power=None,
core_floor_limit=None,
core_eff_floor_limit=None,
throttle=None,
base_board=None,
gpu_board=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 argument 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.
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.
ecc_blocks (bool, optional): Value override for args.ecc. Defaults to None.
pcie (bool, optional): Value override for args.pcie. Defaults to None.
fan (bool, optional): Value override for args.fan. 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.
perf_level (bool, optional): Value override for args.perf_level. 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.
voltage (bool, optional): Value override for args.voltage. Defaults to None.
schedule (bool, optional): Value override for args.schedule. Defaults to None.
guard (bool, optional): Value override for args.guard. Defaults to None.
guest_data (bool, optional): Value override for args.guest_data. Defaults to None.
fb_usage (bool, optional): Value override for args.fb_usage. Defaults to None.
xgmi (bool, optional): Value override for args.xgmi. Defaults to None.
cpu (cpu_handle, optional): device_handle for target device. Defaults to None.
cpu_power_metrics (bool, optional): Value override for args.cpu_power_metrics. Defaults to None
cpu_prochot (bool, optional): Value override for args.cpu_prochot. Defaults to None.
cpu_freq_metrics (bool, optional): Value override for args.cpu_freq_metrics. Defaults to None.
cpu_c0_res (bool, optional): Value override for args.cpu_c0_res. Defaults to None
cpu_lclk_dpm_level (list, optional): Value override for args.cpu_lclk_dpm_level. Defaults to None
cpu_pwr_svi_telemetry_rails (list, optional): value override for args.cpu_pwr_svi_telemetry_rails. Defaults to None
cpu_io_bandwidth (list, optional): value override for args.cpu_io_bandwidth. Defaults to None
cpu_xgmi_bandwidth (list, optional): value override for args.cpu_xgmi_bandwidth. Defaults to None
cpu_pwr_eff_mode (bool, optional): Value override for args.cpu_pwr_eff_mode. Defaults to None
cpu_metrics_ver (bool, optional): Value override for args.cpu_metrics_ver. Defaults to None
cpu_metrics_table (bool, optional): Value override for args.cpu_metrics_table. Defaults to None
cpu_socket_energy (bool, optional): Value override for args.cpu_socket_energy. Defaults to None
cpu_ddr_bandwidth (bool, optional): Value override for args.cpu_ddr_bandwidth. Defaults to None
cpu_temp (bool, optional): Value override for args.cpu_temp. Defaults to None
cpu_dimm_temp_range_rate (list, optional): Dimm address. Value override for args.cpu_dimm_temp_range_rate. Defaults to None
cpu_dimm_pow_consumption (list, optional): Dimm address. Value override for args.cpu_dimm_pow_consumption. Defaults to None
cpu_dimm_thermal_sensor (list, optional): Dimm address. Value override for args.cpu_dimm_thermal_sensor. Defaults to None
cpu_xgmi_pstate_range (bool, optional): Value override for args.cpu_xgmi_pstate_range. Defaults to None
cpu_railisofreq_policy (bool, optional): Value override for args.cpu_railisofreq_policy. Defaults to None
cpu_dfcstate_ctrl (bool, optional): Value override for args.cpu_dfcstate_ctrl. Defaults to None
cpu_pc6_enable (bool, optional): Value override for args.cpu_pc6_enable. Defaults to None
cpu_cc6_enable (bool, optional): Value override for args.cpu_cc6_enable. Defaults to None
cpu_dimm_sb_reg (list, optional): DIMM sideband register parameters [dimm_addr, lid, reg_offset, reg_space] for read. Value override for args.cpu_dimm_sb_reg. Defaults to None
cpu_tdelta (bool, optional): Value override for args.cpu_tdelta. Defaults to None
cpu_svi3_vr_controller_temp (list, optional): TYPE and optional RAIL_INDEX. Value override for args.cpu_svi3_vr_controller_temp. Defaults to None
cpu_enabled_commands (bool, optional): Value override for args.cpu_enabled_commands. Defaults to None
cpu_sdps_limit (bool, optional): Value override for args.cpu_sdps_limit. Defaults to None
core (device_handle, optional): device_handle for target core. Defaults to None.
core_boost_limit (bool, optional): Value override for args.core_boost_limit. Defaults to None
core_curr_active_freq_core_limit (bool, optional): Value override for args.core_curr_active_freq_core_limit. Defaults to None
core_energy (bool, optional): Value override for args.core_energy. Defaults to None
core_ccd_power (bool, optional): Value override for args.core_ccd_power. Defaults to None
core_floor_limit (bool, optional): Value override for args.core_floor_limit. Defaults to None
core_eff_floor_limit (bool, optional): Value override for args.core_eff_floor_limit. Defaults to None
nic (nic_handle, optional): device_handle for target device. Defaults to None.
nic_power (bool, optional): Value override for args.nic_power. Defaults to None.
nic_temperature (bool, optional): Value override for args.nic_temperature. Defaults to None.
nic_errors (bool, optional): Value override for args.nic_errors. Defaults to None.
brcm_nic (bool, optional): Value override for args.brcm_nic. Defaults to None.
switch (cpu_handle, optional): device_handle for target device. Defaults to None.
switch_power (bool, optional): Value override for args.switch_power. Defaults to None.
switch_errors (bool, optional): Value override for args.switch_errors. Defaults to None.
brcm_switch (bool, optional): Value override for args.brcm_switch. Defaults to None.
Raises:
IndexError: Index error if gpu list is empty
Returns:
None: Print output via AMDSMILogger to destination
"""
# TODO Move watch logic into here and make it driver agnostic or enable it for CPU arguments
# Mutually exclusive args
if gpu:
args.gpu = gpu
if cpu:
args.cpu = cpu
if core:
args.core = core
if self.helpers.is_brcm_nic_initialized() and (
getattr(args, "brcm_nic", False) or brcm_nic
):
args.nic_power = args.power
args.nic_temperature = args.temperature
args.nic_errors = args.ecc
self.logger.output = {}
self.logger.clear_multiple_devices_output()
self.metric_nic(
args,
multiple_devices,
watching_output,
watch,
watch_time,
iterations,
nic,
nic_power,
nic_temperature,
nic_errors,
)
return
if self.helpers.is_brcm_switch_initialized() and (
getattr(args, "brcm_switch", False) or brcm_switch
):
args.switch_power = args.power
args.switch_errors = args.ecc
self.logger.output = {}
self.logger.clear_multiple_devices_output()
self.metric_switch(
args,
multiple_devices,
watching_output,
watch,
watch_time,
iterations,
switch,
switch_power,
switch_errors,
)
return
# Check if a GPU argument has been set
gpu_args_enabled = False
gpu_attributes = [
"usage",
"watch",
"watch_time",
"iterations",
"power",
"clock",
"temperature",
"ecc",
"ecc_blocks",
"pcie",
"fan",
"voltage_curve",
"overdrive",
"perf_level",
"xgmi_err",
"energy",
"mem_usage",
"voltage",
"schedule",
"guard",
"guest_data",
"fb_usage",
"xgmi",
"throttle",
"base_board",
"gpu_board",
]
for attr in gpu_attributes:
if hasattr(args, attr):
if getattr(args, attr):
gpu_args_enabled = True
break
# Check if a CPU argument has been set
cpu_args_enabled = False
cpu_attributes = [
"cpu_power_metrics",
"cpu_prochot",
"cpu_freq_metrics",
"cpu_c0_res",
"cpu_lclk_dpm_level",
"cpu_pwr_svi_telemetry_rails",
"cpu_io_bandwidth",
"cpu_xgmi_bandwidth",
"cpu_pwr_eff_mode",
"cpu_metrics_ver",
"cpu_metrics_table",
"cpu_socket_energy",
"cpu_ddr_bandwidth",
"cpu_temp",
"cpu_dimm_temp_range_rate",
"cpu_dimm_pow_consumption",
"cpu_dimm_thermal_sensor",
"cpu_xgmi_pstate_range",
"cpu_railisofreq_policy",
"cpu_dfcstate_ctrl",
"cpu_pc6_enable",
"cpu_cc6_enable",
"cpu_dimm_sb_reg",
"cpu_tdelta",
"cpu_svi3_vr_controller_temp",
"cpu_enabled_commands",
"cpu_sdps_limit",
]
for attr in cpu_attributes:
if hasattr(args, attr):
if getattr(args, attr):
cpu_args_enabled = True
break
# Check if a Core argument has been set
core_args_enabled = False
core_attributes = [
"core_boost_limit",
"core_curr_active_freq_core_limit",
"core_energy",
"core_ccd_power",
"core_floor_limit",
"core_eff_floor_limit",
]
for attr in core_attributes:
if hasattr(args, attr):
if getattr(args, attr):
core_args_enabled = True
break
# Handle CPU and GPU driver initialization cases
if self.helpers.is_amd_hsmp_initialized() and self.helpers.is_amdgpu_initialized():
logging.debug(
"gpu_args_enabled: %s, cpu_args_enabled: %s, core_args_enabled: %s",
gpu_args_enabled,
cpu_args_enabled,
core_args_enabled,
)
logging.debug(
"args.gpu: %s, args.cpu: %s, args.core: %s", args.gpu, args.cpu, args.core
)
# If a GPU or CPU argument is provided only print out the specified device.
if args.cpu == None and args.gpu == None and args.core == None:
# If no args are set, print out all CPU, GPU, and Core metrics info
if not gpu_args_enabled and not cpu_args_enabled and not core_args_enabled:
args.cpu = self.cpu_handles
args.gpu = self.device_handles
args.core = self.core_handles
# Handle cases where the user has only specified an argument and no specific device
if args.gpu == None and gpu_args_enabled:
args.gpu = self.device_handles
if args.cpu == None and cpu_args_enabled:
args.cpu = self.cpu_handles
if args.core == None and core_args_enabled:
args.core = self.core_handles
# Print out CPU first
if args.cpu:
self.metric_cpu(
args,
multiple_devices,
cpu,
cpu_power_metrics,
cpu_prochot,
cpu_freq_metrics,
cpu_c0_res,
cpu_lclk_dpm_level,
cpu_pwr_svi_telemetry_rails,
cpu_io_bandwidth,
cpu_xgmi_bandwidth,
cpu_pwr_eff_mode,
cpu_metrics_ver,
cpu_metrics_table,
cpu_socket_energy,
cpu_ddr_bandwidth,
cpu_temp,
cpu_dimm_temp_range_rate,
cpu_dimm_pow_consumption,
cpu_dimm_thermal_sensor,
cpu_xgmi_pstate_range,
cpu_railisofreq_policy,
cpu_dfcstate_ctrl,
cpu_pc6_enable,
cpu_cc6_enable,
cpu_dimm_sb_reg,
cpu_tdelta,
cpu_svi3_vr_controller_temp,
cpu_enabled_commands,
cpu_sdps_limit,
)
if args.core:
self.logger.output = {}
self.logger.clear_multiple_devices_output()
self.metric_core(
args,
multiple_devices,
core,
core_boost_limit,
core_curr_active_freq_core_limit,
core_energy,
core_ccd_power,
core_floor_limit,
core_eff_floor_limit,
)
if args.gpu:
self.logger.output = {}
self.logger.clear_multiple_devices_output()
self.metric_gpu(
args,
multiple_devices,
watching_output,
gpu,
usage,
watch,
watch_time,
iterations,
power,
clock,
temperature,
ecc,
ecc_blocks,
pcie,
fan,
voltage_curve,
overdrive,
perf_level,
xgmi_err,
energy,
mem_usage,
voltage,
schedule,
guard,
guest_data,
fb_usage,
xgmi,
throttle,
base_board,
gpu_board,
)
elif self.helpers.is_amd_hsmp_initialized(): # Only CPU is initialized
if args.cpu == None and args.core == None:
# If no args are set, print out all CPU and Core metrics info
if not cpu_args_enabled and not core_args_enabled:
args.cpu = self.cpu_handles
args.core = self.core_handles
if args.cpu == None and cpu_args_enabled:
args.cpu = self.cpu_handles
if args.core == None and core_args_enabled:
args.core = self.core_handles
if args.cpu:
self.metric_cpu(
args,
multiple_devices,
cpu,
cpu_power_metrics,
cpu_prochot,
cpu_freq_metrics,
cpu_c0_res,
cpu_lclk_dpm_level,
cpu_pwr_svi_telemetry_rails,
cpu_io_bandwidth,
cpu_xgmi_bandwidth,
cpu_pwr_eff_mode,
cpu_metrics_ver,
cpu_metrics_table,
cpu_socket_energy,
cpu_ddr_bandwidth,
cpu_temp,
cpu_dimm_temp_range_rate,
cpu_dimm_pow_consumption,
cpu_dimm_thermal_sensor,
cpu_xgmi_pstate_range,
cpu_railisofreq_policy,
cpu_dfcstate_ctrl,
cpu_pc6_enable,
cpu_cc6_enable,
cpu_dimm_sb_reg,
cpu_tdelta,
cpu_svi3_vr_controller_temp,
cpu_enabled_commands,
cpu_sdps_limit,
)
if args.core:
self.logger.output = {}
self.logger.clear_multiple_devices_output()
self.metric_core(
args,
multiple_devices,
core,
core_boost_limit,
core_curr_active_freq_core_limit,
core_energy,
core_ccd_power,
core_floor_limit,
core_eff_floor_limit,
)
elif self.helpers.is_amdgpu_initialized(): # Only GPU is initialized
if args.gpu == None:
args.gpu = self.device_handles
self.logger.clear_multiple_devices_output()
self.metric_gpu(
args,
multiple_devices,
watching_output,
gpu,
usage,
watch,
watch_time,
iterations,
power,
clock,
temperature,
ecc,
ecc_blocks,
pcie,
fan,
voltage_curve,
overdrive,
perf_level,
xgmi_err,
energy,
mem_usage,
voltage,
schedule,
throttle,
base_board,
gpu_board,
)
if self.logger.is_json_format():
self.logger.combine_arrays_to_json()