使用OpenClaw监控GPU

更新时间:
复制为 MD 格式

本文介绍如何在DSW实例中使用OpenClaw实现GPU自动化监控,包括训练任务状态通知、异常智能识别、OOM自动恢复以及定时报告生成等功能。

背景介绍

在模型训练过程中,训练任务可能因各种原因(如CUDA内存溢出、显存不足、GPU利用率异常等)而中断或效率降低。通过配置OpenClaw,您可以实现对DSW实例中GPU状态的自动化监控,及时发现问题并自动处理,从而提高训练效率并节省人工成本。

完成本文档配置后,您的DSW实例将具备以下能力:

  • 任务状态自动通知:训练任务完成或异常中断时,通过钉钉即时发送通知。

  • 异常智能识别:自动检测GPU利用率骤降、Loss发散、内存溢出等异常情况。

  • 故障自动干预:检测到OOM后自动调整参数并重启训练任务。

  • 定时状态汇总:每日自动生成训练任务状态报告,便于掌控全局进度。

前提条件

场景一:配置训练任务完成通知

应用场景

当您提交长时间运行的训练任务(例如需要数小时完成的微调任务)后,通常需要定期检查任务是否完成。通过配置OpenClaw任务完成通知,您可以在训练任务结束时自动接收钉钉消息,无需手动监控任务状态。

实现方法

在训练脚本末尾添加OpenClaw消息发送命令,使训练任务完成或失败时自动发送通知。

训练脚本基础示例

# 执行训练命令
python train.py --model qwen-7b --lr 2e-5 --epochs 3

# 训练结束后发送通知($?为训练脚本的退出码)
openclaw message send --channel dingtalk --target "user:<staffid>" -m "训练任务已结束,退出码:$?"
说明
  • 注意请将<staffid>替换为您真实的staffid,获取方式可直接在DSWweb UI中询问OpenClaw:请帮我查看staffid

  • 退出码为0表示任务正常结束,非零值表示任务异常退出。

训练脚本增强示例(包含训练结果信息)

python train.py --model qwen-7b --lr 2e-5 --epochs 3
EXIT_CODE=$?

if [ $EXIT_CODE -eq 0 ]; then
  FINAL_LOSS=$(tail -n 5 train.log | grep -oP 'loss=\K[\d.]+' | tail -1)
  openclaw message send --channel dingtalk --target "user:<staffid>" -m "训练完成!最终 loss:${FINAL_LOSS},请查看训练结果"
else
  openclaw message send --channel dingtalk --target "user:<staffid>" -m "训练任务异常终止,退出码:${EXIT_CODE},请检查日志文件"
fi

场景二:配置训练过程异常监控

应用场景

训练任务在执行过程中可能出现异常情况(如GPU利用率骤降、显存占用接近上限、温度异常等),这些异常往往预示着训练任务即将失败或效率降低。通过配置定时监控,OpenClaw可以在异常发生时及时发送告警,避免算力浪费。

实现方法

创建GPU监控脚本/mnt/workspace/gpu_monitor.py

import subprocess
import sys

def get_gpu_stats():
    """获取GPU关键指标"""
    result = subprocess.run(
        ['nvidia-smi', '--query-gpu=utilization.gpu,memory.used,memory.total,temperature.gpu',
         '--format=csv,noheader,nounits'],
        capture_output=True, text=True
    )
    stats = []
    for i, line in enumerate(result.stdout.strip().split('\n')):
        util, mem_used, mem_total, temp = [x.strip() for x in line.split(',')]
        stats.append({
            'gpu_id': i,
            'utilization': int(util),
            'memory_used': int(mem_used),
            'memory_total': int(mem_total),
            'memory_pct': round(int(mem_used) / int(mem_total) * 100, 1),
            'temperature': int(temp)
        })
    return stats

def check_anomaly(stats):
    """检测异常,返回告警信息列表"""
    alerts = []
    for s in stats:
        gid = s['gpu_id']
        # GPU利用率过低(训练任务应保持高利用率)
        if s['utilization'] < 20:
            alerts.append(f"GPU {gid} 利用率仅 {s['utilization']}%,可能存在任务阻塞")
        # 显存接近上限
        if s['memory_pct'] > 90:
            alerts.append(f"GPU {gid} 显存占用 {s['memory_pct']}%,存在OOM风险")
        # 温度过高
        if s['temperature'] > 85:
            alerts.append(f"GPU {gid} 温度 {s['temperature']}°C,请注意散热")
    return alerts

