Skip to content

Experiment._get_seed 在 Hydra multirun 下崩溃:hydra.job.id 是 str,却被拿来做算术 #168

Description

@SongshGeo

现象

--multirun 配上非空的 exp.seed 时,实验一启动就崩:

File "abses/core/experiment.py", line 390, in _get_seed
    r = random.Random(self._base_seed + job_id * 1000 + run_id)
TypeError: unsupported operand type(s) for +: 'int' and 'str'

原因

Experiment.job_idabses/core/experiment.py:299-306)在 Hydra 环境下返回:

return self.hydra_config.job.get("id", 0)

而 Hydra 把 hydra.job.id 声明成字符串hydra/conf/__init__.py):

id: str = MISSING      # 第 61 行
num: int = MISSING     # 第 64 行   ← 同一个数字,但类型是 int

BasicLauncher 赋值时写的是整数(sweep_config.hydra.job.id = idx),但 OmegaConf 按 schema 强制转成了 str。于是 job_id * 1000 变成一个重复 1000 次的字符串,int + str 抛 TypeError。

归档产物可以佐证:任意一次 multirun 的 .hydra/hydra.yaml 里都是 id: '2'(带引号)。

复现

python -m your_pkg --multirun some=a,b exp.repeats=2   # exp.seed 非 None

单次运行(hydra.run.dir)不受影响 —— 单次运行下 job.id 不参与这条路径。

为什么现在才暴露

_get_seed 开头有 if self._base_seed is None: return None。只要没设种子就永远走不到那行加法。我们之前的实验一直没设 exp.seed(也因此不可复现),最近为了可复现加上种子,"multirun + 有种子"这个组合第一次相遇就炸。

建议修法

hydra.job.num(schema 本就是 int)而不是 hydra.job.id

return self.hydra_config.job.get("num", 0)

或者保守一点,就地转换:

return int(self.hydra_config.job.get("id", 0))

注意 job.id 在某些 launcher(如 submitit)下会是形如 "12345_0" 的作业号,int() 会失败 —— 所以 job.num 更稳妥。

环境

  • abses 0.11.7(本地 HEAD c570cac7 同样存在,行号一致)
  • hydra-core 1.3.5,Python 3.11

下游临时兜底

我们在自己的入口里用子类覆盖 job_id 强制转 int(我们把 abses 钉死在 0.11.7,理由是可复现性,暂不动版本)。上游修好后这个子类可以纯减法删掉。

另见姊妹 issue:_is_hydra_parallel 导致 num_process 完全失效。

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions