← 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_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)
 
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_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_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)
 
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)
 
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)
 
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_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_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, 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 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 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)
 
float ck_attention_pytorch_sdpa_scale_f32 (int head_dim)
 
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_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 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 2816 of file attention_kernels.c.

◆ CK_GGML_FA_TILE_Q

#define CK_GGML_FA_TILE_Q   64

Definition at line 2814 of file attention_kernels.c.

◆ CK_GGML_FA_TILE_Q_LARGE

#define CK_GGML_FA_TILE_Q_LARGE   336

Definition at line 2815 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 2817 of file attention_kernels.c.

◆ CK_NOINLINE

#define CK_NOINLINE

Definition at line 328 of file attention_kernels.c.

◆ CK_OPTNONE

#define CK_OPTNONE

Definition at line 336 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 1167 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 9175 of file attention_kernels.c.

9190{
9192 d_output, q, k, v, attn_weights,
9193 d_q, d_k, d_v, d_scores,
9194 num_heads, num_heads, // num_kv_heads == num_heads
9195 num_tokens, head_dim, aligned_head_dim, aligned_context_window);
9196}
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 9036 of file attention_kernels.c.

9052{
9053 const float scale = 1.0f / sqrtf((float)head_dim);
9054 int T = num_tokens;
9055 int H = num_heads;
9056 int H_kv = num_kv_heads;
9057 int hd = head_dim;
9058 int ad = aligned_head_dim;
9059 int aw = aligned_context_window;
9060
9061 const size_t d_q_elems = (size_t)H * (size_t)T * (size_t)ad;
9062 const size_t kv_elems = (size_t)H_kv * (size_t)T * (size_t)ad;
9063 /* Zero the aligned outputs so padded lanes never leak garbage to downstream GEMMs. */
9064 for (size_t idx = 0; idx < d_q_elems; ++idx) {
9065 d_q[idx] = 0.0f;
9066 }
9067 for (size_t idx = 0; idx < kv_elems; ++idx) {
9068 d_k[idx] = 0.0f;
9069 d_v[idx] = 0.0f;
9070 }
9071
9072 // Process each query head
9073 for (int h = 0; h < H; ++h) {
9074 // Which KV head does this query head use?
9075 int kv_h = (int)((long long)h * (long long)H_kv / (long long)H);
9076
9077 // ----------------------------------------------------------------
9078 // Step 1: d_weights = d_output @ V^T and d_v += weights^T @ d_output
9079 // ----------------------------------------------------------------
9080 // For each query position i, compute d_weights[i, j] for j <= i
9081 // and accumulate d_v[j] contributions
9082
9083 for (int i = 0; i < T; ++i) {
9084 size_t d_out_base = qkv_index(h, i, 0, T, ad);
9085
9086 for (int j = 0; j <= i; ++j) {
9087 size_t v_base = qkv_index(kv_h, j, 0, T, ad);
9088 size_t w_idx = score_index(h, i, j, aw);
9089 float w = attn_weights[w_idx];
9090
9091 // d_weights[h, i, j] = d_output[h, i, :] @ v[kv_h, j, :]^T
9092 float dot = 0.0f;
9093 for (int dd = 0; dd < hd; ++dd) {
9094 dot += d_output[d_out_base + dd] * v[v_base + dd];
9095 }
9096 d_scores[w_idx] = dot;
9097
9098 // d_v[kv_h, j, :] += weights[h, i, j] * d_output[h, i, :]
9099 for (int dd = 0; dd < hd; ++dd) {
9100 d_v[v_base + dd] += w * d_output[d_out_base + dd];
9101 }
9102 }
9103
9104 // Zero out upper triangle of d_scores
9105 for (int j = i + 1; j < T; ++j) {
9106 d_scores[score_index(h, i, j, aw)] = 0.0f;
9107 }
9108 /* Scores scratch uses aligned_context_window, zero the padded columns. */
9109 for (int j = T; j < aw; ++j) {
9110 d_scores[score_index(h, i, j, aw)] = 0.0f;
9111 }
9112 }
9113
9114 // ----------------------------------------------------------------
9115 // Step 2: Backward through softmax (in-place on d_scores for this head)
9116 // ----------------------------------------------------------------
9117 // d_scores = softmax_backward(d_scores, attn_weights)
9118 // Formula: d_score[i,j] = w[i,j] * (d_w[i,j] - sum_k(w[i,k] * d_w[i,k]))
9119
9120 for (int i = 0; i < T; ++i) {
9121 int base = h * aw * aw + i * aw;
9122
9123 // Compute dot product: sum_j w[i,j] * d_w[i,j]
9124 float dot_product = 0.0f;
9125 for (int j = 0; j <= i; ++j) {
9126 float wt = attn_weights[base + j];
9127 float dw = d_scores[base + j];
9128 dot_product += wt * dw;
9129 }
9130
9131 // Apply softmax backward formula
9132 for (int j = 0; j <= i; ++j) {
9133 float wt = attn_weights[base + j];
9134 float dw = d_scores[base + j];
9135 d_scores[base + j] = wt * (dw - dot_product);
9136 }
9137 }
9138
9139 // ----------------------------------------------------------------
9140 // Step 3: d_q = d_scores @ K * scale
9141 // d_k += d_scores^T @ Q * scale
9142 // ----------------------------------------------------------------
9143
9144 for (int i = 0; i < T; ++i) {
9145 size_t d_q_base = qkv_index(h, i, 0, T, ad);
9146 size_t q_base = qkv_index(h, i, 0, T, ad);
9147
9148 // d_q[h, i, :] = sum_j d_scores[h, i, j] * k[kv_h, j, :] * scale
9149 // d_k[kv_h, j, :] += d_scores[h, i, j] * q[h, i, :] * scale
9150 for (int j = 0; j <= i; ++j) {
9151 size_t k_base = qkv_index(kv_h, j, 0, T, ad);
9152 size_t d_k_base = qkv_index(kv_h, j, 0, T, ad);
9153 float ds = d_scores[score_index(h, i, j, aw)] * scale;
9154
9155 for (int dd = 0; dd < hd; ++dd) {
9156 d_q[d_q_base + dd] += ds * k[k_base + dd];
9157 d_k[d_k_base + dd] += ds * q[q_base + dd];
9158 }
9159 }
9160 }
9161 }
9162}
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 8983 of file attention_kernels.c.

9004{
9005 (void)d_x;
9006 const size_t head_elems = (size_t)num_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
9007 const size_t kv_elems = (size_t)num_kv_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
9008
9009 if (!scratch_d_output || !scratch_q || !scratch_k || !scratch_v) return;
9010
9011 convert_bf16_tensor_to_buf(d_output, scratch_d_output, head_elems);
9012 convert_bf16_tensor_to_buf(q, scratch_q, head_elems);
9013 convert_bf16_tensor_to_buf(k, scratch_k, kv_elems);
9014 convert_bf16_tensor_to_buf(v, scratch_v, kv_elems);
9015
9016 attention_backward_causal_head_major_gqa(scratch_d_output, scratch_q, scratch_k, scratch_v,
9017 attn_weights,
9018 d_q, d_k, d_v, d_scores,
9019 num_heads, num_kv_heads,
9020 num_tokens, head_dim,
9021 aligned_head_dim, aligned_context_window);
9022 /* No free - caller owns scratch buffers */
9023}
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 1941 of file attention_kernels.c.

1949{
1950 // Online softmax:
1951 // m = running max, s = running sum(exp(score - m))
1952 // out = sum(exp(score - m) * v)
1953 float m = -INFINITY;
1954 float s = 0.0f;
1955
1956 for (int d = 0; d < head_dim; ++d) {
1957 out_vec[d] = 0.0f;
1958 }
1959
1960 for (int j = 0; j < kv_tokens; ++j) {
1961 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
1962 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
1963
1964 float dot = 0.0f;
1965 for (int d = 0; d < head_dim; ++d) {
1966 dot += q_vec[d] * k_vec[d];
1967 }
1968 float score = dot * scale;
1969
1970 if (score > m) {
1971 float exp_m = (m == -INFINITY) ? 0.0f : expf(m - score);
1972 s *= exp_m;
1973 for (int d = 0; d < head_dim; ++d) {
1974 out_vec[d] *= exp_m;
1975 }
1976 s += 1.0f;
1977 for (int d = 0; d < head_dim; ++d) {
1978 out_vec[d] += v_vec[d];
1979 }
1980 m = score;
1981 } else {
1982 float e = expf(score - m);
1983 s += e;
1984 for (int d = 0; d < head_dim; ++d) {
1985 out_vec[d] += e * v_vec[d];
1986 }
1987 }
1988 }
1989
1990 float inv_s = 1.0f / s;
1991 for (int d = 0; d < head_dim; ++d) {
1992 out_vec[d] *= inv_s;
1993 }
1994 for (int d = head_dim; d < aligned_head_dim; ++d) {
1995 out_vec[d] = 0.0f;
1996 }
1997}
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 2003 of file attention_kernels.c.

2011{
2012 if (kv_tokens <= 0) {
2013 for (int d = 0; d < aligned_head_dim; ++d) {
2014 out_vec[d] = 0.0f;
2015 }
2016 return;
2017 }
2018
2019 for (int d = 0; d < aligned_head_dim; ++d) {
2020 out_vec[d] = 0.0f;
2021 }
2022
2023 float max_score = -INFINITY;
2024 for (int j = 0; j < kv_tokens; ++j) {
2025 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2026 float dot = 0.0f;
2027 for (int d = 0; d < head_dim; ++d) {
2028 dot += q_vec[d] * k_vec[d];
2029 }
2030 float score = dot * scale;
2031 if (score > max_score) {
2032 max_score = score;
2033 }
2034 }
2035
2036 float sum = 0.0f;
2037 for (int j = 0; j < kv_tokens; ++j) {
2038 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2039 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
2040 float dot = 0.0f;
2041 for (int d = 0; d < head_dim; ++d) {
2042 dot += q_vec[d] * k_vec[d];
2043 }
2044 float score = dot * scale;
2045 float w = expf(score - max_score);
2046 sum += w;
2047 for (int d = 0; d < head_dim; ++d) {
2048 out_vec[d] += w * v_vec[d];
2049 }
2050 }
2051
2052 if (sum > 0.0f) {
2053 float inv_sum = 1.0f / sum;
2054 for (int d = 0; d < head_dim; ++d) {
2055 out_vec[d] *= inv_sum;
2056 }
2057 } else {
2058 for (int d = 0; d < head_dim; ++d) {
2059 out_vec[d] = 0.0f;
2060 }
2061 }
2062 for (int d = head_dim; d < aligned_head_dim; ++d) {
2063 out_vec[d] = 0.0f;
2064 }
2065}

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 2119 of file attention_kernels.c.

2127{
2128 if (kv_tokens <= 0) {
2129 for (int d = 0; d < aligned_head_dim; ++d) {
2130 out_vec[d] = 0.0f;
2131 }
2132 return;
2133 }
2134
2135 for (int d = 0; d < aligned_head_dim; ++d) {
2136 out_vec[d] = 0.0f;
2137 }
2138
2139 // Mirror llama.cpp GGML flash-attention more closely:
2140 // - Q is converted through FP16 before the KQ dot
2141 // - V accumulation is rounded through FP16 at each update
2142 // - the softmax accumulator uses the online max/sum form
2143 float sum = 0.0f;
2144 float max_score = -INFINITY;
2145 for (int j = 0; j < kv_tokens; ++j) {
2146 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2147 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
2148 float dot = 0.0f;
2149 for (int d = 0; d < head_dim; ++d) {
2150 dot += ck_round_fp16_scalar(q_vec[d]) * ck_round_fp16_scalar(k_vec[d]);
2151 }
2152 float score = dot * scale;
2153
2154 const float prev_max = max_score;
2155 float max_scale = 1.0f;
2156 float value_scale = 1.0f;
2157
2158 if (score > max_score) {
2159 max_score = score;
2160 max_scale = isfinite(prev_max) ? expf(prev_max - max_score) : 0.0f;
2161 for (int d = 0; d < head_dim; ++d) {
2162 out_vec[d] = ck_round_fp16_scalar(out_vec[d] * max_scale);
2163 }
2164 } else {
2165 value_scale = expf(score - max_score);
2166 }
2167
2168 for (int d = 0; d < head_dim; ++d) {
2169 const float v_rounded = ck_round_fp16_scalar(v_vec[d]);
2170 const float updated = out_vec[d] + value_scale * v_rounded;
2171 out_vec[d] = ck_round_fp16_scalar(updated);
2172 }
2173
2174 sum = sum * max_scale + value_scale;
2175 }
2176
2177 if (sum > 0.0f) {
2178 float inv_sum = 1.0f / sum;
2179 for (int d = 0; d < head_dim; ++d) {
2180 out_vec[d] *= inv_sum;
2181 }
2182 } else {
2183 for (int d = 0; d < head_dim; ++d) {
2184 out_vec[d] = 0.0f;
2185 }
2186 }
2187 for (int d = head_dim; d < aligned_head_dim; ++d) {
2188 out_vec[d] = 0.0f;
2189 }
2190}
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 2194 of file attention_kernels.c.

2198{
2199 if (kv_tokens <= 0) {
2200 memset(out_vec, 0, (size_t)aligned_head_dim * sizeof(float));
2201 return;
2202 }
2203
2204 float *q_rounded = (float *)alloca((size_t)head_dim * sizeof(float));
2205 ck_round_fp16_buffer(q_vec, q_rounded, (size_t)head_dim);
2206 memset(out_vec, 0, (size_t)aligned_head_dim * sizeof(float));
2207
2208 float sum = 0.0f;
2209 float max_score = -INFINITY;
2210 for (int j = 0; j < kv_tokens; ++j) {
2211 const float *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
2212 const float *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
2213 float dot = 0.0f;
2214 for (int d = 0; d < head_dim; ++d) {
2215 dot += q_rounded[d] * k_vec[d];
2216 }
2217 const float score = dot * scale;
2218 const float prev_max = max_score;
2219 float max_scale = 1.0f;
2220 float value_scale = 1.0f;
2221 if (score > max_score) {
2222 max_score = score;
2223 max_scale = isfinite(prev_max) ? expf(prev_max - max_score) : 0.0f;
2224 for (int d = 0; d < head_dim; ++d) {
2225 out_vec[d] = ck_round_fp16_scalar(out_vec[d] * max_scale);
2226 }
2227 } else {
2228 value_scale = expf(score - max_score);
2229 }
2230 for (int d = 0; d < head_dim; ++d) {
2231 const float updated = out_vec[d] + value_scale * v_vec[d];
2232 out_vec[d] = ck_round_fp16_scalar(updated);
2233 }
2234 sum = sum * max_scale + value_scale;
2235 }
2236
2237 if (sum > 0.0f) {
2238 const float inv_sum = 1.0f / sum;
2239 for (int d = 0; d < head_dim; ++d) {
2240 out_vec[d] *= inv_sum;
2241 }
2242 } else {
2243 memset(out_vec, 0, (size_t)head_dim * sizeof(float));
2244 }
2245}
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 1281 of file attention_kernels.c.

1291{
1292 const float scale = 1.0f / sqrtf((float)head_dim);
1293
1294 // Phase 1: compute scaled dot-product scores Q·K^T / sqrt(d_k),
1295 // lower triangle only (j <= i).
1296 for (int h = 0; h < num_heads; ++h) {
1297 for (int i = 0; i < num_tokens; ++i) {
1298 for (int j = 0; j <= i; ++j) {
1299 float dot = 0.0f;
1300 size_t base_q = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1301 size_t base_k = qkv_index(h, j, 0, num_tokens, aligned_head_dim);
1302
1303 for (int d = 0; d < head_dim; ++d) {
1304 dot += q[base_q + d] * k[base_k + d];
1305 }
1306
1307 scores[score_index(h, i, j, aligned_context_window)] = dot * scale;
1308 }
1309
1310 // Ensure upper triangle is zeroed so there are no stale values
1311 // before the softmax kernel runs.
1312 for (int j = i + 1; j < num_tokens; ++j) {
1313 scores[score_index(h, i, j, aligned_context_window)] = 0.0f;
1314 }
1315 }
1316 }
1317
1318 // Phase 2: apply causal row-wise softmax in-place over j <= i.
1320 num_heads,
1321 num_tokens,
1322 aligned_context_window);
1323
1324 // Phase 3: attention weights · V.
1325 for (int h = 0; h < num_heads; ++h) {
1326 for (int i = 0; i < num_tokens; ++i) {
1327 size_t out_base = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1328
1329 // Zero the full aligned head slice so padded dims stay clean.
1330 for (int d = 0; d < aligned_head_dim; ++d) {
1331 output[out_base + d] = 0.0f;
1332 }
1333
1334 // Weighted sum over causal positions.
1335 for (int j = 0; j <= i; ++j) {
1336 float w = scores[score_index(h, i, j, aligned_context_window)];
1337 size_t v_base = qkv_index(h, j, 0, num_tokens, aligned_head_dim);
1338
1339 for (int d = 0; d < head_dim; ++d) {
1340 output[out_base + d] += w * v[v_base + d];
1341 }
1342 }
1343 }
1344 }
1345}
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 1357 of file attention_kernels.c.

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

1446{
1447 const float scale = 1.0f / sqrtf((float)head_dim);
1448
1449 for (int h = 0; h < num_heads; ++h) {
1450 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
1451 for (int i = 0; i < num_tokens; ++i) {
1452 for (int j = 0; j <= i; ++j) {
1453 float dot = 0.0f;
1454 size_t base_q = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1455 size_t base_k = qkv_index(kv_head, j, 0, num_tokens, aligned_head_dim);
1456
1457 for (int d = 0; d < head_dim; ++d) {
1458 dot += q[base_q + d] * k[base_k + d];
1459 }
1460
1461 scores[score_index(h, i, j, aligned_context_window)] = dot * scale;
1462 }
1463
1464 for (int j = i + 1; j < num_tokens; ++j) {
1465 scores[score_index(h, i, j, aligned_context_window)] = 0.0f;
1466 }
1467 }
1468 }
1469
1471 num_heads,
1472 num_tokens,
1473 aligned_context_window);
1474
1475 for (int h = 0; h < num_heads; ++h) {
1476 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
1477 for (int i = 0; i < num_tokens; ++i) {
1478 size_t out_base = qkv_index(h, i, 0, num_tokens, aligned_head_dim);
1479 for (int d = 0; d < aligned_head_dim; ++d) {
1480 output[out_base + d] = 0.0f;
1481 }
1482
1483 for (int j = 0; j <= i; ++j) {
1484 float w = scores[score_index(h, i, j, aligned_context_window)];
1485 size_t v_base = qkv_index(kv_head, j, 0, num_tokens, aligned_head_dim);
1486
1487 for (int d = 0; d < head_dim; ++d) {
1488 output[out_base + d] += w * v[v_base + d];
1489 }
1490 }
1491 }
1492 }
1493}

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 1577 of file attention_kernels.c.

1591{
1592 const size_t q_elems = (size_t)num_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
1593 const size_t kv_elems = (size_t)num_kv_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
1594
1595 if (!scratch_q || !scratch_k || !scratch_v) return;
1596
1597 convert_bf16_tensor_to_buf(q, scratch_q, q_elems);
1598 convert_bf16_tensor_to_buf(k, scratch_k, kv_elems);
1599 convert_bf16_tensor_to_buf(v, scratch_v, kv_elems);
1600
1601 // Use exact version to avoid fast exp approximation error accumulating
1602 // with BF16 precision loss.
1603 attention_forward_causal_head_major_gqa_exact(scratch_q, scratch_k, scratch_v,
1604 scores, output,
1605 num_heads, num_kv_heads,
1606 num_tokens, head_dim,
1607 aligned_head_dim, aligned_context_window);
1608 /* No free - caller owns scratch buffers */
1609}
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 1505 of file attention_kernels.c.

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

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 4370 of file attention_kernels.c.

4379{
4381 num_heads, num_kv_heads,
4382 num_tokens, head_dim,
4383 aligned_head_dim,
4384 /*kv_stride_tokens=*/num_tokens,
4385 /*causal=*/1,
4386 /*round_full_kv_fp16=*/0,
4387 /*output_token_major=*/0,
4388 1.0f / sqrtf((float)head_dim));
4389}
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 4422 of file attention_kernels.c.

4432{
4434 num_heads, num_kv_heads,
4435 num_tokens, head_dim,
4436 aligned_head_dim,
4437 kv_stride_tokens,
4438 /*causal=*/1,
4439 /*round_full_kv_fp16=*/0,
4440 /*output_token_major=*/0,
4441 1.0f / sqrtf((float)head_dim));
4442}

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 5343 of file attention_kernels.c.

5347{
5348 size_t elements = 0;
5349 if (num_kv_heads > 0 && kv_stride_tokens > 0 && aligned_head_dim > 0 &&
5350 (size_t)num_kv_heads <= SIZE_MAX / (size_t)kv_stride_tokens) {
5351 const size_t rows = (size_t)num_kv_heads * (size_t)kv_stride_tokens;
5352 if (rows <= SIZE_MAX / (size_t)aligned_head_dim) {
5353 elements = rows * (size_t)aligned_head_dim;
5354 }
5355 }
5356 float *workspace = elements > 0 && elements <= SIZE_MAX / (2 * sizeof(float))
5357 ? (float *)malloc(2 * elements * sizeof(float))
5358 : NULL;
5359 if (!workspace) {
5361 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5362 head_dim, aligned_head_dim, kv_stride_tokens);
5363 return;
5364 }
5366 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5367 aligned_head_dim, kv_stride_tokens, workspace,
5368 2 * elements * sizeof(float));
5369 free(workspace);
5370}
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 5287 of file attention_kernels.c.

5291{
5292 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
5293 num_tokens <= 0 || kv_stride_tokens < num_tokens) {
5294 return;
5295 }
5296 ck_attention_causal_f16kv_args_t args = {
5297 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5298 head_dim, aligned_head_dim, kv_stride_tokens, 0,
5299 };
5300 ck_attention_causal_f16kv_work(0, 1, &args);
5301}
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 5303 of file attention_kernels.c.

5308{
5309 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
5310 num_tokens <= 0 || kv_stride_tokens < num_tokens) {
5311 return;
5312 }
5313 size_t elements = 0;
5314 if ((size_t)num_kv_heads <= SIZE_MAX / (size_t)kv_stride_tokens) {
5315 const size_t rows = (size_t)num_kv_heads * (size_t)kv_stride_tokens;
5316 if (rows <= SIZE_MAX / (size_t)aligned_head_dim) {
5317 elements = rows * (size_t)aligned_head_dim;
5318 }
5319 }
5320 if (elements == 0 || elements > SIZE_MAX / (2 * sizeof(float)) ||
5321 !rounded_kv || rounded_kv_bytes < 2 * elements * sizeof(float)) {
5322 fprintf(stderr,
5323 "HARD KERNEL CONTRACT FAULT: FP16-KV attention workspace is too small\n");
5324 abort();
5325 }
5326 ck_round_fp16_buffer(k, rounded_kv, elements);
5327 ck_round_fp16_buffer(v, rounded_kv + elements, elements);
5328 ck_attention_causal_f16kv_args_t args = {
5329 q, rounded_kv, rounded_kv + elements, output,
5330 num_heads, num_kv_heads, num_tokens,
5331 head_dim, aligned_head_dim, kv_stride_tokens, 1,
5332 };
5333 ck_threadpool_t *pool = ck_threadpool_global();
5334 const int workers = pool ? ck_threadpool_n_threads(pool) : 1;
5335 const int active = workers < num_heads ? workers : num_heads;
5336 if (active > 1) {
5338 } else {
5339 ck_attention_causal_f16kv_work(0, 1, &args);
5340 }
5341}
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 5024 of file attention_kernels.c.

5034{
5035 (void)head_dim;
5037 num_heads, num_kv_heads,
5038 num_tokens, head_dim,
5039 aligned_head_dim,
5040 kv_stride_tokens,
5041 /*causal=*/1,
5042 /*round_full_kv_fp16=*/0,
5043 /*output_token_major=*/0,
5044 1.0f);
5045}

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 5047 of file attention_kernels.c.

5058{
5060 num_heads, num_kv_heads,
5061 num_tokens, head_dim,
5062 aligned_head_dim,
5063 kv_stride_tokens,
5064 /*causal=*/1,
5065 /*round_full_kv_fp16=*/0,
5066 /*output_token_major=*/1,
5067 1.0f);
5068}

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 4444 of file attention_kernels.c.

4455{
4457 num_heads, num_kv_heads,
4458 num_tokens, head_dim,
4459 aligned_head_dim,
4460 kv_stride_tokens,
4461 /*causal=*/1,
4462 /*round_full_kv_fp16=*/0,
4463 /*output_token_major=*/1,
4464 1.0f / sqrtf((float)head_dim));
4465}

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 5960 of file attention_kernels.c.

5967{
5969 q, k, v, output, num_heads, num_kv_heads, num_tokens, num_tokens,
5970 head_dim, aligned_head_dim, kv_stride_tokens, sliding_window,
5971 scores, scores_bytes, value_columns, value_columns_bytes,
5972 scaled_scores, scaled_scores_bytes, 1);
5973}
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)

References ck_attention_llama_regular_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 8673 of file attention_kernels.c.

