File size: 7,162 Bytes
4b8f766 | 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 | #!/usr/bin/env bash
# =============================================================================
# ext32k_b4.sh -- YaRN extension 16k -> 32k on b4, then evaluate 1k..32k.
#
# WHY b4 AND NOT b3, at a 32,768 window:
# b3 documents are 16,384-32,768 tokens -- mean 21,224 = 65% of the window, and
# the MINIMUM is 16,384. So every b3 sample carries an EOT boundary plus part of
# a second document, and no dependency can span 32k. That is the same defect as
# the original flux corpus (median 826 tok), one scale up.
# b4 documents are 32,768-65,536 -- the minimum EQUALS the window, so every
# sample is one contiguous document and a 32k-spanning dependency is possible.
# Truncating a 44k document to 32k is fine; a straddled window is not.
#
# YaRN INVARIANT (the bug that cost 27pp at 16k):
# SCALE * ORIG_MAXPOS must equal seq_len EXACTLY, and ORIG_MAXPOS must be the
# length the parent was actually TRAINED at. 2 * 16384 = 32768. The default
# ORIG_MAXPOS is 1024 (YARNOps.cpp:57) and would silently be wrong.
#
# PARENT: l2 = the best 16k arm (b2 docs, which fit the 16k window). Extending
# from the strongest 16k model, not from run7'.
#
# GLOBAL BATCH held at 524,288 (B=1, T=32768, grad_accum=16) so the optimizer
# trajectory matches every 16k arm. Only the window changed.
#
# MEMORY: 2x H200 = 143 GB. cp=2 puts 16,384 tokens on each rank -> ~130.8 GB,
# 91% utilisation. That is close enough that fragmentation could still OOM, so
# PHASE 1 is a 3-step probe and the full run only starts if it survives.
# =============================================================================
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
EXE=./build/bluscriptCP_exec
CK=checkpoints_bluscriptcp/rank_0
LOG=ext32k_logs; mkdir -p "$LOG"
M="$LOG/master.log"
say(){ echo "[$(date -u +%H:%M:%S)] $*" | tee -a "$M" >&2; }
die(){ say "FATAL: $*"; exit 1; }
T=32768; NP=2; GPUS=0,1
ORIG=16384; SCALE=2 # 2 * 16384 == 32768 exactly
STEPS=${STEPS:-750}
STABLE=${STABLE:-$(( STEPS - 200 ))} # WSD: flat LR, minimal legal decay tail
FREQ=${FREQ:-50}
KEEP=${KEEP:-1} # disk is tight on this box (~45 GB free)
DATA=lendata/b4_32768_65536
PARENT="$CK/lenbucket_l2_blumodelcp_run2_step_400.ckpt"
HAY="$PWD/lendata/haystack/b2val_haystack.bin"
ARCH="CP_N_EMBD=1536 CP_N_LAYER=36 CP_N_HEAD=12 CP_N_KVHEAD=4 CP_FFN=4096 CP_WEIGHT_TYING=0"
$PY -c "import tiktoken" 2>/dev/null || die "tiktoken missing"
[ -x "$EXE" ] || die "$EXE not built"
[ -f "$PARENT" ] || die "parent l2 missing: $PARENT"
[ -f "$HAY" ] || die "haystack missing"
[ -d "$DATA" ] || die "$DATA missing"
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 >=1 train and >=1 val shard in $DATA (have $ntr/$nva)"
have=$(( $(du -cb "$DATA"/*train*.bin | tail -1 | cut -f1) / 2 ))
need=$(( STEPS*524288 ))
say "=== 16k -> 32k YaRN extension on b4 ==="
say "$ntr train shards = $(echo "scale=3; $have/1000000000" | bc) B tokens; need $(echo "scale=3; $need/1000000000" | bc) B for $STEPS steps"
[ "$have" -lt "$need" ] && say "WARNING: data repeats $(echo "scale=2; $need/$have" | bc)x"
say "YaRN: SCALE=$SCALE ORIG_MAXPOS=$ORIG -> $((SCALE*ORIG)) (must equal CP_T=$T)"
[ $((SCALE*ORIG)) -eq $T ] || die "YaRN invariant violated"
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_MAX_LR=1e-3 CP_MIN_LR=1e-4 CP_WARMUP=100 CP_REWARMUP=100 CP_REWARMUP_PEAK=0.3"
# ---- PHASE 1: does 32k fit at cp=2 on 143 GB? -----------------------------
if [ ! -f "$LOG/probe.ok" ]; then
say "PHASE 1: 3-step memory probe (projected 130.8 GB of 143 GB = 91%)"
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 -- 32k does not fit at cp=2 on this box."
say " 32k needs cp=4 (67.5 GB/GPU). Options: a 4-GPU box, or stop here."
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" | tail -1 | sed 's/^/ /' >&2
say "PROBE OK: peak $(grep -aoE 'mem: [0-9]+MB' "$LOG/probe.log" | tail -1)"
touch "$LOG/probe.ok"
fi
# ---- PHASE 2: the extension ------------------------------------------------
if [ -f "$LOG/ext.ckpt" ] && [ -f "$(cat "$LOG/ext.ckpt")" ]; then
say "extension already trained -> $(cat "$LOG/ext.ckpt")"
else
say "PHASE 2: $STEPS steps, stable=$STABLE, ckpt every $FREQ keep $KEEP"
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=524288 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 during 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"
echo "$CKF" > "$LOG/ext.ckpt"
say "ext32k -> 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)"
fi
# ---- PHASE 3: evaluate, including the new 32k point ------------------------
EXT=$(basename "$(cat "$LOG/ext.ckpt")")
EXTRA="ext32k=$EXT"
[ -f "$CK/lenbucket_l2_blumodelcp_run2_step_400.ckpt" ] && \
EXTRA="$EXTRA l2=lenbucket_l2_blumodelcp_run2_step_400.ckpt"
MODELS=$(echo $EXTRA | tr ' ' '\n' | cut -d= -f1 | tr '\n' ' ')
say "PHASE 3: eval models $MODELS"
# 32744 + MAX_NEW 24 = 32768 exactly; 32760 would pad to 33024 and abort.
for LEN in 4096 8192 16360 32744; do
say "eval PROMPT_LEN=$LEN"
GEN_DATA_ROOT=$DATA HAY="$HAY" PY=$PY OUT=ext32k_len_$LEN TASKS="niah_single" \
CKPTS="$MODELS" 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=0,1 JOBS_PER_GPU=1 BF16=1 GREEDY=1 \
CKPT_EXTRA="$EXTRA" ./run_longeval.sh >> "$LOG/eval_$LEN.log" 2>&1 \
|| say " WARN nonzero at $LEN"
[ -s "ext32k_len_$LEN/summary.csv" ] && say " -> $(sed -n 1p ext32k_len_$LEN/summary.csv) / $(sed -n 2p ext32k_len_$LEN/summary.csv)"
done
say "=== EXT32K DONE ==="
|