Reverendo commited on
Commit
bcbd7e6
·
verified ·
1 Parent(s): ba18fe4

fast local checkpoints, fewer bucket writes

Browse files
Files changed (1) hide show
  1. scugnizz-llama.py +74 -20
scugnizz-llama.py CHANGED
@@ -45,6 +45,9 @@ KEEP (optimizer resume):
45
  SAFE TO DELETE (weights-only snapshots):
46
  - checkpoint_weights_last.pt
47
  - old model_final.pt after a newer run finishes
 
 
 
48
  """
49
 
50
 
@@ -276,9 +279,13 @@ def parse_args():
276
  p.add_argument("--dropout", type=float, default=0.0)
277
  p.add_argument("--eval-interval", type=int, default=50)
278
  p.add_argument("--eval-batches", type=int, default=10)
279
- p.add_argument("--save-interval", type=int, default=50)
280
- p.add_argument("--weights-save-interval", type=int, default=10,
281
- help="Save weights-only checkpoint every N steps (fast, ~3GB)")
 
 
 
 
282
  p.add_argument("--log-interval", type=int, default=10)
283
  p.add_argument("--pcs-a", type=float, default=0.8309193524478643)
284
  p.add_argument("--pcs-b", type=float, default=0.0)
@@ -439,11 +446,11 @@ def save_ckpt(path, model, opt, step, best, rank, world_size, mirror_resume=Fals
439
  barrier(rank, world_size)
440
 
441
 
442
- def copy_best_ckpt(out, rank, world_size):
443
  if not is_main(rank):
444
  barrier(rank, world_size)
445
  return
446
- last, best = out / "checkpoint_last.pt", out / "checkpoint_best.pt"
447
  if last.exists():
448
  shutil.copy2(last, best)
449
  print("SAVED", best, "(copy of checkpoint_last)", flush=True)
@@ -488,12 +495,12 @@ def load_init_payload(path, dev):
488
  return ck, None, False
489
 
490
 
491
- def resume_training(model, out, a, rank, world_size, dev):
492
  start, best, opt_state = 0, float("inf"), None
493
  if a.no_resume:
494
  return start, best, opt_state
495
 
496
- resume_path = find_resume_ckpt(out)
497
  init_path = a.init_from or fetch_init_hub(a, rank, world_size)
498
  weights_path = out / "model_final.pt"
499
 
@@ -565,11 +572,40 @@ def resume_training(model, out, a, rank, world_size, dev):
565
  return start, best, opt_state
566
 
567
 
568
- def find_resume_ckpt(out: Path):
569
- for name in ("checkpoint_last.pt", RESUME_CKPT, "checkpoint_best.pt"):
570
- p = out / name
571
- if p.exists():
572
- return p
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
  return None
574
 
575
 
@@ -651,8 +687,10 @@ def main():
651
  set_seed(a.seed, rank)
652
  dt = dtype_of(a.dtype, dev)
653
  out = Path(a.out_dir)
 
654
  if is_main(rank):
655
  out.mkdir(parents=True, exist_ok=True)
 
656
  (out / "CHECKPOINT_POLICY.txt").write_text(KEEP_NOTE, encoding="utf-8")
657
  barrier(rank, world_size)
658
 
@@ -674,7 +712,7 @@ def main():
674
  params = sum(p.numel() for p in model.parameters())
675
  log0(rank, f"params {params/1e9:.3f}B ({params/1e6:.1f}M)", flush=True)
676
 
677
- start, best, opt_state = resume_training(model, out, a, rank, world_size, dev)
678
  if is_main(rank):
679
  (out / "args.json").write_text(json.dumps(vars(a), indent=2), encoding="utf-8")
680
  barrier(rank, world_size)
@@ -694,17 +732,20 @@ def main():
694
  opt.load_state_dict(opt_state)
695
  log0(rank, "loaded optimizer state", flush=True)
696
 
697
- last = out / "checkpoint_last.pt"
698
- bestp = out / "checkpoint_best.pt"
699
- weights_last = out / "checkpoint_weights_last.pt"
 
700
 
701
  log0(rank, "initializing data streams...", flush=True)
 
702
  train = Batcher(a, tok, dev, rank, log=is_main(rank))
703
  val = Batcher(a, tok, dev, 10_000, log=False) if is_main(rank) else None
704
  log0(rank, f"starting training loop from step {start}...", flush=True)
705
  t0 = time.time()
706
  roll = 0.0
707
  n = 0
 
708
  model.train()
709
 
710
  for step in range(start, a.max_steps + 1):
@@ -727,13 +768,17 @@ def main():
727
 
728
  if step % a.log_interval == 0:
729
  avg = roll / max(1, n)
730
- elapsed = max(1e-6, time.time() - t0)
 
 
731
  tok_s = max(1, step - start + 1) * tps / elapsed
 
732
  log0(
733
  rank,
734
- f"step {step:08d} | loss {avg:.4f} | ppl {math.exp(min(20, avg)):.1f} | lr {lr:.2e} | tok/s {tok_s:.0f} | trained_tokens {step*tps} | rows {train.rows}",
735
  flush=True,
736
  )
 
737
  roll = 0.0
738
  n = 0
739
 
@@ -761,13 +806,22 @@ def main():
761
  if step > 0 and step % a.save_interval == 0:
762
  save_ckpt(last, model, opt, step, best, rank, world_size, mirror_resume=True)
763
  if val_improved:
764
- copy_best_ckpt(out, rank, world_size)
 
 
 
 
 
 
765
  if is_main(rank) and a.push_every_save:
766
  upload_final(str(out), a.hub_repo_id, a.hub_path, f"pretrain checkpoint step {step}")
767
 
768
  save_ckpt(last, model, opt, a.max_steps, best, rank, world_size, mirror_resume=True)
 
769
  if is_main(rank):
770
- torch.save(raw_model(model).state_dict(), out / "model_final.pt")
 
 
771
  tok.save_pretrained(out / "tokenizer")
772
  if a.push:
773
  upload_final(str(out), a.hub_repo_id, a.hub_path, "final ScugnizzLLM Llama-PCS pretrain")
 
45
  SAFE TO DELETE (weights-only snapshots):
46
  - checkpoint_weights_last.pt
47
  - old model_final.pt after a newer run finishes
48
+
49
+ Checkpoints write to CKPT_LOCAL_DIR (default /tmp) first, then resume is copied to out-dir.
50
+ Set WEIGHTS_SAVE_INTERVAL=0 for long runs (default).
51
  """
