claude_refactor_v3: New train_gtauav.py, added entry point main.py, added utils
This commit is contained in:
2
src/utils/__init__.py
Normal file
2
src/utils/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
"""Utilities: paths, seeding, IO."""
|
||||
|
||||
51
src/utils/io_utils.py
Normal file
51
src/utils/io_utils.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""IO helpers: atomic checkpoint saves, VRAM cleanup."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import gc
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def atomic_save_torch(obj: Any, path: Path) -> None:
|
||||
"""Save a PyTorch object atomically via temp file + os.replace.
|
||||
|
||||
On any failure (KeyboardInterrupt / SIGTERM included), the temp file
|
||||
is removed. Makes --resume safe: a partial checkpoint never lands at
|
||||
the destination path.
|
||||
|
||||
Args:
|
||||
obj: Anything torch.save can handle.
|
||||
path: Destination path. Parent directory is created if missing.
|
||||
"""
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
fd, tmp = tempfile.mkstemp(suffix=".pt.tmp", dir=path.parent)
|
||||
os.close(fd)
|
||||
try:
|
||||
torch.save(obj, tmp)
|
||||
os.replace(tmp, path)
|
||||
except BaseException:
|
||||
if os.path.exists(tmp):
|
||||
os.remove(tmp)
|
||||
raise
|
||||
|
||||
|
||||
def clear_vram() -> None:
|
||||
"""Free VRAM and reset peak memory stats."""
|
||||
gc.collect()
|
||||
if torch.cuda.is_available():
|
||||
torch.cuda.empty_cache()
|
||||
torch.cuda.reset_peak_memory_stats()
|
||||
allocated_gb = torch.cuda.memory_allocated() / 1e9
|
||||
logger.info("VRAM cleared. Current usage: %.2f GB", allocated_gb)
|
||||
|
||||
|
||||
|
||||
|
||||
32
src/utils/path_utils.py
Normal file
32
src/utils/path_utils.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""Project root resolution via marker files."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
# Markers identifying the project root (per REQUIREMENTS_GIN_STYLE.md §5).
|
||||
_MARKERS: tuple[str, ...] = ("pyproject.toml", ".git", "in")
|
||||
|
||||
|
||||
def get_proj_dir() -> str:
|
||||
"""Return absolute project root with trailing slash.
|
||||
|
||||
Walks up from this file's directory until finding pyproject.toml,
|
||||
.git, or in/. Searches up to 10 levels.
|
||||
|
||||
Returns:
|
||||
Project root path with trailing slash, e.g. '/home/user/caption-test/'.
|
||||
|
||||
Raises:
|
||||
RuntimeError: If no marker found within 10 parent directories.
|
||||
"""
|
||||
current = Path(__file__).resolve().parent
|
||||
for _ in range(10):
|
||||
if any((current / m).exists() for m in _MARKERS):
|
||||
return str(current) + "/"
|
||||
current = current.parent
|
||||
raise RuntimeError(
|
||||
f"Project root not found. Looked for {_MARKERS} starting at "
|
||||
f"{Path(__file__).resolve().parent}",
|
||||
)
|
||||
|
||||
23
src/utils/seed_utils.py
Normal file
23
src/utils/seed_utils.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""RNG seeding for reproducibility."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import random
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
|
||||
|
||||
def set_seed(seed: int = 42) -> None:
|
||||
"""Fix all RNG seeds (Python random, NumPy, PyTorch CPU + all CUDA devices).
|
||||
|
||||
Args:
|
||||
seed: Integer seed.
|
||||
"""
|
||||
random.seed(seed)
|
||||
np.random.seed(seed)
|
||||
torch.manual_seed(seed)
|
||||
torch.cuda.manual_seed_all(seed)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user