1#![allow(non_snake_case)]
15
16use crate::mamba2::ssd::serial_recalculated::{
17 Mamba2BackendExt,
18 combined_backward::{self, CombinedGrads},
19};
20use burn::backend::autodiff::{
21 Autodiff,
22 checkpoint::{base::Checkpointer, strategy::CheckpointStrategy},
23 grads::Gradients,
24 ops::{Backward, Ops, OpsKind},
25};
26use burn::backend::tensor::FloatTensor;
27use burn::backend::{Backend, BackendTypes};
28
29impl<B: Backend + Mamba2BackendExt, C: CheckpointStrategy> Mamba2BackendExt for Autodiff<B, C> {
30 fn ssd_serial_recalculated(
38 x_bnlhp: FloatTensor<Self>,
39 dt_discretized_bhnl: FloatTensor<Self>,
40 b_bnlhr: FloatTensor<Self>,
41 c_bnlhr: FloatTensor<Self>,
42 d_h: FloatTensor<Self>,
43 initial_state_bhpr: FloatTensor<Self>,
44 a_decay_h: FloatTensor<Self>,
45 ) -> (FloatTensor<Self>, FloatTensor<Self>) {
46 #[derive(Debug)]
48 struct CombinedKernelsBackward;
49
50 #[derive(Clone, Debug)]
51 struct State<B: Backend> {
52 x_bnlhp: <B as BackendTypes>::FloatTensorPrimitive,
53 dt_discretized_bhnl: <B as BackendTypes>::FloatTensorPrimitive,
54 b_bnlhr: <B as BackendTypes>::FloatTensorPrimitive,
55 c_bnlhr: <B as BackendTypes>::FloatTensorPrimitive,
56 d_h: <B as BackendTypes>::FloatTensorPrimitive,
57 initial_state_bhpr: <B as BackendTypes>::FloatTensorPrimitive,
58 a_decay_h: <B as BackendTypes>::FloatTensorPrimitive,
59 flat_len_y_BNLHP: usize,
61 flat_len_final_state_BHPR: usize,
62 shape_x_bnlhp: [usize; 5],
64 shape_dt_discretized_bhnl: [usize; 4],
65 shape_b_bnlhr: [usize; 5],
66 shape_c_bnlhr: [usize; 5],
67 shape_d_h: [usize; 1],
68 shape_initial_state_bhpr: [usize; 4],
69 shape_a_decay_h: [usize; 1],
70 shape_y_bnlhp: [usize; 5], shape_final_state_bhpr: [usize; 4], }
73
74 #[allow(clippy::type_complexity)]
79 impl<B: Backend + Mamba2BackendExt> Backward<B, 7> for CombinedKernelsBackward {
80 type State = State<B>;
81
82 fn backward(
83 self,
84 ops: Ops<Self::State, 7>,
85 grads: &mut Gradients,
86 _checkpointer: &mut Checkpointer,
87 ) {
88 let [
89 node_x_bnlhp,
90 node_dt_discretized_bhnl,
91 node_b_bnlhr,
92 node_c_bnlhr,
93 node_d_h,
94 node_initial_state_bhpr,
95 node_a_decay_h,
96 ] = ops.parents;
97
98 let d_combined: <B as BackendTypes>::FloatTensorPrimitive =
99 grads.consume::<B>(&ops.node);
100
101 let State {
102 x_bnlhp,
103 dt_discretized_bhnl,
104 b_bnlhr,
105 c_bnlhr,
106 d_h,
107 initial_state_bhpr,
108 a_decay_h,
109 flat_len_y_BNLHP,
111 flat_len_final_state_BHPR,
112 shape_x_bnlhp,
114 shape_dt_discretized_bhnl,
115 shape_b_bnlhr,
116 shape_c_bnlhr,
117 shape_d_h,
118 shape_initial_state_bhpr,
119 shape_a_decay_h,
120 shape_y_bnlhp,
122 shape_final_state_bhpr,
123 } = ops.state;
124
125 use crate::utils::fprim::F;
127
128 let x_bnlhp = F::<B, 5>::new(x_bnlhp).reshape(shape_x_bnlhp);
129 let dt_discretized_bhnl =
130 F::<B, 4>::new(dt_discretized_bhnl).reshape(shape_dt_discretized_bhnl);
131 let b_bnlhr = F::<B, 5>::new(b_bnlhr).reshape(shape_b_bnlhr);
132 let c_bnlhr = F::<B, 5>::new(c_bnlhr).reshape(shape_c_bnlhr);
133 let d_h = F::<B, 1>::new(d_h).reshape(shape_d_h);
134 let initial_state_bhpr =
135 F::<B, 4>::new(initial_state_bhpr).reshape(shape_initial_state_bhpr);
136 let a_decay_h = F::<B, 1>::new(a_decay_h).reshape(shape_a_decay_h);
137
138 let (d_y_bnlhp, d_final_state_bhpr) =
140 crate::utils::combined_grad::unflatten_pair::<B, 5, 4>(
141 d_combined,
142 flat_len_y_BNLHP,
143 flat_len_final_state_BHPR,
144 shape_y_bnlhp,
145 shape_final_state_bhpr,
146 );
147
148 let CombinedGrads {
150 d_x_bnlhp,
151 d_dt_discretized_bhnl,
152 d_b_bnlhr,
153 d_c_bnlhr,
154 d_d_h,
155 d_initial_state_bhpr,
156 d_a_decay_h,
157 ..
158 } = combined_backward::combined_backward(
159 F::<B, 5>::new(d_y_bnlhp),
160 F::<B, 4>::new(d_final_state_bhpr),
161 x_bnlhp,
163 dt_discretized_bhnl,
164 b_bnlhr,
165 c_bnlhr,
166 d_h,
167 initial_state_bhpr,
168 a_decay_h,
169 );
170
171 if let Some(n) = node_x_bnlhp {
173 grads.register::<B>(n.id, d_x_bnlhp.inner());
174 }
175 if let Some(n) = node_dt_discretized_bhnl {
176 grads.register::<B>(n.id, d_dt_discretized_bhnl.inner());
177 }
178 if let Some(n) = node_b_bnlhr {
179 grads.register::<B>(n.id, d_b_bnlhr.inner());
180 }
181 if let Some(n) = node_c_bnlhr {
182 grads.register::<B>(n.id, d_c_bnlhr.inner());
183 }
184 if let Some(n) = node_d_h {
185 grads.register::<B>(n.id, d_d_h.inner());
186 }
187 if let Some(n) = node_initial_state_bhpr {
188 grads.register::<B>(n.id, d_initial_state_bhpr.inner());
189 }
190 if let Some(n) = node_a_decay_h {
191 grads.register::<B>(n.id, d_a_decay_h.inner());
192 }
193 }
194 } use burn::backend::TensorMetadata;
200 let [batch, nchunks, chunk_len, nheads, per_head_dim] = x_bnlhp.primitive.shape().dims();
201 let [_, _, _, _nheads_b, state_rank] = b_bnlhr.primitive.shape().dims();
202
203 let flat_len_y_BNLHP = batch * nchunks * chunk_len * nheads * per_head_dim;
204 let flat_len_final_state_BHPR = batch * nheads * per_head_dim * state_rank;
205
206 let shape_x_bnlhp: [usize; 5] = [batch, nchunks, chunk_len, nheads, per_head_dim];
207 let shape_dt_discretized_bhnl: [usize; 4] = [batch, nheads, nchunks, chunk_len];
208 let shape_b_bnlhr: [usize; 5] = [batch, nchunks, chunk_len, nheads, state_rank];
209 let shape_c_bnlhr: [usize; 5] = [batch, nchunks, chunk_len, nheads, state_rank];
210 let shape_d_h: [usize; 1] = [nheads];
211 let shape_initial_state_bhpr: [usize; 4] = [batch, nheads, per_head_dim, state_rank];
212 let shape_a_decay_h: [usize; 1] = [nheads];
213 let shape_y_bnlhp: [usize; 5] = [batch, nchunks, chunk_len, nheads, per_head_dim];
214 let shape_final_state_bhpr: [usize; 4] = [batch, nheads, per_head_dim, state_rank];
215
216 match CombinedKernelsBackward
218 .prepare::<C>([
219 x_bnlhp.node.clone(),
220 dt_discretized_bhnl.node.clone(),
221 b_bnlhr.node.clone(),
222 c_bnlhr.node.clone(),
223 d_h.node.clone(),
224 initial_state_bhpr.node.clone(),
225 a_decay_h.node.clone(),
226 ])
227 .compute_bound()
228 .stateful() {
230 OpsKind::Tracked(prep) => {
231 let (prim_y_bnlhp, prim_final_state_bhpr) = B::ssd_serial_recalculated(
233 x_bnlhp.primitive.clone(),
234 dt_discretized_bhnl.primitive.clone(),
235 b_bnlhr.primitive.clone(),
236 c_bnlhr.primitive.clone(),
237 d_h.primitive.clone(),
238 initial_state_bhpr.primitive.clone(),
239 a_decay_h.primitive.clone(),
240 );
241
242 let (prim_combined, _, _) = crate::utils::combined_grad::flatten_pair::<B>(
245 prim_y_bnlhp,
246 prim_final_state_bhpr,
247 );
248
249 let state = State {
250 x_bnlhp: x_bnlhp.primitive.clone(),
251 dt_discretized_bhnl: dt_discretized_bhnl.primitive.clone(),
252 b_bnlhr: b_bnlhr.primitive.clone(),
253 c_bnlhr: c_bnlhr.primitive.clone(),
254 d_h: d_h.primitive.clone(),
255 initial_state_bhpr: initial_state_bhpr.primitive.clone(),
256 a_decay_h: a_decay_h.primitive.clone(),
257 flat_len_y_BNLHP,
259 flat_len_final_state_BHPR,
260 shape_x_bnlhp, shape_dt_discretized_bhnl, shape_b_bnlhr, shape_c_bnlhr, shape_d_h, shape_initial_state_bhpr, shape_a_decay_h,
262 shape_y_bnlhp, shape_final_state_bhpr,
263 };
264 let tracked_combined: FloatTensor<Autodiff<B, C>> =
265 prep.finish(state, prim_combined);
266
267 let (tracked_y_bnlhp, tracked_final_state_bhpr) =
272 crate::utils::combined_grad::autodiff_unflatten_pair::<B, C, 5, 4>(
273 tracked_combined,
274 flat_len_y_BNLHP,
275 flat_len_final_state_BHPR,
276 shape_y_bnlhp,
277 shape_final_state_bhpr,
278 );
279
280 (
281 tracked_y_bnlhp,
282 tracked_final_state_bhpr,
283 )
284 }
285
286 OpsKind::UnTracked(prep) => {
287 let (prim_y_bnlhp, prim_final_state_bhpr) = B::ssd_serial_recalculated(
289 x_bnlhp.primitive,
290 dt_discretized_bhnl.primitive,
291 b_bnlhr.primitive,
292 c_bnlhr.primitive,
293 d_h.primitive,
294 initial_state_bhpr.primitive,
295 a_decay_h.primitive,
296 );
297
298 let (combined, _, _) = crate::utils::combined_grad::flatten_pair::<B>(
299 prim_y_bnlhp,
300 prim_final_state_bhpr,
301 );
302
303 let tracked_combined: FloatTensor<Autodiff<B, C>> =
304 prep.finish(combined);
305
306 let (tracked_y_bnlhp, tracked_final_state_bhpr) = crate::utils::combined_grad::autodiff_unflatten_pair::<B, C, 5, 4>(
307 tracked_combined,
308 flat_len_y_BNLHP,
309 flat_len_final_state_BHPR,
310 shape_y_bnlhp,
311 shape_final_state_bhpr,
312 );
313
314 (
315 tracked_y_bnlhp,
316 tracked_final_state_bhpr,
317 )
318 }
319 } } }