← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
attention_kernels_sliding.c File Reference

Sliding-window flash attention kernels split from attention_kernels.c. More...

#include "ckernel_engine.h"
#include "ck_threadpool.h"
#include <math.h>
#include <stdlib.h>

Go to the source code of this file.

Macros

#define CK_SLIDING_FLASH_IMPL   attention_flash_query_sliding
 
#define SLIDING_DECODE_IMPL   attention_flash_query_sliding
 
#define SLIDING_DECODE_IMPL_GEMMA4   attention_flash_query_sliding
 
#define SLIDING_FLASH_IMPL   attention_flash_query_sliding
 
#define SLIDING_FLASH_IMPL_GEMMA4   attention_flash_query_sliding
 

Functions

static void attention_flash_query_sliding (const float *q_vec, const float *k_head, const float *v_head, int query_pos, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec, int sliding_window)
 
void attention_forward_causal_head_major_gqa_flash_strided_sliding (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4 (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
static void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window, int output_token_major)
 
void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_token_output (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
void attention_forward_causal_head_major_shared_kv_sliding_gemma4 (const float *q, float *output, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
void attention_forward_decode_head_major_gqa_flash_sliding (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)
 
void attention_forward_decode_head_major_gqa_flash_sliding_gemma4 (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)
 
void attention_forward_decode_head_major_shared_kv_sliding_gemma4 (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)
 
static size_t attention_output_index (int h, int t, int num_heads, int num_tokens, int aligned_head_dim, int output_token_major)
 
static int ck_env_int_default (const char *name, int fallback)
 
static void ck_sliding_attention_compute_one (const ck_sliding_attention_args_t *a, int job)
 
static int ck_sliding_attention_parallel_disabled (void)
 
static int ck_sliding_attention_pick_threads (ck_threadpool_t *pool, int total_jobs, int num_tokens, int head_dim)
 
static void ck_sliding_attention_work_fn (int ith, int nth, void *args)
 
static size_t qkv_index (int h, int t, int d, int num_tokens, int aligned_head_dim)
 

Detailed Description

Sliding-window flash attention kernels split from attention_kernels.c.

Definition in file attention_kernels_sliding.c.

Macro Definition Documentation

◆ CK_SLIDING_FLASH_IMPL

#define CK_SLIDING_FLASH_IMPL   attention_flash_query_sliding

◆ SLIDING_DECODE_IMPL

#define SLIDING_DECODE_IMPL   attention_flash_query_sliding

◆ SLIDING_DECODE_IMPL_GEMMA4

#define SLIDING_DECODE_IMPL_GEMMA4   attention_flash_query_sliding

◆ SLIDING_FLASH_IMPL

#define SLIDING_FLASH_IMPL   attention_flash_query_sliding

◆ SLIDING_FLASH_IMPL_GEMMA4

#define SLIDING_FLASH_IMPL_GEMMA4   attention_flash_query_sliding

Function Documentation

◆ attention_flash_query_sliding()

static void attention_flash_query_sliding ( const float *  q_vec,
const float *  k_head,
const float *  v_head,
int  query_pos,
int  kv_tokens,
int  head_dim,
int  aligned_head_dim,
float  scale,
float *  out_vec,
int  sliding_window 
)
static

Definition at line 392 of file attention_kernels_sliding.c.

402{
403 float m = -INFINITY;
404 float s = 0.0f;
405
406 int window_start = 0;
407 if (sliding_window > 0) {
408 window_start = query_pos - sliding_window + 1;
409 if (window_start < 0) window_start = 0;
410 }
411
412 for (int d = 0; d < head_dim; ++d) {
413 out_vec[d] = 0.0f;
414 }
415
416 int effective_kv_end = query_pos < kv_tokens ? query_pos : kv_tokens - 1;
417 for (int j = window_start; j <= effective_kv_end; ++j) {
418 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
419 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
420
421 float dot = 0.0f;
422 for (int d = 0; d < head_dim; ++d) {
423 dot += q_vec[d] * k_vec[d];
424 }
425 float score = dot * scale;
426
427 if (score > m) {
428 float exp_m = (m == -INFINITY) ? 0.0f : expf(m - score);
429 s *= exp_m;
430 for (int d = 0; d < head_dim; ++d) {
431 out_vec[d] *= exp_m;
432 }
433 s += 1.0f;
434 for (int d = 0; d < head_dim; ++d) {
435 out_vec[d] += v_vec[d];
436 }
437 m = score;
438 } else {
439 float e = expf(score - m);
440 s += e;
441 for (int d = 0; d < head_dim; ++d) {
442 out_vec[d] += e * v_vec[d];
443 }
444 }
445 }
446
447 float inv_s = 1.0f / s;
448 for (int d = 0; d < head_dim; ++d) {
449 out_vec[d] *= inv_s;
450 }
451 for (int d = head_dim; d < aligned_head_dim; ++d) {
452 out_vec[d] = 0.0f;
453 }
454}
int32_t float * score
Definition tokenizer.h:328

References score.

◆ attention_forward_causal_head_major_gqa_flash_strided_sliding()

void attention_forward_causal_head_major_gqa_flash_strided_sliding ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  sliding_window 
)

Flash attention forward with sliding window (prefill)

Test:
test_attention.py::TestAttentionForward::test_sliding_window_prefill

Sliding-window attention for prefill: each token attends to the last W tokens. When sliding_window <= 0, behaves like regular causal attention.

After changes: make test

Definition at line 566 of file attention_kernels_sliding.c.

578{
579 if (!q || !k || !v || !output) {
580 return;
581 }
582 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
583 return;
584 }
585 if (kv_stride_tokens < num_tokens) {
586 return;
587 }
588
589 /* Debug escape hatch:
590 * For Gemma bring-up, force the proven non-sliding flash kernel to isolate
591 * whether divergence is caused by sliding-window implementation details.
592 */
593 if (getenv("CK_FORCE_NONSLIDING_ATTN")) {
595 q, k, v, output, num_heads, num_kv_heads, num_tokens,
596 head_dim, aligned_head_dim, kv_stride_tokens
597 );
598 return;
599 }
600
601 const float scale = 1.0f / sqrtf((float)head_dim);
602 const int T = num_tokens;
603 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
604
605 const int total_jobs = num_heads * T;
606 ck_threadpool_t *pool = ck_threadpool_global();
607 const int active = ck_sliding_attention_pick_threads(pool, total_jobs, T, head_dim);
608 if (pool && active > 1) {
609 ck_sliding_attention_args_t args = {
610 .q = q,
611 .k = k,
612 .v = v,
613 .output = output,
614 .num_heads = num_heads,
615 .num_kv_heads = num_kv_heads,
616 .num_tokens = T,
617 .head_dim = head_dim,
618 .aligned_head_dim = aligned_head_dim,
619 .kv_stride_tokens = kv_stride_tokens,
620 .sliding_window = sliding_window,
621 .output_token_major = 0,
622 .scale = scale,
623 };
625 return;
626 }
627
628#if defined(__AVX512F__)
629 #define SLIDING_FLASH_IMPL attention_flash_query_sliding_avx512
630#elif defined(__AVX2__)
631 #define SLIDING_FLASH_IMPL attention_flash_query_sliding_avx2
632#elif defined(__AVX__)
633 #define SLIDING_FLASH_IMPL attention_flash_query_sliding_avx
634#else
635 #define SLIDING_FLASH_IMPL attention_flash_query_sliding
636#endif
637
638 for (int h = 0; h < num_heads; ++h) {
639 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
640 const float *k_head = k + (size_t)kv_head * kv_head_stride;
641 const float *v_head = v + (size_t)kv_head * kv_head_stride;
642
643 for (int i = 0; i < T; ++i) {
644 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
645 float *out_vec = output + attention_output_index(
646 h, i, num_heads, T, aligned_head_dim, 0);
647 SLIDING_FLASH_IMPL(q_vec, k_head, v_head,
648 /*query_pos=*/i,
649 /*kv_tokens=*/T,
650 head_dim, aligned_head_dim,
651 scale, out_vec,
652 sliding_window);
653 }
654 }
655
656#undef SLIDING_FLASH_IMPL
657}
static size_t qkv_index(int h, int t, int d, int num_tokens, int aligned_head_dim)
static int ck_sliding_attention_pick_threads(ck_threadpool_t *pool, int total_jobs, int num_tokens, int head_dim)
#define SLIDING_FLASH_IMPL
static size_t attention_output_index(int h, int t, int num_heads, int num_tokens, int aligned_head_dim, int output_token_major)
static void ck_sliding_attention_work_fn(int ith, int nth, void *args)
void ck_threadpool_dispatch_n(ck_threadpool_t *pool, int active_threads, ck_work_fn_t fn, void *args)
ck_threadpool_t * ck_threadpool_global(void)
void attention_forward_causal_head_major_gqa_flash_strided(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens)

