监控系统
不是 Agent,是一组机制
监控不是一个独立的 Agent。它是由多个组件组成的机制:
- watchdog — 运行在 GPU 服务器上的 Python 脚本,持续监控训练进程
- CronCreate — 定时任务,周期性检查 watchdog 的输出
- 编排器 — 接收监控信息并做出反应
mermaid
graph LR
T[训练进程] -->|输出| W[watchdog.py]
W -->|写入| S[/tmp/jx-monitor/<br/>summary.txt]
C[CronCreate] -->|定期读取| S
C -->|异常时| O[编排器]
O -->|决策| A[修复 / 重启 / 通知用户]监控类别
| 类别 | 监控项 | 检查频率 | 异常处理 |
|---|---|---|---|
| 进程健康 | GPU 利用率、显存占用、进程存活 | 每分钟 | 进程挂了 → 自动重启或通知 |
| 训练进度 | loss 趋势、学习率、当前 epoch | 每 5 分钟 | loss 爆炸 → 暂停并通知 |
| 资源状态 | 磁盘空间、checkpoint 大小 | 每 10 分钟 | 空间不足 → 清理旧 checkpoint |
| WandB 同步 | WandB 进程、网络连接 | 每 5 分钟 | 同步中断 → 重启 WandB |
两阶段训练监控
这是监控系统最重要的设计。训练的前期和后期,监控策略完全不同:
第一阶段:主动看守
训练启动 → 前 30 分钟训练刚启动时,问题出现的概率最高:
- CUDA OOM(显存不够)
- 数据加载报错
- WandB 初始化失败
- 学习率配置错误导致 loss 爆炸
这个阶段,编排器主动等待,高频检查训练状态。不设 CronCreate,而是直接在当前 session 中监控。
yaml
# 第一阶段监控配置
phase: active-watch
check_interval: 60s # 每分钟检查
duration: 30m # 持续 30 分钟
watch_for:
- process_alive
- gpu_utilization > 0
- loss_is_finite
- wandb_connected不要跳过看守期
很多训练失败发生在前几分钟。跳过看守期意味着你可能在 8 小时后才发现训练从第 2 分钟就挂了。
第二阶段:巡检模式
看守期结束(一切正常)→ 切换到 CronCreate 定时巡检训练稳定后,没必要持续监控。切换到 CronCreate,定期检查健康状态:
yaml
# 第二阶段监控配置
phase: patrol
check_interval: 15m # 每 15 分钟
alert_conditions:
- loss_spike > 3x_moving_avg
- gpu_utilization < 10% # 可能挂了
- disk_usage > 90%
- process_not_alive
normal_action: log_only
alert_action: notify_orchestrator阶段切换
mermaid
stateDiagram-v2
[*] --> ActiveWatch: 训练启动
ActiveWatch --> Patrol: 30 分钟内无异常
ActiveWatch --> Alert: 发现问题
Patrol --> Alert: 巡检发现异常
Alert --> ActiveWatch: 修复后重新看守
Patrol --> Complete: 训练正常结束
Complete --> [*]配置文件
监控配置在 .omc/research/training/monitoring.yaml:
yaml
monitoring:
# 全局设置
server: ic2
gpus: [0, 1, 2]
tmux_session: train-exp03
wandb_project: fine-grained-research
wandb_run: exp03_contrastive
# 第一阶段
active_watch:
enabled: true
duration: 30m
check_interval: 60s
healthy_criteria:
gpu_util_min: 10
loss_finite: true
process_alive: true
# 第二阶段
patrol:
check_interval: 15m
alert_thresholds:
loss_spike_ratio: 3.0
gpu_util_min: 10
disk_usage_max: 90
# watchdog 配置
watchdog:
path: tools/watchdog.py
output: /tmp/jx-monitor/status/summary.txt
pid_file: /tmp/jx-monitor/watchdog.pid健康检查而非超时
核心理念
监控基于健康状态,不是超时。
传统做法是设一个超时:训练超过 24 小时就报警。这很粗糙 — 训练可能本来就需要 20 小时,也可能在第 2 小时就已经 loss 爆炸了。
AutoResearch 的做法是检查健康指标:
| 指标 | 健康 | 不健康 |
|---|---|---|
| GPU 利用率 | > 10% | 持续 < 10%(训练可能挂了) |
| Loss | 有限值且在下降 | NaN / Inf / 3 倍移动平均 |
| 进程 | 存活 | 不存在 |
| WandB | 在同步 | 超过 30 分钟没有新数据点 |
| 磁盘 | 使用率 < 90% | 使用率 > 90% |
只要所有指标健康,训练就继续。不管它跑了 2 小时还是 20 小时。
健康检查的实现
watchdog 每次检查生成一个摘要文件:
json
{
"timestamp": "2025-03-15T20:30:00Z",
"status": "healthy",
"gpu_util": [82, 79, 85],
"gpu_mem": [18.2, 17.8, 19.1],
"current_epoch": 45,
"total_epochs": 100,
"current_loss": 0.342,
"loss_trend": "decreasing",
"wandb_last_sync": "2025-03-15T20:29:45Z",
"disk_usage": "67%",
"eta": "2025-03-16T08:30:00Z"
}CronCreate 读这个文件,解析 status 字段。只要是 healthy,就什么都不做。出现 warning 或 critical 时才通知编排器。
每台服务器一个 CronCreate
规则
每台远程服务器只设一个 CronCreate job。不管在上面跑了几个训练任务。
这是为了避免 CronCreate job 堆积。watchdog 脚本本身可以监控同一台机器上的多个训练任务,CronCreate 只需要读一个总摘要文件。