8686{
8687 if (q_tokens >= CK_GGML_FA_TILE_Q) {
8689 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
8690 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
8691 NULL, 0);
8692 }
8693 if (num_heads <= 0 || aligned_head_dim <= 0 ||
8694 (size_t) num_heads > SIZE_MAX / (size_t) aligned_head_dim) {
8696 }
8697 const size_t token_elements = (size_t) num_heads * (size_t) aligned_head_dim;
8698 if (token_elements > SIZE_MAX / (2 * sizeof(float))) {
8700 }
8701 const size_t workspace_bytes = 2 * token_elements * sizeof(float);
8702 float *workspace = (float *) malloc(workspace_bytes);
8703 if (!workspace) return CK_ATTENTION_STATUS_INVALID_ARGUMENT;
8704 const ck_attention_status_t status =
8706 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
8707 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
8708 workspace, workspace_bytes);
8709 free(workspace);
8710 return status;
8711}
#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 8596 of file attention_kernels.c.

8611{
8612 if (!q || !k_cache || !v_cache || !output ||
8613 num_heads <= 0 || num_kv_heads <= 0 || q_tokens <= 0 ||
8614 past_tokens < 0 || past_tokens + q_tokens > cache_capacity ||
8615 head_dim <= 0 || aligned_head_dim < head_dim) {
8617 }
8618 if (reduction != CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA) {
8620 }
8621
8622 if (q_tokens >= CK_GGML_FA_TILE_Q) {
8623 ck_attention_f16_prefill_qtile64_args_t args = {
8624 .q = q, .k_cache = k_cache, .v_cache = v_cache, .output = output,
8625 .num_heads = num_heads, .num_kv_heads = num_kv_heads,
8626 .q_tokens = q_tokens, .past_tokens = past_tokens,
8627 .cache_capacity = cache_capacity, .head_dim = head_dim,
8628 .aligned_head_dim = aligned_head_dim, .cache_is_bf16 = 1,
8629 };
8630 ck_threadpool_t *pool = ck_threadpool_global();
8631 int active = pool ? ck_threadpool_n_threads(pool) : 1;
8632 if (active > num_kv_heads) active = num_kv_heads;
8633 if (pool && active > 1 && ck_threadpool_thread_id(pool) <= 0) {
8635 } else {
8637 }
8638 const size_t count = (size_t)num_heads * (size_t)q_tokens * (size_t)aligned_head_dim;
8639 for (size_t i = 0; i < count; ++i) {
8640 output[i] = bf16_to_float(float_to_bf16(output[i]));
8641 }
8643 }
8644
8645 const size_t token_elems = (size_t)num_heads * (size_t)aligned_head_dim;
8646 if (token_elems > SIZE_MAX / (2 * sizeof(float)) ||
8647 !token_workspace || token_workspace_bytes < 2 * token_elems * sizeof(float)) {
8649 }
8650 float *q_token = token_workspace;
8651 float *out_token = token_workspace + token_elems;
8653 for (int t = 0; t < q_tokens; ++t) {
8654 for (int h = 0; h < num_heads; ++h) {
8655 memcpy(q_token + (size_t)h * (size_t)aligned_head_dim,
8656 q + ((size_t)h * (size_t)q_tokens + (size_t)t) * (size_t)aligned_head_dim,
8657 (size_t)aligned_head_dim * sizeof(float));
8658 }
8660 q_token, k_cache, v_cache, out_token,
8661 num_heads, num_kv_heads, past_tokens + t + 1, cache_capacity,
8662 head_dim, aligned_head_dim, reduction);
8663 if (status != CK_ATTENTION_STATUS_OK) break;
8664 for (int h = 0; h < num_heads; ++h) {
8665 memcpy(output + ((size_t)h * (size_t)q_tokens + (size_t)t) * (size_t)aligned_head_dim,
8666 out_token + (size_t)h * (size_t)aligned_head_dim,
8667 (size_t)aligned_head_dim * sizeof(float));
8668 }
8669 }
8670 return status;
8671}
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

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(), 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 7335 of file attention_kernels.c.

7360{
7361 if (route_num_heads <= 0 || route_num_kv_heads <= 0 ||
7362 route_num_heads % route_num_kv_heads != 0 || route_head_dim <= 0 ||
7363 route_query_tokens <= 0 || route_min_kv_tokens < route_query_tokens ||
7364 route_workers < route_num_kv_heads ||
7365 route_workers % route_num_kv_heads != 0 ||
7366 route_query_tile_size < 16 || route_query_tile_size > 128 ||
7367 route_query_tile_size % 16 != 0 ||
7368 route_concurrent_query_tiles <= 0 ||
7369 route_concurrent_query_tiles > 4) {
7371 }
7372 ck_threadpool_t *pool = ck_threadpool_global();
7373 const int active = pool ? ck_threadpool_n_threads(pool) : 1;
7374 const int kv_tokens = past_tokens + q_tokens;
7376 num_heads == route_num_heads && num_kv_heads == route_num_kv_heads &&
7377 head_dim == route_head_dim && aligned_head_dim == route_head_dim &&
7378 q_tokens == route_query_tokens && kv_tokens >= route_min_kv_tokens &&
7379 active == route_workers) {
7381 q, k_cache, v_cache, output, num_heads, num_kv_heads,
7382 q_tokens, past_tokens, cache_capacity, head_dim, aligned_head_dim,
7383 route_query_tile_size, route_concurrent_query_tiles,
7384 gqa_workspace, gqa_workspace_bytes);
7385 }
7387 q, k_cache, v_cache, output, num_heads, num_kv_heads,
7388 q_tokens, past_tokens, cache_capacity, head_dim, aligned_head_dim,
7389 reduction, token_workspace, token_workspace_bytes);
7390}
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 7641 of file attention_kernels.c.

7654{
7656 q_tokens >= CK_GGML_FA_TILE_Q) {
7658 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7659 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
7660 NULL, 0);
7661 }
7662
7663 if (num_heads <= 0 || aligned_head_dim <= 0 ||
7664 (size_t) num_heads > SIZE_MAX / (size_t) aligned_head_dim) {
7666 }
7667 const size_t token_elements = (size_t) num_heads * (size_t) aligned_head_dim;
7668 if (token_elements > SIZE_MAX / (2 * sizeof(float))) {
7670 }
7671 const size_t workspace_bytes = 2 * token_elements * sizeof(float);
7672 float *workspace = (float *) malloc(workspace_bytes);
7673 if (!workspace) {
7675 }
7676 const ck_attention_status_t status =
7678 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7679 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
7680 workspace, workspace_bytes);
7681 free(workspace);
7682 return status;
7683}

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 7419 of file attention_kernels.c.

7434{
7435 if (!q || !k_cache || !v_cache || !output ||
7436 num_heads <= 0 || num_kv_heads <= 0 || q_tokens <= 0 ||
7437 past_tokens < 0 || past_tokens + q_tokens > cache_capacity ||
7438 head_dim <= 0 || aligned_head_dim < head_dim) {
7440 }
7441
7443 q_tokens < CK_GGML_FA_TILE_Q) {
7445 }
7446
7449 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7450 past_tokens, cache_capacity, head_dim, aligned_head_dim, 0,
7451 (size_t) q_tokens * (size_t) aligned_head_dim,
7452 (size_t) q_tokens * (size_t) aligned_head_dim,
7454 }
7455
7458 reduction != CK_ATTN_REDUCTION_FP32_ONLINE) {
7460 }
7461
7462 const size_t token_elems = (size_t) num_heads * (size_t) aligned_head_dim;
7463 if (token_elems > SIZE_MAX / (2 * sizeof(float))) {
7465 }
7466 const size_t required_bytes = 2 * token_elems * sizeof(float);
7467 if (!token_workspace || token_workspace_bytes < required_bytes) {
7469 }
7470 float *q_token = token_workspace;
7471 float *out_token = token_workspace + token_elems;
7472
7474 for (int t = 0; t < q_tokens; ++t) {
7475 for (int h = 0; h < num_heads; ++h) {
7476 const float *src = q +
7477 ((size_t) h * (size_t) q_tokens + (size_t) t) * (size_t) aligned_head_dim;
7478 memcpy(q_token + (size_t) h * (size_t) aligned_head_dim,
7479 src,
7480 (size_t) aligned_head_dim * sizeof(float));
7481 }
7482
7484 q_token, k_cache, v_cache, out_token,
7485 num_heads, num_kv_heads, past_tokens + t + 1, cache_capacity,
7486 head_dim, aligned_head_dim, reduction);
7487 if (status != CK_ATTENTION_STATUS_OK) {
7488 break;
7489 }
7490
7491 for (int h = 0; h < num_heads; ++h) {
7492 float *dst = output +
7493 ((size_t) h * (size_t) q_tokens + (size_t) t) * (size_t) aligned_head_dim;
7494 memcpy(dst,
7495 out_token + (size_t) h * (size_t) aligned_head_dim,
7496 (size_t) aligned_head_dim * sizeof(float));
7497 }
7498 }
7499
7500 return status;
7501}
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, 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_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 7234 of file attention_kernels.c.

7250{
7251 if (!q || !k_cache || !v_cache || !output || !workspace || num_heads <= 0 ||
7252 num_kv_heads <= 0 || num_heads % num_kv_heads != 0 ||
7253 query_tile_size <= 0 || q_tokens < query_tile_size || past_tokens < 0 ||
7254 past_tokens + q_tokens > cache_capacity || head_dim <= 0 ||
7255 aligned_head_dim < head_dim || query_tile_size < 16 ||
7256 query_tile_size > 128 || query_tile_size % 16 != 0 ||
7257 concurrent_query_tiles <= 0 || concurrent_query_tiles > 4) {
7259 }
7260
7261 ck_threadpool_t *pool = ck_threadpool_global();
7262 const int active = pool ? ck_threadpool_n_threads(pool) : 1;
7263 if (!pool || active < num_kv_heads || active % num_kv_heads != 0 ||
7264 ck_threadpool_thread_id(pool) > 0) {
7266 }
7267 const size_t required_workspace =
7269 num_heads, num_kv_heads, head_dim, active,
7270 query_tile_size, concurrent_query_tiles);
7271 if (required_workspace == 0 || workspace_bytes < required_workspace) {
7273 }
7274 const int lanes = active / num_kv_heads;
7275 const size_t tile_elems =
7276 (size_t) num_kv_heads * (size_t) head_dim * CK_GGML_FA_TILE_KV;
7277 uintptr_t workspace_address = (uintptr_t) workspace;
7278 workspace_address = (workspace_address + 63u) & ~(uintptr_t) 63u;
7279 unsigned char *workspace_base = (unsigned char *) workspace_address;
7280 size_t cursor = 0;
7281 float *shared_k_tiles = (float *) (workspace_base + cursor);
7282 cursor += tile_elems * sizeof(float);
7283 cursor = ck_attention_align64_size(cursor);
7284 float *shared_v_tiles = (float *) (workspace_base + cursor);
7285 cursor += tile_elems * sizeof(float);
7286 cursor = ck_attention_align64_size(cursor);
7287 ck_attention_gqa_team_barrier_t *barriers =
7288 (ck_attention_gqa_team_barrier_t *) (workspace_base + cursor);
7289 cursor += (size_t) num_kv_heads * sizeof(*barriers);
7290 cursor = ck_attention_align64_size(cursor);
7291 unsigned char *worker_workspace = workspace_base + cursor;
7292 const size_t worker_workspace_stride =
7294 num_heads, num_kv_heads, head_dim, active,
7295 query_tile_size, concurrent_query_tiles);
7296 for (int group = 0; group < num_kv_heads; ++group) {
7297 __atomic_store_n(&barriers[group].arrived, 0, __ATOMIC_RELAXED);
7298 __atomic_store_n(&barriers[group].phase, 0, __ATOMIC_RELAXED);
7299 barriers[group].lanes = lanes;
7300 }
7301
7302 ck_attention_f16_prefill_gqa_reuse_args_t args = {
7303 .base = {
7304 .q = q,
7305 .k_cache = k_cache,
7306 .v_cache = v_cache,
7307 .output = output,
7308 .num_heads = num_heads,
7309 .num_kv_heads = num_kv_heads,
7310 .q_tokens = q_tokens,
7311 .past_tokens = past_tokens,
7312 .cache_capacity = cache_capacity,
7313 .head_dim = head_dim,
7314 .aligned_head_dim = aligned_head_dim,
7315 .cache_is_bf16 = 0,
7317 .q_head_stride =
7318 (size_t) q_tokens * (size_t) aligned_head_dim,
7319 .output_head_stride =
7320 (size_t) q_tokens * (size_t) aligned_head_dim,
7321 },
7322 .shared_k_tiles = shared_k_tiles,
7323 .shared_v_tiles = shared_v_tiles,
7324 .barriers = barriers,
7325 .worker_workspace = worker_workspace,
7326 .worker_workspace_stride = worker_workspace_stride,
7327 .query_tile_size = query_tile_size,
7328 .concurrent_query_tiles = concurrent_query_tiles,
7329 };
7331 pool, active, ck_attention_f16_prefill_gqa_reuse_work, &args);
7333}
#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 6716 of file attention_kernels.c.

6723{
6724 const size_t worker_bytes =
6726 num_heads, num_kv_heads, head_dim, workers,
6727 query_tile_size, concurrent_query_tiles);
6728 if (worker_bytes == 0) return 0;
6729 size_t bytes = 63u;
6730 bytes = ck_attention_align64_size(bytes) +
6731 (size_t) num_kv_heads * (size_t) head_dim * CK_GGML_FA_TILE_KV *
6732 sizeof(float);
6733 bytes = ck_attention_align64_size(bytes) +
6734 (size_t) num_kv_heads * CK_GGML_FA_TILE_KV * (size_t) head_dim *
6735 sizeof(float);
6736 bytes = ck_attention_align64_size(bytes) +
6737 (size_t) num_kv_heads * sizeof(ck_attention_gqa_team_barrier_t);
6738 bytes = ck_attention_align64_size(bytes) +
6739 (size_t) workers * worker_bytes;
6740 return bytes;
6741}

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 7392 of file attention_kernels.c.

7405{
7406 if (!q || !k_cache || !v_cache || !output || num_heads <= 0 ||
7407 num_kv_heads <= 0 || q_tokens < CK_GGML_FA_TILE_Q || past_tokens < 0 ||
7408 past_tokens + q_tokens > cache_capacity || head_dim <= 0 ||
7409 aligned_head_dim < head_dim) {
7411 }
7413 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7414 past_tokens, cache_capacity, head_dim, aligned_head_dim, 0,
7415 (size_t) q_tokens * (size_t) aligned_head_dim,
7416 (size_t) q_tokens * (size_t) aligned_head_dim, schedule);
7417}

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_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 8713 of file attention_kernels.c.

8726{
8727 if (!q || !k_cache || !v_cache || !output ||
8728 num_heads <= 0 || num_kv_heads <= 0 ||
8729 num_heads % num_kv_heads != 0 ||
8730 q_tokens <= 0 || past_tokens < 0 ||
8731 past_tokens + q_tokens > cache_capacity ||
8732 head_dim <= 0 || aligned_head_dim < head_dim) {
8734 }
8735 if (reduction != CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA) {
8737 }
8738
8739#if defined(__AVX512F__)
8740 pthread_once(&ck_pytorch_attention_once, ck_bind_pytorch_attention_primitives);
8741 return ck_attention_prefill_bf16_pytorch_math_gqa_full(
8742 q, k_cache, v_cache, output,
8743 num_heads, num_kv_heads, q_tokens, past_tokens, cache_capacity,
8744 head_dim, aligned_head_dim);
8745#else
8747#endif
8748}

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 7616 of file attention_kernels.c.

7633{
7635 q, k_cache, v_cache, output, num_heads, num_kv_heads, q_tokens,
7636 past_tokens, cache_capacity, head_dim, aligned_head_dim, reduction,
7637 token_workspace, token_workspace_bytes, segment_lengths, num_segments,
7639}
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_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 5070 of file attention_kernels.c.

5077{
5079 q, q, q, output, num_heads, num_heads, num_tokens,
5080 head_dim, aligned_head_dim, kv_stride_tokens
5081 );
5082}
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 6089 of file attention_kernels.c.

6100{
6101 if (!q_chunk || !k_cache || !v_cache || !out_chunk) {
6102 return;
6103 }
6104 if (num_heads <= 0 || num_kv_heads <= 0 || q_tokens <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6105 return;
6106 }
6107 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6108 return;
6109 }
6110
6111 const float scale = 1.0f;
6112 const size_t cache_head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6113 const size_t q_head_stride = (size_t)q_tokens * (size_t)aligned_head_dim;
6114
6115 for (int h = 0; h < num_heads; ++h) {
6116 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6117 const float *k_head = k_cache + (size_t)kv_head * cache_head_stride;
6118 const float *v_head = v_cache + (size_t)kv_head * cache_head_stride;
6119 for (int t = 0; t < q_tokens; ++t) {
6120 const float *q_head = q_chunk + (size_t)h * q_head_stride + (size_t)t * (size_t)aligned_head_dim;
6121 float *out_head = out_chunk + (size_t)h * q_head_stride + (size_t)t * (size_t)aligned_head_dim;
6122 attention_flash_decode(out_head,
6123 q_head,
6124 k_head,
6125 v_head,
6126 1,
6127 kv_tokens,
6128 1,
6129 aligned_head_dim,
6130 scale);
6131 }
6132 }
6133}
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 8522 of file attention_kernels.c.

8534{
8535 if (!q_token || !k_cache || !v_cache || !out_token ||
8536 num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 ||
8537 cache_capacity <= 0 || kv_tokens > cache_capacity ||
8538 head_dim <= 0 || aligned_head_dim < head_dim ||
8539 num_heads % num_kv_heads != 0) {
8541 }
8542 if (reduction != CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA) {
8544 }
8545
8546#if defined(__AVX512F__)
8547 pthread_once(&ck_pytorch_attention_once, ck_bind_pytorch_attention_primitives);
8548 return ck_attention_decode_bf16_pytorch_math_gqa(
8549 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
8550 kv_tokens, cache_capacity, head_dim, aligned_head_dim);
8551#else
8552 const float scale = 1.0f / sqrtf((float)head_dim);
8553 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
8554 for (int h = 0; h < num_heads; ++h) {
8555 const int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
8556 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
8557 const uint16_t *k_head = k_cache + (size_t)kv_head * head_stride;
8558 const uint16_t *v_head = v_cache + (size_t)kv_head * head_stride;
8559 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
8560
8561 float maximum = -INFINITY;
8562 for (int token = 0; token < kv_tokens; ++token) {
8563 const uint16_t *k_row = k_head + (size_t)token * (size_t)aligned_head_dim;
8564 float dot = 0.0f;
8565 for (int d = 0; d < head_dim; ++d) {
8566 dot = fmaf(q_head[d], bf16_to_float(k_row[d]), dot);
8567 }
8568 const float score = dot * scale;
8569 if (score > maximum) maximum = score;
8570 }
8571
8572 for (int d = 0; d < aligned_head_dim; ++d) out_head[d] = 0.0f;
8573 float denominator = 0.0f;
8574 for (int token = 0; token < kv_tokens; ++token) {
8575 const uint16_t *k_row = k_head + (size_t)token * (size_t)aligned_head_dim;
8576 const uint16_t *v_row = v_head + (size_t)token * (size_t)aligned_head_dim;
8577 float dot = 0.0f;
8578 for (int d = 0; d < head_dim; ++d) {
8579 dot = fmaf(q_head[d], bf16_to_float(k_row[d]), dot);
8580 }
8581 const float probability = expf(dot * scale - maximum);
8582 denominator += probability;
8583 for (int d = 0; d < head_dim; ++d) {
8584 out_head[d] = fmaf(probability, bf16_to_float(v_row[d]), out_head[d]);
8585 }
8586 }
8587 const float inverse = denominator > 0.0f ? 1.0f / denominator : 0.0f;
8588 for (int d = 0; d < head_dim; ++d) {
8589 out_head[d] = bf16_to_float(float_to_bf16(out_head[d] * inverse));
8590 }
8591 }
8593#endif
8594}
const char * token
Definition tokenizer.h:307

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_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 6002 of file attention_kernels.c.

6012{
6013 if (!q_token || !k_cache || !v_cache || !out_token) {
6014 return;
6015 }
6016 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6017 return;
6018 }
6019 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6020 return;
6021 }
6022
6023 const float scale = 1.0f / sqrtf((float)head_dim);
6024 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6025
6026 for (int h = 0; h < num_heads; ++h) {
6027 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6028 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
6029 const float *k_head = k_cache + (size_t)kv_head * head_stride;
6030 const float *v_head = v_cache + (size_t)kv_head * head_stride;
6031 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
6032
6033 attention_flash_decode(out_head,
6034 q_head,
6035 k_head,
6036 v_head,
6037 1,
6038 kv_tokens,
6039 1,
6040 aligned_head_dim,
6041 scale);
6042 }
6043}

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 8750 of file attention_kernels.c.

8760{
8761 if (!q_token || !k_cache || !v_cache || !out_token) {
8762 return;
8763 }
8764 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
8765 return;
8766 }
8767 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
8768 return;
8769 }
8770
8771 const float scale = 1.0f / sqrtf((float)head_dim);
8772 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
8773 const size_t scratch_elems = (size_t)kv_tokens * (size_t)aligned_head_dim;
8774 const size_t scratch_bytes = scratch_elems * sizeof(float);
8775 const size_t max_stack_bytes = 1024u * 1024u;
8776
8777 if (scratch_bytes * 2u > max_stack_bytes) {
8778 for (int h = 0; h < num_heads; ++h) {
8779 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
8780 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
8781 const uint16_t *k_head = k_cache + (size_t)kv_head * head_stride;
8782 const uint16_t *v_head = v_cache + (size_t)kv_head * head_stride;
8783 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
8784
8785 for (int d = 0; d < aligned_head_dim; ++d) {
8786 out_head[d] = 0.0f;
8787 }
8788
8789 float max_score = -INFINITY;
8790 for (int j = 0; j < kv_tokens; ++j) {
8791 const uint16_t *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
8792 float dot = 0.0f;
8793 for (int d = 0; d < head_dim; ++d) {
8794 dot += q_head[d] * CK_FP16_TO_FP32(k_vec[d]);
8795 }
8796 const float score = dot * scale;
8797 if (score > max_score) {
8798 max_score = score;
8799 }
8800 }
8801
8802 float sum = 0.0f;
8803 for (int j = 0; j < kv_tokens; ++j) {
8804 const uint16_t *k_vec = k_head + (size_t)j * (size_t)aligned_head_dim;
8805 const uint16_t *v_vec = v_head + (size_t)j * (size_t)aligned_head_dim;
8806 float dot = 0.0f;
8807 for (int d = 0; d < head_dim; ++d) {
8808 dot += q_head[d] * CK_FP16_TO_FP32(k_vec[d]);
8809 }
8810 const float w = expf(dot * scale - max_score);
8811 sum += w;
8812 for (int d = 0; d < head_dim; ++d) {
8813 out_head[d] += w * CK_FP16_TO_FP32(v_vec[d]);
8814 }
8815 }
8816
8817 if (sum > 0.0f) {
8818 const float inv_sum = 1.0f / sum;
8819 for (int d = 0; d < head_dim; ++d) {
8820 out_head[d] *= inv_sum;
8821 }
8822 }
8823 for (int d = head_dim; d < aligned_head_dim; ++d) {
8824 out_head[d] = 0.0f;
8825 }
8826 }
8827 return;
8828 }
8829
8830 float *k_head_fp32 = (float *)alloca(scratch_bytes);
8831 float *v_head_fp32 = (float *)alloca(scratch_bytes);
8832
8833 for (int kv_head = 0; kv_head < num_kv_heads; ++kv_head) {
8834 const uint16_t *k_head = k_cache + (size_t)kv_head * head_stride;
8835 const uint16_t *v_head = v_cache + (size_t)kv_head * head_stride;
8836 const int q_begin = (int)((long long)kv_head * (long long)num_heads / (long long)num_kv_heads);
8837 const int q_end = (int)((long long)(kv_head + 1) * (long long)num_heads / (long long)num_kv_heads);
8838
8839 ck_local_fp16_to_fp32_2d(k_head, k_head_fp32, kv_tokens, aligned_head_dim, aligned_head_dim, aligned_head_dim);
8840 ck_local_fp16_to_fp32_2d(v_head, v_head_fp32, kv_tokens, aligned_head_dim, aligned_head_dim, aligned_head_dim);
8841
8842 for (int h = q_begin; h < q_end; ++h) {
8843 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
8844 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
8845
8846 attention_flash_decode(out_head,
8847 q_head,
8848 k_head_fp32,
8849 v_head_fp32,
8850 1,
8851 kv_tokens,
8852 1,
8853 aligned_head_dim,
8854 scale);
8855 }
8856 }
8857}
static void ck_local_fp16_to_fp32_2d(const uint16_t *src, float *dst, int rows, int cols, int src_stride, int dst_stride)
#define CK_FP16_TO_FP32(x)

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 6586 of file attention_kernels.c.

6598{
6599 if (!q_token || !k_cache || !v_cache || !out_token ||
6600 num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 ||
6601 cache_capacity <= 0 || kv_tokens > cache_capacity ||
6602 head_dim <= 0 || aligned_head_dim < head_dim) {
6604 }
6605
6606 switch (reduction) {
6609 q_token, k_cache, v_cache, out_token,
6610 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6611 head_dim, aligned_head_dim);
6613
6615 const int partition_alignment = 256;
6616 const int partition_tokens =
6617 ((kv_tokens + partition_alignment - 1) / partition_alignment) * partition_alignment;
6618 const int split_chunks = partition_tokens >= 512 ? ck_get_num_threads() : 1;
6620 q_token, k_cache, v_cache, out_token,
6621 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6622 head_dim, aligned_head_dim, split_chunks);
6624 }
6625
6628 q_token, k_cache, v_cache, out_token,
6629 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6630 head_dim, aligned_head_dim, 1);
6632
6633 default:
6635 }
6636}
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 6565 of file attention_kernels.c.

