Timsty's picture
Add files using upload-large-folder tool
b6a9d87 verified
Raw History Blame Contribute Delete
3.33 kB
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Determinism helpers for reproducible evaluation runs.
Seeding is opt-in. If no seed is supplied and the ``GR00T_EVAL_SEED``
environment variable is unset, these helpers are no-ops, so training and
production code paths are unaffected.
When enabled, :func:`seed_everything` seeds Python, NumPy, torch CPU and
torch CUDA RNGs, sets cuDNN to deterministic mode, and (optionally) asks
torch to use deterministic algorithm implementations. This is required
before any historical metric recording so that run-to-run variance on the
same checkpoint is driven by hardware/library noise only, not by unseeded
RNGs.
"""
from __future__ import annotations
import logging
import os
import random
import numpy as np
import torch
EVAL_SEED_ENV_VAR = "GR00T_EVAL_SEED"
logger = logging.getLogger(__name__)
def get_eval_seed(default: int | None = None) -> int | None:
"""Read the eval seed from the environment, or return ``default``.
Returns ``None`` if the env var is unset / empty and no default is given.
Raises ``ValueError`` if the env var is set but not a valid integer.
"""
raw = os.environ.get(EVAL_SEED_ENV_VAR)
if raw is None or raw == "":
return default
try:
return int(raw)
except ValueError as exc:
raise ValueError(f"{EVAL_SEED_ENV_VAR}={raw!r} is not a valid integer") from exc
def seed_everything(seed: int | None = None, *, warn_only: bool = True) -> int | None:
"""Seed all standard RNGs and enable deterministic cuDNN / CUDA kernels.
Args:
seed: Seed to apply. If ``None``, reads ``GR00T_EVAL_SEED``; if that
is also unset, the function returns ``None`` without changing
any global state.
warn_only: Forwarded to ``torch.use_deterministic_algorithms``. When
``True`` (default), ops without a deterministic implementation
warn instead of raising.
Returns:
The effective seed that was applied, or ``None`` if no seeding was
done (so callers can pass it downstream unconditionally).
"""
if seed is None:
seed = get_eval_seed()
if seed is None:
return None
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed_all(seed)
torch.use_deterministic_algorithms(True, warn_only=warn_only)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
# Required by some CUDA kernels when deterministic algorithms are on.
os.environ.setdefault("CUBLAS_WORKSPACE_CONFIG", ":4096:8")
logger.info("Determinism enabled: seed=%d warn_only=%s", seed, warn_only)
return seed