Download scripts/cont64k_b5_h100.sh from unparallelled/BluScriptCP: direct link, hf CLI and curl.
- Browser
- Download file 14.8 kB
-
https://huggingface.co/unparallelled/BluScriptCP/resolve/main/scripts/cont64k_b5_h100.sh
- Command line
-
hf download hf://unparallelled/BluScriptCP/scripts/cont64k_b5_h100.sh
-
curl -L -o cont64k_b5_h100.sh https://huggingface.co/unparallelled/BluScriptCP/resolve/main/scripts/cont64k_b5_h100.sh
14.8 kB
| # ============================================================================= | |
| # CONTINUE the 64k b5 extension on 8x H100 -- to a FULL b5 epoch. | |
| # | |
| # PARENT: ext64k run3 step 695 (the 64k model: 67/65/52/29 at 8k/16k/32k/64k). | |
| # Recovered from strong-room-grows-fin-03 and now durable on HF at | |
| # checkpoints/ext64k_b5_rank0_step_695.ckpt (byte-verified). | |
| # | |
| # WHY cp=8 AND NOT cp=4: at 64k, cp=4 puts 16,384 tokens on each rank, which | |
| # MEASURED 108,493 MB on the H200 run. An H100 has 81,559 MiB. It does not | |
| # fit. cp=8 halves that to 8,192 tok/rank. There is no other lever: CP_B is | |
| # already 1 and bluscriptCP.cpp has no activation-recompute flag. | |
| # | |
| # WHY CP_INIT_FROM (weights only) AND NOT CP_CKPT_RESUME: ZeRO-1 shards | |
| # optimizer state across the GLOBAL process group (bluscriptCP.cpp:24-28), so | |
| # a sidecar written at world_size=4 cannot load at world_size=8 -- | |
| # ShardedOptimizer::load_state throws ZeroCheckpointError("cross-world-size | |
| # resume not supported"). Weights-only is what every prior stage in this | |
| # project used across a topology change, including the 64k run itself. | |
| # TWO CONSEQUENCES, both deliberate: | |
| # 1. the data loader restarts at token 0, so the first 42% of b5 is seen a | |
| # second time and the remaining 58% for the first time -- a full pass; | |
| # 2. Adam m/v reset, which CP_REWARMUP (100 steps to 1.8e-4) absorbs. | |
| # | |
| # WHY THE FULL EPOCH IS ONLY NOW POSSIBLE: yesterday's box had 5 b5 train | |
| # shards (0.481 B tokens). All 9 are here now = 0.866 B = a real epoch. | |
| # | |
| # TAIL=100, NOT 2: yesterday's 2-step tail left the final LR at 1.2e-4, not the | |
| # ~6e-5 floor -- the checkpoint was labelled decayed but effectively was not. | |
| # | |
| # UPLOAD IS VERIFIED BY BYTE SIZE. Yesterday's up() helper was | |
| # `[ -e "$1" ] || return 0`, which silently SUCCEEDS when the source is | |
| # missing. That is how the step-695 checkpoint was lost: the CLI never | |
| # errored, the log said nothing, and 17 GB never left the box. | |
| # ============================================================================= | |
| 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 | |
| export PATH=/usr/local/cuda/bin:$PATH | |
| PY=/root/gv/envv/bin/python3 # this box's venv (NOT /root/envv) | |
| HF=/root/gv/envv/bin/hf | |
| EXE=./build/bluscriptCP_exec | |
| CK=checkpoints_bluscriptcp/rank_0 | |
| LOG=cont64k_logs; mkdir -p "$LOG" | |
| M="$LOG/master.log" | |
| REPO=unparallelled/BluScriptCP | |
| T=65536; NP=8; GPUS=0,1,2,3,4,5,6,7 | |
| ORIG=32768; SCALE=2 # 2 * 32768 == 65536, the parent's own cache | |
| DATA=Data_Loader/Data/b5_65536_131072 | |
| PARENT="$CK/blumodelcp_run3_step_695.ckpt" | |
| HAY="$PWD/Data_Loader/Data/b2_8192_16384/val_shard_00000.bin" | |
| WARM=100; TAIL=${TAIL:-100}; FREQ=${FREQ:-100}; KEEP=2 | |
| GB=524288 | |
| say(){ echo "[$(date -u +%H:%M:%S)] $*" | tee -a "$M" >&2; } | |
| die(){ say "FATAL: $*"; exit 1; } | |
| # ---- preflight ------------------------------------------------------------- | |
| $PY -c "import tiktoken" 2>/dev/null || die "tiktoken missing (eval would silently score nothing)" | |
| [ -x "$EXE" ] || die "$EXE not built" | |
| # CP_ATTN_FUSION=split needs BOTH kernel families compiled in: CP_FUSED_ROPE | |
| # (Stage 2 QK-norm+RoPE) and CP_ATTN_SPLIT (Stage 3 causal attention). Without | |
| # them SplitAttnSDPA_cp.h compiles to stubs that THROW at the first forward -- | |
| # a default `make` produced exactly that and the run died 73 s in. The Makefile | |
| # records the flag state in this stamp; refuse to start if it is not right. | |
| STAMP=build/objects/.cp_rope_flags | |
| [ -f "$STAMP" ] || die "no build-flag stamp: rebuild with make CP_FUSED_ROPE=1 CP_ATTN_SPLIT=1 SM_ARCH=90 bluscript-cp" | |
| grep -q 'CP_FUSED_ROPE=1' "$STAMP" && grep -q 'CP_ATTN_SPLIT=1' "$STAMP" || \ | |
| die "binary built WITHOUT the split kernels ($(cat "$STAMP")). Rebuild: make CP_FUSED_ROPE=1 CP_ATTN_SPLIT=1 SM_ARCH=90 bluscript-cp -j\$(nproc)" | |
| [ "$EXE" -nt "$STAMP" ] || say "WARN: $EXE is older than the flag stamp -- rebuild if unsure" | |
| [ -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" | |
| PSZ=$(stat -c%s "$PARENT") | |
| [ "$PSZ" = "5225752094" ] || die "parent wrong size: $PSZ (want 5225752094)" | |
| 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 )) | |
| FREEG=$(df -BG --output=avail / | tail -1 | tr -dc 0-9) | |
| [ "$FREEG" -ge 100 ] || die "only ${FREEG} GB free; 8-rank checkpoints need ~90 GB" | |
| say "=== CONTINUE 64k b5 to a FULL EPOCH (8x H100, cp=$NP) ===" | |
| say "parent: ext64k run3 step 695 (64k model), weights-only via CP_INIT_FROM" | |
| 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 on disk" | |
| say "disk: ${FREEG} GB free" | |
| 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: probe -- does 64k fit in 80 GB at cp=8? ---------------------- | |
| if [ ! -f "$LOG/probe.ok" ]; then | |
| say "PHASE 1: 3-step probe (8,192 tok/rank; extrapolates to ~67 GB of 81.5 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=$T CP_MAX_STEPS=3 \ | |
| CUDA_VISIBLE_DEVICES=$GPUS mpirun --allow-run-as-root -np $NP "$EXE" \ | |
| > "$LOG/probe.log" 2>&1 | |
| RC=$? | |
| # The probe must PROVE it trained, not merely fail to say "OOM". The first | |
| # version of this gate only grepped for OOM, so a probe that aborted on every | |
| # rank with `sdpa_split_rope_once_forward: build with -DCP_FUSED_ROPE` was | |
| # declared "PROBE OK" and the real run then died 73 s in. Three independent | |
| # checks now, and the peak-memory parse is one of them: an empty peak means | |
| # no step ever completed. | |
| if grep -qaiE 'out of memory|bad_alloc' "$LOG/probe.log"; then | |
| say "PROBE OOM -- 64k does NOT fit at cp=8 on 80 GB cards." | |
| say " There is no further lever on 8 GPUs: CP_B is 1 and there is no recompute flag." | |
| grep -aoE 'cudaMallocAsync\(size=[0-9]+\) failed' "$LOG/probe.log" | head -2 | sed 's/^/ /' >&2 | |
| exit 1 | |
| fi | |
| if grep -qaE 'terminate called|std::runtime_error|Signal: Aborted' "$LOG/probe.log"; then | |
| say "PROBE CRASHED (not OOM). First error:" | |
| grep -aA1 'terminate called' "$LOG/probe.log" | grep -a 'what()' | head -1 | sed 's/^/ /' >&2 | |
| exit 1 | |
| fi | |
| NSTEP=$(grep -acE '^step +[0-9]+ \|' "$LOG/probe.log") | |
| PEAK=$(grep -aoE 'mem: [0-9]+MB' "$LOG/probe.log" | tail -1) | |
| [ "$RC" -eq 0 ] || { say "PROBE exited $RC"; tail -15 "$LOG/probe.log" >&2; exit 1; } | |
| [ "$NSTEP" -ge 1 ] || { say "PROBE produced NO step lines"; tail -15 "$LOG/probe.log" >&2; exit 1; } | |
| [ -n "$PEAK" ] || { say "PROBE reported no peak memory"; tail -15 "$LOG/probe.log" >&2; exit 1; } | |
| grep -aE '^step +[0-9]+ \|' "$LOG/probe.log" | sed 's/^/ /' >&2 | |
| say "PROBE OK: $NSTEP steps, peak $PEAK of 81559 MiB/card" | |
| touch "$LOG/probe.ok" | |
| fi | |
| # ---- step count: a full epoch over what is on disk ------------------------- | |
| # The probe ran grad_accum=1. Its dt is NOT the per-step cost -- multiplying it | |
| # by grad_accum overstated the real rate 5.8x on the 64k run (74.0 vs 12.85 | |
| # s/step) because fixed per-step costs got multiplied too. Reported for | |
| # information only; the step count comes from the DATA, not the clock. | |
| 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)] | |
| if not d: print("0.0"); raise SystemExit | |
| probe_accum=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 "probe rate (UPPER BOUND, inflated by fixed costs x grad_accum): ${SPS} s/step" | |
| STEPS=${STEPS_OVERRIDE:-$(( have / GB ))} | |
| STABLE=$(( STEPS - WARM - TAIL )) | |
| [ "$STABLE" -lt 1 ] && STABLE=1 | |
| # bluscriptCP.cpp:1006 dies if warmup + stable >= max_steps - 1 | |
| [ $(( WARM + STABLE )) -lt $(( STEPS - 1 )) ] || die "illegal WSD: $WARM+$STABLE >= $STEPS-1" | |
| say "PHASE 2: $STEPS steps x $GB = $(echo "scale=3; $STEPS*$GB/1000000000" | bc) B tokens = a full b5 epoch" | |
| say " WSD: warmup $WARM, stable $STABLE, decay tail $TAIL -> final checkpoint IS decayed" | |
| if [ -f "$LOG/cont.ckpt" ] && [ -f "$(cat "$LOG/cont.ckpt")" ]; then | |
| say "already trained -> $(cat "$LOG/cont.ckpt")" | |
| else | |
| # Reclaim leaked .zero_g* sidecars while training runs: CP_CKPT_KEEP prunes | |
| # .ckpt but NOT the sidecars (that leak filled a 193 GB disk on 2026-09-09). | |
| ( while sleep 300; do | |
| for s in checkpoints_bluscriptcp/rank_*/*.zero_g*; do | |
| [ -e "$s" ] || continue | |
| base=${s%.zero_g*} | |
| [ -f "$base.ckpt" ] || rm -f "$s" | |
| done | |
| done ) & JANITOR=$! | |
| trap 'kill $JANITOR 2>/dev/null' EXIT | |
| 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/cont.log" 2>&1 | |
| kill $JANITOR 2>/dev/null; trap - EXIT | |
| grep -qaiE 'out of memory|bad_alloc' "$LOG/cont.log" && die "OOM in the full run" | |
| RN=$(grep -aoE 'CP_Training_log[0-9]+' "$LOG/cont.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/cont.ckpt"; echo "$RN" > "$LOG/runnum" | |
| say "cont64k -> run $RN, $(basename "$CKF"), $(grep -aE '^step ' "$LOG/cont.log" | tail -1 | grep -oE 'loss: [0-9.]+')" | |
| say " peak mem $(grep -aoE 'mem: [0-9]+MB' "$LOG/cont.log" | tail -1)" | |
| say " final lr $(grep -aE '^step ' "$LOG/cont.log" | tail -1 | grep -oE 'lr [0-9.e-]+') (want ~6e-05 = decayed)" | |
| fi | |
| # ---- PHASE 3: eval, 4 lengths in parallel ---------------------------------- | |
| EXT=$(basename "$(cat "$LOG/cont.ckpt")") | |
| say "PHASE 3: eval cont64k -- 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=cont64k_len_$LEN TASKS="niah_single" \ | |
| CKPTS="cont64k" 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="cont64k=$EXT" ./run_longeval.sh \ | |
| >> "$LOG/eval_$LEN.log" 2>&1 ) & | |
| done | |
| wait | |
| for LEN in 8192 16360 32744 65512; do | |
| [ -s "cont64k_len_$LEN/summary.csv" ] && say " len $LEN -> $(sed -n 2p cont64k_len_$LEN/summary.csv)" \ | |
| || say " len $LEN -> NO RESULT" | |
| done | |
| # ---- PHASE 4: upload, VERIFIED --------------------------------------------- | |
| say "PHASE 4: upload" | |
| { | |
| echo "# 64k b5 continuation to a full epoch -- $(date -u +%Y-%m-%d)" | |
| echo | |
| echo "Parent: ext64k run3 step 695 (67.0/65.0/52.0/29.0 at 8k/16k/32k/64k)," | |
| echo " loaded WEIGHTS-ONLY: ZeRO sidecars cannot cross world_size 4 -> 8." | |
| echo "Data: b5_65536_131072, $ntr shards = $(echo "scale=3; $have/1000000000" | bc) B tokens." | |
| echo "Train: $STEPS steps x $GB = $(echo "scale=3; $STEPS*$GB/1000000000" | bc) B tokens = a full b5 epoch." | |
| echo " The loader restarts at token 0, so b5's first 42% is seen a" | |
| echo " second time and the rest for the first time." | |
| echo " WSD warmup $WARM / stable $STABLE / decay tail $TAIL." | |
| echo " 8x H100, cp=$NP, 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 "cont64k_len_$LEN/summary.csv" 2>/dev/null | cut -d, -f2) | |
| printf "| %s | %s |\n" "$LEN" "${v:-n/a}" | |
| done | |
| echo | |
| echo "Parent for comparison: 67.0 / 65.0 / 52.0 / 29.0." | |
| } > "$LOG/RESULTS.md" | |
| # Upload, then CONFIRM the remote byte size. A missing source is a LOUD failure: | |
| # the silent `[ -e "$1" ] || return 0` in ext64k_b5.sh is what lost the step-695 | |
| # checkpoint -- the CLI never errored and nothing was logged. | |
| UPOK=1 | |
| up(){ # src dst | |
| local src=$1 dst=$2 | |
| if [ ! -e "$src" ]; then say " MISSING SOURCE (NOT UPLOADED): $src"; UPOK=0; return 1; fi | |
| if $HF upload "$REPO" "$src" "$dst" >>"$LOG/upload.log" 2>&1; then say " sent $dst" | |
| else say " UPLOAD FAILED $dst"; UPOK=0; return 1; fi | |
| } | |
| verify(){ # localfile remotepath | |
| $PY - "$REPO" "$1" "$2" <<'PYEOF' | |
| import sys,os | |
| from huggingface_hub import HfApi | |
| repo,loc,rem=sys.argv[1],sys.argv[2],sys.argv[3] | |
| want=os.path.getsize(loc) | |
| got={f.rfilename:(f.size or 0) for f in HfApi().repo_info(repo,files_metadata=True).siblings}.get(rem) | |
| print(f" {'VERIFIED' if got==want else 'MISMATCH/ABSENT'} {rem} local={want:,} remote={got}") | |
| sys.exit(0 if got==want else 1) | |
| PYEOF | |
| } | |
| up "$LOG/RESULTS.md" "docs/CONT64K_B5_RESULTS_$(date -u +%Y-%m-%d).md" | |
| for LEN in 8192 16360 32744 65512; do up "cont64k_len_$LEN" "logs/cont64k_len_$LEN/"; done | |
| up "$LOG" logs/cont64k/ | |
| up "$(basename "$0")" "scripts/$(basename "$0")" | |
| RN=$(cat "$LOG/runnum" 2>/dev/null) | |
| STEP=$(basename "$(cat "$LOG/cont.ckpt")" | grep -oE 'step_[0-9]+' | cut -d_ -f2) | |
| say "uploading the model itself (the part that was lost yesterday)" | |
| SRC="$CK/blumodelcp_run${RN}_step_${STEP}.ckpt" | |
| DST="checkpoints/cont64k_b5_rank0_step_${STEP}.ckpt" | |
| if up "$SRC" "$DST"; then verify "$SRC" "$DST" | tee -a "$M" || UPOK=0; fi | |
| for r in $(seq 0 $((NP-1))); do | |
| S="checkpoints_bluscriptcp/rank_$r/blumodelcp_run${RN}_step_${STEP}.zero_g1" | |
| D="checkpoints/cont64k_b5_rank${r}_step_${STEP}.zero_g1" | |
| if up "$S" "$D"; then verify "$S" "$D" | tee -a "$M" || UPOK=0; fi | |
| done | |
| [ "$UPOK" = 1 ] && say "=== CONT64K DONE -- all uploads verified, safe to tear down ===" \ | |
| || say "=== CONT64K DONE but UPLOADS INCOMPLETE -- DO NOT TEAR DOWN ===" | |