preflight: P2 parses RUN_JSON per cell and requires the frozen 22L/2048 cell to report
Browse files- train/preflight.py +29 -9
train/preflight.py
CHANGED
|
@@ -301,20 +301,40 @@ def torchrun(args, extra, timeout=7200):
|
|
| 301 |
|
| 302 |
def p2_throughput(args, R):
|
| 303 |
"""T1: 20L vs 22L at two sequence lengths, on the real data, for enough steps that the number is
|
| 304 |
-
steady-state. The main run's whole schedule is division by this number.
|
|
|
|
| 305 |
out = {}
|
| 306 |
for layers in (20, 22):
|
| 307 |
for seq in (1024, 2048):
|
| 308 |
-
micro =
|
| 309 |
-
r = torchrun(args, ["--layers", str(layers), "--
|
| 310 |
-
"--micro-batch", str(micro), "--accum", "1", "--max-steps", "
|
| 311 |
-
"--out", WORK + f"/t1_{layers}_{seq}", "--log-every", "
|
| 312 |
timeout=5400)
|
| 313 |
-
|
| 314 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
R["P2"] = out
|
| 316 |
-
|
| 317 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
|
| 319 |
|
| 320 |
def p3_cold_resume(args, R):
|
|
|
|
| 301 |
|
| 302 |
def p2_throughput(args, R):
|
| 303 |
"""T1: 20L vs 22L at two sequence lengths, on the real data, for enough steps that the number is
|
| 304 |
+
steady-state. The main run's whole schedule is division by this number. 22L/576 is the frozen shape;
|
| 305 |
+
20L is the H-column alternative from docs/01-plan.md §2.3."""
|
| 306 |
out = {}
|
| 307 |
for layers in (20, 22):
|
| 308 |
for seq in (1024, 2048):
|
| 309 |
+
micro = 4 if seq == 1024 else 2
|
| 310 |
+
r = torchrun(args, ["--layers", str(layers), "--seq-len", str(seq),
|
| 311 |
+
"--micro-batch", str(micro), "--accum", "1", "--max-steps", "30",
|
| 312 |
+
"--out", WORK + f"/t1_{layers}_{seq}", "--log-every", "10"],
|
| 313 |
timeout=5400)
|
| 314 |
+
cell = {"rc": r["rc"], "seconds": r["seconds"], "micro_batch": micro}
|
| 315 |
+
for line in r["out"].splitlines():
|
| 316 |
+
if line.startswith("RUN_JSON "):
|
| 317 |
+
try:
|
| 318 |
+
cell.update(json.loads(line[len("RUN_JSON "):]))
|
| 319 |
+
except Exception as e:
|
| 320 |
+
cell["run_json_unparseable"] = str(e)[:120]
|
| 321 |
+
elif line.startswith("params:"):
|
| 322 |
+
cell["params_line"] = line[:200]
|
| 323 |
+
elif line.startswith("precision:"):
|
| 324 |
+
cell["precision"] = line[:200]
|
| 325 |
+
if "tok_per_s" not in cell:
|
| 326 |
+
cell["tail"] = r["out"][-1500:]
|
| 327 |
+
cell["err"] = r["err"][-800:]
|
| 328 |
+
out[f"L{layers}_s{seq}"] = cell
|
| 329 |
R["P2"] = out
|
| 330 |
+
got = [c for c in out.values() if isinstance(c.get("tok_per_s"), (int, float))]
|
| 331 |
+
# Pass means all four cells ran AND the frozen cell (22L/seq2048) is reported, because that is the
|
| 332 |
+
# configuration the main run uses; a run where only the cheap cells succeeded proves nothing.
|
| 333 |
+
R["P2_pass"] = bool(len(out) == 4 and all(c.get("rc") == 0 for c in out.values())
|
| 334 |
+
and len(got) == 4 and out["L22_s2048"].get("params") == 106194240)
|
| 335 |
+
R["P2_eta_hours_at_1B"] = ({k: round(1e9 / c["tok_per_s"] / 3600, 2)
|
| 336 |
+
for k, c in out.items() if c.get("tok_per_s")})
|
| 337 |
+
print("VERDICT P2_pass=", R["P2_pass"], "eta_hours:", json.dumps(R["P2_eta_hours_at_1B"]), flush=True)
|
| 338 |
|
| 339 |
|
| 340 |
def p3_cold_resume(args, R):
|