Skip to content

Commit bede958

Browse files
committed
Implement MLPerf v6.1 offline evaluation and RCP mllog logging (b/543463274)
1 parent 8ca356c commit bede958

11 files changed

Lines changed: 1060 additions & 38 deletions

File tree

‎tests/experimental/examples/deepswe_dist/eval_deepswe_test.py‎

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,5 +286,198 @@ async def test_missing_reply_has_deadline(self):
286286
)
287287

288288

289+
mllog_lib = load("mllog_utils_under_test", ROOT / "tunix/utils/mllog_utils.py")
290+
291+
292+
class OfflineEvalRcpTest(unittest.IsolatedAsyncioTestCase):
293+
294+
def test_compute_val_start_step(self):
295+
self.assertEqual(mllog_lib.compute_val_start_step(256), 18)
296+
self.assertEqual(mllog_lib.compute_val_start_step(128), 33)
297+
self.assertEqual(mllog_lib.compute_val_start_step(256, 5), 5)
298+
with self.assertRaises(ValueError):
299+
mllog_lib.compute_val_start_step(0)
300+
301+
def test_checkpoint_manifest_read_write_and_contiguity(self):
302+
with tempfile.TemporaryDirectory() as tmpdir:
303+
manifest_path = str(Path(tmpdir) / "eval_checkpoints.jsonl")
304+
mllog_lib.append_checkpoint_manifest(
305+
manifest_path,
306+
{
307+
"step": 19,
308+
"samples_count": 4864,
309+
"checkpoint_timestamp_ms": 2000,
310+
"checkpoint_path": "gs://ckpt/19/model_params",
311+
"val_start_at": 18,
312+
"max_steps": 50,
313+
},
314+
)
315+
mllog_lib.append_checkpoint_manifest(
316+
manifest_path,
317+
{
318+
"step": 18,
319+
"samples_count": 4608,
320+
"checkpoint_timestamp_ms": 1000,
321+
"checkpoint_path": "gs://ckpt/18/model_params",
322+
"val_start_at": 18,
323+
"max_steps": 50,
324+
},
325+
)
326+
records = mllog_lib.load_checkpoint_manifest(
327+
manifest_path, check_contiguous=True
328+
)
329+
self.assertEqual([r["step"] for r in records], [18, 19])
330+
331+
# Non-contiguous step should raise ValueError
332+
mllog_lib.append_checkpoint_manifest(
333+
manifest_path,
334+
{
335+
"step": 21,
336+
"samples_count": 5376,
337+
"checkpoint_timestamp_ms": 4000,
338+
"checkpoint_path": "gs://ckpt/21/model_params",
339+
"val_start_at": 18,
340+
"max_steps": 50,
341+
},
342+
)
343+
with self.assertRaisesRegex(ValueError, "Non-contiguous"):
344+
mllog_lib.load_checkpoint_manifest(
345+
manifest_path, check_contiguous=True
346+
)
347+
348+
def test_summarize_includes_pass_at_4(self):
349+
rows = [
350+
{"instance_id": "inst_1", "attempt": i, "resolved": i == 0, "reward": 1.0 if i == 0 else 0.0, "status": "ok"}
351+
for i in range(4)
352+
]
353+
summary = eval_lib.summarize(rows, ["inst_1"], 4)
354+
self.assertIn("4", summary["pass_at_k"])
355+
self.assertAlmostEqual(summary["pass_at_k"]["4"], 1.0)
356+
self.assertAlmostEqual(summary["mean_reward"], 0.25)
357+
358+
def test_offline_eval_rcp_sequence_converged_and_aborted(self):
359+
fake_mllogger = mock.MagicMock()
360+
with (
361+
mock.patch.object(mllog_lib, "mllogger", fake_mllogger),
362+
mock.patch.object(mllog_lib, "_is_master_process", return_value=True),
363+
mock.patch.object(mllog_lib, "_flush_to_gcs_if_needed"),
364+
):
365+
args = types.SimpleNamespace(
366+
batch_size=16, num_generations=16, max_steps=50
367+
)
368+
mllog_lib.train_stop(args, step=50, time_ms=5000)
369+
fake_mllogger.end.assert_called_once_with(
370+
key="block_stop",
371+
metadata={"step": 50, "samples_count": 12800},
372+
time_ms=5000,
373+
)
374+
fake_mllogger.reset_mock()
375+
376+
# Step 18: accuracy 0.68 < 0.69 -> no run_stop
377+
passed_18 = mllog_lib.log_offline_eval_step(
378+
step=18,
379+
samples_count=4608,
380+
eval_accuracy=0.68,
381+
target_accuracy=0.69,
382+
checkpoint_timestamp_ms=1000,
383+
is_last_checkpoint=False,
384+
validation_time=12.5,
385+
)
386+
self.assertFalse(passed_18)
387+
end_keys_18 = [c.kwargs["key"] for c in fake_mllogger.end.call_args_list]
388+
self.assertEqual(end_keys_18, ["eval_stop"])
389+
fake_mllogger.reset_mock()
390+
391+
# Step 19: accuracy 0.71 >= 0.69 -> backdated run_stop(time_ms=2000, status="success") + train_samples=4864
392+
passed_19 = mllog_lib.log_offline_eval_step(
393+
step=19,
394+
samples_count=4864,
395+
eval_accuracy=0.71,
396+
target_accuracy=0.69,
397+
checkpoint_timestamp_ms=2000,
398+
is_last_checkpoint=False,
399+
validation_time=14.0,
400+
)
401+
self.assertTrue(passed_19)
402+
fake_mllogger.end.assert_any_call(
403+
key="run_stop",
404+
metadata={"status": "success", "samples_count": 4864},
405+
time_ms=2000,
406+
)
407+
fake_mllogger.event.assert_any_call(
408+
key="train_samples",
409+
value=4864,
410+
)
411+
fake_mllogger.reset_mock()
412+
413+
# Step 50 (final): accuracy 0.68 < 0.69 -> backdated run_stop(time_ms=5000, status="aborted")
414+
passed_50 = mllog_lib.log_offline_eval_step(
415+
step=50,
416+
samples_count=12800,
417+
eval_accuracy=0.68,
418+
target_accuracy=0.69,
419+
checkpoint_timestamp_ms=5000,
420+
is_last_checkpoint=True,
421+
validation_time=15.0,
422+
)
423+
self.assertFalse(passed_50)
424+
fake_mllogger.end.assert_any_call(
425+
key="run_stop",
426+
metadata={"status": "aborted", "samples_count": 12800},
427+
time_ms=5000,
428+
)
429+
430+
async def test_controller_manifest_loop_stops_on_convergence(self):
431+
with tempfile.TemporaryDirectory() as tmpdir:
432+
manifest_path = str(Path(tmpdir) / "eval_checkpoints.jsonl")
433+
for step, ts_ms in ((18, 1000), (19, 2000), (20, 3000)):
434+
mllog_lib.append_checkpoint_manifest(
435+
manifest_path,
436+
{
437+
"step": step,
438+
"samples_count": step * 256,
439+
"checkpoint_timestamp_ms": ts_ms,
440+
"checkpoint_path": f"gs://ckpt/{step}/model_params",
441+
"val_start_at": 18,
442+
"max_steps": 20,
443+
},
444+
)
445+
446+
evaluated_steps = []
447+
448+
async def fake_single_controller(step_args):
449+
evaluated_steps.append(step_args.checkpoint_step)
450+
reached = step_args.checkpoint_step == 19
451+
return {
452+
"checkpoint_step": step_args.checkpoint_step,
453+
"checkpoint_timestamp_ms": step_args.checkpoint_timestamp_ms,
454+
"samples_count": step_args.samples_count,
455+
"target_reached": reached,
456+
"rcp_logged": True,
457+
}
458+
459+
a = eval_lib.parse_args([
460+
"--checkpoint_manifest_file",
461+
manifest_path,
462+
"--output_dir",
463+
str(Path(tmpdir) / "results"),
464+
])
465+
with (
466+
mock.patch.dict(
467+
sys.modules,
468+
{"tunix.utils": types.SimpleNamespace(mllog_utils=mllog_lib)},
469+
),
470+
mock.patch.object(
471+
eval_lib, "_run_single_controller", side_effect=fake_single_controller
472+
),
473+
):
474+
summary = await eval_lib.run_controller(a)
475+
476+
self.assertEqual(evaluated_steps, [18, 19])
477+
self.assertTrue(summary["target_reached"])
478+
self.assertEqual(summary["checkpoint_step"], 19)
479+
self.assertEqual(summary["checkpoint_timestamp_ms"], 2000)
480+
481+
289482
if __name__ == "__main__":
290483
unittest.main()

0 commit comments

Comments
 (0)