if __name__ == '__main__':
    stats = get_gpu_stats()
    alerts = check_anomaly(stats)

    if alerts:
        # 检测到异常,输出告警内容并返回非零退出码
        for alert in alerts:
            print(alert)
        sys.exit(1)
    else:
        print("HEARTBEAT_OK")
        sys.exit(0)

配置OpenClaw定时监控任务:

openclaw cron add \
  --name "GPU健康巡检" \
  --cron "*/15 * * * *" \
  --tz "Asia/Shanghai" \
  --session isolated \
  --message "请执行 GPU 健康检查:

1. 运行命令:python /mnt/workspace/gpu_monitor.py
2. 如果输出 HEARTBEAT_OK,一切正常,不需要通知我
3. 如果检测到异常,请:
   - 通过钉钉把完整的告警信息发给我
   - 结合当前的训练进程状态,判断是否需要我介入
   - 给出你的处理建议" \
  --announce
说明

上述配置将每15分钟自动执行一次GPU健康检查,仅在检测到异常时发送钉钉通知。

验证定时任务

# 查看所有定时任务
openclaw cron list

# 手动触发测试(用实际的job_id替换<job_id>)
openclaw cron run <job_id>

场景三:配置OOM自动恢复

应用场景

CUDA内存溢出(OOM)是模型训练中的常见问题。通过配置OOM自动恢复机制,OpenClaw可以在检测到OOM后自动调整训练参数(如降低batch_size)并重启训练任务,无需人工干预。

实现方法

创建训练配置文件/mnt/workspace/train_config.json

{
  "model": "qwen-7b",
  "batch_size": 16,
  "lr": 2e-5,
  "epochs": 3,
  "max_length": 512,
  "oom_retry_count": 0
}

创建OOM自动恢复脚本/mnt/workspace/auto_recover.py

import json
import subprocess
import sys
from pathlib import Path

CONFIG_PATH = Path("/mnt/workspace/train_config.json")
LOG_PATH = Path("/mnt/workspace/train.log")

def load_config():
    return json.loads(CONFIG_PATH.read_text())

def save_config(config):
    CONFIG_PATH.write_text(json.dumps(config, indent=2))

def check_oom():
    """检查最近的日志中是否存在OOM错误"""
    if not LOG_PATH.exists():
        return False
    recent_lines = LOG_PATH.read_text().split('\n')[-50:]
    oom_keywords = ['CUDA out of memory', 'OutOfMemoryError', 'OOM']
    return any(kw in line for line in recent_lines for kw in oom_keywords)

