← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
mamba2_kernels.c File Reference
#include "ckernel_engine.h"
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

Go to the source code of this file.

Functions

static int ck_mamba_debug_enabled (void)
 
static void ck_mamba_debug_finite (const char *name, const float *x, size_t n)
 
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_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)
 
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_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)
 
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)
 
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_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)
 
static float mamba2_sigmoid_f32 (float x)
 
static float mamba2_silu_f32 (float x)
 
static float mamba2_softplus_f32 (float x)
 

Function Documentation

◆ ck_mamba_debug_enabled()

static int ck_mamba_debug_enabled ( void  )
static

Definition at line 9 of file mamba2_kernels.c.

9 {
10 static int cached = -1;
11 if (cached < 0) {
12 const char *v = getenv("CK_DEBUG_MAMBA");
13 cached = (v && v[0] && v[0] != '0') ? 1 : 0;
14 }
15 return cached;
16}

Referenced by ck_mamba_debug_finite().

◆ ck_mamba_debug_finite()

static void ck_mamba_debug_finite ( const char *  name,
const float *  x,
size_t  n 
)
static

Definition at line 18 of file mamba2_kernels.c.

18 {
19 if (!ck_mamba_debug_enabled() || !x || n == 0) {
20 return;
21 }
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) {
25 const float v = x[i];
26 if (isnan(v)) {
27 ++nan;
28 } else if (!isfinite(v)) {
29 ++inf;
30 } else {
31 if (finite == 0 || v < min_v) min_v = v;
32 if (finite == 0 || v > max_v) max_v = v;
33 ++finite;
34 }
35 }
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);
38}
static int ck_mamba_debug_enabled(void)

References ck_mamba_debug_enabled().

Referenced by mamba2_conv1d_decode_f32(), mamba2_dt_softplus_f32(), mamba2_in_proj_split_f32(), mamba2_rmsnorm_gate_f32(), and mamba2_selective_scan_f32().

◆ mamba2_conv1d_decode_f32()

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 
)

Definition at line 148 of file mamba2_kernels.c.

156 {
157 if (!state_in || !x || !weight || !conv_out || !state_out ||
158 rows <= 0 || conv_dim <= 0 || kernel_size <= 0) {
159 return;
160 }
161
162 ck_mamba_debug_finite("conv.state_in", state_in, (size_t)conv_dim * (size_t)kernel_size);
163 ck_mamba_debug_finite("conv.x[0]", x, (size_t)conv_dim);
165 state_in, x, weight, bias, conv_out, state_out,
166 rows, conv_dim, kernel_size, 0, conv_dim);
167 ck_mamba_debug_finite("conv.out[0]", conv_out, (size_t)conv_dim);
168 ck_mamba_debug_finite("conv.state_out", state_out, (size_t)conv_dim * (size_t)kernel_size);
169}
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)

References ck_mamba_debug_finite(), and mamba2_conv1d_f32_channel_range().

◆ mamba2_conv1d_f32_channel_range()

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 
)

Definition at line 102 of file mamba2_kernels.c.

112 {
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) {
117 return;
118 }
119
120 /* Time rows are dependent, but channels are independent. Keeping one
121 * channel's rolling state local preserves its exact update order while
122 * allowing disjoint channel ranges to execute concurrently.
123 */
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];
132 }
133 state_work[(size_t)kernel_size - 1u] =
134 x[(size_t)row * (size_t)conv_dim + (size_t)ch];
135
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];
140 }
141 conv_out[(size_t)row * (size_t)conv_dim + (size_t)ch] = mamba2_silu_f32(acc);
142 }
143 memcpy(state_out + base, state_work,
144 (size_t)kernel_size * sizeof(float));
145 }
146}
static float mamba2_silu_f32(float x)

References mamba2_silu_f32().

Referenced by mamba2_conv1d_decode_f32().

◆ mamba2_dt_softplus_f32()

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 
)

Definition at line 171 of file mamba2_kernels.c.

177 {
178 if (!dt || !dt_out || rows <= 0 || num_heads <= 0) {
179 return;
180 }
181
182 ck_mamba_debug_finite("dt.in[0]", dt, (size_t)num_heads);
183 ck_mamba_debug_finite("dt.bias", dt_bias, (size_t)num_heads);
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];
187 if (dt_bias) {
188 v += dt_bias[h];
189 }
190 v = mamba2_softplus_f32(v);
191 if (dt_min < dt_max) {
192 if (v < dt_min) {
193 v = dt_min;
194 } else if (v > dt_max) {
195 v = dt_max;
196 }
197 }
198 dt_out[(size_t)row * (size_t)num_heads + (size_t)h] = v;
199 }
200 }
201 ck_mamba_debug_finite("dt.out[0]", dt_out, (size_t)num_heads);
202}
static float mamba2_softplus_f32(float x)

References ck_mamba_debug_finite(), and mamba2_softplus_f32().

◆ mamba2_in_proj_split_f32()

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 
)

Definition at line 65 of file mamba2_kernels.c.

73 {
74 if (!projected || !gate || !hidden_bc || !dt ||
75 rows <= 0 || d_mlp < 0 || intermediate_dim <= 0 || conv_dim <= 0 || num_heads <= 0) {
76 return;
77 }
78
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;
83
84 ck_mamba_debug_finite("split.projected[0]", projected, (size_t)projection_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,
88 src + gate_offset,
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,
94 src + dt_offset,
95 (size_t)num_heads * sizeof(float));
96 }
97 ck_mamba_debug_finite("split.gate[0]", gate, (size_t)intermediate_dim);
98 ck_mamba_debug_finite("split.hidden_bc[0]", hidden_bc, (size_t)conv_dim);
99 ck_mamba_debug_finite("split.dt[0]", dt, (size_t)num_heads);
100}