6576{
6577 const int partition_alignment = 256;
6578 const int partition_tokens =
6579 ((kv_tokens + partition_alignment - 1) / partition_alignment) * partition_alignment;
6581 q_token, k_cache, v_cache, out_token,
6582 num_heads, num_kv_heads, kv_tokens, cache_capacity,
6583 head_dim, aligned_head_dim, split_chunks, partition_tokens);
6584}
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)

References attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned().

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 
)
static

Definition at line 6450 of file attention_kernels.c.

6463{
6464 if (!q_token || !k_cache || !v_cache || !out_token ||
6465 num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 ||
6466 cache_capacity <= 0 || kv_tokens > cache_capacity ||
6467 head_dim <= 0 || aligned_head_dim < head_dim ||
6468 partition_tokens < kv_tokens) {
6469 return;
6470 }
6471
6472 if (split_chunks < 1) {
6473 split_chunks = 1;
6474 }
6475 if (split_chunks > kv_tokens) {
6476 split_chunks = kv_tokens;
6477 }
6478
6479 const int partial_stride = aligned_head_dim + 2;
6480 const size_t max_partial_bytes = 1024u * 1024u;
6481 while (split_chunks > 1 &&
6482 (size_t) num_heads * (size_t) split_chunks * (size_t) partial_stride * sizeof(float) >
6483 max_partial_bytes) {
6484 split_chunks = (split_chunks + 1) / 2;
6485 }
6486
6487 const int chunk_size = (partition_tokens + split_chunks - 1) / split_chunks;
6488 const int scheduled_chunks = (kv_tokens + chunk_size - 1) / chunk_size;
6489 const size_t resolved_count =
6490 (size_t) num_heads * (size_t) scheduled_chunks * (size_t) partial_stride;
6491 float *partials = (float *) alloca(resolved_count * sizeof(float));
6492 ck_attention_f16_split_args_t args = {
6493 .q_token = q_token,
6494 .k_cache = k_cache,
6495 .v_cache = v_cache,
6496 .partials = partials,
6497 .num_heads = num_heads,
6498 .num_kv_heads = num_kv_heads,
6499 .kv_tokens = kv_tokens,
6500 .cache_capacity = cache_capacity,
6501 .head_dim = head_dim,
6502 .aligned_head_dim = aligned_head_dim,
6503 .split_chunks = split_chunks,
6504 .scheduled_chunks = scheduled_chunks,
6505 .partition_tokens = partition_tokens,
6506 };
6507
6508 ck_threadpool_t *pool = ck_threadpool_global();
6509 int active_threads = pool ? ck_threadpool_n_threads(pool) : 1;
6510 const int total_jobs = num_heads * scheduled_chunks;
6511 if (active_threads > total_jobs) {
6512 active_threads = total_jobs;
6513 }
6514 if (pool && active_threads > 1) {
6515 ck_threadpool_dispatch_n(pool, active_threads, ck_attention_f16_split_work, &args);
6516 } else {
6517 ck_attention_f16_split_work(0, 1, &args);
6518 }
6519
6520 for (int h = 0; h < num_heads; ++h) {
6521 float *out_head = out_token + (size_t) h * (size_t) aligned_head_dim;
6522 float final_max = -INFINITY;
6523 float final_sum = 0.0f;
6524 for (int d = 0; d < aligned_head_dim; ++d) {
6525 out_head[d] = 0.0f;
6526 }
6527
6528 for (int chunk = 0; chunk < scheduled_chunks; ++chunk) {
6529 const float *partial = partials +
6530 ((size_t) h * (size_t) scheduled_chunks + (size_t) chunk) * (size_t) partial_stride;
6531 const float chunk_max = partial[0];
6532 const float chunk_sum = partial[1];
6533 if (chunk_sum == 0.0f) {
6534 continue;
6535 }
6536 const float new_max = fmaxf(final_max, chunk_max);
6537 const float old_scale = isfinite(final_max)
6538 ? ck_attention_f16_reduce_expf(final_max - new_max)
6539 : 0.0f;
6540 const float chunk_scale =
6541 ck_attention_f16_reduce_expf(chunk_max - new_max);
6542 for (int d = 0; d < head_dim; ++d) {
6543 const float chunk_term = partial[2 + d] * chunk_scale;
6544 out_head[d] = fmaf(out_head[d], old_scale, chunk_term);
6545 }
6546#if defined(__INTEL_LLVM_COMPILER)
6547 const float scaled_chunk_sum = chunk_sum * chunk_scale;
6548 final_sum = fmaf(final_sum, old_scale, scaled_chunk_sum);
6549#else
6550 final_sum = fmaf(
6551 final_sum, old_scale, chunk_sum * chunk_scale);
6552#endif
6553 final_max = new_max;
6554 }
6555
6556 if (final_sum > 0.0f) {
6557 const float inv_sum = 1.0f / final_sum;
6558 for (int d = 0; d < head_dim; ++d) {
6559 out_head[d] *= inv_sum;
6560 }
6561 }
6562 }
6563}
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().

◆ 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 6151 of file attention_kernels.c.

6161{
6162 if (!q_token || !k_cache || !v_cache || !out_token) {
6163 return;
6164 }
6165 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6166 return;
6167 }
6168 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6169 return;
6170 }
6171
6172 const float scale = 1.0f / sqrtf((float)head_dim);
6173 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6174
6175 for (int h = 0; h < num_heads; ++h) {
6176 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6177 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
6178 const float *k_head = k_cache + (size_t)kv_head * head_stride;
6179 const float *v_head = v_cache + (size_t)kv_head * head_stride;
6180 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
6181
6183 k_head,
6184 v_head,
6185 kv_tokens,
6186 head_dim,
6187 aligned_head_dim,
6188 scale,
6189 out_head);
6190 }
6191}
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 6046 of file attention_kernels.c.

6056{
6057 if (!q_token || !k_cache || !v_cache || !out_token) {
6058 return;
6059 }
6060 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
6061 return;
6062 }
6063 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
6064 return;
6065 }
6066
6067 const float scale = 1.0f;
6068 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
6069
6070 for (int h = 0; h < num_heads; ++h) {
6071 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
6072 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
6073 const float *k_head = k_cache + (size_t)kv_head * head_stride;
6074 const float *v_head = v_cache + (size_t)kv_head * head_stride;
6075 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
6076
6077 attention_flash_decode(out_head,
6078 q_head,
6079 k_head,
6080 v_head,
6081 1,
6082 kv_tokens,
6083 1,
6084 aligned_head_dim,
6085 scale);
6086 }
6087}

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 5975 of file attention_kernels.c.

5982{
5984 q, k, v, output, num_heads, num_kv_heads, 1, live_tokens,
5985 head_dim, aligned_head_dim, kv_stride_tokens, sliding_window,
5986 scores, scores_bytes, value_columns, value_columns_bytes,
5987 scaled_scores, scaled_scores_bytes, 0);
5988}

References ck_attention_llama_regular_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 8873 of file attention_kernels.c.

8883{
8884 if (!q_token || !k_cache || !v_cache || !out_token) {
8885 return;
8886 }
8887 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
8888 return;
8889 }
8890 if (kv_tokens > cache_capacity) {
8891 return;
8892 }
8893
8894 const int strict = ck_strict_parity_enabled();
8895 const float scale = strict
8897 : 1.0f / sqrtf((float) head_dim);
8898 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
8899
8900 // Select SIMD implementation based on compile-time CPU features
8901#if defined(__AVX512F__)
8902 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal_avx512
8903#elif defined(__AVX2__)
8904 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal_avx2
8905#elif defined(__AVX__)
8906 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal_avx
8907#else
8908 #define FLASH_QUERY_IMPL_DECODE attention_flash_query_causal
8909#endif
8910
8911#pragma omp parallel for schedule(static) if(num_heads > 1)
8912 for (int h = 0; h < num_heads; ++h) {
8913 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
8914 const float *q_vec = q_token + (size_t)h * (size_t)aligned_head_dim;
8915 const float *k_head = k_cache + (size_t)kv_head * head_stride;
8916 const float *v_head = v_cache + (size_t)kv_head * head_stride;
8917 float *out_vec = out_token + (size_t)h * (size_t)aligned_head_dim;
8918
8919 if (strict) {
8921 k_head,
8922 v_head,
8923 kv_tokens,
8924 head_dim,
8925 aligned_head_dim,
8926 scale,
8927 out_vec);
8928 continue;
8929 }
8930
8931 FLASH_QUERY_IMPL_DECODE(q_vec, k_head, v_head,
8932 kv_tokens, head_dim, aligned_head_dim,
8933 scale, out_vec);
8934 }
8935
8936#undef FLASH_QUERY_IMPL_DECODE
8937}
static float ck_attention_strict_scale_f32(int head_dim)
#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 6135 of file attention_kernels.c.

6144{
6146 q_token, k_cache, v_cache, out_token, num_heads, num_heads,
6147 kv_tokens, cache_capacity, head_dim, aligned_head_dim
6148 );
6149}
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 5372 of file attention_kernels.c.

5382{
5383 if (!q || !k || !v || !output) {
5384 return;
5385 }
5386 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
5387 return;
5388 }
5389 if (kv_stride_tokens < num_tokens) {
5390 return;
5391 }
5392
5393 const float scale = ck_strict_parity_enabled()
5395 : 1.0f / sqrtf((float) head_dim);
5396 const int T = num_tokens;
5397 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
5398 const int debug_layer_id = ck_strict_parity_enabled() ? ck_attention_vec_dump_next_layer_id() : -1;
5399 float *score_row = (float *) alloca((size_t) T * sizeof(float));
5400 float *v_cols = (float *) alloca((size_t) head_dim * (size_t) T * sizeof(float));
5401 for (int h = 0; h < num_heads; ++h) {
5402 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
5403 const float *k_head = k + (size_t) kv_head * kv_head_stride;
5404 const float *v_head = v + (size_t) kv_head * kv_head_stride;
5405
5406#if CK_ENABLE_LLAMA_CPP_PARITY
5407 float *out_head = output + (size_t) h * (size_t) T * (size_t) aligned_head_dim;
5410 q + (size_t) h * (size_t) T * (size_t) aligned_head_dim,
5411 k_head,
5412 v_head,
5413 out_head,
5414 T,
5415 head_dim,
5416 aligned_head_dim,
5417 scale)) {
5418 ck_attention_trace("regular_graph_oracle", debug_layer_id, h);
5419 continue;
5420 }
5421#endif
5422
5423 for (int d = 0; d < head_dim; ++d) {
5424 float *dst_col = v_cols + (size_t) d * (size_t) T;
5425 for (int j = 0; j < T; ++j) {
5426 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
5427 }
5428 }
5429
5430 for (int i = 0; i < T; ++i) {
5431 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
5432 float *out_vec = output + qkv_index(h, i, 0, T, aligned_head_dim);
5434 k_head,
5435 v_cols,
5436 T,
5437 head_dim,
5438 aligned_head_dim,
5439 scale,
5440 score_row,
5441 out_vec,
5442 debug_layer_id,
5443 h,
5444 i);
5445 }
5446 }
5447}
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 4391 of file attention_kernels.c.

4400{
4402 num_heads, num_kv_heads,
4403 num_tokens, head_dim,
4404 aligned_head_dim,
4405 /*kv_stride_tokens=*/num_tokens,
4406 /*causal=*/0,
4407 /*round_full_kv_fp16=*/1,
4408 /*output_token_major=*/0,
4409 1.0f / sqrtf((float)head_dim));
4410}

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 4467 of file attention_kernels.c.

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

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 4920 of file attention_kernels.c.

4931{
4933 q, k, v, output,
4934 num_heads, num_kv_heads, num_tokens, head_dim,
4935 aligned_head_dim, kv_stride_tokens,
4936 /*causal=*/0,
4937 /*round_full_kv_fp16=*/0,
4938 /*output_token_major=*/0,
4939 1.0f / sqrtf((float)head_dim)
4940 );
4941 const size_t count = (size_t)num_heads * (size_t)num_tokens
4942 * (size_t)aligned_head_dim;
4943 for (size_t i = 0; i < count; ++i) {
4944 output[i] = bf16_to_float(float_to_bf16(output[i]));
4945 }
4946}

References attention_forward_head_major_gqa_flash_impl(), bf16_to_float(), 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 5084 of file attention_kernels.c.

5094{
5095 (void)head_dim;
5097 num_heads, num_kv_heads,
5098 num_tokens, head_dim,
5099 aligned_head_dim,
5100 kv_stride_tokens,
5101 /*causal=*/0,
5102 /*round_full_kv_fp16=*/1,
5103 /*output_token_major=*/0,
5104 1.0f);
5105}

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 5690 of file attention_kernels.c.

5700{
5701 if (num_heads <= 0 || num_tokens <= 0 || head_dim <= 0 ||
5702 (size_t) num_heads > SIZE_MAX / (size_t) num_tokens ||
5703 (size_t) head_dim > SIZE_MAX / (size_t) num_tokens) {
5704 return;
5705 }
5706 const size_t score_elements = (size_t) num_heads * (size_t) num_tokens;
5707 const size_t columns_per_head = (size_t) head_dim * (size_t) num_tokens;
5708 if ((size_t) num_heads > SIZE_MAX / columns_per_head) return;
5709 const size_t column_elements = (size_t) num_heads * columns_per_head;
5710 if (score_elements > SIZE_MAX - column_elements ||
5711 score_elements + column_elements > SIZE_MAX - (size_t) num_tokens) return;
5712 const size_t total_elements = score_elements + column_elements + (size_t) num_tokens;
5713 if (total_elements > SIZE_MAX / sizeof(float)) return;
5714 float *workspace = (float *) malloc(total_elements * sizeof(float));
5715 if (!workspace) return;
5716 float *score_rows = workspace;
5717 float *v_columns = score_rows + score_elements;
5718 float *probability_row = v_columns + column_elements;
5720 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5721 aligned_head_dim, kv_stride_tokens,
5722 score_rows, score_elements * sizeof(float),
5723 v_columns, column_elements * sizeof(float),
5724 probability_row, (size_t) num_tokens * sizeof(float));
5725 free(workspace);
5726}
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 5449 of file attention_kernels.c.

5466{
5467 if (!q || !k || !v || !output) {
5468 return;
5469 }
5470 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
5471 return;
5472 }
5473 if (kv_stride_tokens < num_tokens) {
5474 return;
5475 }
5476
5477 const size_t T = (size_t) num_tokens;
5478 if ((size_t) num_heads > SIZE_MAX / T ||
5479 (size_t) head_dim > SIZE_MAX / T) {
5480 return;
5481 }
5482 const size_t score_elements = (size_t) num_heads * T;
5483 const size_t columns_per_head = (size_t) head_dim * T;
5484 if ((size_t) num_heads > SIZE_MAX / columns_per_head ||
5485 score_elements > SIZE_MAX / sizeof(float) ||
5486 columns_per_head * (size_t) num_heads > SIZE_MAX / sizeof(float) ||
5487 T > SIZE_MAX / sizeof(float)) {
5488 return;
5489 }
5490 const size_t column_elements = columns_per_head * (size_t) num_heads;
5491 if (!score_rows || score_rows_bytes < score_elements * sizeof(float) ||
5492 !v_columns || v_columns_bytes < column_elements * sizeof(float) ||
5493 !probability_row || probability_row_bytes < T * sizeof(float)) {
5494 return;
5495 }
5496
5497 const int strict = ck_strict_parity_enabled();
5498 const float scale = strict
5500 : 1.0f / sqrtf((float) head_dim);
5501 const int token_count = num_tokens;
5502 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
5503 const int debug_layer_id = strict ? ck_attention_vec_dump_next_layer_id() : -1;
5504#if CK_ENABLE_LLAMA_CPP_PARITY
5505 ck_ggml_vec_dot_f32_fn dot_fn = NULL;
5506 ck_ggml_vec_soft_max_f32_fn softmax_fn = NULL;
5507 ck_ggml_compute_forward_mul_mat_fn mul_mat_fn = NULL;
5508 ck_ggml_compute_forward_soft_max_fn softmax_compute_fn = NULL;
5509 if (strict) {
5511 k,
5512 v,
5513 output,
5514 num_heads,
5515 num_kv_heads,
5516 num_tokens,
5517 head_dim,
5518 aligned_head_dim,
5519 kv_stride_tokens,
5520 scale)) {
5521 return;
5522 }
5523 dot_fn = ck_resolve_ggml_vec_dot_f32();
5524 softmax_fn = ck_resolve_ggml_vec_soft_max_f32();
5525 mul_mat_fn = ck_resolve_ggml_compute_forward_mul_mat();
5526 softmax_compute_fn = ck_resolve_ggml_compute_forward_soft_max();
5527 }
5528#endif
5529 if (strict) {
5530 float *score_row = score_rows;
5531 float *v_cols = v_columns;
5532#if CK_ENABLE_LLAMA_CPP_PARITY
5533 float *prob_row = probability_row;
5534#endif
5535
5536 for (int h = 0; h < num_heads; ++h) {
5537 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
5538 const float *k_head = k + (size_t) kv_head * kv_head_stride;
5539 const float *v_head = v + (size_t) kv_head * kv_head_stride;
5540
5541#if CK_ENABLE_LLAMA_CPP_PARITY
5542 float *out_head = output + (size_t) h * (size_t) T * (size_t) aligned_head_dim;
5544 q + (size_t) h * (size_t) T * (size_t) aligned_head_dim,
5545 k_head,
5546 v_head,
5547 out_head,
5548 token_count,
5549 head_dim,
5550 aligned_head_dim,
5551 scale)) {
5552 continue;
5553 }
5554#endif
5555
5556 for (int d = 0; d < head_dim; ++d) {
5557 float *dst_col = v_cols + (size_t) d * (size_t) token_count;
5558 for (int j = 0; j < token_count; ++j) {
5559 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
5560 }
5561 }
5562
5563#if CK_ENABLE_LLAMA_CPP_PARITY
5564 if (dot_fn && softmax_fn && ck_attention_ggml_out_graph_enabled()) {
5565 if (attention_head_full_dyn_ggml_regular_graph_out(
5566 q + (size_t) h * (size_t) T * (size_t) aligned_head_dim,
5567 k_head,
5568 v_cols,
5569 token_count,
5570 head_dim,
5571 aligned_head_dim,
5572 scale,
5573 score_row,
5574 prob_row,
5575 out_head,
5576 dot_fn,
5577 softmax_fn,
5578 debug_layer_id,
5579 h)) {
5580 if (token_count > 0) {
5581 ck_attention_trace("dyn_ggml_regular_graph_out", debug_layer_id, h);
5582 ck_attention_trace_float("scale", debug_layer_id, h, scale);
5583 }
5584 continue;
5585 }
5586 }
5587#endif
5588
5589 for (int i = 0; i < token_count; ++i) {
5590 const float *q_vec = q + qkv_index(h, i, 0, token_count, aligned_head_dim);
5591 float *out_vec = output + qkv_index(h, i, 0, token_count, aligned_head_dim);
5592#if CK_ENABLE_LLAMA_CPP_PARITY
5593 if (dot_fn && softmax_fn) {
5594 if (i == 0) {
5595 ck_attention_trace("dyn_ggml_regular", debug_layer_id, h);
5596 ck_attention_trace_float("scale", debug_layer_id, h, scale);
5597 }
5598 attention_query_full_dyn_ggml_regular(q_vec,
5599 k_head,
5600 v_cols,
5601 token_count,
5602 head_dim,
5603 aligned_head_dim,
5604 scale,
5605 score_row,
5606 prob_row,
5607 out_vec,
5608 dot_fn,
5609 softmax_fn,
5610 debug_layer_id,
5611 h,
5612 i);
5613 } else if (dot_fn && mul_mat_fn && softmax_compute_fn) {
5614 if (i == 0) {
5615 ck_attention_trace("ggml_compute_regular", debug_layer_id, h);
5616 }
5617 attention_query_full_ggml_compute_regular(q_vec,
5618 k_head,
5619 v_cols,
5620 token_count,
5621 head_dim,
5622 aligned_head_dim,
5623 scale,
5624 score_row,
5625 prob_row,
5626 out_vec,
5627 dot_fn,
5628 mul_mat_fn,
5629 softmax_compute_fn);
5630 } else
5631#endif
5632 {
5633 if (i == 0) {
5634 ck_attention_trace("ggml_regular", debug_layer_id, h);
5635 }
5637 k_head,
5638 v_cols,
5639 token_count,
5640 head_dim,
5641 aligned_head_dim,
5642 scale,
5643 score_row,
5644 out_vec,
5645 debug_layer_id,
5646 h,
5647 i);
5648 }
5649 }
5650 }
5651 return;
5652 }
5653
5654#pragma omp parallel for schedule(static) if(num_heads > 1)
5655 for (int h = 0; h < num_heads; ++h) {
5656 float *score_row = score_rows + (size_t) h * (size_t) token_count;
5657 float *v_cols = v_columns + (size_t) h * (size_t) head_dim * (size_t) token_count;
5658 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
5659 const float *k_head = k + (size_t) kv_head * kv_head_stride;
5660 const float *v_head = v + (size_t) kv_head * kv_head_stride;
5661
5662 if (v_cols) {
5663 for (int d = 0; d < head_dim; ++d) {
5664 float *dst_col = v_cols + (size_t) d * (size_t) token_count;
5665 for (int j = 0; j < token_count; ++j) {
5666 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
5667 }
5668 }
5669 }
5670
5671 for (int i = 0; i < token_count; ++i) {
5672 const float *q_vec = q + qkv_index(h, i, 0, token_count, aligned_head_dim);
5673 float *out_vec = output + qkv_index(h, i, 0, token_count, aligned_head_dim);
5675 k_head,
5676 v_cols,
5677 token_count,
5678 head_dim,
5679 aligned_head_dim,
5680 scale,
5681 score_row,
5682 out_vec,
5683 -1,
5684 h,
5685 i);
5686 }
5687 }
5688}
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 4973 of file attention_kernels.c.

4984{
4986 q, k, v, output, num_heads, num_kv_heads, num_tokens,
4987 head_dim, aligned_head_dim, kv_stride_tokens,
4988 /*output_token_major=*/0)) {
4989 return;
4990 }
4991 fprintf(stderr,
4992 "HARD KERNEL CONTRACT FAULT: PyTorch CPU-flash BF16 attention "
4993 "requires AMX-BF16, AVX-512, D=72/A=72 and a token multiple of 16; "
4994 "no numerically different fallback is permitted\n");
4995 abort();
4996}
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 4998 of file attention_kernels.c.

5009{
5011 q, k, v, output, num_heads, num_kv_heads, num_tokens,
5012 head_dim, aligned_head_dim, kv_stride_tokens,
5013 /*output_token_major=*/1)) {
5014 return;
5015 }
5016 fprintf(stderr,
5017 "HARD KERNEL CONTRACT FAULT: PyTorch CPU-flash BF16 token-output "
5018 "attention requires AMX-BF16, AVX-512, D=72/A=72 and a token "
5019 "multiple of 16; no numerically different fallback is permitted\n");
5020 abort();
5021}

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 4948 of file attention_kernels.c.

4959{
4961 q, k, v, output, num_heads, num_kv_heads, num_tokens,
4962 head_dim, aligned_head_dim, kv_stride_tokens)) {
4963 const size_t count = (size_t)num_heads * (size_t)num_tokens
4964 * (size_t)aligned_head_dim;
4965 for (size_t i = 0; i < count; ++i) {
4966 output[i] = bf16_to_float(float_to_bf16(output[i]));
4967 }
4968 return;
4969 }
4970 fprintf(stderr, "CK numerical contract failure: BF16 tiled SDPA received invalid dimensions or could not allocate scratch\n");
4971}
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(), 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 3564 of file attention_kernels.c.

3575{
3577 q, k, v, output, num_heads, num_kv_heads, num_tokens,
3578 head_dim, aligned_head_dim, kv_stride_tokens, CK_GGML_FA_TILE_Q_LARGE);
3579}
#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 3547 of file attention_kernels.c.

3558{
3560 q, k, v, output, num_heads, num_kv_heads, num_tokens,
3561 head_dim, aligned_head_dim, kv_stride_tokens, CK_GGML_FA_TILE_Q);
3562}

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 3527 of file attention_kernels.c.

3538{
3539 const int query_tile_size = num_tokens >= CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS
3543 q, k, v, output, num_heads, num_kv_heads, num_tokens,
3544 head_dim, aligned_head_dim, kv_stride_tokens, query_tile_size);
3545}
#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 4109 of file attention_kernels.c.

