From ac459d26a4656124ad0e4006033ae218aa8eb4bd Mon Sep 17 00:00:00 2001 From: jze9 Date: Wed, 8 Jul 2026 04:01:48 +0500 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=B0=D1=88=D0=B1=D0=BE=D1=80=D0=B4:=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=80=D1=82=D0=BE=D1=87=D0=BA=D0=B0=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20GPU=20(util/=D0=92=D1=82?= =?UTF-8?q?/=C2=B0C=20=D0=B8=D0=B7=20results/gpustat.json)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Веб в Docker без nvidia-smi: хост-сервис gausse-gpustat пишет JSON рядом с базой, /api/overview отдаёт поле gpu (протухшее >30с — честно null). Co-Authored-By: Claude Fable 5 --- src/gausse/web/page.py | 5 +++++ src/gausse/web/stats.py | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/gausse/web/page.py b/src/gausse/web/page.py index 266d5c0..afcd68f 100644 --- a/src/gausse/web/page.py +++ b/src/gausse/web/page.py @@ -61,6 +61,7 @@ PAGE_HTML = r"""
Нереализуемо
Доля реализуемых
Лучший КПД / скорость
+
GPU (GTX 1070)
@@ -131,6 +132,10 @@ async function refresh(){ let best = (o.top && o.top.length) ? o.top[0].efficiency : null; let bestV = (o.top_by_velocity && o.top_by_velocity.length) ? o.top_by_velocity[0].exit_velocity_mps : null; document.getElementById('c-best').textContent = fmtPct(best) + (bestV!=null ? ' / '+fmt(bestV,0)+' м/с' : ''); + const g = o.gpu; + document.getElementById('c-gpu').textContent = g + ? `${g.util_pct}% · ${fmt(g.power_w,0)}Вт · ${g.temp_c}°C` + : 'нет данных'; renderTop(o); const hist=document.getElementById('hist'); hist.innerHTML=''; diff --git a/src/gausse/web/stats.py b/src/gausse/web/stats.py index fb427f0..7da95e2 100644 --- a/src/gausse/web/stats.py +++ b/src/gausse/web/stats.py @@ -1,6 +1,7 @@ """Агрегаты по таблице `runs` для веб-морды — считаются запросами к SQLite.""" import json +import time from pathlib import Path from gausse.storage.database import fetch_run_by_id, fetch_runs, open_connection @@ -13,6 +14,23 @@ def _tail_log(log_path: Path, n_lines: int = 40) -> list[str]: return lines[-n_lines:] +def _gpu_stat(db_path: Path) -> dict | None: + """Загрузка GPU из gpustat.json рядом с базой (пишет gausse-gpustat на хосте). + + Веб живёт в Docker без доступа к nvidia-smi, поэтому хост-сервис раз в + несколько секунд кладёт JSON в каталог результатов. Протухшие данные + (>30с — писатель умер/GPU нет) честно не показываем. + """ + p = db_path.parent / "gpustat.json" + try: + stat = json.loads(p.read_text(encoding="utf-8")) + if time.time() - float(stat.get("ts", 0)) > 30: + return None + return stat + except (OSError, ValueError): + return None + + def overview(db_path: Path, log_path: Path | None = None, top_n: int = 15) -> dict: """Сводка для дашборда: счётчики, гистограмма КПД, топ конфигураций, хвост лога.""" conn = open_connection(db_path) @@ -71,6 +89,7 @@ def overview(db_path: Path, log_path: Path | None = None, top_n: int = 15) -> di "top": top, "top_by_velocity": top_by_velocity, "log_tail": _tail_log(log_path, 40) if log_path else [], + "gpu": _gpu_stat(db_path), }