实验运行器 本节摘要:循环只如其测量般诚实。构建运行器:取 spec,在沙盒子进程里执行,发评估器可信任的 json 指标 blob。研究循环跑不信任的代码——假设来自采样器,实验脚本来自同路径,把任一当进程内安全是请一个把编排器拖垮的崩溃。子进程是语言自带的隔离:独立进程、独立地址空间、父侧的信号句柄。本节运行器不实现完整沙盒(无 cgroup、无 seccomp、无 namespace 重映射),但有硬墙时超时、内存增长的轮询循环、超限杀进程的路径。这是每个更精心沙盒扩展的运行时契约,本节把契约缩到一次能读完。 对应原课程:Phase 19 · Lesson 52 · (原英文 )。本节属「AI Scientist」赛道第三节。
本节摘要:循环只如其测量般诚实。构建运行器:取 spec,在沙盒子进程里执行,发评估器可信任的 json 指标 blob。研究循环跑不信任的代码——假设来自采样器,实验脚本来自同路径,把任一当进程内安全是请一个把编排器拖垮的崩溃。子进程是语言自带的隔离:独立进程、独立地址空间、父侧的信号句柄。本节运行器不实现完整沙盒(无 cgroup、无 seccomp、无 namespace 重映射),但有硬墙时超时、内存增长的轮询循环、超限杀进程的路径。这是每个更精心沙盒扩展的运行时契约,本节把契约缩到一次能读完。
对应原课程:Phase 19 · Lesson 52 ·
experiment-runner(原英文phases/19-capstone-projects/52-experiment-runner/docs/en.md)。本节属「AI Scientist」赛道第三节。
阅读完本节,你应当能够:
研究循环跑不信任的代码。假设来自采样器,实验脚本来自同路径,把任一当进程内安全是请一个把编排器拖垮的崩溃。子进程是最简隔离:独立进程、独立地址空间、父侧信号句柄。
ExperimentSpec spec_id : str (稳定 id, "exp_001") hypothesis_id : int (链回第 48 节队列) script_path : str (要跑的 python 脚本路径) config : dict (作为一个 json 参数传给脚本) seed : int (实验的确定性种子) wall_timeout_s : float (硬超时, 超即杀) memory_cap_mb : int (软上限, 轮询; 超即杀) metric_keys : list[str] (评估器将读哪些字段)
脚本在磁盘上;运行器把 config 写到脚本读的临时文件路径。脚本须在 stdout 打单行 json,其键是 metric_keys 的超集。stdout 其余被捕获但指标解析器忽略。
硬内存上限需 resource.setrlimit,只在 POSIX 工作。本节发可移植方法:轮询平台常驻集大小,超上限杀子进程。上限是软的,因轮询有非零间隔;进程可在两次轮询间尖峰超上限又落回。运行器记最大观测 RSS 使评估器看见运行多近上限。无进程检视支持的系统上,轮询器打一次性警告并禁用,墙时超时仍适用。
运行器在完成后排空两管道。stdout 逐行扫;最后一行解析为 json 且含全部所需 metric_keys 的取为指标 blob。更早 json 行作 intermediate_metrics 留在结果(评估器可作学习曲线)。stderr 逐字捕获。运行器永不在非零退出码上抛,而是记码;任何非零退出标 "crash",即便脚本打了指标,使评估器默认把部分跑当失败。
给定基础 spec 与旋钮名,助手返每值一个 spec(config[knob] 覆写),每 spec 得派生 spec_id。AblationRunner 按序跑返按旋钮值键的 AblationTable。一次一个旋钮——全因子扫指数炸、产评估器无法解的结果;一次一旋钮产评估器可绘的干净轴。多旋钮扫只作重复单旋钮消融,由调用方组合。
每 spec 带种子。运行器经 config 字典把种子转发给脚本(config["__seed"] = spec.seed)。code/experiments/ 的 mock 实验脚本尊种子、跨运行产相同指标。第 51 节评估器依赖此;无确定性,「回归」可能是不同随机初始化。
code/main.py 定义 ExperimentSpec、ExperimentResult、ExperimentRunner、AblationRunner 与确定性 demo。子进程管理一类,内存轮询小线程,消融助手一函数。code/experiments/sparsity_experiment.py 是 mock 实验(读 config 路径、numpy 随机过小训练、打 json 指标行),尊 sleep_s(测超时)与 allocate_mb(测内存轮询)。
@dataclass class ExperimentResult: spec_id: str; hypothesis_id: int; exit_code: int terminal: str # "ok" | "timeout" | "oom" | "crash" wall_time_s: float; peak_rss_mb: float | None metrics: dict; intermediate_metrics: list stdout_tail: str; stderr_tail: str def run(spec: ExperimentSpec) -> ExperimentResult: cfg_path = write_temp_json(spec.config | {"__seed": spec.seed}) proc = subprocess.Popen([sys.executable, spec.script_path, cfg_path], stdout=PIPE, stderr=PIPE) poller = MemoryPoller(proc.pid, spec.memory_cap_mb) # 软上限轮询 try: out, err = proc.communicate(timeout=spec.wall_timeout_s) terminal = "crash" if proc.returncode else "ok" except subprocess.TimeoutExpired: proc.kill(); out, err = proc.communicate() terminal = "timeout" if poller.exceeded: terminal = "oom" metrics, interm = parse_metrics(out, spec.metric_keys) # 末 json 行 + 中间 return ExperimentResult(spec.spec_id, spec.hypothesis_id, proc.returncode, terminal, ..., poller.peak_rss, metrics, interm, ...) def ablate(base, knob, values): return [replace(base, spec_id=f"{base.spec_id}_{knob}_{v}", config={**base.config, knob: v}) for v in values]
设计要点:
terminal字段是评估器的第一读——非"ok"则评估器判定自动为失败,指标不经显著性检验。intermediate_metrics留学习曲线(评估器可看收敛)。消融一次一旋钮产干净轴,全因子炸。种子经 config 转发使确定性跨运行,无它「回归」可能是随机初始化噪声。
真实研究代理(AI-Scientist、MLAgentBench)用 Docker 容器或 Kubernetes job 做更强隔离,加 GPU 资源限额、日志聚合、结果存储。本节子进程 + psutil 是最小可行沙盒——够隔离崩溃、够测超时与 OOM,但不够防恶意代码(无文件系统隔离、无网络限制)。产品化加 Docker(文件系统 + 网络 + 资源)、Firejail(轻量沙盒)、或云函数(毫秒计费、完全隔离)。WandB/MLflow 是指标存储层,与运行器正交。本节的 ExperimentSpec/ExperimentResult 契约是这些产品化封装的底座。
code/main.py + code/experiments/sparsity_experiment.py + code/tests/test_runner.py(覆盖成功、超时、崩溃、消融表、确定性)。ExperimentRunner.run(spec) 是编排器入口,产 ExperimentResult 供第 51 节评估器消费。ablate 函数与 AblationRunner 可独立复用——任何「一次一旋钮」扫场景。换真实验脚本(导真模型),spec/result/runner 不动。
allocate_mb 让 mock 实验分配超上限,确认 terminal="oom"、RSS 被记。sleep_s 让 mock 实验睡超时,确认 terminal="timeout"。terminal="crash"、即便打了指标也当失败。ablate 跑两旋钮各三值,组合成 9 spec,讨论全因子 vs 单旋钮的可解读性。intermediate_metrics 供评估器看收敛。下一节,我们做「结果评估器」——把指标转成一行结论,用从零配对 t 检验判改进、回归、还是噪声。