Cion-lab commited on
Commit
18d95d5
·
verified ·
1 Parent(s): e76a599

Upload train/train_ounce100m.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. train/train_ounce100m.py +40 -5
train/train_ounce100m.py CHANGED
@@ -125,14 +125,26 @@ class HubPush(TrainerCallback):
125
  """
126
 
127
  def __init__(self, repo, api, token, seq_len, seed, fingerprint, seqs_per_step,
128
- prune=True, min_free_gb=6.0, repo_type="dataset"):
129
  self.repo, self.api, self.token = repo, api, token
130
  self.seq_len, self.seed, self.fingerprint = seq_len, seed, fingerprint
131
  self.seqs_per_step, self.repo_type = seqs_per_step, repo_type
132
  self.prune, self.min_free_gb = prune, min_free_gb
 
 
133
  self.n = 0
134
  self.results = []
135
 
 
 
 
 
 
 
 
 
 
 
136
  def on_save(self, args, state, control, **kw):
137
  if not state.is_world_process_zero:
138
  return control
@@ -257,6 +269,10 @@ def main():
257
  ap.add_argument("--val-tokens", type=int, default=2_000_000)
258
  ap.add_argument("--log-every", type=int, default=10)
259
  ap.add_argument("--push-every-steps", type=int, default=0, help="0 = only at 10% boundaries")
 
 
 
 
260
  ap.add_argument("--prune", action="store_true", help="delete local checkpoint after hub verify")
261
  ap.add_argument("--dry-run", action="store_true", help="build everything, train 0 steps")
262
  ap.add_argument("--benchmark", type=int, default=0,
@@ -368,6 +384,14 @@ def main():
368
 
369
  # 10 checkpoints per run is §2's cadence; --push-every-steps overrides for the preflight.
370
  ckpt_every = args.push_every_steps or max(1, steps_planned // 10)
 
 
 
 
 
 
 
 
371
 
372
  api = None
373
  if args.hub_repo:
@@ -420,10 +444,13 @@ def main():
420
  "decay_start": int(steps_planned * args.decay_frac),
421
  "total_steps": steps_planned},
422
  )
 
423
  if api is not None:
424
- tr.add_callback(HubPush(args.hub_repo, api, os.environ.get("HF_TOKEN"), args.seq_len,
425
- args.data_seed, fingerprint, seqs_per_step,
426
- prune=args.prune, repo_type=args.hub_repo_type))
 
 
427
 
428
  # Precision must be ASSERTED, not configured: bf16 "works" silently on Turing and fp32 master
429
  # weights can be lost in a refactor (docs/00-platform-notes.md §8, memory/ERRORS.md E-006). The
@@ -494,7 +521,8 @@ def main():
494
  say(f"validation loss={ev['eval_loss']:.4f} ppl={ppl:.2f} over {n_val} held-out windows")
495
  except Exception as e:
496
  say(f"validation eval failed: {type(e).__name__}: {str(e)[:200]}")
497
- if api is not None:
 
498
  r = hubckpt.push_and_prune(args.hub_repo, out, "final", api, repo_type=args.hub_repo_type,
499
  token=os.environ.get("HF_TOKEN"), prune=args.prune)
500
  # .get, not [k]: `pruned` and `free_after_gb` are only present on some paths through
@@ -502,7 +530,14 @@ def main():
502
  say("final push:", json.dumps({k: r.get(k) for k in
503
  ("verify", "pruned", "free_before_gb", "free_after_gb",
504
  "prune_blocked_reason")}, default=str)[:900])
 
 
 
 
 
 
505
  say("RUN_JSON " + json.dumps({"final_step": step, "val_ppl": ppl, "tokens_consumed": consumed,
 
506
  "tok_per_s": round(consumed_this_run / max(1, elapsed)),
507
  "final_loss": final_loss, "prior_loss": prior,
508
  "micro_batch": args.micro_batch, "seq_len": args.seq_len,
 
125
  """
126
 
127
  def __init__(self, repo, api, token, seq_len, seed, fingerprint, seqs_per_step,
128
+ prune=True, min_free_gb=6.0, repo_type="dataset", stop_after_steps=0):
129
  self.repo, self.api, self.token = repo, api, token
130
  self.seq_len, self.seed, self.fingerprint = seq_len, seed, fingerprint
131
  self.seqs_per_step, self.repo_type = seqs_per_step, repo_type
132
  self.prune, self.min_free_gb = prune, min_free_gb
133
+ self.stop_after = int(stop_after_steps or 0)
134
+ self.stopped_at = None
135
  self.n = 0
136
  self.results = []
137
 
