Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions src/winml/modelkit/commands/_live_chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from __future__ import annotations

import time
from typing import Any

from rich.console import Console
Expand Down Expand Up @@ -41,11 +42,21 @@ def __init__(
chart_height: int = 15,
poll_interval_ms: int = 100,
device_kind: str | None = None,
duration_sec: float | None = None,
clock: Any = None,
) -> None:
self._total = total_iterations
self._warmup = warmup
self._model_id = model_id
self._device = device
# When set, the benchmark phase runs on a wall-clock budget instead of a
# fixed iteration count, so progress is reported as elapsed/total time.
# ``clock`` is the benchmark loop's shared start reference (an object
# with a ``.start`` timestamp); reading it — rather than stamping a local
# clock on the first update() — keeps the bar aligned with the exact
# budget the loop stops on.
self._duration_sec = duration_sec
self._clock = clock
# `device_kind` is the value HWMonitor resolved at start() — pass it
# in when you want the legend to reflect what's actually polled (e.g.
# "auto" that resolved to GPU). Falls back to the requested string
Expand Down Expand Up @@ -234,15 +245,26 @@ def _render_status(
current_util = util_samples[-1] if util_samples else 0.0
mean_util = sum(util_samples) / len(util_samples) if util_samples else 0.0

pct = iteration / self._total if self._total > 0 else 0
if self._duration_sec is not None and phase == "benchmark":
# Duration mode: base progress on elapsed wall-clock time, since the
# benchmark iteration count is not known ahead of time. The start
# reference is the loop's shared clock, so this tracks the same
# budget the loop terminates on.
start = getattr(self._clock, "start", None)
elapsed = time.perf_counter() - start if start else 0.0
pct = min(elapsed / self._duration_sec, 1.0) if self._duration_sec > 0 else 0.0
shown = min(elapsed, self._duration_sec)
progress = f"[green]Time: {shown:.1f}/{self._duration_sec:.0f}s[/green]"
else:
pct = iteration / self._total if self._total > 0 else 0
if phase == "warmup":
progress = f"[yellow]Warmup: {iteration}/{self._warmup}[/yellow]"
else:
progress = f"[green]Iter: {effective_iter}/{total_bench}[/green]"

bar_len = int(pct * 20)
bar = f"[{'=' * bar_len}{' ' * (20 - bar_len)}]"

if phase == "warmup":
progress = f"[yellow]Warmup: {iteration}/{self._warmup}[/yellow]"
else:
progress = f"[green]Iter: {effective_iter}/{total_bench}[/green]"

throughput = 1000.0 / latency_ms if latency_ms > 0 else 0.0

# Row 1: Progress
Expand Down
Loading
Loading