File size: 10,879 Bytes
c5dae6b | 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 | #!/usr/bin/env bash
# =============================================================================
# ext64k_b5.sh -- YaRN extension 32k -> 64k on b5, deadline-aware.
#
# PHASE 1 3-step probe: does 64k fit at cp=4 on 143 GB, and how fast is a step?
# PHASE 2 train as many steps as fit before HARD_STOP, WSD tail sized so the
# FINAL checkpoint is DECAYED and comparable to the 32k results
# PHASE 3 eval 4 lengths IN PARALLEL on the 4 GPUs (wall clock = slowest job)
# PHASE 4 upload ckpt + sidecar + logs
#
# WHY b5: documents are 65,536-131,072 tokens, so the MINIMUM equals the 64k
# window and every training sample is one contiguous document. b4 (32-64k)
# would straddle in roughly half its samples. Same reasoning that made b4 the
# right choice at 32k.
#
# PARENT: b4 full-epoch step 2227 -- the best 32k model (70.0/58.0/43.0 at
# 8k/16k/32k). CP_INIT_FROM loads WEIGHTS ONLY, so its cp=2 shard layout is
# irrelevant to this cp=4 run, and no sidecar is needed (none is read).
#
# YaRN INVARIANT: SCALE * ORIG_MAXPOS must equal seq_len EXACTLY and ORIG_MAXPOS
# must be the length the parent was actually trained at. 2 * 32768 = 65536.
#
# LR: CP_MAX_LR / CP_MIN_LR DO NOT EXIST -- bluscriptCP.cpp:131-132 hardcodes
# 6e-4 / 6e-5 and the env block never reads them. Real schedule is
# 6e-4 * CP_REWARMUP_PEAK(0.3) = 1.8e-4 peak, 6e-5 floor -- the same values
# every previous run used, so results stay comparable.
#
# DEADLINE: HARD_STOP is a UTC epoch. Step count is derived from the MEASURED
# probe rate, not an estimate, so the run lands inside the window.
# =============================================================================
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/python3
HF=/root/envv/bin/hf
EXE=./build/bluscriptCP_exec
CK=checkpoints_bluscriptcp/rank_0
LOG=ext64k_logs; mkdir -p "$LOG"
M="$LOG/master.log"
REPO=unparallelled/BluScriptCP
say(){ echo "[$(date -u +%H:%M:%S)] $*" | tee -a "$M" >&2; }
die(){ say "FATAL: $*"; exit 1; }
T=65536; NP=4; GPUS=0,1,2,3
ORIG=32768; SCALE=2 # 2 * 32768 == 65536
DATA=lendata/b5_65536_131072
PARENT="$CK/b4epoch32k_step2227.ckpt"
HAY="$PWD/lendata/haystack/b2val_haystack.bin"
WARM=100; TAIL=${TAIL:-2}; FREQ=50; KEEP=2
GB=524288
# 23:30 IST = 18:00 UTC today
HARD_STOP=${HARD_STOP:-$(date -u -d "$(date -u +%Y-%m-%d) 18:00:00" +%s)}
RESERVE_MIN=${RESERVE_MIN:-50} # eval (28) + upload (20) + slack
$PY -c "import tiktoken" 2>/dev/null || die "tiktoken missing"
[ -x "$EXE" ] || die "$EXE not built"
[ -f "$PARENT" ] || die "parent missing: $PARENT"
[ -f "$HAY" ] || die "haystack missing: $HAY"
[ -d "$DATA" ] || die "$DATA missing"
[ $((SCALE*ORIG)) -eq $T ] || die "YaRN invariant: $SCALE * $ORIG != $T"
ntr=$(ls "$DATA"/*train*.bin 2>/dev/null | wc -l)
nva=$(ls "$DATA"/*val*.bin 2>/dev/null | wc -l)
[ "$ntr" -ge 1 ] && [ "$nva" -ge 1 ] || die "need train+val shards in $DATA (have $ntr/$nva)"
have=$(( $(du -cb "$DATA"/*train*.bin | tail -1 | cut -f1) / 2 ))
say "=== 32k -> 64k YaRN extension on b5 (4x H200, cp=$NP) ==="
say "parent: b4 full epoch step 2227 (best 32k model)"
say "YaRN SCALE=$SCALE ORIG=$ORIG -> $((SCALE*ORIG)) == CP_T=$T OK"
say "b5: $ntr train shards = $(echo "scale=3; $have/1000000000" | bc) B tokens available"
say "hard stop $(date -u -d @$HARD_STOP +%H:%M) UTC = $(date -u -d @$((HARD_STOP+19800)) +%H:%M) IST, reserving ${RESERVE_MIN}m"
COMMON="CP_SIZE=$NP CP_ATTN_MODE=ring CP_ATTN_FUSION=split CP_T=$T \
YARN_SCALE=$SCALE YARN_ORIG_MAXPOS=$ORIG \
CP_ZERO=1 CP_ZERO_V2=1 CP_ZERO_SYMMETRIC=1 CP_BF16=1 CP_OPTIMIZER=muon \
CP_WARMUP=$WARM CP_REWARMUP=$WARM CP_REWARMUP_PEAK=0.3"
ARCH="CP_N_EMBD=1536 CP_N_LAYER=36 CP_N_HEAD=12 CP_N_KVHEAD=4 CP_FFN=4096 CP_WEIGHT_TYING=0"
# ---- PHASE 1: fit + speed --------------------------------------------------
if [ ! -f "$LOG/probe.ok" ]; then
say "PHASE 1: 3-step probe (64k at cp=4 projects to 108.8 GB of 143 GB)"
env $ARCH $COMMON CP_STABLE=0 CP_CKPT=0 \
CP_INIT_FROM="$PWD/$PARENT" CP_DATA_ROOT="$PWD/$DATA" \
CP_B=1 CP_GLOBAL_BATCH=65536 CP_MAX_STEPS=3 \
CUDA_VISIBLE_DEVICES=$GPUS mpirun --allow-run-as-root -np $NP "$EXE" \
> "$LOG/probe.log" 2>&1
if grep -qaiE 'out of memory|bad_alloc' "$LOG/probe.log"; then
say "PROBE OOM -- 64k does not fit at cp=$NP even on 143 GB cards."
grep -aoE 'cudaMallocAsync\(size=[0-9]+\) failed' "$LOG/probe.log" | head -2 | sed 's/^/ /' >&2
exit 1
fi
grep -aE '^step +[0-9]+ \|' "$LOG/probe.log" | sed 's/^/ /' >&2
say "PROBE OK: peak $(grep -aoE 'mem: [0-9]+MB' "$LOG/probe.log" | tail -1)"
touch "$LOG/probe.ok"
fi
# ---- derive the step count from the MEASURED rate --------------------------
# The probe used a tiny global batch, so its dt is NOT the real per-step cost.
# Scale it: real grad_accum is GB/T vs the probe's 65536/T.
SPS=$($PY - "$LOG/probe.log" $GB $T <<'PYEOF'
import re,sys,statistics
t=open(sys.argv[1],errors='ignore').read()
d=[float(x) for x in re.findall(r'dt: ([0-9.]+)ms', t)]
probe_accum=65536//int(sys.argv[3]) or 1
real_accum=int(sys.argv[2])//int(sys.argv[3])
per=statistics.median(d[1:]) if len(d)>2 else d[-1]
print(f"{per/1000.0*real_accum/probe_accum:.3f}")
PYEOF
)
say "measured step cost at real batch: ${SPS} s/step"
if [ -n "${STEPS_OVERRIDE:-}" ]; then
say "STEPS_OVERRIDE=$STEPS_OVERRIDE -- the probe ran grad_accum=1 so its dt x8"
say " overstated the real step cost 5.8x (74.0 vs a measured 12.85 s/step)."
fi
STEPS=$($PY - "$SPS" "$HARD_STOP" "$RESERVE_MIN" "$have" "$GB" "$WARM" "$TAIL" <<'PYEOF'
import sys,time,math
sps=float(sys.argv[1]); stop=int(sys.argv[2]); res=int(sys.argv[3])
have=int(sys.argv[4]); gb=int(sys.argv[5]); warm=int(sys.argv[6]); tail=int(sys.argv[7])
budget=stop-time.time()-res*60
n=int(budget/sps)
n=min(n, have//gb) # never wrap the data
n=max(n, warm+tail+10) # schedule must be legal
print(n)
PYEOF
)
STEPS=${STEPS_OVERRIDE:-$STEPS}
STABLE=$(( STEPS - WARM - TAIL ))
[ "$STABLE" -lt 1 ] && STABLE=1
say "PHASE 2: $STEPS steps = $(echo "scale=3; $STEPS*$GB/1000000000" | bc) B tokens = $(echo "scale=0; $STEPS*$GB*100/866000000" | bc)% of a b5 epoch"
say " WSD: warmup $WARM, stable $STABLE, decay tail $TAIL -> FINAL checkpoint IS decayed"
if [ -f "$LOG/ext.ckpt" ] && [ -f "$(cat "$LOG/ext.ckpt")" ]; then
say "already trained -> $(cat "$LOG/ext.ckpt")"
else
env $ARCH $COMMON CP_STABLE=$STABLE \
CP_CKPT=1 CP_CKPT_FREQ=$FREQ CP_CKPT_KEEP=$KEEP CP_CKPT_NEW_RUN=1 \
CP_INIT_FROM="$PWD/$PARENT" CP_DATA_ROOT="$PWD/$DATA" \
CP_B=1 CP_GLOBAL_BATCH=$GB CP_MAX_STEPS=$STEPS \
CUDA_VISIBLE_DEVICES=$GPUS mpirun --allow-run-as-root -np $NP "$EXE" \
> "$LOG/ext.log" 2>&1
grep -qaiE 'out of memory|bad_alloc' "$LOG/ext.log" && die "OOM in the full run"
RN=$(grep -aoE 'CP_Training_log[0-9]+' "$LOG/ext.log" | head -1 | grep -oE '[0-9]+')
[ -n "$RN" ] || die "no run number"
CKF=$(ls -t $CK/blumodelcp_run${RN}_step_*.ckpt 2>/dev/null | head -1)
[ -n "$CKF" ] || die "run $RN wrote NO checkpoint"
n=$(ls checkpoints_bluscriptcp/rank_*/"$(basename "$CKF")" 2>/dev/null | wc -l)
[ "$n" -ge "$NP" ] || die "only $n/$NP rank shards for $(basename "$CKF")"
echo "$CKF" > "$LOG/ext.ckpt"; echo "$RN" > "$LOG/runnum"
say "ext64k -> run $RN, $(basename "$CKF"), loss $(grep -aE '^step ' "$LOG/ext.log" | tail -1 | grep -oE 'loss: [0-9.]+')"
say " peak mem $(grep -aoE 'mem: [0-9]+MB' "$LOG/ext.log" | tail -1)"
say " final lr $(grep -aE '^step ' "$LOG/ext.log" | tail -1 | grep -oE 'lr [0-9.e-]+') (should be ~6e-05 = decayed)"
fi
# ---- PHASE 3: eval, 4 lengths in PARALLEL on 4 GPUs ------------------------
EXT=$(basename "$(cat "$LOG/ext.ckpt")")
say "PHASE 3: eval ext64k -- 4 lengths, one GPU each"
# 65512 + MAX_NEW 24 = 65536 exactly; 65528 would pad to 65792 and abort.
for LEN in 8192 16360 32744 65512; do
( GEN_DATA_ROOT=$DATA HAY="$HAY" PY=$PY OUT=ext64k_len_$LEN TASKS="niah_single" \
CKPTS="ext64k" N=100 PROMPT_LEN=$LEN MAX_NEW=24 T=$T \
DEPTHS="0.0,0.25,0.5,0.75,1.0" YARN_ORIG=$ORIG YARN=$SCALE \
GPUS=$(( (LEN==8192)?0:(LEN==16360)?1:(LEN==32744)?2:3 )) JOBS_PER_GPU=1 \
BF16=1 GREEDY=1 CKPT_EXTRA="ext64k=$EXT" ./run_longeval.sh \
>> "$LOG/eval_$LEN.log" 2>&1 ) &
done
wait
for LEN in 8192 16360 32744 65512; do
[ -s "ext64k_len_$LEN/summary.csv" ] && say " len $LEN -> $(sed -n 2p ext64k_len_$LEN/summary.csv)" \
|| say " len $LEN -> NO RESULT"
done
# ---- PHASE 4: upload -------------------------------------------------------
say "PHASE 4: upload"
{
echo "# 32k -> 64k YaRN extension on b5 -- $(date -u +%Y-%m-%d)"
echo
echo "Parent: b4 full-epoch step 2227 (best 32k model: 70.0/58.0/43.0 at 8k/16k/32k)."
echo "Data: b5_65536_131072 -- min doc 65,536 == the window, so every sample is"
echo " ONE contiguous document."
echo "YaRN: SCALE=2 ORIG_MAXPOS=32768 -> 65536 exactly."
echo "Train: $STEPS steps x $GB = $(echo "scale=3; $STEPS*$GB/1000000000" | bc) B tokens"
echo " = $(echo "scale=0; $STEPS*$GB*100/866000000" | bc)% of b5's 0.866 B train split (no wrap)."
echo " WSD warmup $WARM / stable $STABLE / decay tail $TAIL -- final ckpt DECAYED."
echo " LR peak 1.8e-4, floor 6e-5 (CP_MAX_LR is a no-op; see B4 results doc)."
echo " 4x H200, cp=4, B=1 x grad_accum $((GB/T))."
echo "Eval: niah_single, N=100, greedy, shared haystack b2_8192_16384 val."
echo
echo "## Results"; echo
echo "| context | niah_single |"; echo "|---|---|"
for LEN in 8192 16360 32744 65512; do
v=$(sed -n 2p "ext64k_len_$LEN/summary.csv" 2>/dev/null | cut -d, -f2)
printf "| %s | %s |\n" "$LEN" "${v:-n/a}"
done
echo
echo "For comparison, the 32k parent at the same lengths: 70.0 / 58.0 / 43.0 / n/a"
echo "(it cannot run at 64k -- its RoPE cache is sized 32,768)."
echo
echo "NOTE: this is a PARTIAL b5 epoch, sized to a wall-clock deadline. It is a"
echo "first 64k data point, not a converged extension."
} > "$LOG/RESULTS.md"
up(){ [ -e "$1" ] || return 0
$HF upload "$REPO" "$1" "$2" >>"$LOG/upload.log" 2>&1 && say " ok $2" || say " FAIL $2"; }
up "$LOG/RESULTS.md" docs/EXT64K_B5_RESULTS_$(date -u +%Y-%m-%d).md
for LEN in 8192 16360 32744 65512; do up "ext64k_len_$LEN" "logs/ext64k_len_$LEN/"; done
up "$LOG" logs/ext64k/
up ext64k_b5.sh scripts/ext64k_b5.sh
RN=$(cat "$LOG/runnum" 2>/dev/null)
for r in 0 1 2 3; do
for e in ckpt zero_g1; do
up "checkpoints_bluscriptcp/rank_$r/blumodelcp_run${RN}_step_${STEPS}.$e" \
"checkpoints/ext64k_b5_rank${r}_step_${STEPS}.$e"
done
done
say "=== EXT64K DONE ==="
|