Skip to content

Commit dd732cc

Browse files
committed
fix: complete side-channel train path and path-c gates
1 parent 6f418cb commit dd732cc

16 files changed

Lines changed: 2487 additions & 106 deletions

cppmega_mlx/nn/_tilelang/m2rnn_path_c.py

Lines changed: 105 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2613,8 +2613,12 @@ def _post_residual_gate_bwd_kernel_for(
26132613
g_dim = g_heads * v_dim
26142614
g_offset = projected_dim - g_dim
26152615
features = total_heads * v_dim
2616-
lanes = batch * seq * features
2617-
threads = _threads_for(features)
2616+
dy_lanes = batch * seq * features
2617+
dconv_lanes = batch * seq * conv_dim
2618+
dD_lanes = total_heads * v_dim
2619+
dprojected_lanes = batch * seq * projected_dim
2620+
lanes = dy_lanes + dconv_lanes + dD_lanes + dprojected_lanes
2621+
threads = _threads_for(max(features, conv_dim, projected_dim))
26182622
accum_dtype = "float32"
26192623

26202624
@T.prim_func
@@ -2633,51 +2637,106 @@ def bwd(
26332637
tid = T.get_thread_binding(0)
26342638
lane = bx * threads + tid
26352639
if lane < lanes:
2636-
feature = lane % features
2637-
t = (lane // features) % seq
2638-
b = lane // (features * seq)
2639-
h = feature // v_dim
2640-
vv = feature % v_dim
2641-
v_src = h // v_group
2642-
v_index = v_offset + v_src * v_dim + vv
2643-
g_flat = feature // g_repeat
2644-
g_index = g_offset + g_flat
2645-
dpost_val = T.cast(dpost[b, t, feature], accum_dtype)
2646-
g_val = T.cast(projected[b, t, g_index], accum_dtype)
2647-
sig_g = T.alloc_var(T.float32, init=0.0)
2648-
if g_val >= 0.0:
2649-
sig_g = 1.0 / (1.0 + T.exp(-g_val))
2640+
if lane < dy_lanes:
2641+
feature = lane % features
2642+
t = (lane // features) % seq
2643+
b = lane // (features * seq)
2644+
h = feature // v_dim
2645+
vv = feature % v_dim
2646+
g_flat = feature // g_repeat
2647+
g_index = g_offset + g_flat
2648+
dpost_val = T.cast(dpost[b, t, feature], accum_dtype)
2649+
g_val = T.cast(projected[b, t, g_index], accum_dtype)
2650+
sig_g = T.alloc_var(T.float32, init=0.0)
2651+
if g_val >= 0.0:
2652+
sig_g = 1.0 / (1.0 + T.exp(-g_val))
2653+
else:
2654+
sig_g = T.exp(g_val)
2655+
sig_g = sig_g / (1.0 + sig_g)
2656+
dy_recurrent[b, t, h, vv] = T.cast(
2657+
dpost_val * g_val * sig_g,
2658+
grad_dtype,
2659+
)
2660+
elif lane < dy_lanes + dconv_lanes:
2661+
local = lane - dy_lanes
2662+
c = local % conv_dim
2663+
t = (local // conv_dim) % seq
2664+
b = local // (conv_dim * seq)
2665+
acc = T.alloc_var(T.float32, init=0.0)
2666+
if c >= v_offset and c < v_offset + v_heads * v_dim:
2667+
v_rel = c - v_offset
2668+
v_src = v_rel // v_dim
2669+
vv = v_rel % v_dim
2670+
for local_h in T.serial(v_group):
2671+
h = v_src * v_group + local_h
2672+
feature = h * v_dim + vv
2673+
g_flat = feature // g_repeat
2674+
g_index = g_offset + g_flat
2675+
dpost_val = T.cast(dpost[b, t, feature], accum_dtype)
2676+
g_val = T.cast(projected[b, t, g_index], accum_dtype)
2677+
sig_g = T.alloc_var(T.float32, init=0.0)
2678+
if g_val >= 0.0:
2679+
sig_g = 1.0 / (1.0 + T.exp(-g_val))
2680+
else:
2681+
sig_g = T.exp(g_val)
2682+
sig_g = sig_g / (1.0 + sig_g)
2683+
dskipped = dpost_val * g_val * sig_g
2684+
d_val = T.cast(D[h, vv], accum_dtype)
2685+
acc = acc + dskipped * d_val
2686+
dconv_input[b, t, c] = T.cast(acc, grad_dtype)
2687+
elif lane < dy_lanes + dconv_lanes + dD_lanes:
2688+
local = lane - dy_lanes - dconv_lanes
2689+
h = local // v_dim
2690+
vv = local % v_dim
2691+
v_src = h // v_group
2692+
v_index = v_offset + v_src * v_dim + vv
2693+
acc = T.alloc_var(T.float32, init=0.0)
2694+
for b in T.serial(batch):
2695+
for t in T.serial(seq):
2696+
feature = h * v_dim + vv
2697+
g_flat = feature // g_repeat
2698+
g_index = g_offset + g_flat
2699+
dpost_val = T.cast(dpost[b, t, feature], accum_dtype)
2700+
g_val = T.cast(projected[b, t, g_index], accum_dtype)
2701+
sig_g = T.alloc_var(T.float32, init=0.0)
2702+
if g_val >= 0.0:
2703+
sig_g = 1.0 / (1.0 + T.exp(-g_val))
2704+
else:
2705+
sig_g = T.exp(g_val)
2706+
sig_g = sig_g / (1.0 + sig_g)
2707+
dskipped = dpost_val * g_val * sig_g
2708+
v_val = T.cast(conv_input[b, t, v_index], accum_dtype)
2709+
acc = acc + dskipped * v_val
2710+
dD[h, vv] = T.cast(acc, grad_dtype)
26502711
else:
2651-
sig_g = T.exp(g_val)
2652-
sig_g = sig_g / (1.0 + sig_g)
2653-
silu_g = g_val * sig_g
2654-
silu_dg = sig_g * (1.0 + g_val * (1.0 - sig_g))
2655-
y_val = T.cast(y[b, t, h, vv], accum_dtype)
2656-
v_val = T.cast(conv_input[b, t, v_index], accum_dtype)
2657-
d_val = T.cast(D[h, vv], accum_dtype)
2658-
skipped = y_val + v_val * d_val
2659-
dskipped = dpost_val * silu_g
2660-
2661-
T.atomic_add(
2662-
dy_recurrent[b, t, h, vv],
2663-
dskipped,
2664-
memory_order="relaxed",
2665-
)
2666-
T.atomic_add(
2667-
dconv_input[b, t, v_index],
2668-
dskipped * d_val,
2669-
memory_order="relaxed",
2670-
)
2671-
T.atomic_add(
2672-
dD[h, vv],
2673-
dskipped * v_val,
2674-
memory_order="relaxed",
2675-
)
2676-
T.atomic_add(
2677-
dprojected[b, t, g_index],
2678-
dpost_val * skipped * silu_dg,
2679-
memory_order="relaxed",
2680-
)
2712+
local = lane - dy_lanes - dconv_lanes - dD_lanes
2713+
p = local % projected_dim
2714+
t = (local // projected_dim) % seq
2715+
b = local // (projected_dim * seq)
2716+
acc = T.alloc_var(T.float32, init=0.0)
2717+
if p >= g_offset and p < g_offset + g_dim:
2718+
g_flat = p - g_offset
2719+
g_val = T.cast(projected[b, t, p], accum_dtype)
2720+
sig_g = T.alloc_var(T.float32, init=0.0)
2721+
if g_val >= 0.0:
2722+
sig_g = 1.0 / (1.0 + T.exp(-g_val))
2723+
else:
2724+
sig_g = T.exp(g_val)
2725+
sig_g = sig_g / (1.0 + sig_g)
2726+
silu_dg = sig_g * (1.0 + g_val * (1.0 - sig_g))
2727+
for r in T.serial(g_repeat):
2728+
feature = g_flat * g_repeat + r
2729+
h = feature // v_dim
2730+
vv = feature % v_dim
2731+
v_src = h // v_group
2732+
v_index = v_offset + v_src * v_dim + vv
2733+
dpost_val = T.cast(dpost[b, t, feature], accum_dtype)
2734+
y_val = T.cast(y[b, t, h, vv], accum_dtype)
2735+
v_val = T.cast(conv_input[b, t, v_index], accum_dtype)
2736+
d_val = T.cast(D[h, vv], accum_dtype)
2737+
skipped = y_val + v_val * d_val
2738+
acc = acc + dpost_val * skipped * silu_dg
2739+
dprojected[b, t, p] = T.cast(acc, grad_dtype)
26812740

26822741
bwd = _with_global_symbol(
26832742
bwd,

cppmega_mlx/runtime/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
restore_rng_state,
2727
seed_all,
2828
)
29+
from cppmega_mlx.runtime import torch_compile_backend
2930

3031
__all__ = [
3132
"AppliedMemoryLimits",
@@ -46,4 +47,5 @@
4647
"restore_rng_state",
4748
"seed_all",
4849
"selected_path",
50+
"torch_compile_backend",
4951
]

0 commit comments

Comments
 (0)