References attention_forward_causal_head_major_gqa_flash_strided(), attention_output_index(), ck_sliding_attention_pick_threads(), ck_sliding_attention_work_fn(), ck_threadpool_dispatch_n(), ck_threadpool_global(), qkv_index(), and SLIDING_FLASH_IMPL.

◆ attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4()

void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4 ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  sliding_window 
)

Definition at line 763 of file attention_kernels_sliding.c.

775{
777 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
778 aligned_head_dim, kv_stride_tokens, sliding_window,
779 /*output_token_major=*/0);
780}
static void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window, int output_token_major)

References attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

Referenced by attention_forward_causal_head_major_shared_kv_sliding_gemma4().

◆ attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl()

static void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  sliding_window,
int  output_token_major 
)
static

Flash attention decode with sliding window

Test:
test_attention.py::TestAttentionForward::test_sliding_window_decode

Single query token attends to the last W tokens in the KV cache. For decode: effective_kv_tokens = min(kv_tokens, sliding_window)

After changes: make test

Definition at line 668 of file attention_kernels_sliding.c.

681{
682 if (!q || !k || !v || !output) {
683 return;
684 }
685 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
686 return;
687 }
688 if (kv_stride_tokens < num_tokens) {
689 return;
690 }
691
692 if (getenv("CK_FORCE_NONSLIDING_ATTN")) {
693 if (output_token_major) {
695 q, k, v, output, num_heads, num_kv_heads, num_tokens,
696 head_dim, aligned_head_dim, kv_stride_tokens);
697 } else {
699 q, k, v, output, num_heads, num_kv_heads, num_tokens,
700 head_dim, aligned_head_dim, kv_stride_tokens);
701 }
702 return;
703 }
704
705 const float scale = 1.0f;
706 const int T = num_tokens;
707 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
708
709 const int total_jobs = num_heads * T;
710 ck_threadpool_t *pool = ck_threadpool_global();
711 const int active = ck_sliding_attention_pick_threads(pool, total_jobs, T, head_dim);
712 if (pool && active > 1) {
713 ck_sliding_attention_args_t args = {
714 .q = q,
715 .k = k,
716 .v = v,
717 .output = output,
718 .num_heads = num_heads,
719 .num_kv_heads = num_kv_heads,
720 .num_tokens = T,
721 .head_dim = head_dim,
722 .aligned_head_dim = aligned_head_dim,
723 .kv_stride_tokens = kv_stride_tokens,
724 .sliding_window = sliding_window,
725 .output_token_major = output_token_major,
726 .scale = scale,
727 };
729 return;
730 }
731
732#if defined(__AVX512F__)
733 #define SLIDING_FLASH_IMPL_GEMMA4 attention_flash_query_sliding_avx512
734#elif defined(__AVX2__)
735 #define SLIDING_FLASH_IMPL_GEMMA4 attention_flash_query_sliding_avx2
736#elif defined(__AVX__)
737 #define SLIDING_FLASH_IMPL_GEMMA4 attention_flash_query_sliding_avx
738#else
739 #define SLIDING_FLASH_IMPL_GEMMA4 attention_flash_query_sliding
740#endif
741
742 for (int h = 0; h < num_heads; ++h) {
743 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
744 const float *k_head = k + (size_t)kv_head * kv_head_stride;
745 const float *v_head = v + (size_t)kv_head * kv_head_stride;
746
747 for (int i = 0; i < T; ++i) {
748 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
749 float *out_vec = output + attention_output_index(
750 h, i, num_heads, T, aligned_head_dim, output_token_major);
751 SLIDING_FLASH_IMPL_GEMMA4(q_vec, k_head, v_head,
752 /*query_pos=*/i,
753 /*kv_tokens=*/T,
754 head_dim, aligned_head_dim,
755 scale, out_vec,
756 sliding_window);
757 }
758 }
759
760#undef SLIDING_FLASH_IMPL_GEMMA4
761}
#define SLIDING_FLASH_IMPL_GEMMA4
void attention_forward_causal_head_major_gqa_flash_strided_gemma4(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens)
void attention_forward_causal_head_major_gqa_flash_strided_gemma4_token_output(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens)

