File size: 12,826 Bytes
199235a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#!/usr/bin/env bash
# IN2 experiment driver: generate arm C, gate all arms, train A/B/C, probe each,
# read out, upload. Unattended, with hard gates -- every one of them exists because
# the failure it catches is SILENT and would otherwise produce a plausible-looking
# number for the wrong thing.
set -uo pipefail
cd "$(dirname "$0")"
ROOT="$(cd ../.. && pwd)"
export LD_LIBRARY_PATH="$ROOT/Tensor-Implementations/lib:$ROOT/Profiler/lib:${LD_LIBRARY_PATH:-}"
export OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
PY="$ROOT/envv/bin/python"; HF="$ROOT/envv/bin/hf"
LOGDIR=in2_logs; mkdir -p $LOGDIR
MASTER=$LOGDIR/driver_$(date +%Y%m%d_%H%M).log
say(){ echo "[$(date +%H:%M:%S)] $*" | tee -a "$MASTER"; }
die(){ say "FATAL: $*"; say "aborting -- see $MASTER"; exit 1; }

# ---- configuration -------------------------------------------------------
ARCH="CP_N_EMBD=1536 CP_N_LAYER=36 CP_N_HEAD=12 CP_N_KVHEAD=4 CP_FFN=4096 CP_WEIGHT_TYING=0"
BASE_CKPT=${BASE_CKPT:-$PWD/checkpoints_bluscriptcp/rank_0/blumodelcp_run7_step_750.ckpt}
DATA=${DATA:-/root/.cache/huggingface/hub/datasets--navingv--flux/snapshots/5232b3d133d2eb71905725f288ff6b56dc0df773}
T=16384; K=64; EXAMPLES=12816; SHARDS=3
# D_MIN is the generator's DEFAULT (64) and must stay there. It is tempting to set
# it to R so every arm-C needle lands in the failing region -- that is wrong, and the
# gate catches it: d_min feeds draw_sites(lo_margin=span+d_min), so raising it moves
# arm C's PROBES, not just its needles. At d_min=9835 arm C's answers were confined to
# the last ~6.5k of the document (6522 distinct offsets vs arm B's 16293) and cross-arm
# assertion 8 failed. Arm B can only absorb position effects while B and C share
# positions, which is exactly what raising d_min destroys -- and it re-creates the
# position-specific-circuit confound the interleaving exists to prevent.
# The consequence is accepted, not fixed: only ~8.2% of arm C's 820,224 triples land
# beyond R=9835 (67,653 of them). That fraction is the price of positional matching.
D_MIN=${D_MIN:-64}
R_MEASURED=${R_MEASURED:-9835}
FT_STEPS=${FT_STEPS:-400}; GBATCH=${GBATCH:-524288}; B=${B:-4}
YARN=4; GPUS=0,1,2,3; NP=4
HF_REPO=${HF_REPO:-unparallelled/BluScriptCP}
STAGE=/root/in2_upload; rm -rf $STAGE; mkdir -p $STAGE

# Single-instance lock. Three copies of this script ran concurrently once (one from
# each terminal), sharing in2_logs/, checkpoints_bluscriptcp/ and all four GPUs: 10
# exec processes contending, and they would have raced for run numbers and written
# each other's arm markers. A second launch must refuse, not collide.
LOCK=.in2_driver.lock
if [ -e "$LOCK" ] && kill -0 "$(cat "$LOCK" 2>/dev/null)" 2>/dev/null; then
  echo "REFUSING: another driver is already running (pid $(cat "$LOCK")). "
  echo "  If it is dead: rm $LOCK"
  exit 1
fi
echo $$ > "$LOCK"
trap 'rm -f "$LOCK"' EXIT INT TERM

say "IN2 driver starting.  base=$BASE_CKPT  d_min=$D_MIN  R=$R_MEASURED"
[ -x ./build/bluscriptCP_exec ] || die "no binary"
[ -f "$BASE_CKPT" ] || die "base checkpoint missing: $BASE_CKPT"
[ -x "$PY" ] || die "venv python missing"

