36 lines
1.2 KiB
Python
36 lines
1.2 KiB
Python
"""TensorBoard scalar ingestion with optional dependency isolation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from .storage import TuningStorage
|
|
|
|
|
|
class TensorboardUnavailable(RuntimeError):
|
|
pass
|
|
|
|
|
|
def ingest_scalars(storage: TuningStorage, trial_id: str, log_dir: Path) -> int:
|
|
"""Reload all scalar events and idempotently upsert them into SQLite."""
|
|
try:
|
|
from tensorboard.backend.event_processing.event_accumulator import EventAccumulator
|
|
except ImportError as error:
|
|
raise TensorboardUnavailable(
|
|
"缺少 tensorboard,请安装 training_server/requirements.txt"
|
|
) from error
|
|
if not log_dir.is_dir():
|
|
return 0
|
|
accumulator = EventAccumulator(str(log_dir), size_guidance={"scalars": 0})
|
|
try:
|
|
accumulator.Reload()
|
|
except (OSError, ValueError):
|
|
return 0
|
|
points: list[tuple[str, int, float, float]] = []
|
|
for tag in accumulator.Tags().get("scalars", []):
|
|
for event in accumulator.Scalars(tag):
|
|
points.append((tag, int(event.step), float(event.wall_time), float(event.value)))
|
|
if points:
|
|
storage.insert_metrics(trial_id, points)
|
|
return len(points)
|