References attention_forward_causal_head_major_gqa_flash_strided_gemma4(), attention_forward_causal_head_major_gqa_flash_strided_gemma4_token_output(), attention_output_index(), ck_sliding_attention_pick_threads(), ck_sliding_attention_work_fn(), ck_threadpool_dispatch_n(), ck_threadpool_global(), qkv_index(), and SLIDING_FLASH_IMPL_GEMMA4.

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4(), and attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_token_output().

◆ attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_token_output()

void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_token_output ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  sliding_window 
)

Definition at line 782 of file attention_kernels_sliding.c.

794{
796 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
797 aligned_head_dim, kv_stride_tokens, sliding_window,
798 /*output_token_major=*/1);
799}

References attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

◆ attention_forward_causal_head_major_shared_kv_sliding_gemma4()

void attention_forward_causal_head_major_shared_kv_sliding_gemma4 ( const float *  q,
float *  output,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  sliding_window 
)

Definition at line 801 of file attention_kernels_sliding.c.

810{
812 q, q, q, output, num_heads, num_heads, num_tokens,
813 head_dim, aligned_head_dim, kv_stride_tokens, sliding_window
814 );
815}
void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)

References attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4().

◆ attention_forward_decode_head_major_gqa_flash_sliding()

void attention_forward_decode_head_major_gqa_flash_sliding ( const float *  q_token,
const float *  k_cache,
const float *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window 
)