4123{
4124 if (!q || !k || !v || !output) {
4125 return;
4126 }
4127 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0 ||
4128 head_dim <= 0 || aligned_head_dim < head_dim) {
4129 return;
4130 }
4131 if (kv_stride_tokens < num_tokens) {
4132 return;
4133 }
4134
4135 const int T = num_tokens;
4136 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
4137
4139 const float strict_scale = ck_attention_strict_scale_f32(head_dim);
4140 const int debug_layer_id = ck_attention_vec_dump_enabled()
4142 : -1;
4145 q, k, v, output,
4146 num_heads, num_kv_heads, num_tokens,
4147 head_dim, aligned_head_dim, kv_stride_tokens,
4148 causal, output_token_major, strict_scale, debug_layer_id)) {
4149 return;
4150 }
4151 }
4152#if CK_ENABLE_LLAMA_CPP_PARITY
4153 if (!causal && !output_token_major &&
4155 k,
4156 v,
4157 output,
4158 num_heads,
4159 num_kv_heads,
4160 num_tokens,
4161 head_dim,
4162 aligned_head_dim,
4163 kv_stride_tokens,
4164 strict_scale)) {
4165 return;
4166 }
4167#endif
4168 float *score_row = (float *) alloca((size_t) T * sizeof(float));
4169 float *logit_row = (float *) alloca((size_t) T * sizeof(float));
4170 float *v_cols = (float *) alloca((size_t) head_dim * (size_t) T * sizeof(float));
4171 for (int h = 0; h < num_heads; ++h) {
4172 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
4173 const float *k_head = k + (size_t)kv_head * kv_head_stride;
4174 const float *v_head = v + (size_t)kv_head * kv_head_stride;
4175
4176 for (int d = 0; d < head_dim; ++d) {
4177 float *dst_col = v_cols + (size_t) d * (size_t) T;
4178 for (int j = 0; j < T; ++j) {
4179 dst_col[j] = v_head[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
4180 }
4181 }
4182
4183 for (int i = 0; i < T; ++i) {
4184 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
4185 float *out_vec = output + qkv_index(h, i, 0, T, aligned_head_dim);
4186 const int kv_tokens = causal ? (i + 1) : T;
4187 if (kv_tokens <= 0) {
4188 for (int d = 0; d < aligned_head_dim; ++d) {
4189 out_vec[d] = 0.0f;
4190 }
4191 continue;
4192 }
4193 for (int j = 0; j < kv_tokens; ++j) {
4194 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
4195 score_row[j] = ck_ggml_vec_dot_f32_contig(q_vec, k_vec, head_dim);
4196 }
4197 float *raw_dump = NULL;
4198 if (ck_attention_vec_dump_should_emit(debug_layer_id, h, i)) {
4199 raw_dump = (float *) alloca((size_t) kv_tokens * sizeof(float));
4200 memcpy(raw_dump, score_row, (size_t) kv_tokens * sizeof(float));
4201 }
4202 memcpy(logit_row, score_row, (size_t) kv_tokens * sizeof(float));
4203 ck_vec_scale_f32_inplace(logit_row, kv_tokens, strict_scale);
4204 const float max_score = ck_vec_max_f32_contig(logit_row, kv_tokens);
4205 const double sum = ck_ggml_vec_soft_max_row(kv_tokens, score_row, logit_row, max_score);
4206 if (sum > 0.0) {
4207 const float inv_sum = (float) (1.0 / sum);
4208 ck_vec_scale_f32_inplace(score_row, kv_tokens, inv_sum);
4209 for (int d = 0; d < head_dim; ++d) {
4210 const float *v_col = v_cols + (size_t) d * (size_t) T;
4211 out_vec[d] = ck_ggml_vec_dot_f32_contig(score_row, v_col, kv_tokens);
4212 }
4213 } else {
4214 for (int d = 0; d < head_dim; ++d) {
4215 out_vec[d] = 0.0f;
4216 }
4217 }
4218 for (int d = head_dim; d < aligned_head_dim; ++d) {
4219 out_vec[d] = 0.0f;
4220 }
4221 if (raw_dump) {
4222 ck_attention_vec_dump_selected_query(raw_dump, score_row, out_vec, v_cols,
4223 kv_tokens, head_dim,
4224 debug_layer_id, h, i);
4225 }
4226 }
4227 }
4228 return;
4229 }
4230
4231 /*
4232 * Full GGML-style attention consumes FP32 Q with K/V rounded through
4233 * FP16. Materialize that semantic input once so serial, threaded, and
4234 * ISA-specific implementations all see the same values. Causal callers
4235 * retain their existing FP32 K/V contract.
4236 */
4237 float *rounded_kv = NULL;
4238 const float *compute_k = k;
4239 const float *compute_v = v;
4240 if (!causal && round_full_kv_fp16) {
4241 if ((size_t) kv_stride_tokens > SIZE_MAX / (size_t) num_kv_heads) {
4242 return;
4243 }
4244 const size_t rows = (size_t) num_kv_heads * (size_t) kv_stride_tokens;
4245 if ((size_t) aligned_head_dim > SIZE_MAX / rows) {
4246 return;
4247 }
4248 const size_t elements = rows * (size_t) aligned_head_dim;
4249 if (elements > SIZE_MAX / (2 * sizeof(float))) {
4250 return;
4251 }
4252 rounded_kv = (float *) malloc(2 * elements * sizeof(float));
4253 if (!rounded_kv) {
4254 return;
4255 }
4256 compute_k = rounded_kv;
4257 compute_v = rounded_kv + elements;
4258 ck_round_fp16_buffer(k, rounded_kv, elements);
4259 ck_round_fp16_buffer(v, rounded_kv + elements, elements);
4260 }
4261
4262 // Select SIMD implementation based on compile-time CPU features
4263#if defined(__AVX512F__)
4264 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx512
4265#elif defined(__AVX2__)
4266 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx2
4267#elif defined(__AVX__)
4268 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx
4269#else
4270 #define FLASH_QUERY_IMPL attention_flash_query_causal
4271#endif
4272
4273 const int total_queries = num_heads * T;
4274#if defined(__AVX512F__)
4275 if (!causal && !output_token_major && head_dim == 72 && aligned_head_dim >= 72 && ck_attention_qblock8_enabled()) {
4276 ck_threadpool_t *pool = ck_threadpool_global();
4277 const int q_blocks = (T + 7) / 8;
4278 const int total_blocks = num_heads * q_blocks;
4279 int active = ck_attention_pick_active_threads(pool, total_blocks, T);
4280 if (pool && active > 1) {
4281 ck_attention_qblock4_args_t args = {
4282 .q = q,
4283 .k = compute_k,
4284 .v = compute_v,
4285 .output = output,
4286 .num_heads = num_heads,
4287 .num_kv_heads = num_kv_heads,
4288 .num_tokens = num_tokens,
4289 .aligned_head_dim = aligned_head_dim,
4290 .kv_stride_tokens = kv_stride_tokens,
4291 .scale = scale,
4292 };
4293 ck_threadpool_dispatch_n(pool, active, ck_attention_full_qblock8_work, &args);
4294 free(rounded_kv);
4295 return;
4296 }
4297 }
4298
4299 if (!causal && !output_token_major && head_dim == 72 && aligned_head_dim >= 72 && ck_attention_qblock4_enabled()) {
4300 ck_threadpool_t *pool = ck_threadpool_global();
4301 const int q_blocks = (T + 3) / 4;
4302 const int total_blocks = num_heads * q_blocks;
4303 int active = ck_attention_pick_active_threads(pool, total_blocks, T);
4304 if (pool && active > 1) {
4305 ck_attention_qblock4_args_t args = {
4306 .q = q,
4307 .k = compute_k,
4308 .v = compute_v,
4309 .output = output,
4310 .num_heads = num_heads,
4311 .num_kv_heads = num_kv_heads,
4312 .num_tokens = num_tokens,
4313 .aligned_head_dim = aligned_head_dim,
4314 .kv_stride_tokens = kv_stride_tokens,
4315 .scale = scale,
4316 };
4317 ck_threadpool_dispatch_n(pool, active, ck_attention_full_qblock4_work, &args);
4318 free(rounded_kv);
4319 return;
4320 }
4321 }
4322#endif
4323 if (ck_attention_parallel_enabled(total_queries, T, head_dim)) {
4324 ck_threadpool_t *pool = ck_threadpool_global();
4325 const int active = ck_attention_pick_active_threads(pool, total_queries, T);
4326 if (pool && active > 1) {
4327 ck_attention_parallel_args_t args = {
4328 .q = q,
4329 .k = compute_k,
4330 .v = compute_v,
4331 .output = output,
4332 .num_heads = num_heads,
4333 .num_kv_heads = num_kv_heads,
4334 .num_tokens = num_tokens,
4335 .head_dim = head_dim,
4336 .aligned_head_dim = aligned_head_dim,
4337 .kv_stride_tokens = kv_stride_tokens,
4338 .causal = causal,
4339 .output_token_major = output_token_major,
4340 .scale = scale,
4341 };
4343 free(rounded_kv);
4344 return;
4345 }
4346 }
4347
4348 for (int h = 0; h < num_heads; ++h) {
4349 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
4350 const float *k_head = compute_k + (size_t)kv_head * kv_head_stride;
4351 const float *v_head = compute_v + (size_t)kv_head * kv_head_stride;
4352
4353 for (int i = 0; i < T; ++i) {
4354 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
4355 float *out_vec = output + attention_output_index(
4356 h, i, num_heads, T, aligned_head_dim, output_token_major);
4357 const int kv_tokens = causal ? (i + 1) : T;
4358 FLASH_QUERY_IMPL(q_vec, k_head, v_head,
4359 kv_tokens,
4360 head_dim, aligned_head_dim,
4361 scale, out_vec);
4362 }
4363 }
4364
4365 free(rounded_kv);
4366
4367#undef FLASH_QUERY_IMPL
4368}
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)
static int ck_attention_vec_dump_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 4021 of file attention_kernels.c.

4036{
4037 const int T = num_tokens;
4038 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
4039 const size_t kv_half_count = (size_t) T * (size_t) aligned_head_dim;
4040 uint16_t *k_half = (uint16_t *) malloc(kv_half_count * sizeof(uint16_t));
4041 uint16_t *v_half = (uint16_t *) malloc(kv_half_count * sizeof(uint16_t));
4042 if (!k_half || !v_half) {
4043 free(k_half);
4044 free(v_half);
4045 return 0;
4046 }
4047 uint16_t *q_half = (uint16_t *) alloca((size_t) aligned_head_dim * sizeof(uint16_t));
4048 uint16_t *prob_half = (uint16_t *) alloca((size_t) T * sizeof(uint16_t));
4049 uint16_t *v_col_half = (uint16_t *) alloca((size_t) T * sizeof(uint16_t));
4050 float *raw_scores = (float *) alloca((size_t) T * sizeof(float));
4051 float *logits = (float *) alloca((size_t) T * sizeof(float));
4052 int cached_kv_head = -1;
4053
4054 for (int h = 0; h < num_heads; ++h) {
4055 const int kv_head = (int) ((long long) h * (long long) num_kv_heads /
4056 (long long) num_heads);
4057 const float *k_head = k + (size_t) kv_head * kv_head_stride;
4058 const float *v_head = v + (size_t) kv_head * kv_head_stride;
4059 if (kv_head != cached_kv_head) {
4060 for (size_t idx = 0; idx < kv_half_count; ++idx) {
4061 k_half[idx] = CK_FP32_TO_FP16(k_head[idx]);
4062 v_half[idx] = CK_FP32_TO_FP16(v_head[idx]);
4063 }
4064 cached_kv_head = kv_head;
4065 }
4066
4067 for (int i = 0; i < T; ++i) {
4068 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
4069 float *out_vec = output + attention_output_index(
4070 h, i, num_heads, T, aligned_head_dim, output_token_major);
4071 const int kv_tokens = causal ? i + 1 : T;
4072 for (int d = 0; d < aligned_head_dim; ++d) {
4073 q_half[d] = CK_FP32_TO_FP16(q_vec[d]);
4074 }
4075 for (int j = 0; j < kv_tokens; ++j) {
4076 raw_scores[j] = ck_attention_dot_f16_unfused_llama(
4077 q_half,
4078 k_half + (size_t) j * (size_t) aligned_head_dim,
4079 head_dim);
4080 logits[j] = raw_scores[j] * scale;
4081 }
4082
4083 const float max_score = ck_vec_max_f32_contig(logits, kv_tokens);
4084 const double sum = ck_ggml_vec_soft_max_row(kv_tokens, logits, logits, max_score);
4085 const float inv_sum = sum > 0.0 ? (float) (1.0 / sum) : 0.0f;
4086 for (int j = 0; j < kv_tokens; ++j) {
4087 logits[j] *= inv_sum;
4088 prob_half[j] = CK_FP32_TO_FP16(logits[j]);
4089 }
4090 for (int d = 0; d < head_dim; ++d) {
4091 for (int j = 0; j < kv_tokens; ++j) {
4092 v_col_half[j] = v_half[(size_t) j * (size_t) aligned_head_dim + (size_t) d];
4093 }
4094 out_vec[d] = ck_attention_dot_f16_unfused_llama(prob_half, v_col_half, kv_tokens);
4095 }
4096 for (int d = head_dim; d < aligned_head_dim; ++d) {
4097 out_vec[d] = 0.0f;
4098 }
4099 ck_attention_vec_dump_selected_query(raw_scores, logits, out_vec, NULL,
4100 kv_tokens, head_dim,
4101 debug_layer_id, h, i);
4102 }
4103 }
4104 free(k_half);
4105 free(v_half);
4106 return 1;
4107}
static float ck_attention_dot_f16_unfused_llama(const uint16_t *x, const uint16_t *y, int n)
#define CK_FP32_TO_FP16(x)

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 5216 of file attention_kernels.c.

5221{
5223 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5224 aligned_head_dim, kv_stride_tokens, visual_start, visual_tokens,
5225 /*output_token_major=*/0);
5226}
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 5108 of file attention_kernels.c.

5122{
5123 if (!q || !k || !v || !output) {
5124 return;
5125 }
5126 if (num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
5127 return;
5128 }
5129 if (kv_stride_tokens < num_tokens || head_dim <= 0 || aligned_head_dim <= 0) {
5130 return;
5131 }
5132 if (visual_start < 0 || visual_tokens <= 0 || visual_start >= num_tokens) {
5134 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5135 aligned_head_dim, kv_stride_tokens, /*causal=*/1,
5136 /*round_full_kv_fp16=*/0, output_token_major, 1.0f);
5137 return;
5138 }
5139
5140 int visual_end = visual_start + visual_tokens;
5141 if (visual_end > num_tokens) {
5142 visual_end = num_tokens;
5143 }
5144 if (visual_end <= visual_start) {
5146 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5147 aligned_head_dim, kv_stride_tokens, /*causal=*/1,
5148 /*round_full_kv_fp16=*/0, output_token_major, 1.0f);
5149 return;
5150 }
5151
5152 const int T = num_tokens;
5153 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
5154 const float scale = 1.0f;
5155
5157 const int debug_layer_id = ck_attention_vec_dump_enabled()
5159 : -1;
5160 for (int h = 0; h < num_heads; ++h) {
5161 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
5162 const float *k_head = k + (size_t)kv_head * kv_head_stride;
5163 const float *v_head = v + (size_t)kv_head * kv_head_stride;
5164
5165 for (int i = 0; i < T; ++i) {
5166 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
5167 float *out_vec = output + attention_output_index(
5168 h, i, num_heads, T, aligned_head_dim, output_token_major);
5169 const int in_visual = (i >= visual_start && i < visual_end);
5170 const int kv_tokens = in_visual ? visual_end : (i + 1);
5171 attention_flash_query_causal_exact(q_vec, k_head, v_head,
5172 kv_tokens,
5173 head_dim, aligned_head_dim,
5174 scale, out_vec);
5175 ck_attention_vec_dump_exact_query(q_vec, k_head, out_vec,
5176 kv_tokens,
5177 head_dim, aligned_head_dim,
5178 scale,
5179 debug_layer_id, h, i);
5180 }
5181 }
5182 return;
5183 }
5184
5185#if defined(__AVX512F__)
5186 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx512
5187#elif defined(__AVX2__)
5188 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx2
5189#elif defined(__AVX__)
5190 #define FLASH_QUERY_IMPL attention_flash_query_causal_avx
5191#else
5192 #define FLASH_QUERY_IMPL attention_flash_query_causal
5193#endif
5194
5195 for (int h = 0; h < num_heads; ++h) {
5196 int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
5197 const float *k_head = k + (size_t)kv_head * kv_head_stride;
5198 const float *v_head = v + (size_t)kv_head * kv_head_stride;
5199
5200 for (int i = 0; i < T; ++i) {
5201 const float *q_vec = q + qkv_index(h, i, 0, T, aligned_head_dim);
5202 float *out_vec = output + attention_output_index(
5203 h, i, num_heads, T, aligned_head_dim, output_token_major);
5204 const int in_visual = (i >= visual_start && i < visual_end);
5205 const int kv_tokens = in_visual ? visual_end : (i + 1);
5206 FLASH_QUERY_IMPL(q_vec, k_head, v_head,
5207 kv_tokens,
5208 head_dim, aligned_head_dim,
5209 scale, out_vec);
5210 }
5211 }
5212
5213#undef FLASH_QUERY_IMPL
5214}
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 5228 of file attention_kernels.c.

5233{
5235 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5236 aligned_head_dim, kv_stride_tokens, visual_start, visual_tokens,
5237 /*output_token_major=*/1);
5238}

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_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 227 of file attention_kernels.c.

239{
240 if (key_transpose_scratch == NULL) return -1;
242 query, key, value, output, score_scratch, key_transpose_scratch,
243 num_heads, query_tokens, key_tokens, head_dim, scale);
244}

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 3581 of file attention_kernels.c.

3591{
3592 if (!query || !key || !value || !output || num_heads <= 0 ||
3593 query_tokens <= 0 || key_tokens != query_tokens || head_dim <= 0) {
3594 return -1;
3595 }
3596
3597 const float contract_scale = ck_attention_strict_scale_f32(head_dim);
3598 if (scale != contract_scale) {
3599 return -1;
3600 }
3601
3602 const int query_tile_size = query_tokens >= CK_GGML_FA_TILE_Q_LARGE_MIN_TOKENS
3606 query, key, value, output,
3607 num_heads, num_heads, query_tokens,
3608 head_dim, head_dim, key_tokens, query_tile_size);
3609 return 0;
3610}

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 8452 of file attention_kernels.c.

8466{
8467 (void)score_scratch;
8468 if (!query || !key_cache || !value_cache || !selected_indices || !output ||
8469 rows <= 0 || query_heads <= 0 || kv_heads <= 0 || head_dim <= 0 ||
8470 selection_width <= 0 || context_length <= 0 || position < 0 ||
8471 position + rows > context_length || query_heads % kv_heads != 0) {
8472 fprintf(stderr, "CK sparse BF16 CPU-flash attention: invalid contract\n");
8473 abort();
8474 }
8475
8476#if defined(__AVX512F__)
8477 for (int row = 0; row < rows; ++row) {
8478 const int visible_tokens = position + row + 1;
8479 const ck_attention_status_t status =
8480 ck_attention_decode_bf16_pytorch_cpu_flash_masked(
8481 query + (size_t)row * (size_t)query_heads * (size_t)head_dim,
8482 key_cache, value_cache,
8483 output + (size_t)row * (size_t)query_heads * (size_t)head_dim,
8484 selected_indices + (size_t)row * (size_t)selection_width,
8485 selection_width, query_heads, kv_heads, visible_tokens,
8486 context_length, head_dim, head_dim);
8487 if (status != CK_ATTENTION_STATUS_OK) {
8488 fprintf(stderr,
8489 "CK sparse BF16 CPU-flash attention unavailable (status=%d)\n",
8490 (int)status);
8491 abort();
8492 }
8493 }
8494#else
8495 fprintf(stderr,
8496 "CK sparse BF16 CPU-flash attention requires AVX-512F; "
8497 "no numerically different fallback is permitted\n");
8498 abort();
8499#endif
8500}

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 265 of file attention_kernels.c.

269{
270 if (token_major) {
271 return ((size_t)token * (size_t)num_heads + (size_t)h) *
272 (size_t)aligned_head_dim;
273 }
274 return qkv_index(h, token, 0, num_tokens, aligned_head_dim);
275}

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 2247 of file attention_kernels.c.

2259{
2260 if (kv_tokens <= 0) {
2261 for (int d = 0; d < aligned_head_dim; ++d) {
2262 out_vec[d] = 0.0f;
2263 }
2264 return;
2265 }
2266
2267 for (int j = 0; j < kv_tokens; ++j) {
2268 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
2269 score_row[j] = ck_vec_dot_f32_strict(q_vec, k_vec, head_dim);
2270 }
2271 float *raw_dump = NULL;
2272 if (ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
2273 raw_dump = (float *) alloca((size_t) kv_tokens * sizeof(float));
2274 memcpy(raw_dump, score_row, (size_t) kv_tokens * sizeof(float));
2275 }
2276
2277 float max_score = -INFINITY;
2278 for (int j = 0; j < kv_tokens; ++j) {
2279 const float score = score_row[j] * scale;
2280 score_row[j] = score;
2281 if (score > max_score) {
2282 max_score = score;
2283 }
2284 }
2285
2286 double sum = 0.0;
2287 for (int j = 0; j < kv_tokens; ++j) {
2288 const float w = expf(score_row[j] - max_score);
2289 score_row[j] = w;
2290 volatile double next = sum + (double) w;
2291 sum = next;
2292 }
2293
2294 if (sum > 0.0) {
2295 const float inv_sum = (float) (1.0 / sum);
2296 for (int j = 0; j < kv_tokens; ++j) {
2297 score_row[j] *= inv_sum;
2298 }
2299 for (int d = 0; d < head_dim; ++d) {
2300 const float *v_col = v_cols + (size_t) d * (size_t) kv_tokens;
2301 const float dot = ck_vec_dot_f32x_f32_to_f32_via_f64(score_row, v_col, kv_tokens);
2302 out_vec[d] = dot;
2303 }
2304 } else {
2305 for (int d = 0; d < head_dim; ++d) {
2306 out_vec[d] = 0.0f;
2307 }
2308 }
2309
2310 for (int d = head_dim; d < aligned_head_dim; ++d) {
2311 out_vec[d] = 0.0f;
2312 }
2313 if (raw_dump) {
2314 ck_attention_vec_dump_selected_query(raw_dump, score_row, out_vec, v_cols, kv_tokens, head_dim,
2315 layer_id, head_id, query_id);
2316 }
2317}
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 2319 of file attention_kernels.c.

2331{
2332 if (kv_tokens <= 0) {
2333 for (int d = 0; d < aligned_head_dim; ++d) {
2334 out_vec[d] = 0.0f;
2335 }
2336 return;
2337 }
2338
2339 for (int j = 0; j < kv_tokens; ++j) {
2340 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
2341 score_row[j] = ck_ggml_vec_dot_f32_contig(q_vec, k_vec, head_dim);
2342 }
2343 float *raw_dump = NULL;
2344 if (ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
2345 raw_dump = (float *) alloca((size_t) kv_tokens * sizeof(float));
2346 memcpy(raw_dump, score_row, (size_t) kv_tokens * sizeof(float));
2347 }
2348
2349 float *logit_row = (float *) alloca((size_t) kv_tokens * sizeof(float));
2350 memcpy(logit_row, score_row, (size_t) kv_tokens * sizeof(float));
2351 ck_vec_scale_f32_inplace(logit_row, kv_tokens, scale);
2352 const float max_score = ck_vec_max_f32_contig(logit_row, kv_tokens);
2353 const double sum = ck_ggml_vec_soft_max_row(kv_tokens, score_row, logit_row, max_score);
2354 if (sum > 0.0) {
2355 const float inv_sum = (float) (1.0 / sum);
2356 ck_vec_scale_f32_inplace(score_row, kv_tokens, inv_sum);
2357 for (int d = 0; d < head_dim; ++d) {
2358 const float *v_col = v_cols + (size_t) d * (size_t) kv_tokens;
2359 out_vec[d] = ck_ggml_vec_dot_f32_contig(score_row, v_col, kv_tokens);
2360 }
2361 } else {
2362 for (int d = 0; d < head_dim; ++d) {
2363 out_vec[d] = 0.0f;
2364 }
2365 }
2366
2367 for (int d = head_dim; d < aligned_head_dim; ++d) {
2368 out_vec[d] = 0.0f;
2369 }
2370 if (raw_dump) {
2371 ck_attention_vec_dump_selected_query(raw_dump, score_row, out_vec, v_cols, kv_tokens, head_dim,
2372 layer_id, head_id, query_id);
2373 }
2374}

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 4858 of file attention_kernels.c.

4859{
4860 ck_attention_bf16_sdpa_args_t *args = (ck_attention_bf16_sdpa_args_t *)opaque;
4862 args->q, args->k, args->v, args->output,
4863 args->num_heads, args->num_kv_heads, args->num_tokens,
4864 args->head_dim, args->aligned_head_dim, args->kv_stride_tokens,
4865 ith, nth, args->output_token_major)) {
4866 __atomic_store_n(&args->failed, 1, __ATOMIC_RELAXED);
4867 }
4868}
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 8511 of file attention_kernels.c.

8512{
8513#if defined(__AVX512F__)
8514 pthread_once(&ck_pytorch_attention_once, ck_bind_pytorch_attention_primitives);
8515 return ck_pytorch_sgemm_batch != NULL &&
8516 ck_pytorch_attention_expf16 != NULL;
8517#else
8518 return 1;
8519#endif
8520}

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 4846 of file attention_kernels.c.

4847{
4848 ck_attention_bf16_sdpa_args_t *args = (ck_attention_bf16_sdpa_args_t *)opaque;
4850 args->q, args->k, args->v, args->output,
4851 args->num_heads, args->num_kv_heads, args->num_tokens,
4852 args->head_dim, args->aligned_head_dim, args->kv_stride_tokens,
4853 ith, nth)) {
4854 __atomic_store_n(&args->failed, 1, __ATOMIC_RELAXED);
4855 }
4856}
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 5254 of file attention_kernels.c.

