Commit be036ead authored by one's avatar one
Browse files

[hytop] Rename `--showhcuclocks` to `--showsclk` and update help texts for show flags

parent 15f150c7
......@@ -85,12 +85,12 @@ Designed to be script-friendly:
- `--showtemp`: GPU core temperature (`Temp`)
- `--showpower`: average package power (`AvgPwr`, plus `AvgPwr@window`)
- `--showhcuclocks`: sclk frequency (`sclk`)
- `--showsclk`: sclk frequency (`sclk`)
- `--showmemuse`: VRAM usage (`VRAM%`)
- `--showuse`: GPU utilization (`GPU%`, plus `GPU%@window`)
If no `--show*` flags are specified, hytop defaults to:
`--showtemp --showpower --showhcuclocks --showmemuse --showuse`.
`--showtemp --showpower --showsclk --showmemuse --showuse`.
## Development
......
......@@ -4,7 +4,12 @@ from typing import Optional, Set
import typer
from hytop.gpu.metrics import SUPPORTED_SHOW_FLAGS, normalized_show_flags
from hytop.gpu.metrics import (
SHOW_FLAG_HELP,
SUPPORTED_SHOW_FLAGS,
is_supported_show_flag,
normalized_show_flags,
)
from hytop.gpu.service import run_monitor
from hytop.core.validators import parse_csv_ints
......@@ -22,7 +27,7 @@ def remember_show_flag_callback(ctx: typer.Context, param: object, value: bool)
if not value:
return value
flag = getattr(param, "name", None)
if not isinstance(flag, str) or flag not in SUPPORTED_SHOW_FLAGS:
if not isinstance(flag, str) or not is_supported_show_flag(flag):
return value
ordered = ctx.meta.setdefault(SHOW_FLAG_ORDER_KEY, [])
if flag not in ordered:
......@@ -53,31 +58,31 @@ def gpu(
False,
"--showtemp",
callback=remember_show_flag_callback,
help="Display GPU core temperature.",
help=SHOW_FLAG_HELP["showtemp"],
),
showpower: bool = typer.Option(
False,
"--showpower",
callback=remember_show_flag_callback,
help="Display average GPU power.",
help=SHOW_FLAG_HELP["showpower"],
),
showhcuclocks: bool = typer.Option(
showsclk: bool = typer.Option(
False,
"--showhcuclocks",
"--showsclk",
callback=remember_show_flag_callback,
help="Display GPU sclk frequency.",
help=SHOW_FLAG_HELP["showsclk"],
),
showmemuse: bool = typer.Option(
False,
"--showmemuse",
callback=remember_show_flag_callback,
help="Display GPU VRAM usage.",
help=SHOW_FLAG_HELP["showmemuse"],
),
showuse: bool = typer.Option(
False,
"--showuse",
callback=remember_show_flag_callback,
help="Display GPU utilization.",
help=SHOW_FLAG_HELP["showuse"],
),
) -> None:
"""GPU monitoring commands."""
......@@ -91,12 +96,9 @@ def gpu(
interval = ctx.obj["interval"]
window_value = ctx.obj["window"]
timeout_value = ctx.obj.get("timeout")
local_flags = locals()
selected_show_flags = {
"showtemp": showtemp,
"showpower": showpower,
"showhcuclocks": showhcuclocks,
"showmemuse": showmemuse,
"showuse": showuse,
flag: bool(local_flags.get(flag, False)) for flag in SUPPORTED_SHOW_FLAGS
}
requested_order = [
flag
......
from __future__ import annotations
from dataclasses import dataclass
from typing import Final, Iterable
from typing import Final, Iterable, Literal, TypeAlias, TypeGuard
ShowFlag: TypeAlias = Literal[
"showtemp",
"showpower",
"showsclk",
"showmemuse",
"showuse",
]
@dataclass(frozen=True)
......@@ -13,9 +22,11 @@ class RenderColumn:
@dataclass(frozen=True)
class ShowSpec:
flag: str
flag: ShowFlag
metric_json_keys: dict[str, str]
columns: tuple[RenderColumn, ...]
cli_help: str
hy_smi_flag: str | None = None
SHOW_SPECS: Final[tuple[ShowSpec, ...]] = (
......@@ -23,34 +34,44 @@ SHOW_SPECS: Final[tuple[ShowSpec, ...]] = (
flag="showtemp",
metric_json_keys={"temp_c": "Temperature (Sensor core) (C)"},
columns=(RenderColumn(label="Temp", metric="temp_c"),),
cli_help="Display GPU core temperature.",
),
ShowSpec(
flag="showpower",
metric_json_keys={"avg_pwr_w": "Average Graphics Package Power (W)"},
columns=(RenderColumn(label="AvgPwr", metric="avg_pwr_w", avg_label="AvgPwr"),),
cli_help="Display average GPU power.",
),
ShowSpec(
flag="showhcuclocks",
flag="showsclk",
metric_json_keys={"sclk_mhz": "sclk clock speed"},
columns=(RenderColumn(label="sclk", metric="sclk_mhz"),),
cli_help="Display GPU sclk frequency.",
hy_smi_flag="showhcuclocks",
),
ShowSpec(
flag="showmemuse",
metric_json_keys={"vram_pct": "HCU memory use (%)"},
columns=(RenderColumn(label="VRAM%", metric="vram_pct"),),
cli_help="Display GPU VRAM usage.",
),
ShowSpec(
flag="showuse",
metric_json_keys={"hcu_pct": "HCU use (%)"},
columns=(RenderColumn(label="GPU%", metric="hcu_pct", avg_label="GPU%"),),
cli_help="Display GPU utilization.",
),
)
SPEC_BY_FLAG: Final[dict[str, ShowSpec]] = {spec.flag: spec for spec in SHOW_SPECS}
SPEC_BY_FLAG: Final[dict[ShowFlag, ShowSpec]] = {spec.flag: spec for spec in SHOW_SPECS}
SUPPORTED_SHOW_FLAGS: Final[tuple[ShowFlag, ...]] = tuple(spec.flag for spec in SHOW_SPECS)
DEFAULT_SHOW_FLAGS: Final[tuple[ShowFlag, ...]] = SUPPORTED_SHOW_FLAGS
SUPPORTED_SHOW_FLAGS: Final[tuple[str, ...]] = tuple(spec.flag for spec in SHOW_SPECS)
SHOW_FLAG_HELP: Final[dict[ShowFlag, str]] = {spec.flag: spec.cli_help for spec in SHOW_SPECS}
DEFAULT_SHOW_FLAGS: Final[tuple[str, ...]] = SUPPORTED_SHOW_FLAGS
WAIT_IDLE_REQUIRED_SHOW_FLAGS: Final[tuple[ShowFlag, ...]] = ("showmemuse", "showuse")
JSON_KEY_BY_METRIC: Final[dict[str, str]] = {
metric: json_key
......@@ -59,17 +80,24 @@ JSON_KEY_BY_METRIC: Final[dict[str, str]] = {
}
def normalized_show_flags(show_flags: Iterable[str] | None) -> list[str]:
def is_supported_show_flag(flag: str) -> TypeGuard[ShowFlag]:
"""Return True when the provided flag belongs to the supported show-flag set."""
return flag in SPEC_BY_FLAG
def normalized_show_flags(show_flags: Iterable[str] | None) -> list[ShowFlag]:
"""Normalize user-selected show flags, preserving order and uniqueness."""
if not show_flags:
return list(DEFAULT_SHOW_FLAGS)
output: list[str] = []
output: list[ShowFlag] = []
for flag in show_flags:
if flag not in SPEC_BY_FLAG:
spec = SPEC_BY_FLAG.get(flag)
if spec is None:
continue
if flag not in output:
output.append(flag)
if spec.flag not in output:
output.append(spec.flag)
return output if output else list(DEFAULT_SHOW_FLAGS)
......@@ -79,11 +107,15 @@ def hy_smi_args_for_show_flags(show_flags: Iterable[str], wait_idle: bool) -> li
ordered_flags = normalized_show_flags(show_flags)
if wait_idle:
# wait-idle relies on usage+memory metrics even when not displayed.
for required in ("showmemuse", "showuse"):
for required in WAIT_IDLE_REQUIRED_SHOW_FLAGS:
if required not in ordered_flags:
ordered_flags.append(required)
args = ["--json"]
args.extend(f"--{flag}" for flag in ordered_flags)
for flag in ordered_flags:
spec = SPEC_BY_FLAG.get(flag)
if spec:
hy_flag = spec.hy_smi_flag or flag
args.append(f"--{hy_flag}")
return args
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment