52#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__)
56#define CK_DELTANET_MAX_STACK_DIM 4096
57#define CK_DELTANET_LLAMA_CHUNK_SIZE 64
58#define CK_DELTANET_LLAMA_CHUNK_MAX_DIM 256
60#if defined(__GNUC__) || defined(__clang__)
61#define CK_DELTANET_NOINLINE __attribute__((noinline))
63#define CK_DELTANET_NOINLINE
80 "HARD KERNEL CONTRACT FAULT: llama.cpp DeltaNet requires "
81 "expf from libm.so.6\n");
88 return 1.0f / (1.0f + expf(-x));
97#if defined(__AVX512F__)
98typedef __m512 (*ck_deltanet_sleef_expf16_fn)(__m512);
99static ck_deltanet_sleef_expf16_fn ck_deltanet_pytorch_expf16 = NULL;
100static void *ck_deltanet_sleef_handle = NULL;
110 const char *mkl_library = getenv(
"CK_MKL_LIBRARY");
111 if (mkl_library && *mkl_library) {
123#if defined(__AVX512F__)
124 const char *library = getenv(
"CK_SLEEF_LIBRARY");
125 if (library && *library) {
126 ck_deltanet_sleef_handle = dlopen(library, RTLD_NOW | RTLD_LOCAL);
127 if (ck_deltanet_sleef_handle) {
128 ck_deltanet_pytorch_expf16 =
129 (ck_deltanet_sleef_expf16_fn)dlsym(
130 ck_deltanet_sleef_handle,
"Sleef_expf16_u10");
133 ck_deltanet_pytorch_expf16 =
134 (ck_deltanet_sleef_expf16_fn)dlsym(
151 "HARD KERNEL CONTRACT FAULT: PyTorch DeltaNet requires "
152 "MKL vsExp; set CK_MKL_LIBRARY\n");
158#if defined(__AVX512F__)
159 if (ck_deltanet_pytorch_expf16) {
160 const __m512 one = _mm512_set1_ps(1.0f);
161 for (; h + 15 < num_heads; h += 16) {
162 const __m512 bv = _mm512_loadu_ps(beta + h);
163 const __m512 beta_exp = ck_deltanet_pytorch_expf16(
164 _mm512_sub_ps(_mm512_setzero_ps(), bv));
165 const __m512 beta_sigmoid = _mm512_div_ps(
166 one, _mm512_add_ps(one, beta_exp));
167 float beta_lanes[16];
168 _mm512_storeu_ps(beta_lanes, beta_sigmoid);
169 for (
int lane = 0; lane < 16; ++lane) {
176 for (; h < num_heads; ++h) {
188 if (!g || !beta || !gate_values || !beta_values || num_heads <= 0 ||
193 g, beta, gate_values, beta_values, num_heads);
201 const float *state_in,
209#if defined(__AVX512F__)
210static inline float ck_deltanet_gcc_reduce_add_ps(__m512 value)
212 const __m256 hi = _mm512_extractf32x8_ps(value, 1);
213 const __m256 lo = _mm512_castps512_ps256(value);
214 const __m256 sum8 = _mm256_add_ps(hi, lo);
215 const __m128 hi4 = _mm256_extractf128_ps(sum8, 1);
216 const __m128 lo4 = _mm256_castps256_ps128(sum8);
217 const __m128 sum4 = _mm_add_ps(hi4, lo4);
218 const __m128 swapped = _mm_shuffle_ps(sum4, sum4, _MM_SHUFFLE(1, 0, 3, 2));
219 const __m128 sum2 = _mm_add_ps(sum4, swapped);
220 return _mm_cvtss_f32(_mm_add_ss(sum2, _mm_shuffle_ps(sum2, sum2, 1)));
225 const float *x,
const float *y,
int n)
227#if defined(__AVX512F__)
228 const int np = n & ~63;
230 _mm512_setzero_ps(), _mm512_setzero_ps(),
231 _mm512_setzero_ps(), _mm512_setzero_ps()
233 for (
int i = 0; i < np; i += 64) {
234 for (
int j = 0; j < 4; ++j) {
235 const __m512 xv = _mm512_loadu_ps(x + i + j * 16);
236 const __m512 yv = _mm512_loadu_ps(y + i + j * 16);
237 sum[j] = _mm512_fmadd_ps(xv, yv, sum[j]);
240 sum[0] = _mm512_add_ps(sum[0], sum[2]);
241 sum[1] = _mm512_add_ps(sum[1], sum[3]);
242 sum[0] = _mm512_add_ps(sum[0], sum[1]);
243 float result = ck_deltanet_gcc_reduce_add_ps(sum[0]);
245 const int np = n & ~31;
247 _mm256_setzero_ps(), _mm256_setzero_ps(),
248 _mm256_setzero_ps(), _mm256_setzero_ps()
250 for (
int i = 0; i < np; i += 32) {
251 for (
int j = 0; j < 4; ++j) {
252 const __m256 xv = _mm256_loadu_ps(x + i + j * 8);
253 const __m256 yv = _mm256_loadu_ps(y + i + j * 8);
255 sum[j] = _mm256_fmadd_ps(xv, yv, sum[j]);
257 sum[j] = _mm256_add_ps(_mm256_mul_ps(xv, yv), sum[j]);
261 sum[0] = _mm256_add_ps(sum[0], sum[2]);
262 sum[1] = _mm256_add_ps(sum[1], sum[3]);
263 sum[0] = _mm256_add_ps(sum[0], sum[1]);
264 const __m128 halves = _mm_add_ps(
265 _mm256_castps256_ps128(sum[0]), _mm256_extractf128_ps(sum[0], 1));
266 const __m128 pairs = _mm_hadd_ps(halves, halves);
267 float result = _mm_cvtss_f32(_mm_hadd_ps(pairs, pairs));
269 for (
int i = np; i < n; ++i) {
270 result += x[i] * y[i];
275static inline float ck_deltanet_llama_scale(
int state_dim)
278 const __m128 dim = _mm_set_ss((
float) state_dim);
279 return _mm_cvtss_f32(_mm_div_ss(_mm_set_ss(1.0f), _mm_sqrt_ss(dim)));
281 return 1.0f / sqrtf((
float) state_dim);
285static inline __m256 ck_deltanet_fmadd8(__m256 a, __m256 b, __m256 acc)
288 return _mm256_fmadd_ps(a, b, acc);
290 return _mm256_add_ps(_mm256_mul_ps(a, b), acc);
307static void gated_deltanet_llama_chunk64_head(
313 const float *state_in,
323 const int group = head % group_count;
324 const size_t qk_row_stride = (size_t)group_count * (
size_t)state_dim;
325 const size_t value_row_stride = (size_t)num_heads * (
size_t)state_dim;
326 const size_t gate_row_stride = (size_t)num_heads;
327 const size_t state_count = (size_t)state_dim * (
size_t)state_dim;
328 const float scale = 1.0f / sqrtf((
float)state_dim);
333 float transform[
C *
C];
343 float *state = state_out + (size_t)head * state_count;
344 const float *initial = state_in + (size_t)head * state_count;
345 if (state != initial) {
346 for (
size_t i = 0; i < state_count; ++i) {
347 state[i] = initial[i];
351 for (
int chunk_start = 0; chunk_start < rows; chunk_start +=
C) {
352 const int valid = rows - chunk_start <
C ? rows - chunk_start :
C;
354 for (
int i = 0; i <
C; ++i) {
355 const int token = chunk_start + i;
356 const int present = i < valid;
357 const float gate_value = present
358 ? g[(size_t)
token * gate_row_stride + (
size_t)head]
360 gcum[i] = gate_value + (i ? gcum[i - 1] : 0.0f);
361 gate_exp[i] = expf(gcum[i]);
363 float beta_value = 0.0f;
364 const float *q_src = NULL;
365 const float *k_src = NULL;
366 const float *v_src = NULL;
369 beta[(
size_t)
token * gate_row_stride + (
size_t)head]);
370 q_src = q + (size_t)
token * qk_row_stride +
371 (
size_t)group * (size_t)state_dim;
372 k_src = k + (size_t)
token * qk_row_stride +
373 (
size_t)group * (size_t)state_dim;
374 v_src = v + (size_t)
token * value_row_stride +
375 (
size_t)head * (size_t)state_dim;
377 beta_chunk[i] = beta_value;
378 for (
int d = 0; d < state_dim; ++d) {
379 const size_t offset = (size_t)i * (
size_t)state_dim + (size_t)d;
380 q_chunk[offset] = present ? q_src[d] * scale : 0.0f;
381 k_chunk[offset] = present ? k_src[d] : 0.0f;
382 value_beta[offset] = present ? v_src[d] * beta_value : 0.0f;
384 present ? k_src[d] * beta_value * gate_exp[i] : 0.0f;
394 for (
int i = 0; i <
C; ++i) {
395 for (
int j = 0; j <
C; ++j) {
396 const float d = j <= i ? expf(gcum[i] - gcum[j]) : 0.0f;
397 decay[(size_t)i *
C + (
size_t)j] = d;
398 transform[(size_t)i *
C + (
size_t)j] = j < i
399 ? ck_deltanet_llama_avx2_dot(
400 k_chunk + (
size_t)i * (
size_t)state_dim,
401 k_chunk + (
size_t)j * (
size_t)state_dim,
402 state_dim) * beta_chunk[i] * d
406 for (
int i = 0; i <
C; ++i) {
407 for (
int j = 0; j < i; ++j) {
408 work_row[j] = transform[(size_t)i *
C + (
size_t)j];
410 for (
int col = 0; col <= i; ++col) {
411 const float rhs = i == col ? 1.0f : 0.0f;
413 for (
int j = 0; j < i; ++j) {
414 solved -= work_row[j] * transform[(size_t)j *
C + (
size_t)col];
416 transform[(size_t)i *
C + (
size_t)col] = solved;
425 for (
int i = 0; i <
C; ++i) {
427 for (; d + 7 < state_dim; d += 8) {
428 __m256 value_sum = _mm256_setzero_ps();
429 __m256 key_sum = _mm256_setzero_ps();
430 for (
int j = 0; j <
C; ++j) {
431 const __m256 coefficient = _mm256_set1_ps(
432 transform[(
size_t)i *
C + (
size_t)j]);
433 value_sum = ck_deltanet_fmadd8(
435 _mm256_loadu_ps(value_beta +
436 (
size_t)j * (
size_t)state_dim + (
size_t)d),
438 key_sum = ck_deltanet_fmadd8(
440 _mm256_loadu_ps(k_cumdecay +
441 (
size_t)j * (
size_t)state_dim + (
size_t)d),
444 _mm256_storeu_ps(v_new +
445 (
size_t)i * (
size_t)state_dim + (
size_t)d, value_sum);
446 _mm256_storeu_ps(matrix_work +
447 (
size_t)i * (
size_t)state_dim + (
size_t)d, key_sum);
449 for (; d < state_dim; ++d) {
450 float value_sum = 0.0f;
451 float key_sum = 0.0f;
452 for (
int j = 0; j <
C; ++j) {
453 const float coefficient = transform[(size_t)i *
C + (
size_t)j];
454 value_sum += coefficient *
455 value_beta[(size_t)j * (
size_t)state_dim + (size_t)d];
456 key_sum += coefficient *
457 k_cumdecay[(size_t)j * (
size_t)state_dim + (size_t)d];
459 v_new[(size_t)i * (
size_t)state_dim + (size_t)d] = value_sum;
460 matrix_work[(size_t)i * (
size_t)state_dim + (size_t)d] = key_sum;
463 for (
int i = 0; i <
C; ++i) {
465 for (; d + 7 < state_dim; d += 8) {
466 __m256 v_prime = _mm256_setzero_ps();
467 for (
int r = 0; r < state_dim; ++r) {
468 v_prime = ck_deltanet_fmadd8(
469 _mm256_set1_ps(matrix_work[
470 (
size_t)i * (
size_t)state_dim + (
size_t)r]),
471 _mm256_loadu_ps(state +
472 (
size_t)r * (
size_t)state_dim + (
size_t)d),
476 (size_t)i * (
size_t)state_dim + (size_t)d;
477 _mm256_storeu_ps(dst, _mm256_sub_ps(_mm256_loadu_ps(dst), v_prime));
479 for (; d < state_dim; ++d) {
480 float v_prime = 0.0f;
481 for (
int r = 0; r < state_dim; ++r) {
483 matrix_work[(size_t)i * (
size_t)state_dim + (size_t)r] *
484 state[(
size_t)r * (size_t)state_dim + (
size_t)d];
486 v_new[(size_t)i * (
size_t)state_dim + (size_t)d] -= v_prime;
490 for (
int i = 0; i < valid; ++i) {
491 float *out_token = out +
492 (size_t)(chunk_start + i) * value_row_stride +
493 (size_t)head * (
size_t)state_dim;
494 for (
int j = 0; j <= i; ++j) {
495 work_row[j] = ck_deltanet_llama_avx2_dot(
496 q_chunk + (
size_t)i * (
size_t)state_dim,
497 k_chunk + (
size_t)j * (
size_t)state_dim,
498 state_dim) * decay[(size_t)i *
C + (
size_t)j];
501 for (; d + 7 < state_dim; d += 8) {
502 __m256 result = _mm256_setzero_ps();
503 for (
int r = 0; r < state_dim; ++r) {
505 q_chunk[(size_t)i * (
size_t)state_dim + (size_t)r] *
507 result = ck_deltanet_fmadd8(
508 _mm256_set1_ps(q_gate),
509 _mm256_loadu_ps(state +
510 (
size_t)r * (
size_t)state_dim + (
size_t)d),
513 for (
int j = 0; j <= i; ++j) {
514 result = ck_deltanet_fmadd8(
515 _mm256_set1_ps(work_row[j]),
516 _mm256_loadu_ps(v_new +
517 (
size_t)j * (
size_t)state_dim + (
size_t)d),
520 _mm256_storeu_ps(out_token + d, result);
522 for (; d < state_dim; ++d) {
524 for (
int r = 0; r < state_dim; ++r) {
526 q_chunk[(size_t)i * (
size_t)state_dim + (size_t)r] *
528 state[(
size_t)r * (size_t)state_dim + (
size_t)d];
530 for (
int j = 0; j <= i; ++j) {
531 result += work_row[j] *
532 v_new[(size_t)j * (
size_t)state_dim + (size_t)d];
534 out_token[d] = result;
538 const float last_decay = gate_exp[
C - 1];
539 for (
int i = 0; i <
C; ++i) {
540 gate_exp[i] = expf(gcum[
C - 1] - gcum[i]);
542 for (
int r = 0; r < state_dim; ++r) {
544 for (; d + 7 < state_dim; d += 8) {
545 float *state_row = state +
546 (size_t)r * (
size_t)state_dim + (size_t)d;
547 __m256 updated = _mm256_mul_ps(
548 _mm256_loadu_ps(state_row), _mm256_set1_ps(last_decay));
549 for (
int i = 0; i <
C; ++i) {
550 const float key_gate =
551 k_chunk[(size_t)i * (
size_t)state_dim + (size_t)r] *
553 updated = ck_deltanet_fmadd8(
554 _mm256_set1_ps(key_gate),
555 _mm256_loadu_ps(v_new +
556 (
size_t)i * (
size_t)state_dim + (
size_t)d),
559 _mm256_storeu_ps(state_row, updated);
561 for (; d < state_dim; ++d) {
563 state[(size_t)r * (
size_t)state_dim + (size_t)d] * last_decay;
564 for (
int i = 0; i <
C; ++i) {
566 k_chunk[(size_t)i * (
size_t)state_dim + (size_t)r] *
568 v_new[(
size_t)i * (size_t)state_dim + (
size_t)d];
570 state[(size_t)r * (
size_t)state_dim + (size_t)d] = updated;
584 const float *state_in,
593 int pytorch_bf16_boundaries)
597 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
599 group_count <= 0 || num_heads % group_count != 0 ||
601 head_begin < 0 || head_end < head_begin || head_end > num_heads) {
604 const float scale = ck_deltanet_llama_scale(state_dim);
605 const size_t vector_stride = (size_t) state_dim;
606 const size_t state_stride = (size_t) state_dim * (
size_t) state_dim;
610 for (
int h = head_begin; h < head_end; ++h) {
616 const int group = pytorch_bf16_boundaries
617 ? h / (num_heads / group_count)
619 const float *q_head = q + (size_t) group * vector_stride;
620 const float *k_head = k + (size_t) group * vector_stride;
621 const float *v_head = v + (size_t) h * vector_stride;
622 const float *state_prev = state_in + (size_t) h * state_stride;
623 float *state_cur = state_out + (size_t) h * state_stride;
624 float *out_head = out + (size_t) h * vector_stride;
627 if (pytorch_bf16_boundaries) {
635 if (pytorch_bf16_boundaries) {
637 for (
int row = 0; row < state_dim; ++row) {
638 q_scaled[row] = q_head[row] * scale;
642 for (
int row = 0; row < state_dim; ++row) {
643 const size_t row_offset = (size_t) row * (
size_t) state_dim;
644 for (
int col = 0; col < state_dim; ++col) {
645 state_cur[row_offset + (size_t) col] =
646 state_prev[row_offset + (
size_t) col] * gate;
650 for (
int col = 0; col < state_dim; ++col) {
651 for (
int row = 0; row < state_dim; ++row) {
652 column[row] = state_cur[(size_t) row * (
size_t) state_dim + (size_t) col];
654 const float memory = ck_deltanet_llama_avx2_dot(column, k_head, state_dim);
655 const float delta = (v_head[col] - memory) * beta_s;
656 for (
int row = 0; row < state_dim; ++row) {
657 const size_t offset = (size_t) row * (
size_t) state_dim + (size_t) col;
659 const float updated = fmaf(k_head[row], delta, state_cur[offset]);
661 const float updated = state_cur[offset] + k_head[row] * delta;
663 state_cur[offset] = updated;
664 column[row] = updated;
666 if (pytorch_bf16_boundaries) {
668 ck_deltanet_llama_avx2_dot(column, q_scaled, state_dim);
671 ck_deltanet_llama_avx2_dot(column, q_head, state_dim) * scale;
676 if (group_count != num_heads) {
680 q, k, v, g, beta, state_in, state_out, out,
681 num_heads, state_dim, norm_eps);
697 const float *state_in,
709 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
710 num_heads <= 0 || group_count <= 0 || num_heads % group_count != 0 ||
712 head_begin < 0 || head_end < head_begin || head_end > num_heads) {
715 const float scale = ck_deltanet_llama_scale(state_dim);
716 const size_t vector_stride = (size_t) state_dim;
717 const size_t state_stride = (size_t) state_dim * (
size_t) state_dim;
720 for (
int h = head_begin; h < head_end; ++h) {
721 const int group = h % group_count;
722 const float *q_head = q + (size_t) group * vector_stride;
723 const float *k_head = k + (size_t) group * vector_stride;
724 const float *v_head = v + (size_t) h * vector_stride;
725 const float *state_prev = state_in + (size_t) h * state_stride;
726 float *state_cur = state_out + (size_t) h * state_stride;
727 float *out_head = out + (size_t) h * vector_stride;
731 for (
int col = 0; col < state_dim; ++col) {
732 const float *prev_col = state_prev + (size_t) col * vector_stride;
733 float *cur_col = state_cur + (size_t) col * vector_stride;
735 const __m256 gate8 = _mm256_set1_ps(gate);
736 for (; row + 7 < state_dim; row += 8) {
737 const __m256 scaled = _mm256_mul_ps(
738 _mm256_loadu_ps(prev_col + row), gate8);
739 _mm256_storeu_ps(cur_col + row, scaled);
741 for (; row < state_dim; ++row) {
742 cur_col[row] = prev_col[row] * gate;
746 ck_deltanet_llama_avx2_dot(cur_col, k_head, state_dim);
747 const float delta = (v_head[col] - memory) * beta_s;
749 const __m256 delta8 = _mm256_set1_ps(delta);
750 for (; row + 7 < state_dim; row += 8) {
751 const __m256 updated = _mm256_fmadd_ps(
752 _mm256_loadu_ps(k_head + row), delta8,
753 _mm256_loadu_ps(cur_col + row));
754 _mm256_storeu_ps(cur_col + row, updated);
756 for (; row < state_dim; ++row) {
757 cur_col[row] = fmaf(k_head[row], delta, cur_col[row]);
760 ck_deltanet_llama_avx2_dot(cur_col, q_head, state_dim) * scale;
769 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
770 num_heads <= 0 || group_count <= 0 || num_heads % group_count != 0 ||
772 head_begin < 0 || head_end < head_begin || head_end > num_heads) {
777 const float scale = 1.0f / sqrtf((
float) state_dim);
778 const size_t vector_stride = (size_t) state_dim;
779 const size_t state_stride = (size_t) state_dim * (
size_t) state_dim;
782 for (
int h = head_begin; h < head_end; ++h) {
783 const int group = h % group_count;
784 const float *q_head = q + (size_t) group * vector_stride;
785 const float *k_head = k + (size_t) group * vector_stride;
786 const float *v_head = v + (size_t) h * vector_stride;
787 const float *state_prev = state_in + (size_t) h * state_stride;
788 float *state_cur = state_out + (size_t) h * state_stride;
789 float *out_head = out + (size_t) h * vector_stride;
793 for (
int col = 0; col < state_dim; ++col) {
794 const float *prev_col = state_prev + (size_t) col * vector_stride;
795 float *cur_col = state_cur + (size_t) col * vector_stride;
798 for (
int row = 0; row < state_dim; ++row) {
799 cur_col[row] = prev_col[row] * gate;
801 for (
int row = 0; row < state_dim; ++row) {
802 memory += cur_col[row] * k_head[row];
804 const float delta = (v_head[col] - memory) * beta_s;
805 for (
int row = 0; row < state_dim; ++row) {
806 cur_col[row] = fmaf(k_head[row], delta, cur_col[row]);
808 for (
int row = 0; row < state_dim; ++row) {
809 dot += cur_col[row] * q_head[row];
811 out_head[col] = dot * scale;
822 const float *state_in,
831 q, k, v, g, beta, state_in, state_out, out,
832 num_heads, group_count, state_dim, norm_eps, 0, num_heads);
846 const float *state_in,
857 q, k, v, g, beta, state_in, state_out, out,
858 num_heads, group_count, state_dim, norm_eps,
859 head_begin, head_end);
866 while (power < value) {
873#if defined(__GNUC__) && !defined(__clang__)
877 const float *row_weights,
881 const int num_levels = 4;
883 if (level_power < 4) {
886 const int level_step = 1 << level_power;
887 const int level_mask = level_step - 1;
890#if defined(__AVX512F__)
892 for (; col + 63 < state_dim; col += 64) {
894 for (
int level = 0; level < num_levels; ++level) {
895 for (
int block = 0; block < 4; ++block) {
896 acc[level][block] = _mm512_setzero_ps();
901 for (; i + level_step <= state_dim;) {
902 for (
int j = 0; j < level_step; ++j, ++i) {
903 const float *row = matrix + (size_t)i * (
size_t)state_dim + col;
904 const __m512 weight = _mm512_set1_ps(row_weights[i]);
905 for (
int block = 0; block < 4; ++block) {
906 const __m512
product = _mm512_mul_ps(
907 _mm512_loadu_ps(row + block * 16), weight);
908 acc[0][block] = _mm512_add_ps(acc[0][block],
product);
912 for (
int level = 1; level < num_levels; ++level) {
913 for (
int block = 0; block < 4; ++block) {
914 acc[level][block] = _mm512_add_ps(
915 acc[level][block], acc[level - 1][block]);
916 acc[level - 1][block] = _mm512_setzero_ps();
918 const int mask = level_mask << (level * level_power);
919 if ((i &
mask) != 0) {
925 for (; i < state_dim; ++i) {
926 const float *row = matrix + (size_t)i * (
size_t)state_dim + col;
927 const __m512 weight = _mm512_set1_ps(row_weights[i]);
928 for (
int block = 0; block < 4; ++block) {
929 const __m512
product = _mm512_mul_ps(
930 _mm512_loadu_ps(row + block * 16), weight);
931 acc[0][block] = _mm512_add_ps(acc[0][block],
product);
935 for (
int level = 1; level < num_levels; ++level) {
936 for (
int block = 0; block < 4; ++block) {
937 acc[0][block] = _mm512_add_ps(
938 acc[0][block], acc[level][block]);
941 for (
int block = 0; block < 4; ++block) {
942 _mm512_storeu_ps(output + col + block * 16, acc[0][block]);
945#elif defined(__AVX2__)
946 for (; col + 31 < state_dim; col += 32) {
948 for (
int level = 0; level < num_levels; ++level) {
949 for (
int block = 0; block < 4; ++block) {
950 acc[level][block] = _mm256_setzero_ps();
955 for (; i + level_step <= state_dim;) {
956 for (
int j = 0; j < level_step; ++j, ++i) {
957 const float *row = matrix + (size_t)i * (
size_t)state_dim + col;
958 const __m256 weight = _mm256_set1_ps(row_weights[i]);
959 for (
int block = 0; block < 4; ++block) {
960 const __m256
product = _mm256_mul_ps(
961 _mm256_loadu_ps(row + block * 8), weight);
962 acc[0][block] = _mm256_add_ps(acc[0][block],
product);
965 for (
int level = 1; level < num_levels; ++level) {
966 for (
int block = 0; block < 4; ++block) {
967 acc[level][block] = _mm256_add_ps(
968 acc[level][block], acc[level - 1][block]);
969 acc[level - 1][block] = _mm256_setzero_ps();
971 const int mask = level_mask << (level * level_power);
972 if ((i &
mask) != 0) {
977 for (; i < state_dim; ++i) {
978 const float *row = matrix + (size_t)i * (
size_t)state_dim + col;
979 const __m256 weight = _mm256_set1_ps(row_weights[i]);
980 for (
int block = 0; block < 4; ++block) {
981 const __m256
product = _mm256_mul_ps(
982 _mm256_loadu_ps(row + block * 8), weight);
983 acc[0][block] = _mm256_add_ps(acc[0][block],
product);
986 for (
int level = 1; level < num_levels; ++level) {
987 for (
int block = 0; block < 4; ++block) {
988 acc[0][block] = _mm256_add_ps(
989 acc[0][block], acc[level][block]);
992 for (
int block = 0; block < 4; ++block) {
993 _mm256_storeu_ps(output + col + block * 8, acc[0][block]);
1000 for (; col < state_dim; ++col) {
1002 for (
int row = 0; row < state_dim; ++row) {
1003 sum += matrix[(size_t)row * (
size_t)state_dim + col] *
1010#if defined(__GNUC__) && !defined(__clang__)
1019 const float *state_in,
1022 float *debug_decayed_state,
1023 float *debug_memory,
1031 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1032 num_heads <= 0 || group_count <= 0 || num_heads % group_count != 0 ||
1037 const size_t vector_stride = (size_t)state_dim;
1038 const size_t state_stride = vector_stride * vector_stride;
1039 const int heads_per_group = num_heads / group_count;
1040 const float sqrt_dim = sqrtf((
float)state_dim);
1047 g, beta, gate_values, beta_values, num_heads);
1049 for (
int h = 0; h < num_heads; ++h) {
1050 const int group = h / heads_per_group;
1051 const float *q_head = q + (size_t)group * vector_stride;
1052 const float *k_head = k + (size_t)group * vector_stride;
1053 const float *v_head = v + (size_t)h * vector_stride;
1054 const float *state_prev = state_in + (size_t)h * state_stride;
1055 float *state_cur = state_out + (size_t)h * state_stride;
1056 float *out_head = out + (size_t)h * vector_stride;
1058 for (
int col = 0; col < state_dim; ++col) {
1059 q_scaled[col] = q_head[col] / sqrt_dim;
1063 for (
int row = 0; row < state_dim; ++row) {
1064 const size_t row_offset = (size_t)row * vector_stride;
1066#if defined(__AVX2__)
1067 const __m256 gate8 = _mm256_set1_ps(gate_values[h]);
1068 for (; col + 7 < state_dim; col += 8) {
1069 const __m256 state = _mm256_mul_ps(
1070 _mm256_loadu_ps(state_prev + row_offset + (
size_t)col),
1072 _mm256_storeu_ps(state_cur + row_offset + (
size_t)col, state);
1075 for (; col < state_dim; ++col) {
1076 const size_t offset = row_offset + (size_t)col;
1077 const float state = state_prev[offset] * gate_values[h];
1078 state_cur[offset] = state;
1083 state_cur, k_head, memory, state_dim);
1085 if (debug_decayed_state) {
1087 debug_decayed_state + (
size_t)h * state_stride,
1089 state_stride *
sizeof(
float));
1093 debug_memory + (
size_t)h * vector_stride,
1095 vector_stride *
sizeof(
float));
1098 for (
int col = 0; col < state_dim; ++col) {
1099 delta[col] = (v_head[col] - memory[col]) * beta_values[h];
1103 debug_delta + (
size_t)h * vector_stride,
1105 vector_stride *
sizeof(
float));
1108 for (
int row = 0; row < state_dim; ++row) {
1109 const size_t row_offset = (size_t)row * vector_stride;
1110 const float key = k_head[row];
1112#if defined(__AVX2__)
1113 const __m256 key8 = _mm256_set1_ps(key);
1114 for (; col + 7 < state_dim; col += 8) {
1115 const __m256 update = _mm256_mul_ps(
1116 key8, _mm256_loadu_ps(delta + col));
1117 const __m256 state = _mm256_add_ps(
1118 _mm256_loadu_ps(state_cur + row_offset + (
size_t)col),
1120 _mm256_storeu_ps(state_cur + row_offset + (
size_t)col, state);
1123 for (; col < state_dim; ++col) {
1124 const size_t offset = row_offset + (size_t)col;
1125 const float state = state_cur[offset] + key * delta[col];
1126 state_cur[offset] = state;
1131 state_cur, q_scaled, out_head, state_dim);
1133 for (
int col = 0; col < state_dim; ++col) {
1144 const float *state_in,
1153 q, k, v, g, beta, state_in, state_out, out,
1155 num_heads, group_count, state_dim, norm_eps);
1164 const float *state_in,
1167 float *decayed_state,
1176 q, k, v, g, beta, state_in, state_out, out,
1177 decayed_state, memory, delta,
1178 num_heads, group_count, state_dim, norm_eps);
1186 const float *state_in,
1195 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1196 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1197 num_heads % group_count != 0 || state_dim <= 0) {
1200 const size_t qk_stride = (size_t) group_count * (
size_t) state_dim;
1201 const size_t value_stride = (size_t) num_heads * (
size_t) state_dim;
1202 const size_t gate_stride = (size_t) num_heads;
1203 for (
int row = 0; row < rows; ++row) {
1205 q + (
size_t) row * qk_stride,
1206 k + (
size_t) row * qk_stride,
1207 v + (
size_t) row * value_stride,
1208 g + (
size_t) row * gate_stride,
1209 beta + (
size_t) row * gate_stride,
1210 row == 0 ? state_in : state_out,
1212 out + (size_t) row * value_stride,
1213 num_heads, group_count, state_dim, norm_eps);
1222 const float *state_in,
1231 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1232 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1233 num_heads % group_count != 0 || state_dim <= 0) {
1236#if defined(__AVX2__)
1239 for (
int head = 0; head < num_heads; ++head) {
1240 gated_deltanet_llama_chunk64_head(
1241 q, k, v, g, beta, state_in, state_out, out,
1242 rows, num_heads, group_count, head, state_dim);
1248 q, k, v, g, beta, state_in, state_out, out,
1249 rows, num_heads, group_count, state_dim, norm_eps);
1257 const float *state_in,
1266#if defined(__AVX2__)
1267 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1268 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1269 num_heads % group_count != 0 || head < 0 || head >= num_heads ||
1273 gated_deltanet_llama_chunk64_head(
1274 q, k, v, g, beta, state_in, state_out, out,
1275 rows, num_heads, group_count, head, state_dim);
1299 const float *state_in,
1308 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1309 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1310 num_heads % group_count != 0 || state_dim <= 0) {
1313 const size_t qk_stride = (size_t)group_count * (
size_t)state_dim;
1314 const size_t value_stride = (size_t)num_heads * (
size_t)state_dim;
1315 const size_t gate_stride = (size_t)num_heads;
1316 for (
int row = 0; row < rows; ++row) {
1318 q + (
size_t)row * qk_stride,
1319 k + (
size_t)row * qk_stride,
1320 v + (
size_t)row * value_stride,
1321 g + (
size_t)row * gate_stride,
1322 beta + (
size_t)row * gate_stride,
1323 row == 0 ? state_in : state_out,
1325 out + (size_t)row * value_stride,
1326 num_heads, group_count, state_dim, norm_eps);
1335 const float *state_in,
1342 const float q_scale = 1.0f / sqrtf((
float)state_dim);
1343 const size_t vec_stride = (size_t)state_dim;
1344 const size_t state_stride = (size_t)state_dim * (
size_t)state_dim;
1346 for (
int h = 0; h < num_heads; ++h) {
1347 const float *q_head = q + (size_t)h * vec_stride;
1348 const float *k_head = k + (size_t)h * vec_stride;
1349 const float *v_head = v + (size_t)h * vec_stride;
1350 const float *state_prev = state_in + (size_t)h * state_stride;
1351 float *state_cur = state_out + (size_t)h * state_stride;
1352 float *out_head = out + (size_t)h * vec_stride;
1355 const float gate = expf(g[h]);
1357 for (
int row = 0; row < state_dim; ++row) {
1358 const size_t row_off = (size_t)row * (
size_t)state_dim;
1359 for (
int col = 0; col < state_dim; ++col) {
1360 state_cur[row_off + (size_t)col] = state_prev[row_off + (
size_t)col] * gate;
1364 for (
int col = 0; col < state_dim; ++col) {
1365 float kv_mem = 0.0f;
1366 for (
int row = 0; row < state_dim; ++row) {
1367 const float k_hat = k_head[row];
1368 kv_mem += state_cur[(size_t)row * (
size_t)state_dim + (size_t)col] * k_hat;
1371 const float delta = (v_head[col] - kv_mem) * beta_s;
1372 for (
int row = 0; row < state_dim; ++row) {
1373 const float k_hat = k_head[row];
1374 state_cur[(size_t)row * (
size_t)state_dim + (size_t)col] += k_hat * delta;
1378 for (
int col = 0; col < state_dim; ++col) {
1380 for (
int row = 0; row < state_dim; ++row) {
1381 const float q_hat = q_head[row] * q_scale;
1382 acc += state_cur[(size_t)row * (
size_t)state_dim + (size_t)col] * q_hat;
1384 out_head[col] = acc;
1390 const float *d_state_out,
1396 const float *state_in,
1397 const float *state_out,
1408 const float q_scale = 1.0f / sqrtf((
float)state_dim);
1409 const size_t vec_stride = (size_t)state_dim;
1410 const size_t state_stride = (size_t)state_dim * (
size_t)state_dim;
1420 for (
int h = 0; h < num_heads; ++h) {
1421 const float *d_out_head = d_out + (size_t)h * vec_stride;
1422 const float *d_state_out_head = d_state_out + (size_t)h * state_stride;
1423 const float *q_head = q + (size_t)h * vec_stride;
1424 const float *k_head = k + (size_t)h * vec_stride;
1425 const float *v_head = v + (size_t)h * vec_stride;
1426 const float *state_prev = state_in + (size_t)h * state_stride;
1427 const float *state_cur = state_out + (size_t)h * state_stride;
1428 float *d_q_head = d_q + (size_t)h * vec_stride;
1429 float *d_k_head = d_k + (size_t)h * vec_stride;
1430 float *d_v_head = d_v + (size_t)h * vec_stride;
1431 float *d_state_prev = d_state_in + (size_t)h * state_stride;
1434 const float gate = expf(g[h]);
1436 float qk_dot = 0.0f;
1437 float out_delta_dot = 0.0f;
1438 float beta_acc = 0.0f;
1439 float gate_acc = 0.0f;
1441 for (
int i = 0; i < state_dim; ++i) {
1442 q_hat[i] = q_head[i] * q_scale;
1443 k_hat[i] = k_head[i];
1449 qk_dot += q_hat[i] * k_hat[i];
1452 for (
int col = 0; col < state_dim; ++col) {
1454 for (
int row = 0; row < state_dim; ++row) {
1455 mem += (state_prev[(size_t)row * (
size_t)state_dim + (size_t)col] * gate) * k_hat[row];
1458 delta[col] = (v_head[col] - mem) * beta_s;
1459 out_delta_dot += d_out_head[col] * delta[col];
1462 for (
int row = 0; row < state_dim; ++row) {
1463 const size_t row_off = (size_t)row * (
size_t)state_dim;
1464 float dq_acc = 0.0f;
1465 float dk_acc = q_hat[row] * out_delta_dot;
1466 for (
int col = 0; col < state_dim; ++col) {
1467 const float d_state_direct = d_state_out_head[row_off + (size_t)col];
1468 dq_acc += state_cur[row_off + (size_t)col] * d_out_head[col];
1469 dk_acc += d_state_direct * delta[col];
1471 d_q_hat[row] = dq_acc;
1472 d_k_hat[row] = dk_acc;
1475 for (
int col = 0; col < state_dim; ++col) {
1476 float d_delta_acc = d_out_head[col] * qk_dot;
1477 for (
int row = 0; row < state_dim; ++row) {
1478 d_delta_acc += d_state_out_head[(size_t)row * (
size_t)state_dim + (size_t)col] * k_hat[row];
1481 d_v_head[col] = beta_s * d_delta_acc;
1482 d_mem[col] = -beta_s * d_delta_acc;
1483 beta_acc += d_delta_acc * (v_head[col] - kv_mem[col]);
1486 for (
int row = 0; row < state_dim; ++row) {
1487 const size_t row_off = (size_t)row * (
size_t)state_dim;
1488 float s_dm_acc = 0.0f;
1489 for (
int col = 0; col < state_dim; ++col) {
1490 s_dm_acc += (state_prev[row_off + (size_t)col] * gate) * d_mem[col];
1492 d_k_hat[row] += s_dm_acc;
1495 for (
int row = 0; row < state_dim; ++row) {
1496 const size_t row_off = (size_t)row * (
size_t)state_dim;
1497 for (
int col = 0; col < state_dim; ++col) {
1498 const float d_state_total = d_state_out_head[row_off + (size_t)col]
1499 + q_hat[row] * d_out_head[col]
1500 + k_hat[row] * d_mem[col];
1501 d_state_prev[row_off + (size_t)col] = gate * d_state_total;
1502 gate_acc += d_state_total * state_prev[row_off + (size_t)col];
1506 for (
int i = 0; i < state_dim; ++i) {
1507 d_q_head[i] = d_q_hat[i] * q_scale;
1508 d_k_head[i] = d_k_hat[i];
1511 d_g[h] = gate_acc * gate;
1512 d_beta[h] = beta_acc * beta_s * (1.0f - beta_s);
1517static void ck_deltanet_scale_rows_avx(
const float *src,
float *dst,
int dim,
float scale)
1519 const __m256 scale_v = _mm256_set1_ps(scale);
1521 for (; i + 8 <= dim; i += 8) {
1522 __m256 x = _mm256_loadu_ps(src + i);
1523 _mm256_storeu_ps(dst + i, _mm256_mul_ps(x, scale_v));
1525 for (; i < dim; ++i) {
1526 dst[i] = src[i] * scale;
1530void gated_deltanet_autoregressive_forward_avx(
const float *q,
1535 const float *state_in,
1542 const float q_scale = 1.0f / sqrtf((
float)state_dim);
1543 const size_t vec_stride = (size_t)state_dim;
1544 const size_t state_stride = (size_t)state_dim * (
size_t)state_dim;
1551 for (
int h = 0; h < num_heads; ++h) {
1552 const float *q_head = q + (size_t)h * vec_stride;
1553 const float *k_head = k + (size_t)h * vec_stride;
1554 const float *v_head = v + (size_t)h * vec_stride;
1555 const float *state_prev = state_in + (size_t)h * state_stride;
1556 float *state_cur = state_out + (size_t)h * state_stride;
1557 float *out_head = out + (size_t)h * vec_stride;
1559 const float gate = expf(g[h]);
1563 ck_deltanet_scale_rows_avx(q_head, q_hat, state_dim, q_scale);
1564 ck_deltanet_scale_rows_avx(k_head, k_hat, state_dim, 1.0f);
1566 const __m256 beta_v = _mm256_set1_ps(beta_s);
1567 const __m256 zero_v = _mm256_setzero_ps();
1570 for (; col + 8 <= state_dim; col += 8) {
1571 _mm256_storeu_ps(kv_mem + col, zero_v);
1572 _mm256_storeu_ps(out_head + col, zero_v);
1574 for (; col < state_dim; ++col) {
1576 out_head[col] = 0.0f;
1579 for (
int row = 0; row < state_dim; ++row) {
1580 const size_t row_off = (size_t)row * (
size_t)state_dim;
1581 const __m256 k_hat_v = _mm256_set1_ps(k_hat[row]);
1582 const __m256 gate_v = _mm256_set1_ps(gate);
1585 for (; col + 8 <= state_dim; col += 8) {
1586 __m256 prev_v = _mm256_loadu_ps(state_prev + row_off + (
size_t)col);
1587 __m256 cur_v = _mm256_mul_ps(prev_v, gate_v);
1588 __m256 kv_v = _mm256_loadu_ps(kv_mem + col);
1589 kv_v = _mm256_add_ps(kv_v, _mm256_mul_ps(cur_v, k_hat_v));
1590 _mm256_storeu_ps(state_cur + row_off + (
size_t)col, cur_v);
1591 _mm256_storeu_ps(kv_mem + col, kv_v);
1593 for (; col < state_dim; ++col) {
1594 const float cur = state_prev[row_off + (size_t)col] * gate;
1595 state_cur[row_off + (size_t)col] = cur;
1596 kv_mem[col] += cur * k_hat[row];
1601 for (; col + 8 <= state_dim; col += 8) {
1602 __m256 v_v = _mm256_loadu_ps(v_head + col);
1603 __m256 kv_v = _mm256_loadu_ps(kv_mem + col);
1604 __m256 delta_v = _mm256_mul_ps(_mm256_sub_ps(v_v, kv_v), beta_v);
1605 _mm256_storeu_ps(delta + col, delta_v);
1607 for (; col < state_dim; ++col) {
1608 delta[col] = (v_head[col] - kv_mem[col]) * beta_s;
1611 for (
int row = 0; row < state_dim; ++row) {
1612 const size_t row_off = (size_t)row * (
size_t)state_dim;
1613 const __m256 k_hat_v = _mm256_set1_ps(k_hat[row]);
1614 const __m256 q_hat_v = _mm256_set1_ps(q_hat[row]);
1617 for (; col + 8 <= state_dim; col += 8) {
1618 __m256 cur_v = _mm256_loadu_ps(state_cur + row_off + (
size_t)col);
1619 __m256 delta_v = _mm256_loadu_ps(delta + col);
1620 __m256 out_v = _mm256_loadu_ps(out_head + col);
1621 __m256 updated_v = _mm256_add_ps(cur_v, _mm256_mul_ps(k_hat_v, delta_v));
1622 out_v = _mm256_add_ps(out_v, _mm256_mul_ps(updated_v, q_hat_v));
1623 _mm256_storeu_ps(state_cur + row_off + (
size_t)col, updated_v);
1624 _mm256_storeu_ps(out_head + col, out_v);
1626 for (; col < state_dim; ++col) {
1627 const float updated = state_cur[row_off + (size_t)col] + k_hat[row] * delta[col];
1628 state_cur[row_off + (size_t)col] = updated;
1629 out_head[col] += updated * q_hat[row];
1636#if defined(__AVX2__)
1637static inline __m256 ck_deltanet_fmadd256(__m256 a, __m256 b, __m256 c)
1640 return _mm256_fmadd_ps(a, b, c);
1642 return _mm256_add_ps(_mm256_mul_ps(a, b), c);
1646void gated_deltanet_autoregressive_forward_avx2(
const float *q,
1651 const float *state_in,
1658 const float q_scale = 1.0f / sqrtf((
float)state_dim);
1659 const size_t vec_stride = (size_t)state_dim;
1660 const size_t state_stride = (size_t)state_dim * (
size_t)state_dim;
1667 for (
int h = 0; h < num_heads; ++h) {
1668 const float *q_head = q + (size_t)h * vec_stride;
1669 const float *k_head = k + (size_t)h * vec_stride;
1670 const float *v_head = v + (size_t)h * vec_stride;
1671 const float *state_prev = state_in + (size_t)h * state_stride;
1672 float *state_cur = state_out + (size_t)h * state_stride;
1673 float *out_head = out + (size_t)h * vec_stride;
1675 const float gate = expf(g[h]);
1679 ck_deltanet_scale_rows_avx(q_head, q_hat, state_dim, q_scale);
1680 ck_deltanet_scale_rows_avx(k_head, k_hat, state_dim, 1.0f);
1682 const __m256 beta_v = _mm256_set1_ps(beta_s);
1683 const __m256 zero_v = _mm256_setzero_ps();
1686 for (; col + 8 <= state_dim; col += 8) {
1687 _mm256_storeu_ps(kv_mem + col, zero_v);
1688 _mm256_storeu_ps(out_head + col, zero_v);
1690 for (; col < state_dim; ++col) {
1692 out_head[col] = 0.0f;
1696 for (; row + 2 <= state_dim; row += 2) {
1697 const size_t row0_off = (size_t)row * (
size_t)state_dim;
1698 const size_t row1_off = (size_t)(row + 1) * (size_t)state_dim;
1699 const __m256 k0_v = _mm256_set1_ps(k_hat[row]);
1700 const __m256 k1_v = _mm256_set1_ps(k_hat[row + 1]);
1701 const __m256 gate0_v = _mm256_set1_ps(gate);
1702 const __m256 gate1_v = _mm256_set1_ps(gate);
1705 for (; col + 8 <= state_dim; col += 8) {
1706 __m256 prev0_v = _mm256_loadu_ps(state_prev + row0_off + (
size_t)col);
1707 __m256 prev1_v = _mm256_loadu_ps(state_prev + row1_off + (
size_t)col);
1708 __m256 cur0_v = _mm256_mul_ps(prev0_v, gate0_v);
1709 __m256 cur1_v = _mm256_mul_ps(prev1_v, gate1_v);
1710 __m256 kv_v = _mm256_loadu_ps(kv_mem + col);
1711 kv_v = ck_deltanet_fmadd256(cur0_v, k0_v, kv_v);
1712 kv_v = ck_deltanet_fmadd256(cur1_v, k1_v, kv_v);
1713 _mm256_storeu_ps(state_cur + row0_off + (
size_t)col, cur0_v);
1714 _mm256_storeu_ps(state_cur + row1_off + (
size_t)col, cur1_v);
1715 _mm256_storeu_ps(kv_mem + col, kv_v);
1717 for (; col < state_dim; ++col) {
1718 const float cur0 = state_prev[row0_off + (size_t)col] * gate;
1719 const float cur1 = state_prev[row1_off + (size_t)col] * gate;
1720 state_cur[row0_off + (size_t)col] = cur0;
1721 state_cur[row1_off + (size_t)col] = cur1;
1722 kv_mem[col] += cur0 * k_hat[row] + cur1 * k_hat[row + 1];
1725 for (; row < state_dim; ++row) {
1726 const size_t row_off = (size_t)row * (
size_t)state_dim;
1727 const __m256 k_hat_v = _mm256_set1_ps(k_hat[row]);
1728 const __m256 gate_v = _mm256_set1_ps(gate);
1730 for (; col + 8 <= state_dim; col += 8) {
1731 __m256 prev_v = _mm256_loadu_ps(state_prev + row_off + (
size_t)col);
1732 __m256 cur_v = _mm256_mul_ps(prev_v, gate_v);
1733 __m256 kv_v = _mm256_loadu_ps(kv_mem + col);
1734 kv_v = ck_deltanet_fmadd256(cur_v, k_hat_v, kv_v);
1735 _mm256_storeu_ps(state_cur + row_off + (
size_t)col, cur_v);
1736 _mm256_storeu_ps(kv_mem + col, kv_v);
1738 for (; col < state_dim; ++col) {
1739 const float cur = state_prev[row_off + (size_t)col] * gate;
1740 state_cur[row_off + (size_t)col] = cur;
1741 kv_mem[col] += cur * k_hat[row];
1746 for (; col + 8 <= state_dim; col += 8) {
1747 __m256 v_v = _mm256_loadu_ps(v_head + col);
1748 __m256 kv_v = _mm256_loadu_ps(kv_mem + col);
1749 __m256 delta_v = _mm256_mul_ps(_mm256_sub_ps(v_v, kv_v), beta_v);
1750 _mm256_storeu_ps(delta + col, delta_v);
1752 for (; col < state_dim; ++col) {
1753 delta[col] = (v_head[col] - kv_mem[col]) * beta_s;
1757 for (; row + 2 <= state_dim; row += 2) {
1758 const size_t row0_off = (size_t)row * (
size_t)state_dim;
1759 const size_t row1_off = (size_t)(row + 1) * (size_t)state_dim;
1760 const __m256 k0_v = _mm256_set1_ps(k_hat[row]);
1761 const __m256 k1_v = _mm256_set1_ps(k_hat[row + 1]);
1762 const __m256 q0_v = _mm256_set1_ps(q_hat[row]);
1763 const __m256 q1_v = _mm256_set1_ps(q_hat[row + 1]);
1766 for (; col + 8 <= state_dim; col += 8) {
1767 __m256 cur0_v = _mm256_loadu_ps(state_cur + row0_off + (
size_t)col);
1768 __m256 cur1_v = _mm256_loadu_ps(state_cur + row1_off + (
size_t)col);
1769 __m256 delta_v = _mm256_loadu_ps(delta + col);
1770 __m256 out_v = _mm256_loadu_ps(out_head + col);
1771 __m256 upd0_v = ck_deltanet_fmadd256(k0_v, delta_v, cur0_v);
1772 __m256 upd1_v = ck_deltanet_fmadd256(k1_v, delta_v, cur1_v);
1773 out_v = ck_deltanet_fmadd256(upd0_v, q0_v, out_v);
1774 out_v = ck_deltanet_fmadd256(upd1_v, q1_v, out_v);
1775 _mm256_storeu_ps(state_cur + row0_off + (
size_t)col, upd0_v);
1776 _mm256_storeu_ps(state_cur + row1_off + (
size_t)col, upd1_v);
1777 _mm256_storeu_ps(out_head + col, out_v);
1779 for (; col < state_dim; ++col) {
1780 const float upd0 = state_cur[row0_off + (size_t)col] + k_hat[row] * delta[col];
1781 const float upd1 = state_cur[row1_off + (size_t)col] + k_hat[row + 1] * delta[col];
1782 state_cur[row0_off + (size_t)col] = upd0;
1783 state_cur[row1_off + (size_t)col] = upd1;
1784 out_head[col] += upd0 * q_hat[row] + upd1 * q_hat[row + 1];
1787 for (; row < state_dim; ++row) {
1788 const size_t row_off = (size_t)row * (
size_t)state_dim;
1789 const __m256 k_hat_v = _mm256_set1_ps(k_hat[row]);
1790 const __m256 q_hat_v = _mm256_set1_ps(q_hat[row]);
1792 for (; col + 8 <= state_dim; col += 8) {
1793 __m256 cur_v = _mm256_loadu_ps(state_cur + row_off + (
size_t)col);
1794 __m256 delta_v = _mm256_loadu_ps(delta + col);
1795 __m256 out_v = _mm256_loadu_ps(out_head + col);
1796 __m256 updated_v = ck_deltanet_fmadd256(k_hat_v, delta_v, cur_v);
1797 out_v = ck_deltanet_fmadd256(updated_v, q_hat_v, out_v);
1798 _mm256_storeu_ps(state_cur + row_off + (
size_t)col, updated_v);
1799 _mm256_storeu_ps(out_head + col, out_v);
1801 for (; col < state_dim; ++col) {
1802 const float updated = state_cur[row_off + (size_t)col] + k_hat[row] * delta[col];
1803 state_cur[row_off + (size_t)col] = updated;
1804 out_head[col] += updated * q_hat[row];
1811#if defined(__AVX512F__)
1812static inline __m512 ck_deltanet_madd512(__m512 a, __m512 b, __m512 c)
1814 return _mm512_add_ps(_mm512_mul_ps(a, b), c);
1817static void ck_deltanet_scale_rows_avx512(
const float *src,
float *dst,
int dim,
float scale)
1819 const __m512 scale_v = _mm512_set1_ps(scale);
1821 for (; i + 16 <= dim; i += 16) {
1822 __m512 x = _mm512_loadu_ps(src + i);
1823 _mm512_storeu_ps(dst + i, _mm512_mul_ps(x, scale_v));
1825 for (; i < dim; ++i) {
1826 dst[i] = src[i] * scale;
1830void gated_deltanet_autoregressive_forward_avx512(
const float *q,
1835 const float *state_in,
1842 const float q_scale = 1.0f / sqrtf((
float)state_dim);
1843 const size_t vec_stride = (size_t)state_dim;
1844 const size_t state_stride = (size_t)state_dim * (
size_t)state_dim;
1851 for (
int h = 0; h < num_heads; ++h) {
1852 const float *q_head = q + (size_t)h * vec_stride;
1853 const float *k_head = k + (size_t)h * vec_stride;
1854 const float *v_head = v + (size_t)h * vec_stride;
1855 const float *state_prev = state_in + (size_t)h * state_stride;
1856 float *state_cur = state_out + (size_t)h * state_stride;
1857 float *out_head = out + (size_t)h * vec_stride;
1859 const float gate = expf(g[h]);
1863 ck_deltanet_scale_rows_avx512(q_head, q_hat, state_dim, q_scale);
1864 ck_deltanet_scale_rows_avx512(k_head, k_hat, state_dim, 1.0f);
1866 const __m512 beta_v = _mm512_set1_ps(beta_s);
1867 const __m512 zero_v = _mm512_setzero_ps();
1870 for (; col + 16 <= state_dim; col += 16) {
1871 _mm512_storeu_ps(kv_mem + col, zero_v);
1872 _mm512_storeu_ps(out_head + col, zero_v);
1874 for (; col < state_dim; ++col) {
1876 out_head[col] = 0.0f;
1879 for (
int row = 0; row < state_dim; ++row) {
1880 const size_t row_off = (size_t)row * (
size_t)state_dim;
1881 const __m512 k_hat_v = _mm512_set1_ps(k_hat[row]);
1882 const __m512 gate_v = _mm512_set1_ps(gate);
1884 for (; col + 16 <= state_dim; col += 16) {
1885 __m512 prev_v = _mm512_loadu_ps(state_prev + row_off + (
size_t)col);
1886 __m512 cur_v = _mm512_mul_ps(prev_v, gate_v);
1887 __m512 kv_v = _mm512_loadu_ps(kv_mem + col);
1888 kv_v = ck_deltanet_madd512(cur_v, k_hat_v, kv_v);
1889 _mm512_storeu_ps(state_cur + row_off + (
size_t)col, cur_v);
1890 _mm512_storeu_ps(kv_mem + col, kv_v);
1892 for (; col < state_dim; ++col) {
1893 const float cur = state_prev[row_off + (size_t)col] * gate;
1894 state_cur[row_off + (size_t)col] = cur;
1895 kv_mem[col] += cur * k_hat[row];
1900 for (; col + 16 <= state_dim; col += 16) {
1901 __m512 v_v = _mm512_loadu_ps(v_head + col);
1902 __m512 kv_v = _mm512_loadu_ps(kv_mem + col);
1903 __m512 delta_v = _mm512_mul_ps(_mm512_sub_ps(v_v, kv_v), beta_v);
1904 _mm512_storeu_ps(delta + col, delta_v);
1906 for (; col < state_dim; ++col) {
1907 delta[col] = (v_head[col] - kv_mem[col]) * beta_s;
1910 for (
int row = 0; row < state_dim; ++row) {
1911 const size_t row_off = (size_t)row * (
size_t)state_dim;
1912 const __m512 k_hat_v = _mm512_set1_ps(k_hat[row]);
1913 const __m512 q_hat_v = _mm512_set1_ps(q_hat[row]);
1915 for (; col + 16 <= state_dim; col += 16) {
1916 __m512 cur_v = _mm512_loadu_ps(state_cur + row_off + (
size_t)col);
1917 __m512 delta_v = _mm512_loadu_ps(delta + col);
1918 __m512 out_v = _mm512_loadu_ps(out_head + col);
1919 __m512 updated_v = ck_deltanet_madd512(k_hat_v, delta_v, cur_v);
1920 out_v = ck_deltanet_madd512(updated_v, q_hat_v, out_v);
1921 _mm512_storeu_ps(state_cur + row_off + (
size_t)col, updated_v);
1922 _mm512_storeu_ps(out_head + col, out_v);
1924 for (; col < state_dim; ++col) {
1925 const float updated = state_cur[row_off + (size_t)col] + k_hat[row] * delta[col];
1926 state_cur[row_off + (size_t)col] = updated;
1927 out_head[col] += updated * q_hat[row];
1936 const char *env = getenv(
"CK_DELTANET_FORCE_REF");
1937 return env && atoi(env) != 0;
1945#if defined(__AVX512F__)
1947#elif defined(__AVX2__)
1949#elif defined(__AVX__)
1961 const float *state_in,
1968 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out) {
1971 if (num_heads <= 0 || state_dim <= 0) {
1981 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1984#if defined(__AVX512F__)
1985 gated_deltanet_autoregressive_forward_avx512(
1986 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1987#elif defined(__AVX2__)
1988 gated_deltanet_autoregressive_forward_avx2(
1989 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1990#elif defined(__AVX__)
1991 gated_deltanet_autoregressive_forward_avx(
1992 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1995 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
2004 const float *state_in,
2012 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out) {
2015 if (rows <= 0 || num_heads <= 0 || state_dim <= 0) {
2019 const size_t vector_stride = (size_t)num_heads * (
size_t)state_dim;
2020 const size_t gate_stride = (size_t)num_heads;
2021 for (
int row = 0; row < rows; ++row) {
2022 const float *row_state_in = row == 0 ? state_in : state_out;
2024 q + (
size_t)row * vector_stride,
2025 k + (
size_t)row * vector_stride,
2026 v + (
size_t)row * vector_stride,
2027 g + (
size_t)row * gate_stride,
2028 beta + (
size_t)row * gate_stride,
2031 out + (
size_t)row * vector_stride,
2039 const float *d_state_out,
2045 const float *state_in,
2046 const float *state_out,
2057 if (!d_out || !d_state_out || !q || !k || !v || !g || !beta || !state_in || !state_out ||
2058 !d_q || !d_k || !d_v || !d_g || !d_beta || !d_state_in) {
static int product(size_t a, size_t b, size_t *out)
static uint16_t float_to_bf16(float f)
static float bf16_to_float(uint16_t v)
int ck_strict_parity_enabled(void)
#define CK_DELTANET_LLAMA_CHUNK_SIZE
#define CK_DELTANET_NOINLINE
void gated_deltanet_autoregressive_backward(const float *d_out, const float *d_state_out, const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, const float *state_out, float *d_q, float *d_k, float *d_v, float *d_g, float *d_beta, float *d_state_in, int num_heads, int state_dim, float norm_eps)
static ck_deltanet_mkl_vsexp_fn ck_deltanet_pytorch_vsexp
static pthread_once_t ck_deltanet_libm_once
void gated_deltanet_pytorch_gate_values_debug(const float *g, const float *beta, float *gate_values, float *beta_values, int num_heads)
static void ck_deltanet_pytorch_outer_sum(const float *matrix, const float *row_weights, float *output, int state_dim)
void gated_deltanet_pytorch_grouped_bf16_forward_debug(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, float *decayed_state, float *memory, float *delta, int num_heads, int group_count, int state_dim, float norm_eps)
static void ck_bind_deltanet_pytorch_primitives(void)
void gated_deltanet_autoregressive_forward_ref(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int state_dim, float norm_eps)
static pthread_once_t ck_deltanet_pytorch_primitives_once
static int ck_deltanet_ceil_log2(int value)
static void gated_deltanet_pytorch_grouped_bf16_forward_impl(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, float *debug_decayed_state, float *debug_memory, float *debug_delta, int num_heads, int group_count, int state_dim, float norm_eps)
void gated_deltanet_llama_avx2_prefill_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int state_dim, float norm_eps)
static ck_deltanet_libm_f32_fn ck_deltanet_llama_expf
static void gated_deltanet_llama_avx2_grouped_forward_transposed_impl(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps, int head_begin, int head_end)
void(* ck_deltanet_mkl_vsexp_fn)(int, const float *, float *)
void gated_deltanet_llama_avx2_forward_head_range(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps, int head_begin, int head_end)
static void * ck_deltanet_mkl_handle
void gated_deltanet_llama_avx2_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps)
#define CK_DELTANET_LLAMA_CHUNK_MAX_DIM
static void * ck_deltanet_libm_handle
static void gated_deltanet_llama_avx2_grouped_forward_impl(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps, int head_begin, int head_end, int pytorch_bf16_boundaries)
static void ck_deltanet_pytorch_gate_values(const float *g, const float *beta, float *gate_values, float *beta_values, int num_heads)
static float ck_deltanet_sigmoidf(float x)
void gated_deltanet_pytorch_grouped_bf16_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps)
void gated_deltanet_pytorch_grouped_bf16_prefill_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int state_dim, float norm_eps)
void gated_deltanet_autoregressive_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int state_dim, float norm_eps)
void gated_deltanet_llama_chunk64_head_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int head, int state_dim)
#define CK_DELTANET_MAX_STACK_DIM
void gated_deltanet_autoregressive_backward_ref(const float *d_out, const float *d_state_out, const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, const float *state_out, float *d_q, float *d_k, float *d_v, float *d_g, float *d_beta, float *d_state_in, int num_heads, int state_dim, float norm_eps)
static void ck_bind_deltanet_llama_libm(void)
static float ck_deltanet_llama_sigmoidf(float x)
void gated_deltanet_prefill_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int state_dim, float norm_eps)
static int ck_deltanet_force_ref(void)
void gated_deltanet_llama_chunk64_prefill_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int state_dim, float norm_eps)
const char * gated_deltanet_impl_name(void)
float(* ck_deltanet_libm_f32_fn)(float)
int32_t int32_t int32_t int32_t int32_t mask
__attribute__((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)