# ---- 1. arm C data (A and B already generated) ---------------------------
if [ ! -f in2_data/arm_c/.done ]; then
  say "generating arm C (train) at --d-min $D_MIN (generator default; see note above)"
  FILL=$(ls Data_Loader/Data/flux_train_0000{1,2,3}*.bin 2>/dev/null | head -12 | tr '\n' ' ')
  [ -z "$FILL" ] && FILL=$(ls Data_Loader/Data/flux_train*.bin | head -12 | tr '\n' ' ')
  $PY Tests/bluscriptcp/in2_gen.py --arm c --T $T --examples $EXAMPLES --K $K --shards $SHARDS \
      --seed 0 --d-min $D_MIN --filler-shards $FILL --out-dir in2_data/arm_c >>"$MASTER" 2>&1 \
      || die "arm C train generation failed"
  say "generating arm C (val)"
  $PY Tests/bluscriptcp/in2_gen.py --arm c --T $T --examples 64 --split val --K $K --shards 1 \
      --seed 0 --d-min $D_MIN --filler-shards $(ls Data_Loader/Data/flux_val*.bin | head -1) \
      --out-dir in2_data/arm_c >>"$MASTER" 2>&1 || die "arm C val generation failed"
  touch in2_data/arm_c/.done
fi
grep -E 'distance:' "$MASTER" | tail -2 | while read -r l; do say "  arm C $l"; done

# ---- 2. GATE: 23 layout assertions, all arms, both splits ---------------
# This is what caught arm B silently dropping 213 of 1024 needles last time -- a
# desynchronised answer_start histogram destroys the B-vs-C matched-position
# discipline the whole primary claim rests on.
for SPLIT in train val; do
  say "gate ($SPLIT) on all three arms"
  OUT=$($PY Tests/bluscriptcp/in2_gate.py --dirs in2_data/arm_a in2_data/arm_b in2_data/arm_c \
        --split $SPLIT --B $B --dp 1 2>&1); echo "$OUT" >>"$MASTER"
  echo "$OUT" | grep -q "ALL PASS" || { echo "$OUT" | tail -20; die "GATE FAILED ($SPLIT)"; }
  say "  gate $SPLIT: ALL PASS"
done

