File size: 5,313 Bytes
880dff9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/env bash
# 四个 baseline 臂(linear / xattn / prompt / adaln)的单卡端到端 smoke:
#   每臂:单进程 train.py(不走 DeepSpeed)--limit 8 --max_steps 2 → 导出 step-2.safetensors
#         → 用该 ckpt 推理一条 right:1.0:21(20 步)并实测位移 → check_ckpt(CPU)strict 装回
#   最后把每臂的 n_new_params / step_time / 峰值显存 / 实测位移汇总到 outputs/smoke_baselines/summary.json。
# 用法:bash scripts/smoke_baselines.sh                 # 四臂依次在 GPUS(默认 4 5 6 7)上轮流跑
#      ARMS="linear adaln" bash scripts/smoke_baselines.sh
#      PARALLEL=1 bash scripts/smoke_baselines.sh      # 四臂各占一张卡并行(要有四张空闲卡)
#      SUMMARY_ONLY=1 bash scripts/smoke_baselines.sh  # 只重算汇总(各臂产物已在)
# 单卡无 DeepSpeed 时 AdamW 直接更新 bf16 参数,峰值显存 ≈ 47 GB(权重 + 梯度 + 两份 Adam 状态各 10 GB + 激活)。
set -euo pipefail
ROOT=/opt/dlami/nvme/zhiyangdeng/ActionRoPE
PY=$ROOT/.venv/bin/python
export DIFFSYNTH_SKIP_DOWNLOAD=True
export PYTHONPATH="$ROOT"
ARMS="${ARMS:-linear xattn prompt adaln}"
GPUS=(${GPUS:-4 5 6 7})
PARALLEL="${PARALLEL:-0}"
INFER_STEPS="${INFER_STEPS:-20}"
CLIP="${CLIP:-clip_Eybx_200000958_000273}"    # val_eybx,tidal_flats,sidecar valid
OUT=$ROOT/outputs/smoke_baselines
mkdir -p "$OUT" "$ROOT/outputs/samples"
LOG=$OUT/smoke_baselines.log
exec > >(tee -a "$LOG") 2>&1
T_ALL=$(date +%s)

run_arm() {  # run_arm <arm> <gpu>
  local ARM=$1 GPU=$2 T0 RUN CKPT
  T0=$(date +%s)
  RUN=$ROOT/outputs/smoke_${ARM}_1gpu
  mkdir -p "$RUN"
  echo "===== [$ARM] GPU $GPU:单卡 2 步训练 → $RUN ($(date '+%F %T')) ====="
  CUDA_VISIBLE_DEVICES=$GPU "$PY" "$ROOT/actionrope/train.py" \
    --arm "$ARM" --limit 8 --max_steps 2 --save_every 2 --val_every 0 --warmup_steps 0 \
    --num_workers 2 --seed 0 --output "$RUN" 2>&1 | tee "$RUN/train.log"
  CKPT=$RUN/step-2.safetensors
  test -s "$CKPT"
  echo "===== [$ARM] GPU $GPU:step-2 推理 right:1.0:21($INFER_STEPS 步) ====="
  CUDA_VISIBLE_DEVICES=$GPU "$PY" -m actionrope.infer --ckpt "$CKPT" --first_frame "$CLIP" --scene tidal_flats \
    --actions "right:1.0:21" --steps "$INFER_STEPS" --seed 0 \
    --out "$ROOT/outputs/samples/smoke_${ARM}_right_x1.mp4" 2>&1 | tee "$RUN/infer.log"
  echo "===== [$ARM]:check_ckpt(CPU,臂按 ckpt 自动识别) ====="
  "$PY" "$ROOT/tests/check_ckpt.py" "$CKPT" --json_out "$RUN/check_ckpt.json" > "$RUN/check_ckpt.log" 2>&1
  "$PY" -c "import json; r=json.load(open('$RUN/check_ckpt.json')); assert r['strict_load_ok'] and r['arm']=='$ARM', r; print('check_ckpt', {k: r[k] for k in ('arm','n_tensors','n_arm_tensors','n_new_params','n_changed_tensors','arm_nonzero_tensors') if k in r})"
  echo "----- [$ARM] 通过,耗时 $(( $(date +%s) - T0 )) s -----"
}

i=0
PIDS=()
[ "${SUMMARY_ONLY:-0}" = 1 ] && ARMS_RUN="" || ARMS_RUN="$ARMS"
for ARM in $ARMS_RUN; do
  GPU=${GPUS[$(( i % ${#GPUS[@]} ))]}
  if [ "$PARALLEL" = 1 ]; then
    run_arm "$ARM" "$GPU" > "$OUT/${ARM}.log" 2>&1 &
    PIDS+=($!)
  else
    run_arm "$ARM" "$GPU"
  fi
  i=$((i + 1))
done
if [ "$PARALLEL" = 1 ]; then
  FAIL=0
  for p in "${PIDS[@]}"; do wait "$p" || FAIL=1; done
  for ARM in $ARMS; do cat "$OUT/${ARM}.log"; done
  [ "$FAIL" = 0 ] || { echo "有臂失败"; exit 1; }
fi

# 汇总:每臂 n_new_params / 2 步的 step_time / 峰值显存 / 推理实测位移
"$PY" - "$OUT/summary.json" $ARMS <<'EOF'
import csv, json, sys
ROOT = "/opt/dlami/nvme/zhiyangdeng/ActionRoPE"
out_path, arms = sys.argv[1], sys.argv[2:]
summary = {}
for arm in arms:
    run = f"{ROOT}/outputs/smoke_{arm}_1gpu"
    cfg = json.load(open(f"{run}/config.json"))
    rows = list(csv.DictReader(open(f"{run}/train_log.csv")))
    inf = json.load(open(f"{ROOT}/outputs/samples/smoke_{arm}_right_x1.json"))
    chk = json.load(open(f"{run}/check_ckpt.json"))
    summary[arm] = {
        "n_new_params": cfg["model"]["n_new_params"], "arm_class": cfg["model"]["arm_class"], "arm_kwargs": cfg["model"]["arm_kwargs"],
        "text_mode": cfg["args"]["text_mode"], "train_used": cfg["dataset"]["train_used"],
        "step_time_s": [round(float(r["step_time"]), 2) for r in rows], "loss": [round(float(r["loss"]), 4) for r in rows],
        "grad_norm": [round(float(r["grad_norm"]), 3) for r in rows],
        "peak_mem_gb": round(max(float(r["mem_gb"]) for r in rows), 1),
        "infer_steps": inf["steps"], "infer_sample_sec": round(inf["sample_sec"], 1), "infer_peak_mem_gb": round(inf["peak_mem_gb"], 1),
        "infer_measured_bg_shift_80": inf["measured"]["sift"], "infer_expected_bg_shift_80": inf["expected_bg_shift_80"],
        "infer_error_px": inf["error_px"], "infer_sift_source": inf["measured"]["sift_source"],
        "ckpt_n_tensors": chk["n_tensors"], "ckpt_n_arm_tensors": chk["n_arm_tensors"],
        "ckpt_dit_changed_tensors": chk["n_changed_tensors"], "ckpt_arm_nonzero_tensors": chk.get("arm_nonzero_tensors"),
        "ckpt_size_gb": round(chk["size_gb"], 2),
    }
json.dump(summary, open(out_path, "w"), indent=2, ensure_ascii=False)
print(json.dumps(summary, indent=1, ensure_ascii=False))
EOF
echo "===== smoke_baselines 全部通过($ARMS),总耗时 $(( $(date +%s) - T_ALL )) s ($(date '+%F %T')) ====="