10 static int cached = -1;
12 const char *v = getenv(
"CK_DEBUG_MAMBA");
13 cached = (v && v[0] && v[0] !=
'0') ? 1 : 0;
22 size_t finite = 0, nan = 0, inf = 0;
23 float min_v = 0.0f, max_v = 0.0f;
24 for (
size_t i = 0; i < n; ++i) {
28 }
else if (!isfinite(v)) {
31 if (finite == 0 || v < min_v) min_v = v;
32 if (finite == 0 || v > max_v) max_v = v;
36 fprintf(stderr,
"[CK_DEBUG_MAMBA] %s finite=%zu/%zu nan=%zu inf=%zu min=%g max=%g\n",
37 name, finite, n, nan, inf, finite ? (
double)min_v : 0.0, finite ? (double)max_v : 0.0);
42 const float z = expf(-x);
43 return 1.0f / (1.0f + z);
46 const float z = expf(x);
47 return z / (1.0f + z);
62 return log1pf(expf(x));
74 if (!projected || !gate || !hidden_bc || !dt ||
75 rows <= 0 || d_mlp < 0 || intermediate_dim <= 0 || conv_dim <= 0 || num_heads <= 0) {
79 const int projection_dim = 2 * d_mlp + intermediate_dim + conv_dim + num_heads;
80 const int gate_offset = 2 * d_mlp;
81 const int hidden_bc_offset = gate_offset + intermediate_dim;
82 const int dt_offset = hidden_bc_offset + conv_dim;
85 for (
int row = 0; row < rows; ++row) {
86 const float *src = projected + (size_t)row * (
size_t)projection_dim;
87 memcpy(gate + (
size_t)row * (
size_t)intermediate_dim,
89 (
size_t)intermediate_dim *
sizeof(
float));
90 memcpy(hidden_bc + (
size_t)row * (
size_t)conv_dim,
91 src + hidden_bc_offset,
92 (
size_t)conv_dim *
sizeof(
float));
93 memcpy(dt + (
size_t)row * (
size_t)num_heads,
95 (
size_t)num_heads *
sizeof(
float));
113 if (!state_in || !x || !weight || !conv_out || !state_out ||
114 rows <= 0 || conv_dim <= 0 || kernel_size <= 0 ||
115 channel_begin < 0 || channel_begin >= channel_end ||
116 channel_end > conv_dim) {
124 for (
int ch = channel_begin; ch < channel_end; ++ch) {
125 float state_work[(size_t)kernel_size];
126 const size_t base = (size_t)ch * (
size_t)kernel_size;
127 memcpy(state_work, state_in + base,
128 (
size_t)kernel_size *
sizeof(
float));
129 for (
int row = 0; row < rows; ++row) {
130 for (
int k = 0; k < kernel_size - 1; ++k) {
131 state_work[(size_t)k] = state_work[(
size_t)k + 1u];
133 state_work[(size_t)kernel_size - 1u] =
134 x[(
size_t)row * (size_t)conv_dim + (
size_t)ch];
136 float acc = bias ? bias[ch] : 0.0f;
137 for (
int k = 0; k < kernel_size; ++k) {
138 acc += state_work[(size_t)k] *
139 weight[(
size_t)ch * (size_t)kernel_size + (
size_t)k];
141 conv_out[(size_t)row * (
size_t)conv_dim + (size_t)ch] =
mamba2_silu_f32(acc);
143 memcpy(state_out + base, state_work,
144 (
size_t)kernel_size *
sizeof(
float));
157 if (!state_in || !x || !weight || !conv_out || !state_out ||
158 rows <= 0 || conv_dim <= 0 || kernel_size <= 0) {
165 state_in, x, weight, bias, conv_out, state_out,
166 rows, conv_dim, kernel_size, 0, conv_dim);
172 const float *dt_bias,
178 if (!dt || !dt_out || rows <= 0 || num_heads <= 0) {
184 for (
int row = 0; row < rows; ++row) {
185 for (
int h = 0; h < num_heads; ++h) {
186 float v = dt[(size_t)row * (
size_t)num_heads + (size_t)h];
191 if (dt_min < dt_max) {
194 }
else if (v > dt_max) {
198 dt_out[(size_t)row * (
size_t)num_heads + (size_t)h] = v;
218 if (!state_in || !x || !dt || !a || !b || !c || !d || !state_out || !y ||
219 rows <= 0 || num_heads <= 0 || head_dim <= 0 || state_dim <= 0 || num_groups <= 0) {
223 const int packed_xbc = (x == b && b == c);
224 const size_t inner_dim = (size_t)num_heads * (
size_t)head_dim;
225 const size_t bc_dim = (size_t)num_groups * (
size_t)state_dim;
226 const size_t packed_stride = inner_dim + 2u * bc_dim;
228 for (
int row = 0; row < rows; ++row) {
229 const float *packed_row = packed_xbc ? x + (size_t)row * packed_stride : NULL;
230 for (
int h = 0; h < num_heads; ++h) {
231 const int heads_per_group = (num_heads + num_groups - 1) / num_groups;
232 int group = h / heads_per_group;
233 if (group >= num_groups) group = num_groups - 1;
234 const float dt_h = dt[(size_t)row * (
size_t)num_heads + (size_t)h];
235 const float d_a = expf(dt_h * a[h]);
236 const float d_h = d[h];
237 const float *b_row = packed_xbc
238 ? (packed_row + inner_dim + (size_t)group * (
size_t)state_dim)
239 : (b + ((size_t)row * (
size_t)num_groups + (size_t)group) * (size_t)state_dim);
240 const float *c_row = packed_xbc
241 ? (packed_row + inner_dim + bc_dim + (size_t)group * (
size_t)state_dim)
242 : (c + ((size_t)row * (
size_t)num_groups + (size_t)group) * (size_t)state_dim);
244 for (
int hd = 0; hd < head_dim; ++hd) {
245 const size_t x_idx = ((size_t)row * (
size_t)num_heads + (size_t)h) * (size_t)head_dim + (
size_t)hd;
246 const float x_val = packed_xbc ? packed_row[(size_t)h * (
size_t)head_dim + (size_t)hd] : x[x_idx];
247 const size_t state_base =
248 (((size_t)row * (
size_t)num_heads + (size_t)h) * (size_t)head_dim + (
size_t)hd) *
251 for (
int s = 0; s < state_dim; ++s) {
252 const size_t si = state_base + (size_t)s;
253 const float new_state = state_in[si] * d_a + dt_h * b_row[s] * x_val;
254 state_out[si] = new_state;
255 acc += new_state * c_row[s];
257 y[x_idx] = acc + d_h * x_val;
281 if (!state_init || !x || !dt || !a || !b || !c || !d || !state_out || !y ||
282 batch <= 0 || seq_len <= 0 || num_heads <= 0 || head_dim <= 0 ||
283 state_dim <= 0 || num_groups <= 0 || head_begin < 0 ||
284 head_begin >= head_end || head_end > num_heads) {
288 const size_t state_per_batch = (size_t)num_heads * (
size_t)head_dim * (size_t)state_dim;
289 const size_t head_state = (size_t)head_dim * (
size_t)state_dim;
290 const int packed_xbc = (x == b && b == c);
291 const size_t inner_dim = (size_t)num_heads * (
size_t)head_dim;
292 const size_t bc_dim = (size_t)num_groups * (
size_t)state_dim;
293 const size_t packed_stride = inner_dim + 2u * bc_dim;
294 const int heads_per_group = (num_heads + num_groups - 1) / num_groups;
296 for (
int bs = 0; bs < batch; ++bs) {
297 float *state_batch = state_out + (size_t)bs * state_per_batch;
298 memcpy(state_batch + (
size_t)head_begin * head_state,
299 state_init + (
size_t)bs * state_per_batch + (
size_t)head_begin * head_state,
300 (
size_t)(head_end - head_begin) * head_state *
sizeof(
float));
301 for (
int t = 0; t < seq_len; ++t) {
302 for (
int h = head_begin; h < head_end; ++h) {
308 int group = h / heads_per_group;
309 if (group >= num_groups) group = num_groups - 1;
310 const float dt_h = dt[((size_t)bs * (
size_t)seq_len + (size_t)t) * (size_t)num_heads + (
size_t)h];
311 const float d_a = expf(dt_h * a[h]);
312 const float d_h = d[h];
313 const float *packed_row = x + ((size_t)bs * (
size_t)seq_len + (size_t)t) * packed_stride;
314 const float *b_row = packed_xbc
315 ? (packed_row + inner_dim + (size_t)group * (
size_t)state_dim)
316 : (b + (((size_t)bs * (
size_t)seq_len + (size_t)t) * (size_t)num_groups + (
size_t)group) * (
size_t)state_dim);
317 const float *c_row = packed_xbc
318 ? (packed_row + inner_dim + bc_dim + (size_t)group * (
size_t)state_dim)
319 : (c + (((size_t)bs * (
size_t)seq_len + (size_t)t) * (size_t)num_groups + (
size_t)group) * (
size_t)state_dim);
321 for (
int hd = 0; hd < head_dim; ++hd) {
322 const size_t x_idx = (((size_t)bs * (
size_t)seq_len + (size_t)t) * (size_t)num_heads + (
size_t)h) * (
size_t)head_dim + (size_t)hd;
323 const float x_val = packed_xbc ? packed_row[(size_t)h * (
size_t)head_dim + (size_t)hd] : x[x_idx];
324 const size_t state_base = ((size_t)h * (
size_t)head_dim + (size_t)hd) * (size_t)state_dim;
326 for (
int st = 0; st < state_dim; ++st) {
327 const size_t si = state_base + (size_t)st;
328 const float new_state = state_batch[si] * d_a + dt_h * b_row[st] * x_val;
329 state_batch[si] = new_state;
330 acc += new_state * c_row[st];
332 y[x_idx] = acc + d_h * x_val;
354 if (!state_init || !x || !dt || !a || !b || !c || !d || !state_out || !y ||
355 batch <= 0 || seq_len <= 0 || num_heads <= 0 || head_dim <= 0 || state_dim <= 0 || num_groups <= 0) {
359 const size_t state_per_batch = (size_t)num_heads * (
size_t)head_dim * (size_t)state_dim;
361 ck_mamba_debug_finite(
"scan.x[0]", x, (
size_t)num_heads * (
size_t)head_dim + 2u * (
size_t)num_groups * (
size_t)state_dim);
366 state_init, x, dt, a, b, c, d, state_out, y,
367 batch, seq_len, num_heads, head_dim, state_dim, num_groups,
381 if (!x || !gate || !weight || !out || rows <= 0 || inner_dim <= 0 || group_size <= 0) {
388 for (
int row = 0; row < rows; ++row) {
389 const float *x_row = x + (size_t)row * (
size_t)inner_dim;
390 const float *gate_row = gate + (size_t)row * (
size_t)inner_dim;
391 float *out_row = out + (size_t)row * (
size_t)inner_dim;
395 if (
end > inner_dim) {
400 for (
int col =
start; col <
end; ++col) {
404 const float inv_rms = 1.0f / sqrtf(ms / (
float)count + eps);
405 for (
int col =
start; col <
end; ++col) {
407 out_row[col] = gated * inv_rms * weight[col];
void mamba2_selective_state_update_decode_f32(const float *state_in, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int rows, int num_heads, int head_dim, int state_dim, int num_groups)
void mamba2_in_proj_split_f32(const float *projected, float *gate, float *hidden_bc, float *dt, int rows, int d_mlp, int intermediate_dim, int conv_dim, int num_heads)
static float mamba2_silu_f32(float x)
static float mamba2_sigmoid_f32(float x)
static int ck_mamba_debug_enabled(void)
void mamba2_conv1d_f32_channel_range(const float *state_in, const float *x, const float *weight, const float *bias, float *conv_out, float *state_out, int rows, int conv_dim, int kernel_size, int channel_begin, int channel_end)
static void ck_mamba_debug_finite(const char *name, const float *x, size_t n)
static float mamba2_softplus_f32(float x)
void mamba2_dt_softplus_f32(const float *dt, const float *dt_bias, float *dt_out, int rows, int num_heads, float dt_min, float dt_max)
void mamba2_selective_scan_f32(const float *state_init, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int batch, int seq_len, int num_heads, int head_dim, int state_dim, int num_groups)
void mamba2_selective_scan_f32_head_range(const float *state_init, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int batch, int seq_len, int num_heads, int head_dim, int state_dim, int num_groups, int head_begin, int head_end)
void mamba2_conv1d_decode_f32(const float *state_in, const float *x, const float *weight, const float *bias, float *conv_out, float *state_out, int rows, int conv_dim, int kernel_size)
void mamba2_rmsnorm_gate_f32(const float *x, const float *gate, const float *weight, float *out, int rows, int inner_dim, int group_size, float eps)