Skip to content

Commit f523359

Browse files
committed
feat(v5-g06): extras.memory_peak_bytes via mx.metal.get_peak_memory
Closes V5-G06 / cppmega-mlx-cn3. UI MemoryBar estimate vs real peak never compared. stage_train now brackets train loop with mx.metal.reset_peak_memory() + get_peak_memory(); reports extras.memory_peak_bytes. 1/1 e2e green; 43 stage_train pytest unchanged.
1 parent 47405d2 commit f523359

2 files changed

Lines changed: 39 additions & 0 deletions

File tree

cppmega_v4/runner/stages.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,15 @@ def _count(tree: Any) -> int:
634634
"num_clips": 0,
635635
}
636636

637+
# G06: memory peak instrumentation — bracket train loop with
638+
# reset_peak_memory + get_peak_memory; extras.memory_peak_bytes.
639+
memory_peak_bytes: int | None = None
640+
try:
641+
if hasattr(mx, "metal"):
642+
mx.metal.reset_peak_memory()
643+
except Exception:
644+
pass
645+
637646
losses: list[float] = []
638647
lr_trajectory: list[float] = []
639648
# Snapshot one leaf with a real gradient; fixed first-leaf probes can
@@ -690,6 +699,12 @@ def _count(tree: Any) -> int:
690699
mx.eval(all_modules.parameters(), opt.state)
691700
losses.append(float(loss.item()))
692701

702+
try:
703+
if hasattr(mx, "metal"):
704+
memory_peak_bytes = int(mx.metal.get_peak_memory())
705+
except Exception:
706+
pass
707+
693708
after_flat = dict(nn.utils.tree_flatten(all_modules.parameters()))
694709
delta = 0.0
695710
if probe_key is not None and probe_before is not None:
@@ -775,6 +790,7 @@ def _count(tree: Any) -> int:
775790
"side_channels_observed": side_channels_observed,
776791
"graph_diff": graph_diff,
777792
"gradient_clip": clip_extras,
793+
"memory_peak_bytes": memory_peak_bytes,
778794
"mtp": _compute_mtp_extras(
779795
all_modules, mtp_k, mtp_betas, vocab_size,
780796
batch, seq, hidden, targets,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// G06: stage_train brackets train loop with reset_peak_memory +
2+
// get_peak_memory; extras.memory_peak_bytes populated.
3+
4+
import { test, expect } from "@playwright/test";
5+
import { gotoApp, selectPreset, closeModal } from "../fixtures";
6+
7+
test("G06: extras.memory_peak_bytes populated and > 0", async ({ page }) => {
8+
test.setTimeout(60_000);
9+
await gotoApp(page);
10+
await selectPreset(page, "llama3_8b");
11+
await page.getByTestId("run-pipeline-toggle").click();
12+
await page.getByTestId("run-pipeline-train").click();
13+
const modal = page.getByTestId("run-result-modal");
14+
await modal.waitFor({ timeout: 60_000 });
15+
await page.getByTestId("run-result-expand-train").click();
16+
const peakText = await page.getByTestId(
17+
"run-result-extras-train-memory_peak_bytes").textContent();
18+
const peak = parseInt(peakText?.trim() ?? "0", 10);
19+
// M1/M2/M3 Mac Metal backend reports peak memory; should be at
20+
// least 1MB after a 2-step llama3_8b train with 64-hidden bricks.
21+
expect(peak).toBeGreaterThan(1_000_000);
22+
await closeModal(page);
23+
});

0 commit comments

Comments
 (0)