feat(train/monitor): 评估峰值不再撑爆整卡 + 从指定阶段重训 + 闭环误差诊断

- train.py:evaluate 改 bs=64,结束后 empty_cache()。WDDM 下 15.9 GiB 的评估峰值用完不退,
  整卡顶到 96% 后驱动把训练张量换出(实测 Local 18.8 GB / Shared 1.9 GB),吞吐从 5.5k
  掉到 444 samples/s、8000 步 eval 卡死 68 分钟;改后峰值 5.32 GiB、eval 106 s、吞吐 6.4–7.0k。
- pstate/pipeline:新增 --fresh-from=<阶段>:只把该阶段及之后的产物移进 ml/archive/(不删),
  与参数失效取并集;配合 FROM 实现"只重训某一阶段,之后全部重做"(沙盒实测选 train 只归档 ml/runs/base)。
- monitor:运行方式加「从指定阶段重训」+ 起始阶段下拉;TARGET_SAMPLES 默认改 200 万;
  「最好 X%」改标最好那次 eval 的步数(原来错标当前步,18,000 步显示成 0.2% 的出处)。
  连同工作区已有的停止补扫 sweep_nt(按命令行补杀 git-bash 下逃逸的孙进程)一并提交。
- eval/diag_tail.py:闭环末位误差 / 是否进过 5 mm 窗口的逐题诊断(手动运行,不进流水线)。
This commit is contained in:
cbb
2026-10-18 23:15:53 +08:00
parent 7fe1e5e0b3
commit c2732fb3cd
6 changed files with 180 additions and 19 deletions
+4 -3
View File
@@ -1,6 +1,6 @@
"""流水线状态与互斥锁(单一写者:所有对 ml/runs/pipeline.json / pipeline.lock 的写都经过本模块,原子替换)。
pipeline.sh 自动调用,一般不需要手动运行:
python -m ml.pstate reset <阶段1,...> [--fresh] # `all` 开始:保留 rc=0 的已完成阶段(续跑);参数变了只作废受影响的阶段;--fresh 全部作废
python -m ml.pstate reset <阶段1,...> [--fresh] # `all` 开始:保留 rc=0 的已完成阶段(续跑);参数变了只作废受影响的阶段;--fresh 全部作废;--fresh-from=<阶段> 只作废该阶段及之后
python -m ml.pstate todo # 打印计划中尚未完成的阶段(空格分隔)
python -m ml.pstate begin <阶段> [键=值 ...] # 阶段开始
python -m ml.pstate set <阶段> 键=值 ... # 阶段中途更新
@@ -194,11 +194,12 @@ def main():
if cmd == 'reset':
plan = rest[0].split(',') if rest and rest[0] else []
pn = params_now(); prev = d.get('params') or {}
changed = []
changed = [k for k in PARAM_KEYS if prev and prev.get(k) != pn[k]]
ff = next((r.split('=', 1)[1] for r in rest if r.startswith('--fresh-from=')), '')
if '--fresh' in rest: bad = set(ORDER)
else:
changed = [k for k in PARAM_KEYS if prev and prev.get(k) != pn[k]]
bad = {st for k in changed for st in AFFECTS[k]}
if ff in ORDER: bad |= set(ORDER[ORDER.index(ff):])
if changed: print('参数与上次不同:' + json.dumps({k: (prev.get(k), pn[k]) for k in changed}, ensure_ascii=False)
+ ';受影响的阶段重跑:' + ' '.join(st for st in ORDER if st in bad), file=sys.stderr)
keep = {k: v for k, v in d.get('stages', {}).items() if v.get('rc') == 0 and k not in bad}