spark_model/layers/ops/
ssm_ssd.rs1#![allow(unused_imports)]
7
8use anyhow::Result;
9use spark_runtime::gpu::{DevicePtr, GpuBackend, KernelHandle};
10use spark_runtime::kernel_args::{KernelLaunch, div_ceil};
11
12use super::*;
13
14pub const SSD_L: u32 = 64;
16pub const SSD_PT: u32 = 64;
18
19#[allow(clippy::too_many_arguments)]
21pub fn mamba2_ssd_cumsum(
22 gpu: &dyn GpuBackend,
23 kernel: KernelHandle,
24 dt_raw: DevicePtr,
25 a_log: DevicePtr,
26 dt_bias: DevicePtr,
27 dt_out: DevicePtr,
28 da_cs: DevicePtr,
29 seq_len: u32,
30 num_heads: u32,
31 nchunks: u32,
32 batch_size: u32,
33 dt_stride: u32,
34 dt_min: f32,
35 dt_max: f32,
36 stream: u64,
37) -> Result<()> {
38 KernelLaunch::new(gpu, kernel)
39 .grid([nchunks, num_heads, batch_size])
40 .block([SSD_L, 1, 1])
41 .arg_ptr(dt_raw)
42 .arg_ptr(a_log)
43 .arg_ptr(dt_bias)
44 .arg_ptr(dt_out)
45 .arg_ptr(da_cs)
46 .arg_u32(seq_len)
47 .arg_u32(num_heads)
48 .arg_u32(nchunks)
49 .arg_u32(dt_stride)
50 .arg_f32(dt_min)
51 .arg_f32(dt_max)
52 .launch(stream)
53}
54
55#[allow(clippy::too_many_arguments)]
57pub fn mamba2_ssd_bmm(
58 gpu: &dyn GpuBackend,
59 kernel: KernelHandle,
60 b_proj: DevicePtr,
61 c_proj: DevicePtr,
62 cb: DevicePtr,
63 seq_len: u32,
64 nchunks: u32,
65 n_groups: u32,
66 state_size: u32,
67 batch_size: u32,
68 bc_stride: u32,
69 stream: u64,
70) -> Result<()> {
71 let smem = 2 * SSD_L * state_size * 2;
73 KernelLaunch::new(gpu, kernel)
74 .grid([nchunks, n_groups, batch_size])
75 .block([128, 1, 1])
76 .shared_mem(smem)
77 .arg_ptr(b_proj)
78 .arg_ptr(c_proj)
79 .arg_ptr(cb)
80 .arg_u32(seq_len)
81 .arg_u32(nchunks)
82 .arg_u32(n_groups)
83 .arg_u32(state_size)
84 .arg_u32(bc_stride)
85 .launch(stream)
86}
87
88pub const MAX_DYNAMIC_SMEM: u32 = 101_376;
93
94pub fn ssd_scan_smem(state_size: u32) -> u32 {
98 SSD_PT * (state_size + 1) * 4
99 + 2 * SSD_L * state_size * 2
100 + 2 * SSD_L * state_size * 2
101 + 2 * SSD_L * SSD_PT * 2
102 + 2 * SSD_L * 4
103 + 2 * SSD_L * 4
104}
105
106pub fn ssd_scan_fits(state_size: u32) -> bool {
114 ssd_scan_smem(state_size) <= MAX_DYNAMIC_SMEM
115}
116
117#[allow(clippy::too_many_arguments)]
120pub fn mamba2_ssd_scan(
121 gpu: &dyn GpuBackend,
122 kernel: KernelHandle,
123 h_state: DevicePtr,
124 x: DevicePtr,
125 b_proj: DevicePtr,
126 c_proj: DevicePtr,
127 d_param: DevicePtr,
128 dt_f32: DevicePtr,
129 da_cs: DevicePtr,
130 cb: DevicePtr,
131 output: DevicePtr,
132 seq_len: u32,
133 num_heads: u32,
134 head_dim: u32,
135 state_size: u32,
136 n_groups: u32,
137 nchunks: u32,
138 batch_size: u32,
139 x_stride: u32,
140 bc_stride: u32,
141 y_stride: u32,
142 stream: u64,
143) -> Result<()> {
144 let smem = ssd_scan_smem(state_size);
148 KernelLaunch::new(gpu, kernel)
149 .grid([num_heads, head_dim / SSD_PT, batch_size])
150 .block([512, 1, 1]) .shared_mem(smem)
152 .arg_ptr(h_state)
153 .arg_ptr(x)
154 .arg_ptr(b_proj)
155 .arg_ptr(c_proj)
156 .arg_ptr(d_param)
157 .arg_ptr(dt_f32)
158 .arg_ptr(da_cs)
159 .arg_ptr(cb)
160 .arg_ptr(output)
161 .arg_u32(seq_len)
162 .arg_u32(num_heads)
163 .arg_u32(head_dim)
164 .arg_u32(state_size)
165 .arg_u32(n_groups)
166 .arg_u32(nchunks)
167 .arg_u32(x_stride)
168 .arg_u32(bc_stride)
169 .arg_u32(y_stride)
170 .launch(stream)
171}