Definition at line 817 of file attention_kernels_sliding.c.

829{
830 if (!q_token || !k_cache || !v_cache || !out_token) {
831 return;
832 }
833 if (num_heads <= 0 || num_kv_heads <= 0 || cache_capacity <= 0) {
834 return;
835 }
836 if (kv_tokens <= 0 || kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
837 return;
838 }
839
840 /* Debug escape hatch:
841 * Route decode through non-sliding flash attention when requested to
842 * quickly A/B check sliding-window kernel correctness.
843 */
844 if (getenv("CK_FORCE_NONSLIDING_ATTN")) {
846 q_token, k_cache, v_cache, out_token,
847 num_heads, num_kv_heads, kv_tokens, cache_capacity,
848 head_dim, aligned_head_dim
849 );
850 return;
851 }
852
853 const float scale = 1.0f / sqrtf((float)head_dim);
854 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
855
856 // Compute effective KV tokens based on sliding window
857 int effective_kv_tokens = kv_tokens;
858 if (sliding_window > 0 && sliding_window < kv_tokens) {
859 effective_kv_tokens = sliding_window;
860 }
861
862 // Guard against empty window (shouldn't happen with kv_tokens >= 1)
863 if (effective_kv_tokens <= 0) {
864 return;
865 }
866
867 // Offset to start reading from the last effective_kv_tokens entries
868 int kv_start_offset = kv_tokens - effective_kv_tokens;
869
870#if defined(__AVX512F__)
871 #define SLIDING_DECODE_IMPL attention_flash_query_sliding_avx512
872#elif defined(__AVX2__)
873 #define SLIDING_DECODE_IMPL attention_flash_query_sliding_avx2
874#elif defined(__AVX__)
875 #define SLIDING_DECODE_IMPL attention_flash_query_sliding_avx
876#else
877 #define SLIDING_DECODE_IMPL attention_flash_query_sliding
878#endif
879
880 for (int h = 0; h < num_heads; ++h) {
881 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
882 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
883 // Offset K/V pointer to start from the first token in the sliding window
884 const float *k_head = k_cache + (size_t)kv_head * head_stride
885 + (size_t)kv_start_offset * (size_t)aligned_head_dim;
886 const float *v_head = v_cache + (size_t)kv_head * head_stride
887 + (size_t)kv_start_offset * (size_t)aligned_head_dim;
888 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
889
890 // Use query_pos relative to the windowed KV (last token = effective_kv_tokens - 1)
891 // sliding_window = 0 since we've already windowed via K/V pointer offset
892 SLIDING_DECODE_IMPL(q_head, k_head, v_head,
893 /*query_pos=*/effective_kv_tokens - 1,
894 /*kv_tokens=*/effective_kv_tokens,
895 head_dim, aligned_head_dim,
896 scale, out_head,
897 /*sliding_window=*/0);
898 }
899
900#undef SLIDING_DECODE_IMPL
901}
#define SLIDING_DECODE_IMPL
void attention_forward_decode_head_major_gqa_flash(const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)

