← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
recurrent_gate_kernels.c
Go to the documentation of this file.
1#ifndef _GNU_SOURCE
2#define _GNU_SOURCE
3#endif
4
5#include "bf16_utils.h"
6#include "ckernel_engine.h"
7
8#include <dlfcn.h>
9#include <math.h>
10#include <pthread.h>
11#include <stdio.h>
12#include <stdlib.h>
13#if defined(__AVX2__) || defined(__AVX512F__)
14#include <immintrin.h>
15#endif
16
17typedef float (*ck_recurrent_libm_f32_fn)(float);
21static void *ck_recurrent_libm_handle = NULL;
22static pthread_once_t ck_recurrent_libm_once = PTHREAD_ONCE_INIT;
23
25{
26 ck_recurrent_libm_handle = dlopen("libm.so.6", RTLD_NOW | RTLD_LOCAL);
34 }
36 fprintf(stderr,
37 "HARD KERNEL CONTRACT FAULT: llama.cpp recurrent softplus "
38 "requires expf/logf from libm.so.6\n");
39 abort();
40 }
41}
42
43static inline float recurrent_softplus(float x) {
45 if (x > 20.0f) {
46 return x;
47 }
48 if (x < -20.0f) {
50 }
52}
53
54static inline float recurrent_sigmoid(float x) {
55 if (x >= 0.0f) {
56 float z = expf(-x);
57 return 1.0f / (1.0f + z);
58 }
59 {
60 float z = expf(x);
61 return z / (1.0f + z);
62 }
63}
64
65void recurrent_dt_gate_forward(const float *alpha,
66 const float *dt_bias,
67 const float *a,
68 float *gate,
69 int rows,
70 int num_heads,
71 int state_dim) {
72 const int dim = num_heads * state_dim;
73 for (int row = 0; row < rows; ++row) {
74 const float *alpha_row = alpha + (size_t) row * (size_t) dim;
75 float *gate_row = gate + (size_t) row * (size_t) dim;
76 for (int col = 0; col < dim; ++col) {
77 const float x = alpha_row[col] + dt_bias[col];
78 gate_row[col] = recurrent_softplus(x) * a[col];
79 }
80 }
81}
82
83void recurrent_dt_gate_expanded_forward(const float *alpha,
84 const float *dt_bias,
85 const float *a,
86 float *gate,
87 int rows,
88 int num_heads,
89 int state_dim) {
90 for (int row = 0; row < rows; ++row) {
91 const float *alpha_row = alpha + (size_t) row * (size_t) num_heads;
92 float *gate_row = gate + (size_t) row * (size_t) num_heads * (size_t) state_dim;
93 for (int h = 0; h < num_heads; ++h) {
94 const float sp = recurrent_softplus(alpha_row[h] + dt_bias[h]);
95 const float *a_head = a + (size_t) h * (size_t) state_dim;
96 float *gate_head = gate_row + (size_t) h * (size_t) state_dim;
97 for (int col = 0; col < state_dim; ++col) {
98 gate_head[col] = sp * a_head[col];
99 }
100 }
101 }
102}
103
104void recurrent_dt_gate_backward(const float *d_gate,
105 const float *alpha,
106 const float *dt_bias,
107 const float *a,
108 float *d_alpha,
109 float *d_dt_bias,
110 float *d_a,
111 int rows,
112 int dim) {
113 for (int col = 0; col < dim; ++col) {
114 d_dt_bias[col] = 0.0f;
115 d_a[col] = 0.0f;
116 }
117
118 for (int row = 0; row < rows; ++row) {
119 const float *d_gate_row = d_gate + (size_t) row * (size_t) dim;
120 const float *alpha_row = alpha + (size_t) row * (size_t) dim;
121 float *d_alpha_row = d_alpha + (size_t) row * (size_t) dim;
122 for (int col = 0; col < dim; ++col) {
123 const float x = alpha_row[col] + dt_bias[col];
124 const float sp = recurrent_softplus(x);
125 const float sig = recurrent_sigmoid(x);
126 const float d_out = d_gate_row[col];
127 d_a[col] += d_out * sp;
128 {
129 const float d_x = d_out * a[col] * sig;
130 d_alpha_row[col] = d_x;
131 d_dt_bias[col] += d_x;
132 }
133 }
134 }
135}
136
137void recurrent_silu_forward(const float *x,
138 float *out,
139 int rows,
140 int dim) {
141 for (int row = 0; row < rows; ++row) {
142 const float *x_row = x + (size_t) row * (size_t) dim;
143 float *out_row = out + (size_t) row * (size_t) dim;
144 for (int col = 0; col < dim; ++col) {
145 const float xv = x_row[col];
146 out_row[col] = xv * recurrent_sigmoid(xv);
147 }
148 }
149}
150
151#if defined(__AVX512F__)
152typedef __m512 (*ck_recurrent_sleef_expf16_fn)(__m512);
153typedef __m512 (*ck_recurrent_sleef_log1pf16_fn)(__m512);
154static ck_recurrent_sleef_expf16_fn ck_recurrent_pytorch_expf16 = NULL;
155static ck_recurrent_sleef_log1pf16_fn ck_recurrent_pytorch_log1pf16 = NULL;
156static void *ck_recurrent_sleef_handle = NULL;
157static pthread_once_t ck_recurrent_sleef_once = PTHREAD_ONCE_INIT;
158
159static void ck_bind_recurrent_pytorch_sleef(void)
160{
161 const char *library = getenv("CK_SLEEF_LIBRARY");
162 if (library && *library) {
163 ck_recurrent_sleef_handle = dlopen(library, RTLD_NOW | RTLD_LOCAL);
164 if (ck_recurrent_sleef_handle) {
165 ck_recurrent_pytorch_expf16 = (ck_recurrent_sleef_expf16_fn)dlsym(
166 ck_recurrent_sleef_handle, "Sleef_expf16_u10");
167 ck_recurrent_pytorch_log1pf16 = (ck_recurrent_sleef_log1pf16_fn)dlsym(
168 ck_recurrent_sleef_handle, "Sleef_log1pf16_u10");
169 }
170 } else {
171 ck_recurrent_pytorch_expf16 =
172 (ck_recurrent_sleef_expf16_fn)dlsym(RTLD_DEFAULT, "Sleef_expf16_u10");
173 ck_recurrent_pytorch_log1pf16 =
174 (ck_recurrent_sleef_log1pf16_fn)dlsym(RTLD_DEFAULT, "Sleef_log1pf16_u10");
175 }
176}
177#endif
178
180 const float *dt_bias,
181 const float *a,
182 float *gate,
183 int rows,
184 int num_heads,
185 int state_dim)
186{
187 if (!alpha || !dt_bias || !a || !gate || rows < 0 || num_heads < 0 || state_dim != 1) {
188 fprintf(stderr,
189 "HARD KERNEL CONTRACT FAULT: invalid PyTorch FP32 recurrent dt-gate arguments\n");
190 abort();
191 }
192#if defined(__AVX512F__)
193 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
194 if (!ck_recurrent_pytorch_expf16 || !ck_recurrent_pytorch_log1pf16) {
195 fprintf(stderr,
196 "HARD KERNEL CONTRACT FAULT: PyTorch FP32 recurrent dt gate requires "
197 "SLEEF Sleef_expf16_u10 and Sleef_log1pf16_u10; set CK_SLEEF_LIBRARY\n");
198 abort();
199 }
200 if ((num_heads & 15) != 0) {
201 fprintf(stderr,
202 "HARD KERNEL CONTRACT FAULT: PyTorch AVX-512 recurrent dt gate requires "
203 "a head count divisible by 16 (got %d)\n",
204 num_heads);
205 abort();
206 }
209 fprintf(stderr,
210 "HARD KERNEL CONTRACT FAULT: PyTorch FP32 recurrent dt gate requires "
211 "log1pf from libm.so.6\n");
212 abort();
213 }
214 const __m512 threshold = _mm512_set1_ps(20.0f);
215 const int count = rows * num_heads;
216 int index = 0;
217 for (; index + 32 <= count; index += 32) {
218 for (int half = 0; half < 2; ++half) {
219 float x_lanes[16] __attribute__((aligned(64)));
220 float a_lanes[16] __attribute__((aligned(64)));
221 const int base = index + half * 16;
222 for (int lane = 0; lane < 16; ++lane) {
223 const int head = (base + lane) % num_heads;
224 x_lanes[lane] = alpha[base + lane] + dt_bias[head];
225 a_lanes[lane] = a[head];
226 }
227 const __m512 x = _mm512_load_ps(x_lanes);
228 const __m512 softplus = _mm512_mask_blend_ps(
229 _mm512_cmp_ps_mask(x, threshold, _CMP_GT_OQ),
230 ck_recurrent_pytorch_log1pf16(ck_recurrent_pytorch_expf16(x)),
231 x);
232 _mm512_storeu_ps(
233 gate + base,
234 _mm512_mul_ps(softplus, _mm512_load_ps(a_lanes)));
235 }
236 }
237 for (; index < count; ++index) {
238 const int head = index % num_heads;
239 const float x = alpha[index] + dt_bias[head];
240 const float softplus = x > 20.0f
241 ? x
243 gate[index] = softplus * a[head];
244 }
245#else
246 fprintf(stderr,
247 "HARD KERNEL CONTRACT FAULT: PyTorch FP32 recurrent dt gate requires AVX-512\n");
248 abort();
249#endif
250}
251
253 float *out,
254 int rows,
255 int dim)
256{
257 if (!x || !out || rows < 0 || dim < 0) {
258 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid PyTorch BF16 recurrent SiLU arguments\n");
259 abort();
260 }
261#if defined(__AVX512F__)
262 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
263 if (!ck_recurrent_pytorch_expf16) {
264 fprintf(stderr,
265 "HARD KERNEL CONTRACT FAULT: PyTorch BF16 recurrent SiLU requires "
266 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
267 abort();
268 }
269#endif
270 for (int row = 0; row < rows; ++row) {
271 const float *src = x + (size_t)row * (size_t)dim;
272 float *dst = out + (size_t)row * (size_t)dim;
273 int col = 0;
274#if defined(__AVX512F__)
275 for (; col + 16 <= dim; col += 16) {
276 float lanes[16] __attribute__((aligned(64)));
277 for (int lane = 0; lane < 16; ++lane) {
278 lanes[lane] = bf16_to_float(float_to_bf16(src[col + lane]));
279 }
280 const __m512 values = _mm512_load_ps(lanes);
281 const __m512 denominator = _mm512_add_ps(
282 _mm512_set1_ps(1.0f),
283 ck_recurrent_pytorch_expf16(
284 _mm512_sub_ps(_mm512_setzero_ps(), values)));
285 _mm512_store_ps(lanes, _mm512_div_ps(values, denominator));
286 for (int lane = 0; lane < 16; ++lane) {
287 dst[col + lane] = bf16_to_float(float_to_bf16(lanes[lane]));
288 }
289 }
290#endif
291 for (; col < dim; ++col) {
292 const float value = bf16_to_float(float_to_bf16(src[col]));
293 const float silu = value / (1.0f + expf(-value));
294 dst[col] = bf16_to_float(float_to_bf16(silu));
295 }
296 }
297}
298
300 float *out,
301 int rows,
302 int dim)
303{
304 if (!x || !out || rows < 0 || dim < 0) {
305 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid BF16-input FP32-output SiLU arguments\n");
306 abort();
307 }
308#if defined(__AVX512F__)
309 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
310 if (!ck_recurrent_pytorch_expf16) {
311 fprintf(stderr,
312 "HARD KERNEL CONTRACT FAULT: PyTorch BF16-input SiLU requires "
313 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
314 abort();
315 }
316#endif
317 const int count = rows * dim;
318 int i = 0;
319#if defined(__AVX512F__)
320 for (; i + 16 <= count; i += 16) {
321 float lanes[16] __attribute__((aligned(64)));
322 for (int lane = 0; lane < 16; ++lane) {
323 lanes[lane] = bf16_to_float(float_to_bf16(x[i + lane]));
324 }
325 const __m512 values = _mm512_load_ps(lanes);
326 const __m512 denominator = _mm512_add_ps(
327 _mm512_set1_ps(1.0f),
328 ck_recurrent_pytorch_expf16(
329 _mm512_sub_ps(_mm512_setzero_ps(), values)));
330 _mm512_storeu_ps(out + i, _mm512_div_ps(values, denominator));
331 }
332#endif
333 for (; i < count; ++i) {
334 const float value = bf16_to_float(float_to_bf16(x[i]));
335 out[i] = value / (1.0f + expf(-value));
336 }
337}
338
340 const float *x,
341 float *out,
342 int rows,
343 int dim)
344{
345 if (!x || !out || rows < 0 || dim < 0) {
346 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid BF16-input FP32-output sigmoid arguments\n");
347 abort();
348 }
349#if defined(__AVX512F__)
350 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
351 if (!ck_recurrent_pytorch_expf16) {
352 fprintf(stderr,
353 "HARD KERNEL CONTRACT FAULT: PyTorch BF16-input sigmoid requires "
354 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
355 abort();
356 }
357#endif
358 const int count = rows * dim;
359 int i = 0;
360#if defined(__AVX512F__)
361 for (; i + 16 <= count; i += 16) {
362 float lanes[16] __attribute__((aligned(64)));
363 for (int lane = 0; lane < 16; ++lane) {
364 lanes[lane] = bf16_to_float(float_to_bf16(x[i + lane]));
365 }
366 const __m512 values = _mm512_load_ps(lanes);
367 const __m512 denominator = _mm512_add_ps(
368 _mm512_set1_ps(1.0f),
369 ck_recurrent_pytorch_expf16(
370 _mm512_sub_ps(_mm512_setzero_ps(), values)));
371 _mm512_storeu_ps(out + i,
372 _mm512_div_ps(_mm512_set1_ps(1.0f), denominator));
373 }
374#endif
375 for (; i < count; ++i) {
376 const float value = bf16_to_float(float_to_bf16(x[i]));
377 out[i] = 1.0f / (1.0f + expf(-value));
378 }
379}
380
381#if defined(__AVX512F__) && defined(__AVX512DQ__)
382/* Match ggml's AVX-512 exp approximation and instruction grouping exactly. */
383static inline __m512 recurrent_ggml_expf_avx512(__m512 x) {
384 const __m512 r = _mm512_set1_ps(0x1.8p23f);
385 const __m512 z = _mm512_fmadd_ps(x, _mm512_set1_ps(0x1.715476p+0f), r);
386 const __m512 n = _mm512_sub_ps(z, r);
387 const __m512 b = _mm512_fnmadd_ps(
388 n, _mm512_set1_ps(0x1.7f7d1cp-20f),
389 _mm512_fnmadd_ps(n, _mm512_set1_ps(0x1.62e4p-1f), x));
390 const __mmask16 d = _mm512_cmp_ps_mask(
391 _mm512_abs_ps(n), _mm512_set1_ps(192.0f), _CMP_GT_OQ);
392 const __m512 u = _mm512_mul_ps(b, b);
393 const __m512 j = _mm512_fmadd_ps(
394 _mm512_fmadd_ps(
395 _mm512_fmadd_ps(
396 _mm512_set1_ps(0x1.0e4020p-7f), b,
397 _mm512_set1_ps(0x1.573e2ep-5f)),
398 u,
399 _mm512_fmadd_ps(
400 _mm512_set1_ps(0x1.555e66p-3f), b,
401 _mm512_set1_ps(0x1.fffdb6p-2f))),
402 u,
403 _mm512_fmadd_ps(
404 _mm512_set1_ps(0x1.ffffecp-1f), b,
405 _mm512_set1_ps(1.0f)));
406 const __m512 res = _mm512_scalef_ps(j, n);
407 if (_mm512_kortestz(d, d)) {
408 return res;
409 }
410 const __m512 zero = _mm512_setzero_ps();
411 const __m512 alt = _mm512_mask_blend_ps(
412 _mm512_cmp_ps_mask(n, zero, _CMP_LE_OQ),
413 _mm512_set1_ps(INFINITY),
414 zero);
415 return _mm512_mask_blend_ps(d, res, alt);
416}
417#endif
418
419#if defined(__AVX2__) && defined(__FMA__)
420/* Match ggml's AVX2 exp approximation exactly; it is the fallback provider ABI. */
421static inline __m256 recurrent_ggml_expf_avx2(__m256 x) {
422 const __m256 r = _mm256_set1_ps(0x1.8p23f);
423 const __m256 z = _mm256_fmadd_ps(x, _mm256_set1_ps(0x1.715476p+0f), r);
424 const __m256 n = _mm256_sub_ps(z, r);
425 const __m256 b = _mm256_fnmadd_ps(
426 n, _mm256_set1_ps(0x1.7f7d1cp-20f),
427 _mm256_fnmadd_ps(n, _mm256_set1_ps(0x1.62e4p-1f), x));
428 const __m256i e = _mm256_slli_epi32(_mm256_castps_si256(z), 23);
429 const __m256 k = _mm256_castsi256_ps(
430 _mm256_add_epi32(e, _mm256_castps_si256(_mm256_set1_ps(1.0f))));
431 const __m256i c = _mm256_castps_si256(
432 _mm256_cmp_ps(_mm256_andnot_ps(_mm256_set1_ps(-0.0f), n),
433 _mm256_set1_ps(126.0f), _CMP_GT_OQ));
434 const __m256 u = _mm256_mul_ps(b, b);
435 const __m256 j = _mm256_fmadd_ps(
436 _mm256_fmadd_ps(
437 _mm256_fmadd_ps(_mm256_set1_ps(0x1.0e4020p-7f), b,
438 _mm256_set1_ps(0x1.573e2ep-5f)),
439 u,
440 _mm256_fmadd_ps(_mm256_set1_ps(0x1.555e66p-3f), b,
441 _mm256_set1_ps(0x1.fffdb6p-2f))),
442 u, _mm256_mul_ps(_mm256_set1_ps(0x1.ffffecp-1f), b));
443 if (!_mm256_movemask_ps(_mm256_castsi256_ps(c))) {
444 return _mm256_fmadd_ps(j, k, k);
445 }
446 const __m256i g = _mm256_and_si256(
447 _mm256_castps_si256(_mm256_cmp_ps(n, _mm256_setzero_ps(), _CMP_LE_OQ)),
448 _mm256_set1_epi32((int) 0x82000000u));
449 const __m256 s1 = _mm256_castsi256_ps(
450 _mm256_add_epi32(g, _mm256_set1_epi32(0x7f000000)));
451 const __m256 s2 = _mm256_castsi256_ps(_mm256_sub_epi32(e, g));
452 const __m256i d = _mm256_castps_si256(
453 _mm256_cmp_ps(_mm256_andnot_ps(_mm256_set1_ps(-0.0f), n),
454 _mm256_set1_ps(192.0f), _CMP_GT_OQ));
455 return _mm256_or_ps(
456 _mm256_and_ps(_mm256_castsi256_ps(d), _mm256_mul_ps(s1, s1)),
457 _mm256_andnot_ps(
458 _mm256_castsi256_ps(d),
459 _mm256_or_ps(
460 _mm256_and_ps(
461 _mm256_castsi256_ps(c),
462 _mm256_mul_ps(_mm256_fmadd_ps(s2, j, s2), s1)),
463 _mm256_andnot_ps(
464 _mm256_castsi256_ps(c), _mm256_fmadd_ps(k, j, k)))));
465}
466#endif
467
468void recurrent_silu_forward_ggml(const float *x,
469 float *out,
470 int rows,
471 int dim) {
472 for (int row = 0; row < rows; ++row) {
473 const float *x_row = x + (size_t) row * (size_t) dim;
474 float *out_row = out + (size_t) row * (size_t) dim;
475 int col = 0;
476#if defined(__AVX512F__) && defined(__AVX512DQ__)
477 for (; col + 16 <= dim; col += 16) {
478 const __m512 xv = _mm512_loadu_ps(x_row + col);
479 const __m512 neg = _mm512_sub_ps(_mm512_setzero_ps(), xv);
480 const __m512 denom = _mm512_add_ps(
481 _mm512_set1_ps(1.0f), recurrent_ggml_expf_avx512(neg));
482 _mm512_storeu_ps(out_row + col, _mm512_div_ps(xv, denom));
483 }
484#elif defined(__AVX2__) && defined(__FMA__)
485 for (; col + 8 <= dim; col += 8) {
486 const __m256 xv = _mm256_loadu_ps(x_row + col);
487 const __m256 neg = _mm256_sub_ps(_mm256_setzero_ps(), xv);
488 const __m256 denom = _mm256_add_ps(
489 _mm256_set1_ps(1.0f), recurrent_ggml_expf_avx2(neg));
490 _mm256_storeu_ps(out_row + col, _mm256_div_ps(xv, denom));
491 }
492#endif
493 float (*volatile llama_expf)(float) = expf;
494 for (; col < dim; ++col) {
495 const float xv = x_row[col];
496 out_row[col] = xv / (1.0f + llama_expf(-xv));
497 }
498 }
499}
500
502 float *out,
503 int rows,
504 int dim) {
505 float (*volatile llama_expf)(float) = expf;
506 for (int row = 0; row < rows; ++row) {
507 const float *x_row = x + (size_t) row * (size_t) dim;
508 float *out_row = out + (size_t) row * (size_t) dim;
509 for (int col = 0; col < dim; ++col) {
510 out_row[col] = 1.0f / (1.0f + llama_expf(-x_row[col]));
511 }
512 }
513}
514
515void recurrent_silu_backward(const float *d_out,
516 const float *x,
517 float *d_x,
518 int rows,
519 int dim) {
520 for (int row = 0; row < rows; ++row) {
521 const float *d_out_row = d_out + (size_t) row * (size_t) dim;
522 const float *x_row = x + (size_t) row * (size_t) dim;
523 float *d_x_row = d_x + (size_t) row * (size_t) dim;
524 for (int col = 0; col < dim; ++col) {
525 const float xv = x_row[col];
526 const float sig = recurrent_sigmoid(xv);
527 d_x_row[col] = d_out_row[col] * (sig + xv * sig * (1.0f - sig));
528 }
529 }
530}
#define RTLD_DEFAULT
static uint16_t float_to_bf16(float f)
Definition bf16_utils.h:90
static float bf16_to_float(uint16_t v)
Definition bf16_utils.h:38
float(* ck_recurrent_libm_f32_fn)(float)
void recurrent_sigmoid_forward_ggml(const float *x, float *out, int rows, int dim)
static ck_recurrent_libm_f32_fn ck_recurrent_llama_logf
void recurrent_silu_forward_pytorch_bf16_input_fp32_output(const float *x, float *out, int rows, int dim)
void recurrent_dt_gate_expanded_forward(const float *alpha, const float *dt_bias, const float *a, float *gate, int rows, int num_heads, int state_dim)
static float recurrent_softplus(float x)
void recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output(const float *x, float *out, int rows, int dim)
void recurrent_silu_forward_ggml(const float *x, float *out, int rows, int dim)
static void * ck_recurrent_libm_handle
void recurrent_silu_forward(const float *x, float *out, int rows, int dim)
static ck_recurrent_libm_f32_fn ck_recurrent_pytorch_log1pf
void recurrent_silu_forward_pytorch_bf16_storage(const float *x, float *out, int rows, int dim)
static void ck_bind_recurrent_llama_libm(void)
static float recurrent_sigmoid(float x)
void recurrent_dt_gate_forward_pytorch_fp32(const float *alpha, const float *dt_bias, const float *a, float *gate, int rows, int num_heads, int state_dim)
static ck_recurrent_libm_f32_fn ck_recurrent_llama_expf
void recurrent_silu_backward(const float *d_out, const float *x, float *d_x, int rows, int dim)
static pthread_once_t ck_recurrent_libm_once
void recurrent_dt_gate_backward(const float *d_gate, const float *alpha, const float *dt_bias, const float *a, float *d_alpha, float *d_dt_bias, float *d_a, int rows, int dim)
void recurrent_dt_gate_forward(const float *alpha, const float *dt_bias, const float *a, float *gate, int rows, int num_heads, int state_dim)
__attribute__((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)
static void silu(float *x, int n)