Download code/sbatch_gateq.sh from Avra98/Sudoku_superposition: direct link, hf CLI and curl.
- Browser
- Download file 11.5 kB
-
https://huggingface.co/Avra98/Sudoku_superposition/resolve/main/code/sbatch_gateq.sh
- Command line
-
hf download hf://Avra98/Sudoku_superposition/code/sbatch_gateq.sh
-
curl -L -o sbatch_gateq.sh https://huggingface.co/Avra98/Sudoku_superposition/resolve/main/code/sbatch_gateq.sh
11.5 kB
| #SBATCH --partition=songmei | |
| #SBATCH --nodelist=feanor | |
| #SBATCH --gres=gpu:2 | |
| #SBATCH --cpus-per-task=16 | |
| #SBATCH --mem=96G | |
| #SBATCH --time=72:00:00 | |
| #SBATCH --requeue | |
| #SBATCH --job-name=w12_gateq | |
| #SBATCH --output=/scratch/users/gatmiry/llm-reasoning-logic-puzzles/sudoku-code/wavecurriculum_ceq/logs/slurm_%x_%j.out | |
| #SBATCH --error=/scratch/users/gatmiry/llm-reasoning-logic-puzzles/sudoku-code/wavecurriculum_ceq/logs/slurm_%x_%j.err | |
| # Walk stages 4..12 from the verified stage-4 checkpoint, on a CE(q||p) gate | |
| # that is finally measured correctly. Same criterion as sbatch_ceq_multigpu.sh; | |
| # three bugs in how it was READ are fixed, and every one of them was inflating | |
| # the statistic, which is why every stage past 4 stalled. | |
| # | |
| # prefix data.py rewrote value tokens with an instance only when train=True, | |
| # so eval scored p on a solution-valued sequence: every earlier empty | |
| # cell handed the model the true digit, the current cell fell out by | |
| # elimination, and the gate then charged that against a q which | |
| # conditions on nothing of the sort. Instance-valued sequences now | |
| # come through the batch and p is averaged over SUDOKU_EVAL_READS of | |
| # them, which is both what training feeds and a marginal comparable | |
| # to q. Worth ~0.07 nats of the stage-4 hinge. | |
| # depth evaluater.py pinned k_budget = K, so one full-depth prediction was | |
| # compared against every stage's q. The gate pass now activates | |
| # exactly `stage` slots and rebuilds the latents at that depth. | |
| # q the stored pool stops at coverage (`while uncovered`, plus | |
| # require_new dropping redundant draws), so it is ~5 grids per puzzle | |
| # -- 1.4 by stage 11 -- and it deliberately spends those draws on | |
| # rare candidates, which flattens the histogram. That is fatal for a | |
| # gate whose headroom is log|S| - H(q): re-sampling the same | |
| # generator 200x per cell moves q(true) from 0.40 to 0.63 at stage 4 | |
| # and H(q) from 0.96 to 0.50, i.e. real headroom 0.60 nats, not 0.15. | |
| # SUDOKU_GATE_Q points at gen_bigq.py output and the eval split is | |
| # restricted to the puzzles it covers. | |
| # | |
| # Measured on the stage-4..11 checkpoints of the ungated w12_full12 run, the | |
| # hinge goes from 0.07-0.46 (fail everywhere) to 0.000-0.002 (pass everywhere). | |
| # Verified in the training loop itself: stage 4 reads hinge 0.0026 against a | |
| # 0.05 bar and promotes. | |
| # | |
| # Submit with: | |
| # sbatch --gres=gpu:2 --job-name=w12_gateq \ | |
| # --export=ALL,CEQ_TAG=w12_gateq sbatch_gateq.sh | |
| set -u | |
| hostname | |
| nvidia-smi -L | |
| echo "[$(date)] ${CEQ_TAG:-w12_gateq} starting" | |
| TAG="${CEQ_TAG:-w12_gateq}" | |
| SCRATCH_ROOT=/scratch/users/gatmiry/llm-reasoning-logic-puzzles | |
| RUN_DIR=${SCRATCH_ROOT}/sudoku-code/wavecurriculum_ceq | |
| ENV_LOCAL=/tmp/logicpuzzles | |
| CAND_DIR=/tmp/sudoku_s12 | |
| INST_DIR=/tmp/sudoku_superposition | |
| LOCAL_LOG=/tmp/sudoku_wave_runs/${TAG} | |
| WARM_DIR=/tmp/sudoku_warmstart_${TAG} | |
| # The stage-4 checkpoint this run starts from, tarred up from the diagonal | |
| # probe so the run begins at exactly the weights the gate was verified on. | |
| S4_TAR=${RUN_DIR}/d4_ckpt.tgz | |
| LOGIN_STAGE=gandalf.berkeley.edu:/tmp/sudoku_hf_${TAG} | |
| mkdir -p "${RUN_DIR}/logs" "${LOCAL_LOG}" "${LOCAL_LOG}/_hf_tars" "${WARM_DIR}" | |
| echo "[$(date)] /tmp free:" | |
| df -h /tmp | tail -1 | |
| SCP_OPTS="-o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new" | |
| [ -f "${HOME}/.ssh/id_ed25519_berkeley" ] && SCP_OPTS="${SCP_OPTS} -i ${HOME}/.ssh/id_ed25519_berkeley" | |
| if XLA_PYTHON_CLIENT_PREALLOCATE=false ${ENV_LOCAL}/bin/python -u -c \ | |
| "import jax; assert jax.default_backend()=='gpu'" 2>/dev/null; then | |
| echo "[$(date)] reusing ${ENV_LOCAL}" | |
| else | |
| echo "ERROR: ${ENV_LOCAL} missing or not GPU-capable" >&2 | |
| exit 1 | |
| fi | |
| export PY=${ENV_LOCAL}/bin/python | |
| export LD_LIBRARY_PATH=\ | |
| ${ENV_LOCAL}/lib/python3.9/site-packages/nvidia/cudnn/lib:\ | |
| ${ENV_LOCAL}/lib/python3.9/site-packages/nvidia/cublas/lib:\ | |
| ${ENV_LOCAL}/lib/python3.9/site-packages/nvidia/cuda_runtime/lib:\ | |
| ${ENV_LOCAL}/lib/python3.9/site-packages/nvidia/cuda_nvrtc/lib:\ | |
| ${ENV_LOCAL}/lib/python3.9/site-packages/nvidia/nccl/lib:\ | |
| ${LD_LIBRARY_PATH:-} | |
| NDEV=$(XLA_PYTHON_CLIENT_PREALLOCATE=false ${PY} -u -c \ | |
| "import jax; print(jax.local_device_count())") | |
| export SUDOKU_MINIBATCH="${SUDOKU_MINIBATCH:-64}" | |
| if [ -z "${NDEV}" ] || [ "${NDEV}" -lt 1 ]; then | |
| echo "ERROR: could not determine device count" >&2 | |
| exit 1 | |
| fi | |
| if [ $(( SUDOKU_MINIBATCH % NDEV )) -ne 0 ]; then | |
| echo "ERROR: minibatch ${SUDOKU_MINIBATCH} not divisible by ${NDEV} devices" >&2 | |
| exit 1 | |
| fi | |
| echo "[$(date)] ${NDEV} GPU(s), global batch ${SUDOKU_MINIBATCH}" | |
| for f in train_assignments.npy train_starts.npy train_counts.npy \ | |
| test_assignments.npy test_starts.npy test_counts.npy; do | |
| [ -s "${INST_DIR}/${f}" ] || { echo "missing ${INST_DIR}/${f}" >&2; exit 1; } | |
| done | |
| for f in train_cand_masks.npy test_cand_masks.npy; do | |
| [ -s "${CAND_DIR}/${f}" ] || { echo "missing ${CAND_DIR}/${f}" >&2; exit 1; } | |
| done | |
| [ -s "${RUN_DIR}/test_bigq300.npz" ] || { | |
| echo "ERROR: missing ${RUN_DIR}/test_bigq300.npz (gen_bigq.py output)" >&2 | |
| exit 1; } | |
| # ---- Resume, in priority order ---------------------------------------------- | |
| # 1. this job's own node-local workdir (survives a requeue onto the same node) | |
| # 2. the rolling latest.tar staged on the login node | |
| # 3. the stage-4 checkpoint tarball (genuine cold start only) | |
| CKPT_LOC="" | |
| FRESH=1 | |
| if ls -1d "${LOCAL_LOG}"/checkpoint_* >/dev/null 2>&1; then | |
| CKPT_LOC="${LOCAL_LOG}" | |
| FRESH=0 | |
| echo "[$(date)] resuming in place from step $(ls -1d ${LOCAL_LOG}/checkpoint_* | grep -v orbax-checkpoint-tmp | sed 's/.*checkpoint_//' | sort -n | tail -1)" | |
| elif scp ${SCP_OPTS} "${LOGIN_STAGE}/latest.tar" "${WARM_DIR}/latest.tar" 2>/dev/null \ | |
| && tar -C "${WARM_DIR}" -xf "${WARM_DIR}/latest.tar"; then | |
| rm -f "${WARM_DIR}/latest.tar" | |
| CKPT_LOC="${WARM_DIR}" | |
| FRESH=0 | |
| echo "[$(date)] resuming from staged step $(ls -1d ${WARM_DIR}/checkpoint_* | sed 's/.*checkpoint_//' | sort -n | tail -1)" | |
| elif [ "${CEQ_SCRATCH:-0}" = "1" ]; then | |
| # The data-curriculum baseline cannot inherit d4_ckpt.tgz: those weights were | |
| # trained with a depth ladder, which is the thing the baseline removes. | |
| CKPT_LOC="${WARM_DIR}" | |
| echo "[$(date)] random init (CEQ_SCRATCH=1)" | |
| else | |
| [ -s "${S4_TAR}" ] || { echo "ERROR: no ${S4_TAR}" >&2; exit 1; } | |
| rm -rf "${WARM_DIR:?}"/checkpoint_* | |
| tar -C "${WARM_DIR}" -xzf "${S4_TAR}" || { echo "ERROR: bad ${S4_TAR}" >&2; exit 1; } | |
| CKPT_LOC="${WARM_DIR}" | |
| echo "[$(date)] cold start from stage-4 checkpoint $(ls -1d ${WARM_DIR}/checkpoint_* | sed 's/.*checkpoint_//' | sort -n | tail -1)" | |
| fi | |
| du -sh "${CKPT_LOC}" 2>/dev/null || true | |
| export SUDOKU_RESUME=1 | |
| BASE_STAGE="${CEQ_START_STAGE:-4}" | |
| CEQ_LOG_PROBE="${RUN_DIR}/logs/${TAG}.log" | |
| if [ "${FRESH}" = "0" ] && [ -f "${CEQ_LOG_PROBE}" ]; then | |
| RECOVER_STAGE=$(grep -oE "promote to stage [0-9]+" "${CEQ_LOG_PROBE}" \ | |
| | grep -oE "[0-9]+$" | sort -n | tail -1) | |
| if [ -n "${RECOVER_STAGE}" ] && [ "${RECOVER_STAGE}" -gt "${BASE_STAGE}" ]; then | |
| echo "[$(date)] recovered curriculum stage ${RECOVER_STAGE} from log (base ${BASE_STAGE})" | |
| BASE_STAGE="${RECOVER_STAGE}" | |
| fi | |
| fi | |
| export SUDOKU_START_STAGE="${BASE_STAGE}" | |
| export SUDOKU_MAX_STAGE=12 | |
| export SUDOKU_LATENT_SLOTS=12 | |
| export SUDOKU_RECURRENT=1 | |
| export SUDOKU_CAND_SLOT_MODE=depth | |
| # num_passes = min(pps*stage, K). pps=1 is the latent curriculum: stage t reads | |
| # out of slot t. pps=K pins every stage at full depth, so the stage only selects | |
| # the data and there is a single readout -- the data-curriculum baseline. | |
| export SUDOKU_PASSES_PER_STAGE="${CEQ_PPS:-1}" | |
| export SUDOKU_AUX_WEIGHT=0.0 | |
| export SUDOKU_LEVEL_BALANCED=0 | |
| export SUDOKU_DATA_CURRICULUM=none | |
| export SUDOKU_BACKTRACK="${CEQ_BACKTRACK:-0}" | |
| export SUDOKU_BACKTRACK_MODE=adaptive | |
| export SUDOKU_BACKTRACK_MARGIN=0.02 | |
| export SUDOKU_INSTANCE_EPOCHS=5 | |
| export SUDOKU_INSTANCE_PUZZLES="${CEQ_PUZZLES:-100000}" | |
| export SUDOKU_MIN_STAGE_STEPS="${CEQ_MIN_STAGE_STEPS:-50000}" | |
| # ---- The gate ---- | |
| export SUDOKU_PROMOTE_CEQ=0.90 | |
| export SUDOKU_PROMOTE_CEQ_MODE="${CEQ_MODE:-hinge}" | |
| export SUDOKU_PROMOTE_CEQ_MARGIN=0.0 | |
| export SUDOKU_PROMOTE_HINGE="${CEQ_HINGE:-0.0}" | |
| export SUDOKU_PROMOTE_HINGE_SLACK="${CEQ_HINGE_SLACK:-0.05}" | |
| # Large-sample q, and the instance prefixes p is averaged over. These two are | |
| # the whole point of this script; without them the gate reads 20-200x too high. | |
| export SUDOKU_GATE_Q="${RUN_DIR}/test_bigq300.npz" | |
| export SUDOKU_EVAL_READS="${CEQ_EVAL_READS:-4}" | |
| export SUDOKU_PROMOTE_ACC=0.95 | |
| export SUDOKU_PROMOTE_SPREAD=0.88 | |
| export SUDOKU_PROMOTE_HBOUND=0.0 | |
| export SUDOKU_PROMOTE_LOC_WAVE=0.0 | |
| export SUDOKU_PLATEAU_STEPS=0 | |
| export SUDOKU_PATIENCE=0 | |
| export SUDOKU_MAX_STEPS="${CEQ_MAX_STEPS:-2000000}" | |
| export SUDOKU_EVAL_EVERY="${CEQ_EVAL_EVERY:-2000}" | |
| export SUDOKU_SAVE_EVERY=10000 | |
| export SUDOKU_CKPT_KEEP=2 | |
| export SUDOKU_LR="${CEQ_LR:-0.0002}" | |
| export SUDOKU_DROPOUT="${CEQ_DROPOUT:-0.2}" | |
| export SUDOKU_WD="${CEQ_WD:-0.005}" | |
| export SUDOKU_LOC_WEIGHT="${CEQ_LOC_WEIGHT:-1.0}" | |
| export SUDOKU_VALUE_WEIGHT="${CEQ_VALUE_WEIGHT:-1.0}" | |
| export SUDOKU_LEAK_WEIGHT="${CEQ_LEAK_WEIGHT:-0.0}" | |
| export SUDOKU_TRAIN_PATH="${SCRATCH_ROOT}/sudoku-code/datasets/train_sudoku_puzzles.npy" | |
| export SUDOKU_TEST_PATH="${SCRATCH_ROOT}/sudoku-code/datasets/test_sudoku_puzzles.npy" | |
| export SUDOKU_TRAIN_CAND="${CAND_DIR}/train_cand_masks.npy" | |
| export SUDOKU_TEST_CAND="${CAND_DIR}/test_cand_masks.npy" | |
| export SUDOKU_INSTANCE_DIR="${INST_DIR}" | |
| export XLA_PYTHON_CLIENT_MEM_FRACTION="${CEQ_MEM_FRAC:-0.8}" | |
| HF_TOKEN_FILE="${HF_TOKEN_FILE:-/scratch/users/gatmiry/.hf_token}" | |
| if [ -z "${HF_TOKEN:-}" ] && [ -s "${HF_TOKEN_FILE}" ]; then | |
| HF_TOKEN="$(cat "${HF_TOKEN_FILE}")" | |
| export HF_TOKEN | |
| fi | |
| export HUGGING_FACE_HUB_TOKEN="${HF_TOKEN:-}" | |
| HF_PKGS="${HF_PKGS:-/scratch/users/gatmiry/hf_pkgs}" | |
| TRAIN_LOG="${RUN_DIR}/logs/${TAG}.log" | |
| SYNC_LOG="${RUN_DIR}/logs/hf_sync_${TAG}.log" | |
| tmp_avail_kb=$(df -Pk /tmp | awk 'NR==2{print $4}') | |
| echo "[$(date)] /tmp avail ${tmp_avail_kb} KB" | |
| if [ "${tmp_avail_kb}" -lt 3000000 ]; then | |
| echo "ERROR: /tmp has less than 3G free; refusing to start" >&2 | |
| exit 1 | |
| fi | |
| cd "${RUN_DIR}" | |
| PYTHONPATH="${HF_PKGS}${PYTHONPATH:+:${PYTHONPATH}}" ${PY} -u "${RUN_DIR}/hf_sync.py" \ | |
| --workdir "${LOCAL_LOG}" \ | |
| --log "${TRAIN_LOG}" \ | |
| --scratch-log "${TRAIN_LOG}" \ | |
| --repo Avra98/Sudoku_superposition \ | |
| --prefix runs/${TAG} \ | |
| --login-stage "${LOGIN_STAGE}" \ | |
| --token-file "${HF_TOKEN_FILE}" \ | |
| --interval 60 \ | |
| > "${SYNC_LOG}" 2>&1 & | |
| SYNC_PID=$! | |
| echo "[$(date)] starting ${TAG}" | |
| echo " stages ${SUDOKU_START_STAGE}..12, ${NDEV} GPU(s), min ${SUDOKU_MIN_STAGE_STEPS} steps/stage" | |
| echo " gate: per-puzzle hinge V <= hinge_floor + ${SUDOKU_PROMOTE_HINGE_SLACK}" | |
| echo " gate q: ${SUDOKU_GATE_Q} (large-sample), ${SUDOKU_EVAL_READS} instance prefixes" | |
| echo " hf=Avra98/Sudoku_superposition/runs/${TAG}" | |
| ${PY} -u -m train.main \ | |
| --workdir="${LOCAL_LOG}" --exp_name="${TAG}" \ | |
| --ckpt_loc="${CKPT_LOC}" \ | |
| >> "${TRAIN_LOG}" 2>&1 | |
| EC=$? | |
| kill ${SYNC_PID} 2>/dev/null || true | |
| wait ${SYNC_PID} 2>/dev/null || true | |
| PYTHONPATH="${HF_PKGS}${PYTHONPATH:+:${PYTHONPATH}}" ${PY} -u "${RUN_DIR}/hf_sync.py" --once \ | |
| --workdir "${LOCAL_LOG}" \ | |
| --log "${TRAIN_LOG}" \ | |
| --scratch-log "${TRAIN_LOG}" \ | |
| --repo Avra98/Sudoku_superposition \ | |
| --prefix runs/${TAG} \ | |
| --login-stage "${LOGIN_STAGE}" \ | |
| --token-file "${HF_TOKEN_FILE}" \ | |
| >> "${SYNC_LOG}" 2>&1 || true | |
| echo "[$(date)] ${TAG} exit ${EC}" | |
| exit ${EC} | |