References attention_forward_decode_head_major_gqa_flash(), and SLIDING_DECODE_IMPL.

◆ attention_forward_decode_head_major_gqa_flash_sliding_gemma4()

void attention_forward_decode_head_major_gqa_flash_sliding_gemma4 ( const float *  q_token,
const float *  k_cache,
const float *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window 
)

Definition at line 903 of file attention_kernels_sliding.c.

915{
916 if (!q_token || !k_cache || !v_cache || !out_token) {
917 return;
918 }
919 if (num_heads <= 0 || num_kv_heads <= 0 || cache_capacity <= 0) {
920 return;
921 }
922 if (kv_tokens <= 0 || kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
923 return;
924 }
925
926 if (getenv("CK_FORCE_NONSLIDING_ATTN")) {
928 q_token, k_cache, v_cache, out_token,
929 num_heads, num_kv_heads, kv_tokens, cache_capacity,
930 head_dim, aligned_head_dim
931 );
932 return;
933 }
934
935 const float scale = 1.0f;
936 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
937 int effective_kv_tokens = kv_tokens;
938 if (sliding_window > 0 && sliding_window < kv_tokens) {
939 effective_kv_tokens = sliding_window;
940 }
941 if (effective_kv_tokens <= 0) {
942 return;
943 }
944 int kv_start_offset = kv_tokens - effective_kv_tokens;
945
946#if defined(__AVX512F__)
947 #define SLIDING_DECODE_IMPL_GEMMA4 attention_flash_query_sliding_avx512
948#elif defined(__AVX2__)
949 #define SLIDING_DECODE_IMPL_GEMMA4 attention_flash_query_sliding_avx2
950#elif defined(__AVX__)
951 #define SLIDING_DECODE_IMPL_GEMMA4 attention_flash_query_sliding_avx
952#else
953 #define SLIDING_DECODE_IMPL_GEMMA4 attention_flash_query_sliding
954#endif
955
956 for (int h = 0; h < num_heads; ++h) {
957 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
958 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
959 const float *k_head = k_cache + (size_t)kv_head * head_stride
960 + (size_t)kv_start_offset * (size_t)aligned_head_dim;
961 const float *v_head = v_cache + (size_t)kv_head * head_stride
962 + (size_t)kv_start_offset * (size_t)aligned_head_dim;
963 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
964
965 SLIDING_DECODE_IMPL_GEMMA4(q_head, k_head, v_head,
966 /*query_pos=*/effective_kv_tokens - 1,
967 /*kv_tokens=*/effective_kv_tokens,
968 head_dim, aligned_head_dim,
969 scale, out_head,
970 /*sliding_window=*/0);
971 }
972
973#undef SLIDING_DECODE_IMPL_GEMMA4
974}
#define SLIDING_DECODE_IMPL_GEMMA4
void attention_forward_decode_head_major_gqa_flash_gemma4(const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)