def recover():
    config = load_config()

    if config['oom_retry_count'] >= 3:
        print(f"已自动重试 {config['oom_retry_count']} 次,batch_size 降至 {config['batch_size']},仍然出现OOM,需要人工介入")
        sys.exit(2)  # 退出码2表示需要人工处理

    # 将batch_size减半
    old_batch = config['batch_size']
    config['batch_size'] = max(1, old_batch // 2)
    config['oom_retry_count'] += 1
    save_config(config)

    print(f"检测到OOM,已将batch_size从 {old_batch} 调整为 {config['batch_size']}(第 {config['oom_retry_count']} 次自动恢复),正在重启训练任务...")

    # 重启训练任务(后台运行)
    subprocess.Popen([
        'python', 'train.py',
        '--batch_size', str(config['batch_size']),
        '--lr', str(config['lr']),
        '--epochs', str(config['epochs'])
    ], stdout=open(str(LOG_PATH), 'a'), stderr=subprocess.STDOUT)

    sys.exit(0)

if __name__ == '__main__':
    if check_oom():
        recover()
    else:
        print("HEARTBEAT_OK")

配置OpenClaw OOM监控任务:

openclaw cron add \
  --name "OOM自愈守卫" \
  --cron "*/5 * * * *" \
  --tz "Asia/Shanghai" \
  --session isolated \
  --message "执行 OOM 自愈检查:

1. 运行:python /mnt/workspace/auto_recover.py
2. 如果输出 HEARTBEAT_OK,不需要任何操作
3. 如果输出包含'已将 batch_size 调整',通过钉钉告诉我调整详情,并说明训练已自动重启
4. 如果退出码为 2(需要人工介入),立刻通过钉钉通知我,附上最后 20 行训练日志" \
  --announce

自动恢复工作流程

  1. 训练任务发生OOM。

  2. OpenClaw5分钟内检测到OOM错误。

  3. 自动将batch_size减半并重启训练任务。

  4. 通过钉钉发送处理结果通知。

  5. 如连续3次自动恢复失败,则通知用户人工介入。

场景四:配置每日训练报告

应用场景

通过配置每日训练报告,您可以在每天固定时间(如每日上午9点)自动接收DSW实例的全局状态汇总,包括当前运行的训练任务、GPU资源使用情况以及最近的实验结果,便于掌控整体训练进度。

实现方法

创建日报生成脚本/mnt/workspace/daily_report.py

import subprocess
import json
from datetime import datetime, timedelta
from pathlib import Path

def get_running_jobs():
    """获取当前正在运行的训练进程"""
    result = subprocess.run(['ps', 'aux'], capture_output=True, text=True)
    jobs = [line for line in result.stdout.split('\n')
            if 'train.py' in line or 'finetune.py' in line]
    return jobs

def get_gpu_summary():
    result = subprocess.run(
        ['nvidia-smi', '--query-gpu=index,name,utilization.gpu,memory.used,memory.total',
         '--format=csv,noheader'],
        capture_output=True, text=True
    )
    return result.stdout.strip()

def get_experiment_log_summary():
    """读取实验记录"""
    log_path = Path("/mnt/workspace/experiment_log.md")
    if not log_path.exists():
        return "暂无实验记录"
    # 返回最后30行
    lines = log_path.read_text().split('\n')
    return '\n'.join(lines[-30:])

if __name__ == '__main__':
    now = datetime.now().strftime('%Y-%m-%d %H:%M')
    running = get_running_jobs()
    gpu = get_gpu_summary()
    exp_log = get_experiment_log_summary()

    report = f"""=== DSW 日报 {now} ===

【当前运行中的任务】
{chr(10).join(running) if running else '无正在运行的训练任务'}

【GPU 状态】
{gpu}

【最近实验记录】
{exp_log}
"""
    print(report)

配置OpenClaw每日报告任务:

openclaw cron add \
  --name "每日训练日报" \
  --cron "0 9 * * *" \
  --tz "Asia/Shanghai" \
  --session isolated \
  --message "生成今日 DSW 工作日报:

1. 运行:python /mnt/workspace/daily_report.py
2. 根据输出内容,生成一份简洁的日报,包括:
   - 当前正在运行的任务简述
   - GPU 资源使用情况
   - 最近实验结果摘要(如有)
   - 如发现任何异常,提醒我关注
3. 通过钉钉发送这份日报,格式友好易读" \
  --announce

任务管理

您可以同时配置并运行上述所有监控任务,它们相互独立且互不干扰。

监控任务汇总

任务名称

触发时机

功能说明

GPU健康巡检

15分钟

监控GPU利用率、显存占用、温度等指标,异常时发送告警

OOM自愈守卫

5分钟

检测OOM错误并自动调整参数重启训练

每日训练日报

每天9:00

汇总并推送当前任务状态、GPU使用情况、实验记录

训练结束通知

训练脚本结束时

任务完成或失败时即时通知

管理定时任务

# 查看所有定时任务
openclaw cron list

# 禁用某个任务(使用实际的job_id替换<job_id>)
openclaw cron disable <job_id>

# 重新启用任务
openclaw cron enable <job_id>

常见问题

Q:未收到钉钉通知,如何排查?

# 检查OpenClaw服务状态
openclaw status

# 发送测试消息
openclaw message send -m "测试消息,如果收到此消息说明钉钉配置正常"

Q:定时任务已触发但脚本未执行?

# 查看所有定时任务
openclaw cron list

# 查看指定任务的执行日志(使用实际的job_id替换<job_id>)
openclaw cron logs <job_id> --tail 20

Q:如何批量禁用所有监控任务?

您可以使用以下命令批量禁用或启用所有定时任务(需安装jq工具):

# 批量禁用所有任务
openclaw cron list --json | jq -r '.[].id' | xargs -I {} openclaw cron disable {}

# 批量启用所有任务
openclaw cron list --json | jq -r '.[].id' | xargs -I {} openclaw cron enable {}

或者,您可以直接告诉OpenClaw执行批量操作:

帮我把所有 cron 定时任务都禁用,周一早上 9 点再全部重新启用