You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(pr2): mark PR-2 LANDED+MEASURED — bs=4xseq=4096 OOM(114G)->fits(64.93G)
Update FUSED-PIPELINE-ROADMAP §5 PR-2 (status + measured peak table + numeric
equivalence + honest floor) and MEGATRON-VS-MLX-PATHS (seq=4096 now reachable:
64.93 GiB peak / 514 tok/s live on gb10, was 'cannot run'). The 116 GB was a
loop/graph problem, fixed by env-gated numerically-equivalent grad accumulation
in one_step_train (commit 05e53d8), not a kernel change.
**Highest mem ROI, smallest diff.** Independent of PR-1; can land in parallel.
138
+
**STATUS (2026-06-02): LANDED + MEASURED ON gb10 (commit `05e53d8`). bs=4×seq=4096 went OOM→FITS.**
138
139
-**First step:** wire `grad_accum_steps` (scaffolding at `checkpoint.py:101-104`) into `one_step_train` (`loop.py`) with `mx.eval(grads)`-and-drop per microbatch; add `mx.eval(hidden_states)` barrier after each attention-only checkpointed layer; switch optimizer to `optimizers_quantized.py`; call `maybe_clear_cache_after_step` (`runtime/memory.py:191`) each step.
139
140
-**Unblocks:** seq=4096 step 116 GB → 30–40 GB on gb10 — makes the real production config (bs4×seq4096) *reachable* on a single box without waiting for Relax.
-`one_step_train` (`loop.py`): `grad_accum_steps` kwarg / `GRAD_ACCUM_STEPS` env (default 1 = byte-identical to the prior single-`mx.eval` step). When N>1: split the batch into N microbatches, run `value_and_grad` per micro, `mx.eval` the **token-weighted** running accumulator as a free-barrier, drop each micro's fwd/bwd graph before the next. Optional `clear_cache` hook.
144
+
-`hybrid_lm.py`: opt-in `mx.eval(hidden_states)` after each grad-checkpointed layer (`CPPMEGA_MLX_CHECKPOINT_EVAL_BARRIER=1`, default OFF) — converts the previously no-op checkpoint into a real free-barrier.
**Numeric equivalence (RULE #1, verified on Mac, `scratch/pr2_grad_accum_equivalence.py`):** N=4 micro vs full-batch → loss abs-diff **0.0**, worst grad rel-diff **2.8e-7**, post-step param rel-diff **1.2e-7**; checkpoint barrier ON vs OFF → grads **bitwise identical**. Token-weighting (`weight = n_i / N_total`) makes `sum_i weight_i · grad_i` exactly the full-batch grad for a token-mean loss. 165 loop/compiled/gradient/checkpoint tests pass.
**Result:** the real `bs=4×seq=4096` step went from **OOM (>114 GB, watchdog-killed)** to **67.94 GiB — it now fits on a single gb10**, loss finite + decreasing (10.54→10.29), ~526 tok/s. Active working set drops **linearly with N** (6.06 GiB @ N=4 → 3.05 GiB @ N=8), confirming the activation lever. The ~64–68 GiB *peak* is the **allocator high-water mark, not the live set** (active is 3–6 GiB) — `clear_cache` trims but the CUDA-MLX allocator/graph-cache holds the high-water mark. **Honest floor:** loop-level levers land the seq=4096 step at **~62–68 GiB peak — well under the 100 GB box budget, above the 30–40 GiB stretch target.** Reaching 30–40 GiB *peak* needs allocator-limit pinning (`apply_memory_limit_plan` / `MLX_CUDA_GRAPH_CACHE_SIZE`) and/or the durable Relax whole-step liveness (§4); the dominant residual term is the **allocator high-water mark / static param+optimizer block**, not activations (which grad-accum already collapses).
159
+
141
160
### PR-3 — Auto-fusion / block-registry (the Megatron-spec equivalent)
142
161
**The composability layer.** Depends on PR-1's brick descriptors existing.
143
162
-**First step:** define the `TransformerLayerSubmodules`-style block-spec dataclass; register `mamba3`/`mla`/`moe` as `FusionBlockDescriptor`s (`fusion.py:64`) with paired `_bwd`; register the fused chain signatures in `FusionScheduleRegistry` (`fusion.py:295`); drive `plan_path_c_direct_fusion_chain_for_region` candidates from `select_longest` (`fusion.py:344`) matches instead of the fixed signature. Audit template-execution for any try/except that masks a broken chain (RULE #1).
0 commit comments