Source code for ptyrad.runtime.seed
"""
Random seed resolution and initialization.
This module provides utilities to ensure reproducibility across PtyRAD
reconstructions by managing random seeds for Python, NumPy, and PyTorch.
It includes logic to prioritize user-provided seeds and automatically
enforce seeding during distributed (multi-GPU) runs to prevent divergent
model initializations.
"""
import logging
from typing import Optional
logger = logging.getLogger(__name__)
[docs]
def resolve_seed_priority(args_seed, params_seed, acc):
"""Determines the final random seed to use based on user inputs and runtime context.
This function resolves the seed using the following priority hierarchy:
1. Command Line Argument (`args_seed`)
2. Configuration File (`params_seed`)
3. Automatic Fallback (forces seed to 42 if running in multi-GPU mode to
ensure consistent probe/object initializations across processes).
4. None (no fixed seed).
Args:
args_seed (int or None): The seed provided via command-line arguments.
params_seed (int or None): The seed provided in the parameters YAML file.
acc (accelerate.Accelerator or None): The active HuggingFace Accelerator
instance, used to check the number of active processes.
Returns:
int or None: The resolved integer seed, or None if no seeding is required.
"""
if args_seed is not None:
seed = args_seed
logger.info(f"Random seed: {seed} provided by CLI argument")
elif params_seed is not None:
seed = params_seed
logger.info(f"Random seed: {seed} provided by params file")
elif acc is not None and acc.num_processes > 1:
seed = 42 # seed is required otherwise the probe position with random displacement could cause objects with different shapes
logger.info(f"Random seed: {seed} is set automatically because multi GPU is detected but no seed is provided")
else:
seed = None
return seed
[docs]
def set_random_seed(seed: Optional[int], deterministic: bool = False):
"""Sets the random seeds for Python, NumPy, and PyTorch operations.
Ensures that pseudo-random number generators (PRNGs) across all relevant
libraries and devices (CPU and all available CUDA GPUs) are synchronized
for reproducible reconstructions.
Args:
seed (int, optional): The integer seed to apply. If None, this function
does nothing.
deterministic (bool, optional): If True, forces PyTorch to use deterministic
algorithms. Note that this can significantly impact performance and
may cause crashes if certain operations do not have a deterministic
implementation. Defaults to False.
"""
import random
import numpy as np
import torch
if seed is not None:
random.seed(seed) # Python's RNG
np.random.seed(seed) # NumPy RNG
torch.manual_seed(seed) # PyTorch CPU RNG
if torch.cuda.is_available():
torch.cuda.manual_seed_all(seed) # All GPUs
if deterministic:
# This would slow down the operation a bit: https://docs.pytorch.org/docs/stable/notes/randomness.html
torch.use_deterministic_algorithms(True)