trainer: an unverified checkpoint never rolls latest.json and never prunes (E-042)
Browse files- train/train_ounce100m.py +13 -1
train/train_ounce100m.py
CHANGED
|
@@ -166,13 +166,25 @@ class HubPush(TrainerCallback):
|
|
| 166 |
# session would quietly re-read 100 M tokens.
|
| 167 |
res = hubckpt.push_and_prune(self.repo, d, f"ckpt/checkpoint-{step}", self.api,
|
| 168 |
repo_type=self.repo_type, token=self.token, prune=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
ptr_body = {"path_in_repo": f"ckpt/checkpoint-{step}", "step": step,
|
| 170 |
"samples_consumed": samples, "tokens_consumed": samples * self.seq_len,
|
| 171 |
"fingerprint": self.fingerprint, "seed": self.seed}
|
| 172 |
hubckpt.write_latest_pointer(self.repo, ptr_body, self.api, repo_type=self.repo_type,
|
| 173 |
token=self.token)
|
| 174 |
if self.prune:
|
| 175 |
-
hubckpt.
|
| 176 |
loss = next((h["loss"] for h in reversed(state.log_history) if "loss" in h), None)
|
| 177 |
print(f"CKPT {step} samples={samples:,} push+verify={round(time.time()-t0,1)}s "
|
| 178 |
f"ok={res['verify']['ok']} pruned={res.get('pruned')} free={res['free_after_gb']}GB "
|
|
|
|
| 166 |
# session would quietly re-read 100 M tokens.
|
| 167 |
res = hubckpt.push_and_prune(self.repo, d, f"ckpt/checkpoint-{step}", self.api,
|
| 168 |
repo_type=self.repo_type, token=self.token, prune=False)
|
| 169 |
+
# E-042: `prune=False` above means `push_and_prune`'s own guard never runs, so this path had to
|
| 170 |
+
# carry it. An unverified checkpoint must stop the session *before* the pointer moves: a pointer
|
| 171 |
+
# rolled onto bytes nobody checked, with the local copy then deleted, is a run that cannot be
|
| 172 |
+
# resumed and does not know it.
|
| 173 |
+
ver = res["verify"]
|
| 174 |
+
if not ver["ok"]:
|
| 175 |
+
raise RuntimeError(
|
| 176 |
+
f"checkpoint {step} did not verify on the Hub "
|
| 177 |
+
f"(missing={len(ver['missing'])} mismatched={len(ver['mismatch'])} "
|
| 178 |
+
f"extra={len(ver['extra'])} readback_ok={ver['readback_ok']}). Keeping the local copy in "
|
| 179 |
+
f"{d} and refusing to roll latest.json -- the next session would otherwise resume from "
|
| 180 |
+
"bytes that were never confirmed to exist.")
|
| 181 |
ptr_body = {"path_in_repo": f"ckpt/checkpoint-{step}", "step": step,
|
| 182 |
"samples_consumed": samples, "tokens_consumed": samples * self.seq_len,
|
| 183 |
"fingerprint": self.fingerprint, "seed": self.seed}
|
| 184 |
hubckpt.write_latest_pointer(self.repo, ptr_body, self.api, repo_type=self.repo_type,
|
| 185 |
token=self.token)
|
| 186 |
if self.prune:
|
| 187 |
+
hubckpt.prune_verified(d, res, self.min_free_gb)
|
| 188 |
loss = next((h["loss"] for h in reversed(state.log_history) if "loss" in h), None)
|
| 189 |
print(f"CKPT {step} samples={samples:,} push+verify={round(time.time()-t0,1)}s "
|
| 190 |
f"ok={res['verify']['ok']} pruned={res.get('pruned')} free={res['free_after_gb']}GB "
|