5255{
5256 const ck_attention_causal_f16kv_args_t *args =
5257 (const ck_attention_causal_f16kv_args_t *)opaque;
5258 const float scale = 1.0f / sqrtf((float)args->head_dim);
5259 const int T = args->num_tokens;
5260 const size_t kv_head_stride =
5261 (size_t)args->kv_stride_tokens * (size_t)args->aligned_head_dim;
5262
5263 for (int h = ith; h < args->num_heads; h += nth) {
5264 const int kv_head = (int)((long long)h * (long long)args->num_kv_heads /
5265 (long long)args->num_heads);
5266 const float *k_head = args->k + (size_t)kv_head * kv_head_stride;
5267 const float *v_head = args->v + (size_t)kv_head * kv_head_stride;
5268
5269 for (int i = 0; i < T; ++i) {
5270 const float *q_vec = args->q +
5271 qkv_index(h, i, 0, T, args->aligned_head_dim);
5272 float *out_vec = args->output +
5273 qkv_index(h, i, 0, T, args->aligned_head_dim);
5274 if (args->inputs_prerounded) {
5276 q_vec, k_head, v_head, /*kv_tokens=*/i + 1,
5277 args->head_dim, args->aligned_head_dim, scale, out_vec);
5278 } else {
5280 q_vec, k_head, v_head, /*kv_tokens=*/i + 1,
5281 args->head_dim, args->aligned_head_dim, scale, out_vec);
5282 }
5283 }
5284 }
5285}
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 6214 of file attention_kernels.c.

6217{
6218 int i = 0;
6219#if defined(__AVX512F__)
6220 // Match ggml's AVX-512 FP16-to-FP32 path: four 16-lane
6221 // accumulators per 64 values, then its fixed pairwise tree.
6222 __m512 sum0 = _mm512_setzero_ps();
6223 __m512 sum1 = _mm512_setzero_ps();
6224 __m512 sum2 = _mm512_setzero_ps();
6225 __m512 sum3 = _mm512_setzero_ps();
6226 const int n64 = n & ~63;
6227 for (; i < n64; i += 64) {
6228 const __m512 x0 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i)));
6229 const __m512 y0 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i)));
6230 const __m512 x1 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i + 16)));
6231 const __m512 y1 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i + 16)));
6232 const __m512 x2 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i + 32)));
6233 const __m512 y2 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i + 32)));
6234 const __m512 x3 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (x + i + 48)));
6235 const __m512 y3 = _mm512_cvtph_ps(_mm256_loadu_si256((const __m256i *) (y + i + 48)));
6236 sum0 = _mm512_fmadd_ps(x0, y0, sum0);
6237 sum1 = _mm512_fmadd_ps(x1, y1, sum1);
6238 sum2 = _mm512_fmadd_ps(x2, y2, sum2);
6239 sum3 = _mm512_fmadd_ps(x3, y3, sum3);
6240 }
6241 sum0 = _mm512_add_ps(sum0, sum2);
6242 sum1 = _mm512_add_ps(sum1, sum3);
6243 sum0 = _mm512_add_ps(sum0, sum1);
6244 const float vector_result = _mm512_reduce_add_ps(sum0);
6245#elif defined(__AVX2__) && defined(__F16C__)
6246 // Match ggml_vec_dot_f16's AVX reduction contract: four independent
6247 // accumulators per 32 values, followed by its fixed pairwise tree.
6248 __m256 sum0 = _mm256_setzero_ps();
6249 __m256 sum1 = _mm256_setzero_ps();
6250 __m256 sum2 = _mm256_setzero_ps();
6251 __m256 sum3 = _mm256_setzero_ps();
6252 const int n32 = n & ~31;
6253 for (; i < n32; i += 32) {
6254 const __m256 x0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i)));
6255 const __m256 y0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i)));
6256 const __m256 x1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 8)));
6257 const __m256 y1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 8)));
6258 const __m256 x2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 16)));
6259 const __m256 y2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 16)));
6260 const __m256 x3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 24)));
6261 const __m256 y3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 24)));
6262#if defined(__FMA__)
6263 sum0 = _mm256_fmadd_ps(x0, y0, sum0);
6264 sum1 = _mm256_fmadd_ps(x1, y1, sum1);
6265 sum2 = _mm256_fmadd_ps(x2, y2, sum2);
6266 sum3 = _mm256_fmadd_ps(x3, y3, sum3);
6267#else
6268 sum0 = _mm256_add_ps(sum0, _mm256_mul_ps(x0, y0));
6269 sum1 = _mm256_add_ps(sum1, _mm256_mul_ps(x1, y1));
6270 sum2 = _mm256_add_ps(sum2, _mm256_mul_ps(x2, y2));
6271 sum3 = _mm256_add_ps(sum3, _mm256_mul_ps(x3, y3));
6272#endif
6273 }
6274 sum0 = _mm256_add_ps(sum0, sum2);
6275 sum1 = _mm256_add_ps(sum1, sum3);
6276 sum0 = _mm256_add_ps(sum0, sum1);
6277 const __m128 pair = _mm_add_ps(
6278 _mm256_castps256_ps128(sum0),
6279 _mm256_extractf128_ps(sum0, 1));
6280 const __m128 half = _mm_hadd_ps(pair, pair);
6281 const float vector_result = _mm_cvtss_f32(_mm_hadd_ps(half, half));
6282#else
6283 const float vector_result = 0.0f;
6284#endif
6285 /* ggml_vec_dot_f16 stores the SIMD reduction in ggml_float (double) and
6286 * accumulates any scalar tail there. This matters for head dimensions
6287 * below or not divisible by the active ISA step (for example D=32 on
6288 * AVX-512 and padded D=80). */
6289 double result = (double) vector_result;
6290 for (; i < n; ++i) {
6291 const float product = CK_FP16_TO_FP32(x[i]) * CK_FP16_TO_FP32(y[i]);
6292 result += (double) product;
6293 }
6294 return (float) result;
6295}

References CK_FP16_TO_FP32.

Referenced by 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 1105 of file attention_kernels.c.

1108{
1109 int i = 0;
1110#if defined(__AVX2__) && defined(__F16C__)
1111 __m256 sum0 = _mm256_setzero_ps();
1112 __m256 sum1 = _mm256_setzero_ps();
1113 __m256 sum2 = _mm256_setzero_ps();
1114 __m256 sum3 = _mm256_setzero_ps();
1115 const int n32 = n & ~31;
1116 for (; i < n32; i += 32) {
1117 const __m256 x0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i)));
1118 const __m256 y0 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i)));
1119 const __m256 x1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 8)));
1120 const __m256 y1 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 8)));
1121 const __m256 x2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 16)));
1122 const __m256 y2 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 16)));
1123 const __m256 x3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (x + i + 24)));
1124 const __m256 y3 = _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *) (y + i + 24)));
1125#if defined(__FMA__)
1126 sum0 = _mm256_fmadd_ps(x0, y0, sum0);
1127 sum1 = _mm256_fmadd_ps(x1, y1, sum1);
1128 sum2 = _mm256_fmadd_ps(x2, y2, sum2);
1129 sum3 = _mm256_fmadd_ps(x3, y3, sum3);
1130#else
1131 sum0 = _mm256_add_ps(sum0, _mm256_mul_ps(x0, y0));
1132 sum1 = _mm256_add_ps(sum1, _mm256_mul_ps(x1, y1));
1133 sum2 = _mm256_add_ps(sum2, _mm256_mul_ps(x2, y2));
1134 sum3 = _mm256_add_ps(sum3, _mm256_mul_ps(x3, y3));
1135#endif
1136 }
1137 sum0 = _mm256_add_ps(sum0, sum2);
1138 sum1 = _mm256_add_ps(sum1, sum3);
1139 sum0 = _mm256_add_ps(sum0, sum1);
1140 const __m128 pair = _mm_add_ps(
1141 _mm256_castps256_ps128(sum0),
1142 _mm256_extractf128_ps(sum0, 1));
1143 const __m128 half = _mm_hadd_ps(pair, pair);
1144 float result = _mm_cvtss_f32(_mm_hadd_ps(half, half));
1145#else
1146 float result = 0.0f;
1147#endif
1148 for (; i < n; ++i) {
1149 result += CK_FP16_TO_FP32(x[i]) * CK_FP16_TO_FP32(y[i]);
1150 }
1151 return result;
1152}

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 6943 of file attention_kernels.c.

6944{
6945 const ck_attention_f16_prefill_gqa_reuse_args_t *args =
6946 (const ck_attention_f16_prefill_gqa_reuse_args_t *) opaque;
6947 const ck_attention_f16_prefill_qtile64_args_t *base = &args->base;
6948 const int lanes = nth / base->num_kv_heads;
6949 const int kv_group = ith / lanes;
6950 const int lane = ith % lanes;
6951 const int heads_per_group = base->num_heads / base->num_kv_heads;
6952 const int head_begin = kv_group * heads_per_group;
6953 const int query_tiles =
6954 (base->q_tokens + args->query_tile_size - 1) / args->query_tile_size;
6955 const int kv_tokens = base->past_tokens + base->q_tokens;
6956 const float scale = ck_attention_strict_scale_f32(base->head_dim);
6957 const size_t kv_head_stride =
6958 (size_t) base->cache_capacity * (size_t) base->aligned_head_dim;
6959 const uint16_t *k_head =
6960 base->k_cache + (size_t) kv_group * kv_head_stride;
6961 const uint16_t *v_head =
6962 base->v_cache + (size_t) kv_group * kv_head_stride;
6963 float *shared_k = args->shared_k_tiles +
6964 (size_t) kv_group * (size_t) base->head_dim * CK_GGML_FA_TILE_KV;
6965 float *shared_v = args->shared_v_tiles +
6966 (size_t) kv_group * CK_GGML_FA_TILE_KV * (size_t) base->head_dim;
6967 ck_attention_gqa_team_barrier_t *barrier = &args->barriers[kv_group];
6968 const int max_group_jobs =
6969 heads_per_group * args->concurrent_query_tiles;
6970 const int local_capacity = (max_group_jobs + lanes - 1) / lanes;
6971 unsigned char *worker = args->worker_workspace +
6972 (size_t) ith * args->worker_workspace_stride;
6973 size_t cursor = 0;
6974 cursor = ck_attention_align64_size(cursor);
6975 int *local_heads = (int *) (worker + cursor);
6976 cursor += (size_t) local_capacity * sizeof(int);
6977 int *local_iq = (int *) (worker + cursor);
6978 cursor += (size_t) local_capacity * sizeof(int);
6979 int *local_rows = (int *) (worker + cursor);
6980 cursor += (size_t) local_capacity * sizeof(int);
6981 cursor = ck_attention_align64_size(cursor);
6982 float *q_tiles = (float *) (worker + cursor);
6983 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
6984 (size_t) base->head_dim * sizeof(float);
6985 cursor = ck_attention_align64_size(cursor);
6986 float *kq_tiles = (float *) (worker + cursor);
6987 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
6988 CK_GGML_FA_TILE_KV * sizeof(float);
6989 cursor = ck_attention_align64_size(cursor);
6990 float *vkq_tiles = (float *) (worker + cursor);
6991 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
6992 (size_t) base->head_dim * sizeof(float);
6993 cursor = ck_attention_align64_size(cursor);
6994 float *sum_rows = (float *) (worker + cursor);
6995 cursor += (size_t) local_capacity * (size_t) args->query_tile_size *
6996 sizeof(float);
6997 cursor = ck_attention_align64_size(cursor);
6998 float *max_rows = (float *) (worker + cursor);
6999
7000 for (int query_tile_begin = 0; query_tile_begin < query_tiles;
7001 query_tile_begin += args->concurrent_query_tiles) {
7002 int batch_tiles = query_tiles - query_tile_begin;
7003 if (batch_tiles > args->concurrent_query_tiles) {
7004 batch_tiles = args->concurrent_query_tiles;
7005 }
7006 const int group_jobs = heads_per_group * batch_tiles;
7007 int local_jobs = 0;
7008
7009 for (int group_job = lane; group_job < group_jobs; group_job += lanes) {
7010 const int local = local_jobs++;
7011 const int group_head = group_job / batch_tiles;
7012 const int batch_tile = group_job % batch_tiles;
7013 const int h = head_begin + group_head;
7014 const int iq =
7015 (query_tile_begin + batch_tile) * args->query_tile_size;
7016 int tile_rows = base->q_tokens - iq;
7017 if (tile_rows > args->query_tile_size) {
7018 tile_rows = args->query_tile_size;
7019 }
7020 local_heads[local] = h;
7021 local_iq[local] = iq;
7022 local_rows[local] = tile_rows;
7023
7024 float *q_tile = q_tiles +
7025 (size_t) local * (size_t) args->query_tile_size *
7026 (size_t) base->head_dim;
7027 float *vkq = vkq_tiles +
7028 (size_t) local * (size_t) args->query_tile_size *
7029 (size_t) base->head_dim;
7030 float *sum_row = sum_rows +
7031 (size_t) local * (size_t) args->query_tile_size;
7032 float *max_row = max_rows +
7033 (size_t) local * (size_t) args->query_tile_size;
7034 memset(q_tile, 0,
7035 (size_t) args->query_tile_size * (size_t) base->head_dim *
7036 sizeof(float));
7037 memset(vkq, 0,
7038 (size_t) args->query_tile_size * (size_t) base->head_dim *
7039 sizeof(float));
7040 for (int tq = 0; tq < args->query_tile_size; ++tq) {
7041 sum_row[tq] = 0.0f;
7042 max_row[tq] = -INFINITY;
7043 }
7044 for (int tq = 0; tq < tile_rows; ++tq) {
7045 const float *q_vec = base->q +
7046 (size_t) h * base->q_head_stride +
7047 (size_t) (iq + tq) * (size_t) base->aligned_head_dim;
7048 memcpy(q_tile + (size_t) tq * (size_t) base->head_dim,
7049 q_vec, (size_t) base->head_dim * sizeof(float));
7050 }
7051 }
7052
7053 int kv_limit = base->past_tokens +
7054 (query_tile_begin + batch_tiles) * args->query_tile_size;
7055 if (kv_limit > kv_tokens) kv_limit = kv_tokens;
7056
7057 for (int ik = 0; ik < kv_limit; ik += CK_GGML_FA_TILE_KV) {
7058 int kv_tile = kv_limit - ik;
7059 if (kv_tile > CK_GGML_FA_TILE_KV) kv_tile = CK_GGML_FA_TILE_KV;
7060 const int packed_elems = CK_GGML_FA_TILE_KV * base->head_dim;
7061 for (int flat = lane; flat < packed_elems; flat += lanes) {
7062 const int tk = flat / base->head_dim;
7063 const int d = flat % base->head_dim;
7064 float k_value = 0.0f;
7065 float v_value = 0.0f;
7066 if (tk < kv_tile) {
7067 const uint16_t *k_vec = k_head +
7068 (size_t) (ik + tk) * (size_t) base->aligned_head_dim;
7069 const uint16_t *v_vec = v_head +
7070 (size_t) (ik + tk) * (size_t) base->aligned_head_dim;
7072 k_vec[d], base->cache_is_bf16);
7074 v_vec[d], base->cache_is_bf16);
7075 }
7076 shared_k[(size_t) d * CK_GGML_FA_TILE_KV + (size_t) tk] =
7077 k_value;
7078 shared_v[(size_t) tk * (size_t) base->head_dim + (size_t) d] =
7079 v_value;
7080 }
7082
7083 for (int local = 0; local < local_jobs; ++local) {
7084 const int iq = local_iq[local];
7085 const int tile_rows = local_rows[local];
7086 float *q_tile = q_tiles +
7087 (size_t) local * (size_t) args->query_tile_size *
7088 (size_t) base->head_dim;
7089 float *kq = kq_tiles +
7090 (size_t) local * (size_t) args->query_tile_size *
7092 float *vkq = vkq_tiles +
7093 (size_t) local * (size_t) args->query_tile_size *
7094 (size_t) base->head_dim;
7095 float *sum_row = sum_rows +
7096 (size_t) local * (size_t) args->query_tile_size;
7097 float *max_row = max_rows +
7098 (size_t) local * (size_t) args->query_tile_size;
7099 memset(kq, 0,
7100 (size_t) args->query_tile_size * CK_GGML_FA_TILE_KV *
7101 sizeof(float));
7103 kq, q_tile, shared_k, args->query_tile_size,
7104 base->head_dim, CK_GGML_FA_TILE_KV);
7106 kq, args->query_tile_size * CK_GGML_FA_TILE_KV, scale);
7107
7108 for (int tq = 0; tq < args->query_tile_size; ++tq) {
7109 float *kq_row = kq + (size_t) tq * CK_GGML_FA_TILE_KV;
7110 const int last_valid_key = base->past_tokens + iq + tq;
7111 for (int tk = 0; tk < CK_GGML_FA_TILE_KV; ++tk) {
7112 const int key = ik + tk;
7113 if (tk >= kv_tile || tq >= tile_rows || key > last_valid_key) {
7114 kq_row[tk] = -INFINITY;
7115 }
7116 }
7117 const float tile_max =
7119 if (tile_max == -INFINITY) {
7120 memset(kq_row, 0,
7121 CK_GGML_FA_TILE_KV * sizeof(float));
7122 continue;
7123 }
7124 const float old_max = max_row[tq];
7125 const float new_max = old_max > tile_max ? old_max : tile_max;
7126 if (new_max > old_max) {
7127 const float ms =
7128 ck_attention_reference_expf(old_max - new_max);
7130 vkq + (size_t) tq * (size_t) base->head_dim,
7131 base->head_dim, ms);
7132 sum_row[tq] *= ms;
7133 }
7134 max_row[tq] = new_max;
7135 sum_row[tq] = (float) (
7136 (double) sum_row[tq] +
7138 CK_GGML_FA_TILE_KV, kq_row, kq_row, new_max));
7139 }
7141 vkq, kq, shared_v, args->query_tile_size,
7142 CK_GGML_FA_TILE_KV, base->head_dim);
7143 }
7145 }
7146
7147 for (int local = 0; local < local_jobs; ++local) {
7148 const int h = local_heads[local];
7149 const int iq = local_iq[local];
7150 const int tile_rows = local_rows[local];
7151 float *vkq = vkq_tiles +
7152 (size_t) local * (size_t) args->query_tile_size *
7153 (size_t) base->head_dim;
7154 float *sum_row = sum_rows +
7155 (size_t) local * (size_t) args->query_tile_size;
7156 for (int tq = 0; tq < tile_rows; ++tq) {
7157 float *out_vec = base->output +
7158 (size_t) h * base->output_head_stride +
7159 (size_t) (iq + tq) * (size_t) base->aligned_head_dim;
7160 const float inv_sum =
7161 sum_row[tq] == 0.0f ? 0.0f : 1.0f / sum_row[tq];
7162 for (int d = 0; d < base->head_dim; ++d) {
7163 out_vec[d] = vkq[
7164 (size_t) tq * (size_t) base->head_dim + (size_t) d] *
7165 inv_sum;
7166 }
7167 for (int d = base->head_dim; d < base->aligned_head_dim; ++d) {
7168 out_vec[d] = 0.0f;
7169 }
7170 }
7171 }
7172 }
7173}
static float ck_attention_u16_cache_to_f32(uint16_t value, int cache_is_bf16)
static float ck_attention_reference_expf(float value)
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 6678 of file attention_kernels.c.

6685{
6686 if (num_heads <= 0 || num_kv_heads <= 0 ||
6687 num_heads % num_kv_heads != 0 || workers < num_kv_heads ||
6688 workers % num_kv_heads != 0 || head_dim <= 0 ||
6689 query_tile_size <= 0 || concurrent_query_tiles <= 0) {
6690 return 0;
6691 }
6692 const int lanes = workers / num_kv_heads;
6693 const int group_jobs =
6694 (num_heads / num_kv_heads) * concurrent_query_tiles;
6695 const size_t local_capacity =
6696 (size_t) (group_jobs + lanes - 1) / (size_t) lanes;
6697 size_t bytes = 0;
6698 bytes = ck_attention_align64_size(bytes) +
6699 3u * local_capacity * sizeof(int);
6700 bytes = ck_attention_align64_size(bytes) +
6701 local_capacity * (size_t) query_tile_size * (size_t) head_dim *
6702 sizeof(float);
6703 bytes = ck_attention_align64_size(bytes) +
6704 local_capacity * (size_t) query_tile_size * CK_GGML_FA_TILE_KV *
6705 sizeof(float);
6706 bytes = ck_attention_align64_size(bytes) +
6707 local_capacity * (size_t) query_tile_size * (size_t) head_dim *
6708 sizeof(float);
6709 bytes = ck_attention_align64_size(bytes) +
6710 local_capacity * (size_t) query_tile_size * sizeof(float);
6711 bytes = ck_attention_align64_size(bytes) +
6712 local_capacity * (size_t) query_tile_size * sizeof(float);
6713 return ck_attention_align64_size(bytes);
6714}

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,
size_t  q_head_stride,
size_t  output_head_stride,
ck_attention_prefill_schedule_t  schedule 
)
static

Definition at line 7175 of file attention_kernels.c.

7191{
7192 if (schedule < CK_ATTN_PREFILL_SCHEDULE_KV_HEADS ||
7195 }
7196 ck_attention_f16_prefill_qtile64_args_t args = {
7197 .q = q,
7198 .k_cache = k_cache,
7199 .v_cache = v_cache,
7200 .output = output,
7201 .num_heads = num_heads,
7202 .num_kv_heads = num_kv_heads,
7203 .q_tokens = q_tokens,
7204 .past_tokens = past_tokens,
7205 .cache_capacity = cache_capacity,
7206 .head_dim = head_dim,
7207 .aligned_head_dim = aligned_head_dim,
7208 .cache_is_bf16 = cache_is_bf16,
7209 .schedule = schedule,
7210 .q_head_stride = q_head_stride,
7211 .output_head_stride = output_head_stride,
7212 };
7213 ck_threadpool_t *pool = ck_threadpool_global();
7214 int active = pool ? ck_threadpool_n_threads(pool) : 1;
7215 const int query_tiles =
7216 (q_tokens + CK_GGML_FA_TILE_Q - 1) / CK_GGML_FA_TILE_Q;
7217 int available_jobs = num_heads;
7218 if (schedule == CK_ATTN_PREFILL_SCHEDULE_KV_HEADS) {
7219 available_jobs = num_kv_heads;
7220 } else if (schedule == CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES ||
7222 available_jobs = num_heads * query_tiles;
7223 }
7224 if (active > available_jobs) active = available_jobs;
7225 if (pool && active > 1 && ck_threadpool_thread_id(pool) <= 0) {
7227 pool, active, ck_attention_f16_prefill_qtile64_work, &args);
7228 } else {
7230 }
7232}
@ 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(), and attention_forward_causal_head_major_gqa_prefill_append_f16cache_qtile64_schedule().

◆ ck_attention_f16_prefill_qtile64_work()

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

Definition at line 6765 of file attention_kernels.c.