References attention_forward_decode_head_major_gqa_flash_gemma4(), and SLIDING_DECODE_IMPL_GEMMA4.

Referenced by attention_forward_decode_head_major_shared_kv_sliding_gemma4().

◆ attention_forward_decode_head_major_shared_kv_sliding_gemma4()

void attention_forward_decode_head_major_shared_kv_sliding_gemma4 ( const float *  q_token,
const float *  k_cache,
const float *  v_cache,
float *  out_token,
int  num_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window 
)

Definition at line 976 of file attention_kernels_sliding.c.

987{
989 q_token, k_cache, v_cache, out_token, num_heads, num_heads,
990 kv_tokens, cache_capacity, head_dim, aligned_head_dim, sliding_window
991 );
992}
void attention_forward_decode_head_major_gqa_flash_sliding_gemma4(const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)

References attention_forward_decode_head_major_gqa_flash_sliding_gemma4().

◆ attention_output_index()

static size_t attention_output_index ( int  h,
int  t,
int  num_heads,
int  num_tokens,
int  aligned_head_dim,
int  output_token_major 
)
inlinestatic

Definition at line 26 of file attention_kernels_sliding.c.

32{
33 if (output_token_major) {
34 return ((size_t)t * (size_t)num_heads + (size_t)h)
35 * (size_t)aligned_head_dim;
36 }
37 return qkv_index(h, t, 0, num_tokens, aligned_head_dim);
38}

References qkv_index().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding(), attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl(), and ck_sliding_attention_compute_one().

◆ ck_env_int_default()

static int ck_env_int_default ( const char *  name,
int  fallback 
)
static

Definition at line 472 of file attention_kernels_sliding.c.

473{
474 const char *v = getenv(name);
475 if (!v || !v[0]) return fallback;
476 char *end = NULL;
477 long parsed = strtol(v, &end, 10);
478 if (end == v || (end && *end != '\0')) return fallback;
479 if (parsed < 0) parsed = 0;
480 if (parsed > 1 << 20) parsed = 1 << 20;
481 return (int)parsed;
482}
uint32_t end
Definition utf8.c:215

References end.

Referenced by ck_sliding_attention_pick_threads().

◆ ck_sliding_attention_compute_one()

static void ck_sliding_attention_compute_one ( const ck_sliding_attention_args_t *  a,
int  job 
)
static

Definition at line 509 of file attention_kernels_sliding.c.

