Files
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

256 lines
11 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.
"""CLI leaf test: set command."""
import common.common as common
from common.common import amdsmi
from cli.base import TestCliBase
def _strip_prefix(value, prefix):
# Backport of str.removeprefix() (added in Python 3.9) because the test suite
# still supports Python 3.8. Strips a leading enum-name prefix (e.g.
# "AMDSMI_DEV_PERF_LEVEL_") when present, otherwise returns value unchanged.
if value.startswith(prefix):
return value[len(prefix) :]
return value
class TestSet(TestCliBase):
def test_command(self):
self.common.print_func_name("")
msg = f"{self.tab}### amd-smi set"
self.common.print(msg)
# Get current settings
power_profile = {}
for index, gpu in enumerate(self.common.processors):
try:
power_profile[index] = amdsmi.amdsmi_get_gpu_power_profile_presets(gpu, 0)
except amdsmi.AmdSmiLibraryException:
power_profile[index] = None
cmds = self.CreateCmds(
"set", "Set Arguments:", "Device Arguments:", "Command Modifiers:", ""
)
self.RunCmds(cmds)
# Restore starting values
cmds = []
for index, gpu in enumerate(self.common.processors):
# Validate max fan speed is sensible; gpu_od GPUs must report <= 100
fan_max = self.metric_data["gpu_data"][index]["fan"]["max"]
if fan_max != "N/A":
self.assertGreater(fan_max, 0, f"GPU {index}: max fan speed must be > 0")
# Detect gpu_od interface via sysfs for this GPU
gpu_bdf = self.list_data[index]["bdf"]
has_gpu_od = common.has_gpu_od_interface(gpu_bdf)
if has_gpu_od:
self.assertLessEqual(
fan_max, 100, f"GPU {index}: gpu_od max fan speed must be <= 100"
)
else:
self.assertLessEqual(fan_max, 255, f"GPU {index}: max fan speed must be <= 255")
# reset --fans (works for both legacy hwmon and gpu_od interfaces)
fan_speed = self.metric_data["gpu_data"][index]["fan"]["speed"]
if fan_speed != "N/A":
cmds.append((f"amd-smi reset --fans --gpu {index}", self.PASS))
# set --perf-level defaults
perf_level = self.metric_data["gpu_data"][index]["perf_level"]
if perf_level != "N/A":
perf_level = _strip_prefix(perf_level, "AMDSMI_DEV_PERF_LEVEL_")
cmds.append((f"amd-smi set --perf-level {perf_level} --gpu {index}", self.PASS))
# set --profile defaults
if power_profile[index]:
profile = _strip_prefix(power_profile[index]["current"], "AMDSMI_PWR_PROF_PRST_")
cmds.append((f"amd-smi set --profile {profile} --gpu {index}", self.PASS))
# set --perf-determinism defaults
clock_sys = self.static_data["gpu_data"][index]["clock"]["sys"]
if clock_sys != "N/A":
num = len(clock_sys["frequency_levels"])
level = f"Level {num - 1}"
clock_freq = int(clock_sys["frequency_levels"][level]["value"])
cmds.append(
(f"amd-smi set --perf-determinism {clock_freq} --gpu {index}", self.PASS)
)
# set --compute-partition defaults
accelerator_type = self.partition_data["current_partition"][index]["accelerator_type"]
if accelerator_type != "N/A":
cmds.append(
(f"amd-smi set --compute-partition {accelerator_type} --gpu {index}", self.PASS)
)
# set --memory-partition defaults
memory_partition = self.partition_data["current_partition"][index]["memory"]
if memory_partition != "N/A":
cmds.append(
(f"amd-smi set --memory-partition {memory_partition} --gpu {index}", self.PASS)
)
# set --compute-partition-mem-alloc-mode defaults
try:
mem_alloc_mode = self.static_data["gpu_data"][index]["partition"][
"compute_partition_mem_alloc_mode"
]
except (KeyError, TypeError):
mem_alloc_mode = "N/A"
if mem_alloc_mode not in ("N/A", "INVALID"):
cmds.append(
(
f"amd-smi set --compute-partition-mem-alloc-mode {mem_alloc_mode} --gpu {index}",
self.PASS,
)
)
# set --power-cap defaults
for power_type in self.power_types:
_power_type = self.static_data["gpu_data"][index]["limit"][power_type]
socket_power_limit = _power_type["socket_power_limit"]
if socket_power_limit != "N/A":
socket_power = socket_power_limit["value"]
cmds.append(
(
f"amd-smi set --power-cap {socket_power} {power_type} --gpu {index}",
self.PASS,
)
)
# Both bounds are inclusive: the exact min and max must
# succeed. A reported min of 0 means the technical minimum
# is 1, since setting 0 reads back the current cap.
min_power = max(_power_type["min_power_limit"]["value"], 1)
max_power = _power_type["max_power_limit"]["value"]
cmds.append(
(
f"amd-smi set --power-cap {min_power} {power_type} --gpu {index}",
self.PASS,
)
)
cmds.append(
(
f"amd-smi set --power-cap {max_power} {power_type} --gpu {index}",
self.PASS,
)
)
# set --soc-pstate defaults
soc_pstate = self.static_data["gpu_data"][index]["soc_pstate"]
if soc_pstate != "N/A":
current = int(soc_pstate["current"])
cmds.append((f"amd-smi set --soc-pstate {current} --gpu {index}", self.PASS))
# set --xgmi-plpd defaults
xgmi_plpd = self.static_data["gpu_data"][index]["xgmi_plpd"]
if xgmi_plpd != "N/A":
current = int(xgmi_plpd["current"])
cmds.append((f"amd-smi set --xgmi-plpd {current} --gpu {index}", self.PASS))
# set --ptl-status defaults
ptl_state = self.static_data["gpu_data"][index]["limit"]["ptl_state"]
if ptl_state != "N/A":
if ptl_state == "Disabled":
ptl_state_value = 0
else:
ptl_state_value = 1
cmds.append(
(f"amd-smi set --ptl-status {ptl_state_value} --gpu {index}", self.PASS)
)
# set --ptl-format defaults
ptl_format = self.static_data["gpu_data"][index]["limit"]["ptl_format"]
if ptl_format != "N/A":
# TODO: get the right ptl-format
cmds.append((f"amd-smi set --ptl-format {ptl_format} --gpu {index}", self.PASS))
# set --clk-limit defaults
clock = self.metric_data["gpu_data"][index]["clock"]
for clk_type in self.clk_limits:
if clk_type == "SCLK":
clk_type_name = "socclk_0"
else:
clk_type_name = "mem_0"
for limit_type in self.limit_types:
if limit_type == "MIN":
clk_limit_name = "min_clk"
else:
clk_limit_name = "max_clk"
clk_type_limit_name = clock[clk_type_name][clk_limit_name]
if type(clk_type_limit_name) is dict:
value = clk_type_limit_name["value"]
cmds.append(
(
f"amd-smi set --clk-limit {clk_type} {limit_type} {value} --gpu {index}",
self.PASS,
)
)
# set --clk-level defaults
clock = self.static_data["gpu_data"][index]["clock"]
for clk_type in self.clk_levels:
value = -1
clk_type_name = ""
if clk_type == "SCLK":
clk_type_name = "sys"
elif clk_type == "MCLK":
clk_type_name = "mem"
elif clk_type == "FCLK":
clk_type_name = "df"
elif clk_type == "SOCCLK":
clk_type_name = "soc"
else:
bus = self.static_data["gpu_data"][index]["bus"]
pcie_levels = bus["pcie_levels"]
if type(pcie_levels) is dict:
value = len(pcie_levels)
if value > 0:
value -= 1
if clk_type != "PCIE" and value < 0:
clk_type_name = clock[clk_type_name]
if type(clk_type_name) is dict:
current_level = clk_type_name["current_level"]
value = current_level
if value >= 0:
cmds.append(
(f"amd-smi set --clk-level {clk_type} {value} --gpu {index}", self.PASS)
)
# set --process-isolation defaults
process_isolation = self.static_data["gpu_data"][index]["process_isolation"]
if process_isolation == "Disabled":
process_isolation_value = 0
else:
process_isolation_value = 1
cmds.append(
(
f"amd-smi set --process-isolation {process_isolation_value} --gpu {index}",
self.PASS,
)
)
print("Restore Starting Values")
self.RunCmds(cmds)
return