计算节点安全约定 (L1–L7)
reproduce.sh 在 SLURM allocation 内一个全新的计算节点上运行, 而不是代理生成它的登录节点。以下约定 (L1–L7) 确保脚本能在计算节点 真正跑完。
PaperBench 复现代理通过 ari-skill-paper-re/src/prompts/replicator.md 中的 COMPUTE-NODE EXECUTION CONVENTIONS 区块被指示这些约定 (这里 也复述一份,以便你手动审查生成的 reproduce.sh)。
L1 — 共享文件系统
reproduce.sh 中所有路径必须在 每个 allocated 节点上都可解析。
- ✅
$HOME,/work/...,/scratch/...,/lustre/...,/nfs/... - ❌
/tmp,/var/tmp,/local, 仅容器本地挂载的路径
ARI 在 checkpoint 位于节点本地 FS 时警告,但不会拒绝运行 — 多节点时 rank 1+ 看不到 rank 0 的文件会导致静默失败。
L2 — MPI 调用: mpirun 之上优先 srun
# 优先 (使用 SLURM 的 PMI/PMIx 集成; 不需要单独安装的 OpenMPI/MPICH):
srun -n $SLURM_NTASKS ./my_program
# 可接受的回退 (仅当 OpenMPI/MPICH 作为模块加载时):
mpirun -np $SLURM_NTASKS ./my_program
# 最后手段的 Python 回退 (srun / mpirun 都不在 PATH 上时):
pip install --user mpi4py
python -c "from mpi4py import MPI; ..."先用 which srun mpirun 测试。代理 prompt 指示复现器发出此检查。
L3 — GRES 探测
当 rubric 的 execution_profile.gpu_type 设置时,ARI 在向 sbatch 添加 --gres=gpu:<type>:N 前检查 sinfo -o '%G'。如果未配置 GRES ((null)),标志会被剥离,记录警告 — --gpus-per-task 存留。
交互式验证:
from ari_skill_paper_re.server import _slurm_has_gres
_slurm_has_gres() # True / FalseL4 — Conda / virtualenv 激活
#!/usr/bin/env bash 不会自动激活任何 Python 环境。如果你的 reproduce.sh 需要特定 env,前置:
# 选项 A: source ~/.bashrc (集群默认 Python env)
source ~/.bashrc
# 选项 B: 显式 conda activate
source ~/miniconda3/etc/profile.d/conda.sh
conda activate ari-repro
# 选项 C: 依赖 /usr/bin/python3 + user-site 安装
pip install --user numpy matplotlib mpi4py代理 prompt 推动复现器从这些里选一个。
L5 — 模块加载
站点特定模块 (CUDA, OpenMPI, 编译器, mathlibs) 必须在 reproduce.sh 内加载,而不是仅在登录节点。用 rubric 的 execution_profile.module_loads 指定:
"module_loads": ["cuda/12.4", "openmpi/4.1", "gcc/11.3"]代理然后发出:
module load cuda/12.4 openmpi/4.1 gcc/11.3reproduce.sh 顶部。ARI 不验证模块名 — 你集群的 module avail 是 authoritative。
L6 — 多节点 fan-out
reproduce.sh 作为第一个 allocated 节点上的一个 rank 启动。 要使用每个 allocated 节点,脚本必须 fan out:
srun -N $SLURM_JOB_NUM_NODES -n $SLURM_NTASKS ./my_program没有这个,脚本只用 1 个节点,即使 sbatch --nodes=4 成功。代理 prompt 有专门的 "MULTI-NODE FAN-OUT" 区块提醒复现器。
L7 — Timeout 包装
SLURM --time 强制硬墙钟,超时 SIGTERM。为了部分结果安全,把长阶段 用 timeout 包装:
timeout 1800 python long_step.py # 30 分钟每步上限
timeout 600 ./bench # 10 分钟基准测试上限这确保一个慢步骤不会吃掉整个 allocation。代理 prompt 鼓励但不强制。
验证生成的 reproduce.sh
启动前的快速清单:
# 1. 无节点本地路径
grep -E '/(tmp|var/tmp|local)/' repro_sandbox/reproduce.sh && echo BAD
# 2. srun 或 mpirun (而非赤裸 ./program)
grep -E 'srun|mpirun' repro_sandbox/reproduce.sh || echo MISSING_FANOUT
# 3. execution_profile 要求时的模块加载
grep -E '^module load' repro_sandbox/reproduce.sh
# 4. 长步骤的 timeout 包装
grep -E 'timeout' repro_sandbox/reproduce.sh