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

Attention score/softmax/output kernels with SIMD (SSE/AVX/AVX512) More...

#include "bf16_utils.h"
#include "attention_oracle_ggml.h"
#include "ckernel_engine.h"
#include "ck_threadpool.h"
#include <dlfcn.h>
#include <limits.h>
#include <math.h>
#include <float.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include "ck_speed_profiles.h"
#include <string.h>

Go to the source code of this file.

Macros

#define CK_ENABLE_LLAMA_CPP_PARITY   0
 
#define CK_GGML_FA_TILE_KV   64
 
#define CK_GGML_FA_TILE_Q   64
 
#define CK_GGML_FA_TILE_Q_LARGE   336
 
#define CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS   1536
 
#define CK_MUSE_PREFILL_QUERY_TILE   1024
 
#define CK_NOINLINE
 
#define CK_OPTNONE
 
#define FLASH_QUERY_IMPL   attention_flash_query_causal
 
#define FLASH_QUERY_IMPL   attention_flash_query_causal
 
#define FLASH_QUERY_IMPL_DECODE   attention_flash_query_causal
 
#define RTLD_DEFAULT   ((void *)0)
 

Typedefs

typedef float(* ck_attention_math_f32_fn) (float)
 

Functions

void attention_backward_causal_head_major (const float *d_output, const float *q, const float *k, const float *v, const float *attn_weights, float *d_q, float *d_k, float *d_v, float *d_scores, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)
 
void attention_backward_causal_head_major_gqa (const float *d_output, const float *q, const float *k, const float *v, const float *attn_weights, float *d_q, float *d_k, float *d_v, float *d_scores, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)
 
void attention_backward_causal_head_major_gqa_bf16 (const uint16_t *d_output, float *d_x, const uint16_t *q, const uint16_t *k, const uint16_t *v, const float *attn_weights, float *d_q, float *d_k, float *d_v, float *d_scores, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window, float *scratch_d_output, float *scratch_q, float *scratch_k, float *scratch_v)
 
static void attention_flash_query_causal (const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)
 
static void attention_flash_query_causal_exact (const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)
 
static void attention_flash_query_causal_exact_f16kv (const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)
 
static void attention_flash_query_causal_exact_prerounded_f16kv (const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)
 
void attention_forward_causal_head_major (const float *q, const float *k, const float *v, float *scores, float *output, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)
 
void attention_forward_causal_head_major_exact (const float *q, const float *k, const float *v, float *scores, float *output, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)
 
void attention_forward_causal_head_major_gqa (const float *q, const float *k, const float *v, float *scores, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)
 
void attention_forward_causal_head_major_gqa_bf16 (const uint16_t *q, const uint16_t *k, const uint16_t *v, float *scores, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window, float *scratch_q, float *scratch_k, float *scratch_v)
 
void attention_forward_causal_head_major_gqa_exact (const float *q, const float *k, const float *v, float *scores, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)
 
void attention_forward_causal_head_major_gqa_flash (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)
 
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)
 
void attention_forward_causal_head_major_gqa_flash_strided_f16kv (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_f16kv_serial (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_f16kv_workspace (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, float *rounded_kv, size_t rounded_kv_bytes)
 
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)
 
void attention_forward_causal_head_major_gqa_flash_strided_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)
 
void attention_forward_causal_head_major_gqa_llama_regular_strided_sliding_workspace (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, float *scores, size_t scores_bytes, float *value_columns, size_t value_columns_bytes, float *scaled_scores, size_t scaled_scores_bytes)
 
void attention_forward_causal_head_major_gqa_muse_eager_bf16_storage (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, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
void attention_forward_causal_head_major_gqa_muse_eager_bf16_storage_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, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, void *gqa_workspace, size_t gqa_workspace_bytes, int route_num_heads, int route_num_kv_heads, int route_head_dim, int route_query_tokens, int route_min_kv_tokens, int route_workers, int route_query_tile_size, int route_concurrent_query_tiles)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int query_tile_size, int concurrent_query_tiles, void *workspace, size_t workspace_bytes)
 
size_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes (int num_heads, int num_kv_heads, int head_dim, int workers, int query_tile_size, int concurrent_query_tiles)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_qtile64_schedule (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_prefill_schedule_t schedule)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_sliding_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_full_bf16cache_pytorch_contract (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_contract_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_sliding_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)
 
void attention_forward_causal_head_major_shared_kv_gemma4 (const float *q, float *output, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens)
 
void attention_forward_chunk_head_major_gqa_flash_gemma4 (const float *q_chunk, const float *k_cache, const float *v_cache, float *out_chunk, int num_heads, int num_kv_heads, int q_tokens, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_gemma4_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_regular_noscale (const float *q_token, const uint16_t *k_cache, const uint16_t *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)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_sliding_gemma4_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)
 
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)
 
void attention_forward_decode_head_major_gqa_flash_f16cache (const float *q_token, const uint16_t *k_cache, const uint16_t *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)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_flash_f16cache_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)
 
void attention_forward_decode_head_major_gqa_flash_f16cache_split (const float *q_token, const uint16_t *k_cache, const uint16_t *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 split_chunks)
 
static void attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned (const float *q_token, const uint16_t *k_cache, const uint16_t *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 split_chunks, int partition_tokens, int kv_start, float attention_scale)
 
void attention_forward_decode_head_major_gqa_flash_f16kv (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)
 
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)
 
void attention_forward_decode_head_major_gqa_llama_regular_sliding_workspace (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int live_tokens, int kv_stride_tokens, int head_dim, int aligned_head_dim, int sliding_window, float *scores, size_t scores_bytes, float *value_columns, size_t value_columns_bytes, float *scaled_scores, size_t scaled_scores_bytes)
 
void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage (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, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage_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, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
void attention_forward_decode_head_major_gqa_regular (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)
 WARNING: This is NOT true flash attention!
 
void attention_forward_decode_head_major_shared_kv_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)
 
void attention_forward_full_head_major_gqa_exact_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)
 
void attention_forward_full_head_major_gqa_flash (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)
 
void attention_forward_full_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)
 
void attention_forward_full_head_major_gqa_flash_strided_bf16_storage (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_full_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_full_head_major_gqa_ggml_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)
 
void attention_forward_full_head_major_gqa_ggml_strided_workspace (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, float *score_rows, size_t score_rows_bytes, float *v_columns, size_t v_columns_bytes, float *probability_row, size_t probability_row_bytes)
 
void attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage (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_full_head_major_gqa_pytorch_cpu_flash_bf16_storage_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)
 
void attention_forward_full_head_major_gqa_sdpa_bf16_storage (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_full_head_major_gqa_tiled336_f16kv_fp32_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)
 
void attention_forward_full_head_major_gqa_tiled64_f16kv_fp32_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)
 
void attention_forward_full_head_major_gqa_tiled_f16kv_fp32_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)
 
static void attention_forward_head_major_gqa_flash_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 causal, int round_full_kv_fp16, int output_token_major, float scale)
 
static int attention_forward_head_major_gqa_unfused_f16_strict (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 causal, int output_token_major, float scale, int debug_layer_id)
 
void attention_forward_mixed_visual_chunk_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, int visual_start, int visual_tokens)
 
static void attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_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 visual_start, int visual_tokens, int output_token_major)
 
void attention_forward_mixed_visual_chunk_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, int visual_start, int visual_tokens)
 
int attention_forward_query_key_head_major_f32 (const float *query, const float *key, const float *value, float *output, float *score_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
int attention_forward_query_key_head_major_f32_decode_heads (const float *query, const float *key, const float *value, float *output, float *score_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
int attention_forward_query_key_head_major_f32_packed_k (const float *query, const float *key, const float *value, float *output, float *score_scratch, float *key_transpose_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
int attention_forward_query_key_head_major_tiled_f16kv_fp32 (const float *query, const float *key, const float *value, float *output, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
void attention_forward_sparse_token_major_gqa_bf16cache_pytorch_cpu_flash_contract (const float *query, const uint16_t *key_cache, const uint16_t *value_cache, const float *selected_indices, float *output, float *score_scratch, int rows, int query_heads, int kv_heads, int head_dim, int selection_width, int context_length, int position)
 
static size_t attention_output_index (int h, int token, int num_heads, int num_tokens, int aligned_head_dim, int token_major)
 
static void attention_query_full_exact_regular (const float *q_vec, const float *k_head, const float *v_cols, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *score_row, float *out_vec, int layer_id, int head_id, int query_id)
 
static void attention_query_full_ggml_regular (const float *q_vec, const float *k_head, const float *v_cols, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *score_row, float *out_vec, int layer_id, int head_id, int query_id)
 
static size_t ck_attention_align64_size (size_t value)
 
static void ck_attention_bf16_pytorch_flash_work (int ith, int nth, void *opaque)
 
int ck_attention_bf16_pytorch_gqa_available (void)
 
static void ck_attention_bf16_sdpa_work (int ith, int nth, void *opaque)
 
static void ck_attention_causal_f16kv_work (int ith, int nth, void *opaque)
 
static float ck_attention_dot_f16_llama (const uint16_t *x, const uint16_t *y, int n)
 
static float ck_attention_dot_f16_unfused_llama (const uint16_t *x, const uint16_t *y, int n)
 
static void ck_attention_f16_prefill_gqa_reuse_work (int ith, int nth, void *opaque)
 
static size_t ck_attention_f16_prefill_gqa_reuse_worker_bytes (int num_heads, int num_kv_heads, int head_dim, int workers, int query_tile_size, int concurrent_query_tiles)
 
static ck_attention_status_t ck_attention_f16_prefill_qtile64_dispatch (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int cache_is_bf16, float attention_scale, size_t q_head_stride, size_t output_head_stride, ck_attention_prefill_schedule_t schedule)
 
static void ck_attention_f16_prefill_qtile64_work (int ith, int nth, void *opaque)
 
static float ck_attention_f16_reduce_expf (float value)
 
static void ck_attention_f16_split_work (int ith, int nth, void *opaque)
 
static void ck_attention_flash_query_auto (const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)
 
static ck_attention_status_t ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments, ck_attention_prefill_schedule_t schedule)
 
static ck_attention_status_t ck_attention_forward_decode_f16cache_gemma4 (const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)
 
static void ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_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, int query_tile_size)
 
static int ck_attention_forward_query_key_head_major_f32_run (const float *query, const float *key, const float *value, float *output, float *score_scratch, float *key_transpose_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
static int ck_attention_full_bf16_pytorch_flash (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 output_token_major)
 
static int ck_attention_full_bf16_sdpa_amx_range (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 head_begin, int head_step, int output_token_major)
 
static int ck_attention_full_bf16_sdpa_tiled (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)
 
static int ck_attention_full_bf16_sdpa_tiled_range (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 head_begin, int head_step)
 
static void ck_attention_full_grid_work (int ith, int nth, void *opaque)
 
static void ck_attention_full_tiled_f16kv_fp32_range (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 query_tile_size, int ith, int nth)
 
static void ck_attention_full_tiled_f16kv_fp32_work (int ith, int nth, void *opaque)
 
static int ck_attention_ggml_out_graph_enabled (void)
 
static void ck_attention_gqa_team_barrier_wait (ck_attention_gqa_team_barrier_t *barrier)
 
static void ck_attention_llama_regular_impl (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int query_tokens, int live_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window, float *scores, size_t scores_bytes, float *value_columns, size_t value_columns_bytes, float *scaled_scores, size_t scaled_scores_bytes, int batched_prefill)
 
static void ck_attention_llama_regular_query (const float *query, const float *key_head, const float *value_columns, float *output, float *scores, float *scaled_scores, int live_tokens, int padded_tokens, int query_position, int head_dim, int aligned_head_dim, int sliding_window, int batched_prefill)
 
static void ck_attention_mad_f16_llama (uint16_t *y, const uint16_t *x, float scale, int n)
 
static void ck_attention_matmul_f32_accum (float *c, const float *a, const float *b, int m, int k, int n)
 
static void ck_attention_muse_eager_bf16_storage_impl (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int query_tokens, int kv_tokens, int kv_stride_tokens, int head_dim, int aligned_head_dim, int sliding_window, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
static int ck_attention_parallel_enabled (int total_queries, int num_tokens, int head_dim)
 
static int ck_attention_pick_active_threads (const ck_threadpool_t *pool, int total_queries, int num_tokens)
 
static ck_attention_status_t ck_attention_prefill_append_f16cache_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)
 
float ck_attention_pytorch_sdpa_scale_f32 (int head_dim)
 
static void ck_attention_query_key_f32_head_work (int ith, int nth, void *opaque)
 
static void ck_attention_query_key_f32_transpose_work (int ith, int nth, void *opaque)
 
static void ck_attention_query_key_f32_work (int ith, int nth, void *opaque)
 
static float ck_attention_reference_expf (float value)
 
static int ck_attention_reverse_out_dot_enabled (void)
 
static void ck_attention_scale_f16_llama (uint16_t *y, float scale, int n)
 
int ck_attention_sparse_bf16_pytorch_gqa_available (void)
 
static float ck_attention_strict_scale_f32 (int head_dim)
 
static int ck_attention_strict_unfused_f16_enabled (void)
 
static void ck_attention_trace (const char *branch, int layer_id, int head_id)
 
static void ck_attention_trace_float (const char *tag, int layer_id, int head_id, float value)
 
static void ck_attention_trace_query (const char *tag, int layer_id, int head_id, int query_id, int value)
 
static float ck_attention_u16_cache_to_f32 (uint16_t value, int cache_is_bf16)
 
static int ck_attention_vec_dump_enabled (void)
 
static void ck_attention_vec_dump_exact_query (const float *q_vec, const float *k_head, const float *out_vec, int kv_tokens, int head_dim, int aligned_head_dim, float scale, int layer_id, int head_id, int query_id)
 
static int ck_attention_vec_dump_next_layer_id (void)
 
static int ck_attention_vec_dump_parse_env_int (const char *name, int *out)
 
static void ck_attention_vec_dump_selected_query (const float *raw_scores, const float *probs, const float *out_vec, const float *v_cols, int kv_tokens, int head_dim, int layer_id, int head_id, int query_id)
 
static int ck_attention_vec_dump_should_emit (int layer_id, int head_id, int query_id)
 
static void ck_attention_vec_dump_tensor (const char *name, int layer_id, int query_id, const float *data, size_t elem_count)
 
static int ck_attention_vec_dump_vcols_enabled (void)
 
static float ck_bf16_dot_contract (const float *a, const float *b, int count)
 
static float ck_ggml_vec_dot_f32_contig (const float *x, const float *y, int n)
 
static double ck_ggml_vec_soft_max_row (int n, float *y, const float *x, float max)
 
static int ck_llama_kv_pad_256 (int live_tokens, int capacity)
 
static float ck_llama_regular_dot_f16 (const float *a, const float *b, int count)
 
static float ck_llama_regular_gemm_f16 (const float *probability, const float *value_column, int count)
 
static void ck_llama_regular_prefill_work (int ith, int nth, void *opaque)
 
static void ck_local_fp16_to_fp32_2d (const uint16_t *src, float *dst, int rows, int cols, int src_stride, int dst_stride)
 
static void ck_local_fp16_to_fp32_row (const uint16_t *src, float *dst, int n)
 
static size_t ck_muse_attention_checked_product (size_t left, size_t right, const char *label)
 
static void ck_round_fp16_buffer (const float *src, float *dst, size_t count)
 
static float ck_round_fp16_scalar (float x)
 
static float ck_vec_dot_f32_reverse_strict (const float *x, const float *y, int n)
 
static float ck_vec_dot_f32_strict (const float *x, const float *y, int n)
 
static float ck_vec_dot_f32x_f32_to_f32_via_f64 (const float *x, const float *y, int n)
 
static float ck_vec_max_f32_contig (const float *x, int n)
 
static void ck_vec_scale_f32_inplace (float *x, int n, float scale)
 
static void convert_bf16_tensor_to_buf (const uint16_t *src, float *dst, size_t count)
 
static size_t qkv_index (int h, int t, int d, int num_tokens, int aligned_head_dim)
 
static size_t score_index (int h, int i, int j, int aligned_context_window)
 

Variables

static int ck_attention_vec_dump_layer_seq = 0
 
static const char ck_attention_vec_dump_magic [8] = {'C', 'K', 'D', 'M', 'P', '\0', '\0', '\0'}
 
static const uint32_t ck_attention_vec_dump_version = 1u
 

Detailed Description

Attention score/softmax/output kernels with SIMD (SSE/AVX/AVX512)

CK-ENGINE KERNEL RULES:

  1. NO malloc/free - memory via bump allocator, pointers passed in
  2. NO OpenMP - parallelization at orchestrator/codegen layer
  3. API must define: inputs, outputs, workspace, and memory layouts
  4. Pure computation - deterministic, no side effects

After changes: make test && make llamacpp-parity-full

Attention: softmax(Q @ K^T / sqrt(d)) @ V Supports GQA (grouped-query attention) with head broadcasting.

Definition in file attention_kernels.c.

Macro Definition Documentation

◆ CK_ENABLE_LLAMA_CPP_PARITY

#define CK_ENABLE_LLAMA_CPP_PARITY   0

Definition at line 19 of file attention_kernels.c.

◆ CK_GGML_FA_TILE_KV

#define CK_GGML_FA_TILE_KV   64

Definition at line 2890 of file attention_kernels.c.

◆ CK_GGML_FA_TILE_Q

#define CK_GGML_FA_TILE_Q   64

Definition at line 2888 of file attention_kernels.c.

◆ CK_GGML_FA_TILE_Q_LARGE

#define CK_GGML_FA_TILE_Q_LARGE   336

Definition at line 2889 of file attention_kernels.c.

◆ CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS

#define CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS   1536

Definition at line 2891 of file attention_kernels.c.

◆ CK_MUSE_PREFILL_QUERY_TILE

#define CK_MUSE_PREFILL_QUERY_TILE   1024

Definition at line 9051 of file attention_kernels.c.

◆ CK_NOINLINE

#define CK_NOINLINE

Definition at line 402 of file attention_kernels.c.

◆ CK_OPTNONE

#define CK_OPTNONE

Definition at line 410 of file attention_kernels.c.

◆ FLASH_QUERY_IMPL [1/2]

#define FLASH_QUERY_IMPL   attention_flash_query_causal

◆ FLASH_QUERY_IMPL [2/2]

#define FLASH_QUERY_IMPL   attention_flash_query_causal

◆ FLASH_QUERY_IMPL_DECODE

#define FLASH_QUERY_IMPL_DECODE   attention_flash_query_causal

◆ RTLD_DEFAULT

#define RTLD_DEFAULT   ((void *)0)

Definition at line 32 of file attention_kernels.c.

Typedef Documentation

◆ ck_attention_math_f32_fn

typedef float(* ck_attention_math_f32_fn) (float)

Definition at line 1241 of file attention_kernels.c.

Function Documentation

◆ attention_backward_causal_head_major()

void attention_backward_causal_head_major ( const float *  d_output,
const float *  q,
const float *  k,
const float *  v,
const float *  attn_weights,
float *  d_q,
float *  d_k,
float *  d_v,
float *  d_scores,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window 
)

Causal attention backward (non-GQA version)

Test:

test_attention_backward.py::TestAttentionBackward::test_backward

test_attention_backward.py::TestAttentionBackward::test_backward_vs_separate

test_parity.py::test_attention_backward_parity

Non-GQA version where num_heads == num_kv_heads. Simpler than GQA, no head broadcasting needed.

After changes: make test && make llamacpp-parity-full

Definition at line 9931 of file attention_kernels.c.

9946{
9948 d_output, q, k, v, attn_weights,
9949 d_q, d_k, d_v, d_scores,
9950 num_heads, num_heads, // num_kv_heads == num_heads
9951 num_tokens, head_dim, aligned_head_dim, aligned_context_window);
9952}
void attention_backward_causal_head_major_gqa(const float *d_output, const float *q, const float *k, const float *v, const float *attn_weights, float *d_q, float *d_k, float *d_v, float *d_scores, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)

References attention_backward_causal_head_major_gqa().

◆ attention_backward_causal_head_major_gqa()

void attention_backward_causal_head_major_gqa ( const float *  d_output,
const float *  q,
const float *  k,
const float *  v,
const float *  attn_weights,
float *  d_q,
float *  d_k,
float *  d_v,
float *  d_scores,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window 
)

GQA causal attention backward (score-matrix version)

Test:

test_attention_backward.py::TestAttentionBackwardGQA::test_gqa_backward

test_attention_backward.py::TestAttentionBackwardGQA::test_gqa_vs_separate

test_parity.py::test_attention_backward_parity

Computes dQ, dK, dV given dOutput and attention weights. Supports grouped-query attention with head broadcasting.

After changes: make test && make llamacpp-parity-full

Definition at line 9792 of file attention_kernels.c.

9808{
9809 const float scale = 1.0f / sqrtf((float)head_dim);
9810 int T = num_tokens;
9811 int H = num_heads;
9812 int H_kv = num_kv_heads;
9813 int hd = head_dim;
9814 int ad = aligned_head_dim;
9815 int aw = aligned_context_window;
9816
9817 const size_t d_q_elems = (size_t)H * (size_t)T * (size_t)ad;
9818 const size_t kv_elems = (size_t)H_kv * (size_t)T * (size_t)ad;
9819 /* Zero the aligned outputs so padded lanes never leak garbage to downstream GEMMs. */
9820 for (size_t idx = 0; idx < d_q_elems; ++idx) {
9821 d_q[idx] = 0.0f;
9822 }
9823 for (size_t idx = 0; idx < kv_elems; ++idx) {
9824 d_k[idx] = 0.0f;
9825 d_v[idx] = 0.0f;
9826 }
9827
9828 // Process each query head
9829 for (int h = 0; h < H; ++h) {
9830 // Which KV head does this query head use?
9831 int kv_h = (int)((long long)h * (long long)H_kv / (long long)H);
9832
9833 // ----------------------------------------------------------------
9834 // Step 1: d_weights = d_output @ V^T and d_v += weights^T @ d_output
9835 // ----------------------------------------------------------------
9836 // For each query position i, compute d_weights[i, j] for j <= i
9837 // and accumulate d_v[j] contributions
9838
9839 for (int i = 0; i < T; ++i) {
9840 size_t d_out_base = qkv_index(h, i, 0, T, ad);
9841
9842 for (int j = 0; j <= i; ++j) {
9843 size_t v_base = qkv_index(kv_h, j, 0, T, ad);
9844 size_t w_idx = score_index(h, i, j, aw);
9845 float w = attn_weights[w_idx];
9846
9847 // d_weights[h, i, j] = d_output[h, i, :] @ v[kv_h, j, :]^T
9848 float dot = 0.0f;
9849 for (int dd = 0; dd < hd; ++dd) {
9850 dot += d_output[d_out_base + dd] * v[v_base + dd];
9851 }
9852 d_scores[w_idx] = dot;
9853
9854 // d_v[kv_h, j, :] += weights[h, i, j] * d_output[h, i, :]
9855 for (int dd = 0; dd < hd; ++dd) {
9856 d_v[v_base + dd] += w * d_output[d_out_base + dd];
9857 }
9858 }
9859
9860 // Zero out upper triangle of d_scores
9861 for (int j = i + 1; j < T; ++j) {
9862 d_scores[score_index(h, i, j, aw)] = 0.0f;
9863 }
9864 /* Scores scratch uses aligned_context_window, zero the padded columns. */
9865 for (int j = T; j < aw; ++j) {
9866 d_scores[score_index(h, i, j, aw)] = 0.0f;
9867 }
9868 }
9869
9870 // ----------------------------------------------------------------
9871 // Step 2: Backward through softmax (in-place on d_scores for this head)
9872 // ----------------------------------------------------------------
9873 // d_scores = softmax_backward(d_scores, attn_weights)
9874 // Formula: d_score[i,j] = w[i,j] * (d_w[i,j] - sum_k(w[i,k] * d_w[i,k]))
9875
9876 for (int i = 0; i < T; ++i) {
9877 int base = h * aw * aw + i * aw;
9878
9879 // Compute dot product: sum_j w[i,j] * d_w[i,j]
9880 float dot_product = 0.0f;
9881 for (int j = 0; j <= i; ++j) {
9882 float wt = attn_weights[base + j];
9883 float dw = d_scores[base + j];
9884 dot_product += wt * dw;
9885 }
9886
9887 // Apply softmax backward formula
9888 for (int j = 0; j <= i; ++j) {
9889 float wt = attn_weights[base + j];
9890 float dw = d_scores[base + j];
9891 d_scores[base + j] = wt * (dw - dot_product);
9892 }
9893 }
9894
9895 // ----------------------------------------------------------------
9896 // Step 3: d_q = d_scores @ K * scale
9897 // d_k += d_scores^T @ Q * scale
9898 // ----------------------------------------------------------------
9899
9900 for (int i = 0; i < T; ++i) {
9901 size_t d_q_base = qkv_index(h, i, 0, T, ad);
9902 size_t q_base = qkv_index(h, i, 0, T, ad);
9903
9904 // d_q[h, i, :] = sum_j d_scores[h, i, j] * k[kv_h, j, :] * scale
9905 // d_k[kv_h, j, :] += d_scores[h, i, j] * q[h, i, :] * scale
9906 for (int j = 0; j <= i; ++j) {
9907 size_t k_base = qkv_index(kv_h, j, 0, T, ad);
9908 size_t d_k_base = qkv_index(kv_h, j, 0, T, ad);
9909 float ds = d_scores[score_index(h, i, j, aw)] * scale;
9910
9911 for (int dd = 0; dd < hd; ++dd) {
9912 d_q[d_q_base + dd] += ds * k[k_base + dd];
9913 d_k[d_k_base + dd] += ds * q[q_base + dd];
9914 }
9915 }
9916 }
9917 }
9918}
static size_t qkv_index(int h, int t, int d, int num_tokens, int aligned_head_dim)
static size_t score_index(int h, int i, int j, int aligned_context_window)

References qkv_index(), and score_index().

Referenced by attention_backward_causal_head_major(), attention_backward_causal_head_major_gqa_bf16(), and ck_layer_backward_rmsnorm_swiglu().

◆ attention_backward_causal_head_major_gqa_bf16()

void attention_backward_causal_head_major_gqa_bf16 ( const uint16_t *  d_output,
float *  d_x,
const uint16_t *  q,
const uint16_t *  k,
const uint16_t *  v,
const float *  attn_weights,
float *  d_q,
float *  d_k,
float *  d_v,
float *  d_scores,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window,
float *  scratch_d_output,
float *  scratch_q,
float *  scratch_k,
float *  scratch_v 
)

BF16 attention backward with caller-provided scratch buffers

Test:
bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_backward

Accepts BF16 inputs, converts to FP32, runs FP32 backward. Caller provides scratch buffers (no per-call malloc).

After changes: make test

Definition at line 9739 of file attention_kernels.c.

9760{
9761 (void)d_x;
9762 const size_t head_elems = (size_t)num_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
9763 const size_t kv_elems = (size_t)num_kv_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
9764
9765 if (!scratch_d_output || !scratch_q || !scratch_k || !scratch_v) return;
9766
9767 convert_bf16_tensor_to_buf(d_output, scratch_d_output, head_elems);
9768 convert_bf16_tensor_to_buf(q, scratch_q, head_elems);
9769 convert_bf16_tensor_to_buf(k, scratch_k, kv_elems);
9770 convert_bf16_tensor_to_buf(v, scratch_v, kv_elems);
9771
9772 attention_backward_causal_head_major_gqa(scratch_d_output, scratch_q, scratch_k, scratch_v,
9773 attn_weights,
9774 d_q, d_k, d_v, d_scores,
9775 num_heads, num_kv_heads,
9776 num_tokens, head_dim,
9777 aligned_head_dim, aligned_context_window);
9778 /* No free - caller owns scratch buffers */
9779}
static void convert_bf16_tensor_to_buf(const uint16_t *src, float *dst, size_t count)

References attention_backward_causal_head_major_gqa(), and convert_bf16_tensor_to_buf().

◆ attention_flash_query_causal()

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

Definition at line 2015 of file attention_kernels.c.

2023{
2024 // Online softmax:
2025 // m = running max, s = running sum(exp(score - m))
2026 // out = sum(exp(score - m) * v)
2027 float m = -INFINITY;
2028 float s = 0.0f;
2029
2030 for (int d = 0; d < head_dim; ++d) {
2031 out_vec[d] = 0.0f;
2032 }
2033
2034 for (int j = 0; j < kv_tokens; ++j) {
2035 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2036 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
2037
2038 float dot = 0.0f;
2039 for (int d = 0; d < head_dim; ++d) {
2040 dot += q_vec[d] * k_vec[d];
2041 }
2042 float score = dot * scale;
2043
2044 if (score > m) {
2045 float exp_m = (m == -INFINITY) ? 0.0f : expf(m - score);
2046 s *= exp_m;
2047 for (int d = 0; d < head_dim; ++d) {
2048 out_vec[d] *= exp_m;
2049 }
2050 s += 1.0f;
2051 for (int d = 0; d < head_dim; ++d) {
2052 out_vec[d] += v_vec[d];
2053 }
2054 m = score;
2055 } else {
2056 float e = expf(score - m);
2057 s += e;
2058 for (int d = 0; d < head_dim; ++d) {
2059 out_vec[d] += e * v_vec[d];
2060 }
2061 }
2062 }
2063
2064 float inv_s = 1.0f / s;
2065 for (int d = 0; d < head_dim; ++d) {
2066 out_vec[d] *= inv_s;
2067 }
2068 for (int d = head_dim; d < aligned_head_dim; ++d) {
2069 out_vec[d] = 0.0f;
2070 }
2071}
int32_t float * score
Definition tokenizer.h:328

References score.

Referenced by ck_attention_flash_query_auto().

◆ attention_flash_query_causal_exact()

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

Definition at line 2077 of file attention_kernels.c.

2085{
2086 if (kv_tokens <= 0) {
2087 for (int d = 0; d < aligned_head_dim; ++d) {
2088 out_vec[d] = 0.0f;
2089 }
2090 return;
2091 }
2092
2093 for (int d = 0; d < aligned_head_dim; ++d) {
2094 out_vec[d] = 0.0f;
2095 }
2096
2097 float max_score = -INFINITY;
2098 for (int j = 0; j < kv_tokens; ++j) {
2099 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2100 float dot = 0.0f;
2101 for (int d = 0; d < head_dim; ++d) {
2102 dot += q_vec[d] * k_vec[d];
2103 }
2104 float score = dot * scale;
2105 if (score > max_score) {
2106 max_score = score;
2107 }
2108 }
2109
2110 float sum = 0.0f;
2111 for (int j = 0; j < kv_tokens; ++j) {
2112 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2113 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
2114 float dot = 0.0f;
2115 for (int d = 0; d < head_dim; ++d) {
2116 dot += q_vec[d] * k_vec[d];
2117 }
2118 float score = dot * scale;
2119 float w = expf(score - max_score);
2120 sum += w;
2121 for (int d = 0; d < head_dim; ++d) {
2122 out_vec[d] += w * v_vec[d];
2123 }
2124 }
2125
2126 if (sum > 0.0f) {
2127 float inv_sum = 1.0f / sum;
2128 for (int d = 0; d < head_dim; ++d) {
2129 out_vec[d] *= inv_sum;
2130 }
2131 } else {
2132 for (int d = 0; d < head_dim; ++d) {
2133 out_vec[d] = 0.0f;
2134 }
2135 }
2136 for (int d = head_dim; d < aligned_head_dim; ++d) {
2137 out_vec[d] = 0.0f;
2138 }
2139}

References score.

Referenced by attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl().

◆ attention_flash_query_causal_exact_f16kv()

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

Definition at line 2193 of file attention_kernels.c.

2201{
2202 if (kv_tokens <= 0) {
2203 for (int d = 0; d < aligned_head_dim; ++d) {
2204 out_vec[d] = 0.0f;
2205 }
2206 return;
2207 }
2208
2209 for (int d = 0; d < aligned_head_dim; ++d) {
2210 out_vec[d] = 0.0f;
2211 }
2212
2213 // Mirror llama.cpp GGML flash-attention more closely:
2214 // - Q is converted through FP16 before the KQ dot
2215 // - V accumulation is rounded through FP16 at each update
2216 // - the softmax accumulator uses the online max/sum form
2217 float sum = 0.0f;
2218 float max_score = -INFINITY;
2219 for (int j = 0; j < kv_tokens; ++j) {
2220 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2221 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
2222 float dot = 0.0f;
2223 for (int d = 0; d < head_dim; ++d) {
2224 dot += ck_round_fp16_scalar(q_vec[d]) * ck_round_fp16_scalar(k_vec[d]);
2225 }
2226 float score = dot * scale;
2227
2228 const float prev_max = max_score;
2229 float max_scale = 1.0f;
2230 float value_scale = 1.0f;
2231
2232 if (score > max_score) {
2233 max_score = score;
2234 max_scale = isfinite(prev_max) ? expf(prev_max - max_score) : 0.0f;
2235 for (int d = 0; d < head_dim; ++d) {
2236 out_vec[d] = ck_round_fp16_scalar(out_vec[d] * max_scale);
2237 }
2238 } else {
2239 value_scale = expf(score - max_score);
2240 }
2241
2242 for (int d = 0; d < head_dim; ++d) {
2243 const float v_rounded = ck_round_fp16_scalar(v_vec[d]);
2244 const float updated = out_vec[d] + value_scale * v_rounded;
2245 out_vec[d] = ck_round_fp16_scalar(updated);
2246 }
2247
2248 sum = sum * max_scale + value_scale;
2249 }
2250
2251 if (sum > 0.0f) {
2252 float inv_sum = 1.0f / sum;
2253 for (int d = 0; d < head_dim; ++d) {
2254 out_vec[d] *= inv_sum;
2255 }
2256 } else {
2257 for (int d = 0; d < head_dim; ++d) {
2258 out_vec[d] = 0.0f;
2259 }
2260 }
2261 for (int d = head_dim; d < aligned_head_dim; ++d) {
2262 out_vec[d] = 0.0f;
2263 }
2264}
static float ck_round_fp16_scalar(float x)

References ck_round_fp16_scalar(), and score.

Referenced by attention_forward_decode_head_major_gqa_flash_f16kv(), attention_forward_decode_head_major_gqa_regular(), and ck_attention_causal_f16kv_work().

◆ attention_flash_query_causal_exact_prerounded_f16kv()

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

Definition at line 2268 of file attention_kernels.c.

2272{
2273 if (kv_tokens <= 0) {
2274 memset(out_vec, 0, (size_t)aligned_head_dim * sizeof(float));
2275 return;
2276 }
2277
2278 float *q_rounded = (float *)alloca((size_t)head_dim * sizeof(float));
2279 ck_round_fp16_buffer(q_vec, q_rounded, (size_t)head_dim);
2280 memset(out_vec, 0, (size_t)aligned_head_dim * sizeof(float));
2281
2282 float sum = 0.0f;
2283 float max_score = -INFINITY;
2284 for (int j = 0; j < kv_tokens; ++j) {
2285 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2286 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
2287 float dot = 0.0f;
2288 for (int d = 0; d < head_dim; ++d) {
2289 dot += q_rounded[d] * k_vec[d];
2290 }
2291 const float score = dot * scale;
2292 const float prev_max = max_score;
2293 float max_scale = 1.0f;
2294 float value_scale = 1.0f;
2295 if (score > max_score) {
2296 max_score = score;
2297 max_scale = isfinite(prev_max) ? expf(prev_max - max_score) : 0.0f;
2298 for (int d = 0; d < head_dim; ++d) {
2299 out_vec[d] = ck_round_fp16_scalar(out_vec[d] * max_scale);
2300 }
2301 } else {
2302 value_scale = expf(score - max_score);
2303 }
2304 for (int d = 0; d < head_dim; ++d) {
2305 const float updated = out_vec[d] + value_scale * v_vec[d];
2306 out_vec[d] = ck_round_fp16_scalar(updated);
2307 }
2308 sum = sum * max_scale + value_scale;
2309 }
2310
2311 if (sum > 0.0f) {
2312 const float inv_sum = 1.0f / sum;
2313 for (int d = 0; d < head_dim; ++d) {
2314 out_vec[d] *= inv_sum;
2315 }
2316 } else {
2317 memset(out_vec, 0, (size_t)head_dim * sizeof(float));
2318 }
2319}
static void ck_round_fp16_buffer(const float *src, float *dst, size_t count)

References ck_round_fp16_buffer(), ck_round_fp16_scalar(), and score.

Referenced by ck_attention_causal_f16kv_work().

◆ attention_forward_causal_head_major()

void attention_forward_causal_head_major ( const float *  q,
const float *  k,
const float *  v,
float *  scores,
float *  output,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window 
)

Causal attention forward (score-matrix version)

Test:

test_attention.py::TestAttentionForward::test_causal_forward

test_attention.py::TestAttentionForward::test_gqa_broadcast

test_attention.py::TestAttentionForward::test_exact_vs_fast

test_parity.py::test_attention_parity

Computes softmax(Q @ K^T / sqrt(d)) @ V with causal masking. Uses O(N^2) memory for scores matrix.

After changes: make test && make llamacpp-parity-full

Definition at line 1355 of file attention_kernels.c.

1365{
1366 const float scale = 1.0f / sqrtf((float)head_dim);
1367
1368 // Phase 1: compute scaled dot-product scores Q·K^T / sqrt(d_k),
1369 // lower triangle only (j <= i).
1370 for (int h = 0; h < num_heads; ++h) {
1371 for (int i = 0; i < num_tokens; ++i) {
1372 for (int j = 0; j <= i; ++j) {
1373 float dot = 0.0f;
1374 size_t base_q = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1375 size_t base_k = qkv_index(h, j, 0, num_tokens, aligned_head_dim);
1376
1377 for (int d = 0; d < head_dim; ++d) {
1378 dot += q[base_q + d] * k[base_k + d];
1379 }
1380
1381 scores[score_index(h, i, j, aligned_context_window)] = dot * scale;
1382 }
1383
1384 // Ensure upper triangle is zeroed so there are no stale values
1385 // before the softmax kernel runs.
1386 for (int j = i + 1; j < num_tokens; ++j) {
1387 scores[score_index(h, i, j, aligned_context_window)] = 0.0f;
1388 }
1389 }
1390 }
1391
1392 // Phase 2: apply causal row-wise softmax in-place over j <= i.
1394 num_heads,
1395 num_tokens,
1396 aligned_context_window);
1397
1398 // Phase 3: attention weights · V.
1399 for (int h = 0; h < num_heads; ++h) {
1400 for (int i = 0; i < num_tokens; ++i) {
1401 size_t out_base = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1402
1403 // Zero the full aligned head slice so padded dims stay clean.
1404 for (int d = 0; d < aligned_head_dim; ++d) {
1405 output[out_base + d] = 0.0f;
1406 }
1407
1408 // Weighted sum over causal positions.
1409 for (int j = 0; j <= i; ++j) {
1410 float w = scores[score_index(h, i, j, aligned_context_window)];
1411 size_t v_base = qkv_index(h, j, 0, num_tokens, aligned_head_dim);
1412
1413 for (int d = 0; d < head_dim; ++d) {
1414 output[out_base + d] += w * v[v_base + d];
1415 }
1416 }
1417 }
1418 }
1419}
void causal_softmax_head_major(float *scores, int num_heads, int num_tokens, int aligned_context_window)

References causal_softmax_head_major(), qkv_index(), and score_index().

◆ attention_forward_causal_head_major_exact()

void attention_forward_causal_head_major_exact ( const float *  q,
const float *  k,
const float *  v,
float *  scores,
float *  output,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window 
)

Causal attention forward (exact version using stdlib expf)

Test:

test_attention.py::TestAttentionForward::test_exact_single

test_attention.py::TestAttentionForward::test_exact_vs_fast

Uses standard library expf for numerical accuracy reference. Slower but provides maximum accuracy.

After changes: make test

Definition at line 1431 of file attention_kernels.c.

1441{
1442 const float scale = 1.0f / sqrtf((float)head_dim);
1443
1444 // Phase 1: compute scaled dot-product scores Q·K^T / sqrt(d_k),
1445 // lower triangle only (j <= i).
1446 for (int h = 0; h < num_heads; ++h) {
1447 for (int i = 0; i < num_tokens; ++i) {
1448 for (int j = 0; j <= i; ++j) {
1449 float dot = 0.0f;
1450 size_t base_q = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1451 size_t base_k = qkv_index(h, j, 0, num_tokens, aligned_head_dim);
1452
1453 for (int d = 0; d < head_dim; ++d) {
1454 dot += q[base_q + d] * k[base_k + d];
1455 }
1456
1457 scores[score_index(h, i, j, aligned_context_window)] = dot * scale;
1458 }
1459
1460 // Ensure upper triangle is zeroed so there are no stale values
1461 // before the softmax kernel runs.
1462 for (int j = i + 1; j < num_tokens; ++j) {
1463 scores[score_index(h, i, j, aligned_context_window)] = 0.0f;
1464 }
1465 }
1466 }
1467
1468 // Phase 2: apply causal row-wise softmax using exact expf.
1470 num_heads,
1471 num_tokens,
1472 aligned_context_window);
1473
1474 // Phase 3: attention weights · V.
1475 for (int h = 0; h < num_heads; ++h) {
1476 for (int i = 0; i < num_tokens; ++i) {
1477 size_t out_base = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1478
1479 // Zero the full aligned head slice so padded dims stay clean.
1480 for (int d = 0; d < aligned_head_dim; ++d) {
1481 output[out_base + d] = 0.0f;
1482 }
1483
1484 // Weighted sum over causal positions.
1485 for (int j = 0; j <= i; ++j) {
1486 float w = scores[score_index(h, i, j, aligned_context_window)];
1487 size_t v_base = qkv_index(h, j, 0, num_tokens, aligned_head_dim);
1488
1489 for (int d = 0; d < head_dim; ++d) {
1490 output[out_base + d] += w * v[v_base + d];
1491 }
1492 }
1493 }
1494 }
1495}
void causal_softmax_head_major_exact(float *scores, int num_heads, int num_tokens, int aligned_context_window)

References causal_softmax_head_major_exact(), qkv_index(), and score_index().

◆ attention_forward_causal_head_major_gqa()

void attention_forward_causal_head_major_gqa ( const float *  q,
const float *  k,
const float *  v,
float *  scores,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window 
)

GQA causal attention forward (score-matrix version)

Test:

test_attention.py::TestAttentionForward::test_gqa_forward

test_attention.py::TestAttentionForward::test_gqa_broadcast

test_attention_backward.py::TestAttentionBackwardGQA::test_gqa_backward

test_parity.py::test_attention_gqa_parity

Grouped-query attention: Q has num_heads, K/V have num_kv_heads. Each query head maps to a KV head via ratio.

After changes: make test && make llamacpp-parity-full

Definition at line 1509 of file attention_kernels.c.

1520{
1521 const float scale = 1.0f / sqrtf((float)head_dim);
1522
1523 for (int h = 0; h < num_heads; ++h) {
1524 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
1525 for (int i = 0; i < num_tokens; ++i) {
1526 for (int j = 0; j <= i; ++j) {
1527 float dot = 0.0f;
1528 size_t base_q = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1529 size_t base_k = qkv_index(kv_head, j, 0, num_tokens, aligned_head_dim);
1530
1531 for (int d = 0; d < head_dim; ++d) {
1532 dot += q[base_q + d] * k[base_k + d];
1533 }
1534
1535 scores[score_index(h, i, j, aligned_context_window)] = dot * scale;
1536 }
1537
1538 for (int j = i + 1; j < num_tokens; ++j) {
1539 scores[score_index(h, i, j, aligned_context_window)] = 0.0f;
1540 }
1541 }
1542 }
1543
1545 num_heads,
1546 num_tokens,
1547 aligned_context_window);
1548
1549 for (int h = 0; h < num_heads; ++h) {
1550 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
1551 for (int i = 0; i < num_tokens; ++i) {
1552 size_t out_base = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1553 for (int d = 0; d < aligned_head_dim; ++d) {
1554 output[out_base + d] = 0.0f;
1555 }
1556
1557 for (int j = 0; j <= i; ++j) {
1558 float w = scores[score_index(h, i, j, aligned_context_window)];
1559 size_t v_base = qkv_index(kv_head, j, 0, num_tokens, aligned_head_dim);
1560
1561 for (int d = 0; d < head_dim; ++d) {
1562 output[out_base + d] += w * v[v_base + d];
1563 }
1564 }
1565 }
1566 }
1567}

References causal_softmax_head_major(), qkv_index(), and score_index().

Referenced by ck_layer_forward_rmsnorm_swiglu(), ck_layer_forward_rmsnorm_swiglu_q4_k(), ck_layer_forward_rmsnorm_swiglu_quant(), and ck_layer_forward_rmsnorm_swiglu_ref().

◆ attention_forward_causal_head_major_gqa_bf16()

void attention_forward_causal_head_major_gqa_bf16 ( const uint16_t *  q,
const uint16_t *  k,
const uint16_t *  v,
float *  scores,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window,
float *  scratch_q,
float *  scratch_k,
float *  scratch_v 
)

BF16 GQA causal attention forward

Test:

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_forward

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_gqa

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_flash

Accepts BF16 inputs, converts to FP32, uses exact softmax. Caller provides scratch buffers (no per-call malloc).

After changes: make test

Definition at line 1651 of file attention_kernels.c.

1665{
1666 const size_t q_elems = (size_t)num_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
1667 const size_t kv_elems = (size_t)num_kv_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
1668
1669 if (!scratch_q || !scratch_k || !scratch_v) return;
1670
1671 convert_bf16_tensor_to_buf(q, scratch_q, q_elems);
1672 convert_bf16_tensor_to_buf(k, scratch_k, kv_elems);
1673 convert_bf16_tensor_to_buf(v, scratch_v, kv_elems);
1674
1675 // Use exact version to avoid fast exp approximation error accumulating
1676 // with BF16 precision loss.
1677 attention_forward_causal_head_major_gqa_exact(scratch_q, scratch_k, scratch_v,
1678 scores, output,
1679 num_heads, num_kv_heads,
1680 num_tokens, head_dim,
1681 aligned_head_dim, aligned_context_window);
1682 /* No free - caller owns scratch buffers */
1683}
void attention_forward_causal_head_major_gqa_exact(const float *q, const float *k, const float *v, float *scores, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int aligned_context_window)

References attention_forward_causal_head_major_gqa_exact(), and convert_bf16_tensor_to_buf().

◆ attention_forward_causal_head_major_gqa_exact()

void attention_forward_causal_head_major_gqa_exact ( const float *  q,
const float *  k,
const float *  v,
float *  scores,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  aligned_context_window 
)

GQA causal attention forward (exact version using stdlib expf)

Test:

test_attention.py::TestAttentionForward::test_gqa_exact

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_gqa

Uses standard library expf for numerical accuracy reference. Used by BF16 wrapper to avoid approximation error accumulation.

After changes: make test

Definition at line 1579 of file attention_kernels.c.

1590{
1591 const float scale = 1.0f / sqrtf((float)head_dim);
1592
1593 for (int h = 0; h < num_heads; ++h) {
1594 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
1595 for (int i = 0; i < num_tokens; ++i) {
1596 for (int j = 0; j <= i; ++j) {
1597 float dot = 0.0f;
1598 size_t base_q = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1599 size_t base_k = qkv_index(kv_head, j, 0, num_tokens, aligned_head_dim);
1600
1601 for (int d = 0; d < head_dim; ++d) {
1602 dot += q[base_q + d] * k[base_k + d];
1603 }
1604
1605 scores[score_index(h, i, j, aligned_context_window)] = dot * scale;
1606 }
1607
1608 for (int j = i + 1; j < num_tokens; ++j) {
1609 scores[score_index(h, i, j, aligned_context_window)] = 0.0f;
1610 }
1611 }
1612 }
1613
1614 // Use exact softmax with standard library expf
1616 num_heads,
1617 num_tokens,
1618 aligned_context_window);
1619
1620 for (int h = 0; h < num_heads; ++h) {
1621 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
1622 for (int i = 0; i < num_tokens; ++i) {
1623 size_t out_base = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1624 for (int d = 0; d < aligned_head_dim; ++d) {
1625 output[out_base + d] = 0.0f;
1626 }
1627
1628 for (int j = 0; j <= i; ++j) {
1629 float w = scores[score_index(h, i, j, aligned_context_window)];
1630 size_t v_base = qkv_index(kv_head, j, 0, num_tokens, aligned_head_dim);
1631
1632 for (int d = 0; d < head_dim; ++d) {
1633 output[out_base + d] += w * v[v_base + d];
1634 }
1635 }
1636 }
1637 }
1638}

References causal_softmax_head_major_exact(), qkv_index(), and score_index().

Referenced by attention_forward_causal_head_major_gqa_bf16(), ck_layer_forward_rmsnorm_swiglu(), and ck_layer_forward_rmsnorm_swiglu_ref().

◆ attention_forward_causal_head_major_gqa_flash()

void attention_forward_causal_head_major_gqa_flash ( 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 
)

Definition at line 4444 of file attention_kernels.c.

4453{
4455 num_heads, num_kv_heads,
4456 num_tokens, head_dim,
4457 aligned_head_dim,
4458 /*kv_stride_tokens=*/num_tokens,
4459 /*causal=*/1,
4460 /*round_full_kv_fp16=*/0,
4461 /*output_token_major=*/0,
4462 1.0f / sqrtf((float)head_dim));
4463}
static void attention_forward_head_major_gqa_flash_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 causal, int round_full_kv_fp16, int output_token_major, float scale)

References attention_forward_head_major_gqa_flash_impl().

Referenced by ck_layer_forward_rmsnorm_swiglu(), ck_layer_forward_rmsnorm_swiglu_q4_k(), ck_layer_forward_rmsnorm_swiglu_quant(), ck_layer_forward_rmsnorm_swiglu_ref(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_9_prefill(), and qwen2_0_5b_decode_layer_9_prefill().

◆ attention_forward_causal_head_major_gqa_flash_strided()

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 
)

Flash attention forward with custom KV stride (for KV cache)

Test:

test_flash_attention.py::TestFlashAttention::test_flash_strided

test_kv_cache_attention.py::TestKVCacheAttention::test_flash_attention

Variant with configurable kv_stride_tokens for KV cache layouts where K/V may not be contiguous in memory.

After changes: make test

Definition at line 4496 of file attention_kernels.c.

4506{
4508 num_heads, num_kv_heads,
4509 num_tokens, head_dim,
4510 aligned_head_dim,
4511 kv_stride_tokens,
4512 /*causal=*/1,
4513 /*round_full_kv_fp16=*/0,
4514 /*output_token_major=*/0,
4515 1.0f / sqrtf((float)head_dim));
4516}

References attention_forward_head_major_gqa_flash_impl().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding(), ck_test_attention_causal(), mega_fused_attention_prefill(), mega_fused_attention_prefill_q8_0(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_9_prefill(), and qwen2_0_5b_decode_layer_9_prefill().

◆ attention_forward_causal_head_major_gqa_flash_strided_f16kv()

void attention_forward_causal_head_major_gqa_flash_strided_f16kv ( 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 
)

Definition at line 5417 of file attention_kernels.c.

5421{
5422 size_t elements = 0;
5423 if (num_kv_heads > 0 && kv_stride_tokens > 0 && aligned_head_dim > 0 &&
5424 (size_t)num_kv_heads <= SIZE_MAX / (size_t)kv_stride_tokens) {
5425 const size_t rows = (size_t)num_kv_heads * (size_t)kv_stride_tokens;
5426 if (rows <= SIZE_MAX / (size_t)aligned_head_dim) {
5427 elements = rows * (size_t)aligned_head_dim;
5428 }
5429 }
5430 float *workspace = elements > 0 && elements <= SIZE_MAX / (2 * sizeof(float))
5431 ? (float *)malloc(2 * elements * sizeof(float))
5432 : NULL;
5433 if (!workspace) {
5435 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5436 head_dim, aligned_head_dim, kv_stride_tokens);
5437 return;
5438 }
5440 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5441 aligned_head_dim, kv_stride_tokens, workspace,
5442 2 * elements * sizeof(float));
5443 free(workspace);
5444}
void attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace(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, float *rounded_kv, size_t rounded_kv_bytes)
void attention_forward_causal_head_major_gqa_flash_strided_f16kv_serial(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_f16kv_serial(), and attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace().

◆ attention_forward_causal_head_major_gqa_flash_strided_f16kv_serial()

void attention_forward_causal_head_major_gqa_flash_strided_f16kv_serial ( 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 
)

Definition at line 5361 of file attention_kernels.c.

5365{
5366 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
5367 num_tokens <= 0 || kv_stride_tokens < num_tokens) {
5368 return;
5369 }
5370 ck_attention_causal_f16kv_args_t args = {
5371 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5372 head_dim, aligned_head_dim, kv_stride_tokens, 0,
5373 };
5374 ck_attention_causal_f16kv_work(0, 1, &args);
5375}
static void ck_attention_causal_f16kv_work(int ith, int nth, void *opaque)

References ck_attention_causal_f16kv_work().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_f16kv().

◆ attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace()

void attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace ( 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,
float *  rounded_kv,
size_t  rounded_kv_bytes 
)

Definition at line 5377 of file attention_kernels.c.

5382{
5383 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
5384 num_tokens <= 0 || kv_stride_tokens < num_tokens) {
5385 return;
5386 }
5387 size_t elements = 0;
5388 if ((size_t)num_kv_heads <= SIZE_MAX / (size_t)kv_stride_tokens) {
5389 const size_t rows = (size_t)num_kv_heads * (size_t)kv_stride_tokens;
5390 if (rows <= SIZE_MAX / (size_t)aligned_head_dim) {
5391 elements = rows * (size_t)aligned_head_dim;
5392 }
5393 }
5394 if (elements == 0 || elements > SIZE_MAX / (2 * sizeof(float)) ||
5395 !rounded_kv || rounded_kv_bytes < 2 * elements * sizeof(float)) {
5396 fprintf(stderr,
5397 "HARD KERNEL CONTRACT FAULT: FP16-KV attention workspace is too small\n");
5398 abort();
5399 }
5400 ck_round_fp16_buffer(k, rounded_kv, elements);
5401 ck_round_fp16_buffer(v, rounded_kv + elements, elements);
5402 ck_attention_causal_f16kv_args_t args = {
5403 q, rounded_kv, rounded_kv + elements, output,
5404 num_heads, num_kv_heads, num_tokens,
5405 head_dim, aligned_head_dim, kv_stride_tokens, 1,
5406 };
5407 ck_threadpool_t *pool = ck_threadpool_global();
5408 const int workers = pool ? ck_threadpool_n_threads(pool) : 1;
5409 const int active = workers < num_heads ? workers : num_heads;
5410 if (active > 1) {
5412 } else {
5413 ck_attention_causal_f16kv_work(0, 1, &args);
5414 }
5415}
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)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)

References ck_attention_causal_f16kv_work(), ck_round_fp16_buffer(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_f16kv().

◆ attention_forward_causal_head_major_gqa_flash_strided_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 
)

Definition at line 5098 of file attention_kernels.c.

5108{
5109 (void)head_dim;
5111 num_heads, num_kv_heads,
5112 num_tokens, head_dim,
5113 aligned_head_dim,
5114 kv_stride_tokens,
5115 /*causal=*/1,
5116 /*round_full_kv_fp16=*/0,
5117 /*output_token_major=*/0,
5118 1.0f);
5119}

References attention_forward_head_major_gqa_flash_impl().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl(), and attention_forward_causal_head_major_shared_kv_gemma4().

◆ attention_forward_causal_head_major_gqa_flash_strided_gemma4_token_output()

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 
)

Definition at line 5121 of file attention_kernels.c.

5132{
5134 num_heads, num_kv_heads,
5135 num_tokens, head_dim,
5136 aligned_head_dim,
5137 kv_stride_tokens,
5138 /*causal=*/1,
5139 /*round_full_kv_fp16=*/0,
5140 /*output_token_major=*/1,
5141 1.0f);
5142}

References attention_forward_head_major_gqa_flash_impl().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

◆ attention_forward_causal_head_major_gqa_flash_strided_token_output()

void attention_forward_causal_head_major_gqa_flash_strided_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 
)

Definition at line 4518 of file attention_kernels.c.

4529{
4531 num_heads, num_kv_heads,
4532 num_tokens, head_dim,
4533 aligned_head_dim,
4534 kv_stride_tokens,
4535 /*causal=*/1,
4536 /*round_full_kv_fp16=*/0,
4537 /*output_token_major=*/1,
4538 1.0f / sqrtf((float)head_dim));
4539}

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_causal_head_major_gqa_llama_regular_strided_sliding_workspace()

void attention_forward_causal_head_major_gqa_llama_regular_strided_sliding_workspace ( 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,
float *  scores,
size_t  scores_bytes,
float *  value_columns,
size_t  value_columns_bytes,
float *  scaled_scores,
size_t  scaled_scores_bytes 
)

Definition at line 6086 of file attention_kernels.c.

6093{
6094 if (!q || !k || !v || !output || !scores || !value_columns || !scaled_scores ||
6095 num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0 || head_dim <= 0 ||
6096 aligned_head_dim < head_dim || kv_stride_tokens < num_tokens ||
6097 num_heads > INT_MAX / num_tokens) return;
6098
6099 const size_t score_elements = scores_bytes / sizeof(float);
6100 const size_t scaled_elements = scaled_scores_bytes / sizeof(float);
6101 const size_t value_elements = value_columns_bytes / sizeof(float);
6102 if ((size_t)num_kv_heads > SIZE_MAX / (size_t)head_dim) return;
6103 const size_t value_rows = (size_t)num_kv_heads * (size_t)head_dim;
6104 const size_t value_capacity = value_rows > 0 ? value_elements / value_rows : 0;
6105 const size_t padded_size = num_tokens < 256
6106 ? 256 : (((size_t)num_tokens + 255) / 256) * 256;
6107 const int padded = padded_size > (size_t)INT_MAX ? 0 : (int)padded_size;
6108
6109 /* Older direct callers provide one score row and one value bank. Keep that
6110 * ABI usable while generated v8 runtimes provide the parallel workspace. */
6111 if (padded <= 0 || value_capacity < (size_t)padded ||
6112 score_elements < (size_t)padded * 2 ||
6113 scaled_elements < (size_t)padded * 2 ||
6114 value_elements < value_rows * (size_t)padded) {
6116 q, k, v, output, num_heads, num_kv_heads, num_tokens, num_tokens,
6117 head_dim, aligned_head_dim, kv_stride_tokens, sliding_window,
6118 scores, scores_bytes, value_columns, value_columns_bytes,
6119 scaled_scores, scaled_scores_bytes, 1);
6120 return;
6121 }
6122
6125 q, k, v, output, num_heads, num_kv_heads, num_tokens, num_tokens,
6126 head_dim, aligned_head_dim, kv_stride_tokens, sliding_window,
6127 scores, (size_t)padded * sizeof(float),
6128 value_columns, (size_t)head_dim * (size_t)padded * sizeof(float),
6129 scaled_scores, (size_t)padded * sizeof(float), 1);
6130 return;
6131 }
6132
6133 const size_t kv_head_stride =
6134 (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
6135 for (int kv_head = 0; kv_head < num_kv_heads; ++kv_head) {
6136 const float *value_head = v + (size_t)kv_head * kv_head_stride;
6137 float *packed_head = value_columns +
6138 (size_t)kv_head * (size_t)head_dim * (size_t)padded;
6139 for (int dim = 0; dim < head_dim; ++dim) {
6140 float *column = packed_head + (size_t)dim * (size_t)padded;
6141 int token = 0;
6142 for (; token < num_tokens; ++token) {
6143 column[token] =
6144 value_head[(size_t)token * (size_t)aligned_head_dim + (size_t)dim];
6145 }
6146 for (; token < padded; ++token) column[token] = 0.0f;
6147 }
6148 }
6149
6150 ck_llama_regular_prefill_args_t args = {
6151 .q = q,
6152 .k = k,
6153 .value_columns = value_columns,
6154 .output = output,
6155 .scores = scores,
6156 .scaled_scores = scaled_scores,
6157 .num_heads = num_heads,
6158 .num_kv_heads = num_kv_heads,
6159 .num_tokens = num_tokens,
6160 .head_dim = head_dim,
6161 .aligned_head_dim = aligned_head_dim,
6162 .kv_stride_tokens = kv_stride_tokens,
6163 .sliding_window = sliding_window,
6164 .padded = padded,
6165 };
6166 atomic_init(&args.next_job, 0);
6167
6168 size_t scratch_lanes = score_elements / (size_t)padded;
6169 const size_t scaled_lanes = scaled_elements / (size_t)padded;
6170 if (scaled_lanes < scratch_lanes) scratch_lanes = scaled_lanes;
6171 int active = scratch_lanes > (size_t)INT_MAX ? INT_MAX : (int)scratch_lanes;
6172 const int jobs = num_heads * num_tokens;
6173 if (active > jobs) active = jobs;
6174 ck_threadpool_t *pool = ck_threadpool_global();
6175 const int pool_threads = pool ? ck_threadpool_n_threads(pool) : 1;
6176 if (active > pool_threads) active = pool_threads;
6177 if (active < 1) active = 1;
6178 if (pool && active > 1) {
6180 } else {
6181 ck_llama_regular_prefill_work(0, 1, &args);
6182 }
6183}
static void ck_llama_regular_prefill_work(int ith, int nth, void *opaque)
static int ck_attention_vec_dump_enabled(void)
static void ck_attention_llama_regular_impl(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int query_tokens, int live_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window, float *scores, size_t scores_bytes, float *value_columns, size_t value_columns_bytes, float *scaled_scores, size_t scaled_scores_bytes, int batched_prefill)
const char * token
Definition tokenizer.h:307

References ck_attention_llama_regular_impl(), ck_attention_vec_dump_enabled(), ck_llama_regular_prefill_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and token.

◆ attention_forward_causal_head_major_gqa_muse_eager_bf16_storage()

void attention_forward_causal_head_major_gqa_muse_eager_bf16_storage ( 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,
float *  scores,
size_t  scores_bytes,
uint16_t *  key_rows,
size_t  key_rows_bytes,
uint16_t *  value_columns,
size_t  value_columns_bytes,
uint16_t *  gemm_rows,
size_t  gemm_rows_bytes,
uint16_t *  gemm_scores,
size_t  gemm_scores_bytes 
)

Definition at line 9206 of file attention_kernels.c.

9215{
9217 q, k, v, output, num_heads, num_kv_heads, num_tokens, num_tokens,
9218 kv_stride_tokens, head_dim, aligned_head_dim, 0,
9219 scores, scores_bytes, key_rows, key_rows_bytes,
9220 value_columns, value_columns_bytes, gemm_rows, gemm_rows_bytes,
9221 gemm_scores, gemm_scores_bytes);
9222}
static void ck_attention_muse_eager_bf16_storage_impl(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int query_tokens, int kv_tokens, int kv_stride_tokens, int head_dim, int aligned_head_dim, int sliding_window, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_causal_head_major_gqa_muse_eager_bf16_storage_sliding()

void attention_forward_causal_head_major_gqa_muse_eager_bf16_storage_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,
float *  scores,
size_t  scores_bytes,
uint16_t *  key_rows,
size_t  key_rows_bytes,
uint16_t *  value_columns,
size_t  value_columns_bytes,
uint16_t *  gemm_rows,
size_t  gemm_rows_bytes,
uint16_t *  gemm_scores,
size_t  gemm_scores_bytes 
)

Definition at line 9224 of file attention_kernels.c.

9233{
9235 q, k, v, output, num_heads, num_kv_heads, num_tokens, num_tokens,
9236 kv_stride_tokens, head_dim, aligned_head_dim, sliding_window,
9237 scores, scores_bytes, key_rows, key_rows_bytes,
9238 value_columns, value_columns_bytes, gemm_rows, gemm_rows_bytes,
9239 gemm_scores, gemm_scores_bytes);
9240}

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction 
)

Definition at line 9429 of file attention_kernels.c.

9442{
9443 if (q_tokens >= CK_GGML_FA_TILE_Q) {
9445 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
9446 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
9447 NULL, 0);
9448 }
9449 if (num_heads <= 0 || aligned_head_dim <= 0 ||
9450 (size_t) num_heads > SIZE_MAX / (size_t) aligned_head_dim) {
9452 }
9453 const size_t token_elements = (size_t) num_heads * (size_t) aligned_head_dim;
9454 if (token_elements > SIZE_MAX / (2 * sizeof(float))) {
9456 }
9457 const size_t workspace_bytes = 2 * token_elements * sizeof(float);
9458 float *workspace = (float *) malloc(workspace_bytes);
9459 if (!workspace) return CK_ATTENTION_STATUS_INVALID_ARGUMENT;
9460 const ck_attention_status_t status =
9462 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
9463 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
9464 workspace, workspace_bytes);
9465 free(workspace);
9466 return status;
9467}
#define CK_GGML_FA_TILE_Q
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace(const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
ck_attention_status_t
@ CK_ATTENTION_STATUS_INVALID_ARGUMENT

References attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, and CK_GGML_FA_TILE_Q.

◆ attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes 
)

Definition at line 9352 of file attention_kernels.c.

9367{
9368 if (!q || !k_cache || !v_cache || !output ||
9369 num_heads <= 0 || num_kv_heads <= 0 || q_tokens <= 0 ||
9370 past_tokens < 0 || past_tokens + q_tokens > cache_capacity ||
9371 head_dim <= 0 || aligned_head_dim < head_dim) {
9373 }
9374 if (reduction != CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA) {
9376 }
9377
9378 if (q_tokens >= CK_GGML_FA_TILE_Q) {
9379 ck_attention_f16_prefill_qtile64_args_t args = {
9380 .q = q, .k_cache = k_cache, .v_cache = v_cache, .output = output,
9381 .num_heads = num_heads, .num_kv_heads = num_kv_heads,
9382 .q_tokens = q_tokens, .past_tokens = past_tokens,
9383 .cache_capacity = cache_capacity, .head_dim = head_dim,
9384 .aligned_head_dim = aligned_head_dim, .cache_is_bf16 = 1,
9385 };
9386 ck_threadpool_t *pool = ck_threadpool_global();
9387 int active = pool ? ck_threadpool_n_threads(pool) : 1;
9388 if (active > num_kv_heads) active = num_kv_heads;
9389 if (pool && active > 1 && ck_threadpool_thread_id(pool) <= 0) {
9391 } else {
9393 }
9394 const size_t count = (size_t)num_heads * (size_t)q_tokens * (size_t)aligned_head_dim;
9395 for (size_t i = 0; i < count; ++i) {
9396 output[i] = bf16_to_float(float_to_bf16(output[i]));
9397 }
9399 }
9400
9401 const size_t token_elems = (size_t)num_heads * (size_t)aligned_head_dim;
9402 if (token_elems > SIZE_MAX / (2 * sizeof(float)) ||
9403 !token_workspace || token_workspace_bytes < 2 * token_elems * sizeof(float)) {
9405 }
9406 float *q_token = token_workspace;
9407 float *out_token = token_workspace + token_elems;
9409 for (int t = 0; t < q_tokens; ++t) {
9410 for (int h = 0; h < num_heads; ++h) {
9411 memcpy(q_token + (size_t)h * (size_t)aligned_head_dim,
9412 q + ((size_t)h * (size_t)q_tokens + (size_t)t) * (size_t)aligned_head_dim,
9413 (size_t)aligned_head_dim * sizeof(float));
9414 }
9416 q_token, k_cache, v_cache, out_token,
9417 num_heads, num_kv_heads, past_tokens + t + 1, cache_capacity,
9418 head_dim, aligned_head_dim, reduction);
9419 if (status != CK_ATTENTION_STATUS_OK) break;
9420 for (int h = 0; h < num_heads; ++h) {
9421 memcpy(output + ((size_t)h * (size_t)q_tokens + (size_t)t) * (size_t)aligned_head_dim,
9422 out_token + (size_t)h * (size_t)aligned_head_dim,
9423 (size_t)aligned_head_dim * sizeof(float));
9424 }
9425 }
9426 return status;
9427}
static void ck_attention_f16_prefill_qtile64_work(int ith, int nth, void *opaque)
ck_attention_status_t attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract(const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)
static uint16_t float_to_bf16(float f)
Definition bf16_utils.h:90
static float bf16_to_float(uint16_t v)
Definition bf16_utils.h:38
int ck_threadpool_thread_id(const ck_threadpool_t *pool)
@ CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA
@ CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT
@ CK_ATTENTION_STATUS_OK
const uint8_t size_t count
Definition true_bpe.h:209

References attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract(), bf16_to_float(), ck_attention_f16_prefill_qtile64_work(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA, CK_GGML_FA_TILE_Q, ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_thread_id(), count, and float_to_bf16().

Referenced by attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes,
void *  gqa_workspace,
size_t  gqa_workspace_bytes,
int  route_num_heads,
int  route_num_kv_heads,
int  route_head_dim,
int  route_query_tokens,
int  route_min_kv_tokens,
int  route_workers,
int  route_query_tile_size,
int  route_concurrent_query_tiles 
)

Definition at line 7686 of file attention_kernels.c.

7711{
7712 if (route_num_heads <= 0 || route_num_kv_heads <= 0 ||
7713 route_num_heads % route_num_kv_heads != 0 || route_head_dim <= 0 ||
7714 route_query_tokens <= 0 || route_min_kv_tokens < route_query_tokens ||
7715 route_workers < route_num_kv_heads ||
7716 route_workers % route_num_kv_heads != 0 ||
7717 route_query_tile_size < 16 || route_query_tile_size > 128 ||
7718 route_query_tile_size % 16 != 0 ||
7719 route_concurrent_query_tiles <= 0 ||
7720 route_concurrent_query_tiles > 4) {
7722 }
7723 ck_threadpool_t *pool = ck_threadpool_global();
7724 const int active = pool ? ck_threadpool_n_threads(pool) : 1;
7725 const int kv_tokens = past_tokens + q_tokens;
7727 num_heads == route_num_heads && num_kv_heads == route_num_kv_heads &&
7728 head_dim == route_head_dim && aligned_head_dim == route_head_dim &&
7729 q_tokens == route_query_tokens && kv_tokens >= route_min_kv_tokens &&
7730 active == route_workers) {
7732 q, k_cache, v_cache, output, num_heads, num_kv_heads,
7733 q_tokens, past_tokens, cache_capacity, head_dim, aligned_head_dim,
7734 route_query_tile_size, route_concurrent_query_tiles,
7735 gqa_workspace, gqa_workspace_bytes);
7736 }
7738 q, k_cache, v_cache, output, num_heads, num_kv_heads,
7739 q_tokens, past_tokens, cache_capacity, head_dim, aligned_head_dim,
7740 reduction, token_workspace, token_workspace_bytes);
7741}
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config(const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int query_tile_size, int concurrent_query_tiles, void *workspace, size_t workspace_bytes)
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace(const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
@ CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64

References attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace(), attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64, ck_threadpool_global(), and ck_threadpool_n_threads().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction 
)

Definition at line 8155 of file attention_kernels.c.

8168{
8170 q_tokens >= CK_GGML_FA_TILE_Q) {
8172 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
8173 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
8174 NULL, 0);
8175 }
8176
8177 if (num_heads <= 0 || aligned_head_dim <= 0 ||
8178 (size_t) num_heads > SIZE_MAX / (size_t) aligned_head_dim) {
8180 }
8181 const size_t token_elements = (size_t) num_heads * (size_t) aligned_head_dim;
8182 if (token_elements > SIZE_MAX / (2 * sizeof(float))) {
8184 }
8185 const size_t workspace_bytes = 2 * token_elements * sizeof(float);
8186 float *workspace = (float *) malloc(workspace_bytes);
8187 if (!workspace) {
8189 }
8190 const ck_attention_status_t status =
8192 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
8193 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
8194 workspace, workspace_bytes);
8195 free(workspace);
8196 return status;
8197}

References attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64, and CK_GGML_FA_TILE_Q.

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes 
)

Definition at line 7770 of file attention_kernels.c.

7785{
7786 if (!q || !k_cache || !v_cache || !output ||
7787 num_heads <= 0 || num_kv_heads <= 0 || q_tokens <= 0 ||
7788 past_tokens < 0 || past_tokens + q_tokens > cache_capacity ||
7789 head_dim <= 0 || aligned_head_dim < head_dim) {
7791 }
7792
7794 q_tokens < CK_GGML_FA_TILE_Q) {
7796 }
7797
7800 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7801 past_tokens, cache_capacity, head_dim, aligned_head_dim, 0, 0.0f,
7802 (size_t) q_tokens * (size_t) aligned_head_dim,
7803 (size_t) q_tokens * (size_t) aligned_head_dim,
7805 }
7806
7809 reduction != CK_ATTN_REDUCTION_FP32_ONLINE) {
7811 }
7812
7813 const size_t token_elems = (size_t) num_heads * (size_t) aligned_head_dim;
7814 if (token_elems > SIZE_MAX / (2 * sizeof(float))) {
7816 }
7817 const size_t required_bytes = 2 * token_elems * sizeof(float);
7818 if (!token_workspace || token_workspace_bytes < required_bytes) {
7820 }
7821 float *q_token = token_workspace;
7822 float *out_token = token_workspace + token_elems;
7823
7825 for (int t = 0; t < q_tokens; ++t) {
7826 for (int h = 0; h < num_heads; ++h) {
7827 const float *src = q +
7828 ((size_t) h * (size_t) q_tokens + (size_t) t) * (size_t) aligned_head_dim;
7829 memcpy(q_token + (size_t) h * (size_t) aligned_head_dim,
7830 src,
7831 (size_t) aligned_head_dim * sizeof(float));
7832 }
7833
7835 q_token, k_cache, v_cache, out_token,
7836 num_heads, num_kv_heads, past_tokens + t + 1, cache_capacity,
7837 head_dim, aligned_head_dim, reduction);
7838 if (status != CK_ATTENTION_STATUS_OK) {
7839 break;
7840 }
7841
7842 for (int h = 0; h < num_heads; ++h) {
7843 float *dst = output +
7844 ((size_t) h * (size_t) q_tokens + (size_t) t) * (size_t) aligned_head_dim;
7845 memcpy(dst,
7846 out_token + (size_t) h * (size_t) aligned_head_dim,
7847 (size_t) aligned_head_dim * sizeof(float));
7848 }
7849 }
7850
7851 return status;
7852}
static ck_attention_status_t ck_attention_f16_prefill_qtile64_dispatch(const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int cache_is_bf16, float attention_scale, size_t q_head_stride, size_t output_head_stride, ck_attention_prefill_schedule_t schedule)
ck_attention_status_t attention_forward_decode_head_major_gqa_flash_f16cache_contract(const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)
@ CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES
@ CK_ATTN_REDUCTION_F16_ONLINE_FP32_MERGE
@ CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE
@ CK_ATTN_REDUCTION_FP32_ONLINE

References attention_forward_decode_head_major_gqa_flash_f16cache_contract(), ck_attention_f16_prefill_qtile64_dispatch(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES, CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64, CK_ATTN_REDUCTION_F16_ONLINE_FP32_MERGE, CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE, CK_ATTN_REDUCTION_FP32_ONLINE, and CK_GGML_FA_TILE_Q.

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace(), and attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_gemma4_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gemma4_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes 
)

Definition at line 7962 of file attention_kernels.c.

7968{
7970 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7971 past_tokens, cache_capacity, head_dim, aligned_head_dim, 0, reduction,
7972 token_workspace, token_workspace_bytes, NULL, 0);
7973}
static ck_attention_status_t ck_attention_prefill_append_f16cache_gemma4_workspace(const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  query_tile_size,
int  concurrent_query_tiles,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 7585 of file attention_kernels.c.

7601{
7602 if (!q || !k_cache || !v_cache || !output || !workspace || num_heads <= 0 ||
7603 num_kv_heads <= 0 || num_heads % num_kv_heads != 0 ||
7604 query_tile_size <= 0 || q_tokens < query_tile_size || past_tokens < 0 ||
7605 past_tokens + q_tokens > cache_capacity || head_dim <= 0 ||
7606 aligned_head_dim < head_dim || query_tile_size < 16 ||
7607 query_tile_size > 128 || query_tile_size % 16 != 0 ||
7608 concurrent_query_tiles <= 0 || concurrent_query_tiles > 4) {
7610 }
7611
7612 ck_threadpool_t *pool = ck_threadpool_global();
7613 const int active = pool ? ck_threadpool_n_threads(pool) : 1;
7614 if (!pool || active < num_kv_heads || active % num_kv_heads != 0 ||
7615 ck_threadpool_thread_id(pool) > 0) {
7617 }
7618 const size_t required_workspace =
7620 num_heads, num_kv_heads, head_dim, active,
7621 query_tile_size, concurrent_query_tiles);
7622 if (required_workspace == 0 || workspace_bytes < required_workspace) {
7624 }
7625 const int lanes = active / num_kv_heads;
7626 const size_t tile_elems =
7627 (size_t) num_kv_heads * (size_t) head_dim * CK_GGML_FA_TILE_KV;
7628 uintptr_t workspace_address = (uintptr_t) workspace;
7629 workspace_address = (workspace_address + 63u) & ~(uintptr_t) 63u;
7630 unsigned char *workspace_base = (unsigned char *) workspace_address;
7631 size_t cursor = 0;
7632 float *shared_k_tiles = (float *) (workspace_base + cursor);
7633 cursor += tile_elems * sizeof(float);
7634 cursor = ck_attention_align64_size(cursor);
7635 float *shared_v_tiles = (float *) (workspace_base + cursor);
7636 cursor += tile_elems * sizeof(float);
7637 cursor = ck_attention_align64_size(cursor);
7638 ck_attention_gqa_team_barrier_t *barriers =
7639 (ck_attention_gqa_team_barrier_t *) (workspace_base + cursor);
7640 cursor += (size_t) num_kv_heads * sizeof(*barriers);
7641 cursor = ck_attention_align64_size(cursor);
7642 unsigned char *worker_workspace = workspace_base + cursor;
7643 const size_t worker_workspace_stride =
7645 num_heads, num_kv_heads, head_dim, active,
7646 query_tile_size, concurrent_query_tiles);
7647 for (int group = 0; group < num_kv_heads; ++group) {
7648 __atomic_store_n(&barriers[group].arrived, 0, __ATOMIC_RELAXED);
7649 __atomic_store_n(&barriers[group].phase, 0, __ATOMIC_RELAXED);
7650 barriers[group].lanes = lanes;
7651 }
7652
7653 ck_attention_f16_prefill_gqa_reuse_args_t args = {
7654 .base = {
7655 .q = q,
7656 .k_cache = k_cache,
7657 .v_cache = v_cache,
7658 .output = output,
7659 .num_heads = num_heads,
7660 .num_kv_heads = num_kv_heads,
7661 .q_tokens = q_tokens,
7662 .past_tokens = past_tokens,
7663 .cache_capacity = cache_capacity,
7664 .head_dim = head_dim,
7665 .aligned_head_dim = aligned_head_dim,
7666 .cache_is_bf16 = 0,
7668 .q_head_stride =
7669 (size_t) q_tokens * (size_t) aligned_head_dim,
7670 .output_head_stride =
7671 (size_t) q_tokens * (size_t) aligned_head_dim,
7672 },
7673 .shared_k_tiles = shared_k_tiles,
7674 .shared_v_tiles = shared_v_tiles,
7675 .barriers = barriers,
7676 .worker_workspace = worker_workspace,
7677 .worker_workspace_stride = worker_workspace_stride,
7678 .query_tile_size = query_tile_size,
7679 .concurrent_query_tiles = concurrent_query_tiles,
7680 };
7682 pool, active, ck_attention_f16_prefill_gqa_reuse_work, &args);
7684}
#define CK_GGML_FA_TILE_KV
static void ck_attention_f16_prefill_gqa_reuse_work(int ith, int nth, void *opaque)
size_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes(int num_heads, int num_kv_heads, int head_dim, int workers, int query_tile_size, int concurrent_query_tiles)
static size_t ck_attention_f16_prefill_gqa_reuse_worker_bytes(int num_heads, int num_kv_heads, int head_dim, int workers, int query_tile_size, int concurrent_query_tiles)
static size_t ck_attention_align64_size(size_t value)
@ CK_ATTN_PREFILL_SCHEDULE_GQA_SHARED_KV_TILES
@ CK_ATTENTION_STATUS_INSUFFICIENT_WORKSPACE

References attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes(), ck_attention_align64_size(), ck_attention_f16_prefill_gqa_reuse_work(), ck_attention_f16_prefill_gqa_reuse_worker_bytes(), CK_ATTENTION_STATUS_INSUFFICIENT_WORKSPACE, CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, CK_ATTN_PREFILL_SCHEDULE_GQA_SHARED_KV_TILES, CK_GGML_FA_TILE_KV, ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_thread_id().

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes()

size_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes ( int  num_heads,
int  num_kv_heads,
int  head_dim,
int  workers,
int  query_tile_size,
int  concurrent_query_tiles 
)

Definition at line 7064 of file attention_kernels.c.

7071{
7072 const size_t worker_bytes =
7074 num_heads, num_kv_heads, head_dim, workers,
7075 query_tile_size, concurrent_query_tiles);
7076 if (worker_bytes == 0) return 0;
7077 size_t bytes = 63u;
7078 bytes = ck_attention_align64_size(bytes) +
7079 (size_t) num_kv_heads * (size_t) head_dim * CK_GGML_FA_TILE_KV *
7080 sizeof(float);
7081 bytes = ck_attention_align64_size(bytes) +
7082 (size_t) num_kv_heads * CK_GGML_FA_TILE_KV * (size_t) head_dim *
7083 sizeof(float);
7084 bytes = ck_attention_align64_size(bytes) +
7085 (size_t) num_kv_heads * sizeof(ck_attention_gqa_team_barrier_t);
7086 bytes = ck_attention_align64_size(bytes) +
7087 (size_t) workers * worker_bytes;
7088 return bytes;
7089}

References ck_attention_align64_size(), ck_attention_f16_prefill_gqa_reuse_worker_bytes(), and CK_GGML_FA_TILE_KV.

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_qtile64_schedule()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_qtile64_schedule ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_prefill_schedule_t  schedule 
)

Definition at line 7743 of file attention_kernels.c.

7756{
7757 if (!q || !k_cache || !v_cache || !output || num_heads <= 0 ||
7758 num_kv_heads <= 0 || q_tokens < CK_GGML_FA_TILE_Q || past_tokens < 0 ||
7759 past_tokens + q_tokens > cache_capacity || head_dim <= 0 ||
7760 aligned_head_dim < head_dim) {
7762 }
7764 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7765 past_tokens, cache_capacity, head_dim, aligned_head_dim, 0, 0.0f,
7766 (size_t) q_tokens * (size_t) aligned_head_dim,
7767 (size_t) q_tokens * (size_t) aligned_head_dim, schedule);
7768}

References ck_attention_f16_prefill_qtile64_dispatch(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, and CK_GGML_FA_TILE_Q.

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_sliding_gemma4_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_sliding_gemma4_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes 
)

Definition at line 7975 of file attention_kernels.c.

7981{
7983 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7984 past_tokens, cache_capacity, head_dim, aligned_head_dim, sliding_window,
7985 reduction, token_workspace, token_workspace_bytes, NULL, 0);
7986}

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_full_bf16cache_pytorch_contract()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_full_bf16cache_pytorch_contract ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction 
)

Definition at line 9469 of file attention_kernels.c.

9482{
9483 if (!q || !k_cache || !v_cache || !output ||
9484 num_heads <= 0 || num_kv_heads <= 0 ||
9485 num_heads % num_kv_heads != 0 ||
9486 q_tokens <= 0 || past_tokens < 0 ||
9487 past_tokens + q_tokens > cache_capacity ||
9488 head_dim <= 0 || aligned_head_dim < head_dim) {
9490 }
9491 if (reduction != CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA) {
9493 }
9494
9495#if defined(__AVX512F__)
9496 pthread_once(&ck_pytorch_attention_once, ck_bind_pytorch_attention_primitives);
9497 return ck_attention_prefill_bf16_pytorch_math_gqa_full(
9498 q, k_cache, v_cache, output,
9499 num_heads, num_kv_heads, q_tokens, past_tokens, cache_capacity,
9500 head_dim, aligned_head_dim);
9501#else
9503#endif
9504}

References CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, and CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA.

◆ attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_contract_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_contract_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes,
const int *  segment_lengths,
int  num_segments 
)

Definition at line 8130 of file attention_kernels.c.

8147{
8149 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
8150 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
8151 token_workspace, token_workspace_bytes, segment_lengths, num_segments,
8153}
static ck_attention_status_t ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace(const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments, ck_attention_prefill_schedule_t schedule)

References ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace(), and CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES.

◆ attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_gemma4_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_gemma4_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes,
const int *  segment_lengths,
int  num_segments 
)

Definition at line 8003 of file attention_kernels.c.

8009{
8011 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
8012 past_tokens, cache_capacity, head_dim, aligned_head_dim, 0,
8013 reduction, token_workspace, token_workspace_bytes,
8014 segment_lengths, num_segments);
8015}

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_sliding_gemma4_workspace()

ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_sliding_gemma4_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes,
const int *  segment_lengths,
int  num_segments 
)

Definition at line 7988 of file attention_kernels.c.

7995{
7997 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7998 past_tokens, cache_capacity, head_dim, aligned_head_dim, sliding_window,
7999 reduction, token_workspace, token_workspace_bytes,
8000 segment_lengths, num_segments);
8001}

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_shared_kv_gemma4()

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

Definition at line 5144 of file attention_kernels.c.

5151{
5153 q, q, q, output, num_heads, num_heads, num_tokens,
5154 head_dim, aligned_head_dim, kv_stride_tokens
5155 );
5156}
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)

References attention_forward_causal_head_major_gqa_flash_strided_gemma4().

◆ attention_forward_chunk_head_major_gqa_flash_gemma4()

void attention_forward_chunk_head_major_gqa_flash_gemma4 ( const float *  q_chunk,
const float *  k_cache,
const float *  v_cache,
float *  out_chunk,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim 
)

Definition at line 6299 of file attention_kernels.c.

6310{
6311 if (!q_chunk || !k_cache || !v_cache || !out_chunk) {
6312 return;
6313 }
6314 if (num_heads <= 0 || num_kv_heads <= 0 || q_tokens <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6315 return;
6316 }
6317 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6318 return;
6319 }
6320
6321 const float scale = 1.0f;
6322 const size_t cache_head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6323 const size_t q_head_stride = (size_t)q_tokens * (size_t)aligned_head_dim;
6324
6325 for (int h = 0; h < num_heads; ++h) {
6326 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6327 const float *k_head = k_cache + (size_t)kv_head * cache_head_stride;
6328 const float *v_head = v_cache + (size_t)kv_head * cache_head_stride;
6329 for (int t = 0; t < q_tokens; ++t) {
6330 const float *q_head = q_chunk + (size_t)h * q_head_stride + (size_t)t * (size_t)aligned_head_dim;
6331 float *out_head = out_chunk + (size_t)h * q_head_stride + (size_t)t * (size_t)aligned_head_dim;
6332 attention_flash_decode(out_head,
6333 q_head,
6334 k_head,
6335 v_head,
6336 1,
6337 kv_tokens,
6338 1,
6339 aligned_head_dim,
6340 scale);
6341 }
6342 }
6343}
void attention_flash_decode(float *out, const float *q, const float *k, const float *v, int T_q, int T_k, int H, int D_h, float scale)
Main flash attention function with SIMD dispatch.

References attention_flash_decode().

◆ attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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,
ck_attention_reduction_t  reduction 
)

Definition at line 9278 of file attention_kernels.c.

9290{
9291 if (!q_token || !k_cache || !v_cache || !out_token ||
9292 num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 ||
9293 cache_capacity <= 0 || kv_tokens > cache_capacity ||
9294 head_dim <= 0 || aligned_head_dim < head_dim ||
9295 num_heads % num_kv_heads != 0) {
9297 }
9298 if (reduction != CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA) {
9300 }
9301
9302#if defined(__AVX512F__)
9303 pthread_once(&ck_pytorch_attention_once, ck_bind_pytorch_attention_primitives);
9304 return ck_attention_decode_bf16_pytorch_math_gqa(
9305 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
9306 kv_tokens, cache_capacity, head_dim, aligned_head_dim);
9307#else
9308 const float scale = 1.0f / sqrtf((float)head_dim);
9309 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
9310 for (int h = 0; h < num_heads; ++h) {
9311 const int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
9312 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
9313 const uint16_t *k_head = k_cache + (size_t)kv_head * head_stride;
9314 const uint16_t *v_head = v_cache + (size_t)kv_head * head_stride;
9315 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
9316
9317 float maximum = -INFINITY;
9318 for (int token = 0; token < kv_tokens; ++token) {
9319 const uint16_t *k_row = k_head + (size_t)token * (size_t)aligned_head_dim;
9320 float dot = 0.0f;
9321 for (int d = 0; d < head_dim; ++d) {
9322 dot = fmaf(q_head[d], bf16_to_float(k_row[d]), dot);
9323 }
9324 const float score = dot * scale;
9325 if (score > maximum) maximum = score;
9326 }
9327
9328 for (int d = 0; d < aligned_head_dim; ++d) out_head[d] = 0.0f;
9329 float denominator = 0.0f;
9330 for (int token = 0; token < kv_tokens; ++token) {
9331 const uint16_t *k_row = k_head + (size_t)token * (size_t)aligned_head_dim;
9332 const uint16_t *v_row = v_head + (size_t)token * (size_t)aligned_head_dim;
9333 float dot = 0.0f;
9334 for (int d = 0; d < head_dim; ++d) {
9335 dot = fmaf(q_head[d], bf16_to_float(k_row[d]), dot);
9336 }
9337 const float probability = expf(dot * scale - maximum);
9338 denominator += probability;
9339 for (int d = 0; d < head_dim; ++d) {
9340 out_head[d] = fmaf(probability, bf16_to_float(v_row[d]), out_head[d]);
9341 }
9342 }
9343 const float inverse = denominator > 0.0f ? 1.0f / denominator : 0.0f;
9344 for (int d = 0; d < head_dim; ++d) {
9345 out_head[d] = bf16_to_float(float_to_bf16(out_head[d] * inverse));
9346 }
9347 }
9349#endif
9350}

References bf16_to_float(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA, float_to_bf16(), score, and token.

Referenced by attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace().

◆ attention_forward_decode_head_major_gqa_f16cache_gemma4_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_gemma4_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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,
ck_attention_reduction_t  reduction 
)

Definition at line 6910 of file attention_kernels.c.

6915{
6917 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
6918 kv_tokens, cache_capacity, head_dim, aligned_head_dim, 0, reduction);
6919}
static ck_attention_status_t ck_attention_forward_decode_f16cache_gemma4(const float *q_token, const uint16_t *k_cache, const uint16_t *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, ck_attention_reduction_t reduction)

References ck_attention_forward_decode_f16cache_gemma4().

◆ attention_forward_decode_head_major_gqa_f16cache_regular_noscale()

ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_regular_noscale ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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 6844 of file attention_kernels.c.

6856{
6857 if (!q_token || !k_cache || !v_cache || !out_token ||
6858 num_heads <= 0 || num_kv_heads <= 0 || num_heads % num_kv_heads != 0 ||
6859 kv_tokens <= 0 || cache_capacity <= 0 || kv_tokens > cache_capacity ||
6860 head_dim <= 0 || head_dim > 4096 || aligned_head_dim < head_dim ||
6861 sliding_window < 0 ||
6862 (size_t) cache_capacity > SIZE_MAX / (size_t) aligned_head_dim) {
6864 }
6865
6866 const size_t cache_head_stride = (size_t) cache_capacity * (size_t) aligned_head_dim;
6867 const int first_token = sliding_window > 0 && kv_tokens > sliding_window
6868 ? kv_tokens - sliding_window : 0;
6869 uint16_t *q_half = (uint16_t *) alloca((size_t) head_dim * sizeof(uint16_t));
6870 for (int h = 0; h < num_heads; ++h) {
6871 const int kv_head = h / (num_heads / num_kv_heads);
6872 const float *q_head = q_token + (size_t) h * (size_t) aligned_head_dim;
6873 const uint16_t *k_head = k_cache + (size_t) kv_head * cache_head_stride;
6874 const uint16_t *v_head = v_cache + (size_t) kv_head * cache_head_stride;
6875 float *out_head = out_token + (size_t) h * (size_t) aligned_head_dim;
6876 for (int d = 0; d < head_dim; ++d) q_half[d] = CK_FP32_TO_FP16(q_head[d]);
6877
6878 float maximum = -INFINITY;
6879 for (int token = first_token; token < kv_tokens; ++token) {
6880 const float score = ck_attention_dot_f16_llama(
6881 q_half, k_head + (size_t) token * (size_t) aligned_head_dim, head_dim);
6882 if (score > maximum) maximum = score;
6883 }
6884 if (!isfinite(maximum)) return CK_ATTENTION_STATUS_INVALID_ARGUMENT;
6885
6886 double total = 0.0;
6887 for (int token = first_token; token < kv_tokens; ++token) {
6888 const float score = ck_attention_dot_f16_llama(
6889 q_half, k_head + (size_t) token * (size_t) aligned_head_dim, head_dim);
6890 total += (double) ck_attention_reference_expf(score - maximum);
6891 }
6892 if (!(total > 0.0) || !isfinite(total)) return CK_ATTENTION_STATUS_INVALID_ARGUMENT;
6893
6894 for (int d = 0; d < head_dim; ++d) out_head[d] = 0.0f;
6895 for (int token = first_token; token < kv_tokens; ++token) {
6896 const float score = ck_attention_dot_f16_llama(
6897 q_half, k_head + (size_t) token * (size_t) aligned_head_dim, head_dim);
6898 const float probability = ck_attention_reference_expf(score - maximum) / (float) total;
6899 const float rounded_probability = CK_FP16_TO_FP32(CK_FP32_TO_FP16(probability));
6900 const uint16_t *v_row = v_head + (size_t) token * (size_t) aligned_head_dim;
6901 for (int d = 0; d < head_dim; ++d) {
6902 out_head[d] = fmaf(rounded_probability, CK_FP16_TO_FP32(v_row[d]), out_head[d]);
6903 }
6904 }
6905 for (int d = head_dim; d < aligned_head_dim; ++d) out_head[d] = 0.0f;
6906 }
6908}
static float ck_attention_reference_expf(float value)
static float ck_attention_dot_f16_llama(const uint16_t *x, const uint16_t *y, int n)
#define CK_FP16_TO_FP32(x)
#define CK_FP32_TO_FP16(x)

References ck_attention_dot_f16_llama(), ck_attention_reference_expf(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_FP16_TO_FP32, CK_FP32_TO_FP16, score, and token.

Referenced by ck_attention_forward_decode_f16cache_gemma4().

◆ attention_forward_decode_head_major_gqa_f16cache_sliding_gemma4_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_sliding_gemma4_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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,
ck_attention_reduction_t  reduction 
)

Definition at line 6921 of file attention_kernels.c.

6926{
6928 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
6929 kv_tokens, cache_capacity, head_dim, aligned_head_dim,
6930 sliding_window, reduction);
6931}

References ck_attention_forward_decode_f16cache_gemma4().

◆ attention_forward_decode_head_major_gqa_flash()

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 
)

Flash attention decode (single token attends to KV cache)

Test:

test_flash_attention.py::TestFlashAttention::test_flash_decode

test_kv_cache_attention.py::TestKVCacheAttention::test_flash_decode

test_fused_attention_decode.py::TestFusedAttentionDecode::test_flash_decode

test_attention.py::TestAttentionForward::test_flash_decode

Single query token attends to kv_tokens in KV cache. Uses true flash attention from attention_flash_true.c.

After changes: make test && make llamacpp-parity-full

Definition at line 6212 of file attention_kernels.c.

6222{
6223 if (!q_token || !k_cache || !v_cache || !out_token) {
6224 return;
6225 }
6226 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6227 return;
6228 }
6229 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6230 return;
6231 }
6232
6233 const float scale = 1.0f / sqrtf((float)head_dim);
6234 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6235
6236 for (int h = 0; h < num_heads; ++h) {
6237 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6238 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
6239 const float *k_head = k_cache + (size_t)kv_head * head_stride;
6240 const float *v_head = v_cache + (size_t)kv_head * head_stride;
6241 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
6242
6243 attention_flash_decode(out_head,
6244 q_head,
6245 k_head,
6246 v_head,
6247 1,
6248 kv_tokens,
6249 1,
6250 aligned_head_dim,
6251 scale);
6252 }
6253}

References attention_flash_decode().

Referenced by attention_forward_decode_head_major_gqa_flash_sliding(), mega_fused_attention_decode_q5_0(), mega_fused_attention_decode_q5_0_parallel_simd(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_11_decode(), qwen2_0_5b_decode_layer_11_decode(), qwen2_0_5b_decode_layer_12_decode(), qwen2_0_5b_decode_layer_12_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_14_decode(), qwen2_0_5b_decode_layer_14_decode(), qwen2_0_5b_decode_layer_15_decode(), qwen2_0_5b_decode_layer_15_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_17_decode(), qwen2_0_5b_decode_layer_17_decode(), qwen2_0_5b_decode_layer_18_decode(), qwen2_0_5b_decode_layer_18_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_20_decode(), qwen2_0_5b_decode_layer_20_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_22_decode(), qwen2_0_5b_decode_layer_22_decode(), qwen2_0_5b_decode_layer_23_decode(), qwen2_0_5b_decode_layer_23_decode(), qwen2_0_5b_decode_layer_2_decode(), qwen2_0_5b_decode_layer_2_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_4_decode(), qwen2_0_5b_decode_layer_4_decode(), qwen2_0_5b_decode_layer_5_decode(), qwen2_0_5b_decode_layer_5_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_9_decode(), and qwen2_0_5b_decode_layer_9_decode().

◆ attention_forward_decode_head_major_gqa_flash_f16cache()

void attention_forward_decode_head_major_gqa_flash_f16cache ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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 
)

Definition at line 9506 of file attention_kernels.c.

9516{
9517 if (!q_token || !k_cache || !v_cache || !out_token) {
9518 return;
9519 }
9520 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
9521 return;
9522 }
9523 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
9524 return;
9525 }
9526
9527 const float scale = 1.0f / sqrtf((float)head_dim);
9528 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
9529 const size_t scratch_elems = (size_t)kv_tokens * (size_t)aligned_head_dim;
9530 const size_t scratch_bytes = scratch_elems * sizeof(float);
9531 const size_t max_stack_bytes = 1024u * 1024u;
9532
9533 if (scratch_bytes * 2u > max_stack_bytes) {
9534 for (int h = 0; h < num_heads; ++h) {
9535 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
9536 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
9537 const uint16_t *k_head = k_cache + (size_t)kv_head * head_stride;
9538 const uint16_t *v_head = v_cache + (size_t)kv_head * head_stride;
9539 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
9540
9541 for (int d = 0; d < aligned_head_dim; ++d) {
9542 out_head[d] = 0.0f;
9543 }
9544
9545 float max_score = -INFINITY;
9546 for (int j = 0; j < kv_tokens; ++j) {
9547 const uint16_t *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
9548 float dot = 0.0f;
9549 for (int d = 0; d < head_dim; ++d) {
9550 dot += q_head[d] * CK_FP16_TO_FP32(k_vec[d]);
9551 }
9552 const float score = dot * scale;
9553 if (score > max_score) {
9554 max_score = score;
9555 }
9556 }
9557
9558 float sum = 0.0f;
9559 for (int j = 0; j < kv_tokens; ++j) {
9560 const uint16_t *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
9561 const uint16_t *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
9562 float dot = 0.0f;
9563 for (int d = 0; d < head_dim; ++d) {
9564 dot += q_head[d] * CK_FP16_TO_FP32(k_vec[d]);
9565 }
9566 const float w = expf(dot * scale - max_score);
9567 sum += w;
9568 for (int d = 0; d < head_dim; ++d) {
9569 out_head[d] += w * CK_FP16_TO_FP32(v_vec[d]);
9570 }
9571 }
9572
9573 if (sum > 0.0f) {
9574 const float inv_sum = 1.0f / sum;
9575 for (int d = 0; d < head_dim; ++d) {
9576 out_head[d] *= inv_sum;
9577 }
9578 }
9579 for (int d = head_dim; d < aligned_head_dim; ++d) {
9580 out_head[d] = 0.0f;
9581 }
9582 }
9583 return;
9584 }
9585
9586 float *k_head_fp32 = (float *)alloca(scratch_bytes);
9587 float *v_head_fp32 = (float *)alloca(scratch_bytes);
9588
9589 for (int kv_head = 0; kv_head < num_kv_heads; ++kv_head) {
9590 const uint16_t *k_head = k_cache + (size_t)kv_head * head_stride;
9591 const uint16_t *v_head = v_cache + (size_t)kv_head * head_stride;
9592 const int q_begin = (int)((long long)kv_head * (long long)num_heads / (long long)num_kv_heads);
9593 const int q_end = (int)((long long)(kv_head + 1) * (long long)num_heads / (long long)num_kv_heads);
9594
9595 ck_local_fp16_to_fp32_2d(k_head, k_head_fp32, kv_tokens, aligned_head_dim, aligned_head_dim, aligned_head_dim);
9596 ck_local_fp16_to_fp32_2d(v_head, v_head_fp32, kv_tokens, aligned_head_dim, aligned_head_dim, aligned_head_dim);
9597
9598 for (int h = q_begin; h < q_end; ++h) {
9599 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
9600 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
9601
9602 attention_flash_decode(out_head,
9603 q_head,
9604 k_head_fp32,
9605 v_head_fp32,
9606 1,
9607 kv_tokens,
9608 1,
9609 aligned_head_dim,
9610 scale);
9611 }
9612 }
9613}
static void ck_local_fp16_to_fp32_2d(const uint16_t *src, float *dst, int rows, int cols, int src_stride, int dst_stride)

References attention_flash_decode(), CK_FP16_TO_FP32, ck_local_fp16_to_fp32_2d(), and score.

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_contract().

◆ attention_forward_decode_head_major_gqa_flash_f16cache_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_flash_f16cache_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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,
ck_attention_reduction_t  reduction 
)

Definition at line 6933 of file attention_kernels.c.

6945{
6946 if (!q_token || !k_cache || !v_cache || !out_token ||
6947 num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 ||
6948 cache_capacity <= 0 || kv_tokens > cache_capacity ||
6949 head_dim <= 0 || aligned_head_dim < head_dim) {
6951 }
6952
6953 switch (reduction) {
6956 q_token, k_cache, v_cache, out_token,
6957 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6958 head_dim, aligned_head_dim);
6960
6962 const int partition_alignment = 256;
6963 const int partition_tokens =
6964 ((kv_tokens + partition_alignment - 1) / partition_alignment) * partition_alignment;
6965 const int split_chunks = partition_tokens >= 512 ? ck_get_num_threads() : 1;
6967 q_token, k_cache, v_cache, out_token,
6968 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6969 head_dim, aligned_head_dim, split_chunks);
6971 }
6972
6975 q_token, k_cache, v_cache, out_token,
6976 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6977 head_dim, aligned_head_dim, 1);
6979
6980 default:
6982 }
6983}
void attention_forward_decode_head_major_gqa_flash_f16cache(const float *q_token, const uint16_t *k_cache, const uint16_t *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)
void attention_forward_decode_head_major_gqa_flash_f16cache_split(const float *q_token, const uint16_t *k_cache, const uint16_t *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 split_chunks)
int ck_get_num_threads(void)

References attention_forward_decode_head_major_gqa_flash_f16cache(), attention_forward_decode_head_major_gqa_flash_f16cache_split(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, CK_ATTN_REDUCTION_F16_ONLINE_FP32_MERGE, CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE, CK_ATTN_REDUCTION_FP32_ONLINE, and ck_get_num_threads().

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace(), and ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace().

◆ attention_forward_decode_head_major_gqa_flash_f16cache_split()

void attention_forward_decode_head_major_gqa_flash_f16cache_split ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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  split_chunks 
)

Definition at line 6784 of file attention_kernels.c.

6795{
6796 const int partition_alignment = 256;
6797 const int partition_tokens =
6798 ((kv_tokens + partition_alignment - 1) / partition_alignment) * partition_alignment;
6800 q_token, k_cache, v_cache, out_token,
6801 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6802 head_dim, aligned_head_dim, split_chunks, partition_tokens, 0,
6804}
static void attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned(const float *q_token, const uint16_t *k_cache, const uint16_t *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 split_chunks, int partition_tokens, int kv_start, float attention_scale)
static float ck_attention_strict_scale_f32(int head_dim)

References attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned(), and ck_attention_strict_scale_f32().

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_contract().

◆ attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned()

static void attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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  split_chunks,
int  partition_tokens,
int  kv_start,
float  attention_scale 
)
static

Definition at line 6662 of file attention_kernels.c.

6677{
6678 if (!q_token || !k_cache || !v_cache || !out_token ||
6679 num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 ||
6680 cache_capacity <= 0 || kv_tokens > cache_capacity ||
6681 kv_start < 0 || kv_start >= kv_tokens ||
6682 head_dim <= 0 || aligned_head_dim < head_dim ||
6683 partition_tokens < kv_tokens - kv_start || !isfinite(attention_scale)) {
6684 return;
6685 }
6686
6687 const int live_tokens = kv_tokens - kv_start;
6688
6689 if (split_chunks < 1) {
6690 split_chunks = 1;
6691 }
6692 if (split_chunks > live_tokens) {
6693 split_chunks = live_tokens;
6694 }
6695
6696 const int partial_stride = aligned_head_dim + 2;
6697 const size_t max_partial_bytes = 1024u * 1024u;
6698 while (split_chunks > 1 &&
6699 (size_t) num_heads * (size_t) split_chunks * (size_t) partial_stride * sizeof(float) >
6700 max_partial_bytes) {
6701 split_chunks = (split_chunks + 1) / 2;
6702 }
6703
6704 const int chunk_size = (partition_tokens + split_chunks - 1) / split_chunks;
6705 const int scheduled_chunks = (live_tokens + chunk_size - 1) / chunk_size;
6706 const size_t resolved_count =
6707 (size_t) num_heads * (size_t) scheduled_chunks * (size_t) partial_stride;
6708 float *partials = (float *) alloca(resolved_count * sizeof(float));
6709 ck_attention_f16_split_args_t args = {
6710 .q_token = q_token,
6711 .k_cache = k_cache,
6712 .v_cache = v_cache,
6713 .partials = partials,
6714 .num_heads = num_heads,
6715 .num_kv_heads = num_kv_heads,
6716 .kv_start = kv_start,
6717 .kv_tokens = kv_tokens,
6718 .cache_capacity = cache_capacity,
6719 .head_dim = head_dim,
6720 .aligned_head_dim = aligned_head_dim,
6721 .split_chunks = split_chunks,
6722 .scheduled_chunks = scheduled_chunks,
6723 .partition_tokens = partition_tokens,
6724 .attention_scale = attention_scale,
6725 };
6726
6727 ck_threadpool_t *pool = ck_threadpool_global();
6728 int active_threads = pool ? ck_threadpool_n_threads(pool) : 1;
6729 const int total_jobs = num_heads * scheduled_chunks;
6730 if (active_threads > total_jobs) {
6731 active_threads = total_jobs;
6732 }
6733 if (pool && active_threads > 1) {
6734 ck_threadpool_dispatch_n(pool, active_threads, ck_attention_f16_split_work, &args);
6735 } else {
6736 ck_attention_f16_split_work(0, 1, &args);
6737 }
6738
6739 for (int h = 0; h < num_heads; ++h) {
6740 float *out_head = out_token + (size_t) h * (size_t) aligned_head_dim;
6741 float final_max = -INFINITY;
6742 float final_sum = 0.0f;
6743 for (int d = 0; d < aligned_head_dim; ++d) {
6744 out_head[d] = 0.0f;
6745 }
6746
6747 for (int chunk = 0; chunk < scheduled_chunks; ++chunk) {
6748 const float *partial = partials +
6749 ((size_t) h * (size_t) scheduled_chunks + (size_t) chunk) * (size_t) partial_stride;
6750 const float chunk_max = partial[0];
6751 const float chunk_sum = partial[1];
6752 if (chunk_sum == 0.0f) {
6753 continue;
6754 }
6755 const float new_max = fmaxf(final_max, chunk_max);
6756 const float old_scale = isfinite(final_max)
6757 ? ck_attention_f16_reduce_expf(final_max - new_max)
6758 : 0.0f;
6759 const float chunk_scale =
6760 ck_attention_f16_reduce_expf(chunk_max - new_max);
6761 for (int d = 0; d < head_dim; ++d) {
6762 const float chunk_term = partial[2 + d] * chunk_scale;
6763 out_head[d] = fmaf(out_head[d], old_scale, chunk_term);
6764 }
6765#if defined(__INTEL_LLVM_COMPILER)
6766 const float scaled_chunk_sum = chunk_sum * chunk_scale;
6767 final_sum = fmaf(final_sum, old_scale, scaled_chunk_sum);
6768#else
6769 final_sum = fmaf(
6770 final_sum, old_scale, chunk_sum * chunk_scale);
6771#endif
6772 final_max = new_max;
6773 }
6774
6775 if (final_sum > 0.0f) {
6776 const float inv_sum = 1.0f / final_sum;
6777 for (int d = 0; d < head_dim; ++d) {
6778 out_head[d] *= inv_sum;
6779 }
6780 }
6781 }
6782}
static float ck_attention_f16_reduce_expf(float value)
static void ck_attention_f16_split_work(int ith, int nth, void *opaque)

References ck_attention_f16_reduce_expf(), ck_attention_f16_split_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_split(), and ck_attention_forward_decode_f16cache_gemma4().

◆ attention_forward_decode_head_major_gqa_flash_f16kv()

void attention_forward_decode_head_major_gqa_flash_f16kv ( 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 
)

Definition at line 6361 of file attention_kernels.c.

6371{
6372 if (!q_token || !k_cache || !v_cache || !out_token) {
6373 return;
6374 }
6375 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6376 return;
6377 }
6378 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6379 return;
6380 }
6381
6382 const float scale = 1.0f / sqrtf((float)head_dim);
6383 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6384
6385 for (int h = 0; h < num_heads; ++h) {
6386 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6387 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
6388 const float *k_head = k_cache + (size_t)kv_head * head_stride;
6389 const float *v_head = v_cache + (size_t)kv_head * head_stride;
6390 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
6391
6393 k_head,
6394 v_head,
6395 kv_tokens,
6396 head_dim,
6397 aligned_head_dim,
6398 scale,
6399 out_head);
6400 }
6401}
static void attention_flash_query_causal_exact_f16kv(const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)

References attention_flash_query_causal_exact_f16kv().

◆ attention_forward_decode_head_major_gqa_flash_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 
)

Definition at line 6256 of file attention_kernels.c.

6266{
6267 if (!q_token || !k_cache || !v_cache || !out_token) {
6268 return;
6269 }
6270 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6271 return;
6272 }
6273 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6274 return;
6275 }
6276
6277 const float scale = 1.0f;
6278 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6279
6280 for (int h = 0; h < num_heads; ++h) {
6281 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6282 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
6283 const float *k_head = k_cache + (size_t)kv_head * head_stride;
6284 const float *v_head = v_cache + (size_t)kv_head * head_stride;
6285 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
6286
6287 attention_flash_decode(out_head,
6288 q_head,
6289 k_head,
6290 v_head,
6291 1,
6292 kv_tokens,
6293 1,
6294 aligned_head_dim,
6295 scale);
6296 }
6297}

References attention_flash_decode().

Referenced by attention_forward_decode_head_major_gqa_flash_sliding_gemma4(), and attention_forward_decode_head_major_shared_kv_gemma4().

◆ attention_forward_decode_head_major_gqa_llama_regular_sliding_workspace()

void attention_forward_decode_head_major_gqa_llama_regular_sliding_workspace ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  live_tokens,
int  kv_stride_tokens,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
float *  scores,
size_t  scores_bytes,
float *  value_columns,
size_t  value_columns_bytes,
float *  scaled_scores,
size_t  scaled_scores_bytes 
)

Definition at line 6185 of file attention_kernels.c.

6192{
6194 q, k, v, output, num_heads, num_kv_heads, 1, live_tokens,
6195 head_dim, aligned_head_dim, kv_stride_tokens, sliding_window,
6196 scores, scores_bytes, value_columns, value_columns_bytes,
6197 scaled_scores, scaled_scores_bytes, 0);
6198}

References ck_attention_llama_regular_impl().

◆ attention_forward_decode_head_major_gqa_muse_eager_bf16_storage()

void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage ( 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,
float *  scores,
size_t  scores_bytes,
uint16_t *  key_rows,
size_t  key_rows_bytes,
uint16_t *  value_columns,
size_t  value_columns_bytes,
uint16_t *  gemm_rows,
size_t  gemm_rows_bytes,
uint16_t *  gemm_scores,
size_t  gemm_scores_bytes 
)

Definition at line 9242 of file attention_kernels.c.

9251{
9253 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
9254 1, kv_tokens, cache_capacity, head_dim, aligned_head_dim, 0,
9255 scores, scores_bytes, key_rows, key_rows_bytes,
9256 value_columns, value_columns_bytes, gemm_rows, gemm_rows_bytes,
9257 gemm_scores, gemm_scores_bytes);
9258}

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_decode_head_major_gqa_muse_eager_bf16_storage_sliding()

void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage_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,
float *  scores,
size_t  scores_bytes,
uint16_t *  key_rows,
size_t  key_rows_bytes,
uint16_t *  value_columns,
size_t  value_columns_bytes,
uint16_t *  gemm_rows,
size_t  gemm_rows_bytes,
uint16_t *  gemm_scores,
size_t  gemm_scores_bytes 
)

Definition at line 9260 of file attention_kernels.c.

9269{
9271 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
9272 1, kv_tokens, cache_capacity, head_dim, aligned_head_dim,
9273 sliding_window, scores, scores_bytes, key_rows, key_rows_bytes,
9274 value_columns, value_columns_bytes, gemm_rows, gemm_rows_bytes,
9275 gemm_scores, gemm_scores_bytes);
9276}

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_decode_head_major_gqa_regular()

void attention_forward_decode_head_major_gqa_regular ( 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 
)

WARNING: This is NOT true flash attention!

This function is named "flash" but implements regular attention with O(n) complexity. It's kept for reference and as a fallback.

TRUE flash attention is implemented in attention_flash_true.c

Test:

test_kv_cache_attention.py::TestKVCacheAttention::test_regular_decode

test_attention.py::TestAttentionForward::test_regular_decode

Regular attention decode (score-matrix version) for fallback.

After changes: make test

Definition at line 9629 of file attention_kernels.c.

9639{
9640 if (!q_token || !k_cache || !v_cache || !out_token) {
9641 return;
9642 }
9643 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
9644 return;
9645 }
9646 if (kv_tokens > cache_capacity) {
9647 return;
9648 }
9649
9650 const int strict = ck_strict_parity_enabled();
9651 const float scale = strict
9653 : 1.0f / sqrtf((float) head_dim);
9654 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
9655
9656 // Select SIMD implementation based on compile-time CPU features
9657#if defined(__AVX512F__)
9658 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal_avx512
9659#elif defined(__AVX2__)
9660 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal_avx2
9661#elif defined(__AVX__)
9662 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal_avx
9663#else
9664 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal
9665#endif
9666
9667#pragma omp parallel for schedule(static) if(num_heads > 1)
9668 for (int h = 0; h < num_heads; ++h) {
9669 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
9670 const float *q_vec = q_token + (size_t)h * (size_t)aligned_head_dim;
9671 const float *k_head = k_cache + (size_t)kv_head * head_stride;
9672 const float *v_head = v_cache + (size_t)kv_head * head_stride;
9673 float *out_vec = out_token + (size_t)h * (size_t)aligned_head_dim;
9674
9675 if (strict) {
9677 k_head,
9678 v_head,
9679 kv_tokens,
9680 head_dim,
9681 aligned_head_dim,
9682 scale,
9683 out_vec);
9684 continue;
9685 }
9686
9687 FLASH_QUERY_IMPL_DECODE(q_vec, k_head, v_head,
9688 kv_tokens, head_dim, aligned_head_dim,
9689 scale, out_vec);
9690 }
9691
9692#undef FLASH_QUERY_IMPL_DECODE
9693}
#define FLASH_QUERY_IMPL_DECODE
int ck_strict_parity_enabled(void)

References attention_flash_query_causal_exact_f16kv(), ck_attention_strict_scale_f32(), ck_strict_parity_enabled(), and FLASH_QUERY_IMPL_DECODE.

Referenced by ck_attention_flash_decode_wrapper(), ck_layer_forward_rmsnorm_swiglu_decode_fused_attn_impl(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_11_decode(), qwen2_0_5b_decode_layer_11_decode(), qwen2_0_5b_decode_layer_11_decode(), qwen2_0_5b_decode_layer_12_decode(), qwen2_0_5b_decode_layer_12_decode(), qwen2_0_5b_decode_layer_12_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_14_decode(), qwen2_0_5b_decode_layer_14_decode(), qwen2_0_5b_decode_layer_14_decode(), qwen2_0_5b_decode_layer_15_decode(), qwen2_0_5b_decode_layer_15_decode(), qwen2_0_5b_decode_layer_15_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_17_decode(), qwen2_0_5b_decode_layer_17_decode(), qwen2_0_5b_decode_layer_17_decode(), qwen2_0_5b_decode_layer_18_decode(), qwen2_0_5b_decode_layer_18_decode(), qwen2_0_5b_decode_layer_18_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_20_decode(), qwen2_0_5b_decode_layer_20_decode(), qwen2_0_5b_decode_layer_20_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_22_decode(), qwen2_0_5b_decode_layer_22_decode(), qwen2_0_5b_decode_layer_22_decode(), qwen2_0_5b_decode_layer_23_decode(), qwen2_0_5b_decode_layer_23_decode(), qwen2_0_5b_decode_layer_23_decode(), qwen2_0_5b_decode_layer_2_decode(), qwen2_0_5b_decode_layer_2_decode(), qwen2_0_5b_decode_layer_2_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_4_decode(), qwen2_0_5b_decode_layer_4_decode(), qwen2_0_5b_decode_layer_4_decode(), qwen2_0_5b_decode_layer_5_decode(), qwen2_0_5b_decode_layer_5_decode(), qwen2_0_5b_decode_layer_5_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), and qwen2_0_5b_decode_layer_9_decode().

◆ attention_forward_decode_head_major_shared_kv_gemma4()

void attention_forward_decode_head_major_shared_kv_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 
)

Definition at line 6345 of file attention_kernels.c.

6354{
6356 q_token, k_cache, v_cache, out_token, num_heads, num_heads,
6357 kv_tokens, cache_capacity, head_dim, aligned_head_dim
6358 );
6359}
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().

◆ attention_forward_full_head_major_gqa_exact_strided()

void attention_forward_full_head_major_gqa_exact_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 
)

Definition at line 5446 of file attention_kernels.c.

5456{
5457 if (!q || !k || !v || !output) {
5458 return;
5459 }
5460 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
5461 return;
5462 }
5463 if (kv_stride_tokens < num_tokens) {
5464 return;
5465 }
5466
5467 const float scale = ck_strict_parity_enabled()
5469 : 1.0f / sqrtf((float) head_dim);
5470 const int T = num_tokens;
5471 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
5472 const int debug_layer_id = ck_strict_parity_enabled() ? ck_attention_vec_dump_next_layer_id() : -1;
5473 float *score_row = (float *) alloca((size_t) T * sizeof(float));
5474 float *v_cols = (float *) alloca((size_t) head_dim * (size_t) T * sizeof(float));
5475 for (int h = 0; h < num_heads; ++h) {
5476 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
5477 const float *k_head = k + (size_t) kv_head * kv_head_stride;
5478 const float *v_head = v + (size_t) kv_head * kv_head_stride;
5479
5480#if CK_ENABLE_LLAMA_CPP_PARITY
5481 float *out_head = output + (size_t) h * (size_t) T * (size_t) aligned_head_dim;
5484 q + (size_t) h * (size_t) T * (size_t) aligned_head_dim,
5485 k_head,
5486 v_head,
5487 out_head,
5488 T,
5489 head_dim,
5490 aligned_head_dim,
5491 scale)) {
5492 ck_attention_trace("regular_graph_oracle", debug_layer_id, h);
5493 continue;
5494 }
5495#endif
5496
5497 for (int d = 0; d < head_dim; ++d) {
5498 float *dst_col = v_cols + (size_t) d * (size_t) T;
5499 for (int j = 0; j < T; ++j) {
5500 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
5501 }
5502 }
5503
5504 for (int i = 0; i < T; ++i) {
5505 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
5506 float *out_vec = output + qkv_index(h, i, 0, T, aligned_head_dim);
5508 k_head,
5509 v_cols,
5510 T,
5511 head_dim,
5512 aligned_head_dim,
5513 scale,
5514 score_row,
5515 out_vec,
5516 debug_layer_id,
5517 h,
5518 i);
5519 }
5520 }
5521}
static int ck_attention_vec_dump_next_layer_id(void)
static void attention_query_full_exact_regular(const float *q_vec, const float *k_head, const float *v_cols, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *score_row, float *out_vec, int layer_id, int head_id, int query_id)
static void ck_attention_trace(const char *branch, int layer_id, int head_id)
int ck_attention_head_full_ggml_graph_oracle_regular(const float *q_head, const float *k_head, const float *v_head, float *out_head, int num_tokens, int head_dim, int aligned_head_dim, float scale)

References attention_query_full_exact_regular(), ck_attention_head_full_ggml_graph_oracle_regular(), ck_attention_strict_scale_f32(), ck_attention_trace(), ck_attention_vec_dump_next_layer_id(), ck_strict_parity_enabled(), and qkv_index().

◆ attention_forward_full_head_major_gqa_flash()

void attention_forward_full_head_major_gqa_flash ( 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 
)

Definition at line 4465 of file attention_kernels.c.

4474{
4476 num_heads, num_kv_heads,
4477 num_tokens, head_dim,
4478 aligned_head_dim,
4479 /*kv_stride_tokens=*/num_tokens,
4480 /*causal=*/0,
4481 /*round_full_kv_fp16=*/1,
4482 /*output_token_major=*/0,
4483 1.0f / sqrtf((float)head_dim));
4484}

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_full_head_major_gqa_flash_strided()

void attention_forward_full_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 
)

Definition at line 4541 of file attention_kernels.c.

4551{
4553 num_heads, num_kv_heads,
4554 num_tokens, head_dim,
4555 aligned_head_dim,
4556 kv_stride_tokens,
4557 /*causal=*/0,
4558 /*round_full_kv_fp16=*/1,
4559 /*output_token_major=*/0,
4560 1.0f / sqrtf((float)head_dim));
4561}

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_full_head_major_gqa_flash_strided_bf16_storage()

void attention_forward_full_head_major_gqa_flash_strided_bf16_storage ( 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 
)

Definition at line 4994 of file attention_kernels.c.

5005{
5007 q, k, v, output,
5008 num_heads, num_kv_heads, num_tokens, head_dim,
5009 aligned_head_dim, kv_stride_tokens,
5010 /*causal=*/0,
5011 /*round_full_kv_fp16=*/0,
5012 /*output_token_major=*/0,
5013 1.0f / sqrtf((float)head_dim)
5014 );
5015 const size_t count = (size_t)num_heads * (size_t)num_tokens
5016 * (size_t)aligned_head_dim;
5017 for (size_t i = 0; i < count; ++i) {
5018 output[i] = bf16_to_float(float_to_bf16(output[i]));
5019 }
5020}

References attention_forward_head_major_gqa_flash_impl(), bf16_to_float(), count, and float_to_bf16().

◆ attention_forward_full_head_major_gqa_flash_strided_gemma4()

void attention_forward_full_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 
)

Definition at line 5158 of file attention_kernels.c.

5168{
5169 (void)head_dim;
5171 num_heads, num_kv_heads,
5172 num_tokens, head_dim,
5173 aligned_head_dim,
5174 kv_stride_tokens,
5175 /*causal=*/0,
5176 /*round_full_kv_fp16=*/1,
5177 /*output_token_major=*/0,
5178 1.0f);
5179}

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_full_head_major_gqa_ggml_strided()

void attention_forward_full_head_major_gqa_ggml_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 
)

Definition at line 5764 of file attention_kernels.c.

5774{
5775 if (num_heads <= 0 || num_tokens <= 0 || head_dim <= 0 ||
5776 (size_t) num_heads > SIZE_MAX / (size_t) num_tokens ||
5777 (size_t) head_dim > SIZE_MAX / (size_t) num_tokens) {
5778 return;
5779 }
5780 const size_t score_elements = (size_t) num_heads * (size_t) num_tokens;
5781 const size_t columns_per_head = (size_t) head_dim * (size_t) num_tokens;
5782 if ((size_t) num_heads > SIZE_MAX / columns_per_head) return;
5783 const size_t column_elements = (size_t) num_heads * columns_per_head;
5784 if (score_elements > SIZE_MAX - column_elements ||
5785 score_elements + column_elements > SIZE_MAX - (size_t) num_tokens) return;
5786 const size_t total_elements = score_elements + column_elements + (size_t) num_tokens;
5787 if (total_elements > SIZE_MAX / sizeof(float)) return;
5788 float *workspace = (float *) malloc(total_elements * sizeof(float));
5789 if (!workspace) return;
5790 float *score_rows = workspace;
5791 float *v_columns = score_rows + score_elements;
5792 float *probability_row = v_columns + column_elements;
5794 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5795 aligned_head_dim, kv_stride_tokens,
5796 score_rows, score_elements * sizeof(float),
5797 v_columns, column_elements * sizeof(float),
5798 probability_row, (size_t) num_tokens * sizeof(float));
5799 free(workspace);
5800}
void attention_forward_full_head_major_gqa_ggml_strided_workspace(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, float *score_rows, size_t score_rows_bytes, float *v_columns, size_t v_columns_bytes, float *probability_row, size_t probability_row_bytes)

References attention_forward_full_head_major_gqa_ggml_strided_workspace().

◆ attention_forward_full_head_major_gqa_ggml_strided_workspace()

void attention_forward_full_head_major_gqa_ggml_strided_workspace ( 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,
float *  score_rows,
size_t  score_rows_bytes,
float *  v_columns,
size_t  v_columns_bytes,
float *  probability_row,
size_t  probability_row_bytes 
)

Definition at line 5523 of file attention_kernels.c.

5540{
5541 if (!q || !k || !v || !output) {
5542 return;
5543 }
5544 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
5545 return;
5546 }
5547 if (kv_stride_tokens < num_tokens) {
5548 return;
5549 }
5550
5551 const size_t T = (size_t) num_tokens;
5552 if ((size_t) num_heads > SIZE_MAX / T ||
5553 (size_t) head_dim > SIZE_MAX / T) {
5554 return;
5555 }
5556 const size_t score_elements = (size_t) num_heads * T;
5557 const size_t columns_per_head = (size_t) head_dim * T;
5558 if ((size_t) num_heads > SIZE_MAX / columns_per_head ||
5559 score_elements > SIZE_MAX / sizeof(float) ||
5560 columns_per_head * (size_t) num_heads > SIZE_MAX / sizeof(float) ||
5561 T > SIZE_MAX / sizeof(float)) {
5562 return;
5563 }
5564 const size_t column_elements = columns_per_head * (size_t) num_heads;
5565 if (!score_rows || score_rows_bytes < score_elements * sizeof(float) ||
5566 !v_columns || v_columns_bytes < column_elements * sizeof(float) ||
5567 !probability_row || probability_row_bytes < T * sizeof(float)) {
5568 return;
5569 }
5570
5571 const int strict = ck_strict_parity_enabled();
5572 const float scale = strict
5574 : 1.0f / sqrtf((float) head_dim);
5575 const int token_count = num_tokens;
5576 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
5577 const int debug_layer_id = strict ? ck_attention_vec_dump_next_layer_id() : -1;
5578#if CK_ENABLE_LLAMA_CPP_PARITY
5579 ck_ggml_vec_dot_f32_fn dot_fn = NULL;
5580 ck_ggml_vec_soft_max_f32_fn softmax_fn = NULL;
5581 ck_ggml_compute_forward_mul_mat_fn mul_mat_fn = NULL;
5582 ck_ggml_compute_forward_soft_max_fn softmax_compute_fn = NULL;
5583 if (strict) {
5585 k,
5586 v,
5587 output,
5588 num_heads,
5589 num_kv_heads,
5590 num_tokens,
5591 head_dim,
5592 aligned_head_dim,
5593 kv_stride_tokens,
5594 scale)) {
5595 return;
5596 }
5597 dot_fn = ck_resolve_ggml_vec_dot_f32();
5598 softmax_fn = ck_resolve_ggml_vec_soft_max_f32();
5599 mul_mat_fn = ck_resolve_ggml_compute_forward_mul_mat();
5600 softmax_compute_fn = ck_resolve_ggml_compute_forward_soft_max();
5601 }
5602#endif
5603 if (strict) {
5604 float *score_row = score_rows;
5605 float *v_cols = v_columns;
5606#if CK_ENABLE_LLAMA_CPP_PARITY
5607 float *prob_row = probability_row;
5608#endif
5609
5610 for (int h = 0; h < num_heads; ++h) {
5611 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
5612 const float *k_head = k + (size_t) kv_head * kv_head_stride;
5613 const float *v_head = v + (size_t) kv_head * kv_head_stride;
5614
5615#if CK_ENABLE_LLAMA_CPP_PARITY
5616 float *out_head = output + (size_t) h * (size_t) T * (size_t) aligned_head_dim;
5618 q + (size_t) h * (size_t) T * (size_t) aligned_head_dim,
5619 k_head,
5620 v_head,
5621 out_head,
5622 token_count,
5623 head_dim,
5624 aligned_head_dim,
5625 scale)) {
5626 continue;
5627 }
5628#endif
5629
5630 for (int d = 0; d < head_dim; ++d) {
5631 float *dst_col = v_cols + (size_t) d * (size_t) token_count;
5632 for (int j = 0; j < token_count; ++j) {
5633 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
5634 }
5635 }
5636
5637#if CK_ENABLE_LLAMA_CPP_PARITY
5638 if (dot_fn && softmax_fn && ck_attention_ggml_out_graph_enabled()) {
5639 if (attention_head_full_dyn_ggml_regular_graph_out(
5640 q + (size_t) h * (size_t) T * (size_t) aligned_head_dim,
5641 k_head,
5642 v_cols,
5643 token_count,
5644 head_dim,
5645 aligned_head_dim,
5646 scale,
5647 score_row,
5648 prob_row,
5649 out_head,
5650 dot_fn,
5651 softmax_fn,
5652 debug_layer_id,
5653 h)) {
5654 if (token_count > 0) {
5655 ck_attention_trace("dyn_ggml_regular_graph_out", debug_layer_id, h);
5656 ck_attention_trace_float("scale", debug_layer_id, h, scale);
5657 }
5658 continue;
5659 }
5660 }
5661#endif
5662
5663 for (int i = 0; i < token_count; ++i) {
5664 const float *q_vec = q + qkv_index(h, i, 0, token_count, aligned_head_dim);
5665 float *out_vec = output + qkv_index(h, i, 0, token_count, aligned_head_dim);
5666#if CK_ENABLE_LLAMA_CPP_PARITY
5667 if (dot_fn && softmax_fn) {
5668 if (i == 0) {
5669 ck_attention_trace("dyn_ggml_regular", debug_layer_id, h);
5670 ck_attention_trace_float("scale", debug_layer_id, h, scale);
5671 }
5672 attention_query_full_dyn_ggml_regular(q_vec,
5673 k_head,
5674 v_cols,
5675 token_count,
5676 head_dim,
5677 aligned_head_dim,
5678 scale,
5679 score_row,
5680 prob_row,
5681 out_vec,
5682 dot_fn,
5683 softmax_fn,
5684 debug_layer_id,
5685 h,
5686 i);
5687 } else if (dot_fn && mul_mat_fn && softmax_compute_fn) {
5688 if (i == 0) {
5689 ck_attention_trace("ggml_compute_regular", debug_layer_id, h);
5690 }
5691 attention_query_full_ggml_compute_regular(q_vec,
5692 k_head,
5693 v_cols,
5694 token_count,
5695 head_dim,
5696 aligned_head_dim,
5697 scale,
5698 score_row,
5699 prob_row,
5700 out_vec,
5701 dot_fn,
5702 mul_mat_fn,
5703 softmax_compute_fn);
5704 } else
5705#endif
5706 {
5707 if (i == 0) {
5708 ck_attention_trace("ggml_regular", debug_layer_id, h);
5709 }
5711 k_head,
5712 v_cols,
5713 token_count,
5714 head_dim,
5715 aligned_head_dim,
5716 scale,
5717 score_row,
5718 out_vec,
5719 debug_layer_id,
5720 h,
5721 i);
5722 }
5723 }
5724 }
5725 return;
5726 }
5727
5728#pragma omp parallel for schedule(static) if(num_heads > 1)
5729 for (int h = 0; h < num_heads; ++h) {
5730 float *score_row = score_rows + (size_t) h * (size_t) token_count;
5731 float *v_cols = v_columns + (size_t) h * (size_t) head_dim * (size_t) token_count;
5732 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
5733 const float *k_head = k + (size_t) kv_head * kv_head_stride;
5734 const float *v_head = v + (size_t) kv_head * kv_head_stride;
5735
5736 if (v_cols) {
5737 for (int d = 0; d < head_dim; ++d) {
5738 float *dst_col = v_cols + (size_t) d * (size_t) token_count;
5739 for (int j = 0; j < token_count; ++j) {
5740 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
5741 }
5742 }
5743 }
5744
5745 for (int i = 0; i < token_count; ++i) {
5746 const float *q_vec = q + qkv_index(h, i, 0, token_count, aligned_head_dim);
5747 float *out_vec = output + qkv_index(h, i, 0, token_count, aligned_head_dim);
5749 k_head,
5750 v_cols,
5751 token_count,
5752 head_dim,
5753 aligned_head_dim,
5754 scale,
5755 score_row,
5756 out_vec,
5757 -1,
5758 h,
5759 i);
5760 }
5761 }
5762}
static void ck_attention_trace_float(const char *tag, int layer_id, int head_id, float value)
static int ck_attention_ggml_out_graph_enabled(void)
static void attention_query_full_ggml_regular(const float *q_vec, const float *k_head, const float *v_cols, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *score_row, float *out_vec, int layer_id, int head_id, int query_id)
int ck_attention_full_ggml_graph_oracle_multihead(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, float scale)

References attention_query_full_ggml_regular(), ck_attention_full_ggml_graph_oracle_multihead(), ck_attention_ggml_out_graph_enabled(), ck_attention_head_full_ggml_graph_oracle_regular(), ck_attention_strict_scale_f32(), ck_attention_trace(), ck_attention_trace_float(), ck_attention_vec_dump_next_layer_id(), ck_strict_parity_enabled(), and qkv_index().

Referenced by attention_forward_full_head_major_gqa_ggml_strided().

◆ attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage()

void attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage ( 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 
)

Definition at line 5047 of file attention_kernels.c.

5058{
5060 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5061 head_dim, aligned_head_dim, kv_stride_tokens,
5062 /*output_token_major=*/0)) {
5063 return;
5064 }
5065 fprintf(stderr,
5066 "HARD KERNEL CONTRACT FAULT: PyTorch CPU-flash BF16 attention "
5067 "requires AMX-BF16, AVX-512, D=72/A=72 and a token multiple of 16; "
5068 "no numerically different fallback is permitted\n");
5069 abort();
5070}
static int ck_attention_full_bf16_pytorch_flash(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 output_token_major)

References ck_attention_full_bf16_pytorch_flash().

◆ attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage_token_output()

void attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage_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 
)

Definition at line 5072 of file attention_kernels.c.

5083{
5085 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5086 head_dim, aligned_head_dim, kv_stride_tokens,
5087 /*output_token_major=*/1)) {
5088 return;
5089 }
5090 fprintf(stderr,
5091 "HARD KERNEL CONTRACT FAULT: PyTorch CPU-flash BF16 token-output "
5092 "attention requires AMX-BF16, AVX-512, D=72/A=72 and a token "
5093 "multiple of 16; no numerically different fallback is permitted\n");
5094 abort();
5095}

References ck_attention_full_bf16_pytorch_flash().

◆ attention_forward_full_head_major_gqa_sdpa_bf16_storage()

void attention_forward_full_head_major_gqa_sdpa_bf16_storage ( 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 
)

Definition at line 5022 of file attention_kernels.c.

5033{
5035 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5036 head_dim, aligned_head_dim, kv_stride_tokens)) {
5037 const size_t count = (size_t)num_heads * (size_t)num_tokens
5038 * (size_t)aligned_head_dim;
5039 for (size_t i = 0; i < count; ++i) {
5040 output[i] = bf16_to_float(float_to_bf16(output[i]));
5041 }
5042 return;
5043 }
5044 fprintf(stderr, "CK numerical contract failure: BF16 tiled SDPA received invalid dimensions or could not allocate scratch\n");
5045}
static int ck_attention_full_bf16_sdpa_tiled(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 bf16_to_float(), ck_attention_full_bf16_sdpa_tiled(), count, and float_to_bf16().

◆ attention_forward_full_head_major_gqa_tiled336_f16kv_fp32_strided()

void attention_forward_full_head_major_gqa_tiled336_f16kv_fp32_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 
)

Definition at line 3638 of file attention_kernels.c.

3649{
3651 q, k, v, output, num_heads, num_kv_heads, num_tokens,
3652 head_dim, aligned_head_dim, kv_stride_tokens, CK_GGML_FA_TILE_Q_LARGE);
3653}
#define CK_GGML_FA_TILE_Q_LARGE
static void ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_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, int query_tile_size)

References ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(), and CK_GGML_FA_TILE_Q_LARGE.

◆ attention_forward_full_head_major_gqa_tiled64_f16kv_fp32_strided()

void attention_forward_full_head_major_gqa_tiled64_f16kv_fp32_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 
)

Definition at line 3621 of file attention_kernels.c.

3632{
3634 q, k, v, output, num_heads, num_kv_heads, num_tokens,
3635 head_dim, aligned_head_dim, kv_stride_tokens, CK_GGML_FA_TILE_Q);
3636}

References ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(), and CK_GGML_FA_TILE_Q.

◆ attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided()

void attention_forward_full_head_major_gqa_tiled_f16kv_fp32_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 
)

Definition at line 3601 of file attention_kernels.c.

3612{
3613 const int query_tile_size = num_tokens >= CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS
3617 q, k, v, output, num_heads, num_kv_heads, num_tokens,
3618 head_dim, aligned_head_dim, kv_stride_tokens, query_tile_size);
3619}
#define CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS

References ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(), CK_GGML_FA_TILE_Q, CK_GGML_FA_TILE_Q_LARGE, and CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS.

◆ attention_forward_head_major_gqa_flash_impl()

static void attention_forward_head_major_gqa_flash_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  causal,
int  round_full_kv_fp16,
int  output_token_major,
float  scale 
)
static

Definition at line 4183 of file attention_kernels.c.

4197{
4198 if (!q || !k || !v || !output) {
4199 return;
4200 }
4201 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0 ||
4202 head_dim <= 0 || aligned_head_dim < head_dim) {
4203 return;
4204 }
4205 if (kv_stride_tokens < num_tokens) {
4206 return;
4207 }
4208
4209 const int T = num_tokens;
4210 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
4211
4213 const float strict_scale = ck_attention_strict_scale_f32(head_dim);
4214 const int debug_layer_id = ck_attention_vec_dump_enabled()
4216 : -1;
4219 q, k, v, output,
4220 num_heads, num_kv_heads, num_tokens,
4221 head_dim, aligned_head_dim, kv_stride_tokens,
4222 causal, output_token_major, strict_scale, debug_layer_id)) {
4223 return;
4224 }
4225 }
4226#if CK_ENABLE_LLAMA_CPP_PARITY
4227 if (!causal && !output_token_major &&
4229 k,
4230 v,
4231 output,
4232 num_heads,
4233 num_kv_heads,
4234 num_tokens,
4235 head_dim,
4236 aligned_head_dim,
4237 kv_stride_tokens,
4238 strict_scale)) {
4239 return;
4240 }
4241#endif
4242 float *score_row = (float *) alloca((size_t) T * sizeof(float));
4243 float *logit_row = (float *) alloca((size_t) T * sizeof(float));
4244 float *v_cols = (float *) alloca((size_t) head_dim * (size_t) T * sizeof(float));
4245 for (int h = 0; h < num_heads; ++h) {
4246 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
4247 const float *k_head = k + (size_t)kv_head * kv_head_stride;
4248 const float *v_head = v + (size_t)kv_head * kv_head_stride;
4249
4250 for (int d = 0; d < head_dim; ++d) {
4251 float *dst_col = v_cols + (size_t) d * (size_t) T;
4252 for (int j = 0; j < T; ++j) {
4253 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
4254 }
4255 }
4256
4257 for (int i = 0; i < T; ++i) {
4258 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
4259 float *out_vec = output + qkv_index(h, i, 0, T, aligned_head_dim);
4260 const int kv_tokens = causal ? (i + 1) : T;
4261 if (kv_tokens <= 0) {
4262 for (int d = 0; d < aligned_head_dim; ++d) {
4263 out_vec[d] = 0.0f;
4264 }
4265 continue;
4266 }
4267 for (int j = 0; j < kv_tokens; ++j) {
4268 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
4269 score_row[j] = ck_ggml_vec_dot_f32_contig(q_vec, k_vec, head_dim);
4270 }
4271 float *raw_dump = NULL;
4272 if (ck_attention_vec_dump_should_emit(debug_layer_id, h, i)) {
4273 raw_dump = (float *) alloca((size_t) kv_tokens * sizeof(float));
4274 memcpy(raw_dump, score_row, (size_t) kv_tokens * sizeof(float));
4275 }
4276 memcpy(logit_row, score_row, (size_t) kv_tokens * sizeof(float));
4277 ck_vec_scale_f32_inplace(logit_row, kv_tokens, strict_scale);
4278 const float max_score = ck_vec_max_f32_contig(logit_row, kv_tokens);
4279 const double sum = ck_ggml_vec_soft_max_row(kv_tokens, score_row, logit_row, max_score);
4280 if (sum > 0.0) {
4281 const float inv_sum = (float) (1.0 / sum);
4282 ck_vec_scale_f32_inplace(score_row, kv_tokens, inv_sum);
4283 for (int d = 0; d < head_dim; ++d) {
4284 const float *v_col = v_cols + (size_t) d * (size_t) T;
4285 out_vec[d] = ck_ggml_vec_dot_f32_contig(score_row, v_col, kv_tokens);
4286 }
4287 } else {
4288 for (int d = 0; d < head_dim; ++d) {
4289 out_vec[d] = 0.0f;
4290 }
4291 }
4292 for (int d = head_dim; d < aligned_head_dim; ++d) {
4293 out_vec[d] = 0.0f;
4294 }
4295 if (raw_dump) {
4296 ck_attention_vec_dump_selected_query(raw_dump, score_row, out_vec, v_cols,
4297 kv_tokens, head_dim,
4298 debug_layer_id, h, i);
4299 }
4300 }
4301 }
4302 return;
4303 }
4304
4305 /*
4306 * Full GGML-style attention consumes FP32 Q with K/V rounded through
4307 * FP16. Materialize that semantic input once so serial, threaded, and
4308 * ISA-specific implementations all see the same values. Causal callers
4309 * retain their existing FP32 K/V contract.
4310 */
4311 float *rounded_kv = NULL;
4312 const float *compute_k = k;
4313 const float *compute_v = v;
4314 if (!causal && round_full_kv_fp16) {
4315 if ((size_t) kv_stride_tokens > SIZE_MAX / (size_t) num_kv_heads) {
4316 return;
4317 }
4318 const size_t rows = (size_t) num_kv_heads * (size_t) kv_stride_tokens;
4319 if ((size_t) aligned_head_dim > SIZE_MAX / rows) {
4320 return;
4321 }
4322 const size_t elements = rows * (size_t) aligned_head_dim;
4323 if (elements > SIZE_MAX / (2 * sizeof(float))) {
4324 return;
4325 }
4326 rounded_kv = (float *) malloc(2 * elements * sizeof(float));
4327 if (!rounded_kv) {
4328 return;
4329 }
4330 compute_k = rounded_kv;
4331 compute_v = rounded_kv + elements;
4332 ck_round_fp16_buffer(k, rounded_kv, elements);
4333 ck_round_fp16_buffer(v, rounded_kv + elements, elements);
4334 }
4335
4336 // Select SIMD implementation based on compile-time CPU features
4337#if defined(__AVX512F__)
4338 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx512
4339#elif defined(__AVX2__)
4340 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx2
4341#elif defined(__AVX__)
4342 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx
4343#else
4344 #define FLASH_QUERY_IMPL attention_flash_query_causal
4345#endif
4346
4347 const int total_queries = num_heads * T;
4348#if defined(__AVX512F__)
4349 if (!causal && !output_token_major && head_dim == 72 && aligned_head_dim >= 72 && ck_attention_qblock8_enabled()) {
4350 ck_threadpool_t *pool = ck_threadpool_global();
4351 const int q_blocks = (T + 7) / 8;
4352 const int total_blocks = num_heads * q_blocks;
4353 int active = ck_attention_pick_active_threads(pool, total_blocks, T);
4354 if (pool && active > 1) {
4355 ck_attention_qblock4_args_t args = {
4356 .q = q,
4357 .k = compute_k,
4358 .v = compute_v,
4359 .output = output,
4360 .num_heads = num_heads,
4361 .num_kv_heads = num_kv_heads,
4362 .num_tokens = num_tokens,
4363 .aligned_head_dim = aligned_head_dim,
4364 .kv_stride_tokens = kv_stride_tokens,
4365 .scale = scale,
4366 };
4367 ck_threadpool_dispatch_n(pool, active, ck_attention_full_qblock8_work, &args);
4368 free(rounded_kv);
4369 return;
4370 }
4371 }
4372
4373 if (!causal && !output_token_major && head_dim == 72 && aligned_head_dim >= 72 && ck_attention_qblock4_enabled()) {
4374 ck_threadpool_t *pool = ck_threadpool_global();
4375 const int q_blocks = (T + 3) / 4;
4376 const int total_blocks = num_heads * q_blocks;
4377 int active = ck_attention_pick_active_threads(pool, total_blocks, T);
4378 if (pool && active > 1) {
4379 ck_attention_qblock4_args_t args = {
4380 .q = q,
4381 .k = compute_k,
4382 .v = compute_v,
4383 .output = output,
4384 .num_heads = num_heads,
4385 .num_kv_heads = num_kv_heads,
4386 .num_tokens = num_tokens,
4387 .aligned_head_dim = aligned_head_dim,
4388 .kv_stride_tokens = kv_stride_tokens,
4389 .scale = scale,
4390 };
4391 ck_threadpool_dispatch_n(pool, active, ck_attention_full_qblock4_work, &args);
4392 free(rounded_kv);
4393 return;
4394 }
4395 }
4396#endif
4397 if (ck_attention_parallel_enabled(total_queries, T, head_dim)) {
4398 ck_threadpool_t *pool = ck_threadpool_global();
4399 const int active = ck_attention_pick_active_threads(pool, total_queries, T);
4400 if (pool && active > 1) {
4401 ck_attention_parallel_args_t args = {
4402 .q = q,
4403 .k = compute_k,
4404 .v = compute_v,
4405 .output = output,
4406 .num_heads = num_heads,
4407 .num_kv_heads = num_kv_heads,
4408 .num_tokens = num_tokens,
4409 .head_dim = head_dim,
4410 .aligned_head_dim = aligned_head_dim,
4411 .kv_stride_tokens = kv_stride_tokens,
4412 .causal = causal,
4413 .output_token_major = output_token_major,
4414 .scale = scale,
4415 };
4417 free(rounded_kv);
4418 return;
4419 }
4420 }
4421
4422 for (int h = 0; h < num_heads; ++h) {
4423 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
4424 const float *k_head = compute_k + (size_t)kv_head * kv_head_stride;
4425 const float *v_head = compute_v + (size_t)kv_head * kv_head_stride;
4426
4427 for (int i = 0; i < T; ++i) {
4428 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
4429 float *out_vec = output + attention_output_index(
4430 h, i, num_heads, T, aligned_head_dim, output_token_major);
4431 const int kv_tokens = causal ? (i + 1) : T;
4432 FLASH_QUERY_IMPL(q_vec, k_head, v_head,
4433 kv_tokens,
4434 head_dim, aligned_head_dim,
4435 scale, out_vec);
4436 }
4437 }
4438
4439 free(rounded_kv);
4440
4441#undef FLASH_QUERY_IMPL
4442}
static double ck_ggml_vec_soft_max_row(int n, float *y, const float *x, float max)
static void ck_vec_scale_f32_inplace(float *x, int n, float scale)
static size_t attention_output_index(int h, int token, int num_heads, int num_tokens, int aligned_head_dim, int token_major)
static float ck_vec_max_f32_contig(const float *x, int n)
static int ck_attention_strict_unfused_f16_enabled(void)
#define FLASH_QUERY_IMPL
static int ck_attention_pick_active_threads(const ck_threadpool_t *pool, int total_queries, int num_tokens)
static float ck_ggml_vec_dot_f32_contig(const float *x, const float *y, int n)
static void ck_attention_vec_dump_selected_query(const float *raw_scores, const float *probs, const float *out_vec, const float *v_cols, int kv_tokens, int head_dim, int layer_id, int head_id, int query_id)
static void ck_attention_full_grid_work(int ith, int nth, void *opaque)
static int attention_forward_head_major_gqa_unfused_f16_strict(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 causal, int output_token_major, float scale, int debug_layer_id)
static int ck_attention_vec_dump_should_emit(int layer_id, int head_id, int query_id)
static int ck_attention_parallel_enabled(int total_queries, int num_tokens, int head_dim)

References attention_forward_head_major_gqa_unfused_f16_strict(), attention_output_index(), ck_attention_full_ggml_graph_oracle_multihead(), ck_attention_full_grid_work(), ck_attention_parallel_enabled(), ck_attention_pick_active_threads(), ck_attention_strict_scale_f32(), ck_attention_strict_unfused_f16_enabled(), ck_attention_vec_dump_enabled(), ck_attention_vec_dump_next_layer_id(), ck_attention_vec_dump_selected_query(), ck_attention_vec_dump_should_emit(), ck_ggml_vec_dot_f32_contig(), ck_ggml_vec_soft_max_row(), ck_round_fp16_buffer(), ck_strict_parity_enabled(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_vec_max_f32_contig(), ck_vec_scale_f32_inplace(), FLASH_QUERY_IMPL, and qkv_index().

Referenced by attention_forward_causal_head_major_gqa_flash(), attention_forward_causal_head_major_gqa_flash_strided(), attention_forward_causal_head_major_gqa_flash_strided_gemma4(), attention_forward_causal_head_major_gqa_flash_strided_gemma4_token_output(), attention_forward_causal_head_major_gqa_flash_strided_token_output(), attention_forward_full_head_major_gqa_flash(), attention_forward_full_head_major_gqa_flash_strided(), attention_forward_full_head_major_gqa_flash_strided_bf16_storage(), attention_forward_full_head_major_gqa_flash_strided_gemma4(), and attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl().

◆ attention_forward_head_major_gqa_unfused_f16_strict()

static int attention_forward_head_major_gqa_unfused_f16_strict ( 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  causal,
int  output_token_major,
float  scale,
int  debug_layer_id 
)
static

Definition at line 4095 of file attention_kernels.c.

4110{
4111 const int T = num_tokens;
4112 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
4113 const size_t kv_half_count = (size_t) T * (size_t) aligned_head_dim;
4114 uint16_t *k_half = (uint16_t *) malloc(kv_half_count * sizeof(uint16_t));
4115 uint16_t *v_half = (uint16_t *) malloc(kv_half_count * sizeof(uint16_t));
4116 if (!k_half || !v_half) {
4117 free(k_half);
4118 free(v_half);
4119 return 0;
4120 }
4121 uint16_t *q_half = (uint16_t *) alloca((size_t) aligned_head_dim * sizeof(uint16_t));
4122 uint16_t *prob_half = (uint16_t *) alloca((size_t) T * sizeof(uint16_t));
4123 uint16_t *v_col_half = (uint16_t *) alloca((size_t) T * sizeof(uint16_t));
4124 float *raw_scores = (float *) alloca((size_t) T * sizeof(float));
4125 float *logits = (float *) alloca((size_t) T * sizeof(float));
4126 int cached_kv_head = -1;
4127
4128 for (int h = 0; h < num_heads; ++h) {
4129 const int kv_head = (int) ((long long) h * (long long) num_kv_heads /
4130 (long long) num_heads);
4131 const float *k_head = k + (size_t) kv_head * kv_head_stride;
4132 const float *v_head = v + (size_t) kv_head * kv_head_stride;
4133 if (kv_head != cached_kv_head) {
4134 for (size_t idx = 0; idx < kv_half_count; ++idx) {
4135 k_half[idx] = CK_FP32_TO_FP16(k_head[idx]);
4136 v_half[idx] = CK_FP32_TO_FP16(v_head[idx]);
4137 }
4138 cached_kv_head = kv_head;
4139 }
4140
4141 for (int i = 0; i < T; ++i) {
4142 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
4143 float *out_vec = output + attention_output_index(
4144 h, i, num_heads, T, aligned_head_dim, output_token_major);
4145 const int kv_tokens = causal ? i + 1 : T;
4146 for (int d = 0; d < aligned_head_dim; ++d) {
4147 q_half[d] = CK_FP32_TO_FP16(q_vec[d]);
4148 }
4149 for (int j = 0; j < kv_tokens; ++j) {
4150 raw_scores[j] = ck_attention_dot_f16_unfused_llama(
4151 q_half,
4152 k_half + (size_t) j * (size_t) aligned_head_dim,
4153 head_dim);
4154 logits[j] = raw_scores[j] * scale;
4155 }
4156
4157 const float max_score = ck_vec_max_f32_contig(logits, kv_tokens);
4158 const double sum = ck_ggml_vec_soft_max_row(kv_tokens, logits, logits, max_score);
4159 const float inv_sum = sum > 0.0 ? (float) (1.0 / sum) : 0.0f;
4160 for (int j = 0; j < kv_tokens; ++j) {
4161 logits[j] *= inv_sum;
4162 prob_half[j] = CK_FP32_TO_FP16(logits[j]);
4163 }
4164 for (int d = 0; d < head_dim; ++d) {
4165 for (int j = 0; j < kv_tokens; ++j) {
4166 v_col_half[j] = v_half[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
4167 }
4168 out_vec[d] = ck_attention_dot_f16_unfused_llama(prob_half, v_col_half, kv_tokens);
4169 }
4170 for (int d = head_dim; d < aligned_head_dim; ++d) {
4171 out_vec[d] = 0.0f;
4172 }
4173 ck_attention_vec_dump_selected_query(raw_scores, logits, out_vec, NULL,
4174 kv_tokens, head_dim,
4175 debug_layer_id, h, i);
4176 }
4177 }
4178 free(k_half);
4179 free(v_half);
4180 return 1;
4181}
static float ck_attention_dot_f16_unfused_llama(const uint16_t *x, const uint16_t *y, int n)

References attention_output_index(), ck_attention_dot_f16_unfused_llama(), ck_attention_vec_dump_selected_query(), CK_FP32_TO_FP16, ck_ggml_vec_soft_max_row(), ck_vec_max_f32_contig(), and qkv_index().

Referenced by attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4()

void attention_forward_mixed_visual_chunk_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,
int  visual_start,
int  visual_tokens 
)

Definition at line 5290 of file attention_kernels.c.

5295{
5297 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5298 aligned_head_dim, kv_stride_tokens, visual_start, visual_tokens,
5299 /*output_token_major=*/0);
5300}
static void attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_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 visual_start, int visual_tokens, int output_token_major)

References attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl().

◆ attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl()

static void attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_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  visual_start,
int  visual_tokens,
int  output_token_major 
)
static

Definition at line 5182 of file attention_kernels.c.

5196{
5197 if (!q || !k || !v || !output) {
5198 return;
5199 }
5200 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
5201 return;
5202 }
5203 if (kv_stride_tokens < num_tokens || head_dim <= 0 || aligned_head_dim <= 0) {
5204 return;
5205 }
5206 if (visual_start < 0 || visual_tokens <= 0 || visual_start >= num_tokens) {
5208 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5209 aligned_head_dim, kv_stride_tokens, /*causal=*/1,
5210 /*round_full_kv_fp16=*/0, output_token_major, 1.0f);
5211 return;
5212 }
5213
5214 int visual_end = visual_start + visual_tokens;
5215 if (visual_end > num_tokens) {
5216 visual_end = num_tokens;
5217 }
5218 if (visual_end <= visual_start) {
5220 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5221 aligned_head_dim, kv_stride_tokens, /*causal=*/1,
5222 /*round_full_kv_fp16=*/0, output_token_major, 1.0f);
5223 return;
5224 }
5225
5226 const int T = num_tokens;
5227 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
5228 const float scale = 1.0f;
5229
5231 const int debug_layer_id = ck_attention_vec_dump_enabled()
5233 : -1;
5234 for (int h = 0; h < num_heads; ++h) {
5235 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
5236 const float *k_head = k + (size_t)kv_head * kv_head_stride;
5237 const float *v_head = v + (size_t)kv_head * kv_head_stride;
5238
5239 for (int i = 0; i < T; ++i) {
5240 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
5241 float *out_vec = output + attention_output_index(
5242 h, i, num_heads, T, aligned_head_dim, output_token_major);
5243 const int in_visual = (i >= visual_start && i < visual_end);
5244 const int kv_tokens = in_visual ? visual_end : (i + 1);
5245 attention_flash_query_causal_exact(q_vec, k_head, v_head,
5246 kv_tokens,
5247 head_dim, aligned_head_dim,
5248 scale, out_vec);
5249 ck_attention_vec_dump_exact_query(q_vec, k_head, out_vec,
5250 kv_tokens,
5251 head_dim, aligned_head_dim,
5252 scale,
5253 debug_layer_id, h, i);
5254 }
5255 }
5256 return;
5257 }
5258
5259#if defined(__AVX512F__)
5260 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx512
5261#elif defined(__AVX2__)
5262 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx2
5263#elif defined(__AVX__)
5264 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx
5265#else
5266 #define FLASH_QUERY_IMPL attention_flash_query_causal
5267#endif
5268
5269 for (int h = 0; h < num_heads; ++h) {
5270 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
5271 const float *k_head = k + (size_t)kv_head * kv_head_stride;
5272 const float *v_head = v + (size_t)kv_head * kv_head_stride;
5273
5274 for (int i = 0; i < T; ++i) {
5275 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
5276 float *out_vec = output + attention_output_index(
5277 h, i, num_heads, T, aligned_head_dim, output_token_major);
5278 const int in_visual = (i >= visual_start && i < visual_end);
5279 const int kv_tokens = in_visual ? visual_end : (i + 1);
5280 FLASH_QUERY_IMPL(q_vec, k_head, v_head,
5281 kv_tokens,
5282 head_dim, aligned_head_dim,
5283 scale, out_vec);
5284 }
5285 }
5286
5287#undef FLASH_QUERY_IMPL
5288}
static void ck_attention_vec_dump_exact_query(const float *q_vec, const float *k_head, const float *out_vec, int kv_tokens, int head_dim, int aligned_head_dim, float scale, int layer_id, int head_id, int query_id)
static void attention_flash_query_causal_exact(const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)

References attention_flash_query_causal_exact(), attention_forward_head_major_gqa_flash_impl(), attention_output_index(), ck_attention_vec_dump_enabled(), ck_attention_vec_dump_exact_query(), ck_attention_vec_dump_next_layer_id(), ck_strict_parity_enabled(), FLASH_QUERY_IMPL, and qkv_index().

Referenced by attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4(), and attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_token_output().

◆ attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_token_output()

void attention_forward_mixed_visual_chunk_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,
int  visual_start,
int  visual_tokens 
)

Definition at line 5302 of file attention_kernels.c.

5307{
5309 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5310 aligned_head_dim, kv_stride_tokens, visual_start, visual_tokens,
5311 /*output_token_major=*/1);
5312}

References attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl().

◆ attention_forward_query_key_head_major_f32()

int attention_forward_query_key_head_major_f32 ( const float *  query,
const float *  key,
const float *  value,
float *  output,
float *  score_scratch,
int  num_heads,
int  query_tokens,
int  key_tokens,
int  head_dim,
float  scale 
)

Definition at line 210 of file attention_kernels.c.

221{
223 query, key, value, output, score_scratch, NULL, num_heads,
224 query_tokens, key_tokens, head_dim, scale);
225}
static int ck_attention_forward_query_key_head_major_f32_run(const float *query, const float *key, const float *value, float *output, float *score_scratch, float *key_transpose_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)

References ck_attention_forward_query_key_head_major_f32_run().

◆ attention_forward_query_key_head_major_f32_decode_heads()

int attention_forward_query_key_head_major_f32_decode_heads ( const float *  query,
const float *  key,
const float *  value,
float *  output,
float *  score_scratch,
int  num_heads,
int  query_tokens,
int  key_tokens,
int  head_dim,
float  scale 
)

Definition at line 260 of file attention_kernels.c.

271{
272 if (query == NULL || key == NULL || value == NULL || output == NULL ||
273 score_scratch == NULL) return -1;
274 if (num_heads <= 0 || query_tokens <= 0 || key_tokens <= 0 ||
275 head_dim <= 0 || !isfinite(scale)) return -2;
276
277 ck_attention_query_key_f32_head_args_t args = {
278 .query = query,
279 .key = key,
280 .value = value,
281 .output = output,
282 .score_scratch = score_scratch,
283 .num_heads = num_heads,
284 .query_tokens = query_tokens,
285 .key_tokens = key_tokens,
286 .head_dim = head_dim,
287 .scale = scale,
288 };
289 ck_threadpool_t *pool = ck_threadpool_global();
290 int active = pool ? ck_threadpool_n_threads(pool) : 1;
291 if (active <= 1) {
293 return 0;
294 }
295 if (active > num_heads) active = num_heads;
296 ck_threadpool_dispatch_n(pool, active,
298 return 0;
299}
static void ck_attention_query_key_f32_head_work(int ith, int nth, void *opaque)

References ck_attention_query_key_f32_head_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

◆ attention_forward_query_key_head_major_f32_packed_k()

int attention_forward_query_key_head_major_f32_packed_k ( const float *  query,
const float *  key,
const float *  value,
float *  output,
float *  score_scratch,
float *  key_transpose_scratch,
int  num_heads,
int  query_tokens,
int  key_tokens,
int  head_dim,
float  scale 
)

Definition at line 301 of file attention_kernels.c.

313{
314 if (key_transpose_scratch == NULL) return -1;
316 query, key, value, output, score_scratch, key_transpose_scratch,
317 num_heads, query_tokens, key_tokens, head_dim, scale);
318}

References ck_attention_forward_query_key_head_major_f32_run().

◆ attention_forward_query_key_head_major_tiled_f16kv_fp32()

int attention_forward_query_key_head_major_tiled_f16kv_fp32 ( const float *  query,
const float *  key,
const float *  value,
float *  output,
int  num_heads,
int  query_tokens,
int  key_tokens,
int  head_dim,
float  scale 
)

Definition at line 3655 of file attention_kernels.c.

3665{
3666 if (!query || !key || !value || !output || num_heads <= 0 ||
3667 query_tokens <= 0 || key_tokens != query_tokens || head_dim <= 0) {
3668 return -1;
3669 }
3670
3671 const float contract_scale = ck_attention_strict_scale_f32(head_dim);
3672 if (scale != contract_scale) {
3673 return -1;
3674 }
3675
3676 const int query_tile_size = query_tokens >= CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS
3680 query, key, value, output,
3681 num_heads, num_heads, query_tokens,
3682 head_dim, head_dim, key_tokens, query_tile_size);
3683 return 0;
3684}

References ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(), ck_attention_strict_scale_f32(), CK_GGML_FA_TILE_Q, CK_GGML_FA_TILE_Q_LARGE, and CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS.

◆ attention_forward_sparse_token_major_gqa_bf16cache_pytorch_cpu_flash_contract()

void attention_forward_sparse_token_major_gqa_bf16cache_pytorch_cpu_flash_contract ( const float *  query,
const uint16_t *  key_cache,
const uint16_t *  value_cache,
const float *  selected_indices,
float *  output,
float *  score_scratch,
int  rows,
int  query_heads,
int  kv_heads,
int  head_dim,
int  selection_width,
int  context_length,
int  position 
)

Definition at line 8966 of file attention_kernels.c.

8980{
8981 (void)score_scratch;
8982 if (!query || !key_cache || !value_cache || !selected_indices || !output ||
8983 rows <= 0 || query_heads <= 0 || kv_heads <= 0 || head_dim <= 0 ||
8984 selection_width <= 0 || context_length <= 0 || position < 0 ||
8985 position + rows > context_length || query_heads % kv_heads != 0) {
8986 fprintf(stderr, "CK sparse BF16 CPU-flash attention: invalid contract\n");
8987 abort();
8988 }
8989
8990#if defined(__AVX512F__)
8991 for (int row = 0; row < rows; ++row) {
8992 const int visible_tokens = position + row + 1;
8993 const ck_attention_status_t status =
8994 ck_attention_decode_bf16_pytorch_cpu_flash_masked(
8995 query + (size_t)row * (size_t)query_heads * (size_t)head_dim,
8996 key_cache, value_cache,
8997 output + (size_t)row * (size_t)query_heads * (size_t)head_dim,
8998 selected_indices + (size_t)row * (size_t)selection_width,
8999 selection_width, query_heads, kv_heads, visible_tokens,
9000 context_length, head_dim, head_dim);
9001 if (status != CK_ATTENTION_STATUS_OK) {
9002 fprintf(stderr,
9003 "CK sparse BF16 CPU-flash attention unavailable (status=%d)\n",
9004 (int)status);
9005 abort();
9006 }
9007 }
9008#else
9009 fprintf(stderr,
9010 "CK sparse BF16 CPU-flash attention requires AVX-512F; "
9011 "no numerically different fallback is permitted\n");
9012 abort();
9013#endif
9014}

References CK_ATTENTION_STATUS_OK.

◆ attention_output_index()

static size_t attention_output_index ( int  h,
int  token,
int  num_heads,
int  num_tokens,
int  aligned_head_dim,
int  token_major 
)
inlinestatic

Definition at line 339 of file attention_kernels.c.

343{
344 if (token_major) {
345 return ((size_t)token * (size_t)num_heads + (size_t)h) *
346 (size_t)aligned_head_dim;
347 }
348 return qkv_index(h, token, 0, num_tokens, aligned_head_dim);
349}

References qkv_index(), and token.

Referenced by attention_forward_head_major_gqa_flash_impl(), attention_forward_head_major_gqa_unfused_f16_strict(), attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl(), and ck_attention_full_grid_work().

◆ attention_query_full_exact_regular()

static void attention_query_full_exact_regular ( const float *  q_vec,
const float *  k_head,
const float *  v_cols,
int  kv_tokens,
int  head_dim,
int  aligned_head_dim,
float  scale,
float *  score_row,
float *  out_vec,
int  layer_id,
int  head_id,
int  query_id 
)
static

Definition at line 2321 of file attention_kernels.c.

2333{
2334 if (kv_tokens <= 0) {
2335 for (int d = 0; d < aligned_head_dim; ++d) {
2336 out_vec[d] = 0.0f;
2337 }
2338 return;
2339 }
2340
2341 for (int j = 0; j < kv_tokens; ++j) {
2342 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
2343 score_row[j] = ck_vec_dot_f32_strict(q_vec, k_vec, head_dim);
2344 }
2345 float *raw_dump = NULL;
2346 if (ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
2347 raw_dump = (float *) alloca((size_t) kv_tokens * sizeof(float));
2348 memcpy(raw_dump, score_row, (size_t) kv_tokens * sizeof(float));
2349 }
2350
2351 float max_score = -INFINITY;
2352 for (int j = 0; j < kv_tokens; ++j) {
2353 const float score = score_row[j] * scale;
2354 score_row[j] = score;
2355 if (score > max_score) {
2356 max_score = score;
2357 }
2358 }
2359
2360 double sum = 0.0;
2361 for (int j = 0; j < kv_tokens; ++j) {
2362 const float w = expf(score_row[j] - max_score);
2363 score_row[j] = w;
2364 volatile double next = sum + (double) w;
2365 sum = next;
2366 }
2367
2368 if (sum > 0.0) {
2369 const float inv_sum = (float) (1.0 / sum);
2370 for (int j = 0; j < kv_tokens; ++j) {
2371 score_row[j] *= inv_sum;
2372 }
2373 for (int d = 0; d < head_dim; ++d) {
2374 const float *v_col = v_cols + (size_t) d * (size_t) kv_tokens;
2375 const float dot = ck_vec_dot_f32x_f32_to_f32_via_f64(score_row, v_col, kv_tokens);
2376 out_vec[d] = dot;
2377 }
2378 } else {
2379 for (int d = 0; d < head_dim; ++d) {
2380 out_vec[d] = 0.0f;
2381 }
2382 }
2383
2384 for (int d = head_dim; d < aligned_head_dim; ++d) {
2385 out_vec[d] = 0.0f;
2386 }
2387 if (raw_dump) {
2388 ck_attention_vec_dump_selected_query(raw_dump, score_row, out_vec, v_cols, kv_tokens, head_dim,
2389 layer_id, head_id, query_id);
2390 }
2391}
static float ck_vec_dot_f32_strict(const float *x, const float *y, int n)
static float ck_vec_dot_f32x_f32_to_f32_via_f64(const float *x, const float *y, int n)

References ck_attention_vec_dump_selected_query(), ck_attention_vec_dump_should_emit(), ck_vec_dot_f32_strict(), ck_vec_dot_f32x_f32_to_f32_via_f64(), and score.

Referenced by attention_forward_full_head_major_gqa_exact_strided().

◆ attention_query_full_ggml_regular()

static void attention_query_full_ggml_regular ( const float *  q_vec,
const float *  k_head,
const float *  v_cols,
int  kv_tokens,
int  head_dim,
int  aligned_head_dim,
float  scale,
float *  score_row,
float *  out_vec,
int  layer_id,
int  head_id,
int  query_id 
)
static

Definition at line 2393 of file attention_kernels.c.

2405{
2406 if (kv_tokens <= 0) {
2407 for (int d = 0; d < aligned_head_dim; ++d) {
2408 out_vec[d] = 0.0f;
2409 }
2410 return;
2411 }
2412
2413 for (int j = 0; j < kv_tokens; ++j) {
2414 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
2415 score_row[j] = ck_ggml_vec_dot_f32_contig(q_vec, k_vec, head_dim);
2416 }
2417 float *raw_dump = NULL;
2418 if (ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
2419 raw_dump = (float *) alloca((size_t) kv_tokens * sizeof(float));
2420 memcpy(raw_dump, score_row, (size_t) kv_tokens * sizeof(float));
2421 }
2422
2423 float *logit_row = (float *) alloca((size_t) kv_tokens * sizeof(float));
2424 memcpy(logit_row, score_row, (size_t) kv_tokens * sizeof(float));
2425 ck_vec_scale_f32_inplace(logit_row, kv_tokens, scale);
2426 const float max_score = ck_vec_max_f32_contig(logit_row, kv_tokens);
2427 const double sum = ck_ggml_vec_soft_max_row(kv_tokens, score_row, logit_row, max_score);
2428 if (sum > 0.0) {
2429 const float inv_sum = (float) (1.0 / sum);
2430 ck_vec_scale_f32_inplace(score_row, kv_tokens, inv_sum);
2431 for (int d = 0; d < head_dim; ++d) {
2432 const float *v_col = v_cols + (size_t) d * (size_t) kv_tokens;
2433 out_vec[d] = ck_ggml_vec_dot_f32_contig(score_row, v_col, kv_tokens);
2434 }
2435 } else {
2436 for (int d = 0; d < head_dim; ++d) {
2437 out_vec[d] = 0.0f;
2438 }
2439 }
2440
2441 for (int d = head_dim; d < aligned_head_dim; ++d) {
2442 out_vec[d] = 0.0f;
2443 }
2444 if (raw_dump) {
2445 ck_attention_vec_dump_selected_query(raw_dump, score_row, out_vec, v_cols, kv_tokens, head_dim,
2446 layer_id, head_id, query_id);
2447 }
2448}

References ck_attention_vec_dump_selected_query(), ck_attention_vec_dump_should_emit(), ck_ggml_vec_dot_f32_contig(), ck_ggml_vec_soft_max_row(), ck_vec_max_f32_contig(), and ck_vec_scale_f32_inplace().

Referenced by attention_forward_full_head_major_gqa_ggml_strided_workspace().

◆ ck_attention_align64_size()

◆ ck_attention_bf16_pytorch_flash_work()

static void ck_attention_bf16_pytorch_flash_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 4932 of file attention_kernels.c.

4933{
4934 ck_attention_bf16_sdpa_args_t *args = (ck_attention_bf16_sdpa_args_t *)opaque;
4936 args->q, args->k, args->v, args->output,
4937 args->num_heads, args->num_kv_heads, args->num_tokens,
4938 args->head_dim, args->aligned_head_dim, args->kv_stride_tokens,
4939 ith, nth, args->output_token_major)) {
4940 __atomic_store_n(&args->failed, 1, __ATOMIC_RELAXED);
4941 }
4942}
static int ck_attention_full_bf16_sdpa_amx_range(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 head_begin, int head_step, int output_token_major)

References ck_attention_full_bf16_sdpa_amx_range().

Referenced by ck_attention_full_bf16_pytorch_flash().

◆ ck_attention_bf16_pytorch_gqa_available()

int ck_attention_bf16_pytorch_gqa_available ( void  )

Definition at line 9025 of file attention_kernels.c.

9026{
9027#if defined(__AVX512F__)
9028 pthread_once(&ck_pytorch_attention_once, ck_bind_pytorch_attention_primitives);
9029 return ck_pytorch_sgemm_batch != NULL &&
9030 ck_pytorch_attention_expf16 != NULL;
9031#else
9032 return 1;
9033#endif
9034}

Referenced by ck_attention_sparse_bf16_pytorch_gqa_available().

◆ ck_attention_bf16_sdpa_work()

static void ck_attention_bf16_sdpa_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 4920 of file attention_kernels.c.

4921{
4922 ck_attention_bf16_sdpa_args_t *args = (ck_attention_bf16_sdpa_args_t *)opaque;
4924 args->q, args->k, args->v, args->output,
4925 args->num_heads, args->num_kv_heads, args->num_tokens,
4926 args->head_dim, args->aligned_head_dim, args->kv_stride_tokens,
4927 ith, nth)) {
4928 __atomic_store_n(&args->failed, 1, __ATOMIC_RELAXED);
4929 }
4930}
static int ck_attention_full_bf16_sdpa_tiled_range(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 head_begin, int head_step)

References ck_attention_full_bf16_sdpa_tiled_range().

Referenced by ck_attention_full_bf16_sdpa_tiled().

◆ ck_attention_causal_f16kv_work()

static void ck_attention_causal_f16kv_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 5328 of file attention_kernels.c.

5329{
5330 const ck_attention_causal_f16kv_args_t *args =
5331 (const ck_attention_causal_f16kv_args_t *)opaque;
5332 const float scale = 1.0f / sqrtf((float)args->head_dim);
5333 const int T = args->num_tokens;
5334 const size_t kv_head_stride =
5335 (size_t)args->kv_stride_tokens * (size_t)args->aligned_head_dim;
5336
5337 for (int h = ith; h < args->num_heads; h += nth) {
5338 const int kv_head = (int)((long long)h * (long long)args->num_kv_heads /
5339 (long long)args->num_heads);
5340 const float *k_head = args->k + (size_t)kv_head * kv_head_stride;
5341 const float *v_head = args->v + (size_t)kv_head * kv_head_stride;
5342
5343 for (int i = 0; i < T; ++i) {
5344 const float *q_vec = args->q +
5345 qkv_index(h, i, 0, T, args->aligned_head_dim);
5346 float *out_vec = args->output +
5347 qkv_index(h, i, 0, T, args->aligned_head_dim);
5348 if (args->inputs_prerounded) {
5350 q_vec, k_head, v_head, /*kv_tokens=*/i + 1,
5351 args->head_dim, args->aligned_head_dim, scale, out_vec);
5352 } else {
5354 q_vec, k_head, v_head, /*kv_tokens=*/i + 1,
5355 args->head_dim, args->aligned_head_dim, scale, out_vec);
5356 }
5357 }
5358 }
5359}
static void attention_flash_query_causal_exact_prerounded_f16kv(const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)

References attention_flash_query_causal_exact_f16kv(), attention_flash_query_causal_exact_prerounded_f16kv(), and qkv_index().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_f16kv_serial(), and attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace().

◆ ck_attention_dot_f16_llama()

static float ck_attention_dot_f16_llama ( const uint16_t *  x,
const uint16_t *  y,
int  n 
)
inlinestatic

Definition at line 6426 of file attention_kernels.c.

6429{
6430 int i = 0;
6431#if defined(__AVX512F__)
6432 // Match ggml's AVX-512 FP16-to-FP32 path: four 16-lane
6433 // accumulators per 64 values, then its fixed pairwise tree.
6434 __m512 sum0 = _mm512_setzero_ps();
6435 __m512 sum1 = _mm512_setzero_ps();
6436 __m512 sum2 = _mm512_setzero_ps();
6437 __m512 sum3 = _mm512_setzero_ps();
6438 const int n64 = n & ~63;
6439 for (; i < n64; i += 64) {
6440 const __m512 x0 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i)));
6441 const __m512 y0 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i)));
6442 const __m512 x1 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i + 16)));
6443 const __m512 y1 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i + 16)));
6444 const __m512 x2 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i + 32)));
6445 const __m512 y2 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i + 32)));
6446 const __m512 x3 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i + 48)));
6447 const __m512 y3 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i + 48)));
6448 sum0 = _mm512_fmadd_ps(x0, y0, sum0);
6449 sum1 = _mm512_fmadd_ps(x1, y1, sum1);
6450 sum2 = _mm512_fmadd_ps(x2, y2, sum2);
6451 sum3 = _mm512_fmadd_ps(x3, y3, sum3);
6452 }
6453 sum0 = _mm512_add_ps(sum0, sum2);
6454 sum1 = _mm512_add_ps(sum1, sum3);
6455 sum0 = _mm512_add_ps(sum0, sum1);
6456 const float vector_result = _mm512_reduce_add_ps(sum0);
6457#elif defined(__AVX2__) && defined(__F16C__)
6458 // Match ggml_vec_dot_f16's AVX reduction contract: four independent
6459 // accumulators per 32 values, followed by its fixed pairwise tree.
6460 __m256 sum0 = _mm256_setzero_ps();
6461 __m256 sum1 = _mm256_setzero_ps();
6462 __m256 sum2 = _mm256_setzero_ps();
6463 __m256 sum3 = _mm256_setzero_ps();
6464 const int n32 = n & ~31;
6465 for (; i < n32; i += 32) {
6466 const __m256 x0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i)));
6467 const __m256 y0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i)));
6468 const __m256 x1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 8)));
6469 const __m256 y1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 8)));
6470 const __m256 x2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 16)));
6471 const __m256 y2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 16)));
6472 const __m256 x3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 24)));
6473 const __m256 y3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 24)));
6474#if defined(__FMA__)
6475 sum0 = _mm256_fmadd_ps(x0, y0, sum0);
6476 sum1 = _mm256_fmadd_ps(x1, y1, sum1);
6477 sum2 = _mm256_fmadd_ps(x2, y2, sum2);
6478 sum3 = _mm256_fmadd_ps(x3, y3, sum3);
6479#else
6480 sum0 = _mm256_add_ps(sum0, _mm256_mul_ps(x0, y0));
6481 sum1 = _mm256_add_ps(sum1, _mm256_mul_ps(x1, y1));
6482 sum2 = _mm256_add_ps(sum2, _mm256_mul_ps(x2, y2));
6483 sum3 = _mm256_add_ps(sum3, _mm256_mul_ps(x3, y3));
6484#endif
6485 }
6486 sum0 = _mm256_add_ps(sum0, sum2);
6487 sum1 = _mm256_add_ps(sum1, sum3);
6488 sum0 = _mm256_add_ps(sum0, sum1);
6489 const __m128 pair = _mm_add_ps(
6490 _mm256_castps256_ps128(sum0),
6491 _mm256_extractf128_ps(sum0, 1));
6492 const __m128 half = _mm_hadd_ps(pair, pair);
6493 const float vector_result = _mm_cvtss_f32(_mm_hadd_ps(half, half));
6494#else
6495 const float vector_result = 0.0f;
6496#endif
6497 /* ggml_vec_dot_f16 stores the SIMD reduction in ggml_float (double) and
6498 * accumulates any scalar tail there. This matters for head dimensions
6499 * below or not divisible by the active ISA step (for example D=32 on
6500 * AVX-512 and padded D=80). */
6501 double result = (double) vector_result;
6502 for (; i < n; ++i) {
6503 const float product = CK_FP16_TO_FP32(x[i]) * CK_FP16_TO_FP32(y[i]);
6504 result += (double) product;
6505 }
6506 return (float) result;
6507}
static int product(size_t a, size_t b, size_t *out)

References CK_FP16_TO_FP32, and product().

Referenced by attention_forward_decode_head_major_gqa_f16cache_regular_noscale(), and ck_attention_f16_split_work().

◆ ck_attention_dot_f16_unfused_llama()

static float ck_attention_dot_f16_unfused_llama ( const uint16_t *  x,
const uint16_t *  y,
int  n 
)
inlinestatic

Definition at line 1179 of file attention_kernels.c.

1182{
1183 int i = 0;
1184#if defined(__AVX2__) && defined(__F16C__)
1185 __m256 sum0 = _mm256_setzero_ps();
1186 __m256 sum1 = _mm256_setzero_ps();
1187 __m256 sum2 = _mm256_setzero_ps();
1188 __m256 sum3 = _mm256_setzero_ps();
1189 const int n32 = n & ~31;
1190 for (; i < n32; i += 32) {
1191 const __m256 x0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i)));
1192 const __m256 y0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i)));
1193 const __m256 x1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 8)));
1194 const __m256 y1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 8)));
1195 const __m256 x2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 16)));
1196 const __m256 y2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 16)));
1197 const __m256 x3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 24)));
1198 const __m256 y3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 24)));
1199#if defined(__FMA__)
1200 sum0 = _mm256_fmadd_ps(x0, y0, sum0);
1201 sum1 = _mm256_fmadd_ps(x1, y1, sum1);
1202 sum2 = _mm256_fmadd_ps(x2, y2, sum2);
1203 sum3 = _mm256_fmadd_ps(x3, y3, sum3);
1204#else
1205 sum0 = _mm256_add_ps(sum0, _mm256_mul_ps(x0, y0));
1206 sum1 = _mm256_add_ps(sum1, _mm256_mul_ps(x1, y1));
1207 sum2 = _mm256_add_ps(sum2, _mm256_mul_ps(x2, y2));
1208 sum3 = _mm256_add_ps(sum3, _mm256_mul_ps(x3, y3));
1209#endif
1210 }
1211 sum0 = _mm256_add_ps(sum0, sum2);
1212 sum1 = _mm256_add_ps(sum1, sum3);
1213 sum0 = _mm256_add_ps(sum0, sum1);
1214 const __m128 pair = _mm_add_ps(
1215 _mm256_castps256_ps128(sum0),
1216 _mm256_extractf128_ps(sum0, 1));
1217 const __m128 half = _mm_hadd_ps(pair, pair);
1218 float result = _mm_cvtss_f32(_mm_hadd_ps(half, half));
1219#else
1220 float result = 0.0f;
1221#endif
1222 for (; i < n; ++i) {
1223 result += CK_FP16_TO_FP32(x[i]) * CK_FP16_TO_FP32(y[i]);
1224 }
1225 return result;
1226}

References CK_FP16_TO_FP32.

Referenced by attention_forward_head_major_gqa_unfused_f16_strict().

◆ ck_attention_f16_prefill_gqa_reuse_work()

static void ck_attention_f16_prefill_gqa_reuse_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 7292 of file attention_kernels.c.

7293{
7294 const ck_attention_f16_prefill_gqa_reuse_args_t *args =
7295 (const ck_attention_f16_prefill_gqa_reuse_args_t *) opaque;
7296 const ck_attention_f16_prefill_qtile64_args_t *base = &args->base;
7297 const int lanes = nth / base->num_kv_heads;
7298 const int kv_group = ith / lanes;
7299 const int lane = ith % lanes;
7300 const int heads_per_group = base->num_heads / base->num_kv_heads;
7301 const int head_begin = kv_group * heads_per_group;
7302 const int query_tiles =
7303 (base->q_tokens + args->query_tile_size - 1) / args->query_tile_size;
7304 const int kv_tokens = base->past_tokens + base->q_tokens;
7305 const float scale = ck_attention_strict_scale_f32(base->head_dim);
7306 const size_t kv_head_stride =
7307 (size_t) base->cache_capacity * (size_t) base->aligned_head_dim;
7308 const uint16_t *k_head =
7309 base->k_cache + (size_t) kv_group * kv_head_stride;
7310 const uint16_t *v_head =
7311 base->v_cache + (size_t) kv_group * kv_head_stride;
7312 float *shared_k = args->shared_k_tiles +
7313 (size_t) kv_group * (size_t) base->head_dim * CK_GGML_FA_TILE_KV;
7314 float *shared_v = args->shared_v_tiles +
7315 (size_t) kv_group * CK_GGML_FA_TILE_KV * (size_t) base->head_dim;
7316 ck_attention_gqa_team_barrier_t *barrier = &args->barriers[kv_group];
7317 const int max_group_jobs =
7318 heads_per_group * args->concurrent_query_tiles;
7319 const int local_capacity = (max_group_jobs + lanes - 1) / lanes;
7320 unsigned char *worker = args->worker_workspace +
7321 (size_t) ith * args->worker_workspace_stride;
7322 size_t cursor = 0;
7323 cursor = ck_attention_align64_size(cursor);
7324 int *local_heads = (int *) (worker + cursor);
7325 cursor += (size_t) local_capacity * sizeof(int);
7326 int *local_iq = (int *) (worker + cursor);
7327 cursor += (size_t) local_capacity * sizeof(int);
7328 int *local_rows = (int *) (worker + cursor);
7329 cursor += (size_t) local_capacity * sizeof(int);
7330 cursor = ck_attention_align64_size(cursor);
7331 float *q_tiles = (float *) (worker + cursor);
7332 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
7333 (size_t) base->head_dim * sizeof(float);
7334 cursor = ck_attention_align64_size(cursor);
7335 float *kq_tiles = (float *) (worker + cursor);
7336 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
7337 CK_GGML_FA_TILE_KV * sizeof(float);
7338 cursor = ck_attention_align64_size(cursor);
7339 float *vkq_tiles = (float *) (worker + cursor);
7340 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
7341 (size_t) base->head_dim * sizeof(float);
7342 cursor = ck_attention_align64_size(cursor);
7343 float *sum_rows = (float *) (worker + cursor);
7344 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
7345 sizeof(float);
7346 cursor = ck_attention_align64_size(cursor);
7347 float *max_rows = (float *) (worker + cursor);
7348
7349 for (int query_tile_begin = 0; query_tile_begin < query_tiles;
7350 query_tile_begin += args->concurrent_query_tiles) {
7351 int batch_tiles = query_tiles - query_tile_begin;
7352 if (batch_tiles > args->concurrent_query_tiles) {
7353 batch_tiles = args->concurrent_query_tiles;
7354 }
7355 const int group_jobs = heads_per_group * batch_tiles;
7356 int local_jobs = 0;
7357
7358 for (int group_job = lane; group_job < group_jobs; group_job += lanes) {
7359 const int local = local_jobs++;
7360 const int group_head = group_job / batch_tiles;
7361 const int batch_tile = group_job % batch_tiles;
7362 const int h = head_begin + group_head;
7363 const int iq =
7364 (query_tile_begin + batch_tile) * args->query_tile_size;
7365 int tile_rows = base->q_tokens - iq;
7366 if (tile_rows > args->query_tile_size) {
7367 tile_rows = args->query_tile_size;
7368 }
7369 local_heads[local] = h;
7370 local_iq[local] = iq;
7371 local_rows[local] = tile_rows;
7372
7373 float *q_tile = q_tiles +
7374 (size_t) local * (size_t) args->query_tile_size *
7375 (size_t) base->head_dim;
7376 float *vkq = vkq_tiles +
7377 (size_t) local * (size_t) args->query_tile_size *
7378 (size_t) base->head_dim;
7379 float *sum_row = sum_rows +
7380 (size_t) local * (size_t) args->query_tile_size;
7381 float *max_row = max_rows +
7382 (size_t) local * (size_t) args->query_tile_size;
7383 memset(q_tile, 0,
7384 (size_t) args->query_tile_size * (size_t) base->head_dim *
7385 sizeof(float));
7386 memset(vkq, 0,
7387 (size_t) args->query_tile_size * (size_t) base->head_dim *
7388 sizeof(float));
7389 for (int tq = 0; tq < args->query_tile_size; ++tq) {
7390 sum_row[tq] = 0.0f;
7391 max_row[tq] = -INFINITY;
7392 }
7393 for (int tq = 0; tq < tile_rows; ++tq) {
7394 const float *q_vec = base->q +
7395 (size_t) h * base->q_head_stride +
7396 (size_t) (iq + tq) * (size_t) base->aligned_head_dim;
7397 memcpy(q_tile + (size_t) tq * (size_t) base->head_dim,
7398 q_vec, (size_t) base->head_dim * sizeof(float));
7399 }
7400 }
7401
7402 int kv_limit = base->past_tokens +
7403 (query_tile_begin + batch_tiles) * args->query_tile_size;
7404 if (kv_limit > kv_tokens) kv_limit = kv_tokens;
7405
7406 for (int ik = 0; ik < kv_limit; ik += CK_GGML_FA_TILE_KV) {
7407 int kv_tile = kv_limit - ik;
7408 if (kv_tile > CK_GGML_FA_TILE_KV) kv_tile = CK_GGML_FA_TILE_KV;
7409 const int packed_elems = CK_GGML_FA_TILE_KV * base->head_dim;
7410 for (int flat = lane; flat < packed_elems; flat += lanes) {
7411 const int tk = flat / base->head_dim;
7412 const int d = flat % base->head_dim;
7413 float k_value = 0.0f;
7414 float v_value = 0.0f;
7415 if (tk < kv_tile) {
7416 const uint16_t *k_vec = k_head +
7417 (size_t) (ik + tk) * (size_t) base->aligned_head_dim;
7418 const uint16_t *v_vec = v_head +
7419 (size_t) (ik + tk) * (size_t) base->aligned_head_dim;
7421 k_vec[d], base->cache_is_bf16);
7423 v_vec[d], base->cache_is_bf16);
7424 }
7425 shared_k[(size_t) d * CK_GGML_FA_TILE_KV + (size_t) tk] =
7426 k_value;
7427 shared_v[(size_t) tk * (size_t) base->head_dim + (size_t) d] =
7428 v_value;
7429 }
7431
7432 for (int local = 0; local < local_jobs; ++local) {
7433 const int iq = local_iq[local];
7434 const int tile_rows = local_rows[local];
7435 float *q_tile = q_tiles +
7436 (size_t) local * (size_t) args->query_tile_size *
7437 (size_t) base->head_dim;
7438 float *kq = kq_tiles +
7439 (size_t) local * (size_t) args->query_tile_size *
7441 float *vkq = vkq_tiles +
7442 (size_t) local * (size_t) args->query_tile_size *
7443 (size_t) base->head_dim;
7444 float *sum_row = sum_rows +
7445 (size_t) local * (size_t) args->query_tile_size;
7446 float *max_row = max_rows +
7447 (size_t) local * (size_t) args->query_tile_size;
7448 memset(kq, 0,
7449 (size_t) args->query_tile_size * CK_GGML_FA_TILE_KV *
7450 sizeof(float));
7452 kq, q_tile, shared_k, args->query_tile_size,
7453 base->head_dim, CK_GGML_FA_TILE_KV);
7455 kq, args->query_tile_size * CK_GGML_FA_TILE_KV, scale);
7456
7457 for (int tq = 0; tq < args->query_tile_size; ++tq) {
7458 float *kq_row = kq + (size_t) tq * CK_GGML_FA_TILE_KV;
7459 const int last_valid_key = base->past_tokens + iq + tq;
7460 for (int tk = 0; tk < CK_GGML_FA_TILE_KV; ++tk) {
7461 const int key = ik + tk;
7462 if (tk >= kv_tile || tq >= tile_rows || key > last_valid_key) {
7463 kq_row[tk] = -INFINITY;
7464 }
7465 }
7466 const float tile_max =
7468 if (tile_max == -INFINITY) {
7469 memset(kq_row, 0,
7470 CK_GGML_FA_TILE_KV * sizeof(float));
7471 continue;
7472 }
7473 const float old_max = max_row[tq];
7474 const float new_max = old_max > tile_max ? old_max : tile_max;
7475 if (new_max > old_max) {
7476 const float ms =
7477 ck_attention_reference_expf(old_max - new_max);
7479 vkq + (size_t) tq * (size_t) base->head_dim,
7480 base->head_dim, ms);
7481 sum_row[tq] *= ms;
7482 }
7483 max_row[tq] = new_max;
7484 sum_row[tq] = (float) (
7485 (double) sum_row[tq] +
7487 CK_GGML_FA_TILE_KV, kq_row, kq_row, new_max));
7488 }
7490 vkq, kq, shared_v, args->query_tile_size,
7491 CK_GGML_FA_TILE_KV, base->head_dim);
7492 }
7494 }
7495
7496 for (int local = 0; local < local_jobs; ++local) {
7497 const int h = local_heads[local];
7498 const int iq = local_iq[local];
7499 const int tile_rows = local_rows[local];
7500 float *vkq = vkq_tiles +
7501 (size_t) local * (size_t) args->query_tile_size *
7502 (size_t) base->head_dim;
7503 float *sum_row = sum_rows +
7504 (size_t) local * (size_t) args->query_tile_size;
7505 for (int tq = 0; tq < tile_rows; ++tq) {
7506 float *out_vec = base->output +
7507 (size_t) h * base->output_head_stride +
7508 (size_t) (iq + tq) * (size_t) base->aligned_head_dim;
7509 const float inv_sum =
7510 sum_row[tq] == 0.0f ? 0.0f : 1.0f / sum_row[tq];
7511 for (int d = 0; d < base->head_dim; ++d) {
7512 out_vec[d] = vkq[
7513 (size_t) tq * (size_t) base->head_dim + (size_t) d] *
7514 inv_sum;
7515 }
7516 for (int d = base->head_dim; d < base->aligned_head_dim; ++d) {
7517 out_vec[d] = 0.0f;
7518 }
7519 }
7520 }
7521 }
7522}
static float ck_attention_u16_cache_to_f32(uint16_t value, int cache_is_bf16)
static void ck_attention_matmul_f32_accum(float *c, const float *a, const float *b, int m, int k, int n)
static void ck_attention_gqa_team_barrier_wait(ck_attention_gqa_team_barrier_t *barrier)

References ck_attention_align64_size(), ck_attention_gqa_team_barrier_wait(), ck_attention_matmul_f32_accum(), ck_attention_reference_expf(), ck_attention_strict_scale_f32(), ck_attention_u16_cache_to_f32(), CK_GGML_FA_TILE_KV, ck_ggml_vec_soft_max_row(), ck_vec_max_f32_contig(), and ck_vec_scale_f32_inplace().

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config().

◆ ck_attention_f16_prefill_gqa_reuse_worker_bytes()

static size_t ck_attention_f16_prefill_gqa_reuse_worker_bytes ( int  num_heads,
int  num_kv_heads,
int  head_dim,
int  workers,
int  query_tile_size,
int  concurrent_query_tiles 
)
static

Definition at line 7026 of file attention_kernels.c.

7033{
7034 if (num_heads <= 0 || num_kv_heads <= 0 ||
7035 num_heads % num_kv_heads != 0 || workers < num_kv_heads ||
7036 workers % num_kv_heads != 0 || head_dim <= 0 ||
7037 query_tile_size <= 0 || concurrent_query_tiles <= 0) {
7038 return 0;
7039 }
7040 const int lanes = workers / num_kv_heads;
7041 const int group_jobs =
7042 (num_heads / num_kv_heads) * concurrent_query_tiles;
7043 const size_t local_capacity =
7044 (size_t) (group_jobs + lanes - 1) / (size_t) lanes;
7045 size_t bytes = 0;
7046 bytes = ck_attention_align64_size(bytes) +
7047 3u * local_capacity * sizeof(int);
7048 bytes = ck_attention_align64_size(bytes) +
7049 local_capacity * (size_t) query_tile_size * (size_t) head_dim *
7050 sizeof(float);
7051 bytes = ck_attention_align64_size(bytes) +
7052 local_capacity * (size_t) query_tile_size * CK_GGML_FA_TILE_KV *
7053 sizeof(float);
7054 bytes = ck_attention_align64_size(bytes) +
7055 local_capacity * (size_t) query_tile_size * (size_t) head_dim *
7056 sizeof(float);
7057 bytes = ck_attention_align64_size(bytes) +
7058 local_capacity * (size_t) query_tile_size * sizeof(float);
7059 bytes = ck_attention_align64_size(bytes) +
7060 local_capacity * (size_t) query_tile_size * sizeof(float);
7061 return ck_attention_align64_size(bytes);
7062}

References ck_attention_align64_size(), and CK_GGML_FA_TILE_KV.

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config(), and attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes().

◆ ck_attention_f16_prefill_qtile64_dispatch()

static ck_attention_status_t ck_attention_f16_prefill_qtile64_dispatch ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  cache_is_bf16,
float  attention_scale,
size_t  q_head_stride,
size_t  output_head_stride,
ck_attention_prefill_schedule_t  schedule 
)
static

Definition at line 7524 of file attention_kernels.c.

7541{
7542 if (schedule < CK_ATTN_PREFILL_SCHEDULE_KV_HEADS ||
7545 }
7546 ck_attention_f16_prefill_qtile64_args_t args = {
7547 .q = q,
7548 .k_cache = k_cache,
7549 .v_cache = v_cache,
7550 .output = output,
7551 .num_heads = num_heads,
7552 .num_kv_heads = num_kv_heads,
7553 .q_tokens = q_tokens,
7554 .past_tokens = past_tokens,
7555 .cache_capacity = cache_capacity,
7556 .head_dim = head_dim,
7557 .aligned_head_dim = aligned_head_dim,
7558 .cache_is_bf16 = cache_is_bf16,
7559 .attention_scale = attention_scale,
7560 .schedule = schedule,
7561 .q_head_stride = q_head_stride,
7562 .output_head_stride = output_head_stride,
7563 };
7564 ck_threadpool_t *pool = ck_threadpool_global();
7565 int active = pool ? ck_threadpool_n_threads(pool) : 1;
7566 const int query_tiles =
7567 (q_tokens + CK_GGML_FA_TILE_Q - 1) / CK_GGML_FA_TILE_Q;
7568 int available_jobs = num_heads;
7569 if (schedule == CK_ATTN_PREFILL_SCHEDULE_KV_HEADS) {
7570 available_jobs = num_kv_heads;
7571 } else if (schedule == CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES ||
7573 available_jobs = num_heads * query_tiles;
7574 }
7575 if (active > available_jobs) active = available_jobs;
7576 if (pool && active > 1 && ck_threadpool_thread_id(pool) <= 0) {
7578 pool, active, ck_attention_f16_prefill_qtile64_work, &args);
7579 } else {
7581 }
7583}
@ CK_ATTN_PREFILL_SCHEDULE_KV_HEADS
@ CK_ATTN_PREFILL_SCHEDULE_KV_GROUP_QUERY_TILES

References ck_attention_f16_prefill_qtile64_work(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTN_PREFILL_SCHEDULE_KV_GROUP_QUERY_TILES, CK_ATTN_PREFILL_SCHEDULE_KV_HEADS, CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES, CK_GGML_FA_TILE_Q, ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_thread_id().

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace(), attention_forward_causal_head_major_gqa_prefill_append_f16cache_qtile64_schedule(), and ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ ck_attention_f16_prefill_qtile64_work()

static void ck_attention_f16_prefill_qtile64_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 7113 of file attention_kernels.c.

7114{
7115 const ck_attention_f16_prefill_qtile64_args_t *args =
7116 (const ck_attention_f16_prefill_qtile64_args_t *) opaque;
7117 const int query_tiles =
7118 (args->q_tokens + CK_GGML_FA_TILE_Q - 1) / CK_GGML_FA_TILE_Q;
7119 const int total_jobs = args->num_heads * query_tiles;
7120 int job_begin = 0;
7121 int job_end = 0;
7122
7123 if (args->schedule == CK_ATTN_PREFILL_SCHEDULE_KV_GROUP_QUERY_TILES &&
7124 nth >= args->num_kv_heads) {
7125 const int kv_group = (ith * args->num_kv_heads) / nth;
7126 const int worker_begin =
7127 (kv_group * nth + args->num_kv_heads - 1) / args->num_kv_heads;
7128 const int worker_end =
7129 ((kv_group + 1) * nth + args->num_kv_heads - 1) /
7130 args->num_kv_heads;
7131 const int lane = ith - worker_begin;
7132 const int lanes = worker_end - worker_begin;
7133 const int head_begin =
7134 (kv_group * args->num_heads + args->num_kv_heads - 1) /
7135 args->num_kv_heads;
7136 const int head_end =
7137 ((kv_group + 1) * args->num_heads + args->num_kv_heads - 1) /
7138 args->num_kv_heads;
7139 const int group_jobs = (head_end - head_begin) * query_tiles;
7140 job_begin = head_begin * query_tiles + (group_jobs * lane) / lanes;
7141 job_end = head_begin * query_tiles + (group_jobs * (lane + 1)) / lanes;
7142 } else if (args->schedule == CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES) {
7143 job_begin = (total_jobs * ith) / nth;
7144 job_end = (total_jobs * (ith + 1)) / nth;
7145 } else {
7146 const int head_begin = (args->num_heads * ith) / nth;
7147 const int head_end = (args->num_heads * (ith + 1)) / nth;
7148 job_begin = head_begin * query_tiles;
7149 job_end = head_end * query_tiles;
7150 }
7151 if (job_begin >= job_end) return;
7152
7153 const int kv_tokens = args->past_tokens + args->q_tokens;
7154 const float scale = args->attention_scale != 0.0f
7155 ? args->attention_scale : ck_attention_strict_scale_f32(args->head_dim);
7156 const size_t kv_head_stride =
7157 (size_t) args->cache_capacity * (size_t) args->aligned_head_dim;
7158
7159 float *q_tile = (float *) alloca(
7160 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
7161 float *k_tile = (float *) alloca(
7162 (size_t) args->head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
7163 float *v_tile = (float *) alloca(
7164 (size_t) CK_GGML_FA_TILE_KV * (size_t) args->head_dim * sizeof(float));
7165 float *kq = (float *) alloca(
7166 (size_t) CK_GGML_FA_TILE_Q * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
7167 float *vkq = (float *) alloca(
7168 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
7169
7170 for (int job = job_begin; job < job_end; ++job) {
7171 const int h = job / query_tiles;
7172 const int iq = (job % query_tiles) * CK_GGML_FA_TILE_Q;
7173 const int kv_head =
7174 (int) ((long long) h * (long long) args->num_kv_heads /
7175 (long long) args->num_heads);
7176 const uint16_t *k_head = args->k_cache + (size_t) kv_head * kv_head_stride;
7177 const uint16_t *v_head = args->v_cache + (size_t) kv_head * kv_head_stride;
7178
7179 const int tile_rows =
7180 (args->q_tokens - iq) < CK_GGML_FA_TILE_Q
7181 ? (args->q_tokens - iq)
7183 float sum_row[CK_GGML_FA_TILE_Q];
7184 float max_row[CK_GGML_FA_TILE_Q];
7185
7186 for (int tq = 0; tq < CK_GGML_FA_TILE_Q; ++tq) {
7187 sum_row[tq] = 0.0f;
7188 max_row[tq] = -INFINITY;
7189 }
7190 memset(q_tile, 0,
7191 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
7192 memset(vkq, 0,
7193 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
7194
7195 for (int tq = 0; tq < tile_rows; ++tq) {
7196 const float *q_vec = args->q +
7197 (size_t) h * args->q_head_stride +
7198 (size_t) (iq + tq) * (size_t) args->aligned_head_dim;
7199 memcpy(q_tile + (size_t) tq * (size_t) args->head_dim,
7200 q_vec,
7201 (size_t) args->head_dim * sizeof(float));
7202 }
7203
7204 for (int ik = 0; ik < kv_tokens; ik += CK_GGML_FA_TILE_KV) {
7205 const int kv_tile =
7206 (kv_tokens - ik) < CK_GGML_FA_TILE_KV
7207 ? (kv_tokens - ik)
7209 memset(k_tile, 0,
7210 (size_t) args->head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
7211 memset(v_tile, 0,
7212 (size_t) CK_GGML_FA_TILE_KV * (size_t) args->head_dim * sizeof(float));
7213 memset(kq, 0,
7214 (size_t) CK_GGML_FA_TILE_Q * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
7215
7216 for (int tk = 0; tk < kv_tile; ++tk) {
7217 const uint16_t *k_vec = k_head +
7218 (size_t) (ik + tk) * (size_t) args->aligned_head_dim;
7219 const uint16_t *v_vec = v_head +
7220 (size_t) (ik + tk) * (size_t) args->aligned_head_dim;
7221 for (int d = 0; d < args->head_dim; ++d) {
7222 k_tile[(size_t) d * (size_t) CK_GGML_FA_TILE_KV + (size_t) tk] =
7223 ck_attention_u16_cache_to_f32(k_vec[d], args->cache_is_bf16);
7224 v_tile[(size_t) tk * (size_t) args->head_dim + (size_t) d] =
7225 ck_attention_u16_cache_to_f32(v_vec[d], args->cache_is_bf16);
7226 }
7227 }
7228
7230 kq, q_tile, k_tile,
7231 CK_GGML_FA_TILE_Q, args->head_dim, CK_GGML_FA_TILE_KV);
7234
7235 for (int tq = 0; tq < CK_GGML_FA_TILE_Q; ++tq) {
7236 float *kq_row = kq +
7237 (size_t) tq * (size_t) CK_GGML_FA_TILE_KV;
7238 const int last_valid_key = args->past_tokens + iq + tq;
7239 for (int tk = 0; tk < CK_GGML_FA_TILE_KV; ++tk) {
7240 const int key = ik + tk;
7241 if (tk >= kv_tile || tq >= tile_rows || key > last_valid_key) {
7242 kq_row[tk] = -INFINITY;
7243 }
7244 }
7245
7246 const float tile_max =
7248 if (tile_max == -INFINITY) {
7249 memset(kq_row, 0,
7250 (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
7251 continue;
7252 }
7253
7254 const float old_max = max_row[tq];
7255 const float new_max = old_max > tile_max ? old_max : tile_max;
7256 if (new_max > old_max) {
7257 const float ms = ck_attention_reference_expf(old_max - new_max);
7259 vkq + (size_t) tq * (size_t) args->head_dim,
7260 args->head_dim, ms);
7261 sum_row[tq] *= ms;
7262 }
7263 max_row[tq] = new_max;
7264 sum_row[tq] = (float) (
7265 (double) sum_row[tq] +
7267 CK_GGML_FA_TILE_KV, kq_row, kq_row, new_max));
7268 }
7269
7271 vkq, kq, v_tile,
7272 CK_GGML_FA_TILE_Q, CK_GGML_FA_TILE_KV, args->head_dim);
7273 }
7274
7275 for (int tq = 0; tq < tile_rows; ++tq) {
7276 float *out_vec = args->output +
7277 (size_t) h * args->output_head_stride +
7278 (size_t) (iq + tq) * (size_t) args->aligned_head_dim;
7279 const float inv_sum =
7280 sum_row[tq] == 0.0f ? 0.0f : 1.0f / sum_row[tq];
7281 for (int d = 0; d < args->head_dim; ++d) {
7282 out_vec[d] =
7283 vkq[(size_t) tq * (size_t) args->head_dim + (size_t) d] * inv_sum;
7284 }
7285 for (int d = args->head_dim; d < args->aligned_head_dim; ++d) {
7286 out_vec[d] = 0.0f;
7287 }
7288 }
7289 }
7290}

References ck_attention_matmul_f32_accum(), ck_attention_reference_expf(), ck_attention_strict_scale_f32(), ck_attention_u16_cache_to_f32(), CK_ATTN_PREFILL_SCHEDULE_KV_GROUP_QUERY_TILES, CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES, CK_GGML_FA_TILE_KV, CK_GGML_FA_TILE_Q, ck_ggml_vec_soft_max_row(), ck_vec_max_f32_contig(), and ck_vec_scale_f32_inplace().

Referenced by attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace(), ck_attention_f16_prefill_qtile64_dispatch(), and ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace().

◆ ck_attention_f16_reduce_expf()

static float ck_attention_f16_reduce_expf ( float  value)
inlinestatic

◆ ck_attention_f16_split_work()

static void ck_attention_f16_split_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 6589 of file attention_kernels.c.

6590{
6591 ck_attention_f16_split_args_t *args = (ck_attention_f16_split_args_t *) opaque;
6592 const int partial_stride = args->aligned_head_dim + 2;
6593 const int total_jobs = args->num_heads * args->scheduled_chunks;
6594 const int chunk_size =
6595 (args->partition_tokens + args->split_chunks - 1) / args->split_chunks;
6596 const size_t head_stride = (size_t) args->cache_capacity * (size_t) args->aligned_head_dim;
6597 const float scale = args->attention_scale;
6598 uint16_t *q_half = (uint16_t *) alloca((size_t) args->aligned_head_dim * sizeof(uint16_t));
6599 uint16_t *acc_half = (uint16_t *) alloca((size_t) args->aligned_head_dim * sizeof(uint16_t));
6600
6601 for (int job = ith; job < total_jobs; job += nth) {
6602 const int h = job / args->scheduled_chunks;
6603 const int chunk = job % args->scheduled_chunks;
6604 const int kv_head = (int) ((long long) h * (long long) args->num_kv_heads /
6605 (long long) args->num_heads);
6606 const int begin = args->kv_start + chunk * chunk_size;
6607 const int end = begin < args->kv_tokens
6608 ? (begin + chunk_size < args->kv_tokens ? begin + chunk_size : args->kv_tokens)
6609 : begin;
6610 const float *q_head = args->q_token + (size_t) h * (size_t) args->aligned_head_dim;
6611 const uint16_t *k_head = args->k_cache + (size_t) kv_head * head_stride;
6612 const uint16_t *v_head = args->v_cache + (size_t) kv_head * head_stride;
6613 float *partial = args->partials + (size_t) job * (size_t) partial_stride;
6614
6615 for (int d = 0; d < args->aligned_head_dim; ++d) {
6616 q_half[d] = CK_FP32_TO_FP16(q_head[d]);
6617 acc_half[d] = CK_FP32_TO_FP16(0.0f);
6618 }
6619
6620 float sum = 0.0f;
6621 float max_score = -INFINITY;
6622 for (int j = begin; j < end; ++j) {
6623 const uint16_t *k_vec = k_head + (size_t) j * (size_t) args->aligned_head_dim;
6624 const uint16_t *v_vec = v_head + (size_t) j * (size_t) args->aligned_head_dim;
6625 const float dot = ck_attention_dot_f16_llama(q_half, k_vec, args->head_dim);
6626 const float score = dot * scale;
6627 const float old_max = max_score;
6628 float max_scale = 1.0f;
6629 float value_scale = 1.0f;
6630
6631 if (score > max_score) {
6632 max_score = score;
6633 max_scale = isfinite(old_max)
6634 ? ck_attention_reference_expf(old_max - max_score)
6635 : 0.0f;
6636 ck_attention_scale_f16_llama(acc_half, max_scale, args->head_dim);
6637 } else {
6638 value_scale = ck_attention_reference_expf(score - max_score);
6639 }
6640
6642 acc_half, v_vec, value_scale, args->head_dim);
6643#if defined(__INTEL_LLVM_COMPILER)
6644 sum = ck_attention_mul_add_rounded_f32(
6645 sum, max_scale, value_scale);
6646#else
6647 sum = fmaf(sum, max_scale, value_scale);
6648#endif
6649 }
6650
6651 partial[0] = max_score;
6652 partial[1] = sum;
6653 for (int d = 0; d < args->head_dim; ++d) {
6654 partial[2 + d] = CK_FP16_TO_FP32(acc_half[d]);
6655 }
6656 for (int d = args->head_dim; d < args->aligned_head_dim; ++d) {
6657 partial[2 + d] = 0.0f;
6658 }
6659 }
6660}
static void ck_attention_mad_f16_llama(uint16_t *y, const uint16_t *x, float scale, int n)
static void ck_attention_scale_f16_llama(uint16_t *y, float scale, int n)
uint32_t end
Definition utf8.c:215

References ck_attention_dot_f16_llama(), ck_attention_mad_f16_llama(), ck_attention_reference_expf(), ck_attention_scale_f16_llama(), CK_FP16_TO_FP32, CK_FP32_TO_FP16, end, and score.

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned().

◆ ck_attention_flash_query_auto()

static void ck_attention_flash_query_auto ( const float *  q_vec,
const float *  k_head,
const float *  v_head,
int  kv_tokens,
int  head_dim,
int  aligned_head_dim,
float  scale,
float *  out_vec 
)
inlinestatic

Definition at line 3715 of file attention_kernels.c.

3723{
3724#if defined(__AVX512F__)
3725 attention_flash_query_causal_avx512(q_vec, k_head, v_head,
3726 kv_tokens, head_dim, aligned_head_dim,
3727 scale, out_vec);
3728#elif defined(__AVX2__)
3729 attention_flash_query_causal_avx2(q_vec, k_head, v_head,
3730 kv_tokens, head_dim, aligned_head_dim,
3731 scale, out_vec);
3732#elif defined(__AVX__)
3733 attention_flash_query_causal_avx(q_vec, k_head, v_head,
3734 kv_tokens, head_dim, aligned_head_dim,
3735 scale, out_vec);
3736#else
3737 attention_flash_query_causal(q_vec, k_head, v_head,
3738 kv_tokens, head_dim, aligned_head_dim,
3739 scale, out_vec);
3740#endif
3741}
static void attention_flash_query_causal(const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)

References attention_flash_query_causal().

Referenced by ck_attention_full_grid_work().

◆ ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace()

static ck_attention_status_t ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes,
const int *  segment_lengths,
int  num_segments,
ck_attention_prefill_schedule_t  schedule 
)
static

Definition at line 8017 of file attention_kernels.c.

8035{
8036 if (!q || !k_cache || !v_cache || !output || !segment_lengths ||
8037 num_segments <= 0 || num_heads <= 0 || num_kv_heads <= 0 ||
8038 q_tokens <= 0 || past_tokens < 0 || past_tokens + q_tokens > cache_capacity ||
8039 head_dim <= 0 || aligned_head_dim < head_dim) {
8041 }
8042 int planned_rows = 0;
8043 for (int s = 0; s < num_segments; ++s) {
8044 if (segment_lengths[s] < 0 || segment_lengths[s] > q_tokens - planned_rows) {
8046 }
8047 planned_rows += segment_lengths[s];
8048 }
8049 if (planned_rows != q_tokens) return CK_ATTENTION_STATUS_INVALID_ARGUMENT;
8050
8051 const size_t head_stride = (size_t) q_tokens * (size_t) aligned_head_dim;
8052 const size_t token_elems = (size_t) num_heads * (size_t) aligned_head_dim;
8053 if (!token_workspace || token_workspace_bytes < 2 * token_elems * sizeof(float)) {
8055 }
8056
8057 int row_offset = 0;
8058 for (int s = 0; s < num_segments; ++s) {
8059 const int rows = segment_lengths[s];
8060 if (rows == 0) continue;
8062 rows >= CK_GGML_FA_TILE_Q) {
8063 ck_attention_f16_prefill_qtile64_args_t args = {
8064 .q = q + (size_t) row_offset * (size_t) aligned_head_dim,
8065 .k_cache = k_cache,
8066 .v_cache = v_cache,
8067 .output = output + (size_t) row_offset * (size_t) aligned_head_dim,
8068 .num_heads = num_heads,
8069 .num_kv_heads = num_kv_heads,
8070 .q_tokens = rows,
8071 .past_tokens = past_tokens + row_offset,
8072 .cache_capacity = cache_capacity,
8073 .head_dim = head_dim,
8074 .aligned_head_dim = aligned_head_dim,
8075 .cache_is_bf16 = 0,
8076 .schedule = schedule,
8077 .q_head_stride = head_stride,
8078 .output_head_stride = head_stride,
8079 };
8080 ck_threadpool_t *pool = ck_threadpool_global();
8081 int active = pool ? ck_threadpool_n_threads(pool) : 1;
8082 const int query_tiles =
8083 (rows + CK_GGML_FA_TILE_Q - 1) / CK_GGML_FA_TILE_Q;
8084 const int available_jobs =
8086 ? num_kv_heads
8087 : num_heads * query_tiles;
8088 if (active > available_jobs) active = available_jobs;
8089 if (pool && active > 1 && ck_threadpool_thread_id(pool) <= 0) {
8091 pool, active, ck_attention_f16_prefill_qtile64_work, &args);
8092 } else {
8094 }
8095 } else {
8096 float *q_token = token_workspace;
8097 float *out_token = token_workspace + token_elems;
8098 ck_attention_reduction_t selected = reduction;
8101 }
8102 for (int t = 0; t < rows; ++t) {
8103 for (int h = 0; h < num_heads; ++h) {
8104 memcpy(
8105 q_token + (size_t) h * (size_t) aligned_head_dim,
8106 q + (size_t) h * head_stride +
8107 (size_t) (row_offset + t) * (size_t) aligned_head_dim,
8108 (size_t) aligned_head_dim * sizeof(float));
8109 }
8110 ck_attention_status_t status =
8112 q_token, k_cache, v_cache, out_token,
8113 num_heads, num_kv_heads, past_tokens + row_offset + t + 1,
8114 cache_capacity, head_dim, aligned_head_dim, selected);
8115 if (status != CK_ATTENTION_STATUS_OK) return status;
8116 for (int h = 0; h < num_heads; ++h) {
8117 memcpy(
8118 output + (size_t) h * head_stride +
8119 (size_t) (row_offset + t) * (size_t) aligned_head_dim,
8120 out_token + (size_t) h * (size_t) aligned_head_dim,
8121 (size_t) aligned_head_dim * sizeof(float));
8122 }
8123 }
8124 }
8125 row_offset += rows;
8126 }
8128}
ck_attention_reduction_t

References attention_forward_decode_head_major_gqa_flash_f16cache_contract(), ck_attention_f16_prefill_qtile64_work(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTN_PREFILL_SCHEDULE_KV_HEADS, CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64, CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE, CK_GGML_FA_TILE_Q, ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_thread_id().

Referenced by attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_contract_workspace().

◆ ck_attention_forward_decode_f16cache_gemma4()

static ck_attention_status_t ck_attention_forward_decode_f16cache_gemma4 ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  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,
ck_attention_reduction_t  reduction 
)
static

Definition at line 6806 of file attention_kernels.c.

6819{
6820 if (!q_token || !k_cache || !v_cache || !out_token ||
6821 num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 ||
6822 cache_capacity <= 0 || kv_tokens > cache_capacity ||
6823 head_dim <= 0 || aligned_head_dim < head_dim || sliding_window < 0) {
6825 }
6826 if (reduction == CK_ATTN_REDUCTION_F16_REGULAR_NOSCALE) {
6828 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
6829 kv_tokens, cache_capacity, head_dim, aligned_head_dim, sliding_window);
6830 }
6833 }
6834 const int kv_start = sliding_window > 0 && kv_tokens > sliding_window
6835 ? kv_tokens - sliding_window : 0;
6836 const int live_tokens = kv_tokens - kv_start;
6838 q_token, k_cache, v_cache, out_token,
6839 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6840 head_dim, aligned_head_dim, 1, live_tokens, kv_start, 1.0f);
6842}
ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_regular_noscale(const float *q_token, const uint16_t *k_cache, const uint16_t *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)
@ CK_ATTN_REDUCTION_F16_REGULAR_NOSCALE

References attention_forward_decode_head_major_gqa_f16cache_regular_noscale(), attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE, and CK_ATTN_REDUCTION_F16_REGULAR_NOSCALE.

Referenced by attention_forward_decode_head_major_gqa_f16cache_gemma4_contract(), attention_forward_decode_head_major_gqa_f16cache_sliding_gemma4_contract(), and ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided()

static void ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_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,
int  query_tile_size 
)
static

Definition at line 3560 of file attention_kernels.c.

3572{
3573 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
3574 num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim ||
3575 kv_stride_tokens < num_tokens || num_heads % num_kv_heads != 0) {
3576 return;
3577 }
3578
3579 ck_attention_full_tiled_f16kv_fp32_args_t args = {
3580 .q = q,
3581 .k = k,
3582 .v = v,
3583 .output = output,
3584 .num_heads = num_heads,
3585 .num_kv_heads = num_kv_heads,
3586 .num_tokens = num_tokens,
3587 .head_dim = head_dim,
3588 .aligned_head_dim = aligned_head_dim,
3589 .kv_stride_tokens = kv_stride_tokens,
3590 .query_tile_size = query_tile_size,
3591 };
3592 ck_threadpool_t *pool = ck_threadpool_global();
3593 const int active = pool ? ck_threadpool_n_threads(pool) : 1;
3594 if (pool && active > 1) {
3596 } else {
3598 }
3599}
static void ck_attention_full_tiled_f16kv_fp32_work(int ith, int nth, void *opaque)

References ck_attention_full_tiled_f16kv_fp32_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by attention_forward_full_head_major_gqa_tiled336_f16kv_fp32_strided(), attention_forward_full_head_major_gqa_tiled64_f16kv_fp32_strided(), attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(), and attention_forward_query_key_head_major_tiled_f16kv_fp32().

◆ ck_attention_forward_query_key_head_major_f32_run()

static int ck_attention_forward_query_key_head_major_f32_run ( const float *  query,
const float *  key,
const float *  value,
float *  output,
float *  score_scratch,
float *  key_transpose_scratch,
int  num_heads,
int  query_tokens,
int  key_tokens,
int  head_dim,
float  scale 
)
static

Definition at line 153 of file attention_kernels.c.

165{
166 if (query == NULL || key == NULL || value == NULL || output == NULL ||
167 score_scratch == NULL) {
168 return -1;
169 }
170 if (num_heads <= 0 || query_tokens <= 0 || key_tokens <= 0 ||
171 head_dim <= 0 || !isfinite(scale)) {
172 return -2;
173 }
174 ck_attention_query_key_f32_args_t args = {
175 .query = query,
176 .key = key,
177 .value = value,
178 .output = output,
179 .score_scratch = score_scratch,
180 .key_transpose_scratch = key_transpose_scratch,
181 .num_heads = num_heads,
182 .query_tokens = query_tokens,
183 .key_tokens = key_tokens,
184 .head_dim = head_dim,
185 .scale = scale,
186 };
187 ck_threadpool_t *pool = ck_threadpool_global();
188 int active = pool ? ck_threadpool_n_threads(pool) : 1;
189 if (key_transpose_scratch != NULL) {
190 int transpose_active = active;
191 const int transpose_rows = num_heads * head_dim;
192 if (transpose_active > transpose_rows) transpose_active = transpose_rows;
193 if (pool && transpose_active > 1) {
194 ck_threadpool_dispatch_n(pool, transpose_active,
196 } else {
198 }
199 }
200 if (active > query_tokens) active = query_tokens;
201 if (pool && active > 1) {
203 pool, active, ck_attention_query_key_f32_work, &args);
204 } else {
206 }
207 return 0;
208}
static void ck_attention_query_key_f32_transpose_work(int ith, int nth, void *opaque)
static void ck_attention_query_key_f32_work(int ith, int nth, void *opaque)

References ck_attention_query_key_f32_transpose_work(), ck_attention_query_key_f32_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by attention_forward_query_key_head_major_f32(), attention_forward_query_key_head_major_f32_packed_k(), and ck_attention_query_key_f32_head_work().

◆ ck_attention_full_bf16_pytorch_flash()

static int ck_attention_full_bf16_pytorch_flash ( 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  output_token_major 
)
static

Definition at line 4944 of file attention_kernels.c.

4949{
4950 ck_attention_bf16_sdpa_args_t args = {
4951 .q=q, .k=k, .v=v, .output=output,
4952 .num_heads=num_heads, .num_kv_heads=num_kv_heads,
4953 .num_tokens=num_tokens, .head_dim=head_dim,
4954 .aligned_head_dim=aligned_head_dim, .kv_stride_tokens=kv_stride_tokens,
4955 .output_token_major=output_token_major,
4956 .failed=0
4957 };
4958 ck_threadpool_t *pool = ck_threadpool_global();
4959 int active = pool ? ck_threadpool_n_threads(pool) : 1;
4960 if (active > num_heads) active = num_heads;
4961 if (pool && active > 1) {
4963 pool, active, ck_attention_bf16_pytorch_flash_work, &args);
4964 } else {
4966 }
4967 return __atomic_load_n(&args.failed, __ATOMIC_RELAXED) == 0;
4968}
static void ck_attention_bf16_pytorch_flash_work(int ith, int nth, void *opaque)

References ck_attention_bf16_pytorch_flash_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage(), and attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage_token_output().

◆ ck_attention_full_bf16_sdpa_amx_range()

static int ck_attention_full_bf16_sdpa_amx_range ( 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  head_begin,
int  head_step,
int  output_token_major 
)
static

Definition at line 4690 of file attention_kernels.c.

4695{
4696#if defined(__AVX512F__)
4697 /*
4698 * This is a schedule contract, not merely an AMX acceleration of the
4699 * portable kernel. PyTorch CPU flash attention composes FP64 scale
4700 * evaluation, oneDNN-style BF16 BRGEMMs, AVX-512 exp/reductions, BF16
4701 * probability storage, and a second BRGEMM. When parity drifts, compare
4702 * this complete sequence with the PyTorch and oneDNN sources before
4703 * changing an isolated primitive or tolerance.
4704 */
4705 enum { Q_BLOCK = 256, KV_BLOCK = 512, K_PAD = 72, D_PAD = 80 };
4706 if (!ck_gemm_bf16_amx_available() || head_dim != 72 || aligned_head_dim != 72 ||
4707 (num_tokens % 16) != 0 || (kv_stride_tokens < num_tokens) ||
4708 num_heads % num_kv_heads != 0) return 0;
4709 uint16_t *q_block = malloc((size_t)Q_BLOCK * K_PAD * sizeof(uint16_t));
4710 uint16_t *k_packed = malloc((size_t)num_tokens * K_PAD * sizeof(uint16_t));
4711 uint16_t *probabilities = malloc((size_t)Q_BLOCK * KV_BLOCK * sizeof(uint16_t));
4712 uint16_t *v_packed = malloc((size_t)num_tokens * D_PAD * sizeof(uint16_t));
4713 float *scores = malloc((size_t)Q_BLOCK * KV_BLOCK * sizeof(float));
4714 float *destination = malloc((size_t)Q_BLOCK * D_PAD * sizeof(float));
4715 float *row_max = malloc((size_t)Q_BLOCK * sizeof(float));
4716 float *row_sum = malloc((size_t)Q_BLOCK * sizeof(float));
4717 if (!q_block || !k_packed || !probabilities || !v_packed || !scores ||
4718 !destination || !row_max || !row_sum) {
4719 free(q_block); free(k_packed); free(probabilities); free(v_packed);
4720 free(scores); free(destination); free(row_max); free(row_sum);
4721 return 0;
4722 }
4723 const float scale = ck_attention_pytorch_sdpa_scale_f32(head_dim);
4724 const size_t q_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
4725 const size_t kv_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
4726 for (int h = head_begin; h < num_heads; h += head_step) {
4727 const int kv_head = (int)((long long)h * num_kv_heads / num_heads);
4728 const float *qh = q + (size_t)h * q_stride;
4729 const float *kh = k + (size_t)kv_head * kv_stride;
4730 const float *vh = v + (size_t)kv_head * kv_stride;
4731 /*
4732 * K and V are invariant across all query blocks for this head. Pack
4733 * each 512-key tile once, retaining the exact block-local layouts
4734 * consumed by the two certified BRGEMMs below.
4735 */
4736 for (int n = 0; n < num_tokens; n += KV_BLOCK) {
4737 const int key_count = num_tokens - n < KV_BLOCK ? num_tokens - n : KV_BLOCK;
4738 uint16_t *k_block = k_packed + (size_t)n * K_PAD;
4739 uint16_t *v_block = v_packed + (size_t)n * D_PAD;
4740 memset(k_block, 0, (size_t)key_count * K_PAD * sizeof(uint16_t));
4741 memset(v_block, 0, (size_t)D_PAD * key_count * sizeof(uint16_t));
4742 for (int key = 0; key < key_count; ++key) {
4743 for (int d = 0; d < head_dim; ++d) {
4744 k_block[(size_t)key * K_PAD + d] =
4745 float_to_bf16(kh[(size_t)(n + key) * aligned_head_dim + d]);
4746 v_block[(size_t)d * key_count + key] =
4747 float_to_bf16(vh[(size_t)(n + key) * aligned_head_dim + d]);
4748 }
4749 }
4750 }
4751 for (int m = 0; m < num_tokens; m += Q_BLOCK) {
4752 const int query_count = num_tokens - m < Q_BLOCK ? num_tokens - m : Q_BLOCK;
4753 memset(q_block, 0, (size_t)query_count * K_PAD * sizeof(uint16_t));
4754 memset(destination, 0, (size_t)query_count * D_PAD * sizeof(float));
4755 for (int row = 0; row < query_count; ++row) {
4756 for (int d = 0; d < head_dim; ++d) {
4757 q_block[(size_t)row * K_PAD + d] =
4758 float_to_bf16(qh[(size_t)(m + row) * aligned_head_dim + d]);
4759 }
4760 row_max[row] = -INFINITY;
4761 row_sum[row] = 0.0f;
4762 }
4763 for (int n = 0; n < num_tokens; n += KV_BLOCK) {
4764 const int key_count = num_tokens - n < KV_BLOCK ? num_tokens - n : KV_BLOCK;
4765 const uint16_t *k_block = k_packed + (size_t)n * K_PAD;
4766 const uint16_t *v_block = v_packed + (size_t)n * D_PAD;
4768 q_block, k_block, scores,
4769 query_count, key_count, K_PAD, 0)) goto fail;
4770 for (int row = 0; row < query_count; ++row) {
4771 float *score_row = scores + (size_t)row * key_count;
4772 uint16_t *prob_row = probabilities + (size_t)row * key_count;
4773 const float block_max = ck_bf16_sdpa_scale_max_avx512(
4774 score_row, key_count, scale);
4775 const float merged_max = row_max[row] > block_max
4776 ? row_max[row] : block_max;
4777 const float old_scale = isfinite(row_max[row])
4778 ? expf(row_max[row] - merged_max) : 0.0f;
4779 const float block_sum = ck_bf16_sdpa_exp_sum_avx512(
4780 score_row, prob_row, key_count, merged_max);
4781 row_sum[row] = block_sum + old_scale * row_sum[row];
4782 row_max[row] = merged_max;
4783 if (n > 0) {
4784 __m512 scale_v = _mm512_set1_ps(old_scale);
4785 int d = 0;
4786 for (; d + 16 <= D_PAD; d += 16) {
4787 float *dst = destination + (size_t)row * D_PAD + d;
4788 _mm512_storeu_ps(dst, _mm512_mul_ps(_mm512_loadu_ps(dst), scale_v));
4789 }
4790 }
4791 }
4793 probabilities, v_block, destination,
4794 query_count, D_PAD, key_count, n > 0)) goto fail;
4795 }
4796 for (int row = 0; row < query_count; ++row) {
4797 const float reciprocal = row_sum[row] == 0.0f ? 1.0f : 1.0f / row_sum[row];
4798 float *out_row = output + (
4799 output_token_major
4800 ? ((size_t)(m + row) * (size_t)num_heads + (size_t)h)
4801 * (size_t)aligned_head_dim
4802 : ((size_t)h * (size_t)num_tokens + (size_t)(m + row))
4803 * (size_t)aligned_head_dim);
4804 for (int d = 0; d < head_dim; ++d) {
4805 out_row[d] = bf16_to_float(
4806 float_to_bf16(destination[(size_t)row * D_PAD + d] * reciprocal));
4807 }
4808 }
4809 }
4810 }
4811 free(q_block); free(k_packed); free(probabilities); free(v_packed);
4812 free(scores); free(destination); free(row_max); free(row_sum);
4813 return 1;
4814fail:
4815 free(q_block); free(k_packed); free(probabilities); free(v_packed);
4816 free(scores); free(destination); free(row_max); free(row_sum);
4817 return 0;
4818#else
4819 (void)q; (void)k; (void)v; (void)output; (void)num_heads;
4820 (void)num_kv_heads; (void)num_tokens; (void)head_dim;
4821 (void)aligned_head_dim; (void)kv_stride_tokens; (void)head_begin; (void)head_step;
4822 (void)output_token_major;
4823 return 0;
4824#endif
4825}
float ck_attention_pytorch_sdpa_scale_f32(int head_dim)
int ck_gemm_bf16_amx_available(void)
int ck_gemm_bf16_fp32out_amx_raw(const uint16_t *A, const uint16_t *B, float *C, int M, int N, int K, int accumulate)

References bf16_to_float(), ck_attention_pytorch_sdpa_scale_f32(), ck_gemm_bf16_amx_available(), ck_gemm_bf16_fp32out_amx_raw(), and float_to_bf16().

Referenced by ck_attention_bf16_pytorch_flash_work().

◆ ck_attention_full_bf16_sdpa_tiled()

static int ck_attention_full_bf16_sdpa_tiled ( 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 
)
static

Definition at line 4970 of file attention_kernels.c.

4974{
4975 ck_attention_bf16_sdpa_args_t args = {
4976 .q=q, .k=k, .v=v, .output=output,
4977 .num_heads=num_heads, .num_kv_heads=num_kv_heads,
4978 .num_tokens=num_tokens, .head_dim=head_dim,
4979 .aligned_head_dim=aligned_head_dim, .kv_stride_tokens=kv_stride_tokens,
4980 .output_token_major=0,
4981 .failed=0
4982 };
4983 ck_threadpool_t *pool = ck_threadpool_global();
4984 int active = pool ? ck_threadpool_n_threads(pool) : 1;
4985 if (active > num_heads) active = num_heads;
4986 if (pool && active > 1) {
4988 } else {
4989 ck_attention_bf16_sdpa_work(0, 1, &args);
4990 }
4991 return __atomic_load_n(&args.failed, __ATOMIC_RELAXED) == 0;
4992}
static void ck_attention_bf16_sdpa_work(int ith, int nth, void *opaque)

References ck_attention_bf16_sdpa_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by attention_forward_full_head_major_gqa_sdpa_bf16_storage().

◆ ck_attention_full_bf16_sdpa_tiled_range()

static int ck_attention_full_bf16_sdpa_tiled_range ( 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  head_begin,
int  head_step 
)
static

Definition at line 4827 of file attention_kernels.c.

4832{
4833 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
4834 head_dim <= 0 || num_tokens <= 0 || aligned_head_dim < head_dim ||
4835 kv_stride_tokens < num_tokens || num_heads % num_kv_heads != 0) return 0;
4836 if ((size_t)num_tokens > SIZE_MAX / (size_t)head_dim) return 0;
4837 const size_t v_col_count = (size_t)head_dim * (size_t)num_tokens;
4838 if (v_col_count > SIZE_MAX / sizeof(float)) return 0;
4839 if ((size_t)num_tokens > SIZE_MAX / (size_t)aligned_head_dim) return 0;
4840 if ((size_t)kv_stride_tokens > SIZE_MAX / (size_t)aligned_head_dim) return 0;
4841 const float scale = ck_attention_pytorch_sdpa_scale_f32(head_dim);
4842 const size_t q_head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
4843 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
4844 if ((size_t)num_heads > SIZE_MAX / q_head_stride) return 0;
4845 if ((size_t)num_kv_heads > SIZE_MAX / kv_head_stride) return 0;
4846 float scores[512];
4847 float probs[512];
4848 float *v_cols = (float *)malloc(v_col_count * sizeof(float));
4849 if (!v_cols) return 0;
4850 for (int h = head_begin; h < num_heads; h += head_step) {
4851 const int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
4852 const float *qh = q + (size_t)h * q_head_stride;
4853 const float *kh = k + (size_t)kv_head * kv_head_stride;
4854 const float *vh = v + (size_t)kv_head * kv_head_stride;
4855 float *oh = output + (size_t)h * q_head_stride;
4856 for (int d = 0; d < head_dim; ++d) {
4857 float *col = v_cols + (size_t)d * (size_t)num_tokens;
4858 for (int t = 0; t < num_tokens; ++t) {
4859 col[t] = vh[(size_t)t * (size_t)aligned_head_dim + (size_t)d];
4860 }
4861 }
4862 for (int row = 0; row < num_tokens; ++row) {
4863 const float *qrow = qh + (size_t)row * (size_t)aligned_head_dim;
4864 float *dst = oh + (size_t)row * (size_t)aligned_head_dim;
4865 for (int d = 0; d < head_dim; ++d) dst[d] = 0.0f;
4866 float running_max = -INFINITY;
4867 float running_sum = 0.0f;
4868 for (int n = 0; n < num_tokens; n += 512) {
4869 const int block = num_tokens - n < 512 ? num_tokens - n : 512;
4870 float block_max = -INFINITY;
4871 for (int j = 0; j < block; ++j) {
4872 scores[j] = ck_bf16_dot_contract(
4873 qrow,
4874 kh + (size_t)(n + j) * (size_t)aligned_head_dim,
4875 head_dim) * scale;
4876 if (scores[j] > block_max) block_max = scores[j];
4877 }
4878 const float merged_max = running_max > block_max ? running_max : block_max;
4879 const float old_scale = isfinite(running_max) ? expf(running_max - merged_max) : 0.0f;
4880 float block_sum = 0.0f;
4881 for (int j = 0; j < block; ++j) {
4882 const float p = expf(scores[j] - merged_max);
4883 block_sum += p;
4884 probs[j] = bf16_to_float(float_to_bf16(p));
4885 }
4886 for (int d = 0; d < head_dim; ++d) {
4887 const float partial = ck_bf16_dot_contract(
4888 probs,
4889 v_cols + (size_t)d * (size_t)num_tokens + (size_t)n,
4890 block);
4891 dst[d] = dst[d] * old_scale + partial;
4892 }
4893 running_sum = running_sum * old_scale + block_sum;
4894 running_max = merged_max;
4895 }
4896 const float inv = running_sum > 0.0f ? 1.0f / running_sum : 0.0f;
4897 for (int d = 0; d < head_dim; ++d) dst[d] *= inv;
4898 for (int d = head_dim; d < aligned_head_dim; ++d) dst[d] = 0.0f;
4899 }
4900 }
4901 free(v_cols);
4902 return 1;
4903}
static float ck_bf16_dot_contract(const float *a, const float *b, int count)

References bf16_to_float(), ck_attention_pytorch_sdpa_scale_f32(), ck_bf16_dot_contract(), and float_to_bf16().

Referenced by ck_attention_bf16_sdpa_work().

◆ ck_attention_full_grid_work()

static void ck_attention_full_grid_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 4033 of file attention_kernels.c.

4034{
4035 ck_attention_parallel_args_t *args = (ck_attention_parallel_args_t *) opaque;
4036 const int T = args->num_tokens;
4037 const int total = args->num_heads * T;
4038 const size_t kv_head_stride = (size_t) args->kv_stride_tokens * (size_t) args->aligned_head_dim;
4039
4040 for (int idx = ith; idx < total; idx += nth) {
4041 const int h = idx / T;
4042 const int i = idx - h * T;
4043 const int kv_head = (int) ((long long) h * (long long) args->num_kv_heads / (long long) args->num_heads);
4044 const float *k_head = args->k + (size_t) kv_head * kv_head_stride;
4045 const float *v_head = args->v + (size_t) kv_head * kv_head_stride;
4046 const float *q_vec = args->q + qkv_index(h, i, 0, T, args->aligned_head_dim);
4047 float *out_vec = args->output + attention_output_index(
4048 h, i, args->num_heads, T, args->aligned_head_dim,
4049 args->output_token_major);
4050 const int kv_tokens = args->causal ? (i + 1) : T;
4051 ck_attention_flash_query_auto(q_vec, k_head, v_head,
4052 kv_tokens,
4053 args->head_dim,
4054 args->aligned_head_dim,
4055 args->scale,
4056 out_vec);
4057 }
4058}
static void ck_attention_flash_query_auto(const float *q_vec, const float *k_head, const float *v_head, int kv_tokens, int head_dim, int aligned_head_dim, float scale, float *out_vec)

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

Referenced by attention_forward_head_major_gqa_flash_impl().

◆ ck_attention_full_tiled_f16kv_fp32_range()

static void ck_attention_full_tiled_f16kv_fp32_range ( 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  query_tile_size,
int  ith,
int  nth 
)
static

Definition at line 3388 of file attention_kernels.c.

3402{
3403 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
3404 num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim ||
3405 kv_stride_tokens < num_tokens || num_heads % num_kv_heads != 0 ||
3406 query_tile_size <= 0) {
3407 return;
3408 }
3409
3410 const float scale = ck_attention_strict_scale_f32(head_dim);
3411 const int T = num_tokens;
3412 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
3413
3414 float *q_tile = (float *) alloca((size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3415 float *k_tile = (float *) alloca((size_t) head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3416 float *v_tile = (float *) alloca((size_t) CK_GGML_FA_TILE_KV * (size_t) head_dim * sizeof(float));
3417 float *kq = (float *) alloca((size_t) query_tile_size * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3418 float *vkq = (float *) alloca((size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3419 float *sum_row = (float *) alloca((size_t) query_tile_size * sizeof(float));
3420 float *max_row = (float *) alloca((size_t) query_tile_size * sizeof(float));
3421
3422 const int total_rows = num_heads * T;
3423 const int rows_per_worker = (total_rows + nth - 1) / nth;
3424 int ir = rows_per_worker * ith;
3425 const int ir1 = (ir + rows_per_worker) < total_rows
3426 ? (ir + rows_per_worker)
3427 : total_rows;
3428
3429 while (ir < ir1) {
3430 const int h = ir / T;
3431 const int iq = ir - h * T;
3432 int tile_rows = ir1 - ir;
3433 if (tile_rows > query_tile_size) tile_rows = query_tile_size;
3434 if (tile_rows > T - iq) tile_rows = T - iq;
3435 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
3436 const float *k_head = k + (size_t) kv_head * kv_head_stride;
3437 const float *v_head = v + (size_t) kv_head * kv_head_stride;
3438
3439 for (int tq = 0; tq < query_tile_size; ++tq) {
3440 sum_row[tq] = 0.0f;
3441 max_row[tq] = -INFINITY;
3442 }
3443
3444 memset(vkq, 0, (size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3445 memset(q_tile, 0, (size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3446 memset(k_tile, 0, (size_t) head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3447 memset(v_tile, 0, (size_t) CK_GGML_FA_TILE_KV * (size_t) head_dim * sizeof(float));
3448
3449 for (int tq = 0; tq < tile_rows; ++tq) {
3450 const float *q_vec = q + qkv_index(h, iq + tq, 0, T, aligned_head_dim);
3451 memcpy(q_tile + (size_t) tq * (size_t) head_dim, q_vec, (size_t) head_dim * sizeof(float));
3452 }
3453
3454 for (int ik = 0; ik < T; ik += CK_GGML_FA_TILE_KV) {
3455 const int kv_tile = (T - ik) < CK_GGML_FA_TILE_KV ? (T - ik) : CK_GGML_FA_TILE_KV;
3456 memset(kq, 0, (size_t) query_tile_size * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3457
3458 for (int tk = 0; tk < kv_tile; ++tk) {
3459 const float *k_vec = k_head + (size_t) (ik + tk) * (size_t) aligned_head_dim;
3460 const float *v_vec = v_head + (size_t) (ik + tk) * (size_t) aligned_head_dim;
3461 for (int d = 0; d < head_dim; ++d) {
3462 k_tile[(size_t) d * (size_t) CK_GGML_FA_TILE_KV + (size_t) tk] =
3463 ck_round_fp16_scalar(k_vec[d]);
3464 v_tile[(size_t) tk * (size_t) head_dim + (size_t) d] =
3465 ck_round_fp16_scalar(v_vec[d]);
3466 }
3467 }
3468
3470 q_tile,
3471 k_tile,
3472 query_tile_size,
3473 head_dim,
3476 query_tile_size * CK_GGML_FA_TILE_KV,
3477 scale);
3478
3479 if (kv_tile < CK_GGML_FA_TILE_KV) {
3480 for (int tq = 0; tq < query_tile_size; ++tq) {
3481 float *kq_row = kq + (size_t) tq * (size_t) CK_GGML_FA_TILE_KV;
3482 for (int tk = kv_tile; tk < CK_GGML_FA_TILE_KV; ++tk) {
3483 kq_row[tk] = -INFINITY;
3484 }
3485 }
3486 }
3487
3488 for (int tq = 0; tq < tile_rows; ++tq) {
3489 float *kq_row = kq + (size_t) tq * (size_t) CK_GGML_FA_TILE_KV;
3490 const float tile_max = ck_vec_max_f32_contig(kq_row, CK_GGML_FA_TILE_KV);
3491 if (tile_max == -INFINITY) {
3492 memset(kq_row, 0, (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3493 continue;
3494 }
3495
3496 const float old_max = max_row[tq];
3497 const float new_max = old_max > tile_max ? old_max : tile_max;
3498 if (new_max > old_max) {
3499 const float ms = ck_attention_reference_expf(old_max - new_max);
3500 ck_vec_scale_f32_inplace(vkq + (size_t) tq * (size_t) head_dim,
3501 head_dim,
3502 ms);
3503 sum_row[tq] *= ms;
3504 }
3505 max_row[tq] = new_max;
3506 sum_row[tq] = (float) (
3507 (double) sum_row[tq] +
3509 CK_GGML_FA_TILE_KV, kq_row, kq_row, new_max));
3510 }
3511
3513 kq,
3514 v_tile,
3515 query_tile_size,
3517 head_dim);
3518 }
3519
3520 for (int tq = 0; tq < tile_rows; ++tq) {
3521 float *out_vec = output + qkv_index(h, iq + tq, 0, T, aligned_head_dim);
3522 const float inv_sum = sum_row[tq] == 0.0f ? 0.0f : (1.0f / sum_row[tq]);
3523 for (int d = 0; d < head_dim; ++d) {
3524 out_vec[d] = vkq[(size_t) tq * (size_t) head_dim + (size_t) d] * inv_sum;
3525 }
3526 for (int d = head_dim; d < aligned_head_dim; ++d) {
3527 out_vec[d] = 0.0f;
3528 }
3529 }
3530 ir += tile_rows;
3531 }
3532}

References ck_attention_matmul_f32_accum(), ck_attention_reference_expf(), ck_attention_strict_scale_f32(), CK_GGML_FA_TILE_KV, ck_ggml_vec_soft_max_row(), ck_round_fp16_scalar(), ck_vec_max_f32_contig(), ck_vec_scale_f32_inplace(), and qkv_index().

Referenced by ck_attention_full_tiled_f16kv_fp32_work().

◆ ck_attention_full_tiled_f16kv_fp32_work()

static void ck_attention_full_tiled_f16kv_fp32_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 3548 of file attention_kernels.c.

3549{
3550 ck_attention_full_tiled_f16kv_fp32_args_t *args =
3551 (ck_attention_full_tiled_f16kv_fp32_args_t *) opaque;
3553 args->q, args->k, args->v, args->output,
3554 args->num_heads, args->num_kv_heads, args->num_tokens,
3555 args->head_dim, args->aligned_head_dim, args->kv_stride_tokens,
3556 args->query_tile_size,
3557 ith, nth);
3558}
static void ck_attention_full_tiled_f16kv_fp32_range(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 query_tile_size, int ith, int nth)

References ck_attention_full_tiled_f16kv_fp32_range().

Referenced by ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided().

◆ ck_attention_ggml_out_graph_enabled()

static int ck_attention_ggml_out_graph_enabled ( void  )
static

Definition at line 500 of file attention_kernels.c.

501{
502 return 0;
503}

Referenced by attention_forward_full_head_major_gqa_ggml_strided_workspace().

◆ ck_attention_gqa_team_barrier_wait()

static void ck_attention_gqa_team_barrier_wait ( ck_attention_gqa_team_barrier_t *  barrier)
inlinestatic

Definition at line 7091 of file attention_kernels.c.

7093{
7094 const int phase = __atomic_load_n(&barrier->phase, __ATOMIC_RELAXED);
7095 if (__atomic_fetch_add(&barrier->arrived, 1, __ATOMIC_ACQ_REL) ==
7096 barrier->lanes - 1) {
7097 __atomic_store_n(&barrier->arrived, 0, __ATOMIC_RELAXED);
7098 __atomic_store_n(&barrier->phase, phase + 1, __ATOMIC_RELEASE);
7099 return;
7100 }
7101 while (__atomic_load_n(&barrier->phase, __ATOMIC_ACQUIRE) == phase) {
7102#if defined(__i386__) || defined(__x86_64__)
7103 _mm_pause();
7104#endif
7105 }
7106}

Referenced by ck_attention_f16_prefill_gqa_reuse_work().

◆ ck_attention_llama_regular_impl()

static void ck_attention_llama_regular_impl ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  query_tokens,
int  live_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  sliding_window,
float *  scores,
size_t  scores_bytes,
float *  value_columns,
size_t  value_columns_bytes,
float *  scaled_scores,
size_t  scaled_scores_bytes,
int  batched_prefill 
)
static

Definition at line 5968 of file attention_kernels.c.

5976{
5977 if (!q || !k || !v || !output || !scores || !value_columns || !scaled_scores ||
5978 num_heads <= 0 || num_kv_heads <= 0 || query_tokens <= 0 || live_tokens <= 0 ||
5979 head_dim <= 0 || aligned_head_dim < head_dim || kv_stride_tokens < live_tokens) return;
5980 size_t scratch_capacity = scores_bytes / sizeof(float);
5981 const size_t scaled_capacity = scaled_scores_bytes / sizeof(float);
5982 const size_t value_capacity = value_columns_bytes /
5983 ((size_t)head_dim * sizeof(float));
5984 if (scaled_capacity < scratch_capacity) scratch_capacity = scaled_capacity;
5985 if (value_capacity < scratch_capacity) scratch_capacity = value_capacity;
5986 if (!batched_prefill && (size_t)kv_stride_tokens < scratch_capacity) {
5987 scratch_capacity = (size_t)kv_stride_tokens;
5988 }
5989 const int padded = scratch_capacity > (size_t)INT_MAX ? 0 :
5990 ck_llama_kv_pad_256(live_tokens, (int)scratch_capacity);
5991 if (padded <= 0 || scores_bytes < (size_t)padded * sizeof(float) ||
5992 scaled_scores_bytes < (size_t)padded * sizeof(float) ||
5993 value_columns_bytes < (size_t)head_dim * (size_t)padded * sizeof(float)) return;
5994
5995 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
5996 const int debug_layer_id = ck_attention_vec_dump_enabled()
5998 int packed_kv_head = -1;
5999 for (int head = 0; head < num_heads; ++head) {
6000 const int kv_head = (int)((long long)head * num_kv_heads / num_heads);
6001 const float *key_head = k + (size_t)kv_head * kv_head_stride;
6002 const float *value_head = v + (size_t)kv_head * kv_head_stride;
6003 if (kv_head != packed_kv_head) {
6004 for (int dim = 0; dim < head_dim; ++dim) {
6005 float *column = value_columns + (size_t)dim * (size_t)padded;
6006 int token = 0;
6007 for (; token < live_tokens; ++token) {
6008 column[token] = value_head[(size_t)token * aligned_head_dim + dim];
6009 }
6010 for (; token < padded; ++token) column[token] = 0.0f;
6011 }
6012 packed_kv_head = kv_head;
6013 }
6014 for (int query = 0; query < query_tokens; ++query) {
6015 const int position = batched_prefill ? query : live_tokens - 1;
6017 q + ((size_t)head * query_tokens + query) * aligned_head_dim,
6018 key_head, value_columns,
6019 output + ((size_t)head * query_tokens + query) * aligned_head_dim,
6020 scores, scaled_scores, live_tokens, padded, position,
6021 head_dim, aligned_head_dim, sliding_window, batched_prefill);
6022 if (debug_layer_id >= 0 &&
6023 ck_attention_vec_dump_should_emit(debug_layer_id, head, query)) {
6025 scaled_scores, scores,
6026 output + ((size_t)head * query_tokens + query) * aligned_head_dim,
6027 value_columns, padded, head_dim,
6028 debug_layer_id, head, query);
6029 }
6030 }
6031 }
6032}
static int ck_llama_kv_pad_256(int live_tokens, int capacity)
static void ck_attention_llama_regular_query(const float *query, const float *key_head, const float *value_columns, float *output, float *scores, float *scaled_scores, int live_tokens, int padded_tokens, int query_position, int head_dim, int aligned_head_dim, int sliding_window, int batched_prefill)

References ck_attention_llama_regular_query(), ck_attention_vec_dump_enabled(), ck_attention_vec_dump_next_layer_id(), ck_attention_vec_dump_selected_query(), ck_attention_vec_dump_should_emit(), ck_llama_kv_pad_256(), and token.

Referenced by attention_forward_causal_head_major_gqa_llama_regular_strided_sliding_workspace(), and attention_forward_decode_head_major_gqa_llama_regular_sliding_workspace().

◆ ck_attention_llama_regular_query()

static void ck_attention_llama_regular_query ( const float *  query,
const float *  key_head,
const float *  value_columns,
float *  output,
float *  scores,
float *  scaled_scores,
int  live_tokens,
int  padded_tokens,
int  query_position,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
int  batched_prefill 
)
static

Definition at line 5930 of file attention_kernels.c.

5936{
5937 const int first = sliding_window > 0 && query_position >= sliding_window
5938 ? query_position - sliding_window + 1 : 0;
5939 const int last = query_position < live_tokens ? query_position : live_tokens - 1;
5940 for (int token = 0; token < padded_tokens; ++token) scores[token] = -INFINITY;
5941 for (int token = first; token <= last; ++token) {
5942 const float *key = key_head + (size_t)token * (size_t)aligned_head_dim;
5943 scores[token] = batched_prefill
5944 ? ck_llama_regular_gemm_f16(query, key, head_dim)
5945 : ck_llama_regular_dot_f16(query, key, head_dim);
5946 }
5947
5948 memcpy(scaled_scores, scores, (size_t)padded_tokens * sizeof(float));
5949 const float scale = 1.0f / sqrtf((float)head_dim);
5950 ck_vec_scale_f32_inplace(scaled_scores, padded_tokens, scale);
5951 const float maximum = ck_vec_max_f32_contig(scaled_scores, padded_tokens);
5952 const double total = ck_ggml_vec_soft_max_row(
5953 padded_tokens, scores, scaled_scores, maximum);
5954 if (total > 0.0) {
5955 ck_vec_scale_f32_inplace(scores, padded_tokens, (float)(1.0 / total));
5956 for (int dim = 0; dim < head_dim; ++dim) {
5957 const float *column = value_columns + (size_t)dim * (size_t)padded_tokens;
5958 output[dim] = batched_prefill
5959 ? ck_llama_regular_gemm_f16(scores, column, padded_tokens)
5960 : ck_llama_regular_dot_f16(scores, column, padded_tokens);
5961 }
5962 } else {
5963 memset(output, 0, (size_t)head_dim * sizeof(float));
5964 }
5965 for (int dim = head_dim; dim < aligned_head_dim; ++dim) output[dim] = 0.0f;
5966}
static float ck_llama_regular_gemm_f16(const float *probability, const float *value_column, int count)
static float ck_llama_regular_dot_f16(const float *a, const float *b, int count)

References ck_ggml_vec_soft_max_row(), ck_llama_regular_dot_f16(), ck_llama_regular_gemm_f16(), ck_vec_max_f32_contig(), ck_vec_scale_f32_inplace(), and token.

Referenced by ck_attention_llama_regular_impl(), and ck_llama_regular_prefill_work().

◆ ck_attention_mad_f16_llama()

static void ck_attention_mad_f16_llama ( uint16_t *  y,
const uint16_t *  x,
float  scale,
int  n 
)
inlinestatic

Definition at line 6543 of file attention_kernels.c.

6547{
6548 int i = 0;
6549#if defined(__AVX512F__)
6550 const __m512 factor = _mm512_set1_ps(scale);
6551 for (; i + 63 < n; i += 64) {
6552 for (int lane = 0; lane < 4; ++lane) {
6553 const int offset = i + lane * 16;
6554 const __m512 xv = _mm512_cvtph_ps(
6555 _mm256_loadu_si256((const __m256i *) (x + offset)));
6556 __m512 yv = _mm512_cvtph_ps(
6557 _mm256_loadu_si256((const __m256i *) (y + offset)));
6558 yv = _mm512_fmadd_ps(xv, factor, yv);
6559 _mm256_storeu_si256(
6560 (__m256i *) (y + offset), _mm512_cvtps_ph(yv, 0));
6561 }
6562 }
6563#elif defined(__AVX2__) && defined(__F16C__)
6564 const __m256 factor = _mm256_set1_ps(scale);
6565 for (; i + 31 < n; i += 32) {
6566 for (int lane = 0; lane < 4; ++lane) {
6567 const int offset = i + lane * 8;
6568 const __m256 xv = _mm256_cvtph_ps(
6569 _mm_loadu_si128((const __m128i *) (x + offset)));
6570 __m256 yv = _mm256_cvtph_ps(
6571 _mm_loadu_si128((const __m128i *) (y + offset)));
6572#if defined(__FMA__)
6573 yv = _mm256_fmadd_ps(xv, factor, yv);
6574#else
6575 yv = _mm256_add_ps(yv, _mm256_mul_ps(xv, factor));
6576#endif
6577 _mm_storeu_si128(
6578 (__m128i *) (y + offset), _mm256_cvtps_ph(yv, 0));
6579 }
6580 }
6581#endif
6582 for (; i < n; ++i) {
6583 const float product = CK_FP16_TO_FP32(x[i]) * scale;
6584 const float updated = CK_FP16_TO_FP32(y[i]) + product;
6585 y[i] = CK_FP32_TO_FP16(updated);
6586 }
6587}

References CK_FP16_TO_FP32, CK_FP32_TO_FP16, and product().

Referenced by ck_attention_f16_split_work().

◆ ck_attention_matmul_f32_accum()

static void ck_attention_matmul_f32_accum ( float *  c,
const float *  a,
const float *  b,
int  m,
int  k,
int  n 
)
static

Definition at line 3367 of file attention_kernels.c.

3373{
3374 for (int i = 0; i < m; ++i) {
3375 float *c_row = c + (size_t) i * (size_t) n;
3376 const float *a_row = a + (size_t) i * (size_t) k;
3377 for (int kk = 0; kk < k; ++kk) {
3378 const float a_ik = a_row[kk];
3379 const float *b_row = b + (size_t) kk * (size_t) n;
3380 for (int j = 0; j < n; ++j) {
3381 c_row[j] += a_ik * b_row[j];
3382 }
3383 }
3384 }
3385}

Referenced by ck_attention_f16_prefill_gqa_reuse_work(), ck_attention_f16_prefill_qtile64_work(), and ck_attention_full_tiled_f16kv_fp32_range().

◆ ck_attention_muse_eager_bf16_storage_impl()

static void ck_attention_muse_eager_bf16_storage_impl ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  query_tokens,
int  kv_tokens,
int  kv_stride_tokens,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
float *  scores,
size_t  scores_bytes,
uint16_t *  key_rows,
size_t  key_rows_bytes,
uint16_t *  value_columns,
size_t  value_columns_bytes,
uint16_t *  gemm_rows,
size_t  gemm_rows_bytes,
uint16_t *  gemm_scores,
size_t  gemm_scores_bytes 
)
static

Definition at line 9053 of file attention_kernels.c.

9076{
9077#if defined(__AVX512F__) && defined(USE_ONEDNN)
9078 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
9079 query_tokens <= 0 || kv_tokens < query_tokens ||
9080 kv_stride_tokens < kv_tokens || head_dim <= 0 ||
9081 aligned_head_dim != head_dim || num_heads % num_kv_heads != 0) {
9082 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid Muse eager attention dimensions\n");
9083 abort();
9084 }
9085
9086 const int workspace_rows = query_tokens < CK_MUSE_PREFILL_QUERY_TILE
9087 ? query_tokens : CK_MUSE_PREFILL_QUERY_TILE;
9088 const size_t score_count = ck_muse_attention_checked_product(
9089 (size_t)workspace_rows, (size_t)kv_tokens, "score");
9090 const size_t kv_matrix_count = ck_muse_attention_checked_product(
9091 (size_t)kv_tokens, (size_t)head_dim, "KV matrix");
9092 const size_t row_count = ck_muse_attention_checked_product(
9093 (size_t)workspace_rows, (size_t)head_dim, "row matrix");
9094 if (score_count > SIZE_MAX / sizeof(*scores) ||
9095 kv_matrix_count > SIZE_MAX / sizeof(*key_rows) ||
9096 row_count > SIZE_MAX / sizeof(*gemm_rows)) {
9097 fprintf(stderr,
9098 "HARD KERNEL CONTRACT FAULT: Muse eager attention workspace "
9099 "byte size overflow\n");
9100 abort();
9101 }
9102 if (!scores || scores_bytes < score_count * sizeof(*scores) ||
9103 !key_rows || key_rows_bytes < kv_matrix_count * sizeof(*key_rows) ||
9104 !value_columns ||
9105 value_columns_bytes < kv_matrix_count * sizeof(*value_columns) ||
9106 !gemm_rows || gemm_rows_bytes < row_count * sizeof(*gemm_rows) ||
9107 !gemm_scores ||
9108 gemm_scores_bytes < score_count * sizeof(*gemm_scores)) {
9109 fprintf(stderr,
9110 "HARD KERNEL CONTRACT FAULT: Muse eager attention received "
9111 "an undersized planner-owned workspace\n");
9112 abort();
9113 }
9114 pthread_once(&ck_pytorch_attention_once, ck_bind_pytorch_attention_primitives);
9115 if (!ck_pytorch_attention_expf16) {
9116 fprintf(stderr,
9117 "HARD KERNEL CONTRACT FAULT: Muse eager attention requires "
9118 "Sleef_expf16_u10 from CK_SLEEF_LIBRARY\n");
9119 abort();
9120 }
9121
9122 const float scale = 1.0f / sqrtf((float)head_dim);
9123 const int heads_per_kv = num_heads / num_kv_heads;
9124 const int query_position_offset = kv_tokens - query_tokens;
9125 const size_t query_head_stride = ck_muse_attention_checked_product(
9126 (size_t)query_tokens, (size_t)aligned_head_dim, "query stride");
9127 const size_t kv_head_stride = ck_muse_attention_checked_product(
9128 (size_t)kv_stride_tokens, (size_t)aligned_head_dim, "KV stride");
9130 (size_t)num_heads, query_head_stride, "query tensor");
9132 (size_t)num_kv_heads, kv_head_stride, "KV tensor");
9133
9134 for (int head = 0; head < num_heads; ++head) {
9135 const int kv_head = head / heads_per_kv;
9136 const float *key_head = k + (size_t)kv_head * kv_head_stride;
9137 const float *value_head = v + (size_t)kv_head * kv_head_stride;
9138 for (int token = 0; token < kv_tokens; ++token) {
9139 const float *key_row = key_head +
9140 (size_t)token * (size_t)aligned_head_dim;
9141 const float *value_row = value_head +
9142 (size_t)token * (size_t)aligned_head_dim;
9143 for (int dim = 0; dim < head_dim; ++dim) {
9144 key_rows[(size_t)token * (size_t)head_dim + (size_t)dim] =
9145 float_to_bf16(key_row[dim]);
9146 value_columns[(size_t)dim * (size_t)kv_tokens + (size_t)token] =
9147 float_to_bf16(value_row[dim]);
9148 }
9149 }
9150
9151 const float *query_head = q + (size_t)head * query_head_stride;
9152 float *output_head = output + (size_t)head * query_head_stride;
9153 for (int query_start = 0; query_start < query_tokens;
9154 query_start += CK_MUSE_PREFILL_QUERY_TILE) {
9155 const int tile_rows = query_tokens - query_start < CK_MUSE_PREFILL_QUERY_TILE
9156 ? query_tokens - query_start : CK_MUSE_PREFILL_QUERY_TILE;
9158 query_head + (size_t)query_start * (size_t)head_dim,
9159 key_rows, NULL, scores,
9160 tile_rows, kv_tokens, head_dim,
9161 gemm_rows, gemm_rows_bytes, gemm_scores, gemm_scores_bytes,
9162 NULL, 0);
9163
9164 for (int query_token = 0; query_token < tile_rows; ++query_token) {
9165 const int query_position = query_position_offset + query_start + query_token;
9166 const int visible_end = query_position + 1;
9167 int visible_begin = 0;
9168 if (sliding_window > 0 && visible_end > sliding_window) {
9169 visible_begin = visible_end - sliding_window;
9170 }
9171 float *score_row = scores +
9172 (size_t)query_token * (size_t)kv_tokens;
9173 for (int token = 0; token < kv_tokens; ++token) {
9174 score_row[token] = bf16_to_float(
9175 float_to_bf16(score_row[token] * scale));
9176 if (token < visible_begin || token >= visible_end) {
9177 score_row[token] = -INFINITY;
9178 }
9179 }
9180 (void)ck_pytorch_softmax_f32(score_row, kv_tokens);
9181 }
9183 scores, value_columns, NULL,
9184 output_head + (size_t)query_start * (size_t)head_dim,
9185 tile_rows, head_dim, kv_tokens,
9186 gemm_scores, gemm_scores_bytes, gemm_rows, gemm_rows_bytes,
9187 NULL, 0);
9188 }
9189 }
9190#else
9191 (void)q; (void)k; (void)v; (void)output; (void)num_heads;
9192 (void)num_kv_heads; (void)query_tokens; (void)kv_tokens;
9193 (void)kv_stride_tokens; (void)head_dim; (void)aligned_head_dim;
9194 (void)sliding_window;
9195 (void)scores; (void)scores_bytes; (void)key_rows; (void)key_rows_bytes;
9196 (void)value_columns; (void)value_columns_bytes;
9197 (void)gemm_rows; (void)gemm_rows_bytes;
9198 (void)gemm_scores; (void)gemm_scores_bytes;
9199 fprintf(stderr,
9200 "HARD KERNEL CONTRACT FAULT: Muse eager attention requires "
9201 "AVX-512 and USE_ONEDNN=1\n");
9202 abort();
9203#endif
9204}
#define CK_MUSE_PREFILL_QUERY_TILE
static size_t ck_muse_attention_checked_product(size_t left, size_t right, const char *label)
void gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage_workspace(const float *A, const void *B, const float *bias, float *C, int M, int N, int K, uint16_t *input_bf16, size_t input_bf16_bytes, uint16_t *output_bf16, size_t output_bf16_bytes, uint16_t *bias_bf16, size_t bias_bf16_bytes)

References bf16_to_float(), ck_muse_attention_checked_product(), CK_MUSE_PREFILL_QUERY_TILE, float_to_bf16(), gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage_workspace(), and token.

Referenced by attention_forward_causal_head_major_gqa_muse_eager_bf16_storage(), attention_forward_causal_head_major_gqa_muse_eager_bf16_storage_sliding(), attention_forward_decode_head_major_gqa_muse_eager_bf16_storage(), and attention_forward_decode_head_major_gqa_muse_eager_bf16_storage_sliding().

◆ ck_attention_parallel_enabled()

static int ck_attention_parallel_enabled ( int  total_queries,
int  num_tokens,
int  head_dim 
)
static

Definition at line 4060 of file attention_kernels.c.

4061{
4062 const char *disable = getenv("CK_DISABLE_ATTENTION_THREADPOOL");
4063 if (disable && disable[0] && strcmp(disable, "0") != 0) return 0;
4064 /*
4065 * A 128-token GQA prefill can fall below the old 2048-query threshold
4066 * even though its causal dot products contain ample independent work.
4067 * Keep smaller prompts serial, but allow the shared pool once at least
4068 * eight 128-query worker grains are available.
4069 */
4070 if (total_queries < 1024 || num_tokens < 128 || head_dim <= 0) return 0;
4071 return 1;
4072}

Referenced by attention_forward_head_major_gqa_flash_impl().

◆ ck_attention_pick_active_threads()

static int ck_attention_pick_active_threads ( const ck_threadpool_t *  pool,
int  total_queries,
int  num_tokens 
)
static

Definition at line 4074 of file attention_kernels.c.

4075{
4076 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
4077 if (nth <= 1) return 1;
4078 const char *cap_env = getenv("CK_ATTENTION_THREAD_CAP");
4079 int cap = cap_env && cap_env[0] ? atoi(cap_env) : 24;
4080 if (cap < 1) cap = 1;
4081 if (cap > nth) cap = nth;
4082 int active = (total_queries + 127) / 128;
4083 if (num_tokens >= 1024 && active < 8) active = 8;
4084 if (active > cap) active = cap;
4085 if (active > nth) active = nth;
4086 return active < 1 ? 1 : active;
4087}

References ck_threadpool_n_threads().

Referenced by attention_forward_head_major_gqa_flash_impl().

◆ ck_attention_prefill_append_f16cache_gemma4_workspace()

static ck_attention_status_t ck_attention_prefill_append_f16cache_gemma4_workspace ( const float *  q,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  q_tokens,
int  past_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
ck_attention_reduction_t  reduction,
float *  token_workspace,
size_t  token_workspace_bytes,
const int *  segment_lengths,
int  num_segments 
)
static

Definition at line 7854 of file attention_kernels.c.

7872{
7873 if (!q || !k_cache || !v_cache || !output || num_heads <= 0 ||
7874 num_kv_heads <= 0 || q_tokens <= 0 || past_tokens < 0 ||
7875 cache_capacity <= 0 || past_tokens > cache_capacity ||
7876 q_tokens > cache_capacity - past_tokens || head_dim <= 0 ||
7877 aligned_head_dim < head_dim || sliding_window < 0) {
7879 }
7880 int one_segment = q_tokens;
7881 if (!segment_lengths && num_segments == 0) {
7882 segment_lengths = &one_segment;
7883 num_segments = 1;
7884 }
7885 if (!segment_lengths || num_segments <= 0 ||
7886 (num_segments > q_tokens && num_segments > 3)) {
7888 }
7889 int planned_rows = 0;
7890 for (int s = 0; s < num_segments; ++s) {
7891 if (segment_lengths[s] < 0 || segment_lengths[s] > q_tokens - planned_rows) {
7893 }
7894 planned_rows += segment_lengths[s];
7895 }
7896 if (planned_rows != q_tokens) return CK_ATTENTION_STATUS_INVALID_ARGUMENT;
7897 if ((size_t) num_heads > SIZE_MAX / (size_t) aligned_head_dim) {
7899 }
7900 const size_t token_elems = (size_t) num_heads * (size_t) aligned_head_dim;
7901 if (token_elems > SIZE_MAX / (2 * sizeof(float)) || !token_workspace ||
7902 token_workspace_bytes < 2 * token_elems * sizeof(float)) {
7904 }
7905 float *q_token = token_workspace;
7906 float *out_token = token_workspace + token_elems;
7907 int row_offset = 0;
7908 for (int s = 0; s < num_segments; ++s) {
7909 const int rows = segment_lengths[s];
7910 if (rows == 0) continue;
7911 if ((reduction == CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64 ||
7913 rows >= CK_GGML_FA_TILE_Q &&
7914 (sliding_window == 0 || past_tokens + row_offset + rows <= sliding_window)) {
7916 q + (size_t) row_offset * (size_t) aligned_head_dim,
7917 k_cache, v_cache,
7918 output + (size_t) row_offset * (size_t) aligned_head_dim,
7919 num_heads, num_kv_heads, rows, past_tokens + row_offset,
7920 cache_capacity, head_dim, aligned_head_dim, 0, 1.0f,
7921 (size_t) q_tokens * (size_t) aligned_head_dim,
7922 (size_t) q_tokens * (size_t) aligned_head_dim,
7924 if (status != CK_ATTENTION_STATUS_OK) return status;
7925 row_offset += rows;
7926 continue;
7927 }
7928 const ck_attention_reduction_t selected =
7933 for (int local_row = 0; local_row < rows; ++local_row) {
7934 const int t = row_offset + local_row;
7935 for (int h = 0; h < num_heads; ++h) {
7936 const float *src = q +
7937 ((size_t) h * (size_t) q_tokens + (size_t) t) *
7938 (size_t) aligned_head_dim;
7939 memcpy(q_token + (size_t) h * (size_t) aligned_head_dim, src,
7940 (size_t) aligned_head_dim * sizeof(float));
7941 }
7943 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
7944 past_tokens + t + 1, cache_capacity, head_dim, aligned_head_dim,
7945 sliding_window, selected);
7946 if (status != CK_ATTENTION_STATUS_OK) {
7947 return status;
7948 }
7949 for (int h = 0; h < num_heads; ++h) {
7950 float *dst = output +
7951 ((size_t) h * (size_t) q_tokens + (size_t) t) *
7952 (size_t) aligned_head_dim;
7953 memcpy(dst, out_token + (size_t) h * (size_t) aligned_head_dim,
7954 (size_t) aligned_head_dim * sizeof(float));
7955 }
7956 }
7957 row_offset += rows;
7958 }
7960}
@ CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64_REGULAR_TAIL_NOSCALE

References ck_attention_f16_prefill_qtile64_dispatch(), ck_attention_forward_decode_f16cache_gemma4(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_OK, CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES, CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64, CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64_REGULAR_TAIL_NOSCALE, CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE, CK_ATTN_REDUCTION_F16_REGULAR_NOSCALE, and CK_GGML_FA_TILE_Q.

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_gemma4_workspace(), attention_forward_causal_head_major_gqa_prefill_append_f16cache_sliding_gemma4_workspace(), attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_gemma4_workspace(), and attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_sliding_gemma4_workspace().

◆ ck_attention_pytorch_sdpa_scale_f32()

float ck_attention_pytorch_sdpa_scale_f32 ( int  head_dim)

Definition at line 4592 of file attention_kernels.c.

4593{
4594 /* PyTorch CPU flash calculate_scale evaluates in FP64, then narrows. */
4595 return head_dim > 0 ? (float)(1.0 / sqrt((double)head_dim)) : 0.0f;
4596}

Referenced by ck_attention_full_bf16_sdpa_amx_range(), and ck_attention_full_bf16_sdpa_tiled_range().

◆ ck_attention_query_key_f32_head_work()

static void ck_attention_query_key_f32_head_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 240 of file attention_kernels.c.

241{
242 ck_attention_query_key_f32_head_args_t *args =
243 (ck_attention_query_key_f32_head_args_t *)opaque;
244 const size_t query_stride =
245 (size_t)args->query_tokens * (size_t)args->head_dim;
246 const size_t kv_stride =
247 (size_t)args->key_tokens * (size_t)args->head_dim;
248 for (int head = ith; head < args->num_heads; head += nth) {
250 args->query + (size_t)head * query_stride,
251 args->key + (size_t)head * kv_stride,
252 args->value + (size_t)head * kv_stride,
253 args->output + (size_t)head * query_stride,
254 args->score_scratch + (size_t)head * args->key_tokens,
255 NULL, 1, args->query_tokens, args->key_tokens,
256 args->head_dim, args->scale);
257 }
258}

References ck_attention_forward_query_key_head_major_f32_run().

Referenced by attention_forward_query_key_head_major_f32_decode_heads().

◆ ck_attention_query_key_f32_transpose_work()

static void ck_attention_query_key_f32_transpose_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 59 of file attention_kernels.c.

60{
61 ck_attention_query_key_f32_args_t *args =
62 (ck_attention_query_key_f32_args_t *)opaque;
63 const int rows = args->num_heads * args->head_dim;
64 for (int row = ith; row < rows; row += nth) {
65 const int head = row / args->head_dim;
66 const int dim = row % args->head_dim;
67 const float *key_head = args->key +
68 (size_t)head * args->key_tokens * args->head_dim;
69 float *packed = args->key_transpose_scratch +
70 (size_t)row * args->key_tokens;
71 for (int key_token = 0; key_token < args->key_tokens; ++key_token) {
72 packed[key_token] =
73 key_head[(size_t)key_token * args->head_dim + dim];
74 }
75 }
76}

Referenced by ck_attention_forward_query_key_head_major_f32_run().

◆ ck_attention_query_key_f32_work()

static void ck_attention_query_key_f32_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 78 of file attention_kernels.c.

79{
80 ck_attention_query_key_f32_args_t *args =
81 (ck_attention_query_key_f32_args_t *)opaque;
82 for (int q_token = ith; q_token < args->query_tokens; q_token += nth) {
83 float *scores = args->score_scratch +
84 (size_t)q_token * args->key_tokens;
85 for (int head = 0; head < args->num_heads; ++head) {
86 const float *q_head = args->query +
87 (size_t)head * args->query_tokens * args->head_dim;
88 const float *k_head = args->key +
89 (size_t)head * args->key_tokens * args->head_dim;
90 const float *v_head = args->value +
91 (size_t)head * args->key_tokens * args->head_dim;
92 float *out_head = args->output +
93 (size_t)head * args->query_tokens * args->head_dim;
94 const float *q_row = q_head + (size_t)q_token * args->head_dim;
95 float maximum = -FLT_MAX;
96 int k_token = 0;
97#if defined(__AVX2__) && defined(__FMA__)
98 for (; args->key_transpose_scratch != NULL &&
99 k_token + 7 < args->key_tokens; k_token += 8) {
100 __m256 dots = _mm256_setzero_ps();
101 for (int dim = 0; dim < args->head_dim; ++dim) {
102 const float *packed = args->key_transpose_scratch +
103 ((size_t)head * args->head_dim + dim) *
104 args->key_tokens + k_token;
105 dots = _mm256_fmadd_ps(
106 _mm256_set1_ps(q_row[dim]),
107 _mm256_loadu_ps(packed), dots);
108 }
109 float dot_values[8];
110 _mm256_storeu_ps(dot_values, dots);
111 for (int lane = 0; lane < 8; ++lane) {
112 const float score = dot_values[lane] * args->scale;
113 scores[k_token + lane] = score;
114 maximum = fmaxf(maximum, score);
115 }
116 }
117#endif
118 for (; k_token < args->key_tokens; ++k_token) {
119 const float *k_row = k_head +
120 (size_t)k_token * args->head_dim;
121 float dot = 0.0f;
122 for (int dim = 0; dim < args->head_dim; ++dim) {
123 dot = fmaf(q_row[dim], k_row[dim], dot);
124 }
125 const float score = dot * args->scale;
126 scores[k_token] = score;
127 maximum = fmaxf(maximum, score);
128 }
129 double denominator = 0.0;
130 for (int k_token = 0; k_token < args->key_tokens; ++k_token) {
131 const float probability = expf(scores[k_token] - maximum);
132 scores[k_token] = probability;
133 denominator += (double)probability;
134 }
135 const float inverse = denominator > 0.0 ? (float)(1.0 / denominator) : 0.0f;
136 float *out_row = out_head +
137 (size_t)q_token * args->head_dim;
138 for (int dim = 0; dim < args->head_dim; ++dim) {
139 out_row[dim] = 0.0f;
140 }
141 for (int k_token = 0; k_token < args->key_tokens; ++k_token) {
142 const float probability = scores[k_token] * inverse;
143 const float *v_row = v_head +
144 (size_t)k_token * args->head_dim;
145 for (int dim = 0; dim < args->head_dim; ++dim) {
146 out_row[dim] = fmaf(probability, v_row[dim], out_row[dim]);
147 }
148 }
149 }
150 }
151}

References score.

Referenced by ck_attention_forward_query_key_head_major_f32_run().

◆ ck_attention_reference_expf()

static float ck_attention_reference_expf ( float  value)
static

Definition at line 1243 of file attention_kernels.c.

1244{
1245#if defined(__linux__)
1246 static void *libm_handle = NULL;
1247 static ck_attention_math_f32_fn fn = NULL;
1248 static int resolved = 0;
1249 if (!resolved) {
1250 libm_handle = dlopen("libm.so.6", RTLD_NOW | RTLD_LOCAL);
1251 if (libm_handle) {
1252 fn = (ck_attention_math_f32_fn) dlsym(libm_handle, "expf");
1253 }
1254 resolved = 1;
1255 }
1256 if (fn) {
1257 return fn(value);
1258 }
1259#endif
1260 return expf(value);
1261}
float(* ck_attention_math_f32_fn)(float)

Referenced by attention_forward_decode_head_major_gqa_f16cache_regular_noscale(), ck_attention_f16_prefill_gqa_reuse_work(), ck_attention_f16_prefill_qtile64_work(), ck_attention_f16_reduce_expf(), ck_attention_f16_split_work(), and ck_attention_full_tiled_f16kv_fp32_range().

◆ ck_attention_reverse_out_dot_enabled()

static int ck_attention_reverse_out_dot_enabled ( void  )
static

Definition at line 487 of file attention_kernels.c.

488{
489 const char *v = getenv("CK_STRICT_ATTN_REVERSE_OUT_DOT");
490 return v && v[0] && strcmp(v, "0") != 0;
491}

◆ ck_attention_scale_f16_llama()

static void ck_attention_scale_f16_llama ( uint16_t *  y,
float  scale,
int  n 
)
inlinestatic

Definition at line 6509 of file attention_kernels.c.

6510{
6511 int i = 0;
6512#if defined(__AVX512F__)
6513 const __m512 factor = _mm512_set1_ps(scale);
6514 for (; i + 63 < n; i += 64) {
6515 for (int lane = 0; lane < 4; ++lane) {
6516 const int offset = i + lane * 16;
6517 __m512 value = _mm512_cvtph_ps(
6518 _mm256_loadu_si256((const __m256i *) (y + offset)));
6519 value = _mm512_mul_ps(value, factor);
6520 _mm256_storeu_si256(
6521 (__m256i *) (y + offset), _mm512_cvtps_ph(value, 0));
6522 }
6523 }
6524#elif defined(__AVX2__) && defined(__F16C__)
6525 const __m256 factor = _mm256_set1_ps(scale);
6526 for (; i + 31 < n; i += 32) {
6527 for (int lane = 0; lane < 4; ++lane) {
6528 const int offset = i + lane * 8;
6529 __m256 value = _mm256_cvtph_ps(
6530 _mm_loadu_si128((const __m128i *) (y + offset)));
6531 value = _mm256_mul_ps(value, factor);
6532 _mm_storeu_si128(
6533 (__m128i *) (y + offset), _mm256_cvtps_ph(value, 0));
6534 }
6535 }
6536#endif
6537 for (; i < n; ++i) {
6538 const float value = CK_FP16_TO_FP32(y[i]);
6539 y[i] = CK_FP32_TO_FP16(value * scale);
6540 }
6541}

References CK_FP16_TO_FP32, and CK_FP32_TO_FP16.

Referenced by ck_attention_f16_split_work().

◆ ck_attention_sparse_bf16_pytorch_gqa_available()

int ck_attention_sparse_bf16_pytorch_gqa_available ( void  )

Definition at line 9016 of file attention_kernels.c.

9017{
9018#if defined(__AVX512F__)
9020#else
9021 return 0;
9022#endif
9023}
int ck_attention_bf16_pytorch_gqa_available(void)

References ck_attention_bf16_pytorch_gqa_available().

◆ ck_attention_strict_scale_f32()

static float ck_attention_strict_scale_f32 ( int  head_dim)
static

Definition at line 1228 of file attention_kernels.c.

1229{
1230 // Keep strict parity on the precise libm sqrtf path. icx -O3 on AVX2 was
1231 // lowering 1/sqrtf(d) to a slightly smaller effective scale, which is
1232 // enough to move layer-0 vision softmax by ~2e-7 and snowball later.
1233 volatile float hd = (float) head_dim;
1234 float (*sqrtf_fn)(float) = sqrtf;
1235 volatile float root = sqrtf_fn(hd);
1236 volatile float one = 1.0f;
1237 volatile float scale = one / root;
1238 return scale;
1239}

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_split(), attention_forward_decode_head_major_gqa_regular(), attention_forward_full_head_major_gqa_exact_strided(), attention_forward_full_head_major_gqa_ggml_strided_workspace(), attention_forward_head_major_gqa_flash_impl(), attention_forward_query_key_head_major_tiled_f16kv_fp32(), ck_attention_f16_prefill_gqa_reuse_work(), ck_attention_f16_prefill_qtile64_work(), and ck_attention_full_tiled_f16kv_fp32_range().

◆ ck_attention_strict_unfused_f16_enabled()

static int ck_attention_strict_unfused_f16_enabled ( void  )
static

Definition at line 4089 of file attention_kernels.c.

4090{
4091 const char *value = getenv("CK_STRICT_ATTN_F16_UNFUSED");
4092 return !value || !value[0] || strcmp(value, "0") != 0;
4093}

Referenced by attention_forward_head_major_gqa_flash_impl().

◆ ck_attention_trace()

static void ck_attention_trace ( const char *  branch,
int  layer_id,
int  head_id 
)
static

Definition at line 596 of file attention_kernels.c.

597{
598 const char *enabled = getenv("CK_STRICT_ATTN_TRACE");
599 const char *dir = getenv("CK_PARITY_DIR");
600 if (!enabled || !enabled[0] || strcmp(enabled, "0") == 0 || !dir || !dir[0] || !branch || !branch[0]) {
601 return;
602 }
603 char path[4096];
604 snprintf(path, sizeof(path), "%s/%s", dir, "strict_trace.txt");
605 FILE *f = fopen(path, "a");
606 if (!f) {
607 return;
608 }
609 fprintf(f, "layer=%d head=%d branch=%s\n", layer_id, head_id, branch);
610 fclose(f);
611}

Referenced by attention_forward_full_head_major_gqa_exact_strided(), and attention_forward_full_head_major_gqa_ggml_strided_workspace().

◆ ck_attention_trace_float()

static void ck_attention_trace_float ( const char *  tag,
int  layer_id,
int  head_id,
float  value 
)
static

Definition at line 634 of file attention_kernels.c.

638{
639 const char *enabled = getenv("CK_STRICT_ATTN_TRACE");
640 const char *dir = getenv("CK_PARITY_DIR");
641 if (!enabled || !enabled[0] || strcmp(enabled, "0") == 0 || !dir || !dir[0] || !tag || !tag[0]) {
642 return;
643 }
644 char path[4096];
645 snprintf(path, sizeof(path), "%s/%s", dir, "strict_trace.txt");
646 FILE *f = fopen(path, "a");
647 if (!f) {
648 return;
649 }
650 fprintf(f, "layer=%d head=%d tag=%s float=%.17g\n", layer_id, head_id, tag, (double) value);
651 fclose(f);
652}

Referenced by attention_forward_full_head_major_gqa_ggml_strided_workspace().

◆ ck_attention_trace_query()

static void ck_attention_trace_query ( const char *  tag,
int  layer_id,
int  head_id,
int  query_id,
int  value 
)
static

Definition at line 613 of file attention_kernels.c.

618{
619 const char *enabled = getenv("CK_STRICT_ATTN_TRACE");
620 const char *dir = getenv("CK_PARITY_DIR");
621 if (!enabled || !enabled[0] || strcmp(enabled, "0") == 0 || !dir || !dir[0] || !tag || !tag[0]) {
622 return;
623 }
624 char path[4096];
625 snprintf(path, sizeof(path), "%s/%s", dir, "strict_trace.txt");
626 FILE *f = fopen(path, "a");
627 if (!f) {
628 return;
629 }
630 fprintf(f, "layer=%d head=%d query=%d tag=%s value=%d\n", layer_id, head_id, query_id, tag, value);
631 fclose(f);
632}

Referenced by ck_attention_vec_dump_selected_query(), and ck_attention_vec_dump_should_emit().

◆ ck_attention_u16_cache_to_f32()

static float ck_attention_u16_cache_to_f32 ( uint16_t  value,
int  cache_is_bf16 
)
inlinestatic

Definition at line 7108 of file attention_kernels.c.

7109{
7110 return cache_is_bf16 ? bf16_to_float(value) : CK_FP16_TO_FP32(value);
7111}

References bf16_to_float(), and CK_FP16_TO_FP32.

Referenced by ck_attention_f16_prefill_gqa_reuse_work(), and ck_attention_f16_prefill_qtile64_work().

◆ ck_attention_vec_dump_enabled()

static int ck_attention_vec_dump_enabled ( void  )
static

◆ ck_attention_vec_dump_exact_query()

static void ck_attention_vec_dump_exact_query ( const float *  q_vec,
const float *  k_head,
const float *  out_vec,
int  kv_tokens,
int  head_dim,
int  aligned_head_dim,
float  scale,
int  layer_id,
int  head_id,
int  query_id 
)
static

Definition at line 2141 of file attention_kernels.c.

2151{
2152 if (!ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
2153 return;
2154 }
2155
2156 float *raw_scores = (float *) alloca((size_t) kv_tokens * sizeof(float));
2157 float *probs = (float *) alloca((size_t) kv_tokens * sizeof(float));
2158 float max_score = -INFINITY;
2159 for (int j = 0; j < kv_tokens; ++j) {
2160 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
2161 float dot = 0.0f;
2162 for (int d = 0; d < head_dim; ++d) {
2163 dot += q_vec[d] * k_vec[d];
2164 }
2165 raw_scores[j] = dot;
2166 const float scaled = dot * scale;
2167 probs[j] = scaled;
2168 if (scaled > max_score) {
2169 max_score = scaled;
2170 }
2171 }
2172
2173 float sum = 0.0f;
2174 for (int j = 0; j < kv_tokens; ++j) {
2175 probs[j] = expf(probs[j] - max_score);
2176 sum += probs[j];
2177 }
2178 if (sum > 0.0f) {
2179 const float inv_sum = 1.0f / sum;
2180 for (int j = 0; j < kv_tokens; ++j) {
2181 probs[j] *= inv_sum;
2182 }
2183 } else {
2184 memset(probs, 0, (size_t) kv_tokens * sizeof(float));
2185 }
2186
2187 ck_attention_vec_dump_selected_query(raw_scores, probs, out_vec, NULL,
2188 kv_tokens, head_dim,
2189 layer_id, head_id, query_id);
2190}

References ck_attention_vec_dump_selected_query(), and ck_attention_vec_dump_should_emit().

Referenced by attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl().

◆ ck_attention_vec_dump_next_layer_id()

◆ ck_attention_vec_dump_parse_env_int()

static int ck_attention_vec_dump_parse_env_int ( const char *  name,
int *  out 
)
static

Definition at line 506 of file attention_kernels.c.

507{
508 const char *v = getenv(name);
509 if (!v || !v[0]) {
510 return 0;
511 }
512 char *end = NULL;
513 long parsed = strtol(v, &end, 10);
514 if (end == v || (end && *end != '\0') || parsed < 0 || parsed > INT32_MAX) {
515 return 0;
516 }
517 if (out) {
518 *out = (int) parsed;
519 }
520 return 1;
521}

References end.

Referenced by ck_attention_vec_dump_should_emit().

◆ ck_attention_vec_dump_selected_query()

static void ck_attention_vec_dump_selected_query ( const float *  raw_scores,
const float *  probs,
const float *  out_vec,
const float *  v_cols,
int  kv_tokens,
int  head_dim,
int  layer_id,
int  head_id,
int  query_id 
)
static

Definition at line 654 of file attention_kernels.c.

663{
664 if (!ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
665 return;
666 }
667 ck_attention_trace_query("vec_dump_selected_query", layer_id, head_id, query_id, 1);
668 char name[32];
669 snprintf(name, sizeof(name), "kq_scores_h%d_q%d", head_id, query_id);
670 ck_attention_vec_dump_tensor(name, layer_id, query_id, raw_scores, (size_t) kv_tokens);
671 snprintf(name, sizeof(name), "kq_soft_h%d_q%d", head_id, query_id);
672 ck_attention_vec_dump_tensor(name, layer_id, query_id, probs, (size_t) kv_tokens);
673 snprintf(name, sizeof(name), "kqv_out_h%d_q%d", head_id, query_id);
674 ck_attention_vec_dump_tensor(name, layer_id, query_id, out_vec, (size_t) head_dim);
675 if (v_cols && ck_attention_vec_dump_vcols_enabled()) {
676 snprintf(name, sizeof(name), "vcols_h%d_q%d", head_id, query_id);
677 ck_attention_vec_dump_tensor(name, layer_id, query_id, v_cols, (size_t) kv_tokens * (size_t) head_dim);
678 }
679}
static void ck_attention_vec_dump_tensor(const char *name, int layer_id, int query_id, const float *data, size_t elem_count)
static void ck_attention_trace_query(const char *tag, int layer_id, int head_id, int query_id, int value)
static int ck_attention_vec_dump_vcols_enabled(void)

References ck_attention_trace_query(), ck_attention_vec_dump_should_emit(), ck_attention_vec_dump_tensor(), and ck_attention_vec_dump_vcols_enabled().

Referenced by attention_forward_head_major_gqa_flash_impl(), attention_forward_head_major_gqa_unfused_f16_strict(), attention_query_full_exact_regular(), attention_query_full_ggml_regular(), ck_attention_llama_regular_impl(), and ck_attention_vec_dump_exact_query().

◆ ck_attention_vec_dump_should_emit()

static int ck_attention_vec_dump_should_emit ( int  layer_id,
int  head_id,
int  query_id 
)
static

Definition at line 523 of file attention_kernels.c.

524{
526 return 0;
527 }
528 int want_layer = -1;
529 int want_head = -1;
530 int want_query = -1;
531 if (!ck_attention_vec_dump_parse_env_int("CK_STRICT_ATTN_DUMP_LAYER", &want_layer)) {
532 return 0;
533 }
534 const int have_head = ck_attention_vec_dump_parse_env_int("CK_STRICT_ATTN_DUMP_HEAD", &want_head);
535 const int have_query = ck_attention_vec_dump_parse_env_int("CK_STRICT_ATTN_DUMP_QUERY", &want_query);
536 const int trace_target = layer_id == want_layer &&
537 (!have_head || head_id == want_head) &&
538 (!have_query || query_id == want_query);
539 if (layer_id != want_layer) {
540 return 0;
541 }
542 if (have_head && head_id != want_head) {
543 return 0;
544 }
545 if (have_query && query_id != want_query) {
546 return 0;
547 }
548 if (trace_target) {
549 ck_attention_trace_query("vec_dump_should_emit", layer_id, head_id, query_id, 1);
550 }
551 return 1;
552}
static int ck_attention_vec_dump_parse_env_int(const char *name, int *out)

References ck_attention_trace_query(), ck_attention_vec_dump_enabled(), and ck_attention_vec_dump_parse_env_int().

Referenced by attention_forward_head_major_gqa_flash_impl(), attention_query_full_exact_regular(), attention_query_full_ggml_regular(), ck_attention_llama_regular_impl(), ck_attention_vec_dump_exact_query(), and ck_attention_vec_dump_selected_query().

◆ ck_attention_vec_dump_tensor()

static void ck_attention_vec_dump_tensor ( const char *  name,
int  layer_id,
int  query_id,
const float *  data,
size_t  elem_count 
)
static

Definition at line 561 of file attention_kernels.c.

566{
567 const char *dir = getenv("CK_PARITY_DIR");
568 if (!dir || !dir[0] || !name || !name[0] || !data || elem_count == 0) {
569 return;
570 }
571
572 char path[4096];
573 snprintf(path, sizeof(path), "%s/%s", dir, "strict_internal.bin");
574 FILE *f = fopen(path, "ab");
575 if (!f) {
576 return;
577 }
578
579 ck_attention_vec_dump_header_t h;
580 memset(&h, 0, sizeof(h));
583 h.layer_id = layer_id;
584 strncpy(h.op_name, name, sizeof(h.op_name) - 1);
585 h.dtype = 0u;
586 h.rank = 1u;
587 h.shape[0] = (int64_t) elem_count;
588 h.elem_count = (uint32_t) elem_count;
589 h.token_id = query_id;
590
591 fwrite(&h, sizeof(h), 1, f);
592 fwrite(data, sizeof(float), elem_count, f);
593 fclose(f);
594}
static const char ck_attention_vec_dump_magic[8]
static const uint32_t ck_attention_vec_dump_version

References ck_attention_vec_dump_magic, and ck_attention_vec_dump_version.

Referenced by ck_attention_vec_dump_selected_query().

◆ ck_attention_vec_dump_vcols_enabled()

static int ck_attention_vec_dump_vcols_enabled ( void  )
static

Definition at line 481 of file attention_kernels.c.

482{
483 const char *v = getenv("CK_STRICT_ATTN_DUMP_VCOLS");
484 return v && v[0] && strcmp(v, "0") != 0;
485}

Referenced by ck_attention_vec_dump_selected_query().

◆ ck_bf16_dot_contract()

static float ck_bf16_dot_contract ( const float *  a,
const float *  b,
int  count 
)
static

Definition at line 4564 of file attention_kernels.c.

4565{
4566#if defined(__AVX512BF16__)
4567 __m512 acc = _mm512_setzero_ps();
4568 int i = 0;
4569 for (; i + 32 <= count; i += 32) {
4570 const __m512bh av = _mm512_cvtne2ps_pbh(_mm512_loadu_ps(a + i + 16), _mm512_loadu_ps(a + i));
4571 const __m512bh bv = _mm512_cvtne2ps_pbh(_mm512_loadu_ps(b + i + 16), _mm512_loadu_ps(b + i));
4572 acc = _mm512_dpbf16_ps(acc, av, bv);
4573 }
4574 float sum = _mm512_reduce_add_ps(acc);
4575 for (; i < count; ++i) {
4576 const float av = bf16_to_float(float_to_bf16(a[i]));
4577 const float bv = bf16_to_float(float_to_bf16(b[i]));
4578 sum += av * bv;
4579 }
4580 return sum;
4581#else
4582 float sum = 0.0f;
4583 for (int i = 0; i < count; ++i) {
4584 const float av = bf16_to_float(float_to_bf16(a[i]));
4585 const float bv = bf16_to_float(float_to_bf16(b[i]));
4586 sum += av * bv;
4587 }
4588 return sum;
4589#endif
4590}

References bf16_to_float(), count, and float_to_bf16().

Referenced by ck_attention_full_bf16_sdpa_tiled_range().

◆ ck_ggml_vec_dot_f32_contig()

static float ck_ggml_vec_dot_f32_contig ( const float *  x,
const float *  y,
int  n 
)
static

Definition at line 1090 of file attention_kernels.c.

1093{
1094 // Keep this a literal port of ggml_vec_dot_f32 so strict parity can match
1095 // llama.cpp's CPU attention path instead of merely approximating it.
1096#if defined(__AVX__)
1097 float sumf = 0.0f;
1098 const int np = (n & ~31);
1099 __m256 sum[4] = {
1100 _mm256_setzero_ps(),
1101 _mm256_setzero_ps(),
1102 _mm256_setzero_ps(),
1103 _mm256_setzero_ps(),
1104 };
1105
1106 for (int i = 0; i < np; i += 32) {
1107 for (int j = 0; j < 4; ++j) {
1108 const __m256 ax = _mm256_loadu_ps(x + i + j * 8);
1109 const __m256 ay = _mm256_loadu_ps(y + i + j * 8);
1110#if defined(__FMA__)
1111 sum[j] = _mm256_fmadd_ps(ax, ay, sum[j]);
1112#else
1113 sum[j] = _mm256_add_ps(_mm256_mul_ps(ax, ay), sum[j]);
1114#endif
1115 }
1116 }
1117
1118 sum[0] = _mm256_add_ps(sum[0], sum[2]);
1119 sum[1] = _mm256_add_ps(sum[1], sum[3]);
1120 sum[0] = _mm256_add_ps(sum[0], sum[1]);
1121 const __m128 t0 = _mm_add_ps(_mm256_castps256_ps128(sum[0]),
1122 _mm256_extractf128_ps(sum[0], 1));
1123 const __m128 t1 = _mm_hadd_ps(t0, t0);
1124 sumf = _mm_cvtss_f32(_mm_hadd_ps(t1, t1));
1125
1126 for (int i = np; i < n; ++i) {
1127 sumf += x[i] * y[i];
1128 }
1129 return sumf;
1130#elif defined(__SSE2__)
1131 float sumf = 0.0f;
1132 const int np = (n & ~15);
1133 __m128 sum[4] = {
1134 _mm_setzero_ps(),
1135 _mm_setzero_ps(),
1136 _mm_setzero_ps(),
1137 _mm_setzero_ps(),
1138 };
1139
1140 for (int i = 0; i < np; i += 16) {
1141 for (int j = 0; j < 4; ++j) {
1142 const __m128 ax = _mm_loadu_ps(x + i + j * 4);
1143 const __m128 ay = _mm_loadu_ps(y + i + j * 4);
1144#if defined(__FMA__)
1145 sum[j] = _mm_fmadd_ps(ax, ay, sum[j]);
1146#else
1147 sum[j] = _mm_add_ps(_mm_mul_ps(ax, ay), sum[j]);
1148#endif
1149 }
1150 }
1151
1152 sum[0] = _mm_add_ps(sum[0], sum[2]);
1153 sum[1] = _mm_add_ps(sum[1], sum[3]);
1154 sum[0] = _mm_add_ps(sum[0], sum[1]);
1155#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__)
1156 sum[0] = _mm_add_ps(sum[0], _mm_movehl_ps(sum[0], sum[0]));
1157 sum[0] = _mm_add_ss(sum[0], _mm_movehdup_ps(sum[0]));
1158#else
1159 __m128 tmp = _mm_shuffle_ps(sum[0], sum[0], _MM_SHUFFLE(2, 3, 0, 1));
1160 sum[0] = _mm_add_ps(sum[0], tmp);
1161 tmp = _mm_movehl_ps(tmp, sum[0]);
1162 sum[0] = _mm_add_ss(sum[0], tmp);
1163#endif
1164 sumf = _mm_cvtss_f32(sum[0]);
1165
1166 for (int i = np; i < n; ++i) {
1167 sumf += x[i] * y[i];
1168 }
1169 return sumf;
1170#else
1171 double sumf = 0.0;
1172 for (int i = 0; i < n; ++i) {
1173 sumf += (double) (x[i] * y[i]);
1174 }
1175 return (float) sumf;
1176#endif
1177}

Referenced by attention_forward_head_major_gqa_flash_impl(), and attention_query_full_ggml_regular().

◆ ck_ggml_vec_soft_max_row()

static double ck_ggml_vec_soft_max_row ( int  n,
float *  y,
const float *  x,
float  max 
)
static

Definition at line 1278 of file attention_kernels.c.

1282{
1283 int i = 0;
1284 double sum = 0.0;
1285
1286#if defined(__AVX512F__) && defined(__AVX512DQ__)
1287 for (; i + 15 < n; i += 16) {
1288 const __m512 val = ck_ggml_v_expf512(
1289 _mm512_sub_ps(_mm512_loadu_ps(x + i), _mm512_set1_ps(max)));
1290 _mm512_storeu_ps(y + i, val);
1291 sum += (double) _mm512_reduce_add_ps(val);
1292 }
1293#elif defined(__AVX2__) && defined(__FMA__)
1294 for (; i + 7 < n; i += 8) {
1295 const __m256 val = ck_ggml_v_expf256(
1296 _mm256_sub_ps(_mm256_loadu_ps(x + i), _mm256_set1_ps(max)));
1297 _mm256_storeu_ps(y + i, val);
1298 __m128 val2 = _mm_add_ps(_mm256_extractf128_ps(val, 1),
1299 _mm256_castps256_ps128(val));
1300 val2 = _mm_add_ps(val2, _mm_movehl_ps(val2, val2));
1301 val2 = _mm_add_ss(val2, _mm_movehdup_ps(val2));
1302 sum += (double) _mm_cvtss_f32(val2);
1303 }
1304#elif defined(__SSE2__)
1305 for (; i + 3 < n; i += 4) {
1306 const __m128 val = ck_ggml_v_expf128(
1307 _mm_sub_ps(_mm_loadu_ps(x + i), _mm_set1_ps(max)));
1308 _mm_storeu_ps(y + i, val);
1309#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__)
1310 __m128 acc = _mm_add_ps(val, _mm_movehl_ps(val, val));
1311 acc = _mm_add_ss(acc, _mm_movehdup_ps(acc));
1312#else
1313 __m128 tmp = _mm_shuffle_ps(val, val, _MM_SHUFFLE(2, 3, 0, 1));
1314 __m128 acc = _mm_add_ps(val, tmp);
1315 tmp = _mm_movehl_ps(tmp, acc);
1316 acc = _mm_add_ss(acc, tmp);
1317#endif
1318 sum += (double) _mm_cvtss_f32(acc);
1319 }
1320#endif
1321
1322 for (; i < n; ++i) {
1323 const float val = expf(x[i] - max);
1324 y[i] = val;
1325 sum += (double) val;
1326 }
1327
1328 return sum;
1329}

Referenced by attention_forward_head_major_gqa_flash_impl(), attention_forward_head_major_gqa_unfused_f16_strict(), attention_query_full_ggml_regular(), ck_attention_f16_prefill_gqa_reuse_work(), ck_attention_f16_prefill_qtile64_work(), ck_attention_full_tiled_f16kv_fp32_range(), and ck_attention_llama_regular_query().

◆ ck_llama_kv_pad_256()

static int ck_llama_kv_pad_256 ( int  live_tokens,
int  capacity 
)
inlinestatic

Definition at line 5802 of file attention_kernels.c.

5803{
5804 if (live_tokens <= 0 || capacity < live_tokens) return 0;
5805 int padded = live_tokens < 256 ? 256 : ((live_tokens + 255) / 256) * 256;
5806 return padded < capacity ? padded : capacity;
5807}

Referenced by ck_attention_llama_regular_impl().

◆ ck_llama_regular_dot_f16()

static float ck_llama_regular_dot_f16 ( const float *  a,
const float *  b,
int  count 
)
inlinestatic

Definition at line 5816 of file attention_kernels.c.

5817{
5818 int i = 0;
5819#if defined(__AVX512F__)
5820 __m512 acc[4] = {
5821 _mm512_setzero_ps(), _mm512_setzero_ps(),
5822 _mm512_setzero_ps(), _mm512_setzero_ps()
5823 };
5824 for (; i + 64 <= count; i += 64) {
5825 for (int lane = 0; lane < 4; ++lane) {
5826 acc[lane] = _mm512_fmadd_ps(
5827 ck_llama_regular_round_f16x16(_mm512_loadu_ps(a + i + lane * 16)),
5828 ck_llama_regular_round_f16x16(_mm512_loadu_ps(b + i + lane * 16)),
5829 acc[lane]);
5830 }
5831 }
5832 acc[0] = _mm512_add_ps(acc[0], acc[2]);
5833 acc[1] = _mm512_add_ps(acc[1], acc[3]);
5834 float sum = _mm512_reduce_add_ps(_mm512_add_ps(acc[0], acc[1]));
5835#elif defined(__AVX__)
5836 __m256 acc[4] = {
5837 _mm256_setzero_ps(), _mm256_setzero_ps(),
5838 _mm256_setzero_ps(), _mm256_setzero_ps()
5839 };
5840 for (; i + 32 <= count; i += 32) {
5841 for (int lane = 0; lane < 4; ++lane) {
5842#if defined(__FMA__)
5843 acc[lane] = _mm256_fmadd_ps(
5844 _mm256_cvtph_ps(_mm256_cvtps_ph(
5845 _mm256_loadu_ps(a + i + lane * 8), _MM_FROUND_TO_NEAREST_INT)),
5846 _mm256_cvtph_ps(_mm256_cvtps_ph(
5847 _mm256_loadu_ps(b + i + lane * 8), _MM_FROUND_TO_NEAREST_INT)),
5848 acc[lane]);
5849#else
5850 acc[lane] = _mm256_add_ps(acc[lane], _mm256_mul_ps(
5851 _mm256_cvtph_ps(_mm256_cvtps_ph(
5852 _mm256_loadu_ps(a + i + lane * 8), _MM_FROUND_TO_NEAREST_INT)),
5853 _mm256_cvtph_ps(_mm256_cvtps_ph(
5854 _mm256_loadu_ps(b + i + lane * 8), _MM_FROUND_TO_NEAREST_INT))));
5855#endif
5856 }
5857 }
5858 acc[0] = _mm256_add_ps(acc[0], acc[2]);
5859 acc[1] = _mm256_add_ps(acc[1], acc[3]);
5860 const __m256 merged = _mm256_add_ps(acc[0], acc[1]);
5861 __m128 halves = _mm_add_ps(
5862 _mm256_extractf128_ps(merged, 1), _mm256_castps256_ps128(merged));
5863 halves = _mm_add_ps(halves, _mm_movehl_ps(halves, halves));
5864 halves = _mm_add_ss(halves, _mm_movehdup_ps(halves));
5865 float sum = _mm_cvtss_f32(halves);
5866#else
5867 float sums[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5868 for (; i + 4 <= count; i += 4) {
5869 for (int lane = 0; lane < 4; ++lane) {
5870 const float av = CK_FP16_TO_FP32(CK_FP32_TO_FP16(a[i + lane]));
5871 const float bv = CK_FP16_TO_FP32(CK_FP32_TO_FP16(b[i + lane]));
5872 sums[lane] = fmaf(av, bv, sums[lane]);
5873 }
5874 }
5875 float sum = (sums[0] + sums[2]) + (sums[1] + sums[3]);
5876#endif
5877 for (; i < count; ++i) {
5878 const float av = CK_FP16_TO_FP32(CK_FP32_TO_FP16(a[i]));
5879 const float bv = CK_FP16_TO_FP32(CK_FP32_TO_FP16(b[i]));
5880 sum = fmaf(av, bv, sum);
5881 }
5882 return sum;
5883}

References CK_FP16_TO_FP32, CK_FP32_TO_FP16, and count.

Referenced by ck_attention_llama_regular_query().

◆ ck_llama_regular_gemm_f16()

static float ck_llama_regular_gemm_f16 ( const float *  probability,
const float *  value_column,
int  count 
)
inlinestatic

Definition at line 5885 of file attention_kernels.c.

5887{
5888 int i = 0;
5889#if defined(__AVX512F__)
5890 __m512 acc = _mm512_setzero_ps();
5891 for (; i + 16 <= count; i += 16) {
5892 acc = _mm512_fmadd_ps(
5893 ck_llama_regular_round_f16x16(_mm512_loadu_ps(value_column + i)),
5894 ck_llama_regular_round_f16x16(_mm512_loadu_ps(probability + i)), acc);
5895 }
5896 float sum = _mm512_reduce_add_ps(acc);
5897#elif defined(__AVX__)
5898 __m256 acc = _mm256_setzero_ps();
5899 for (; i + 8 <= count; i += 8) {
5900#if defined(__FMA__)
5901 acc = _mm256_fmadd_ps(
5902 _mm256_cvtph_ps(_mm256_cvtps_ph(
5903 _mm256_loadu_ps(value_column + i), _MM_FROUND_TO_NEAREST_INT)),
5904 _mm256_cvtph_ps(_mm256_cvtps_ph(
5905 _mm256_loadu_ps(probability + i), _MM_FROUND_TO_NEAREST_INT)), acc);
5906#else
5907 acc = _mm256_add_ps(acc, _mm256_mul_ps(
5908 _mm256_cvtph_ps(_mm256_cvtps_ph(
5909 _mm256_loadu_ps(value_column + i), _MM_FROUND_TO_NEAREST_INT)),
5910 _mm256_cvtph_ps(_mm256_cvtps_ph(
5911 _mm256_loadu_ps(probability + i), _MM_FROUND_TO_NEAREST_INT))));
5912#endif
5913 }
5914 __m128 halves = _mm_add_ps(
5915 _mm256_extractf128_ps(acc, 1), _mm256_castps256_ps128(acc));
5916 halves = _mm_add_ps(halves, _mm_movehl_ps(halves, halves));
5917 halves = _mm_add_ss(halves, _mm_movehdup_ps(halves));
5918 float sum = _mm_cvtss_f32(halves);
5919#else
5920 float sum = 0.0f;
5921#endif
5922 for (; i < count; ++i) {
5923 const float value = CK_FP16_TO_FP32(CK_FP32_TO_FP16(value_column[i]));
5924 const float probability_value = CK_FP16_TO_FP32(CK_FP32_TO_FP16(probability[i]));
5925 sum = fmaf(value, probability_value, sum);
5926 }
5927 return sum;
5928}

References CK_FP16_TO_FP32, CK_FP32_TO_FP16, and count.

Referenced by ck_attention_llama_regular_query().

◆ ck_llama_regular_prefill_work()

static void ck_llama_regular_prefill_work ( int  ith,
int  nth,
void *  opaque 
)
static

Definition at line 6052 of file attention_kernels.c.

6053{
6054 ck_llama_regular_prefill_args_t *a =
6055 (ck_llama_regular_prefill_args_t *)opaque;
6056 float *worker_scores = a->scores + (size_t)ith * (size_t)a->padded;
6057 float *worker_scaled =
6058 a->scaled_scores + (size_t)ith * (size_t)a->padded;
6059 const size_t worker_kv_stride =
6060 (size_t)a->kv_stride_tokens * (size_t)a->aligned_head_dim;
6061 const int jobs = a->num_heads * a->num_tokens;
6062 (void)nth;
6063 /* Query rows are independent, but their cost grows with the causal
6064 * prefix. Dynamic claims keep asymmetric workers balanced while each
6065 * worker retains exclusive ownership of its score scratch. */
6066 for (;;) {
6067 const int job = atomic_fetch_add_explicit(
6068 &a->next_job, 1, memory_order_relaxed);
6069 if (job >= jobs) break;
6070 const int head = job / a->num_tokens;
6071 const int query = job - head * a->num_tokens;
6072 const int kv_head =
6073 (int)((long long)head * a->num_kv_heads / a->num_heads);
6075 a->q + ((size_t)head * a->num_tokens + query) * a->aligned_head_dim,
6076 a->k + (size_t)kv_head * worker_kv_stride,
6077 a->value_columns +
6078 (size_t)kv_head * (size_t)a->head_dim * (size_t)a->padded,
6079 a->output +
6080 ((size_t)head * a->num_tokens + query) * a->aligned_head_dim,
6081 worker_scores, worker_scaled, a->num_tokens, a->padded, query,
6082 a->head_dim, a->aligned_head_dim, a->sliding_window, 1);
6083 }
6084}

References ck_attention_llama_regular_query().

Referenced by attention_forward_causal_head_major_gqa_llama_regular_strided_sliding_workspace().

◆ ck_local_fp16_to_fp32_2d()

static void ck_local_fp16_to_fp32_2d ( const uint16_t *  src,
float *  dst,
int  rows,
int  cols,
int  src_stride,
int  dst_stride 
)
inlinestatic

Definition at line 382 of file attention_kernels.c.

388{
389 if (!src || !dst || rows <= 0 || cols <= 0) {
390 return;
391 }
392 for (int r = 0; r < rows; ++r) {
393 ck_local_fp16_to_fp32_row(src + (size_t)r * (size_t)src_stride,
394 dst + (size_t)r * (size_t)dst_stride,
395 cols);
396 }
397}
static void ck_local_fp16_to_fp32_row(const uint16_t *src, float *dst, int n)

References ck_local_fp16_to_fp32_row().

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache().

◆ ck_local_fp16_to_fp32_row()

static void ck_local_fp16_to_fp32_row ( const uint16_t *  src,
float *  dst,
int  n 
)
inlinestatic

Definition at line 372 of file attention_kernels.c.

373{
374 if (!src || !dst || n <= 0) {
375 return;
376 }
377 for (int i = 0; i < n; ++i) {
378 dst[i] = CK_FP16_TO_FP32(src[i]);
379 }
380}

References CK_FP16_TO_FP32.

Referenced by ck_local_fp16_to_fp32_2d().

◆ ck_muse_attention_checked_product()

static size_t ck_muse_attention_checked_product ( size_t  left,
size_t  right,
const char *  label 
)
static

Definition at line 9036 of file attention_kernels.c.

9038{
9039 if (left != 0 && right > SIZE_MAX / left) {
9040 fprintf(stderr,
9041 "HARD KERNEL CONTRACT FAULT: Muse eager attention %s "
9042 "size overflow\n", label);
9043 abort();
9044 }
9045 return left * right;
9046}
const char * left
Definition true_bpe.h:138
const char const char * right
Definition true_bpe.h:139

References left, and right.

Referenced by ck_attention_muse_eager_bf16_storage_impl().

◆ ck_round_fp16_buffer()

static void ck_round_fp16_buffer ( const float *  src,
float *  dst,
size_t  count 
)
static

Definition at line 356 of file attention_kernels.c.

357{
358 size_t i = 0;
359#if defined(__AVX2__) && defined(__F16C__)
360 for (; i + 8 <= count; i += 8) {
361 const __m256 value = _mm256_loadu_ps(src + i);
362 const __m128i half = _mm256_cvtps_ph(
363 value, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
364 _mm256_storeu_ps(dst + i, _mm256_cvtph_ps(half));
365 }
366#endif
367 for (; i < count; ++i) {
368 dst[i] = ck_round_fp16_scalar(src[i]);
369 }
370}

References ck_round_fp16_scalar(), and count.

Referenced by attention_flash_query_causal_exact_prerounded_f16kv(), attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace(), and attention_forward_head_major_gqa_flash_impl().

◆ ck_round_fp16_scalar()

static float ck_round_fp16_scalar ( float  x)
inlinestatic

◆ ck_vec_dot_f32_reverse_strict()

static float ck_vec_dot_f32_reverse_strict ( const float *  x,
const float *  y,
int  n 
)
static

Definition at line 439 of file attention_kernels.c.

442{
443 float sumf = 0.0f;
444 for (int i = n - 1; i >= 0; --i) {
445 volatile float prod = x[i] * y[i];
446 volatile float next = sumf + prod;
447 sumf = next;
448 }
449 return sumf;
450}

◆ ck_vec_dot_f32_strict()

static float ck_vec_dot_f32_strict ( const float *  x,
const float *  y,
int  n 
)
static

Definition at line 413 of file attention_kernels.c.

416{
417 float sumf = 0.0f;
418 for (int i = 0; i < n; ++i) {
419 volatile float prod = x[i] * y[i];
420 volatile float next = sumf + prod;
421 sumf = next;
422 }
423 return sumf;
424}

Referenced by attention_query_full_exact_regular().

◆ ck_vec_dot_f32x_f32_to_f32_via_f64()

static float ck_vec_dot_f32x_f32_to_f32_via_f64 ( const float *  x,
const float *  y,
int  n 
)
static

Definition at line 426 of file attention_kernels.c.

429{
430 double sum = 0.0;
431 for (int i = 0; i < n; ++i) {
432 volatile double prod = (double) x[i] * (double) y[i];
433 volatile double next = sum + prod;
434 sum = next;
435 }
436 return (float) sum;
437}

Referenced by attention_query_full_exact_regular().

◆ ck_vec_max_f32_contig()

static float ck_vec_max_f32_contig ( const float *  x,
int  n 
)
inlinestatic

Definition at line 2900 of file attention_kernels.c.

2901{
2902 float max_val = -INFINITY;
2903 for (int i = 0; i < n; ++i) {
2904 if (x[i] > max_val) {
2905 max_val = x[i];
2906 }
2907 }
2908 return max_val;
2909}

Referenced by attention_forward_head_major_gqa_flash_impl(), attention_forward_head_major_gqa_unfused_f16_strict(), attention_query_full_ggml_regular(), ck_attention_f16_prefill_gqa_reuse_work(), ck_attention_f16_prefill_qtile64_work(), ck_attention_full_tiled_f16kv_fp32_range(), and ck_attention_llama_regular_query().

◆ ck_vec_scale_f32_inplace()

static void ck_vec_scale_f32_inplace ( float *  x,
int  n,
float  scale 
)
inlinestatic

◆ convert_bf16_tensor_to_buf()

static void convert_bf16_tensor_to_buf ( const uint16_t *  src,
float *  dst,
size_t  count 
)
static

Definition at line 321 of file attention_kernels.c.

322{
323 if (!dst || !src) return;
324 bf16_tensor_to_float(src, dst, count);
325}
static void bf16_tensor_to_float(const uint16_t *src, float *dst, size_t count)
Definition bf16_utils.h:250

References bf16_tensor_to_float(), and count.

Referenced by attention_backward_causal_head_major_gqa_bf16(), and attention_forward_causal_head_major_gqa_bf16().

◆ qkv_index()

◆ score_index()

static size_t score_index ( int  h,
int  i,
int  j,
int  aligned_context_window 
)
inlinestatic

Definition at line 1333 of file attention_kernels.c.

1337{
1338 return ((size_t)h * (size_t)aligned_context_window * (size_t)aligned_context_window)
1339 + (size_t)i * (size_t)aligned_context_window
1340 + (size_t)j;
1341}

Referenced by attention_backward_causal_head_major_gqa(), attention_forward_causal_head_major(), attention_forward_causal_head_major_exact(), attention_forward_causal_head_major_gqa(), and attention_forward_causal_head_major_gqa_exact().

Variable Documentation

◆ ck_attention_vec_dump_layer_seq

int ck_attention_vec_dump_layer_seq = 0
static

Definition at line 467 of file attention_kernels.c.

Referenced by ck_attention_vec_dump_next_layer_id().

◆ ck_attention_vec_dump_magic

const char ck_attention_vec_dump_magic[8] = {'C', 'K', 'D', 'M', 'P', '\0', '\0', '\0'}
static

Definition at line 465 of file attention_kernels.c.

465{'C', 'K', 'D', 'M', 'P', '\0', '\0', '\0'};

Referenced by ck_attention_vec_dump_tensor().

◆ ck_attention_vec_dump_version

const uint32_t ck_attention_vec_dump_version = 1u
static

Definition at line 466 of file attention_kernels.c.

Referenced by ck_attention_vec_dump_tensor().