6766{
6767 const ck_attention_f16_prefill_qtile64_args_t *args =
6768 (const ck_attention_f16_prefill_qtile64_args_t *) opaque;
6769 const int query_tiles =
6770 (args->q_tokens + CK_GGML_FA_TILE_Q - 1) / CK_GGML_FA_TILE_Q;
6771 const int total_jobs = args->num_heads * query_tiles;
6772 int job_begin = 0;
6773 int job_end = 0;
6774
6775 if (args->schedule == CK_ATTN_PREFILL_SCHEDULE_KV_GROUP_QUERY_TILES &&
6776 nth >= args->num_kv_heads) {
6777 const int kv_group = (ith * args->num_kv_heads) / nth;
6778 const int worker_begin =
6779 (kv_group * nth + args->num_kv_heads - 1) / args->num_kv_heads;
6780 const int worker_end =
6781 ((kv_group + 1) * nth + args->num_kv_heads - 1) /
6782 args->num_kv_heads;
6783 const int lane = ith - worker_begin;
6784 const int lanes = worker_end - worker_begin;
6785 const int head_begin =
6786 (kv_group * args->num_heads + args->num_kv_heads - 1) /
6787 args->num_kv_heads;
6788 const int head_end =
6789 ((kv_group + 1) * args->num_heads + args->num_kv_heads - 1) /
6790 args->num_kv_heads;
6791 const int group_jobs = (head_end - head_begin) * query_tiles;
6792 job_begin = head_begin * query_tiles + (group_jobs * lane) / lanes;
6793 job_end = head_begin * query_tiles + (group_jobs * (lane + 1)) / lanes;
6794 } else if (args->schedule == CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES) {
6795 job_begin = (total_jobs * ith) / nth;
6796 job_end = (total_jobs * (ith + 1)) / nth;
6797 } else {
6798 const int head_begin = (args->num_heads * ith) / nth;
6799 const int head_end = (args->num_heads * (ith + 1)) / nth;
6800 job_begin = head_begin * query_tiles;
6801 job_end = head_end * query_tiles;
6802 }
6803 if (job_begin >= job_end) return;
6804
6805 const int kv_tokens = args->past_tokens + args->q_tokens;
6806 const float scale = ck_attention_strict_scale_f32(args->head_dim);
6807 const size_t kv_head_stride =
6808 (size_t) args->cache_capacity * (size_t) args->aligned_head_dim;
6809
6810 float *q_tile = (float *) alloca(
6811 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
6812 float *k_tile = (float *) alloca(
6813 (size_t) args->head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
6814 float *v_tile = (float *) alloca(
6815 (size_t) CK_GGML_FA_TILE_KV * (size_t) args->head_dim * sizeof(float));
6816 float *kq = (float *) alloca(
6817 (size_t) CK_GGML_FA_TILE_Q * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
6818 float *vkq = (float *) alloca(
6819 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
6820
6821 for (int job = job_begin; job < job_end; ++job) {
6822 const int h = job / query_tiles;
6823 const int iq = (job % query_tiles) * CK_GGML_FA_TILE_Q;
6824 const int kv_head =
6825 (int) ((long long) h * (long long) args->num_kv_heads /
6826 (long long) args->num_heads);
6827 const uint16_t *k_head = args->k_cache + (size_t) kv_head * kv_head_stride;
6828 const uint16_t *v_head = args->v_cache + (size_t) kv_head * kv_head_stride;
6829
6830 const int tile_rows =
6831 (args->q_tokens - iq) < CK_GGML_FA_TILE_Q
6832 ? (args->q_tokens - iq)
6834 float sum_row[CK_GGML_FA_TILE_Q];
6835 float max_row[CK_GGML_FA_TILE_Q];
6836
6837 for (int tq = 0; tq < CK_GGML_FA_TILE_Q; ++tq) {
6838 sum_row[tq] = 0.0f;
6839 max_row[tq] = -INFINITY;
6840 }
6841 memset(q_tile, 0,
6842 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
6843 memset(vkq, 0,
6844 (size_t) CK_GGML_FA_TILE_Q * (size_t) args->head_dim * sizeof(float));
6845
6846 for (int tq = 0; tq < tile_rows; ++tq) {
6847 const float *q_vec = args->q +
6848 (size_t) h * args->q_head_stride +
6849 (size_t) (iq + tq) * (size_t) args->aligned_head_dim;
6850 memcpy(q_tile + (size_t) tq * (size_t) args->head_dim,
6851 q_vec,
6852 (size_t) args->head_dim * sizeof(float));
6853 }
6854
6855 for (int ik = 0; ik < kv_tokens; ik += CK_GGML_FA_TILE_KV) {
6856 const int kv_tile =
6857 (kv_tokens - ik) < CK_GGML_FA_TILE_KV
6858 ? (kv_tokens - ik)
6860 memset(k_tile, 0,
6861 (size_t) args->head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
6862 memset(v_tile, 0,
6863 (size_t) CK_GGML_FA_TILE_KV * (size_t) args->head_dim * sizeof(float));
6864 memset(kq, 0,
6865 (size_t) CK_GGML_FA_TILE_Q * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
6866
6867 for (int tk = 0; tk < kv_tile; ++tk) {
6868 const uint16_t *k_vec = k_head +
6869 (size_t) (ik + tk) * (size_t) args->aligned_head_dim;
6870 const uint16_t *v_vec = v_head +
6871 (size_t) (ik + tk) * (size_t) args->aligned_head_dim;
6872 for (int d = 0; d < args->head_dim; ++d) {
6873 k_tile[(size_t) d * (size_t) CK_GGML_FA_TILE_KV + (size_t) tk] =
6874 ck_attention_u16_cache_to_f32(k_vec[d], args->cache_is_bf16);
6875 v_tile[(size_t) tk * (size_t) args->head_dim + (size_t) d] =
6876 ck_attention_u16_cache_to_f32(v_vec[d], args->cache_is_bf16);
6877 }
6878 }
6879
6881 kq, q_tile, k_tile,
6882 CK_GGML_FA_TILE_Q, args->head_dim, CK_GGML_FA_TILE_KV);
6885
6886 for (int tq = 0; tq < CK_GGML_FA_TILE_Q; ++tq) {
6887 float *kq_row = kq +
6888 (size_t) tq * (size_t) CK_GGML_FA_TILE_KV;
6889 const int last_valid_key = args->past_tokens + iq + tq;
6890 for (int tk = 0; tk < CK_GGML_FA_TILE_KV; ++tk) {
6891 const int key = ik + tk;
6892 if (tk >= kv_tile || tq >= tile_rows || key > last_valid_key) {
6893 kq_row[tk] = -INFINITY;
6894 }
6895 }
6896
6897 const float tile_max =
6899 if (tile_max == -INFINITY) {
6900 memset(kq_row, 0,
6901 (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
6902 continue;
6903 }
6904
6905 const float old_max = max_row[tq];
6906 const float new_max = old_max > tile_max ? old_max : tile_max;
6907 if (new_max > old_max) {
6908 const float ms = ck_attention_reference_expf(old_max - new_max);
6910 vkq + (size_t) tq * (size_t) args->head_dim,
6911 args->head_dim, ms);
6912 sum_row[tq] *= ms;
6913 }
6914 max_row[tq] = new_max;
6915 sum_row[tq] = (float) (
6916 (double) sum_row[tq] +
6918 CK_GGML_FA_TILE_KV, kq_row, kq_row, new_max));
6919 }
6920
6922 vkq, kq, v_tile,
6923 CK_GGML_FA_TILE_Q, CK_GGML_FA_TILE_KV, args->head_dim);
6924 }
6925
6926 for (int tq = 0; tq < tile_rows; ++tq) {
6927 float *out_vec = args->output +
6928 (size_t) h * args->output_head_stride +
6929 (size_t) (iq + tq) * (size_t) args->aligned_head_dim;
6930 const float inv_sum =
6931 sum_row[tq] == 0.0f ? 0.0f : 1.0f / sum_row[tq];
6932 for (int d = 0; d < args->head_dim; ++d) {
6933 out_vec[d] =
6934 vkq[(size_t) tq * (size_t) args->head_dim + (size_t) d] * inv_sum;
6935 }
6936 for (int d = args->head_dim; d < args->aligned_head_dim; ++d) {
6937 out_vec[d] = 0.0f;
6938 }
6939 }
6940 }
6941}

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 6377 of file attention_kernels.c.

6378{
6379 ck_attention_f16_split_args_t *args = (ck_attention_f16_split_args_t *) opaque;
6380 const int partial_stride = args->aligned_head_dim + 2;
6381 const int total_jobs = args->num_heads * args->scheduled_chunks;
6382 const int chunk_size =
6383 (args->partition_tokens + args->split_chunks - 1) / args->split_chunks;
6384 const size_t head_stride = (size_t) args->cache_capacity * (size_t) args->aligned_head_dim;
6385 const float scale = ck_attention_strict_scale_f32(args->head_dim);
6386 uint16_t *q_half = (uint16_t *) alloca((size_t) args->aligned_head_dim * sizeof(uint16_t));
6387 uint16_t *acc_half = (uint16_t *) alloca((size_t) args->aligned_head_dim * sizeof(uint16_t));
6388
6389 for (int job = ith; job < total_jobs; job += nth) {
6390 const int h = job / args->scheduled_chunks;
6391 const int chunk = job % args->scheduled_chunks;
6392 const int kv_head = (int) ((long long) h * (long long) args->num_kv_heads /
6393 (long long) args->num_heads);
6394 const int begin = chunk * chunk_size;
6395 const int end = begin < args->kv_tokens
6396 ? (begin + chunk_size < args->kv_tokens ? begin + chunk_size : args->kv_tokens)
6397 : begin;
6398 const float *q_head = args->q_token + (size_t) h * (size_t) args->aligned_head_dim;
6399 const uint16_t *k_head = args->k_cache + (size_t) kv_head * head_stride;
6400 const uint16_t *v_head = args->v_cache + (size_t) kv_head * head_stride;
6401 float *partial = args->partials + (size_t) job * (size_t) partial_stride;
6402
6403 for (int d = 0; d < args->aligned_head_dim; ++d) {
6404 q_half[d] = CK_FP32_TO_FP16(q_head[d]);
6405 acc_half[d] = CK_FP32_TO_FP16(0.0f);
6406 }
6407
6408 float sum = 0.0f;
6409 float max_score = -INFINITY;
6410 for (int j = begin; j < end; ++j) {
6411 const uint16_t *k_vec = k_head + (size_t) j * (size_t) args->aligned_head_dim;
6412 const uint16_t *v_vec = v_head + (size_t) j * (size_t) args->aligned_head_dim;
6413 const float dot = ck_attention_dot_f16_llama(q_half, k_vec, args->head_dim);
6414 const float score = dot * scale;
6415 const float old_max = max_score;
6416 float max_scale = 1.0f;
6417 float value_scale = 1.0f;
6418
6419 if (score > max_score) {
6420 max_score = score;
6421 max_scale = isfinite(old_max)
6422 ? ck_attention_reference_expf(old_max - max_score)
6423 : 0.0f;
6424 ck_attention_scale_f16_llama(acc_half, max_scale, args->head_dim);
6425 } else {
6426 value_scale = ck_attention_reference_expf(score - max_score);
6427 }
6428
6430 acc_half, v_vec, value_scale, args->head_dim);
6431#if defined(__INTEL_LLVM_COMPILER)
6432 sum = ck_attention_mul_add_rounded_f32(
6433 sum, max_scale, value_scale);
6434#else
6435 sum = fmaf(sum, max_scale, value_scale);
6436#endif
6437 }
6438
6439 partial[0] = max_score;
6440 partial[1] = sum;
6441 for (int d = 0; d < args->head_dim; ++d) {
6442 partial[2 + d] = CK_FP16_TO_FP32(acc_half[d]);
6443 }
6444 for (int d = args->head_dim; d < args->aligned_head_dim; ++d) {
6445 partial[2 + d] = 0.0f;
6446 }
6447 }
6448}
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)
static float ck_attention_dot_f16_llama(const uint16_t *x, const uint16_t *y, 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_attention_strict_scale_f32(), 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 3641 of file attention_kernels.c.

3649{
3650#if defined(__AVX512F__)
3651 attention_flash_query_causal_avx512(q_vec, k_head, v_head,
3652 kv_tokens, head_dim, aligned_head_dim,
3653 scale, out_vec);
3654#elif defined(__AVX2__)
3655 attention_flash_query_causal_avx2(q_vec, k_head, v_head,
3656 kv_tokens, head_dim, aligned_head_dim,
3657 scale, out_vec);
3658#elif defined(__AVX__)
3659 attention_flash_query_causal_avx(q_vec, k_head, v_head,
3660 kv_tokens, head_dim, aligned_head_dim,
3661 scale, out_vec);
3662#else
3663 attention_flash_query_causal(q_vec, k_head, v_head,
3664 kv_tokens, head_dim, aligned_head_dim,
3665 scale, out_vec);
3666#endif
3667}
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 7503 of file attention_kernels.c.

7521{
7522 if (!q || !k_cache || !v_cache || !output || !segment_lengths ||
7523 num_segments <= 0 || num_heads <= 0 || num_kv_heads <= 0 ||
7524 q_tokens <= 0 || past_tokens < 0 || past_tokens + q_tokens > cache_capacity ||
7525 head_dim <= 0 || aligned_head_dim < head_dim) {
7527 }
7528 int planned_rows = 0;
7529 for (int s = 0; s < num_segments; ++s) {
7530 if (segment_lengths[s] < 0 || segment_lengths[s] > q_tokens - planned_rows) {
7532 }
7533 planned_rows += segment_lengths[s];
7534 }
7535 if (planned_rows != q_tokens) return CK_ATTENTION_STATUS_INVALID_ARGUMENT;
7536
7537 const size_t head_stride = (size_t) q_tokens * (size_t) aligned_head_dim;
7538 const size_t token_elems = (size_t) num_heads * (size_t) aligned_head_dim;
7539 if (!token_workspace || token_workspace_bytes < 2 * token_elems * sizeof(float)) {
7541 }
7542
7543 int row_offset = 0;
7544 for (int s = 0; s < num_segments; ++s) {
7545 const int rows = segment_lengths[s];
7546 if (rows == 0) continue;
7548 rows >= CK_GGML_FA_TILE_Q) {
7549 ck_attention_f16_prefill_qtile64_args_t args = {
7550 .q = q + (size_t) row_offset * (size_t) aligned_head_dim,
7551 .k_cache = k_cache,
7552 .v_cache = v_cache,
7553 .output = output + (size_t) row_offset * (size_t) aligned_head_dim,
7554 .num_heads = num_heads,
7555 .num_kv_heads = num_kv_heads,
7556 .q_tokens = rows,
7557 .past_tokens = past_tokens + row_offset,
7558 .cache_capacity = cache_capacity,
7559 .head_dim = head_dim,
7560 .aligned_head_dim = aligned_head_dim,
7561 .cache_is_bf16 = 0,
7562 .schedule = schedule,
7563 .q_head_stride = head_stride,
7564 .output_head_stride = head_stride,
7565 };
7566 ck_threadpool_t *pool = ck_threadpool_global();
7567 int active = pool ? ck_threadpool_n_threads(pool) : 1;
7568 const int query_tiles =
7569 (rows + CK_GGML_FA_TILE_Q - 1) / CK_GGML_FA_TILE_Q;
7570 const int available_jobs =
7572 ? num_kv_heads
7573 : num_heads * query_tiles;
7574 if (active > available_jobs) active = available_jobs;
7575 if (pool && active > 1 && ck_threadpool_thread_id(pool) <= 0) {
7577 pool, active, ck_attention_f16_prefill_qtile64_work, &args);
7578 } else {
7580 }
7581 } else {
7582 float *q_token = token_workspace;
7583 float *out_token = token_workspace + token_elems;
7584 ck_attention_reduction_t selected = reduction;
7587 }
7588 for (int t = 0; t < rows; ++t) {
7589 for (int h = 0; h < num_heads; ++h) {
7590 memcpy(
7591 q_token + (size_t) h * (size_t) aligned_head_dim,
7592 q + (size_t) h * head_stride +
7593 (size_t) (row_offset + t) * (size_t) aligned_head_dim,
7594 (size_t) aligned_head_dim * sizeof(float));
7595 }
7596 ck_attention_status_t status =
7598 q_token, k_cache, v_cache, out_token,
7599 num_heads, num_kv_heads, past_tokens + row_offset + t + 1,
7600 cache_capacity, head_dim, aligned_head_dim, selected);
7601 if (status != CK_ATTENTION_STATUS_OK) return status;
7602 for (int h = 0; h < num_heads; ++h) {
7603 memcpy(
7604 output + (size_t) h * head_stride +
7605 (size_t) (row_offset + t) * (size_t) aligned_head_dim,
7606 out_token + (size_t) h * (size_t) aligned_head_dim,
7607 (size_t) aligned_head_dim * sizeof(float));
7608 }
7609 }
7610 }
7611 row_offset += rows;
7612 }
7614}
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_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 3486 of file attention_kernels.c.

3498{
3499 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
3500 num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim ||
3501 kv_stride_tokens < num_tokens || num_heads % num_kv_heads != 0) {
3502 return;
3503 }
3504
3505 ck_attention_full_tiled_f16kv_fp32_args_t args = {
3506 .q = q,
3507 .k = k,
3508 .v = v,
3509 .output = output,
3510 .num_heads = num_heads,
3511 .num_kv_heads = num_kv_heads,
3512 .num_tokens = num_tokens,
3513 .head_dim = head_dim,
3514 .aligned_head_dim = aligned_head_dim,
3515 .kv_stride_tokens = kv_stride_tokens,
3516 .query_tile_size = query_tile_size,
3517 };
3518 ck_threadpool_t *pool = ck_threadpool_global();
3519 const int active = pool ? ck_threadpool_n_threads(pool) : 1;
3520 if (pool && active > 1) {
3522 } else {
3524 }
3525}
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(), and attention_forward_query_key_head_major_f32_packed_k().

◆ 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 4870 of file attention_kernels.c.

4875{
4876 ck_attention_bf16_sdpa_args_t args = {
4877 .q=q, .k=k, .v=v, .output=output,
4878 .num_heads=num_heads, .num_kv_heads=num_kv_heads,
4879 .num_tokens=num_tokens, .head_dim=head_dim,
4880 .aligned_head_dim=aligned_head_dim, .kv_stride_tokens=kv_stride_tokens,
4881 .output_token_major=output_token_major,
4882 .failed=0
4883 };
4884 ck_threadpool_t *pool = ck_threadpool_global();
4885 int active = pool ? ck_threadpool_n_threads(pool) : 1;
4886 if (active > num_heads) active = num_heads;
4887 if (pool && active > 1) {
4889 pool, active, ck_attention_bf16_pytorch_flash_work, &args);
4890 } else {
4892 }
4893 return __atomic_load_n(&args.failed, __ATOMIC_RELAXED) == 0;
4894}
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 4616 of file attention_kernels.c.

4621{
4622#if defined(__AVX512F__)
4623 /*
4624 * This is a schedule contract, not merely an AMX acceleration of the
4625 * portable kernel. PyTorch CPU flash attention composes FP64 scale
4626 * evaluation, oneDNN-style BF16 BRGEMMs, AVX-512 exp/reductions, BF16
4627 * probability storage, and a second BRGEMM. When parity drifts, compare
4628 * this complete sequence with the PyTorch and oneDNN sources before
4629 * changing an isolated primitive or tolerance.
4630 */
4631 enum { Q_BLOCK = 256, KV_BLOCK = 512, K_PAD = 72, D_PAD = 80 };
4632 if (!ck_gemm_bf16_amx_available() || head_dim != 72 || aligned_head_dim != 72 ||
4633 (num_tokens % 16) != 0 || (kv_stride_tokens < num_tokens) ||
4634 num_heads % num_kv_heads != 0) return 0;
4635 uint16_t *q_block = malloc((size_t)Q_BLOCK * K_PAD * sizeof(uint16_t));
4636 uint16_t *k_packed = malloc((size_t)num_tokens * K_PAD * sizeof(uint16_t));
4637 uint16_t *probabilities = malloc((size_t)Q_BLOCK * KV_BLOCK * sizeof(uint16_t));
4638 uint16_t *v_packed = malloc((size_t)num_tokens * D_PAD * sizeof(uint16_t));
4639 float *scores = malloc((size_t)Q_BLOCK * KV_BLOCK * sizeof(float));
4640 float *destination = malloc((size_t)Q_BLOCK * D_PAD * sizeof(float));
4641 float *row_max = malloc((size_t)Q_BLOCK * sizeof(float));
4642 float *row_sum = malloc((size_t)Q_BLOCK * sizeof(float));
4643 if (!q_block || !k_packed || !probabilities || !v_packed || !scores ||
4644 !destination || !row_max || !row_sum) {
4645 free(q_block); free(k_packed); free(probabilities); free(v_packed);
4646 free(scores); free(destination); free(row_max); free(row_sum);
4647 return 0;
4648 }
4649 const float scale = ck_attention_pytorch_sdpa_scale_f32(head_dim);
4650 const size_t q_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
4651 const size_t kv_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
4652 for (int h = head_begin; h < num_heads; h += head_step) {
4653 const int kv_head = (int)((long long)h * num_kv_heads / num_heads);
4654 const float *qh = q + (size_t)h * q_stride;
4655 const float *kh = k + (size_t)kv_head * kv_stride;
4656 const float *vh = v + (size_t)kv_head * kv_stride;
4657 /*
4658 * K and V are invariant across all query blocks for this head. Pack
4659 * each 512-key tile once, retaining the exact block-local layouts
4660 * consumed by the two certified BRGEMMs below.
4661 */
4662 for (int n = 0; n < num_tokens; n += KV_BLOCK) {
4663 const int key_count = num_tokens - n < KV_BLOCK ? num_tokens - n : KV_BLOCK;
4664 uint16_t *k_block = k_packed + (size_t)n * K_PAD;
4665 uint16_t *v_block = v_packed + (size_t)n * D_PAD;
4666 memset(k_block, 0, (size_t)key_count * K_PAD * sizeof(uint16_t));
4667 memset(v_block, 0, (size_t)D_PAD * key_count * sizeof(uint16_t));
4668 for (int key = 0; key < key_count; ++key) {
4669 for (int d = 0; d < head_dim; ++d) {
4670 k_block[(size_t)key * K_PAD + d] =
4671 float_to_bf16(kh[(size_t)(n + key) * aligned_head_dim + d]);
4672 v_block[(size_t)d * key_count + key] =
4673 float_to_bf16(vh[(size_t)(n + key) * aligned_head_dim + d]);
4674 }
4675 }
4676 }
4677 for (int m = 0; m < num_tokens; m += Q_BLOCK) {
4678 const int query_count = num_tokens - m < Q_BLOCK ? num_tokens - m : Q_BLOCK;
4679 memset(q_block, 0, (size_t)query_count * K_PAD * sizeof(uint16_t));
4680 memset(destination, 0, (size_t)query_count * D_PAD * sizeof(float));
4681 for (int row = 0; row < query_count; ++row) {
4682 for (int d = 0; d < head_dim; ++d) {
4683 q_block[(size_t)row * K_PAD + d] =
4684 float_to_bf16(qh[(size_t)(m + row) * aligned_head_dim + d]);
4685 }
4686 row_max[row] = -INFINITY;
4687 row_sum[row] = 0.0f;
4688 }
4689 for (int n = 0; n < num_tokens; n += KV_BLOCK) {
4690 const int key_count = num_tokens - n < KV_BLOCK ? num_tokens - n : KV_BLOCK;
4691 const uint16_t *k_block = k_packed + (size_t)n * K_PAD;
4692 const uint16_t *v_block = v_packed + (size_t)n * D_PAD;
4694 q_block, k_block, scores,
4695 query_count, key_count, K_PAD, 0)) goto fail;
4696 for (int row = 0; row < query_count; ++row) {
4697 float *score_row = scores + (size_t)row * key_count;
4698 uint16_t *prob_row = probabilities + (size_t)row * key_count;
4699 const float block_max = ck_bf16_sdpa_scale_max_avx512(
4700 score_row, key_count, scale);
4701 const float merged_max = row_max[row] > block_max
4702 ? row_max[row] : block_max;
4703 const float old_scale = isfinite(row_max[row])
4704 ? expf(row_max[row] - merged_max) : 0.0f;
4705 const float block_sum = ck_bf16_sdpa_exp_sum_avx512(
4706 score_row, prob_row, key_count, merged_max);
4707 row_sum[row] = block_sum + old_scale * row_sum[row];
4708 row_max[row] = merged_max;
4709 if (n > 0) {
4710 __m512 scale_v = _mm512_set1_ps(old_scale);
4711 int d = 0;
4712 for (; d + 16 <= D_PAD; d += 16) {
4713 float *dst = destination + (size_t)row * D_PAD + d;
4714 _mm512_storeu_ps(dst, _mm512_mul_ps(_mm512_loadu_ps(dst), scale_v));
4715 }
4716 }
4717 }
4719 probabilities, v_block, destination,
4720 query_count, D_PAD, key_count, n > 0)) goto fail;
4721 }
4722 for (int row = 0; row < query_count; ++row) {
4723 const float reciprocal = row_sum[row] == 0.0f ? 1.0f : 1.0f / row_sum[row];
4724 float *out_row = output + (
4725 output_token_major
4726 ? ((size_t)(m + row) * (size_t)num_heads + (size_t)h)
4727 * (size_t)aligned_head_dim
4728 : ((size_t)h * (size_t)num_tokens + (size_t)(m + row))
4729 * (size_t)aligned_head_dim);
4730 for (int d = 0; d < head_dim; ++d) {
4731 out_row[d] = bf16_to_float(
4732 float_to_bf16(destination[(size_t)row * D_PAD + d] * reciprocal));
4733 }
4734 }
4735 }
4736 }
4737 free(q_block); free(k_packed); free(probabilities); free(v_packed);
4738 free(scores); free(destination); free(row_max); free(row_sum);
4739 return 1;
4740fail:
4741 free(q_block); free(k_packed); free(probabilities); free(v_packed);
4742 free(scores); free(destination); free(row_max); free(row_sum);
4743 return 0;
4744#else
4745 (void)q; (void)k; (void)v; (void)output; (void)num_heads;
4746 (void)num_kv_heads; (void)num_tokens; (void)head_dim;
4747 (void)aligned_head_dim; (void)kv_stride_tokens; (void)head_begin; (void)head_step;
4748 (void)output_token_major;
4749 return 0;
4750#endif
4751}
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 4896 of file attention_kernels.c.

4900{
4901 ck_attention_bf16_sdpa_args_t args = {
4902 .q=q, .k=k, .v=v, .output=output,
4903 .num_heads=num_heads, .num_kv_heads=num_kv_heads,
4904 .num_tokens=num_tokens, .head_dim=head_dim,
4905 .aligned_head_dim=aligned_head_dim, .kv_stride_tokens=kv_stride_tokens,
4906 .output_token_major=0,
4907 .failed=0
4908 };
4909 ck_threadpool_t *pool = ck_threadpool_global();
4910 int active = pool ? ck_threadpool_n_threads(pool) : 1;
4911 if (active > num_heads) active = num_heads;
4912 if (pool && active > 1) {
4914 } else {
4915 ck_attention_bf16_sdpa_work(0, 1, &args);
4916 }
4917 return __atomic_load_n(&args.failed, __ATOMIC_RELAXED) == 0;
4918}
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 4753 of file attention_kernels.c.