138
+ def on_step_end(self, args, state, control, **kw):
139
+ # A session that ends ON a verified checkpoint loses nothing when the platform takes the disk.
140
+ # That is how the 10 % cadence is made compatible with an unknown session cap: instead of pushing
141
+ # extra intermediate copies (which multiplies Hub LFS storage by the number of sessions), the run
142
+ # is cut into segments whose length is a whole number of checkpoint intervals.
143
+ if self.stop_after and state.global_step >= self.stop_after:
144
+ self.stopped_at = state.global_step
145
+ control.should_training_stop = True
146
+ return control
147
+
148
  def on_save(self, args, state, control, **kw):
149
  if not state.is_world_process_zero:
150
  return control
 
269
  ap.add_argument("--val-tokens", type=int, default=2_000_000)
270
  ap.add_argument("--log-every", type=int, default=10)
271
  ap.add_argument("--push-every-steps", type=int, default=0, help="0 = only at 10% boundaries")
272
+ ap.add_argument("--stop-after-steps", type=int, default=0,
273
+ help="absolute global step at which THIS session stops training, so it ends on a "
274
+ "verified checkpoint instead of being killed between two of them. Must be a "
275
+ "whole multiple of the checkpoint interval; 0 = run to the horizon.")
276
  ap.add_argument("--prune", action="store_true", help="delete local checkpoint after hub verify")
277
  ap.add_argument("--dry-run", action="store_true", help="build everything, train 0 steps")
278
  ap.add_argument("--benchmark", type=int, default=0,
 
384
 
385
  # 10 checkpoints per run is §2's cadence; --push-every-steps overrides for the preflight.
386
  ckpt_every = args.push_every_steps or max(1, steps_planned // 10)
387
+ if args.stop_after_steps:
388
+ if args.stop_after_steps % ckpt_every:
389
+ raise SystemExit(f"--stop-after-steps {args.stop_after_steps} is not a whole multiple of the "
390
+ f"checkpoint interval {ckpt_every}: the session would end between two "
391
+ f"checkpoints, which is exactly what this flag exists to prevent")
392
+ if args.stop_after_steps > steps_planned:
393
+ raise SystemExit(f"--stop-after-steps {args.stop_after_steps} exceeds the horizon "
394
+ f"{steps_planned}; use 0 to run to the end")
395
 
396
  api = None
397
  if args.hub_repo:
 
444
  "decay_start": int(steps_planned * args.decay_frac),
445
  "total_steps": steps_planned},
446
  )
447
+ hub_cb = None
448
  if api is not None:
449
+ hub_cb = HubPush(args.hub_repo, api, os.environ.get("HF_TOKEN"), args.seq_len,
450
+ args.data_seed, fingerprint, seqs_per_step,
451
+ prune=args.prune, repo_type=args.hub_repo_type,
452
+ stop_after_steps=args.stop_after_steps)
453
+ tr.add_callback(hub_cb)
454
 
455
  # Precision must be ASSERTED, not configured: bf16 "works" silently on Turing and fp32 master
456
  # weights can be lost in a refactor (docs/00-platform-notes.md §8, memory/ERRORS.md E-006). The
 
521
  say(f"validation loss={ev['eval_loss']:.4f} ppl={ppl:.2f} over {n_val} held-out windows")
522
  except Exception as e:
523
  say(f"validation eval failed: {type(e).__name__}: {str(e)[:200]}")
524
+ segment = bool(hub_cb and hub_cb.stopped_at and step < steps_planned)
525
+ if api is not None and not segment:
526
  r = hubckpt.push_and_prune(args.hub_repo, out, "final", api, repo_type=args.hub_repo_type,
527
  token=os.environ.get("HF_TOKEN"), prune=args.prune)
528
  # .get, not [k]: `pruned` and `free_after_gb` are only present on some paths through
 
530
  say("final push:", json.dumps({k: r.get(k) for k in
531
  ("verify", "pruned", "free_before_gb", "free_after_gb",
532
  "prune_blocked_reason")}, default=str)[:900])
533
+ elif segment:
534
+ # The session stopped on a checkpoint interval, and HubPush already pushed AND verified that
535
+ # checkpoint and rolled latest.json to it. Re-pushing it as "final" would add a 1.7 GB LFS
536
+ # revision per session for a copy the Hub already holds.
537
+ say(f"segment boundary reached at step {step} of {steps_planned}: the checkpoint HubPush just "
538
+ "verified is the resume point, so no separate final push")
539
  say("RUN_JSON " + json.dumps({"final_step": step, "val_ppl": ppl, "tokens_consumed": consumed,
540
+ "segment_stop": segment, "steps_planned": steps_planned,
541
  "tok_per_s": round(consumed_this_run / max(1, elapsed)),
542
  "final_loss": final_loss, "prior_loss": prior,
543
  "micro_batch": args.micro_batch, "seq_len": args.seq_len,