Skip to content

Commit 3fa1c0a

Browse files
committed
Implement MLPerf v6.1 RCP logging and deferred offline evaluation for DeepSWE
1 parent 8ca356c commit 3fa1c0a

13 files changed

Lines changed: 1546 additions & 56 deletions

File tree

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

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,5 +286,228 @@ 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")
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+
train_samples_calls = [
408+
c for c in fake_mllogger.event.call_args_list if c.kwargs.get("key") == "train_samples"
409+
]
410+
self.assertEqual(len(train_samples_calls), 0)
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+
def test_mlperf_6_1_0_init_print_disclosures(self):
431+
fake_mllogger = mock.MagicMock()
432+
with (
433+
mock.patch.object(mllog_lib, "mllogger", fake_mllogger),
434+
mock.patch.object(mllog_lib, "_is_master_process", return_value=True),
435+
mock.patch.object(mllog_lib, "_flush_to_gcs_if_needed"),
436+
):
437+
args = types.SimpleNamespace(
438+
batch_size=16,
439+
num_generations=16,
440+
max_steps=50,
441+
max_prompt_length=4096,
442+
max_response_length=61440,
443+
target_accuracy=0.69,
444+
)
445+
mllog_lib.init_print(args, train_dataset=list(range(1000)))
446+
emitted = {
447+
c.kwargs["key"]: c.kwargs["value"]
448+
for c in fake_mllogger.event.call_args_list
449+
}
450+
self.assertEqual(emitted["eval_samples"], 251)
451+
self.assertEqual(emitted["max_sequence_length"], 65536)
452+
self.assertEqual(emitted["opt_adamw_beta_2"], 0.999)
453+
self.assertEqual(emitted["opt_adamw_weight_decay"], 0.0)
454+
self.assertAlmostEqual(emitted["opt_gradient_clip_norm"], 0.125)
455+
self.assertEqual(emitted["lowest_numerical_precision_in_linear"], "bfloat16")
456+
self.assertEqual(emitted["lowest_numerical_precision_in_attn"], "bfloat16")
457+
self.assertEqual(emitted["lowest_numerical_precision_in_comm"], "bfloat16")
458+
self.assertEqual(emitted["config_filename"], "qwen35_397b_grpo")
459+
460+
async def test_controller_manifest_loop_stops_on_convergence(self):
461+
with tempfile.TemporaryDirectory() as tmpdir:
462+
manifest_path = str(Path(tmpdir) / "eval_checkpoints.jsonl")
463+
for step, ts_ms in ((18, 1000), (19, 2000), (20, 3000)):
464+
mllog_lib.append_checkpoint_manifest(
465+
manifest_path,
466+
{
467+
"step": step,
468+
"samples_count": step * 256,
469+
"checkpoint_timestamp_ms": ts_ms,
470+
"checkpoint_path": f"gs://ckpt/{step}/model_params",
471+
"val_start_at": 18,
472+
"max_steps": 20,
473+
},
474+
)
475+
476+
evaluated_steps = []
477+
478+
async def fake_single_controller(step_args):
479+
evaluated_steps.append(step_args.checkpoint_step)
480+
reached = step_args.checkpoint_step == 19
481+
return {
482+
"checkpoint_step": step_args.checkpoint_step,
483+
"checkpoint_timestamp_ms": step_args.checkpoint_timestamp_ms,
484+
"samples_count": step_args.samples_count,
485+
"target_reached": reached,
486+
"rcp_logged": True,
487+
}
488+
489+
a = eval_lib.parse_args([
490+
"--checkpoint_manifest_file",
491+
manifest_path,
492+
"--output_dir",
493+
str(Path(tmpdir) / "results"),
494+
])
495+
with (
496+
mock.patch.dict(
497+
sys.modules,
498+
{"tunix.utils": types.SimpleNamespace(mllog_utils=mllog_lib)},
499+
),
500+
mock.patch.object(
501+
eval_lib, "_run_single_controller", side_effect=fake_single_controller
502+
),
503+
):
504+
summary = await eval_lib.run_controller(a)
505+
506+
self.assertEqual(evaluated_steps, [18, 19])
507+
self.assertTrue(summary["target_reached"])
508+
self.assertEqual(summary["checkpoint_step"], 19)
509+
self.assertEqual(summary["checkpoint_timestamp_ms"], 2000)
510+
511+
289512
if __name__ == "__main__":
290513
unittest.main()

0 commit comments

Comments
 (0)