52
 
53
 
 
279
  p.add_argument("--dropout", type=float, default=0.0)
280
  p.add_argument("--eval-interval", type=int, default=50)
281
  p.add_argument("--eval-batches", type=int, default=10)
282
+ p.add_argument("--save-interval", type=int, default=100)
283
+ p.add_argument("--weights-save-interval", type=int, default=0,
284
+ help="Weights-only snapshot every N steps (0=off; slows bucket I/O)")
285
+ p.add_argument("--ckpt-local-dir", default="/tmp/scugnizz-ckpts",
286
+ help="Fast local dir for checkpoint writes; synced to out-dir periodically")
287
+ p.add_argument("--bucket-sync-interval", type=int, default=1,
288
+ help="Sync resume checkpoint to out-dir every N save-intervals (1=every save)")
289
  p.add_argument("--log-interval", type=int, default=10)
290
  p.add_argument("--pcs-a", type=float, default=0.8309193524478643)
291
  p.add_argument("--pcs-b", type=float, default=0.0)
 
446
  barrier(rank, world_size)
447
 
448
 
449
+ def copy_best_ckpt(local, rank, world_size):
450
  if not is_main(rank):
451
  barrier(rank, world_size)
452
  return
453
+ last, best = local / "checkpoint_last.pt", local / "checkpoint_best.pt"
454
  if last.exists():
455
  shutil.copy2(last, best)
456
  print("SAVED", best, "(copy of checkpoint_last)", flush=True)
 
495
  return ck, None, False
496
 
497
 
498
+ def resume_training(model, local, out, a, rank, world_size, dev):
499
  start, best, opt_state = 0, float("inf"), None
500
  if a.no_resume:
501
  return start, best, opt_state
502
 
503
+ resume_path = find_resume_ckpt(local, out)
504
  init_path = a.init_from or fetch_init_hub(a, rank, world_size)
505
  weights_path = out / "model_final.pt"
506
 
 
572
  return start, best, opt_state
573
 
574
 
575
+ def sync_file(src, dst, rank, world_size):
576
+ if not is_main(rank):
577
+ barrier(rank, world_size)
578
+ return
579
+ if src.exists():
580
+ dst.parent.mkdir(parents=True, exist_ok=True)
581
+ tmp = dst.with_suffix(dst.suffix + ".tmp")
582
+ shutil.copy2(src, tmp)
583
+ tmp.replace(dst)
584
+ print("SYNCED", dst, flush=True)
585
+ barrier(rank, world_size)
586
+
587
+
588
+ def sync_bucket_ckpts(local, out, rank, world_size, names):
589
+ if not is_main(rank):
590
+ barrier(rank, world_size)
591
+ return
592
+ for name in names:
593
+ src, dst = local / name, out / name
594
+ if src.exists():
595
+ dst.parent.mkdir(parents=True, exist_ok=True)
596
+ tmp = dst.with_suffix(dst.suffix + ".tmp")
597
+ shutil.copy2(src, tmp)
598
+ tmp.replace(dst)
599
+ print("SYNCED", dst, flush=True)
600
+ barrier(rank, world_size)
601
+
602
+
603
+ def find_resume_ckpt(local, out):
604
+ for base in (local, out):
605
+ for name in ("checkpoint_last.pt", RESUME_CKPT, "checkpoint_best.pt"):
606
+ p = base / name
607
+ if p.exists():
608
+ return p
609
  return None
