File size: 8,992 Bytes
63d61fb | 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 | #!/bin/sh
# Fractus x8 one-shot deploy: env -> assets -> smoke -> launch -> verify.
# Designed to run DETACHED on a fresh vast.ai 8x5090 pod (POSIX sh, no bashisms):
# tr -d '\r' < pod_deploy_x8.sh > /root/deploy.sh && nohup sh /root/deploy.sh > /root/deploy.log 2>&1 &
# Progress: tail -f /root/deploy.log (marker files /root/.st_* make re-runs cheap)
set -e
# prerequisite: HF token already written to /root/.hf_token (kept OUT of this file)
[ -s /root/.hf_token ] || { echo "ERROR: write HF token to /root/.hf_token first"; exit 1; }
chmod 600 /root/.hf_token
export HF_HUB_ENABLE_HF_TRANSFER=1
if [ ! -f /root/.st_env ]; then
echo "=== [1/5] pip: huggingface_hub + hf_transfer"
pip install -q -U huggingface_hub hf_transfer
touch /root/.st_env
fi
if [ ! -f /root/.st_torch ]; then
echo "=== [2/5] torch cu128 (sm_120 needs >=2.7) — several GB, be patient"
pip install -q -U torch --index-url https://download.pytorch.org/whl/cu128
python3 -c "import torch; assert torch.cuda.is_available(); print('torch', torch.__version__, torch.cuda.get_device_name(0))"
touch /root/.st_torch
fi
if [ ! -f /root/.st_assets ]; then
echo "=== [3/5] assets: code + manifests + 8 ckpts (~36GB) + 8 shards (~14GB)"
python3 - << 'PYEOF'
import os, json, re, shutil
from huggingface_hub import snapshot_download, hf_hub_download, HfApi
tok = open('/root/.hf_token').read().strip()
REPO, DREPO = 'thefinalboss/fractus-cte', 'thefinalboss/fractus-datasets'
api = HfApi(token=tok)
print('-- code', flush=True)
snapshot_download(REPO, repo_type='model', local_dir='/root/fractus-opt', token=tok,
allow_patterns=['fractus/*', 'scripts/*', 'tests/*', 'benchmarks/*',
'docs/*', 'README.md'])
print('-- manifests', flush=True)
for f in ('checkpoints/X6_MANIFEST.json', 'checkpoints/RESUME_MANIFEST_8GPU.json'):
p = hf_hub_download(REPO, f, repo_type='model', token=tok)
shutil.copy(p, '/root/' + os.path.basename(f))
x6 = json.load(open('/root/X6_MANIFEST.json'))['gpus']
r8 = json.load(open('/root/RESUME_MANIFEST_8GPU.json'))
print('-- checkpoints x8', flush=True)
os.makedirs('/root/ckpts', exist_ok=True)
offs = {}
for i in range(8):
key = f'gpu_{i}'
if i < 6 and key in x6 and x6[key].get('start_token') is not None:
src, offs[i] = f'checkpoints/x6run/', int(x6[key]['start_token'])
elif key in r8:
src, offs[i] = 'checkpoints/', int(r8[key]['start_token'])
elif str(i) in r8:
src, offs[i] = 'checkpoints/', int(r8[str(i)]['start_token'])
else:
raise RuntimeError(f'no offset for gpu {i}')
p = hf_hub_download(REPO, src + f'fractus_1b_gpu{i}.pt', repo_type='model', token=tok)
shutil.copy(p, f'/root/ckpts/fractus_1b_gpu{i}.pt')
print(' ckpt', i, 'resume_at', offs[i], flush=True)
print('-- shards x8', flush=True)
os.makedirs('/root/shards', exist_ok=True)
npys = [f.path for f in api.list_repo_tree(DREPO, repo_type='dataset', recursive=True)
if f.path.endswith('.npy')]
phase2 = [p for p in npys if 'phase2' in p.lower()] or npys
by_idx = {}
for p in phase2:
m = re.search(r'gpu[_\-]?(\d+)', os.path.basename(p))
if m is not None:
by_idx.setdefault(int(m.group(1)), p)
ordered = [by_idx.get(i) for i in range(8)]
if any(v is None for v in ordered):
ordered = sorted(phase2)[:8]
assert len(ordered) == 8, f'expected 8 shards, got {len(ordered)}'
shard_path = {}
for i, p in enumerate(ordered):
q = hf_hub_download(DREPO, p, repo_type='dataset', token=tok)
dst = f'/root/shards/shard_gpu{i}.npy'
if not os.path.exists(dst):
shutil.copy(q, dst)
shard_path[i] = dst
print(' shard', i, '<-', os.path.basename(p), flush=True)
json.dump({'offsets': {str(k): v for k, v in offs.items()},
'shards': {str(k): v for k, v in shard_path.items()}},
open('/root/assets.json', 'w'), indent=1)
# generate launch_x8.sh with literal values (no shell indirection)
L = ['#!/bin/sh', 'mkdir -p /root/logs /root/ckpts_run']
for i in range(8):
L.append(
f"CUDA_VISIBLE_DEVICES={i} GPU_ID={i} START_TOKEN={offs[i]} BATCH=__BATCH__ "
f"SEQ=128 CE_CHUNK=2048 FRACTUS_ATTN_IMPL=chunked BLOCK_CKPT=1 "
f"PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True "
f"CKPT_IN=/root/ckpts/fractus_1b_gpu{i}.pt "
f"CKPT_OUT=/root/ckpts_run/fractus_1b_gpu{i}.pt "
f"SHARD={shard_path[i]} "
f"python -u /root/fractus-opt/scripts/fast4gpu_boost_v2.py >> /root/logs/g{i}.log 2>&1 &")
open('/root/launch_x8.sh', 'w').write('\n'.join(L) + '\n')
sync = '''#!/usr/bin/env python3
"""Hourly HF safety-sync: parses token positions from logs, uploads ckpt_run
files (never while .tmp exists) + X8_MANIFEST.json."""
import re, json, time
from huggingface_hub import HfApi
tok = open('/root/.hf_token').read().strip()
api, REPO = HfApi(token=tok), 'thefinalboss/fractus-cte'
while True:
time.sleep(3600)
try:
man = {'status': 'x8_running', 'gpus': {}}
for i in range(8):
pos = None
try:
txt = open(f'/root/logs/g{i}.log').read()
for m in re.finditer(r'GPU \\d:\\s+([\\d,]+) tf=', txt):
pos = int(m.group(1).replace(',', ''))
except OSError:
pass
man['gpus'][f'gpu_{i}'] = {'start_token': pos}
ck, tmp = f'/root/ckpts_run/fractus_1b_gpu{i}.pt', f'/root/ckpts_run/fractus_1b_gpu{i}.pt.tmp'
if pos is not None and not os.path.exists(tmp):
api.upload_file(path_or_fileobj=ck,
path_in_repo=f'checkpoints/x8run/fractus_1b_gpu{i}.pt',
repo_id=REPO, repo_type='model',
commit_message='x8 hourly sync gpu%d @ %s' % (i, pos))
print('synced', i, pos, flush=True)
api.upload_file(path_or_fileobj=json.dumps(man, indent=1).encode(),
path_in_repo='checkpoints/X8_MANIFEST.json',
repo_id=REPO, repo_type='model',
commit_message='x8 manifest')
except Exception as e:
print('sync error (retry next hour):', e, flush=True)
'''
sync = sync.replace('import re, json, time', 'import re, json, time, os')
open('/root/sync_hf.py', 'w').write(sync)
smoke = '''#!/usr/bin/env python3
"""Real-shape throughput probe on GPU0: tick_chunk_train_ce under bf16 autocast."""
import os, sys, time
import torch
sys.path.insert(0, '/root/fractus-opt')
from fractus.continuous_engine import ContinuousThoughtEngine
B = int(os.environ.get('B', '8'))
CFG = dict(vocab_size=50257, d_model=1280, n_heads=20, d_head=64, n_levels=2,
n_oscillators=16, coupling_rank=8, n_experts=128, top_k=2,
expert_d_ff=2048, siren_rank=64, n_layers=16)
torch.manual_seed(0)
eng = ContinuousThoughtEngine(**CFG).cuda()
eng.reset_thought(batch_size=B)
opt = torch.optim.SGD(eng.parameters(), lr=7e-4, momentum=0.9)
toks = torch.randint(0, 50257, (B, 129), device='cuda')
chunk, target = toks[:, :-1], toks[:, 1:]
times = []
ok = True
for i in range(24):
try:
t0 = time.perf_counter()
with torch.autocast('cuda', dtype=torch.bfloat16):
ce, lb = eng.tick_chunk_train_ce(chunk, target, ce_chunk=2048, block_ckpt=True)
loss = ce + 0.02 * lb
opt.zero_grad(set_to_none=True)
loss.backward()
opt.step()
torch.cuda.synchronize()
if i >= 6:
times.append(time.perf_counter() - t0)
except torch.cuda.OutOfMemoryError:
ok = False
break
if not ok or len(times) < 3:
print(f'B={B} RESULT FAIL oom')
raise SystemExit(1)
med = sorted(times)[len(times) // 2]
mem = torch.cuda.max_memory_allocated() / 1e9
print(f'B={B} RESULT tok_s_per_gpu={B * 128 / med:.0f} peakVRAM={mem:.2f}GB')
'''
open('/root/gpu_smoke.py', 'w').write(smoke)
print(json.dumps(json.load(open('/root/assets.json')), indent=1), flush=True)
PYEOF
touch /root/.st_assets
fi
echo "=== [4/5] smoke GPU0: B=8 then B=4 fallback"
B_CHOSEN=""
for b in 8 4; do
if B=$b python3 /root/gpu_smoke.py | tee /tmp/smoke_b$b.txt | grep -q "RESULT"; then
B_CHOSEN=$b
grep "RESULT" /tmp/smoke_b$b.txt
break
else
echo "B=$b failed (see /tmp/smoke_b$b.txt)"
fi
done
[ -z "$B_CHOSEN" ] && { echo "NO_BATCH_WORKS"; exit 1; }
sed -i "s/BATCH=__BATCH__/BATCH=$B_CHOSEN/" /root/launch_x8.sh
echo "=== [5/5] LAUNCH x8 (B=$B_CHOSEN) + hourly HF sync"
rm -f /root/logs/g*.log
mkdir -p /root/logs
nohup sh /root/launch_x8.sh > /root/launch.log 2>&1 &
nohup python3 -u /root/sync_hf.py >> /root/logs/sync.log 2>&1 &
sleep 150
echo "--- processes:"; pgrep -fc 'fast4gpu_boost_v2' || true
echo "--- GPUs:"; nvidia-smi --query-gpu=index,utilization.gpu,memory.used --format=csv,noheader
for i in 0 1 2 3 4 5 6 7; do echo "g$i: $(grep -E 'boostv2|Error|error' /root/logs/g$i.log | tail -n 1)"; done
touch /root/.deploy_done
echo "=== DEPLOY_COMPLETE"
|