# ---- 3. train the three arms --------------------------------------------
declare -A RUNNO
for ARM in a b c; do
  MK=$LOGDIR/arm_${ARM}.trained
  if [ -f "$MK" ]; then RUNNO[$ARM]=$(cat "$MK"); say "arm $ARM already trained (run ${RUNNO[$ARM]})"; continue; fi
  # One checkpoint step costs 17 GB across 4 ranks (3.9 GB model + 2 sidecars, per
  # rank). The first attempt filled a 193 GB disk: FREQ=100 x KEEP=2 x 3 arms is up
  # to 102 GB of arm checkpoints on top of the base. Saves then failed with a mere
  # [WARN] while training carried on, so arm C ran all 400 steps and reported "done"
  # with ZERO checkpoints on disk -- 45 minutes of GPU time for nothing. Check first.
  FREE_G=$(df -BG --output=avail / | tail -1 | tr -dc '0-9')
  say "  free disk: ${FREE_G}G"
  [ "${FREE_G:-0}" -ge 40 ] || die "only ${FREE_G}G free; one arm checkpoint needs ~17G plus a same-size .tmp during the write. Free space before continuing."

  # Prune sidecars whose .ckpt has already been rotated away. CP_CKPT_KEEP prunes
  # .ckpt files but NOT the zero_g* sidecars bluscriptCP writes alongside them, so
  # they accumulate silently -- 50 GB of them built up on the 600M run.
  for d in checkpoints_bluscriptcp/rank_*; do
    [ -d "$d" ] || continue
    K=$(ls $d/*.ckpt 2>/dev/null | grep -oE '_run[0-9]+_step_[0-9]+' | sort -u)
    for f in $d/*.zero_g*; do
      [ -e "$f" ] || continue
      S=$(echo "$f" | grep -oE '_run[0-9]+_step_[0-9]+')
      echo "$K" | grep -qx "$S" || rm -f "$f"
    done
    rm -f $d/*.tmp
  done

  L=$LOGDIR/arm_${ARM}_train.log
  say "training arm $ARM  ($FT_STEPS steps x $GBATCH tokens, T=$T, cp=$NP, YaRN=$YARN)"
  env CUDA_VISIBLE_DEVICES=$GPUS $ARCH \
    CP_INIT_FROM="$BASE_CKPT" \
    CP_SIZE=$NP CP_ATTN_MODE=ring CP_ATTN_FUSION=split \
    CP_T=$T YARN_SCALE=$YARN CP_B=$B CP_GLOBAL_BATCH=$GBATCH \
    CP_ZERO=1 CP_ZERO_V2=1 CP_ZERO_SYMMETRIC=1 CP_BF16=1 CP_OPTIMIZER=muon \
    CP_MAX_LR=1e-3 CP_MIN_LR=1e-4 CP_REWARMUP=100 CP_REWARMUP_PEAK=0.3 \
    CP_MAX_STEPS=$FT_STEPS CP_WARMUP=1 \
    CP_CKPT=1 CP_CKPT_FREQ=200 CP_CKPT_KEEP=1 CP_CKPT_NEW_RUN=1 \
    CP_DATA_ROOT="$PWD/in2_data/arm_$ARM" \
    mpirun --allow-run-as-root -np $NP ./build/bluscriptCP_exec > "$L" 2>&1 \
    || die "arm $ARM training failed -- see $L"
  RN=$(grep -oE 'CP_Training_log[0-9]+' "$L" | head -1 | grep -oE '[0-9]+')
  [ -n "$RN" ] || die "arm $ARM: could not determine run number"
  # A zero exit code is NOT proof the checkpoint exists: bluscriptCP catches a failed
  # save, prints [WARN], and trains on. Verify the artifact, not the signal.
  CKF=$(ls -t checkpoints_bluscriptcp/rank_0/blumodelcp_run${RN}_step_*.ckpt 2>/dev/null | head -1)
  [ -n "$CKF" ] || die "arm $ARM (run $RN) finished but wrote NO checkpoint -- check $L for 'checkpoint save ... failed'"
  say "  arm $ARM checkpoint: $(basename "$CKF") ($(du -h "$CKF" | cut -f1))"
  if grep -q 'checkpoint save.*failed' "$L"; then
    die "arm $ARM: a checkpoint save FAILED during training (see $L). Refusing to continue on a partial arm."
  fi
  echo "$RN" > "$MK"; RUNNO[$ARM]=$RN
  say "  arm $ARM done -> run $RN, final loss $(grep -E '^step ' "$L" | tail -1 | grep -oE 'loss: [0-9.]+')"
done

# ---- 3b. LEARNABILITY GATE (arm C) --------------------------------------
# The plan is explicit: if arm C's synthetic val_loss does not fall, the run says
# nothing about IN2 and must NOT be written up as a null.
CSV=CP_BluScreipt_Training_logs/CP_Training_log${RUNNO[c]}.csv
if [ -f "$CSV" ]; then
  # val_loss is forward-filled and val_freq defaults to 250, so a 400-step arm yields
  # as few as ONE real evaluation. Comparing first to last of a forward-filled column
  # then reports "did not fall" for a run that was never measured twice -- which is
  # exactly what aborted the first attempt AFTER all three arms had trained.
  NV=$(awk -F, 'NR>1 && $3+0>0 {print $3}' "$CSV" | sort -u | wc -l)
  V=$(awk -F, 'NR>1 && $3+0>0 && $3!=p {v=$3; if(f==""){f=$3} p=$3} END{print f" "v}' "$CSV")
  VF=${V% *}; VL=${V#* }
  say "arm C val_loss: $NV distinct point(s), first=$VF last=$VL"
  if [ "${NV:-0}" -lt 2 ]; then
    say "  learnability gate SKIPPED: only $NV validation point(s) -- cannot judge a trend."
    say "  (lower CP_VAL_FREQ, or lengthen the arm, to make this gate meaningful)"
    VF=1; VL=0   # force the comparison below to pass
  fi
  $PY -c "import sys; sys.exit(0 if float('$VL') < float('$VF') else 1)" \
    || die "LEARNABILITY GATE FAILED: arm C val_loss did not fall ($VF -> $VL). The run says nothing about IN2."
  say "  learnability gate: PASS"
else say "  WARN: no CSV for arm C run ${RUNNO[c]}; learnability gate skipped"; fi

# ---- 4. probe each arm (same YaRN cache it trained under) ---------------
for ARM in a b c; do
  OUTD=probe_arm_${ARM}
  [ -f $OUTD/reach.csv ] && { say "probe $ARM already done"; continue; }
  CK=$(ls -t checkpoints_bluscriptcp/rank_0/blumodelcp_run${RUNNO[$ARM]}_step_*.ckpt 2>/dev/null | head -1)
  [ -n "$CK" ] || die "arm $ARM: no checkpoint for run ${RUNNO[$ARM]}"
  say "probing arm $ARM  ($CK)"
  CKPT="$PWD/$CK" OUT=$OUTD FACTORS=$YARN CACHES=yarn YARN_SCALE=$YARN GPUS=$GPUS BLOCKS=3 \
    ./probe_1b.sh >>"$MASTER" 2>&1 || say "  WARN: probe $ARM returned nonzero"
  [ -f $OUTD/reach.csv ] && say "  arm $ARM reach.csv written" || say "  WARN: no reach.csv for arm $ARM"
done

# ---- 5. readout ---------------------------------------------------------
say "readout"
$PY Tests/bluscriptcp/in2_report.py --needle-dir probe_arm_c/needles --T $T \
    --arms a b c --R $R_MEASURED --blocks 3 > $LOGDIR/in2_report.txt 2>&1 \
    || say "  WARN: in2_report returned nonzero (see $LOGDIR/in2_report.txt)"
tail -30 $LOGDIR/in2_report.txt | tee -a "$MASTER"

# ---- 6. UPLOAD everything needed to carry forward -----------------------
say "staging artefacts for HF"
cp -r $LOGDIR $STAGE/ 2>/dev/null
for d in probe_run8 probe_run8_s4 probe_run7_yarn4 probe_arm_a probe_arm_b probe_arm_c; do
  [ -d "$d" ] && cp -r "$d" $STAGE/ 2>/dev/null
done
mkdir -p $STAGE/train_csv && cp CP_BluScreipt_Training_logs/*.csv $STAGE/train_csv/ 2>/dev/null
mkdir -p $STAGE/run_logs  && cp run_logs/*.log $STAGE/run_logs/ 2>/dev/null
cp -r /root/claude-vault $STAGE/vault 2>/dev/null
# code: git holds it, but a tarball costs nothing and survives a lost branch
tar czf $STAGE/cp_source.tgz --exclude='build' --exclude='checkpoints_bluscriptcp' \
    --exclude='in2_data' --exclude='Data_Loader/Data' --exclude='.git' --exclude='*.bin' \
    -C "$ROOT" dist/Context_Parallelism dist/zero dist/communication/src/processGroupNccl.cpp 2>/dev/null
# the three arm checkpoints (weights only -- flat, loadable at any np)
mkdir -p $STAGE/checkpoints
for ARM in a b c; do
  CK=$(ls -t checkpoints_bluscriptcp/rank_0/blumodelcp_run${RUNNO[$ARM]:-0}_step_*.ckpt 2>/dev/null | head -1)
  [ -n "$CK" ] && cp "$CK" $STAGE/checkpoints/arm_${ARM}_$(basename "$CK")
done
[ -f "$BASE_CKPT" ] && cp "$BASE_CKPT" $STAGE/checkpoints/extended_$(basename "$BASE_CKPT")
du -sh $STAGE/* 2>/dev/null | tee -a "$MASTER"

if [ -x "$HF" ]; then
  say "uploading to $HF_REPO"
  "$HF" upload "$HF_REPO" $STAGE/cp_source.tgz  source/cp_source_in2.tgz      >>"$MASTER" 2>&1
  "$HF" upload "$HF_REPO" $STAGE/vault          docs/                          >>"$MASTER" 2>&1
  "$HF" upload "$HF_REPO" $STAGE/in2_logs       logs/in2/                      >>"$MASTER" 2>&1
  "$HF" upload "$HF_REPO" $STAGE/train_csv      logs/in2_train_csv/            >>"$MASTER" 2>&1
  "$HF" upload "$HF_REPO" $STAGE/run_logs       logs/in2_stdout/               >>"$MASTER" 2>&1
  for d in probe_run8 probe_run8_s4 probe_run7_yarn4 probe_arm_a probe_arm_b probe_arm_c; do
    [ -d "$STAGE/$d" ] && "$HF" upload "$HF_REPO" "$STAGE/$d" "logs/$d/"       >>"$MASTER" 2>&1
  done
  "$HF" upload "$HF_REPO" $STAGE/checkpoints    checkpoints/in2/               >>"$MASTER" 2>&1
  say "upload complete"
else say "WARN: hf CLI not found at $HF -- artefacts staged in $STAGE but NOT uploaded"; fi

say "DONE. staged copy: $STAGE   master log: $MASTER"