511{
512 if (!a || job < 0) return;
513
514 const int T = a->num_tokens;
515 const size_t kv_head_stride = (size_t)a->kv_stride_tokens * (size_t)a->aligned_head_dim;
516
517#if defined(__AVX512F__)
518 #define CK_SLIDING_FLASH_IMPL attention_flash_query_sliding_avx512
519#elif defined(__AVX2__)
520 #define CK_SLIDING_FLASH_IMPL attention_flash_query_sliding_avx2
521#elif defined(__AVX__)
522 #define CK_SLIDING_FLASH_IMPL attention_flash_query_sliding_avx
523#else
524 #define CK_SLIDING_FLASH_IMPL attention_flash_query_sliding
525#endif
526
527 const int h = job / T;
528 const int i = job - h * T;
529 const int kv_head = (int)((long long)h * (long long)a->num_kv_heads /
530 (long long)a->num_heads);
531 const float *k_head = a->k + (size_t)kv_head * kv_head_stride;
532 const float *v_head = a->v + (size_t)kv_head * kv_head_stride;
533 const float *q_vec = a->q + qkv_index(h, i, 0, T, a->aligned_head_dim);
534 float *out_vec = a->output + attention_output_index(
535 h, i, a->num_heads, T, a->aligned_head_dim, a->output_token_major);
536
537 CK_SLIDING_FLASH_IMPL(q_vec, k_head, v_head,
538 /*query_pos=*/i,
539 /*kv_tokens=*/T,
540 a->head_dim, a->aligned_head_dim,
541 a->scale, out_vec,
542 a->sliding_window);
543
544#undef CK_SLIDING_FLASH_IMPL
545}
#define CK_SLIDING_FLASH_IMPL

References attention_output_index(), CK_SLIDING_FLASH_IMPL, and qkv_index().

Referenced by ck_sliding_attention_work_fn().

◆ ck_sliding_attention_parallel_disabled()

static int ck_sliding_attention_parallel_disabled ( void  )
static

Definition at line 484 of file attention_kernels_sliding.c.

485{
486 const char *v = getenv("CK_DISABLE_SLIDING_ATTN_PARALLEL");
487 return v && v[0] && v[0] != '0';
488}

Referenced by ck_sliding_attention_pick_threads().

◆ ck_sliding_attention_pick_threads()

static int ck_sliding_attention_pick_threads ( ck_threadpool_t *  pool,
int  total_jobs,
int  num_tokens,
int  head_dim 
)
static

Definition at line 490 of file attention_kernels_sliding.c.

494{
495 if (!pool || total_jobs <= 0) return 1;
497 if (ck_threadpool_thread_id(pool) > 0) return 1;
498
499 const int min_tokens = ck_env_int_default("CK_SLIDING_ATTN_PARALLEL_MIN_TOKENS", 128);
500 if (num_tokens < min_tokens || head_dim < 8) return 1;
501
502 int active = ck_threadpool_n_threads(pool);
503 const int cap = ck_env_int_default("CK_SLIDING_ATTN_THREAD_CAP", active);
504 if (cap > 0 && active > cap) active = cap;
505 if (active > total_jobs) active = total_jobs;
506 return active > 1 ? active : 1;
507}
static int ck_env_int_default(const char *name, int fallback)
static int ck_sliding_attention_parallel_disabled(void)
int ck_threadpool_thread_id(const ck_threadpool_t *pool)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)

References ck_env_int_default(), ck_sliding_attention_parallel_disabled(), ck_threadpool_n_threads(), and ck_threadpool_thread_id().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding(), and attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

◆ ck_sliding_attention_work_fn()

static void ck_sliding_attention_work_fn ( int  ith,
int  nth,
void *  args 
)
static

Definition at line 547 of file attention_kernels_sliding.c.

548{
549 const ck_sliding_attention_args_t *a = (const ck_sliding_attention_args_t *)args;
550 if (!a || ith < 0 || nth <= 0 || ith >= nth) return;
551 const int total_jobs = a->num_heads * a->num_tokens;
552 for (int job = ith; job < total_jobs; job += nth) {
554 }
555}
static void ck_sliding_attention_compute_one(const ck_sliding_attention_args_t *a, int job)

References ck_sliding_attention_compute_one().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding(), and attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

◆ qkv_index()

static size_t qkv_index ( int  h,
int  t,
int  d,
int  num_tokens,
int  aligned_head_dim 
)
inlinestatic

Definition at line 16 of file attention_kernels_sliding.c.

21{
22 return ((size_t)h * (size_t)num_tokens + (size_t)t) * (size_t)aligned_head_dim
23 + (size_t)d;
24}

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding(), attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl(), attention_output_index(), and ck_sliding_attention_compute_one().