scripts
Browse files- qwen2.5-7b_c4_1B/scripts/bits_llm.py +108 -0
- qwen2.5-7b_c4_1B/scripts/bits_lm_traj.py +84 -0
- qwen2.5-7b_c4_1B/scripts/eval_ppl.py +67 -0
- qwen2.5-7b_c4_1B/scripts/eval_seed.sh +11 -0
- qwen2.5-7b_c4_1B/scripts/heldout_c4val_4000x512.pt +3 -0
- qwen2.5-7b_c4_1B/scripts/hf_arm.py +18 -0
- qwen2.5-7b_c4_1B/scripts/run_3seeds_1B.sh +15 -0
- qwen2.5-7b_c4_1B/scripts/to_bf16.py +11 -0
qwen2.5-7b_c4_1B/scripts/bits_llm.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Bits-for-LLM encoder (extended): token id -> fixed random n-bit code -> encoder -> hidden.
|
| 3 |
+
Backward compatible: defaults (enc_type='mlp', ffn_depth=2, out_scale=0) reproduce the
|
| 4 |
+
original 2-layer MLP exactly. New encoder-only tuning knobs for the 7B sweep:
|
| 5 |
+
- ffn_depth : number of Linear layers in the MLP (2 = original, 3 = deeper)
|
| 6 |
+
- out_scale : if >0, rescale the final projection so output std ~= out_scale (init-scale match)
|
| 7 |
+
- enc_type='tfenc' : small Transformer encoder over the bit-code (TF-Enc-H4-FFN512 replica)
|
| 8 |
+
"""
|
| 9 |
+
import torch, torch.nn as nn
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class BitsEmbedding(nn.Module):
|
| 13 |
+
def __init__(self, vocab, hidden, nbits=64, W=256, seed=0, dtype=torch.bfloat16,
|
| 14 |
+
enc_type='mlp', ffn_depth=2, out_scale=0.0):
|
| 15 |
+
super().__init__()
|
| 16 |
+
g = torch.Generator().manual_seed(seed)
|
| 17 |
+
# plain attribute (NOT a buffer) so FSDP never shards it
|
| 18 |
+
self._codes = torch.randint(0, 2, (vocab, nbits), generator=g).to(dtype)
|
| 19 |
+
self.vocab, self.hidden, self.nbits, self.W = vocab, hidden, nbits, W
|
| 20 |
+
self.enc_type, self.ffn_depth = enc_type, ffn_depth
|
| 21 |
+
self.padding_idx = None
|
| 22 |
+
if enc_type == 'tfenc':
|
| 23 |
+
self.tok_bits = 16
|
| 24 |
+
assert nbits % self.tok_bits == 0, "nbits must be divisible by 16 for tfenc"
|
| 25 |
+
self.seq = nbits // self.tok_bits
|
| 26 |
+
self.in_proj = nn.Linear(self.tok_bits, W)
|
| 27 |
+
self.pos = nn.Parameter(torch.zeros(self.seq, W))
|
| 28 |
+
layer = nn.TransformerEncoderLayer(d_model=W, nhead=4, dim_feedforward=512,
|
| 29 |
+
activation='gelu', batch_first=True, norm_first=True)
|
| 30 |
+
self.tfenc = nn.TransformerEncoder(layer, num_layers=2)
|
| 31 |
+
self.out_proj = nn.Linear(W, hidden)
|
| 32 |
+
self.to(dtype)
|
| 33 |
+
else: # mlp with ffn_depth linear layers (>=2)
|
| 34 |
+
layers = [nn.Linear(nbits, W), nn.GELU()]
|
| 35 |
+
for _ in range(max(0, ffn_depth - 2)):
|
| 36 |
+
layers += [nn.Linear(W, W), nn.GELU()]
|
| 37 |
+
layers += [nn.Linear(W, hidden)]
|
| 38 |
+
self.ffn = nn.Sequential(*layers).to(dtype)
|
| 39 |
+
if out_scale and out_scale > 0:
|
| 40 |
+
self._match_out_scale(out_scale)
|
| 41 |
+
|
| 42 |
+
def _final(self):
|
| 43 |
+
return self.out_proj if self.enc_type == 'tfenc' else self.ffn[-1]
|
| 44 |
+
|
| 45 |
+
def _match_out_scale(self, target_std):
|
| 46 |
+
# empirically rescale the final (linear) layer so the OUTPUT embedding std ~= target_std,
|
| 47 |
+
# matching the standard embedding's init scale (~initializer_range). Output is linear in
|
| 48 |
+
# the final layer for both mlp (ffn[-1]) and tfenc (out_proj), so scaling it scales output.
|
| 49 |
+
with torch.no_grad():
|
| 50 |
+
idx = torch.randint(0, self.vocab, (4096,))
|
| 51 |
+
cur = self.forward(idx).float().std().item()
|
| 52 |
+
if cur > 1e-8:
|
| 53 |
+
k = target_std / cur
|
| 54 |
+
last = self._final()
|
| 55 |
+
last.weight.mul_(k)
|
| 56 |
+
if last.bias is not None:
|
| 57 |
+
last.bias.mul_(k)
|
| 58 |
+
|
| 59 |
+
def forward(self, ids):
|
| 60 |
+
if self._codes.device != ids.device:
|
| 61 |
+
self._codes = self._codes.to(ids.device)
|
| 62 |
+
codes = self._codes[ids]
|
| 63 |
+
if self.enc_type == 'tfenc':
|
| 64 |
+
*lead, n = codes.shape
|
| 65 |
+
x = codes.reshape(-1, self.seq, self.tok_bits)
|
| 66 |
+
x = self.in_proj(x) + self.pos
|
| 67 |
+
x = self.tfenc(x).mean(dim=1)
|
| 68 |
+
return self.out_proj(x).reshape(*lead, self.hidden)
|
| 69 |
+
return self.ffn(codes)
|
| 70 |
+
|
| 71 |
+
def n_params(self):
|
| 72 |
+
return sum(p.numel() for p in self.parameters())
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
def swap_in_bits(model, nbits, W, seed, enc_type='mlp', ffn_depth=2, out_scale=0.0):
|
| 76 |
+
cfg = model.config
|
| 77 |
+
if getattr(cfg, "tie_word_embeddings", False):
|
| 78 |
+
out = model.get_output_embeddings()
|
| 79 |
+
if out is not None:
|
| 80 |
+
new = nn.Linear(out.weight.shape[1], out.weight.shape[0], bias=False)
|
| 81 |
+
new.weight = nn.Parameter(out.weight.detach().clone())
|
| 82 |
+
model.set_output_embeddings(new); cfg.tie_word_embeddings = False
|
| 83 |
+
dtype = next(model.parameters()).dtype
|
| 84 |
+
bits = BitsEmbedding(cfg.vocab_size, cfg.hidden_size, nbits, W, seed, dtype,
|
| 85 |
+
enc_type=enc_type, ffn_depth=ffn_depth, out_scale=out_scale)
|
| 86 |
+
dev = model.get_input_embeddings().weight.device
|
| 87 |
+
model.set_input_embeddings(bits.to(dev))
|
| 88 |
+
orig = cfg.vocab_size * cfg.hidden_size
|
| 89 |
+
print(f"[Bits enc={enc_type} depth={ffn_depth} W={W} nbits={nbits} scale={out_scale}] "
|
| 90 |
+
f"table {orig/1e9:.3f}B -> encoder {bits.n_params()/1e6:.2f}M "
|
| 91 |
+
f"= {orig/max(bits.n_params(),1):.0f}x compression", flush=True)
|
| 92 |
+
return bits
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def get_dataset(tokenizer, max_len, n_tokens, split_stream):
|
| 96 |
+
from datasets import load_dataset
|
| 97 |
+
ds = load_dataset("allenai/c4", "en", split=split_stream, streaming=True)
|
| 98 |
+
def gen():
|
| 99 |
+
buf = []
|
| 100 |
+
while True:
|
| 101 |
+
for ex in ds:
|
| 102 |
+
ids = tokenizer(ex["text"], add_special_tokens=False)["input_ids"]
|
| 103 |
+
buf.extend(ids + [tokenizer.eos_token_id])
|
| 104 |
+
while len(buf) >= max_len:
|
| 105 |
+
yield {"input_ids": buf[:max_len], "labels": buf[:max_len]}
|
| 106 |
+
buf = buf[max_len:]
|
| 107 |
+
from datasets import IterableDataset
|
| 108 |
+
return IterableDataset.from_generator(gen)
|
qwen2.5-7b_c4_1B/scripts/bits_lm_traj.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""EXACT original from-scratch recipe (bits_lm_scratch.py) + intermediate checkpoints every 100M
|
| 3 |
+
tokens, so we get the full 100M->500M trajectory for both arms. Training dynamics are identical to
|
| 4 |
+
the original (only checkpoint saving is added).
|
| 5 |
+
Camera-ready additions (2026-11-05): transformers 5 warmup_steps (= ceil(0.02*max_steps), what
|
| 6 |
+
warmup_ratio=0.02 computed before), multi-GPU token accounting via WORLD_SIZE, optional FSDP
|
| 7 |
+
sharding (same optimizer step, states sharded across ranks), keep all checkpoints."""
|
| 8 |
+
import argparse, sys, math, os, torch
|
| 9 |
+
sys.path.insert(0, '/root')
|
| 10 |
+
from bits_llm import swap_in_bits, get_dataset
|
| 11 |
+
from transformers import AutoTokenizer, AutoConfig, AutoModelForCausalLM, TrainingArguments, Trainer, TrainerCallback
|
| 12 |
+
import subprocess
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class Bf16Save(TrainerCallback):
|
| 16 |
+
"""Disk only: after each save, rewrite the fp32 safetensors of that checkpoint to bf16 in a detached
|
| 17 |
+
process (30G -> 15G per 7B checkpoint). Training dynamics untouched."""
|
| 18 |
+
def on_save(self, args, state, control, **kw):
|
| 19 |
+
if state.is_world_process_zero:
|
| 20 |
+
d = os.path.join(args.output_dir, f'checkpoint-{state.global_step}')
|
| 21 |
+
subprocess.Popen([sys.executable, '/root/to_bf16.py', d], stdout=open(d + '/bf16.log', 'w'), stderr=subprocess.STDOUT)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def main():
|
| 25 |
+
ap = argparse.ArgumentParser()
|
| 26 |
+
ap.add_argument('--arm', required=True, choices=['bits', 'standard'])
|
| 27 |
+
ap.add_argument('--model', default='Qwen/Qwen2.5-7B')
|
| 28 |
+
ap.add_argument('--tokens', type=int, default=500_000_000)
|
| 29 |
+
ap.add_argument('--max_len', type=int, default=512)
|
| 30 |
+
ap.add_argument('--bs', type=int, default=8)
|
| 31 |
+
ap.add_argument('--grad_accum', type=int, default=8)
|
| 32 |
+
ap.add_argument('--lr', type=float, default=3e-4)
|
| 33 |
+
ap.add_argument('--nbits', type=int, default=256)
|
| 34 |
+
ap.add_argument('--W', type=int, default=512)
|
| 35 |
+
ap.add_argument('--seed', type=int, default=42)
|
| 36 |
+
ap.add_argument('--out', required=True)
|
| 37 |
+
ap.add_argument('--fsdp', action='store_true')
|
| 38 |
+
ap.add_argument('--save_tokens', type=int, default=100_000_000)
|
| 39 |
+
a = ap.parse_args()
|
| 40 |
+
torch.manual_seed(a.seed)
|
| 41 |
+
tok = AutoTokenizer.from_pretrained(a.model)
|
| 42 |
+
if tok.pad_token is None:
|
| 43 |
+
tok.pad_token = tok.eos_token
|
| 44 |
+
cfg = AutoConfig.from_pretrained(a.model)
|
| 45 |
+
model = AutoModelForCausalLM.from_config(cfg, torch_dtype=torch.bfloat16, attn_implementation='sdpa')
|
| 46 |
+
if not a.fsdp:
|
| 47 |
+
model = model.cuda()
|
| 48 |
+
if a.arm == 'bits':
|
| 49 |
+
swap_in_bits(model, a.nbits, a.W, a.seed)
|
| 50 |
+
if not a.fsdp:
|
| 51 |
+
model = model.cuda()
|
| 52 |
+
nparam = sum(p.numel() for p in model.parameters())
|
| 53 |
+
emb = sum(p.numel() for p in model.get_input_embeddings().parameters())
|
| 54 |
+
print(f"[{a.arm} s{a.seed}] total={nparam/1e6:.0f}M embed={emb/1e6:.2f}M", flush=True)
|
| 55 |
+
train_ds = get_dataset(tok, a.max_len, a.tokens, 'train')
|
| 56 |
+
world = int(os.environ.get('WORLD_SIZE', 1))
|
| 57 |
+
tps = a.max_len * a.bs * a.grad_accum * world # tokens per optimizer step across all ranks
|
| 58 |
+
max_steps = max(1, a.tokens // tps)
|
| 59 |
+
save_every = max(1, a.save_tokens // tps) # checkpoint every 100M tokens
|
| 60 |
+
extra = {}
|
| 61 |
+
if a.fsdp:
|
| 62 |
+
extra = dict(fsdp='full_shard auto_wrap',
|
| 63 |
+
fsdp_config={'transformer_layer_cls_to_wrap': ['Qwen2DecoderLayer']})
|
| 64 |
+
targs = TrainingArguments(
|
| 65 |
+
output_dir=a.out, per_device_train_batch_size=a.bs, gradient_accumulation_steps=a.grad_accum,
|
| 66 |
+
learning_rate=a.lr, max_steps=max_steps, logging_steps=10, bf16=True,
|
| 67 |
+
save_strategy='steps', save_steps=save_every, save_total_limit=None, save_only_model=True,
|
| 68 |
+
optim='adamw_torch', gradient_checkpointing=True, report_to=['tensorboard'], dataloader_num_workers=2,
|
| 69 |
+
warmup_steps=math.ceil(0.02 * max_steps), lr_scheduler_type='cosine', max_grad_norm=1.0, seed=a.seed,
|
| 70 |
+
**extra)
|
| 71 |
+
def collate(b):
|
| 72 |
+
return {'input_ids': torch.tensor([x['input_ids'] for x in b]),
|
| 73 |
+
'labels': torch.tensor([x['labels'] for x in b])}
|
| 74 |
+
tr = Trainer(model=model, args=targs, train_dataset=train_ds, data_collator=collate)
|
| 75 |
+
tr.add_callback(Bf16Save())
|
| 76 |
+
print(f"[{a.arm} s{a.seed}] world={world} tokens/step={tps} max_steps={max_steps} save_every={save_every}", flush=True)
|
| 77 |
+
tr.train()
|
| 78 |
+
tr.save_model(a.out + '/final')
|
| 79 |
+
final = tr.state.log_history[-1].get('loss', float('nan')) if tr.state.log_history else float('nan')
|
| 80 |
+
print(f"[{a.arm} s{a.seed}] max_steps={max_steps} save_every={save_every} DONE final_loss~={final}", flush=True)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
if __name__ == '__main__':
|
| 84 |
+
main()
|
qwen2.5-7b_c4_1B/scripts/eval_ppl.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Held-out perplexity eval for Bits vs Standard checkpoints (supports encoder variants).
|
| 3 |
+
Same held-out set, same metric exp(mean per-token CE). For Bits variants, pass the SAME
|
| 4 |
+
--enc_type/--ffn_depth/--W/--nbits used at training so the module structure matches for loading."""
|
| 5 |
+
import argparse, glob, os, math, sys, torch
|
| 6 |
+
os.environ['HF_HUB_OFFLINE'] = '1'
|
| 7 |
+
os.environ['TRANSFORMERS_OFFLINE'] = '1'
|
| 8 |
+
import torch.nn.functional as F
|
| 9 |
+
sys.path.insert(0, '/root')
|
| 10 |
+
from transformers import AutoConfig, AutoModelForCausalLM
|
| 11 |
+
from safetensors.torch import load_file
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def build(a):
|
| 15 |
+
cfg = AutoConfig.from_pretrained(a.ckpt)
|
| 16 |
+
if a.arm == 'standard':
|
| 17 |
+
return AutoModelForCausalLM.from_pretrained(
|
| 18 |
+
a.ckpt, torch_dtype=torch.bfloat16, attn_implementation='sdpa').cuda().eval()
|
| 19 |
+
from bits_llm import swap_in_bits
|
| 20 |
+
model = AutoModelForCausalLM.from_config(cfg, torch_dtype=torch.bfloat16, attn_implementation='sdpa')
|
| 21 |
+
swap_in_bits(model, a.nbits, a.W, a.seed, enc_type=a.enc_type, ffn_depth=a.ffn_depth, out_scale=0.0)
|
| 22 |
+
sd = {}
|
| 23 |
+
for f in glob.glob(os.path.join(a.ckpt, '*.safetensors')):
|
| 24 |
+
sd.update(load_file(f))
|
| 25 |
+
missing, unexpected = model.load_state_dict(sd, strict=False)
|
| 26 |
+
enc_keys = [k for k in sd if 'embed_tokens' in k or '.ffn.' in k or 'in_proj' in k or 'out_proj' in k or 'tfenc' in k]
|
| 27 |
+
print(f"[load] tensors={len(sd)} enc_keys={len(enc_keys)} missing={len(missing)} unexpected={len(unexpected)}", flush=True)
|
| 28 |
+
if len(enc_keys) == 0:
|
| 29 |
+
print("[load][FATAL] no encoder weights in checkpoint", flush=True); sys.exit(3)
|
| 30 |
+
return model.cuda().eval()
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
@torch.no_grad()
|
| 34 |
+
def evaluate(model, seqs, bs):
|
| 35 |
+
tot_loss, tot_tok = 0.0, 0
|
| 36 |
+
for i in range(0, len(seqs), bs):
|
| 37 |
+
batch = torch.tensor(seqs[i:i+bs]).cuda()
|
| 38 |
+
logits = model(input_ids=batch).logits[:, :-1, :].float()
|
| 39 |
+
labels = batch[:, 1:]
|
| 40 |
+
loss = F.cross_entropy(logits.reshape(-1, logits.size(-1)), labels.reshape(-1), reduction='sum')
|
| 41 |
+
tot_loss += loss.item(); tot_tok += labels.numel()
|
| 42 |
+
ml = tot_loss / tot_tok
|
| 43 |
+
return ml, math.exp(ml)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def main():
|
| 47 |
+
ap = argparse.ArgumentParser()
|
| 48 |
+
ap.add_argument('--arm', required=True, choices=['bits', 'standard'])
|
| 49 |
+
ap.add_argument('--ckpt', required=True)
|
| 50 |
+
ap.add_argument('--data', default='/root/heldout_c4val_4000x512.pt')
|
| 51 |
+
ap.add_argument('--nbits', type=int, default=256)
|
| 52 |
+
ap.add_argument('--W', type=int, default=512)
|
| 53 |
+
ap.add_argument('--enc_type', default='mlp', choices=['mlp', 'tfenc'])
|
| 54 |
+
ap.add_argument('--ffn_depth', type=int, default=2)
|
| 55 |
+
ap.add_argument('--seed', type=int, default=42)
|
| 56 |
+
ap.add_argument('--n_seq', type=int, default=4000)
|
| 57 |
+
ap.add_argument('--bs', type=int, default=8)
|
| 58 |
+
a = ap.parse_args()
|
| 59 |
+
model = build(a)
|
| 60 |
+
seqs = torch.load(a.data)[:a.n_seq]
|
| 61 |
+
ml, ppl = evaluate(model, seqs, a.bs)
|
| 62 |
+
print(f"RESULT arm={a.arm} ckpt={a.ckpt} enc={a.enc_type} depth={a.ffn_depth} W={a.W} nbits={a.nbits} "
|
| 63 |
+
f"tokens={len(seqs)*len(seqs[0])} eval_loss={ml:.4f} ppl={ppl:.2f}", flush=True)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
if __name__ == '__main__':
|
| 67 |
+
main()
|
qwen2.5-7b_c4_1B/scripts/eval_seed.sh
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# usage: eval_seed.sh SEED ARM GPU -> appends RESULT lines to /root/traj/s3_1B/eval_s${SEED}_${ARM}.log
|
| 3 |
+
seed=$1; arm=$2; gpu=$3
|
| 4 |
+
source /venv/main/bin/activate; cd /root
|
| 5 |
+
dir=/root/traj/s3_1B/s${seed}_$([ $arm = bits ] && echo bits || echo std)
|
| 6 |
+
out=/root/traj/s3_1B/eval_s${seed}_${arm}.log
|
| 7 |
+
for c in $(ls -d $dir/checkpoint-* | sort -t- -k2 -n) $dir/final; do
|
| 8 |
+
grep -q "ckpt=$c " $out 2>/dev/null && continue
|
| 9 |
+
CUDA_VISIBLE_DEVICES=$gpu python eval_ppl.py --arm $arm --ckpt $c --seed $seed 2>&1 | grep -aE "RESULT|FATAL|Traceback|Error" >> $out
|
| 10 |
+
done
|
| 11 |
+
echo "EVAL_DONE seed=$seed arm=$arm" >> $out
|
qwen2.5-7b_c4_1B/scripts/heldout_c4val_4000x512.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:1484c78c496936bc7264647e1a253237791ba318953a71f0a4b62425228714cd
|
| 3 |
+
size 6015111
|
qwen2.5-7b_c4_1B/scripts/hf_arm.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, sys, time
|
| 2 |
+
os.environ["HF_HUB_ENABLE_HF_TRANSFER"]="1"
|
| 3 |
+
from huggingface_hub import HfApi
|
| 4 |
+
arm=sys.argv[1]; tok=sys.stdin.readline().strip()
|
| 5 |
+
api=HfApi(token=tok); repo="bit2vec/bitsseal"; base="/root/traj/s3_1B"
|
| 6 |
+
for attempt in range(8):
|
| 7 |
+
try:
|
| 8 |
+
api.upload_folder(folder_path=f"{base}/{arm}", repo_id=repo, path_in_repo=f"qwen2.5-7b_c4_1B/{arm}",
|
| 9 |
+
allow_patterns=["checkpoint-*/*.safetensors","checkpoint-*/*.json","checkpoint-*/bf16.log"], commit_message=f"{arm}: all checkpoints")
|
| 10 |
+
print("ARM_UPLOADED", arm, time.strftime("%H:%M:%S"), flush=True); break
|
| 11 |
+
except Exception as e:
|
| 12 |
+
print("RETRY", arm, attempt, repr(e)[:300], flush=True); time.sleep(300)
|
| 13 |
+
else:
|
| 14 |
+
print("GAVEUP", arm, flush=True)
|
| 15 |
+
if arm=="s42_bits":
|
| 16 |
+
api.upload_folder(folder_path=base, repo_id=repo, path_in_repo="qwen2.5-7b_c4_1B/logs", allow_patterns=["*.log"], ignore_patterns=["**/checkpoint-*/**","**/runs/**"], commit_message="logs")
|
| 17 |
+
api.upload_folder(folder_path="/root", repo_id=repo, path_in_repo="qwen2.5-7b_c4_1B/scripts", allow_patterns=["bits_llm.py","bits_lm_traj.py","eval_ppl.py","eval_seed.sh","run_3seeds_1B.sh","to_bf16.py","hf_arm.py","heldout_c4val_4000x512.pt"], commit_message="scripts")
|
| 18 |
+
print("LOGS_SCRIPTS_DONE", flush=True)
|
qwen2.5-7b_c4_1B/scripts/run_3seeds_1B.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# 3 seed pairs at 1B tokens, both arms of a seed at once on 4 GPUs each, seeds back to back.
|
| 3 |
+
cd /root
|
| 4 |
+
export FSDP_MODE="full_shard auto_wrap"
|
| 5 |
+
OUT=/root/traj/s3_1B; mkdir -p $OUT
|
| 6 |
+
for seed in 43 44 42; do
|
| 7 |
+
echo "[$(date -u +%FT%TZ)] START seed $seed" >> $OUT/driver.log
|
| 8 |
+
CUDA_VISIBLE_DEVICES=0,1,2,3 torchrun --nproc_per_node 4 --master_port 29501 bits_lm_traj.py --arm bits --bs 16 --grad_accum 1 --tokens 1000000000 --seed $seed --fsdp --out $OUT/s${seed}_bits > $OUT/s${seed}_bits.log 2>&1 &
|
| 9 |
+
P1=$!
|
| 10 |
+
CUDA_VISIBLE_DEVICES=4,5,6,7 torchrun --nproc_per_node 4 --master_port 29502 bits_lm_traj.py --arm standard --bs 16 --grad_accum 1 --tokens 1000000000 --seed $seed --fsdp --out $OUT/s${seed}_std > $OUT/s${seed}_std.log 2>&1 &
|
| 11 |
+
P2=$!
|
| 12 |
+
wait $P1; R1=$?; wait $P2; R2=$?
|
| 13 |
+
echo "[$(date -u +%FT%TZ)] END seed $seed bits_rc=$R1 std_rc=$R2" >> $OUT/driver.log
|
| 14 |
+
done
|
| 15 |
+
echo "[$(date -u +%FT%TZ)] ALL_SEEDS_DONE" >> $OUT/driver.log
|
qwen2.5-7b_c4_1B/scripts/to_bf16.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import sys, os, glob, torch
|
| 2 |
+
from safetensors.torch import load_file, save_file
|
| 3 |
+
d = sys.argv[1]
|
| 4 |
+
for p in sorted(glob.glob(os.path.join(d, '*.safetensors'))):
|
| 5 |
+
sd = load_file(p)
|
| 6 |
+
n = sum(v.numel() for v in sd.values())
|
| 7 |
+
sd = {k: (v.to(torch.bfloat16) if v.is_floating_point() else v) for k, v in sd.items()}
|
| 8 |
+
save_file(sd, p + '.tmp', metadata={'format': 'pt'})
|
| 9 |
+
os.replace(p + '.tmp', p)
|
| 10 |
+
print('bf16', p, n, flush=True)
|
| 11 |
+
print('DONE', flush=True)
|