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
256 lines
11 KiB
Python
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
|