References ck_mamba_debug_finite().

◆ mamba2_rmsnorm_gate_f32()

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 
)

Definition at line 373 of file mamba2_kernels.c.

380 {
381 if (!x || !gate || !weight || !out || rows <= 0 || inner_dim <= 0 || group_size <= 0) {
382 return;
383 }
384
385 ck_mamba_debug_finite("rmsgate.x[0]", x, (size_t)inner_dim);
386 ck_mamba_debug_finite("rmsgate.gate[0]", gate, (size_t)inner_dim);
387 ck_mamba_debug_finite("rmsgate.weight", weight, (size_t)inner_dim);
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;
392
393 for (int start = 0; start < inner_dim; start += group_size) {
394 int end = start + group_size;
395 if (end > inner_dim) {
396 end = inner_dim;
397 }
398 const int count = end - start;
399 float ms = 0.0f;
400 for (int col = start; col < end; ++col) {
401 const float gated = x_row[col] * mamba2_silu_f32(gate_row[col]);
402 ms += gated * gated;
403 }
404 const float inv_rms = 1.0f / sqrtf(ms / (float)count + eps);
405 for (int col = start; col < end; ++col) {
406 const float gated = x_row[col] * mamba2_silu_f32(gate_row[col]);
407 out_row[col] = gated * inv_rms * weight[col];
408 }
409 }
410 }
411 ck_mamba_debug_finite("rmsgate.out[0]", out, (size_t)inner_dim);
412}
uint32_t end
Definition utf8.c:215
uint32_t start
Definition utf8.c:214

References ck_mamba_debug_finite(), end, mamba2_silu_f32(), and start.

◆ mamba2_selective_scan_f32()

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 
)

Definition at line 339 of file mamba2_kernels.c.

353 {
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) {
356 return;
357 }
358
359 const size_t state_per_batch = (size_t)num_heads * (size_t)head_dim * (size_t)state_dim;
360 ck_mamba_debug_finite("scan.state_init", state_init, state_per_batch);
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);
362 ck_mamba_debug_finite("scan.dt[0]", dt, (size_t)num_heads);
363 ck_mamba_debug_finite("scan.a", a, (size_t)num_heads);
364 ck_mamba_debug_finite("scan.d", d, (size_t)num_heads);
366 state_init, x, dt, a, b, c, d, state_out, y,
367 batch, seq_len, num_heads, head_dim, state_dim, num_groups,
368 0, num_heads);
369 ck_mamba_debug_finite("scan.state_out", state_out, (size_t)batch * state_per_batch);
370 ck_mamba_debug_finite("scan.y[0]", y, (size_t)num_heads * (size_t)head_dim);
371}
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)

References ck_mamba_debug_finite(), and mamba2_selective_scan_f32_head_range().

◆ mamba2_selective_scan_f32_head_range()

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 
)

Definition at line 264 of file mamba2_kernels.c.

280 {
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) {
285 return;
286 }
287
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;
295
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) {
303 /* Nemotron-H prefill and decode both use the repeating
304 * B/C group map from repeat_interleave semantics. Keeping
305 * this in sync is required for full-prefix and incremental
306 * decode equivalence.
307 */
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);
320
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;
325 float acc = 0.0f;
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];
331 }
332 y[x_idx] = acc + d_h * x_val;
333 }
334 }
335 }
336 }
337}

Referenced by mamba2_selective_scan_f32().

◆ mamba2_selective_state_update_decode_f32()

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 
)

Definition at line 204 of file mamba2_kernels.c.

217 {
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) {
220 return;
221 }
222
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;
227
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);
243
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) *
249 (size_t)state_dim;
250 float acc = 0.0f;
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];
256 }
257 y[x_idx] = acc + d_h * x_val;
258 }
259 }
260 }
261}

◆ mamba2_sigmoid_f32()

static float mamba2_sigmoid_f32 ( float  x)
inlinestatic

Definition at line 40 of file mamba2_kernels.c.

40 {
41 if (x >= 0.0f) {
42 const float z = expf(-x);
43 return 1.0f / (1.0f + z);
44 }
45 {
46 const float z = expf(x);
47 return z / (1.0f + z);
48 }
49}

Referenced by mamba2_silu_f32().

◆ mamba2_silu_f32()

static float mamba2_silu_f32 ( float  x)
inlinestatic

Definition at line 51 of file mamba2_kernels.c.

51 {
52 return x * mamba2_sigmoid_f32(x);
53}
static float mamba2_sigmoid_f32(float x)

References mamba2_sigmoid_f32().

Referenced by mamba2_conv1d_f32_channel_range(), and mamba2_rmsnorm_gate_f32().

◆ mamba2_softplus_f32()

static float mamba2_softplus_f32 ( float  x)
inlinestatic

Definition at line 55 of file mamba2_kernels.c.

55 {
56 if (x > 20.0f) {
57 return x;
58 }
59 if (x < -20.0f) {
60 return expf(x);
61 }
62 return log1pf(expf(x));
63}

Referenced by mamba2_dt_softplus_f32().