4758{
4759 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
4760 head_dim <= 0 || num_tokens <= 0 || aligned_head_dim < head_dim ||
4761 kv_stride_tokens < num_tokens || num_heads % num_kv_heads != 0) return 0;
4762 if ((size_t)num_tokens > SIZE_MAX / (size_t)head_dim) return 0;
4763 const size_t v_col_count = (size_t)head_dim * (size_t)num_tokens;
4764 if (v_col_count > SIZE_MAX / sizeof(float)) return 0;
4765 if ((size_t)num_tokens > SIZE_MAX / (size_t)aligned_head_dim) return 0;
4766 if ((size_t)kv_stride_tokens > SIZE_MAX / (size_t)aligned_head_dim) return 0;
4767 const float scale = ck_attention_pytorch_sdpa_scale_f32(head_dim);
4768 const size_t q_head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
4769 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
4770 if ((size_t)num_heads > SIZE_MAX / q_head_stride) return 0;
4771 if ((size_t)num_kv_heads > SIZE_MAX / kv_head_stride) return 0;
4772 float scores[512];
4773 float probs[512];
4774 float *v_cols = (float *)malloc(v_col_count * sizeof(float));
4775 if (!v_cols) return 0;
4776 for (int h = head_begin; h < num_heads; h += head_step) {
4777 const int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
4778 const float *qh = q + (size_t)h * q_head_stride;
4779 const float *kh = k + (size_t)kv_head * kv_head_stride;
4780 const float *vh = v + (size_t)kv_head * kv_head_stride;
4781 float *oh = output + (size_t)h * q_head_stride;
4782 for (int d = 0; d < head_dim; ++d) {
4783 float *col = v_cols + (size_t)d * (size_t)num_tokens;
4784 for (int t = 0; t < num_tokens; ++t) {
4785 col[t] = vh[(size_t)t * (size_t)aligned_head_dim + (size_t)d];
4786 }
4787 }
4788 for (int row = 0; row < num_tokens; ++row) {
4789 const float *qrow = qh + (size_t)row * (size_t)aligned_head_dim;
4790 float *dst = oh + (size_t)row * (size_t)aligned_head_dim;
4791 for (int d = 0; d < head_dim; ++d) dst[d] = 0.0f;
4792 float running_max = -INFINITY;
4793 float running_sum = 0.0f;
4794 for (int n = 0; n < num_tokens; n += 512) {
4795 const int block = num_tokens - n < 512 ? num_tokens - n : 512;
4796 float block_max = -INFINITY;
4797 for (int j = 0; j < block; ++j) {
4798 scores[j] = ck_bf16_dot_contract(
4799 qrow,
4800 kh + (size_t)(n + j) * (size_t)aligned_head_dim,
4801 head_dim) * scale;
4802 if (scores[j] > block_max) block_max = scores[j];
4803 }
4804 const float merged_max = running_max > block_max ? running_max : block_max;
4805 const float old_scale = isfinite(running_max) ? expf(running_max - merged_max) : 0.0f;
4806 float block_sum = 0.0f;
4807 for (int j = 0; j < block; ++j) {
4808 const float p = expf(scores[j] - merged_max);
4809 block_sum += p;
4810 probs[j] = bf16_to_float(float_to_bf16(p));
4811 }
4812 for (int d = 0; d < head_dim; ++d) {
4813 const float partial = ck_bf16_dot_contract(
4814 probs,
4815 v_cols + (size_t)d * (size_t)num_tokens + (size_t)n,
4816 block);
4817 dst[d] = dst[d] * old_scale + partial;
4818 }
4819 running_sum = running_sum * old_scale + block_sum;
4820 running_max = merged_max;
4821 }
4822 const float inv = running_sum > 0.0f ? 1.0f / running_sum : 0.0f;
4823 for (int d = 0; d < head_dim; ++d) dst[d] *= inv;
4824 for (int d = head_dim; d < aligned_head_dim; ++d) dst[d] = 0.0f;
4825 }
4826 }
4827 free(v_cols);
4828 return 1;
4829}
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 3959 of file attention_kernels.c.

3960{
3961 ck_attention_parallel_args_t *args = (ck_attention_parallel_args_t *) opaque;
3962 const int T = args->num_tokens;
3963 const int total = args->num_heads * T;
3964 const size_t kv_head_stride = (size_t) args->kv_stride_tokens * (size_t) args->aligned_head_dim;
3965
3966 for (int idx = ith; idx < total; idx += nth) {
3967 const int h = idx / T;
3968 const int i = idx - h * T;
3969 const int kv_head = (int) ((long long) h * (long long) args->num_kv_heads / (long long) args->num_heads);
3970 const float *k_head = args->k + (size_t) kv_head * kv_head_stride;
3971 const float *v_head = args->v + (size_t) kv_head * kv_head_stride;
3972 const float *q_vec = args->q + qkv_index(h, i, 0, T, args->aligned_head_dim);
3973 float *out_vec = args->output + attention_output_index(
3974 h, i, args->num_heads, T, args->aligned_head_dim,
3975 args->output_token_major);
3976 const int kv_tokens = args->causal ? (i + 1) : T;
3977 ck_attention_flash_query_auto(q_vec, k_head, v_head,
3978 kv_tokens,
3979 args->head_dim,
3980 args->aligned_head_dim,
3981 args->scale,
3982 out_vec);
3983 }
3984}
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 3314 of file attention_kernels.c.

