32#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__)
36#if defined(__ARM_NEON) || defined(__aarch64__)
46 return 1.0f / (1.0f + expf(-x));
53#if defined(__AVX512F__)
55static inline __m512 exp512_fast(__m512 x) {
57 x = _mm512_max_ps(x, _mm512_set1_ps(-88.0f));
58 x = _mm512_min_ps(x, _mm512_set1_ps(88.0f));
61 const __m512 log2e = _mm512_set1_ps(1.4426950408889634f);
62 __m512 z = _mm512_mul_ps(x, log2e);
65 __m512 zf = _mm512_roundscale_ps(z, _MM_FROUND_TO_NEAREST_INT);
66 __m512 f = _mm512_sub_ps(z, zf);
69 const __m512 c0 = _mm512_set1_ps(1.0f);
70 const __m512 c1 = _mm512_set1_ps(0.6931471805599453f);
71 const __m512 c2 = _mm512_set1_ps(0.2402265069591007f);
72 const __m512 c3 = _mm512_set1_ps(0.05550410866482158f);
73 const __m512 c4 = _mm512_set1_ps(0.009618129107628478f);
75 __m512 poly = _mm512_fmadd_ps(f, c4, c3);
76 poly = _mm512_fmadd_ps(f, poly, c2);
77 poly = _mm512_fmadd_ps(f, poly, c1);
78 poly = _mm512_fmadd_ps(f, poly, c0);
81 __m512i zi = _mm512_cvtps_epi32(zf);
82 zi = _mm512_add_epi32(zi, _mm512_set1_epi32(127));
83 zi = _mm512_slli_epi32(zi, 23);
84 __m512 scale = _mm512_castsi512_ps(zi);
86 return _mm512_mul_ps(poly, scale);
90static inline __m512 sigmoid512_fast(__m512 x) {
91 __m512 neg_x = _mm512_sub_ps(_mm512_setzero_ps(), x);
92 __m512 exp_neg = exp512_fast(neg_x);
93 __m512 one = _mm512_set1_ps(1.0f);
94 return _mm512_div_ps(one, _mm512_add_ps(one, exp_neg));
100static inline __m256 exp256_fast(__m256 x) {
102 x = _mm256_max_ps(x, _mm256_set1_ps(-88.0f));
103 x = _mm256_min_ps(x, _mm256_set1_ps(88.0f));
106 const __m256 log2e = _mm256_set1_ps(1.4426950408889634f);
107 __m256 z = _mm256_mul_ps(x, log2e);
110 __m256 zf = _mm256_round_ps(z, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
111 __m256 f = _mm256_sub_ps(z, zf);
114 const __m256 c0 = _mm256_set1_ps(1.0f);
115 const __m256 c1 = _mm256_set1_ps(0.6931471805599453f);
116 const __m256 c2 = _mm256_set1_ps(0.2402265069591007f);
117 const __m256 c3 = _mm256_set1_ps(0.05550410866482158f);
118 const __m256 c4 = _mm256_set1_ps(0.009618129107628478f);
120 __m256 poly = _mm256_fmadd_ps(f, c4, c3);
121 poly = _mm256_fmadd_ps(f, poly, c2);
122 poly = _mm256_fmadd_ps(f, poly, c1);
123 poly = _mm256_fmadd_ps(f, poly, c0);
126 __m256i zi = _mm256_cvtps_epi32(zf);
127 zi = _mm256_add_epi32(zi, _mm256_set1_epi32(127));
128 zi = _mm256_slli_epi32(zi, 23);
129 __m256 scale = _mm256_castsi256_ps(zi);
131 return _mm256_mul_ps(poly, scale);
135static inline __m256 sigmoid256_fast(__m256 x) {
136 __m256 neg_x = _mm256_sub_ps(_mm256_setzero_ps(), x);
137 __m256 exp_neg = exp256_fast(neg_x);
138 __m256 one = _mm256_set1_ps(1.0f);
139 return _mm256_div_ps(one, _mm256_add_ps(one, exp_neg));
143static inline __m256 ck_ggml_expf_avx2(__m256 x) {
144 const __m256 r = _mm256_set1_ps(0x1.8p23f);
145 const __m256 z = _mm256_fmadd_ps(x, _mm256_set1_ps(0x1.715476p+0f), r);
146 const __m256 n = _mm256_sub_ps(z, r);
147 const __m256 b = _mm256_fnmadd_ps(
149 _mm256_set1_ps(0x1.7f7d1cp-20f),
150 _mm256_fnmadd_ps(n, _mm256_set1_ps(0x1.62e4p-1f), x));
151 const __m256i e = _mm256_slli_epi32(_mm256_castps_si256(z), 23);
152 const __m256 k = _mm256_castsi256_ps(
153 _mm256_add_epi32(e, _mm256_castps_si256(_mm256_set1_ps(1))));
154 const __m256i c = _mm256_castps_si256(
155 _mm256_cmp_ps(_mm256_andnot_ps(_mm256_set1_ps(-0.0f), n),
156 _mm256_set1_ps(126), _CMP_GT_OQ));
157 const __m256 u = _mm256_mul_ps(b, b);
158 const __m256 j = _mm256_fmadd_ps(
160 _mm256_fmadd_ps(_mm256_set1_ps(0x1.0e4020p-7f), b,
161 _mm256_set1_ps(0x1.573e2ep-5f)),
163 _mm256_fmadd_ps(_mm256_set1_ps(0x1.555e66p-3f), b,
164 _mm256_set1_ps(0x1.fffdb6p-2f))),
166 _mm256_mul_ps(_mm256_set1_ps(0x1.ffffecp-1f), b));
167 if (!_mm256_movemask_ps(_mm256_castsi256_ps(c))) {
168 return _mm256_fmadd_ps(j, k, k);
170 const __m256i g = _mm256_and_si256(
171 _mm256_castps_si256(_mm256_cmp_ps(n, _mm256_setzero_ps(), _CMP_LE_OQ)),
172 _mm256_set1_epi32((
int)0x82000000u));
173 const __m256 s1 = _mm256_castsi256_ps(
174 _mm256_add_epi32(g, _mm256_set1_epi32(0x7f000000u)));
175 const __m256 s2 = _mm256_castsi256_ps(_mm256_sub_epi32(e, g));
176 const __m256i d = _mm256_castps_si256(
177 _mm256_cmp_ps(_mm256_andnot_ps(_mm256_set1_ps(-0.0f), n),
178 _mm256_set1_ps(192), _CMP_GT_OQ));
180 _mm256_and_ps(_mm256_castsi256_ps(d), _mm256_mul_ps(s1, s1)),
182 _mm256_castsi256_ps(d),
184 _mm256_and_ps(_mm256_castsi256_ps(c),
185 _mm256_mul_ps(_mm256_fmadd_ps(s2, j, s2), s1)),
186 _mm256_andnot_ps(_mm256_castsi256_ps(c),
187 _mm256_fmadd_ps(k, j, k)))));
191#if defined(__AVX512F__) && defined(__AVX512DQ__)
194static inline __m512 ck_ggml_expf_avx512(__m512 x) {
195 const __m512 r = _mm512_set1_ps(0x1.8p23f);
196 const __m512 z = _mm512_fmadd_ps(x, _mm512_set1_ps(0x1.715476p+0f), r);
197 const __m512 n = _mm512_sub_ps(z, r);
198 const __m512 b = _mm512_fnmadd_ps(
199 n, _mm512_set1_ps(0x1.7f7d1cp-20f),
200 _mm512_fnmadd_ps(n, _mm512_set1_ps(0x1.62e4p-1f), x));
201 const __mmask16 d = _mm512_cmp_ps_mask(
202 _mm512_abs_ps(n), _mm512_set1_ps(192.0f), _CMP_GT_OQ);
203 const __m512 u = _mm512_mul_ps(b, b);
204 const __m512 j = _mm512_fmadd_ps(
207 _mm512_set1_ps(0x1.0e4020p-7f), b,
208 _mm512_set1_ps(0x1.573e2ep-5f)),
211 _mm512_set1_ps(0x1.555e66p-3f), b,
212 _mm512_set1_ps(0x1.fffdb6p-2f))),
215 _mm512_set1_ps(0x1.ffffecp-1f), b,
216 _mm512_set1_ps(1.0f)));
217 const __m512 res = _mm512_scalef_ps(j, n);
218 if (_mm512_kortestz(d, d)) {
221 const __m512 zero = _mm512_setzero_ps();
222 const __m512 alt = _mm512_mask_blend_ps(
223 _mm512_cmp_ps_mask(n, zero, _CMP_LE_OQ),
224 _mm512_set1_ps(INFINITY),
226 return _mm512_mask_blend_ps(d, res, alt);
230#if defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
240static inline float32x4_t ck_ggml_expf_neon(float32x4_t x) {
241 const float32x4_t r = vdupq_n_f32(0x1.8p23f);
242 const float32x4_t z = vfmaq_f32(r, x, vdupq_n_f32(0x1.715476p+0f));
243 const float32x4_t n = vsubq_f32(z, r);
244 const float32x4_t b = vfmsq_f32(vfmsq_f32(x, n, vdupq_n_f32(0x1.62e4p-1f)), n,
245 vdupq_n_f32(0x1.7f7d1cp-20f));
246 const uint32x4_t e = vshlq_n_u32(vreinterpretq_u32_f32(z), 23);
247 const float32x4_t k = vreinterpretq_f32_u32(vaddq_u32(e, vreinterpretq_u32_f32(vdupq_n_f32(1))));
248 const uint32x4_t c = vcagtq_f32(n, vdupq_n_f32(126));
249 const float32x4_t u = vmulq_f32(b, b);
250 const float32x4_t j = vfmaq_f32(
251 vmulq_f32(vdupq_n_f32(0x1.ffffecp-1f), b),
252 vfmaq_f32(vfmaq_f32(vdupq_n_f32(0x1.fffdb6p-2f), vdupq_n_f32(0x1.555e66p-3f), b),
253 vfmaq_f32(vdupq_n_f32(0x1.573e2ep-5f), vdupq_n_f32(0x1.0e4020p-7f), b), u), u);
254 const uint64x2_t c64 = vreinterpretq_u64_u32(c);
255 if (!(vgetq_lane_u64(c64, 0) | vgetq_lane_u64(c64, 1))) {
256 return vfmaq_f32(k, j, k);
258 const uint32x4_t d = vandq_u32(vclezq_f32(n), vdupq_n_u32(0x82000000));
259 const float32x4_t s1 = vreinterpretq_f32_u32(vaddq_u32(d, vdupq_n_u32(0x7f000000)));
260 const float32x4_t s2 = vreinterpretq_f32_u32(vsubq_u32(e, d));
261 return vbslq_f32(vcagtq_f32(n, vdupq_n_f32(192)), vmulq_f32(s1, s1),
262 vbslq_f32(c, vmulq_f32(vfmaq_f32(s2, s2, j), s1), vfmaq_f32(k, k, j)));
265static inline int ck_swiglu_ggml_ref_forced(
void) {
266 const char *env = getenv(
"CK_DEBUG_SWIGLU_GGML_REF");
267 return env && atoi(env) != 0;
288 const char *fast_env = getenv(
"CK_SWIGLU_FAST");
289 const char *exact_env = getenv(
"CK_SWIGLU_EXACT");
291 !(fast_env && atoi(fast_env) != 0) ||
292 (exact_env && atoi(exact_env) != 0)) {
300 for (
int t = 0; t < T; ++t) {
301 const float *row = input + (size_t)t * (2 * D);
302 float *out_row = output + (size_t)t * D;
305#if defined(__AVX512F__)
307 for (; d + 16 <= D; d += 16) {
308 __m512 a = _mm512_loadu_ps(&row[d]);
309 __m512 b = _mm512_loadu_ps(&row[D + d]);
311 __m512 s = sigmoid512_fast(a);
312 __m512
silu = _mm512_mul_ps(a, s);
313 __m512 y = _mm512_mul_ps(
silu, b);
315 _mm512_storeu_ps(&out_row[d], y);
317#elif defined(__AVX2__)
319 for (; d + 8 <= D; d += 8) {
320 __m256 a = _mm256_loadu_ps(&row[d]);
321 __m256 b = _mm256_loadu_ps(&row[D + d]);
323 __m256 s = sigmoid256_fast(a);
324 __m256
silu = _mm256_mul_ps(a, s);
325 __m256 y = _mm256_mul_ps(
silu, b);
327 _mm256_storeu_ps(&out_row[d], y);
329#elif defined(__AVX__)
334 for (; d + 8 <= D; d += 8) {
335 __m256 a = _mm256_loadu_ps(&row[d]);
336 __m256 b = _mm256_loadu_ps(&row[D + d]);
339 _mm256_store_ps(a_arr, a);
340 for (
int j = 0; j < 8; ++j) {
343 __m256 s = _mm256_load_ps(s_arr);
345 __m256
silu = _mm256_mul_ps(a, s);
346 __m256 y = _mm256_mul_ps(
silu, b);
348 _mm256_storeu_ps(&out_row[d], y);
355 float b = row[D + d];
360 out_row[d] =
silu * b;
370 if (!input || !output_q8 || tokens <= 0 || dim <= 0) {
373 if ((dim %
QK_K) != 0) {
377 const char *fast_env = getenv(
"CK_SWIGLU_FAST");
378 const char *exact_env = getenv(
"CK_SWIGLU_EXACT");
380 (fast_env && atoi(fast_env) != 0) &&
381 !(exact_env && atoi(exact_env) != 0);
383 const int blocks_per_row = dim /
QK_K;
387 for (
int t = 0; t < tokens; ++t) {
388 const float *row = input + (size_t)t * (
size_t)(2 * dim);
389 block_q8_K *q8_row = q8 + (size_t)t * (
size_t)blocks_per_row;
391 for (
int block = 0; block < blocks_per_row; ++block) {
392 const int base = block *
QK_K;
397 for (; d + 8 <=
QK_K; d += 8) {
398 const __m256 a = _mm256_loadu_ps(row + base + d);
399 const __m256 b = _mm256_loadu_ps(row + dim + base + d);
400 const __m256 s = sigmoid256_fast(a);
401 const __m256 y = _mm256_mul_ps(_mm256_mul_ps(a, s), b);
402 _mm256_storeu_ps(tmp + d, y);
409 for (; d <
QK_K; ++d) {
410 const float a = row[base + d];
411 const float b = row[dim + base + d];
413 tmp[d] = (a * s) * b;
433 const float *d_output,
446 for (
int t = 0; t < T; ++t) {
447 const float *row = input + (size_t)t * (2 * D);
448 const float *dy_row = d_output + (size_t)t * D;
449 float *dx_row = d_input + (size_t)t * (2 * D);
452#if defined(__AVX512F__)
454 __m512 one = _mm512_set1_ps(1.0f);
455 for (; d + 16 <= D; d += 16) {
456 __m512 a = _mm512_loadu_ps(&row[d]);
457 __m512 b = _mm512_loadu_ps(&row[D + d]);
458 __m512 dy = _mm512_loadu_ps(&dy_row[d]);
460 __m512 s = sigmoid512_fast(a);
461 __m512
silu = _mm512_mul_ps(a, s);
462 __m512 one_minus_s = _mm512_sub_ps(one, s);
463 __m512 inner = _mm512_fmadd_ps(a, one_minus_s, one);
464 __m512 silu_prime = _mm512_mul_ps(s, inner);
467 __m512 dA = _mm512_mul_ps(dy, _mm512_mul_ps(b, silu_prime));
469 __m512 dB = _mm512_mul_ps(dy,
silu);
471 _mm512_storeu_ps(&dx_row[d], dA);
472 _mm512_storeu_ps(&dx_row[D + d], dB);
474#elif defined(__AVX2__)
476 __m256 one = _mm256_set1_ps(1.0f);
477 for (; d + 8 <= D; d += 8) {
478 __m256 a = _mm256_loadu_ps(&row[d]);
479 __m256 b = _mm256_loadu_ps(&row[D + d]);
480 __m256 dy = _mm256_loadu_ps(&dy_row[d]);
482 __m256 s = sigmoid256_fast(a);
483 __m256
silu = _mm256_mul_ps(a, s);
484 __m256 one_minus_s = _mm256_sub_ps(one, s);
485 __m256 inner = _mm256_fmadd_ps(a, one_minus_s, one);
486 __m256 silu_prime = _mm256_mul_ps(s, inner);
489 __m256 dA = _mm256_mul_ps(dy, _mm256_mul_ps(b, silu_prime));
491 __m256 dB = _mm256_mul_ps(dy,
silu);
493 _mm256_storeu_ps(&dx_row[d], dA);
494 _mm256_storeu_ps(&dx_row[D + d], dB);
496#elif defined(__AVX__)
498 __m256 one = _mm256_set1_ps(1.0f);
502 for (; d + 8 <= D; d += 8) {
503 __m256 a = _mm256_loadu_ps(&row[d]);
504 __m256 b = _mm256_loadu_ps(&row[D + d]);
505 __m256 dy = _mm256_loadu_ps(&dy_row[d]);
508 _mm256_store_ps(a_arr, a);
509 for (
int j = 0; j < 8; ++j) {
512 __m256 s = _mm256_load_ps(s_arr);
514 __m256
silu = _mm256_mul_ps(a, s);
515 __m256 one_minus_s = _mm256_sub_ps(one, s);
516 __m256 a_one_minus_s = _mm256_mul_ps(a, one_minus_s);
517 __m256 inner = _mm256_add_ps(one, a_one_minus_s);
518 __m256 silu_prime = _mm256_mul_ps(s, inner);
521 __m256 dA = _mm256_mul_ps(dy, _mm256_mul_ps(b, silu_prime));
523 __m256 dB = _mm256_mul_ps(dy,
silu);
525 _mm256_storeu_ps(&dx_row[d], dA);
526 _mm256_storeu_ps(&dx_row[D + d], dB);
533 float b = row[D + d];
534 float dy = dy_row[d];
538 float silu_prime = s * (1.0f + a * (1.0f - s));
540 float dA = dy * b * silu_prime;
541 float dB = dy *
silu;
565} ck_swiglu_exact_args_t;
572 const uintptr_t input_begin = (uintptr_t)input;
573 const uintptr_t input_end = input_begin +
574 (size_t)tokens * (
size_t)(2 * dim) *
sizeof(
float);
575 const uintptr_t output_begin = (uintptr_t)output;
576 const uintptr_t output_end = output_begin +
577 (size_t)tokens * (
size_t)dim *
sizeof(float);
578 return input_begin < output_end && output_begin < input_end;
590 const size_t minimum_elements_per_thread = 65536u;
591 const size_t elems = (size_t)tokens * (
size_t)dim;
592 if (!pool || active <= 1 || tokens < 2 ||
593 elems < 2u * minimum_elements_per_thread ||
599 const size_t useful_threads =
600 (elems + minimum_elements_per_thread - 1u) /
601 minimum_elements_per_thread;
602 if ((
size_t)active > useful_threads) active = (
int)useful_threads;
603 if (active > tokens) active = tokens;
607 pool, active, 0, tokens, 1, fn, args);
610 if (input != output) {
621 for (
int begin = 1; begin < tokens;) {
622 int end = begin > tokens - begin ? tokens : begin * 2;
623 int wave_threads = active;
624 const int wave_rows =
end - begin;
625 if (wave_threads > wave_rows) wave_threads = wave_rows;
627 pool, wave_threads, begin,
end, 1, fn, args);
634 const ck_swiglu_exact_args_t *args =
635 (
const ck_swiglu_exact_args_t *)opaque;
637 for (
int t = begin; t <
end; ++t) {
638 const float *row = args->input +
639 (size_t)t * (
size_t)(2 * args->dim);
640 float *out_row = args->output + (size_t)t * (
size_t)args->dim;
642 for (
int d = 0; d < args->dim; ++d) {
644 float b = row[args->dim + d];
647 out_row[d] =
silu * b;
657 if (!input || !output || tokens <= 0 || dim <= 0) {
661 ck_swiglu_exact_args_t args = {input, output, dim};
672} ck_swiglu_ggml_args_t;
676 const ck_swiglu_ggml_args_t *args =
677 (
const ck_swiglu_ggml_args_t *)opaque;
678 const int dim = args->dim;
679#if defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
680 const int force_ref = ck_swiglu_ggml_ref_forced();
682 for (
int t = begin; t <
end; ++t) {
683 const float *row = args->input + (size_t)t * (
size_t)(2 * dim);
684 float *out_row = args->output + (size_t)t * (
size_t)dim;
687#if defined(__AVX512F__) && defined(__AVX512DQ__)
688 for (; d + 16 <= dim; d += 16) {
689 const __m512 gate = _mm512_loadu_ps(row + d);
690 const __m512 up = _mm512_loadu_ps(row + dim + d);
691 const __m512 neg_gate = _mm512_sub_ps(_mm512_setzero_ps(), gate);
692 const __m512 denom = _mm512_add_ps(
693 _mm512_set1_ps(1.0f), ck_ggml_expf_avx512(neg_gate));
694 const __m512
silu = _mm512_div_ps(gate, denom);
695 _mm512_storeu_ps(out_row + d, _mm512_mul_ps(
silu, up));
697#elif defined(__AVX2__) && defined(__FMA__)
698 for (; d + 8 <= dim; d += 8) {
699 const __m256 gate = _mm256_loadu_ps(row + d);
700 const __m256 up = _mm256_loadu_ps(row + dim + d);
701 const __m256 neg_gate = _mm256_sub_ps(_mm256_setzero_ps(), gate);
702 const __m256 denom = _mm256_add_ps(
703 _mm256_set1_ps(1.0f), ck_ggml_expf_avx2(neg_gate));
704 const __m256
silu = _mm256_div_ps(gate, denom);
705 _mm256_storeu_ps(out_row + d, _mm256_mul_ps(
silu, up));
707#elif defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
709 for (; d + 4 <= dim; d += 4) {
710 const float32x4_t gate = vld1q_f32(row + d);
711 const float32x4_t up = vld1q_f32(row + dim + d);
712 const float32x4_t neg_gate = vsubq_f32(vdupq_n_f32(0.0f), gate);
713 const float32x4_t denom = vaddq_f32(
714 vdupq_n_f32(1.0f), ck_ggml_expf_neon(neg_gate));
715 const float32x4_t
silu = vdivq_f32(gate, denom);
716 vst1q_f32(out_row + d, vmulq_f32(
silu, up));
720 for (; d < dim; ++d) {
721 const float gate = row[d];
722 out_row[d] = (gate / (1.0f + expf(-gate))) * row[dim + d];
732 if (!input || !output || tokens <= 0 || dim <= 0) {
736 ck_swiglu_ggml_args_t args = {input, output, dim};
749 if (!gate || !up || !output || tokens <= 0 || dim <= 0) {
752#if defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
753 const int force_ref = ck_swiglu_ggml_ref_forced();
755 for (
int t = 0; t < tokens; ++t) {
756 const float *gate_row = gate + (size_t)t * (
size_t)dim;
757 const float *up_row = up + (size_t)t * (
size_t)dim;
758 float *out_row = output + (size_t)t * (
size_t)dim;
761#if defined(__AVX512F__) && defined(__AVX512DQ__)
762 for (; d + 16 <= dim; d += 16) {
763 const __m512 gate_v = _mm512_loadu_ps(gate_row + d);
764 const __m512 up_v = _mm512_loadu_ps(up_row + d);
765 const __m512 neg_gate = _mm512_sub_ps(_mm512_setzero_ps(), gate_v);
766 const __m512 denom = _mm512_add_ps(
767 _mm512_set1_ps(1.0f), ck_ggml_expf_avx512(neg_gate));
768 const __m512
silu = _mm512_div_ps(gate_v, denom);
769 _mm512_storeu_ps(out_row + d, _mm512_mul_ps(
silu, up_v));
771#elif defined(__AVX2__) && defined(__FMA__)
772 for (; d + 8 <= dim; d += 8) {
773 const __m256 gate_v = _mm256_loadu_ps(gate_row + d);
774 const __m256 up_v = _mm256_loadu_ps(up_row + d);
775 const __m256 neg_gate = _mm256_sub_ps(_mm256_setzero_ps(), gate_v);
776 const __m256 denom = _mm256_add_ps(
777 _mm256_set1_ps(1.0f), ck_ggml_expf_avx2(neg_gate));
778 const __m256
silu = _mm256_div_ps(gate_v, denom);
779 _mm256_storeu_ps(out_row + d, _mm256_mul_ps(
silu, up_v));
781#elif defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
783 for (; d + 4 <= dim; d += 4) {
784 const float32x4_t gate_v = vld1q_f32(gate_row + d);
785 const float32x4_t up_v = vld1q_f32(up_row + d);
786 const float32x4_t neg_gate = vsubq_f32(vdupq_n_f32(0.0f), gate_v);
787 const float32x4_t denom = vaddq_f32(
788 vdupq_n_f32(1.0f), ck_ggml_expf_neon(neg_gate));
789 const float32x4_t
silu = vdivq_f32(gate_v, denom);
790 vst1q_f32(out_row + d, vmulq_f32(
silu, up_v));
794 for (; d < dim; ++d) {
795 const float gate_v = gate_row[d];
796 out_row[d] = (gate_v / (1.0f + expf(-gate_v))) * up_row[d];
806#if defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
807 if (ck_swiglu_ggml_ref_forced()) {
808 return "swiglu_ggml_ref";
811#if defined(__AVX512F__) && defined(__AVX512DQ__)
812 return "swiglu_ggml_avx512";
813#elif defined(__AVX2__) && defined(__FMA__)
814 return "swiglu_ggml_avx2";
815#elif defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
816 return "swiglu_ggml_neon";
818 return "swiglu_ggml_ref";
822#if defined(__AVX512F__)
823typedef __m512 (*ck_sleef_expf16_fn)(__m512);
825static ck_sleef_expf16_fn ck_pytorch_swiglu_expf16 = NULL;
826static void *ck_pytorch_swiglu_sleef_handle = NULL;
827static pthread_once_t ck_pytorch_swiglu_once = PTHREAD_ONCE_INIT;
829static void ck_bind_pytorch_swiglu_sleef(
void)
831 const char *library = getenv(
"CK_SLEEF_LIBRARY");
832 if (library && *library) {
833 ck_pytorch_swiglu_sleef_handle = dlopen(library, RTLD_NOW | RTLD_LOCAL);
834 if (ck_pytorch_swiglu_sleef_handle) {
835 ck_pytorch_swiglu_expf16 = (ck_sleef_expf16_fn)dlsym(
836 ck_pytorch_swiglu_sleef_handle,
"Sleef_expf16_u10");
839 ck_pytorch_swiglu_expf16 =
840 (ck_sleef_expf16_fn)dlsym(
RTLD_DEFAULT,
"Sleef_expf16_u10");
866 if (!input || !output || tokens < 0 || dim < 0) {
867 fprintf(stderr,
"HARD KERNEL CONTRACT FAULT: invalid PyTorch BF16 SwiGLU arguments\n");
871#if defined(__AVX512F__)
872 pthread_once(&ck_pytorch_swiglu_once, ck_bind_pytorch_swiglu_sleef);
873 if (!ck_pytorch_swiglu_expf16) {
875 "HARD KERNEL CONTRACT FAULT: PyTorch BF16 SwiGLU requires "
876 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
881 for (
int t = 0; t < tokens; ++t) {
882 const float *row = input + (size_t)t * (
size_t)(2 * dim);
883 float *out_row = output + (size_t)t * (
size_t)dim;
886#if defined(__AVX512F__)
887 for (; d + 16 <= dim; d += 16) {
888 const __m512 gate = _mm512_loadu_ps(row + d);
889 const __m512 denominator = _mm512_add_ps(
890 _mm512_set1_ps(1.0f),
891 ck_pytorch_swiglu_expf16(_mm512_sub_ps(_mm512_setzero_ps(), gate)));
892 const __m512
silu = _mm512_div_ps(gate, denominator);
894 _mm512_store_ps(silu_lanes,
silu);
895 for (
int lane = 0; lane < 16; ++lane) {
903 for (; d < dim; ++d) {
906 const float silu = gate_bf16 / (1.0f + expf(-gate_bf16));
923 const float *d_output,
931 for (
int t = 0; t < T; ++t) {
932 const float *row = input + (size_t)t * (2 * D);
933 const float *dy_row = d_output + (size_t)t * D;
934 float *dx_row = d_input + (size_t)t * (2 * D);
936 for (
int d = 0; d < D; ++d) {
938 float b = row[D + d];
939 float dy = dy_row[d];
943 float silu_prime = s * (1.0f + a * (1.0f - s));
945 float dA = dy * b * silu_prime;
946 float dB = dy *
silu;
static uint16_t float_to_bf16(float f)
static float bf16_to_float(uint16_t v)
Persistent pthread thread pool for CK-Engine inference.
void ck_threadpool_parallel_for_n(ck_threadpool_t *pool, int active_threads, int begin, int end, int grain_size, ck_range_fn_t fn, void *args)
ck_threadpool_t * ck_threadpool_global(void)
void(* ck_range_fn_t)(int begin, int end, void *args)
int ck_threadpool_thread_id(const ck_threadpool_t *pool)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)
void quantize_row_q8_k(const float *x, void *y, int k)
float sigmoid_scalar(float x)
int ck_strict_parity_enabled(void)
Quantization block structures for weight-only quantization.
const char * ck_swiglu_ggml_provider_name(void)
static void ck_swiglu_dispatch_rows(ck_threadpool_t *pool, int active, int tokens, int dim, ck_range_fn_t fn, void *args, const float *input, float *output)
void swiglu_forward_exact(const float *input, float *output, int tokens, int dim)
void swiglu_forward_pytorch_bf16_storage(const float *input, float *output, int tokens, int dim)
void swiglu_forward(const float *input, float *output, int tokens, int dim)
void swiglu_backward(const float *input, const float *d_output, float *d_input, int tokens, int dim)
static void ck_swiglu_exact_rows(int begin, int end, void *opaque)
static void ck_swiglu_ggml_rows(int begin, int end, void *opaque)
void swiglu_backward_exact(const float *input, const float *d_output, float *d_input, int tokens, int dim)
void swiglu_forward_q8_k(const float *input, void *output_q8, int tokens, int dim)
static float sigmoid_scalar_parity(float x)
void swiglu_forward_ggml(const float *input, float *output, int tokens, int dim)
void swiglu_forward_ggml_split(const float *gate, const float *up, float *output, int tokens, int dim)
static int ck_swiglu_ranges_overlap(const float *input, const float *output, int tokens, int dim)
__attribute__((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)
static void silu(float *x, int n)