| """Deterministic runtime helpers for Phase 2 experiments.""" | |
| from __future__ import annotations | |
| import os | |
| import random | |
| from typing import Optional | |
| import numpy as np | |
| def set_global_seed(seed: int, deterministic_torch: bool = True, seed_torch: bool = True) -> None: | |
| """Seed Python, NumPy, and PyTorch when available.""" | |
| os.environ["PYTHONHASHSEED"] = str(seed) | |
| random.seed(seed) | |
| np.random.seed(seed) | |
| if not seed_torch: | |
| return | |
| try: | |
| import torch | |
| torch.manual_seed(seed) | |
| if torch.cuda.is_available(): | |
| torch.cuda.manual_seed_all(seed) | |
| if deterministic_torch: | |
| torch.use_deterministic_algorithms(True, warn_only=True) | |
| torch.backends.cudnn.benchmark = False | |
| torch.backends.cudnn.deterministic = True | |
| except ImportError: | |
| return | |
| def seed_worker(worker_id: int) -> None: | |
| """Seed DataLoader workers from PyTorch's worker seed.""" | |
| try: | |
| import torch | |
| worker_seed = torch.initial_seed() % 2**32 | |
| except ImportError: | |
| worker_seed = worker_id | |
| np.random.seed(worker_seed) | |
| random.seed(worker_seed) | |
| def make_torch_generator(seed: int) -> Optional[object]: | |
| """Return a seeded torch.Generator, or None if torch is unavailable.""" | |
| try: | |
| import torch | |
| generator = torch.Generator() | |
| generator.manual_seed(seed) | |
| return generator | |
| except ImportError: | |
| return None | |