3328{
3329 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
3330 num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim ||
3331 kv_stride_tokens < num_tokens || num_heads % num_kv_heads != 0 ||
3332 query_tile_size <= 0) {
3333 return;
3334 }
3335
3336 const float scale = ck_attention_strict_scale_f32(head_dim);
3337 const int T = num_tokens;
3338 const size_t kv_head_stride = (size_t) kv_stride_tokens * (size_t) aligned_head_dim;
3339
3340 float *q_tile = (float *) alloca((size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3341 float *k_tile = (float *) alloca((size_t) head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3342 float *v_tile = (float *) alloca((size_t) CK_GGML_FA_TILE_KV * (size_t) head_dim * sizeof(float));
3343 float *kq = (float *) alloca((size_t) query_tile_size * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3344 float *vkq = (float *) alloca((size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3345 float *sum_row = (float *) alloca((size_t) query_tile_size * sizeof(float));
3346 float *max_row = (float *) alloca((size_t) query_tile_size * sizeof(float));
3347
3348 const int total_rows = num_heads * T;
3349 const int rows_per_worker = (total_rows + nth - 1) / nth;
3350 int ir = rows_per_worker * ith;
3351 const int ir1 = (ir + rows_per_worker) < total_rows
3352 ? (ir + rows_per_worker)
3353 : total_rows;
3354
3355 while (ir < ir1) {
3356 const int h = ir / T;
3357 const int iq = ir - h * T;
3358 int tile_rows = ir1 - ir;
3359 if (tile_rows > query_tile_size) tile_rows = query_tile_size;
3360 if (tile_rows > T - iq) tile_rows = T - iq;
3361 const int kv_head = (int) ((long long) h * (long long) num_kv_heads / (long long) num_heads);
3362 const float *k_head = k + (size_t) kv_head * kv_head_stride;
3363 const float *v_head = v + (size_t) kv_head * kv_head_stride;
3364
3365 for (int tq = 0; tq < query_tile_size; ++tq) {
3366 sum_row[tq] = 0.0f;
3367 max_row[tq] = -INFINITY;
3368 }
3369
3370 memset(vkq, 0, (size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3371 memset(q_tile, 0, (size_t) query_tile_size * (size_t) head_dim * sizeof(float));
3372 memset(k_tile, 0, (size_t) head_dim * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3373 memset(v_tile, 0, (size_t) CK_GGML_FA_TILE_KV * (size_t) head_dim * sizeof(float));
3374
3375 for (int tq = 0; tq < tile_rows; ++tq) {
3376 const float *q_vec = q + qkv_index(h, iq + tq, 0, T, aligned_head_dim);
3377 memcpy(q_tile + (size_t) tq * (size_t) head_dim, q_vec, (size_t) head_dim * sizeof(float));
3378 }
3379
3380 for (int ik = 0; ik < T; ik += CK_GGML_FA_TILE_KV) {
3381 const int kv_tile = (T - ik) < CK_GGML_FA_TILE_KV ? (T - ik) : CK_GGML_FA_TILE_KV;
3382 memset(kq, 0, (size_t) query_tile_size * (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3383
3384 for (int tk = 0; tk < kv_tile; ++tk) {
3385 const float *k_vec = k_head + (size_t) (ik + tk) * (size_t) aligned_head_dim;
3386 const float *v_vec = v_head + (size_t) (ik + tk) * (size_t) aligned_head_dim;
3387 for (int d = 0; d < head_dim; ++d) {
3388 k_tile[(size_t) d * (size_t) CK_GGML_FA_TILE_KV + (size_t) tk] =
3389 ck_round_fp16_scalar(k_vec[d]);
3390 v_tile[(size_t) tk * (size_t) head_dim + (size_t) d] =
3391 ck_round_fp16_scalar(v_vec[d]);
3392 }
3393 }
3394
3396 q_tile,
3397 k_tile,
3398 query_tile_size,
3399 head_dim,
3402 query_tile_size * CK_GGML_FA_TILE_KV,
3403 scale);
3404
3405 if (kv_tile < CK_GGML_FA_TILE_KV) {
3406 for (int tq = 0; tq < query_tile_size; ++tq) {
3407 float *kq_row = kq + (size_t) tq * (size_t) CK_GGML_FA_TILE_KV;
3408 for (int tk = kv_tile; tk < CK_GGML_FA_TILE_KV; ++tk) {
3409 kq_row[tk] = -INFINITY;
3410 }
3411 }
3412 }
3413
3414 for (int tq = 0; tq < tile_rows; ++tq) {
3415 float *kq_row = kq + (size_t) tq * (size_t) CK_GGML_FA_TILE_KV;
3416 const float tile_max = ck_vec_max_f32_contig(kq_row, CK_GGML_FA_TILE_KV);
3417 if (tile_max == -INFINITY) {
3418 memset(kq_row, 0, (size_t) CK_GGML_FA_TILE_KV * sizeof(float));
3419 continue;
3420 }
3421
3422 const float old_max = max_row[tq];
3423 const float new_max = old_max > tile_max ? old_max : tile_max;
3424 if (new_max > old_max) {
3425 const float ms = ck_attention_reference_expf(old_max - new_max);
3426 ck_vec_scale_f32_inplace(vkq + (size_t) tq * (size_t) head_dim,
3427 head_dim,
3428 ms);
3429 sum_row[tq] *= ms;
3430 }
3431 max_row[tq] = new_max;
3432 sum_row[tq] = (float) (
3433 (double) sum_row[tq] +
3435 CK_GGML_FA_TILE_KV, kq_row, kq_row, new_max));
3436 }
3437
3439 kq,
3440 v_tile,
3441 query_tile_size,
3443 head_dim);
3444 }
3445
3446 for (int tq = 0; tq < tile_rows; ++tq) {
3447 float *out_vec = output + qkv_index(h, iq + tq, 0, T, aligned_head_dim);
3448 const float inv_sum = sum_row[tq] == 0.0f ? 0.0f : (1.0f / sum_row[tq]);
3449 for (int d = 0; d < head_dim; ++d) {
3450 out_vec[d] = vkq[(size_t) tq * (size_t) head_dim + (size_t) d] * inv_sum;
3451 }
3452 for (int d = head_dim; d < aligned_head_dim; ++d) {
3453 out_vec[d] = 0.0f;
3454 }
3455 }
3456 ir += tile_rows;
3457 }
3458}

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 3474 of file attention_kernels.c.

3475{
3476 ck_attention_full_tiled_f16kv_fp32_args_t *args =
3477 (ck_attention_full_tiled_f16kv_fp32_args_t *) opaque;
3479 args->q, args->k, args->v, args->output,
3480 args->num_heads, args->num_kv_heads, args->num_tokens,
3481 args->head_dim, args->aligned_head_dim, args->kv_stride_tokens,
3482 args->query_tile_size,
3483 ith, nth);
3484}
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 426 of file attention_kernels.c.

427{
428 return 0;
429}

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 6743 of file attention_kernels.c.

6745{
6746 const int phase = __atomic_load_n(&barrier->phase, __ATOMIC_RELAXED);
6747 if (__atomic_fetch_add(&barrier->arrived, 1, __ATOMIC_ACQ_REL) ==
6748 barrier->lanes - 1) {
6749 __atomic_store_n(&barrier->arrived, 0, __ATOMIC_RELAXED);
6750 __atomic_store_n(&barrier->phase, phase + 1, __ATOMIC_RELEASE);
6751 return;
6752 }
6753 while (__atomic_load_n(&barrier->phase, __ATOMIC_ACQUIRE) == phase) {
6754#if defined(__i386__) || defined(__x86_64__)
6755 _mm_pause();
6756#endif
6757 }
6758}

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 5894 of file attention_kernels.c.

5902{
5903 if (!q || !k || !v || !output || !scores || !value_columns || !scaled_scores ||
5904 num_heads <= 0 || num_kv_heads <= 0 || query_tokens <= 0 || live_tokens <= 0 ||
5905 head_dim <= 0 || aligned_head_dim < head_dim || kv_stride_tokens < live_tokens) return;
5906 size_t scratch_capacity = scores_bytes / sizeof(float);
5907 const size_t scaled_capacity = scaled_scores_bytes / sizeof(float);
5908 const size_t value_capacity = value_columns_bytes /
5909 ((size_t)head_dim * sizeof(float));
5910 if (scaled_capacity < scratch_capacity) scratch_capacity = scaled_capacity;
5911 if (value_capacity < scratch_capacity) scratch_capacity = value_capacity;
5912 if (!batched_prefill && (size_t)kv_stride_tokens < scratch_capacity) {
5913 scratch_capacity = (size_t)kv_stride_tokens;
5914 }
5915 const int padded = scratch_capacity > (size_t)INT_MAX ? 0 :
5916 ck_llama_kv_pad_256(live_tokens, (int)scratch_capacity);
5917 if (padded <= 0 || scores_bytes < (size_t)padded * sizeof(float) ||
5918 scaled_scores_bytes < (size_t)padded * sizeof(float) ||
5919 value_columns_bytes < (size_t)head_dim * (size_t)padded * sizeof(float)) return;
5920
5921 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
5922 const int debug_layer_id = ck_attention_vec_dump_enabled()
5924 int packed_kv_head = -1;
5925 for (int head = 0; head < num_heads; ++head) {
5926 const int kv_head = (int)((long long)head * num_kv_heads / num_heads);
5927 const float *key_head = k + (size_t)kv_head * kv_head_stride;
5928 const float *value_head = v + (size_t)kv_head * kv_head_stride;
5929 if (kv_head != packed_kv_head) {
5930 for (int dim = 0; dim < head_dim; ++dim) {
5931 float *column = value_columns + (size_t)dim * (size_t)padded;
5932 int token = 0;
5933 for (; token < live_tokens; ++token) {
5934 column[token] = value_head[(size_t)token * aligned_head_dim + dim];
5935 }
5936 for (; token < padded; ++token) column[token] = 0.0f;
5937 }
5938 packed_kv_head = kv_head;
5939 }
5940 for (int query = 0; query < query_tokens; ++query) {
5941 const int position = batched_prefill ? query : live_tokens - 1;
5943 q + ((size_t)head * query_tokens + query) * aligned_head_dim,
5944 key_head, value_columns,
5945 output + ((size_t)head * query_tokens + query) * aligned_head_dim,
5946 scores, scaled_scores, live_tokens, padded, position,
5947 head_dim, aligned_head_dim, sliding_window, batched_prefill);
5948 if (debug_layer_id >= 0 &&
5949 ck_attention_vec_dump_should_emit(debug_layer_id, head, query)) {
5951 scaled_scores, scores,
5952 output + ((size_t)head * query_tokens + query) * aligned_head_dim,
5953 value_columns, padded, head_dim,
5954 debug_layer_id, head, query);
5955 }
5956 }
5957 }
5958}
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 5856 of file attention_kernels.c.

5862{
5863 const int first = sliding_window > 0 && query_position >= sliding_window
5864 ? query_position - sliding_window + 1 : 0;
5865 const int last = query_position < live_tokens ? query_position : live_tokens - 1;
5866 for (int token = 0; token < padded_tokens; ++token) scores[token] = -INFINITY;
5867 for (int token = first; token <= last; ++token) {
5868 const float *key = key_head + (size_t)token * (size_t)aligned_head_dim;
5869 scores[token] = batched_prefill
5870 ? ck_llama_regular_gemm_f16(query, key, head_dim)
5871 : ck_llama_regular_dot_f16(query, key, head_dim);
5872 }
5873
5874 memcpy(scaled_scores, scores, (size_t)padded_tokens * sizeof(float));
5875 const float scale = 1.0f / sqrtf((float)head_dim);
5876 ck_vec_scale_f32_inplace(scaled_scores, padded_tokens, scale);
5877 const float maximum = ck_vec_max_f32_contig(scaled_scores, padded_tokens);
5878 const double total = ck_ggml_vec_soft_max_row(
5879 padded_tokens, scores, scaled_scores, maximum);
5880 if (total > 0.0) {
5881 ck_vec_scale_f32_inplace(scores, padded_tokens, (float)(1.0 / total));
5882 for (int dim = 0; dim < head_dim; ++dim) {
5883 const float *column = value_columns + (size_t)dim * (size_t)padded_tokens;
5884 output[dim] = batched_prefill
5885 ? ck_llama_regular_gemm_f16(scores, column, padded_tokens)
5886 : ck_llama_regular_dot_f16(scores, column, padded_tokens);
5887 }
5888 } else {
5889 memset(output, 0, (size_t)head_dim * sizeof(float));
5890 }
5891 for (int dim = head_dim; dim < aligned_head_dim; ++dim) output[dim] = 0.0f;
5892}
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().

◆ 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 6331 of file attention_kernels.c.

6335{
6336 int i = 0;
6337#if defined(__AVX512F__)
6338 const __m512 factor = _mm512_set1_ps(scale);
6339 for (; i + 63 < n; i += 64) {
6340 for (int lane = 0; lane < 4; ++lane) {
6341 const int offset = i + lane * 16;
6342 const __m512 xv = _mm512_cvtph_ps(
6343 _mm256_loadu_si256((const __m256i *) (x + offset)));
6344 __m512 yv = _mm512_cvtph_ps(
6345 _mm256_loadu_si256((const __m256i *) (y + offset)));
6346 yv = _mm512_fmadd_ps(xv, factor, yv);
6347 _mm256_storeu_si256(
6348 (__m256i *) (y + offset), _mm512_cvtps_ph(yv, 0));
6349 }
6350 }
6351#elif defined(__AVX2__) && defined(__F16C__)
6352 const __m256 factor = _mm256_set1_ps(scale);
6353 for (; i + 31 < n; i += 32) {
6354 for (int lane = 0; lane < 4; ++lane) {
6355 const int offset = i + lane * 8;
6356 const __m256 xv = _mm256_cvtph_ps(
6357 _mm_loadu_si128((const __m128i *) (x + offset)));
6358 __m256 yv = _mm256_cvtph_ps(
6359 _mm_loadu_si128((const __m128i *) (y + offset)));
6360#if defined(__FMA__)
6361 yv = _mm256_fmadd_ps(xv, factor, yv);
6362#else
6363 yv = _mm256_add_ps(yv, _mm256_mul_ps(xv, factor));
6364#endif
6365 _mm_storeu_si128(
6366 (__m128i *) (y + offset), _mm256_cvtps_ph(yv, 0));
6367 }
6368 }
6369#endif
6370 for (; i < n; ++i) {
6371 const float product = CK_FP16_TO_FP32(x[i]) * scale;
6372 const float updated = CK_FP16_TO_FP32(y[i]) + product;
6373 y[i] = CK_FP32_TO_FP16(updated);
6374 }
6375}

References CK_FP16_TO_FP32, and CK_FP32_TO_FP16.

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 3293 of file attention_kernels.c.

3299{
3300 for (int i = 0; i < m; ++i) {
3301 float *c_row = c + (size_t) i * (size_t) n;
3302 const float *a_row = a + (size_t) i * (size_t) k;
3303 for (int kk = 0; kk < k; ++kk) {
3304 const float a_ik = a_row[kk];
3305 const float *b_row = b + (size_t) kk * (size_t) n;
3306 for (int j = 0; j < n; ++j) {
3307 c_row[j] += a_ik * b_row[j];
3308 }
3309 }
3310 }
3311}

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_parallel_enabled()

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

Definition at line 3986 of file attention_kernels.c.

3987{
3988 const char *disable = getenv("CK_DISABLE_ATTENTION_THREADPOOL");
3989 if (disable && disable[0] && strcmp(disable, "0") != 0) return 0;
3990 /*
3991 * A 128-token GQA prefill can fall below the old 2048-query threshold
3992 * even though its causal dot products contain ample independent work.
3993 * Keep smaller prompts serial, but allow the shared pool once at least
3994 * eight 128-query worker grains are available.
3995 */
3996 if (total_queries < 1024 || num_tokens < 128 || head_dim <= 0) return 0;
3997 return 1;
3998}

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 4000 of file attention_kernels.c.

4001{
4002 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
4003 if (nth <= 1) return 1;
4004 const char *cap_env = getenv("CK_ATTENTION_THREAD_CAP");
4005 int cap = cap_env && cap_env[0] ? atoi(cap_env) : 24;
4006 if (cap < 1) cap = 1;
4007 if (cap > nth) cap = nth;
4008 int active = (total_queries + 127) / 128;
4009 if (num_tokens >= 1024 && active < 8) active = 8;
4010 if (active > cap) active = cap;
4011 if (active > nth) active = nth;
4012 return active < 1 ? 1 : active;
4013}

References ck_threadpool_n_threads().

Referenced by attention_forward_head_major_gqa_flash_impl().

◆ ck_attention_pytorch_sdpa_scale_f32()

float ck_attention_pytorch_sdpa_scale_f32 ( int  head_dim)

Definition at line 4518 of file attention_kernels.c.

4519{
4520 /* PyTorch CPU flash calculate_scale evaluates in FP64, then narrows. */
4521 return head_dim > 0 ? (float)(1.0 / sqrt((double)head_dim)) : 0.0f;
4522}

Referenced by ck_attention_full_bf16_sdpa_amx_range(), and ck_attention_full_bf16_sdpa_tiled_range().

◆ 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 1169 of file attention_kernels.c.

1170{
1171#if defined(__linux__)
1172 static void *libm_handle = NULL;
1173 static ck_attention_math_f32_fn fn = NULL;
1174 static int resolved = 0;
1175 if (!resolved) {
1176 libm_handle = dlopen("libm.so.6", RTLD_NOW | RTLD_LOCAL);
1177 if (libm_handle) {
1178 fn = (ck_attention_math_f32_fn) dlsym(libm_handle, "expf");
1179 }
1180 resolved = 1;
1181 }
1182 if (fn) {
1183 return fn(value);
1184 }
1185#endif
1186 return expf(value);
1187}
float(* ck_attention_math_f32_fn)(float)

Referenced by 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 413 of file attention_kernels.c.

414{
415 const char *v = getenv("CK_STRICT_ATTN_REVERSE_OUT_DOT");
416 return v && v[0] && strcmp(v, "0") != 0;
417}

◆ ck_attention_scale_f16_llama()

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

Definition at line 6297 of file attention_kernels.c.

6298{
6299 int i = 0;
6300#if defined(__AVX512F__)
6301 const __m512 factor = _mm512_set1_ps(scale);
6302 for (; i + 63 < n; i += 64) {
6303 for (int lane = 0; lane < 4; ++lane) {
6304 const int offset = i + lane * 16;
6305 __m512 value = _mm512_cvtph_ps(
6306 _mm256_loadu_si256((const __m256i *) (y + offset)));
6307 value = _mm512_mul_ps(value, factor);
6308 _mm256_storeu_si256(
6309 (__m256i *) (y + offset), _mm512_cvtps_ph(value, 0));
6310 }
6311 }
6312#elif defined(__AVX2__) && defined(__F16C__)
6313 const __m256 factor = _mm256_set1_ps(scale);
6314 for (; i + 31 < n; i += 32) {
6315 for (int lane = 0; lane < 4; ++lane) {
6316 const int offset = i + lane * 8;
6317 __m256 value = _mm256_cvtph_ps(
6318 _mm_loadu_si128((const __m128i *) (y + offset)));
6319 value = _mm256_mul_ps(value, factor);
6320 _mm_storeu_si128(
6321 (__m128i *) (y + offset), _mm256_cvtps_ph(value, 0));
6322 }
6323 }
6324#endif
6325 for (; i < n; ++i) {
6326 const float value = CK_FP16_TO_FP32(y[i]);
6327 y[i] = CK_FP32_TO_FP16(value * scale);
6328 }
6329}

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 8502 of file attention_kernels.c.

8503{
8504#if defined(__AVX512F__)
8506#else
8507 return 0;
8508#endif
8509}
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 1154 of file attention_kernels.c.

1155{
1156 // Keep strict parity on the precise libm sqrtf path. icx -O3 on AVX2 was
1157 // lowering 1/sqrtf(d) to a slightly smaller effective scale, which is
1158 // enough to move layer-0 vision softmax by ~2e-7 and snowball later.
1159 volatile float hd = (float) head_dim;
1160 float (*sqrtf_fn)(float) = sqrtf;
1161 volatile float root = sqrtf_fn(hd);
1162 volatile float one = 1.0f;
1163 volatile float scale = one / root;
1164 return scale;
1165}

Referenced by 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(), ck_attention_f16_split_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 4015 of file attention_kernels.c.

4016{
4017 const char *value = getenv("CK_STRICT_ATTN_F16_UNFUSED");
4018 return !value || !value[0] || strcmp(value, "0") != 0;
4019}

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 522 of file attention_kernels.c.

523{
524 const char *enabled = getenv("CK_STRICT_ATTN_TRACE");
525 const char *dir = getenv("CK_PARITY_DIR");
526 if (!enabled || !enabled[0] || strcmp(enabled, "0") == 0 || !dir || !dir[0] || !branch || !branch[0]) {
527 return;
528 }
529 char path[4096];
530 snprintf(path, sizeof(path), "%s/%s", dir, "strict_trace.txt");
531 FILE *f = fopen(path, "a");
532 if (!f) {
533 return;
534 }
535 fprintf(f, "layer=%d head=%d branch=%s\n", layer_id, head_id, branch);
536 fclose(f);
537}

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 560 of file attention_kernels.c.

564{
565 const char *enabled = getenv("CK_STRICT_ATTN_TRACE");
566 const char *dir = getenv("CK_PARITY_DIR");
567 if (!enabled || !enabled[0] || strcmp(enabled, "0") == 0 || !dir || !dir[0] || !tag || !tag[0]) {
568 return;
569 }
570 char path[4096];
571 snprintf(path, sizeof(path), "%s/%s", dir, "strict_trace.txt");
572 FILE *f = fopen(path, "a");
573 if (!f) {
574 return;
575 }
576 fprintf(f, "layer=%d head=%d tag=%s float=%.17g\n", layer_id, head_id, tag, (double) value);
577 fclose(f);
578}

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 539 of file attention_kernels.c.

544{
545 const char *enabled = getenv("CK_STRICT_ATTN_TRACE");
546 const char *dir = getenv("CK_PARITY_DIR");
547 if (!enabled || !enabled[0] || strcmp(enabled, "0") == 0 || !dir || !dir[0] || !tag || !tag[0]) {
548 return;
549 }
550 char path[4096];
551 snprintf(path, sizeof(path), "%s/%s", dir, "strict_trace.txt");
552 FILE *f = fopen(path, "a");
553 if (!f) {
554 return;
555 }
556 fprintf(f, "layer=%d head=%d query=%d tag=%s value=%d\n", layer_id, head_id, query_id, tag, value);
557 fclose(f);
558}

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 6760 of file attention_kernels.c.

6761{
6762 return cache_is_bf16 ? bf16_to_float(value) : CK_FP16_TO_FP32(value);
6763}

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

Definition at line 401 of file attention_kernels.c.

402{
403 const char *v = getenv("CK_STRICT_ATTN_VEC_DUMP");
404 return v && v[0] && strcmp(v, "0") != 0;
405}

Referenced by attention_forward_head_major_gqa_flash_impl(), attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl(), ck_attention_llama_regular_impl(), and ck_attention_vec_dump_should_emit().

◆ 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 2067 of file attention_kernels.c.

2077{
2078 if (!ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
2079 return;
2080 }
2081
2082 float *raw_scores = (float *) alloca((size_t) kv_tokens * sizeof(float));
2083 float *probs = (float *) alloca((size_t) kv_tokens * sizeof(float));
2084 float max_score = -INFINITY;
2085 for (int j = 0; j < kv_tokens; ++j) {
2086 const float *k_vec = k_head + (size_t) j * (size_t) aligned_head_dim;
2087 float dot = 0.0f;
2088 for (int d = 0; d < head_dim; ++d) {
2089 dot += q_vec[d] * k_vec[d];
2090 }
2091 raw_scores[j] = dot;
2092 const float scaled = dot * scale;
2093 probs[j] = scaled;
2094 if (scaled > max_score) {
2095 max_score = scaled;
2096 }
2097 }
2098
2099 float sum = 0.0f;
2100 for (int j = 0; j < kv_tokens; ++j) {
2101 probs[j] = expf(probs[j] - max_score);
2102 sum += probs[j];
2103 }
2104 if (sum > 0.0f) {
2105 const float inv_sum = 1.0f / sum;
2106 for (int j = 0; j < kv_tokens; ++j) {
2107 probs[j] *= inv_sum;
2108 }
2109 } else {
2110 memset(probs, 0, (size_t) kv_tokens * sizeof(float));
2111 }
2112
2113 ck_attention_vec_dump_selected_query(raw_scores, probs, out_vec, NULL,
2114 kv_tokens, head_dim,
2115 layer_id, head_id, query_id);
2116}

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 432 of file attention_kernels.c.

433{
434 const char *v = getenv(name);
435 if (!v || !v[0]) {
436 return 0;
437 }
438 char *end = NULL;
439 long parsed = strtol(v, &end, 10);
440 if (end == v || (end && *end != '\0') || parsed < 0 || parsed > INT32_MAX) {
441 return 0;
442 }
443 if (out) {
444 *out = (int) parsed;
445 }
446 return 1;
447}

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 580 of file attention_kernels.c.

589{
590 if (!ck_attention_vec_dump_should_emit(layer_id, head_id, query_id)) {
591 return;
592 }
593 ck_attention_trace_query("vec_dump_selected_query", layer_id, head_id, query_id, 1);
594 char name[32];
595 snprintf(name, sizeof(name), "kq_scores_h%d_q%d", head_id, query_id);
596 ck_attention_vec_dump_tensor(name, layer_id, query_id, raw_scores, (size_t) kv_tokens);
597 snprintf(name, sizeof(name), "kq_soft_h%d_q%d", head_id, query_id);
598 ck_attention_vec_dump_tensor(name, layer_id, query_id, probs, (size_t) kv_tokens);
599 snprintf(name, sizeof(name), "kqv_out_h%d_q%d", head_id, query_id);
600 ck_attention_vec_dump_tensor(name, layer_id, query_id, out_vec, (size_t) head_dim);
601 if (v_cols && ck_attention_vec_dump_vcols_enabled()) {
602 snprintf(name, sizeof(name), "vcols_h%d_q%d", head_id, query_id);
603 ck_attention_vec_dump_tensor(name, layer_id, query_id, v_cols, (size_t) kv_tokens * (size_t) head_dim);
604 }
605}
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 449 of file attention_kernels.c.

450{
452 return 0;
453 }
454 int want_layer = -1;
455 int want_head = -1;
456 int want_query = -1;
457 if (!ck_attention_vec_dump_parse_env_int("CK_STRICT_ATTN_DUMP_LAYER", &want_layer)) {
458 return 0;
459 }
460 const int have_head = ck_attention_vec_dump_parse_env_int("CK_STRICT_ATTN_DUMP_HEAD", &want_head);
461 const int have_query = ck_attention_vec_dump_parse_env_int("CK_STRICT_ATTN_DUMP_QUERY", &want_query);
462 const int trace_target = layer_id == want_layer &&
463 (!have_head || head_id == want_head) &&
464 (!have_query || query_id == want_query);
465 if (layer_id != want_layer) {
466 return 0;
467 }
468 if (have_head && head_id != want_head) {
469 return 0;
470 }
471 if (have_query && query_id != want_query) {
472 return 0;
473 }
474 if (trace_target) {
475 ck_attention_trace_query("vec_dump_should_emit", layer_id, head_id, query_id, 1);
476 }
477 return 1;
478}
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 487 of file attention_kernels.c.

492{
493 const char *dir = getenv("CK_PARITY_DIR");
494 if (!dir || !dir[0] || !name || !name[0] || !data || elem_count == 0) {
495 return;
496 }
497
498 char path[4096];
499 snprintf(path, sizeof(path), "%s/%s", dir, "strict_internal.bin");
500 FILE *f = fopen(path, "ab");
501 if (!f) {
502 return;
503 }
504
505 ck_attention_vec_dump_header_t h;
506 memset(&h, 0, sizeof(h));
509 h.layer_id = layer_id;
510 strncpy(h.op_name, name, sizeof(h.op_name) - 1);
511 h.dtype = 0u;
512 h.rank = 1u;
513 h.shape[0] = (int64_t) elem_count;
514 h.elem_count = (uint32_t) elem_count;
515 h.token_id = query_id;
516
517 fwrite(&h, sizeof(h), 1, f);
518 fwrite(data, sizeof(float), elem_count, f);
519 fclose(f);
520}
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 407 of file attention_kernels.c.

408{
409 const char *v = getenv("CK_STRICT_ATTN_DUMP_VCOLS");
410 return v && v[0] && strcmp(v, "0") != 0;
411}

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 4490 of file attention_kernels.c.

4491{
4492#if defined(__AVX512BF16__)
4493 __m512 acc = _mm512_setzero_ps();
4494 int i = 0;
4495 for (; i + 32 <= count; i += 32) {
4496 const __m512bh av = _mm512_cvtne2ps_pbh(_mm512_loadu_ps(a + i + 16), _mm512_loadu_ps(a + i));
4497 const __m512bh bv = _mm512_cvtne2ps_pbh(_mm512_loadu_ps(b + i + 16), _mm512_loadu_ps(b + i));
4498 acc = _mm512_dpbf16_ps(acc, av, bv);
4499 }
4500 float sum = _mm512_reduce_add_ps(acc);
4501 for (; i < count; ++i) {
4502 const float av = bf16_to_float(float_to_bf16(a[i]));
4503 const float bv = bf16_to_float(float_to_bf16(b[i]));
4504 sum += av * bv;
4505 }
4506 return sum;
4507#else
4508 float sum = 0.0f;
4509 for (int i = 0; i < count; ++i) {
4510 const float av = bf16_to_float(float_to_bf16(a[i]));
4511 const float bv = bf16_to_float(float_to_bf16(b[i]));
4512 sum += av * bv;
4513 }
4514 return sum;
4515#endif
4516}

References bf16_to_float(), 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 1016 of file attention_kernels.c.

1019{
1020 // Keep this a literal port of ggml_vec_dot_f32 so strict parity can match
1021 // llama.cpp's CPU attention path instead of merely approximating it.
1022#if defined(__AVX__)
1023 float sumf = 0.0f;
1024 const int np = (n & ~31);
1025 __m256 sum[4] = {
1026 _mm256_setzero_ps(),
1027 _mm256_setzero_ps(),
1028 _mm256_setzero_ps(),
1029 _mm256_setzero_ps(),
1030 };
1031
1032 for (int i = 0; i < np; i += 32) {
1033 for (int j = 0; j < 4; ++j) {
1034 const __m256 ax = _mm256_loadu_ps(x + i + j * 8);
1035 const __m256 ay = _mm256_loadu_ps(y + i + j * 8);
1036#if defined(__FMA__)
1037 sum[j] = _mm256_fmadd_ps(ax, ay, sum[j]);
1038#else
1039 sum[j] = _mm256_add_ps(_mm256_mul_ps(ax, ay), sum[j]);
1040#endif
1041 }
1042 }
1043
1044 sum[0] = _mm256_add_ps(sum[0], sum[2]);
1045 sum[1] = _mm256_add_ps(sum[1], sum[3]);
1046 sum[0] = _mm256_add_ps(sum[0], sum[1]);
1047 const __m128 t0 = _mm_add_ps(_mm256_castps256_ps128(sum[0]),
1048 _mm256_extractf128_ps(sum[0], 1));
1049 const __m128 t1 = _mm_hadd_ps(t0, t0);
1050 sumf = _mm_cvtss_f32(_mm_hadd_ps(t1, t1));
1051
1052 for (int i = np; i < n; ++i) {
1053 sumf += x[i] * y[i];
1054 }
1055 return sumf;
1056#elif defined(__SSE2__)
1057 float sumf = 0.0f;
1058 const int np = (n & ~15);
1059 __m128 sum[4] = {
1060 _mm_setzero_ps(),
1061 _mm_setzero_ps(),
1062 _mm_setzero_ps(),
1063 _mm_setzero_ps(),
1064 };
1065
1066 for (int i = 0; i < np; i += 16) {
1067 for (int j = 0; j < 4; ++j) {
1068 const __m128 ax = _mm_loadu_ps(x + i + j * 4);
1069 const __m128 ay = _mm_loadu_ps(y + i + j * 4);
1070#if defined(__FMA__)
1071 sum[j] = _mm_fmadd_ps(ax, ay, sum[j]);
1072#else
1073 sum[j] = _mm_add_ps(_mm_mul_ps(ax, ay), sum[j]);
1074#endif
1075 }
1076 }
1077
1078 sum[0] = _mm_add_ps(sum[0], sum[2]);
1079 sum[1] = _mm_add_ps(sum[1], sum[3]);
1080 sum[0] = _mm_add_ps(sum[0], sum[1]);
1081#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__)
1082 sum[0] = _mm_add_ps(sum[0], _mm_movehl_ps(sum[0], sum[0]));
1083 sum[0] = _mm_add_ss(sum[0], _mm_movehdup_ps(sum[0]));
1084#else
1085 __m128 tmp = _mm_shuffle_ps(sum[0], sum[0], _MM_SHUFFLE(2, 3, 0, 1));
1086 sum[0] = _mm_add_ps(sum[0], tmp);
1087 tmp = _mm_movehl_ps(tmp, sum[0]);
1088 sum[0] = _mm_add_ss(sum[0], tmp);
1089#endif
1090 sumf = _mm_cvtss_f32(sum[0]);
1091
1092 for (int i = np; i < n; ++i) {
1093 sumf += x[i] * y[i];
1094 }
1095 return sumf;
1096#else
1097 double sumf = 0.0;
1098 for (int i = 0; i < n; ++i) {
1099 sumf += (double) (x[i] * y[i]);
1100 }
1101 return (float) sumf;
1102#endif
1103}

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 1204 of file attention_kernels.c.

1208{
1209 int i = 0;
1210 double sum = 0.0;
1211
1212#if defined(__AVX512F__) && defined(__AVX512DQ__)
1213 for (; i + 15 < n; i += 16) {
1214 const __m512 val = ck_ggml_v_expf512(
1215 _mm512_sub_ps(_mm512_loadu_ps(x + i), _mm512_set1_ps(max)));
1216 _mm512_storeu_ps(y + i, val);
1217 sum += (double) _mm512_reduce_add_ps(val);
1218 }
1219#elif defined(__AVX2__) && defined(__FMA__)
1220 for (; i + 7 < n; i += 8) {
1221 const __m256 val = ck_ggml_v_expf256(
1222 _mm256_sub_ps(_mm256_loadu_ps(x + i), _mm256_set1_ps(max)));
1223 _mm256_storeu_ps(y + i, val);
1224 __m128 val2 = _mm_add_ps(_mm256_extractf128_ps(val, 1),
1225 _mm256_castps256_ps128(val));
1226 val2 = _mm_add_ps(val2, _mm_movehl_ps(val2, val2));
1227 val2 = _mm_add_ss(val2, _mm_movehdup_ps(val2));
1228 sum += (double) _mm_cvtss_f32(val2);
1229 }
1230#elif defined(__SSE2__)
1231 for (; i + 3 < n; i += 4) {
1232 const __m128 val = ck_ggml_v_expf128(
1233 _mm_sub_ps(_mm_loadu_ps(x + i), _mm_set1_ps(max)));
1234 _mm_storeu_ps(y + i, val);
1235#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__)
1236 __m128 acc = _mm_add_ps(val, _mm_movehl_ps(val, val));
1237 acc = _mm_add_ss(acc, _mm_movehdup_ps(acc));
1238#else
1239 __m128 tmp = _mm_shuffle_ps(val, val, _MM_SHUFFLE(2, 3, 0, 1));
1240 __m128 acc = _mm_add_ps(val, tmp);
1241 tmp = _mm_movehl_ps(tmp, acc);
1242 acc = _mm_add_ss(acc, tmp);
1243#endif
1244 sum += (double) _mm_cvtss_f32(acc);
1245 }
1246#endif
1247
1248 for (; i < n; ++i) {
1249 const float val = expf(x[i] - max);
1250 y[i] = val;
1251 sum += (double) val;
1252 }
1253
1254 return sum;
1255}

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 5728 of file attention_kernels.c.

5729{
5730 if (live_tokens <= 0 || capacity < live_tokens) return 0;
5731 int padded = live_tokens < 256 ? 256 : ((live_tokens + 255) / 256) * 256;
5732 return padded < capacity ? padded : capacity;
5733}

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 5742 of file attention_kernels.c.

5743{
5744 int i = 0;
5745#if defined(__AVX512F__)
5746 __m512 acc[4] = {
5747 _mm512_setzero_ps(), _mm512_setzero_ps(),
5748 _mm512_setzero_ps(), _mm512_setzero_ps()
5749 };
5750 for (; i + 64 <= count; i += 64) {
5751 for (int lane = 0; lane < 4; ++lane) {
5752 acc[lane] = _mm512_fmadd_ps(
5753 ck_llama_regular_round_f16x16(_mm512_loadu_ps(a + i + lane * 16)),
5754 ck_llama_regular_round_f16x16(_mm512_loadu_ps(b + i + lane * 16)),
5755 acc[lane]);
5756 }
5757 }
5758 acc[0] = _mm512_add_ps(acc[0], acc[2]);
5759 acc[1] = _mm512_add_ps(acc[1], acc[3]);
5760 float sum = _mm512_reduce_add_ps(_mm512_add_ps(acc[0], acc[1]));
5761#elif defined(__AVX__)
5762 __m256 acc[4] = {
5763 _mm256_setzero_ps(), _mm256_setzero_ps(),
5764 _mm256_setzero_ps(), _mm256_setzero_ps()
5765 };
5766 for (; i + 32 <= count; i += 32) {
5767 for (int lane = 0; lane < 4; ++lane) {
5768#if defined(__FMA__)
5769 acc[lane] = _mm256_fmadd_ps(
5770 _mm256_cvtph_ps(_mm256_cvtps_ph(
5771 _mm256_loadu_ps(a + i + lane * 8), _MM_FROUND_TO_NEAREST_INT)),
5772 _mm256_cvtph_ps(_mm256_cvtps_ph(
5773 _mm256_loadu_ps(b + i + lane * 8), _MM_FROUND_TO_NEAREST_INT)),
5774 acc[lane]);
5775#else
5776 acc[lane] = _mm256_add_ps(acc[lane], _mm256_mul_ps(
5777 _mm256_cvtph_ps(_mm256_cvtps_ph(
5778 _mm256_loadu_ps(a + i + lane * 8), _MM_FROUND_TO_NEAREST_INT)),
5779 _mm256_cvtph_ps(_mm256_cvtps_ph(
5780 _mm256_loadu_ps(b + i + lane * 8), _MM_FROUND_TO_NEAREST_INT))));
5781#endif
5782 }
5783 }
5784 acc[0] = _mm256_add_ps(acc[0], acc[2]);
5785 acc[1] = _mm256_add_ps(acc[1], acc[3]);
5786 const __m256 merged = _mm256_add_ps(acc[0], acc[1]);
5787 __m128 halves = _mm_add_ps(
5788 _mm256_extractf128_ps(merged, 1), _mm256_castps256_ps128(merged));
5789 halves = _mm_add_ps(halves, _mm_movehl_ps(halves, halves));
5790 halves = _mm_add_ss(halves, _mm_movehdup_ps(halves));
5791 float sum = _mm_cvtss_f32(halves);
5792#else
5793 float sums[4] = {0.0f, 0.0f, 0.0f, 0.0f};
5794 for (; i + 4 <= count; i += 4) {
5795 for (int lane = 0; lane < 4; ++lane) {
5796 const float av = CK_FP16_TO_FP32(CK_FP32_TO_FP16(a[i + lane]));
5797 const float bv = CK_FP16_TO_FP32(CK_FP32_TO_FP16(b[i + lane]));
5798 sums[lane] = fmaf(av, bv, sums[lane]);
5799 }
5800 }
5801 float sum = (sums[0] + sums[2]) + (sums[1] + sums[3]);
5802#endif
5803 for (; i < count; ++i) {
5804 const float av = CK_FP16_TO_FP32(CK_FP32_TO_FP16(a[i]));
5805 const float bv = CK_FP16_TO_FP32(CK_FP32_TO_FP16(b[i]));
5806 sum = fmaf(av, bv, sum);
5807 }
5808 return sum;
5809}

References CK_FP16_TO_FP32, and CK_FP32_TO_FP16.

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 5811 of file attention_kernels.c.

5813{
5814 int i = 0;
5815#if defined(__AVX512F__)
5816 __m512 acc = _mm512_setzero_ps();
5817 for (; i + 16 <= count; i += 16) {
5818 acc = _mm512_fmadd_ps(
5819 ck_llama_regular_round_f16x16(_mm512_loadu_ps(value_column + i)),
5820 ck_llama_regular_round_f16x16(_mm512_loadu_ps(probability + i)), acc);
5821 }
5822 float sum = _mm512_reduce_add_ps(acc);
5823#elif defined(__AVX__)
5824 __m256 acc = _mm256_setzero_ps();
5825 for (; i + 8 <= count; i += 8) {
5826#if defined(__FMA__)
5827 acc = _mm256_fmadd_ps(
5828 _mm256_cvtph_ps(_mm256_cvtps_ph(
5829 _mm256_loadu_ps(value_column + i), _MM_FROUND_TO_NEAREST_INT)),
5830 _mm256_cvtph_ps(_mm256_cvtps_ph(
5831 _mm256_loadu_ps(probability + i), _MM_FROUND_TO_NEAREST_INT)), acc);
5832#else
5833 acc = _mm256_add_ps(acc, _mm256_mul_ps(
5834 _mm256_cvtph_ps(_mm256_cvtps_ph(
5835 _mm256_loadu_ps(value_column + i), _MM_FROUND_TO_NEAREST_INT)),
5836 _mm256_cvtph_ps(_mm256_cvtps_ph(
5837 _mm256_loadu_ps(probability + i), _MM_FROUND_TO_NEAREST_INT))));
5838#endif
5839 }
5840 __m128 halves = _mm_add_ps(
5841 _mm256_extractf128_ps(acc, 1), _mm256_castps256_ps128(acc));
5842 halves = _mm_add_ps(halves, _mm_movehl_ps(halves, halves));
5843 halves = _mm_add_ss(halves, _mm_movehdup_ps(halves));
5844 float sum = _mm_cvtss_f32(halves);
5845#else
5846 float sum = 0.0f;
5847#endif
5848 for (; i < count; ++i) {
5849 const float value = CK_FP16_TO_FP32(CK_FP32_TO_FP16(value_column[i]));
5850 const float probability_value = CK_FP16_TO_FP32(CK_FP32_TO_FP16(probability[i]));
5851 sum = fmaf(value, probability_value, sum);
5852 }
5853 return sum;
5854}

References CK_FP16_TO_FP32, and CK_FP32_TO_FP16.

Referenced by ck_attention_llama_regular_query().

◆ 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 308 of file attention_kernels.c.

314{
315 if (!src || !dst || rows <= 0 || cols <= 0) {
316 return;
317 }
318 for (int r = 0; r < rows; ++r) {
319 ck_local_fp16_to_fp32_row(src + (size_t)r * (size_t)src_stride,
320 dst + (size_t)r * (size_t)dst_stride,
321 cols);
322 }
323}
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 298 of file attention_kernels.c.

299{
300 if (!src || !dst || n <= 0) {
301 return;
302 }
303 for (int i = 0; i < n; ++i) {
304 dst[i] = CK_FP16_TO_FP32(src[i]);
305 }
306}

References CK_FP16_TO_FP32.

Referenced by ck_local_fp16_to_fp32_2d().

◆ ck_round_fp16_buffer()

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

Definition at line 282 of file attention_kernels.c.

283{
284 size_t i = 0;
285#if defined(__AVX2__) && defined(__F16C__)
286 for (; i + 8 <= count; i += 8) {
287 const __m256 value = _mm256_loadu_ps(src + i);
288 const __m128i half = _mm256_cvtps_ph(
289 value, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
290 _mm256_storeu_ps(dst + i, _mm256_cvtph_ps(half));
291 }
292#endif
293 for (; i < count; ++i) {
294 dst[i] = ck_round_fp16_scalar(src[i]);
295 }
296}

References ck_round_fp16_scalar().

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 365 of file attention_kernels.c.

368{
369 float sumf = 0.0f;
370 for (int i = n - 1; i >= 0; --i) {
371 volatile float prod = x[i] * y[i];
372 volatile float next = sumf + prod;
373 sumf = next;
374 }
375 return sumf;
376}

◆ ck_vec_dot_f32_strict()

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

Definition at line 339 of file attention_kernels.c.

342{
343 float sumf = 0.0f;
344 for (int i = 0; i < n; ++i) {
345 volatile float prod = x[i] * y[i];
346 volatile float next = sumf + prod;
347 sumf = next;
348 }
349 return sumf;
350}

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 352 of file attention_kernels.c.

355{
356 double sum = 0.0;
357 for (int i = 0; i < n; ++i) {
358 volatile double prod = (double) x[i] * (double) y[i];
359 volatile double next = sum + prod;
360 sum = next;
361 }
362 return (float) sum;
363}

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 2826 of file attention_kernels.c.

2827{
2828 float max_val = -INFINITY;
2829 for (int i = 0; i < n; ++i) {
2830 if (x[i] > max_val) {
2831 max_val = x[i];
2832 }
2833 }
2834 return max_val;
2835}

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 247 of file attention_kernels.c.

248{
249 if (!dst || !src) return;
250 bf16_tensor_to_float(src, dst, count);
251}
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().

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 1259 of file attention_kernels.c.

1263{
1264 return ((size_t)h * (size_t)aligned_context_window * (size_t)aligned_context_window)
1265 + (size_t)i * (size_t)aligned_context_window
1266 + (size_t)j;
1267}

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 393 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 391 of file attention_kernels.c.

391{'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 392 of file attention_kernels.c.

Referenced by ck_attention_vec_dump_tensor().