Skip to content

RL: unify all randomness under a single random_seed (seed audit) #2

Description

@rutayan-nv

Summary

cloudai should have one seed that governs all randomness, derived from the canonical BaseAgentConfig.random_seed (default 42). Today several RNG sites are seeded independently — or not at all — so a run is not reproducible end-to-end from a single knob. This issue records an audit of every randomness source in cloudai core and proposes threading them all from the single seed. Audit only — no fix is requested in this issue.

Motivating bug (already addressed in the env_params/DR work): the domain-randomization sampler defaulted to seed 0 while the agent default is 42, so a config without an explicit random_seed ran the agent and the env on two different seeds.

Canonical seed

  • BaseAgentConfig.random_seed: int = 42src/cloudai/configurator/base_agent.py. Single declared knob, set via TOML [agent_config] random_seed; every agent config inherits it.

Audit of RNG sites in cloudai core

# Site RNG Seeded from random_seed? Notes
1 DR sampler — env_params.py (random.Random(f"{seed}:{name}:{trial}")) Python random Yes (after the DR fix) Per-(seed, param, trial) sub-seeding keeps params independent and reproducible.
2 Gym reset(seed) / seed()np.random.seed(seed)cloudai_gym.py numpy global No (only when a caller passes seed) In the native BaseAgent.run() loop, env.reset() is called with no seed, so numpy's global RNG is never seeded from random_seed.
3 start_action: "random"base_agent.py n/a in core No The contract implies a random first action, but core provides no RNG for it; GridSearchAgent ignores it.
4 GridSearchAgentgrid_search.py none (itertools.product) n/a Deterministic; the only agent shipped in core.

Gaps

  • G1 — no single propagation path. Each RNG (Python random, numpy global, gym reset, plus external-agent frameworks) is seeded independently; nothing guarantees they all derive from random_seed.
  • G2 — numpy global RNG unseeded by default. The gym only seeds numpy when a gymnasium caller passes seed; the native cloudai loop never does, so in-process np.random usage is nondeterministic across runs.
  • G3 — start_action="random" is unwired in core. No core RNG tied to random_seed selects the random start.

Related (out of core)

Stochastic agents (BO, GA, MAB, PPO, DQN) live in cloudaix, not core. Each must read agent_config.random_seed and seed its own framework (numpy / torch / RLlib). There is no central enforcement that they all use the same single seed; this should become a documented contract once core exposes a single derivation utility.

Proposed direction (non-binding)

  • Add a single seed-derivation helper in core, e.g. derive_seed(random_seed, component: str) reusing the f"{seed}:{component}" hashing the DR sampler already uses.
  • Thread it to: the DR sampler (done), the gym (seed numpy global from random_seed when no explicit seed is given), and start_action="random".
  • Publish a contract for external agents: seed your framework from derive_seed(random_seed, "<agent>").

Acceptance criteria

  • One knob (random_seed) makes a full cloudai run reproducible — DR draws, any numpy usage, and random start actions.
  • No RNG site defaults to a seed that disagrees with random_seed.
  • Independence preserved via per-component sub-seeds (not one shared global stream).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    RLReinforcement learning / DSE agents

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions