Skip to content

Commit 44e5093

Browse files
committed
refactor: optimize Mamba3 FP8 memory usage via checkpointing and implement Metal cache clearing on server dispatch
1 parent c8283ef commit 44e5093

12 files changed

Lines changed: 641 additions & 266 deletions

File tree

cppmega_mlx/runtime/path_c_fusion_schedules.py

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
DESCRIPTOR_PORTABLE_KERNEL_BUFFER_LIMIT = 31
115115
DESCRIPTOR_SHARED_SCRATCH_SPILL_THRESHOLD_BYTES = 4 * 1024
116116
DESCRIPTOR_SHARED_SCRATCH_BUDGET_BYTES = 24 * 1024
117+
MAMBA3_BWD_REPLAY_CHECKPOINT_INTERVAL = 64
117118
_DESCRIPTOR_ROOT_READS_MARKER = "cppmega_path_c_root_reads"
118119
_DESCRIPTOR_ROOT_WRITES_MARKER = "cppmega_path_c_root_writes"
119120
_EXACT_ROW_PHASED_BACKWARD_OPS = frozenset(
@@ -1420,7 +1421,11 @@ def build_path_c_descriptor_prim_func(
14201421
)
14211422
if validated_loop_policy == DESCRIPTOR_LOOP_POLICY_ROW_PHASED_HIDDEN:
14221423
prim_func = prim_func.with_attr("tl.fusion.disable_tir_simplify", True)
1423-
owner_output_param_indices = tuple(range(len(physical_abi_plan.param_lines)))
1424+
owner_output_param_indices = tuple(
1425+
idx
1426+
for idx, param in enumerate(prim_func.params)
1427+
if param in prim_func.buffer_map
1428+
)
14241429
if owner_output_param_indices:
14251430
prim_func = prim_func.with_attr(
14261431
"tilelang_out_idx",
@@ -3028,10 +3033,7 @@ def _spill_large_shared_scratch_to_abi(
30283033
byte_count = _flattened_extent(shape) * _DTYPE_NBYTES[dtype]
30293034
total_shared_bytes += byte_count
30303035
scratch_name = match.group("name")
3031-
force_scratch_abi = (
3032-
scratch_name in DESCRIPTOR_ROW_PHASED_BWD_SCRATCH_ABI_BUFFERS
3033-
or scratch_name.endswith("_mamba3_h_steps")
3034-
)
3036+
force_scratch_abi = scratch_name in DESCRIPTOR_ROW_PHASED_BWD_SCRATCH_ABI_BUFFERS
30353037
if (
30363038
byte_count > DESCRIPTOR_SHARED_SCRATCH_SPILL_THRESHOLD_BYTES
30373039
or force_scratch_abi
@@ -9139,7 +9141,8 @@ def _append_row_phased_mamba3_bwd_body(
91399141
out_inner = _scratch_name(node, "mamba3_out_inner")
91409142
y_skip = _scratch_name(node, "mamba3_y_skip")
91419143
out_inner_grad = _scratch_name(node, "mamba3_out_inner_grad")
9142-
h_steps = _scratch_name(node, "mamba3_h_steps")
9144+
h_checkpoint = _scratch_name(node, "mamba3_h_checkpoint")
9145+
angle_checkpoint = _scratch_name(node, "mamba3_angle_checkpoint")
91439146
h_prev = _scratch_name(node, "mamba3_h_prev")
91449147
h_next = _scratch_name(node, "mamba3_h_next")
91459148
dh = _scratch_name(node, "mamba3_dh")
@@ -9177,6 +9180,9 @@ def _append_row_phased_mamba3_bwd_body(
91779180
time_rev = _scratch_name(node, "time_rev")
91789181
time_idx = _scratch_name(node, "time_idx")
91799182
replay_time = _scratch_name(node, "replay_time")
9183+
replay_offset = _scratch_name(node, "replay_offset")
9184+
checkpoint_idx = _scratch_name(node, "checkpoint_idx")
9185+
checkpoint_start = _scratch_name(node, "checkpoint_start")
91809186
src_row = _scratch_name(node, "src_row")
91819187
src_hist = _scratch_name(node, "src_hist")
91829188
hidden_loop = _scratch_name(node, "hidden_loop")
@@ -9209,6 +9215,9 @@ def _append_row_phased_mamba3_bwd_body(
92099215
conv_b_offset = inner_dim
92109216
conv_c_offset = inner_dim + bc_dim
92119217
rot_dim = min(state_dim, 2 * rope_angles)
9218+
checkpoint_interval = MAMBA3_BWD_REPLAY_CHECKPOINT_INTERVAL
9219+
checkpoint_count = (sequence_length + checkpoint_interval - 1) // checkpoint_interval
9220+
angle_extent = heads * rope_angles
92129221

92139222
def _mamba3_hidden_expr(time_expr: str, hidden_expr: str) -> str:
92149223
return _node_indexed_canonical_or_positional_input_expr(
@@ -9246,7 +9255,6 @@ def _mamba3_emit_recompute_row(
92469255
level: int,
92479256
update_angle: bool,
92489257
update_state: bool,
9249-
compute_h_prev: bool,
92509258
) -> None:
92519259
body.append(f"{indent * level}for {proj_dim} in T.serial(0, {in_proj_dim}):")
92529260
body.append(f"{indent * (level + 1)}{sum_scratch}[0] = 0.0")
@@ -9555,11 +9563,6 @@ def _mamba3_emit_recompute_row(
95559563
f"{indent * (level + 2)}{state_idx} = "
95569564
f"{head} * {head_dim * state_dim} + {hidden_dim} * {state_dim} + {state_loop}"
95579565
)
9558-
if compute_h_prev:
9559-
body.append(
9560-
f"{indent * (level + 2)}{h_prev}[{state_idx}] = "
9561-
f"{h_steps}[{time_expr} * {state_extent} + {state_idx}]"
9562-
)
95639566
if update_state:
95649567
body.append(
95659568
f"{indent * (level + 2)}{h_next}[{state_idx}] = "
@@ -9591,7 +9594,7 @@ def _mamba3_emit_recompute_row(
95919594
f"{y_skip}[{feature}] * {projected}[{z_offset} + {feature}] * {scalar0}[0]"
95929595
)
95939596

9594-
body.append(f"{indent * 3}# mamba3_mimo_bwd_policy: exact_reverse_recompute")
9597+
body.append(f"{indent * 3}# mamba3_mimo_bwd_policy: exact_reverse_checkpoint_replay")
95959598
for name, extent in (
95969599
(projected, in_proj_dim),
95979600
(project_grad, in_proj_dim),
@@ -9601,7 +9604,8 @@ def _mamba3_emit_recompute_row(
96019604
(out_inner, inner_dim),
96029605
(y_skip, inner_dim),
96039606
(out_inner_grad, inner_dim),
9604-
(h_steps, (sequence_length + 1) * state_extent),
9607+
(h_checkpoint, (checkpoint_count + 1) * state_extent),
9608+
(angle_checkpoint, (checkpoint_count + 1) * angle_extent),
96059609
(h_prev, state_extent),
96069610
(h_next, state_extent),
96079611
(dh, state_extent),
@@ -9630,7 +9634,11 @@ def _mamba3_emit_recompute_row(
96309634
(angle_cumsum, heads * rope_angles),
96319635
(angle_grad, heads * rope_angles),
96329636
):
9633-
alloc = "T.alloc_shared" if name == h_steps else "T.alloc_local"
9637+
alloc = (
9638+
"T.alloc_shared"
9639+
if name in {h_checkpoint, angle_checkpoint}
9640+
else "T.alloc_local"
9641+
)
96349642
body.append(f"{indent * 3}{name} = {alloc}(({extent},), \"float32\")")
96359643
for scalar in (
96369644
stage_grad,
@@ -9687,32 +9695,67 @@ def _mamba3_emit_recompute_row(
96879695
default="0.0",
96889696
)
96899697
body.append(f"{indent * 6}{h_next}[{state_idx}] = {h0_expr}")
9690-
body.append(f"{indent * 6}{h_steps}[{state_idx}] = {h0_expr}")
9698+
body.append(f"{indent * 6}{h_checkpoint}[{state_idx}] = {h0_expr}")
96919699
body.append(f"{indent * 6}{dh}[{state_idx}] = 0.0")
96929700
body.append(f"{indent * 5}for {grad_flat} in T.serial(0, {heads * rope_angles}):")
96939701
body.append(f"{indent * 6}{angle_cumsum}[{grad_flat}] = 0.0")
9702+
body.append(f"{indent * 6}{angle_checkpoint}[{grad_flat}] = 0.0")
96949703
body.append(f"{indent * 6}{angle_grad}[{grad_flat}] = 0.0")
96959704
body.append(f"{indent * 5}for {replay_time} in T.serial(0, {sequence_length}):")
96969705
_mamba3_emit_recompute_row(
96979706
replay_time,
96989707
level=6,
96999708
update_angle=True,
97009709
update_state=True,
9701-
compute_h_prev=False,
97029710
)
9703-
body.append(f"{indent * 6}for {state_idx} in T.serial(0, {state_extent}):")
9711+
body.append(f"{indent * 6}if (({replay_time} + 1) % {checkpoint_interval}) == 0:")
9712+
body.append(
9713+
f"{indent * 7}{checkpoint_idx} = ({replay_time} + 1) // {checkpoint_interval}"
9714+
)
9715+
body.append(f"{indent * 7}for {state_idx} in T.serial(0, {state_extent}):")
97049716
body.append(
9705-
f"{indent * 7}{h_steps}[({replay_time} + 1) * {state_extent} + {state_idx}] = "
9717+
f"{indent * 8}{h_checkpoint}[{checkpoint_idx} * {state_extent} + {state_idx}] = "
97069718
f"{h_next}[{state_idx}]"
97079719
)
9720+
body.append(f"{indent * 7}for {grad_flat} in T.serial(0, {angle_extent}):")
9721+
body.append(
9722+
f"{indent * 8}{angle_checkpoint}[{checkpoint_idx} * {angle_extent} + {grad_flat}] = "
9723+
f"{angle_cumsum}[{grad_flat}]"
9724+
)
97089725
body.append(f"{indent * 5}for {time_rev} in T.serial(0, {sequence_length}):")
97099726
body.append(f"{indent * 6}{time_idx} = {sequence_length - 1} - {time_rev}")
9727+
body.append(f"{indent * 6}{checkpoint_idx} = {time_idx} // {checkpoint_interval}")
9728+
body.append(
9729+
f"{indent * 6}{checkpoint_start} = {checkpoint_idx} * {checkpoint_interval}"
9730+
)
9731+
body.append(f"{indent * 6}for {state_idx} in T.serial(0, {state_extent}):")
9732+
body.append(
9733+
f"{indent * 7}{h_next}[{state_idx}] = "
9734+
f"{h_checkpoint}[{checkpoint_idx} * {state_extent} + {state_idx}]"
9735+
)
9736+
body.append(f"{indent * 6}for {grad_flat} in T.serial(0, {angle_extent}):")
9737+
body.append(
9738+
f"{indent * 7}{angle_cumsum}[{grad_flat}] = "
9739+
f"{angle_checkpoint}[{checkpoint_idx} * {angle_extent} + {grad_flat}]"
9740+
)
9741+
body.append(f"{indent * 6}for {replay_offset} in T.serial(0, {checkpoint_interval}):")
9742+
body.append(
9743+
f"{indent * 7}{replay_time} = {checkpoint_start} + {replay_offset}"
9744+
)
9745+
body.append(f"{indent * 7}if {replay_time} < {time_idx}:")
9746+
_mamba3_emit_recompute_row(
9747+
replay_time,
9748+
level=8,
9749+
update_angle=True,
9750+
update_state=True,
9751+
)
9752+
body.append(f"{indent * 6}for {state_idx} in T.serial(0, {state_extent}):")
9753+
body.append(f"{indent * 7}{h_prev}[{state_idx}] = {h_next}[{state_idx}]")
97109754
_mamba3_emit_recompute_row(
97119755
time_idx,
97129756
level=6,
9713-
update_angle=False,
9714-
update_state=False,
9715-
compute_h_prev=True,
9757+
update_angle=True,
9758+
update_state=True,
97169759
)
97179760
body.append(f"{indent * 6}for {proj_dim} in T.serial(0, {in_proj_dim}):")
97189761
body.append(f"{indent * 7}{project_grad}[{proj_dim}] = 0.0")

cppmega_v4/jsonrpc/server.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,19 @@ async def ws(socket: WebSocket) -> None:
289289

290290

291291
async def _dispatch(payload: dict, cache: LRUCache):
292-
if payload.get("method") == "pipeline.run":
293-
return await asyncio.to_thread(dispatch, payload, cache=cache)
294-
return dispatch(payload, cache=cache)
292+
try:
293+
if payload.get("method") == "pipeline.run":
294+
return await asyncio.to_thread(dispatch, payload, cache=cache)
295+
return dispatch(payload, cache=cache)
296+
finally:
297+
try:
298+
import mlx.core as mx
299+
if mx.metal.is_available():
300+
mx.metal.clear_cache()
301+
except ImportError:
302+
pass
303+
except Exception:
304+
pass
295305

296306

297307
_BUILD_ID: str | None = None

0 commit comments

Comments
 (0)