610
 
611
 
 
687
  set_seed(a.seed, rank)
688
  dt = dtype_of(a.dtype, dev)
689
  out = Path(a.out_dir)
690
+ local = Path(a.ckpt_local_dir)
691
  if is_main(rank):
692
  out.mkdir(parents=True, exist_ok=True)
693
+ local.mkdir(parents=True, exist_ok=True)
694
  (out / "CHECKPOINT_POLICY.txt").write_text(KEEP_NOTE, encoding="utf-8")
695
  barrier(rank, world_size)
696
 
 
712
  params = sum(p.numel() for p in model.parameters())
713
  log0(rank, f"params {params/1e9:.3f}B ({params/1e6:.1f}M)", flush=True)
714
 
715
+ start, best, opt_state = resume_training(model, local, out, a, rank, world_size, dev)
716
  if is_main(rank):
717
  (out / "args.json").write_text(json.dumps(vars(a), indent=2), encoding="utf-8")
718
  barrier(rank, world_size)
 
732
  opt.load_state_dict(opt_state)
733
  log0(rank, "loaded optimizer state", flush=True)
734
 
735
+ last = local / "checkpoint_last.pt"
736
+ bestp = local / "checkpoint_best.pt"
737
+ weights_last = local / "checkpoint_weights_last.pt"
738
+ saves_done = 0
739
 
740
  log0(rank, "initializing data streams...", flush=True)
741
+ log0(rank, f"ckpt_local={local} out_dir={out}", flush=True)
742
  train = Batcher(a, tok, dev, rank, log=is_main(rank))
743
  val = Batcher(a, tok, dev, 10_000, log=False) if is_main(rank) else None
744
  log0(rank, f"starting training loop from step {start}...", flush=True)
745
  t0 = time.time()
746
  roll = 0.0
747
  n = 0
748
+ log_t0 = t0
749
  model.train()
750
 
751
  for step in range(start, a.max_steps + 1):
 
768
 
769
  if step % a.log_interval == 0:
770
  avg = roll / max(1, n)
771
+ now = time.time()
772
+ elapsed = max(1e-6, now - t0)
773
+ interval = max(1e-6, now - log_t0)
774
  tok_s = max(1, step - start + 1) * tps / elapsed
775
+ instant = a.log_interval * tps / interval
776
  log0(
777
  rank,
778
+ f"step {step:08d} | loss {avg:.4f} | ppl {math.exp(min(20, avg)):.1f} | lr {lr:.2e} | tok/s {tok_s:.0f} ({instant:.0f} inst) | trained_tokens {step*tps} | rows {train.rows}",
779
  flush=True,
780
  )
781
+ log_t0 = now
782
  roll = 0.0
783
  n = 0
784
 
 
806
  if step > 0 and step % a.save_interval == 0:
807
  save_ckpt(last, model, opt, step, best, rank, world_size, mirror_resume=True)
808
  if val_improved:
809
+ copy_best_ckpt(local, rank, world_size)
810
+ saves_done += 1
811
+ if saves_done % max(1, a.bucket_sync_interval) == 0:
812
+ names = [RESUME_CKPT, "checkpoint_last.pt"]
813
+ if (local / "checkpoint_best.pt").exists():
814
+ names.append("checkpoint_best.pt")
815
+ sync_bucket_ckpts(local, out, rank, world_size, names)
816
  if is_main(rank) and a.push_every_save:
817
  upload_final(str(out), a.hub_repo_id, a.hub_path, f"pretrain checkpoint step {step}")
818
 
819
  save_ckpt(last, model, opt, a.max_steps, best, rank, world_size, mirror_resume=True)
820
+ sync_bucket_ckpts(local, out, rank, world_size, (RESUME_CKPT, "checkpoint_last.pt", "checkpoint_best.pt"))
821
  if is_main(rank):
822
+ final_local = local / "model_final.pt"
823
+ torch.save(raw_model(model).state_dict(), final_local)
824
+ sync_file(final_local, out / "model_final.pt", rank, world_size)
825
  tok.save_pretrained(out / "tokenizer")
826
  if a.push:
827
  upload_final(str(out), a.hub_repo_id, a.hub_path, "final ScugnizzLLM Llama-PCS pretrain")