← Back to C-Kernel-Engine Docs Doxygen Source Documentation
 
Loading...
Searching...
No Matches
ckernel_engine.h File Reference
#include <stddef.h>
#include <stdint.h>
#include "ckernel_audio.h"
#include "cpu_features.h"
#include "ckernel_quant.h"
#include "mega_fused_attention.h"
#include "ckernel_rwkv7_decode.h"

Go to the source code of this file.

Data Structures

struct  CKMathBackend
 

Enumerations

enum  ck_attention_prefill_schedule_t {
  CK_ATTN_PREFILL_SCHEDULE_KV_HEADS = 0 , CK_ATTN_PREFILL_SCHEDULE_QUERY_HEADS = 1 , CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES = 2 , CK_ATTN_PREFILL_SCHEDULE_KV_GROUP_QUERY_TILES = 3 ,
  CK_ATTN_PREFILL_SCHEDULE_GQA_SHARED_KV_TILES = 4
}
 
enum  ck_attention_reduction_t {
  CK_ATTN_REDUCTION_FP32_ONLINE = 0 , CK_ATTN_REDUCTION_F16_ONLINE_FP32_MERGE = 1 , CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE = 2 , CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64 = 3 ,
  CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA = 4 , CK_ATTN_REDUCTION_F16_REGULAR_NOSCALE = 5 , CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64_REGULAR_TAIL_NOSCALE = 6
}
 
enum  ck_attention_status_t { CK_ATTENTION_STATUS_OK = 0 , CK_ATTENTION_STATUS_INVALID_ARGUMENT = -1 , CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT = -2 , CK_ATTENTION_STATUS_INSUFFICIENT_WORKSPACE = -3 }
 

Functions

void adamw_clip_update_multi_f32 (float *const *grads, float *const *weights, float *const *m_states, float *const *v_states, const size_t *numels, int tensor_count, float lr, float beta1, float beta2, float eps, float weight_decay, float max_grad_norm, int step)
 
void adamw_update_f32 (const float *grad, float *weight, float *m, float *v, size_t numel, float lr, float beta1, float beta2, float eps, float weight_decay, int step)
 
void add_backward_bf16 (const uint16_t *d_y, uint16_t *d_a, uint16_t *d_b, size_t n)
 
void add_forward_2d_bf16 (const uint16_t *a, const uint16_t *b, uint16_t *y, int tokens, int dim, int aligned_dim)
 
void add_forward_bf16 (const uint16_t *a, const uint16_t *b, uint16_t *y, size_t n)
 
void add_forward_f32 (const float *a, const float *b, float *y, size_t n)
 
void add_inplace_bf16 (uint16_t *a, const uint16_t *b, size_t n)
 
void add_inplace_f32 (float *a, const float *b, size_t n)
 
void add_scaled_forward_bf16 (const uint16_t *a, const uint16_t *b, uint16_t *y, float alpha, size_t n)
 
void add_scaled_inplace_bf16 (uint16_t *a, const uint16_t *b, float alpha, size_t n)
 
void add_stream_inplace (float *a, const float *b, size_t n)
 
void add_stream_reorder_2d (float *main_inout, float *aux_scratch, int grid_h, int grid_w, int embed_dim, int merge_size)
 
int argmax_f32 (const float *scores, int n)
 Find index of maximum value.
 
void assistant_layer_scale_forward (float *hidden, const float *scale, int tokens, int embed_dim)
 
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)
 
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.
 
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_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_sliding (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4 (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
void attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_token_output (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
void attention_forward_causal_head_major_gqa_flash_strided_token_output (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens)
 
void attention_forward_causal_head_major_gqa_llama_regular_strided_sliding_workspace (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window, float *scores, size_t scores_bytes, float *value_columns, size_t value_columns_bytes, float *scaled_scores, size_t scaled_scores_bytes)
 
void attention_forward_causal_head_major_gqa_muse_eager_bf16_storage (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
void attention_forward_causal_head_major_gqa_muse_eager_bf16_storage_sliding (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, void *gqa_workspace, size_t gqa_workspace_bytes, int route_num_heads, int route_num_kv_heads, int route_head_dim, int route_query_tokens, int route_min_kv_tokens, int route_workers, int route_query_tile_size, int route_concurrent_query_tiles)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int query_tile_size, int concurrent_query_tiles, void *workspace, size_t workspace_bytes)
 
size_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes (int num_heads, int num_kv_heads, int head_dim, int workers, int query_tile_size, int concurrent_query_tiles)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_qtile64_schedule (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_prefill_schedule_t schedule)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_append_f16cache_sliding_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_full_bf16cache_pytorch_contract (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_contract_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)
 
ck_attention_status_t attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_sliding_gemma4_workspace (const float *q, const uint16_t *k_cache, const uint16_t *v_cache, float *output, int num_heads, int num_kv_heads, int q_tokens, int past_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction, float *token_workspace, size_t token_workspace_bytes, const int *segment_lengths, int num_segments)
 
void attention_forward_causal_head_major_shared_kv_gemma4 (const float *q, float *output, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens)
 
void attention_forward_causal_head_major_shared_kv_sliding_gemma4 (const float *q, float *output, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int sliding_window)
 
void attention_forward_chunk_head_major_gqa_flash_gemma4 (const float *q_chunk, const float *k_cache, const float *v_cache, float *out_chunk, int num_heads, int num_kv_heads, int q_tokens, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_gemma4_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_regular_noscale (const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_sliding_gemma4_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction)
 
void attention_forward_decode_head_major_gqa_flash (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)
 
void attention_forward_decode_head_major_gqa_flash_f16cache (const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)
 
ck_attention_status_t attention_forward_decode_head_major_gqa_flash_f16cache_contract (const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, ck_attention_reduction_t reduction)
 
void attention_forward_decode_head_major_gqa_flash_f16cache_split (const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int split_chunks)
 
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_flash_sliding (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)
 
void attention_forward_decode_head_major_gqa_flash_sliding_gemma4 (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)
 
void attention_forward_decode_head_major_gqa_llama_regular_sliding_workspace (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int live_tokens, int kv_stride_tokens, int head_dim, int aligned_head_dim, int sliding_window, float *scores, size_t scores_bytes, float *value_columns, size_t value_columns_bytes, float *scaled_scores, size_t scaled_scores_bytes)
 
void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage_sliding (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, float *scores, size_t scores_bytes, uint16_t *key_rows, size_t key_rows_bytes, uint16_t *value_columns, size_t value_columns_bytes, uint16_t *gemm_rows, size_t gemm_rows_bytes, uint16_t *gemm_scores, size_t gemm_scores_bytes)
 
void attention_forward_decode_head_major_gqa_regular (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)
 WARNING: This is NOT true flash attention!
 
void attention_forward_decode_head_major_shared_kv_gemma4 (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)
 
void attention_forward_decode_head_major_shared_kv_sliding_gemma4 (const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window)
 
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)
 
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)
 
void attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_token_output (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int visual_start, int visual_tokens)
 
int attention_forward_query_key_head_major_f32 (const float *query, const float *key, const float *value, float *output, float *score_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
int attention_forward_query_key_head_major_f32_decode_heads (const float *query, const float *key, const float *value, float *output, float *score_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
int attention_forward_query_key_head_major_f32_packed_k (const float *query, const float *key, const float *value, float *output, float *score_scratch, float *key_transpose_scratch, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
int attention_forward_query_key_head_major_tiled_f16kv_fp32 (const float *query, const float *key, const float *value, float *output, int num_heads, int query_tokens, int key_tokens, int head_dim, float scale)
 
void attention_forward_sparse_token_major_gqa_bf16cache_pytorch_cpu_flash_contract (const float *query, const uint16_t *key_cache, const uint16_t *value_cache, const float *selected_indices, float *output, float *score_scratch, int rows, int query_heads, int kv_heads, int head_dim, int selection_width, int context_length, int position)
 
void attn_gate_sigmoid_mul_backward (const float *d_out, const float *x, const float *gate, float *d_x, float *d_gate, int rows, int num_heads, int state_dim)
 
void attn_gate_sigmoid_mul_forward (const float *x, const float *gate, float *out, int rows, int num_heads, int state_dim)
 
void attn_gate_sigmoid_mul_pytorch_bf16_storage (const float *x, const float *gate, float *out, int rows, int num_heads, int state_dim)
 
void attn_gate_softplus_mul_forward (const float *x, const float *gate, float *out, int rows, int num_heads, int state_dim)
 
void axpy_2d_f32 (float *Y, const float *X, float alpha, int num_tokens, int dim, int y_stride, int x_stride)
 Batched AXPY for 2D tensors: Y[t,:] += alpha * X[t,:].
 
void axpy_f32 (float *y, const float *x, float alpha, int n)
 In-place AXPY: y += alpha * x.
 
void axpy_zero_f32 (float *y, const float *x, float alpha, int n)
 Zero output then accumulate: y = 0; y += alpha * x.
 
void backward_causal_softmax_head_major (float *d_scores, const float *weights, int num_heads, int num_tokens, int aligned_context_window)
 
void backward_causal_softmax_head_major_bf16 (uint16_t *d_scores, const uint16_t *weights, int num_heads, int num_tokens, int aligned_context_window, float *scratch_d_scores, float *scratch_weights)
 
void causal_softmax_head_major (float *scores, int num_heads, int num_tokens, int aligned_context_window)
 
void causal_softmax_head_major_bf16 (uint16_t *scores, int num_heads, int num_tokens, int aligned_context_window, float *scratch)
 
void causal_softmax_head_major_exact (float *scores, int num_heads, int num_tokens, int aligned_context_window)
 
int ck_attention_bf16_pytorch_gqa_available (void)
 
void ck_attention_flash_decode_wrapper (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)
 Wrapper to call TRUE flash attention from orchestration layer.
 
float ck_attention_pytorch_sdpa_scale_f32 (int head_dim)
 
int ck_attention_sparse_bf16_pytorch_gqa_available (void)
 
int ck_flash_attn_choose_tile_k (int D_h)
 
int ck_flash_attn_fast_exp_kind (void)
 
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)
 
int ck_gemm_nt_f16_ggml_oracle (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
int ck_gemm_nt_f16_simd_lanes (void)
 
void ck_gemm_nt_head_major_q5_0 (const float *attn_out, const void *wo, const float *bias, float *output, int tokens, int embed_dim, int num_heads, int head_dim)
 Output projection from head-major attention (auto-dispatch)
 
void ck_gemm_nt_head_major_q8_0 (const float *attn_out, const void *wo, const float *bias, float *output, int tokens, int embed_dim, int num_heads, int head_dim)
 Output projection from head-major attention (Q8_0 weights)
 
int ck_get_num_threads (void)
 
int ck_get_physical_cores (void)
 
void ck_layout_head_to_token_f32 (const float *src, float *dst, int heads, int tokens, int head_dim)
 
void ck_layout_token_to_head_f32 (const float *src, float *dst, int tokens, int heads, int head_dim)
 
void * ck_memcpy_parallel_dispatch (void *dst, const void *src, size_t size)
 
int ck_multimodal_mrope_positions_2d (int32_t *positions, int total_tokens, int prefix_start, int position_base, int prefix_tokens, int grid_x, int grid_y, int text_pos)
 
int ck_multimodal_prefix_insert_f32 (const float *source_rows, int32_t *token_ids, float *decoder_rows, int row_count, int source_row_stride, int decoder_row_stride, int copy_dim, int start_row, int decoder_capacity)
 
const char * ck_q6_k_prepared_provider_name (void)
 
const char * ck_q6_k_q8_k_provider_name (void)
 
void ck_residual_add_backward (const float *d_out, float *d_a, float *d_b, int tokens, int aligned_embed_dim)
 
void ck_residual_add_token_major (const float *a, const float *b, float *out, int tokens, int aligned_embed_dim)
 
void ck_residual_add_token_major_bf16_storage (const float *a, const float *b, float *out, int tokens, int aligned_embed_dim)
 
void ck_residual_add_token_major_parallel_dispatch (const float *a, const float *b, float *out, int tokens, int aligned_embed_dim)
 
void ck_set_num_threads (int num_threads)
 
void ck_set_strict_parity (int enabled)
 
const float * ck_strict_consume_next_gemm_a (size_t elems)
 
int ck_strict_mtmd_clip_encode_planar_f32 (const float *planar, int channels, int height, int width, float *out, size_t out_elems)
 
int ck_strict_parity_enabled (void)
 
void ck_strict_store_next_gemm_a (const float *data, size_t elems)
 
CKMathBackend ckernel_backend_native (void)
 
void deepseek_csa_attention_backward_f32 (const float *d_out, const float *q, const float *k, const float *v, const int *indices, const float *attn, float *d_q, float *d_k, float *d_v, int query_tokens, int key_tokens, int heads, int dim, int top_k, float scale)
 
void deepseek_csa_attention_f32 (const float *q, const float *k, const float *v, const int *indices, float *out, float *attn, int query_tokens, int key_tokens, int heads, int dim, int top_k, float scale)
 
void deepseek_dsa_topk_softmax_backward_f32 (const int *indices, const float *weights, const float *d_weights, float *d_scores, int tokens, int heads, int key_count, int top_k)
 
void deepseek_dsa_topk_softmax_f32 (const float *scores, int *indices, float *weights, int tokens, int heads, int key_count, int top_k)
 
void deepseek_hybrid_attention_f32 (const float *q, const float *k, const float *v, const int *indices, float *out, float *attn, int query_tokens, int key_tokens, int heads, int dim, int top_k, float scale, int mode)
 
void deepseek_mhc_mix_backward_f32 (const float *d_out, const float *streams, const float *mix, float *d_streams, float *d_mix, int tokens, int n_streams, int dim)
 
void deepseek_mhc_mix_f32 (const float *streams, const float *mix, float *out, int tokens, int n_streams, int dim)
 
void deepseek_mla_attention_bf16_phases_parallel_dispatch (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)
 
void deepseek_mla_attention_bf16_phases_workspace (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)
 
void deepseek_mla_attention_decode_bf16_phases_workspace (const float *q, const float *k_cache, const float *v_cache, float *output, int num_heads, int num_kv_heads, int cache_len, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride, float scale, float *scores, size_t scores_bytes)
 
void deepseek_mla_attention_decode_f32 (const float *q, const float *k_cache, const float *v_cache, float *output, int num_heads, int num_kv_heads, int cache_len, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride)
 
void deepseek_mla_attention_decode_f32_workspace (const float *q, const float *k_cache, const float *v_cache, float *output, int num_heads, int num_kv_heads, int cache_len, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride, float scale, float *scores, size_t scores_bytes)
 
void deepseek_mla_attention_f32 (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim)
 
void deepseek_mla_attention_f32_parallel_dispatch (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)
 
void deepseek_mla_attention_f32_workspace (const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)
 
void deepseek_mla_kv_cache_batch_store_f32 (float *k_cache, float *v_cache, const float *k, const float *v, int num_tokens, int num_kv_heads, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride)
 
void deepseek_mla_kv_cache_store_f32 (float *k_cache, float *v_cache, const float *k, const float *v, int pos, int num_kv_heads, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride)
 
void deepseek_mla_kv_decompress_bf16 (const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim)
 
void deepseek_mla_kv_decompress_bf16_parallel_dispatch (const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim)
 
void deepseek_mla_kv_decompress_bf16_token_range (const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim, int token_begin, int token_end)
 
void deepseek_mla_kv_decompress_f32 (const float *compressed_kv, const float *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim)
 
void deepseek_mla_partial_rope_concat_f32 (const float *q_nope, const float *q_pe, const float *k_nope, const float *k_pe, const float *cos, const float *sin, float *query, float *key, int tokens, int heads, int qk_nope_dim, int qk_rope_dim)
 
void deepseek_mla_partial_rope_concat_packed_bf16_storage (const float *q_packed, const float *k_nope, const float *kv_a_packed, const float *cos, const float *sin, float *query, float *key, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int qk_rope_dim)
 
void deepseek_mla_partial_rope_concat_packed_f32 (const float *q_packed, const float *k_nope, const float *kv_a_packed, const float *cos, const float *sin, float *query, float *key, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int qk_rope_dim)
 
void dequant_q4_0_row (const void *src, float *dst, size_t n_elements)
 Dequantize Q4_0 row (multiple blocks)
 
void dequant_q4_1_row (const void *src, float *dst, size_t n_elements)
 Dequantize Q4_1 row (multiple blocks)
 
void dequant_q4_k_row (const void *src, float *dst, size_t n_elements)
 Dequantize Q4_K row (multiple blocks)
 
void dequant_q5_0_row (const void *src, float *dst, size_t n_elements)
 Dequantize Q5_0 row (multiple blocks)
 
void dequant_q5_1_row (const void *src, float *dst, size_t n_elements)
 Dequantize Q5_1 row (multiple blocks)
 
void dequant_q6_k_row (const void *src, float *dst, size_t n_elements)
 Dequantize Q6_K row (multiple blocks)
 
void dequant_q8_0_row (const void *src, float *dst, size_t n_elements)
 Dequantize Q8_0 row (multiple blocks)
 
void embedding_backward (const int32_t *token_ids, int token_count, const float *d_output, float *d_token_embeddings, float *d_pos_embeddings, int vocab_size, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_backward_bf16 (const int32_t *token_ids, int token_count, const uint16_t *d_output, uint16_t *d_token_embeddings, uint16_t *d_pos_embeddings, int vocab_size, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_backward_bf16_mixed (const int32_t *token_ids, int token_count, const uint16_t *d_output, float *d_token_embeddings, float *d_pos_embeddings, int vocab_size, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_forward (const int32_t *token_ids, int token_count, int vocab_size, const float *token_embeddings, const float *pos_embeddings, float *output, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_forward_bf16 (const int32_t *token_ids, int token_count, int vocab_size, const uint16_t *token_embeddings, const uint16_t *pos_embeddings, uint16_t *output, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_forward_bf16_fp32 (const int32_t *token_ids, int token_count, int vocab_size, const uint16_t *token_embeddings, const float *pos_embeddings, float *output, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_forward_q4_k (const int32_t *token_ids, int token_count, int vocab_size, const void *token_embeddings, const float *pos_embeddings, float *output, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_forward_q5_0 (const int32_t *token_ids, int token_count, int vocab_size, const void *token_embeddings, const float *pos_embeddings, float *output, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_forward_q6_k (const int32_t *token_ids, int token_count, int vocab_size, const void *token_embeddings, const float *pos_embeddings, float *output, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void embedding_forward_q8_0 (const int32_t *token_ids, int token_count, int vocab_size, const void *token_embeddings, const float *pos_embeddings, float *output, int embed_dim, int aligned_embed_dim, int context_window, int add_pos)
 
void farskip_swiglu_shared_combine_bf16 (const float *hidden, const float *routed, const float *post_attn_residual, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *main_output, float *routed_free_output, int rows, int hidden_dim, int intermediate_dim)
 
void farskip_swiglu_shared_combine_bf16_parallel_dispatch (const float *hidden, const float *routed, const float *post_attn_residual, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *main_output, float *routed_free_output, int rows, int hidden_dim, int intermediate_dim)
 
void farskip_swiglu_shared_combine_bf16_row_range (const float *hidden, const float *routed, const float *post_attn_residual, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *main_output, float *routed_free_output, int rows, int hidden_dim, int intermediate_dim, int row_begin, int row_end)
 
void fc1_backward_kernel (const float *d_output, const float *fc1_input, const float *W_fc1, float *d_input, float *d_W_fc1, float *d_b_fc1, int T, int aligned_in, int aligned_out, int num_threads)
 
void fc2_backward_kernel (const float *d_output, const float *fc2_input, const float *W_fc2, float *d_input, float *d_W_fc2, float *d_b_fc2, int T, int aligned_in, int aligned_out, int num_threads)
 
void feature_concat (const float *main_input, const float *branch_input, float *output, int rows, int main_dim, int branch_slice_dim, int num_branch_slices)
 
void feature_concat_2way (const float *main_input, const float *branch_input, float *output, int rows, int main_dim, int branch_slice_dim, int num_branch_slices)
 
void feature_slice_copy (const float *src, float *dst, int rows, int src_dim, int dst_dim, int dst_feature_offset)
 
void final_logit_scale_f32 (float *logits, int tokens, int vocab_size, float scale)
 
void final_logit_scale_muse_pytorch_bf16_storage (float *logits, int tokens, int vocab_size, float scale)
 
void final_logit_softcap_muse_pytorch_bf16_storage (float *logits, int tokens, int vocab_size, float cap)
 
void fused_mlp_swiglu_decode (const float *x, const float *W_gate, const float *W_up, const float *W_down, const float *b_gate, const float *b_up, const float *b_down, float *output, int D, int Hff)
 
void fused_mlp_swiglu_decode_tiled (const float *x, const float *W_gate, const float *W_up, const float *W_down, const float *b_gate, const float *b_up, const float *b_down, float *output, int D, int Hff)
 
void fused_mlp_swiglu_decode_v2 (const float *x, const float *W_gate, const float *W_up, const float *W_down, const float *b_gate, const float *b_up, const float *b_down, float *output, int D, int Hff)
 
void fused_mlp_swiglu_prefill (const float *x, const float *W_gate, const float *W_up, const float *W_down, float *output, int seq_len, int hidden, int intermediate, float *scratch)
 Fused MLP (Gate + Up + SwiGLU + Down) for prefill.
 
void fused_mlp_swiglu_prefill_bias (const float *x, const float *W_gate, const float *W_up, const float *W_down, const float *B_gate, const float *B_up, const float *B_down, float *output, int seq_len, int hidden, int intermediate, float *scratch)
 Fused MLP (Gate + Up + SwiGLU + Down) for prefill with biases.
 
void fused_mlp_swiglu_prefill_w1w2_quant (const float *x, const void *W1, const float *B1, CKDataType w1_dt, const void *W2, const float *B2, CKDataType w2_dt, float *output, int seq_len, int embed_dim, int aligned_embed_dim, int intermediate_dim, int aligned_intermediate_dim, void *scratch)
 Quantized fused MLP for prefill (W1=gate+up, W2=down)
 
size_t fused_mlp_swiglu_prefill_w1w2_quant_scratch_size (int aligned_embed_dim, int aligned_intermediate_dim)
 Get scratch buffer size for fused_mlp_swiglu_prefill_w1w2_quant.
 
size_t fused_mlp_swiglu_scratch_size (int intermediate)
 Get scratch buffer size for fused_mlp_swiglu_prefill.
 
void fused_rmsnorm_qkv_prefill (const float *x, const float *gamma, const float *Wq, const float *Wk, const float *Wv, float *Q, float *K, float *V, int seq_len, int hidden, int q_dim, int kv_dim, float eps, float *scratch)
 Fused RMSNorm + QKV projection for prefill.
 
void fused_rmsnorm_qkv_prefill_head_major (const float *x, const float *gamma, const float *Wq, const float *Bq, const float *Wk, const float *Bk, const float *Wv, const float *Bv, float *Q, float *K, float *V, int seq_len, int embed_dim, int aligned_embed_dim, int num_heads, int num_kv_heads, int head_dim, int aligned_head_dim, int kv_stride_tokens, float eps, float *scratch)
 Fused RMSNorm + QKV projection for prefill (head-major outputs)
 
void fused_rmsnorm_qkv_prefill_head_major_quant (const float *x, const float *gamma, const void *Wq, const float *Bq, CKDataType wq_dt, const void *Wk, const float *Bk, CKDataType wk_dt, const void *Wv, const float *Bv, CKDataType wv_dt, float *Q, float *K, float *V, int seq_len, int embed_dim, int aligned_embed_dim, int num_heads, int num_kv_heads, int head_dim, int aligned_head_dim, int kv_stride_tokens, float eps, void *scratch)
 Fused RMSNorm + QKV projection for prefill (head-major, Q8 activations)
 
size_t fused_rmsnorm_qkv_prefill_head_major_quant_scratch_size (int aligned_embed_dim)
 Get scratch buffer size for fused_rmsnorm_qkv_prefill_head_major_quant.
 
size_t fused_rmsnorm_qkv_scratch_size (int hidden)
 Get scratch buffer size for fused_rmsnorm_qkv_prefill.
 
void gated_deltanet_autoregressive_backward (const float *d_out, const float *d_state_out, const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, const float *state_out, float *d_q, float *d_k, float *d_v, float *d_g, float *d_beta, float *d_state_in, int num_heads, int state_dim, float norm_eps)
 
void gated_deltanet_autoregressive_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int state_dim, float norm_eps)
 
void gated_deltanet_llama_avx2_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps)
 
void gated_deltanet_llama_avx2_prefill_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int state_dim, float norm_eps)
 
void gated_deltanet_llama_chunk64_head_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int head, int state_dim)
 
void gated_deltanet_llama_chunk64_prefill_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int state_dim, float norm_eps)
 
void gated_deltanet_prefill_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int state_dim, float norm_eps)
 
void gated_deltanet_pytorch_grouped_bf16_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps)
 
void gated_deltanet_pytorch_grouped_bf16_prefill_forward (const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int state_dim, float norm_eps)
 
void geglu_backward_bf16_mixed (const uint16_t *x, const uint16_t *d_out, float *d_x, int tokens, int dim)
 
void geglu_backward_fp32 (const float *x, const float *d_out, float *d_x, int tokens, int dim)
 
void geglu_forward_bf16 (const uint16_t *x, uint16_t *out, int tokens, int dim, float *scratch)
 
void geglu_forward_exact (const float *x, float *out, int tokens, int dim)
 
void geglu_forward_fp32 (const float *x, float *out, int tokens, int dim)
 
void geglu_forward_ggml_native (const float *x, float *out, int tokens, int dim)
 
void geglu_forward_quick (const float *x, float *out, int tokens, int dim)
 
void gelu_backward_exact (const float *input, const float *d_output, float *d_input, size_t n)
 
void gelu_backward_exact_bf16 (const uint16_t *input, const uint16_t *d_output, uint16_t *d_input, size_t n, float *scratch_input, float *scratch_d_output, float *scratch_d_input)
 
void gelu_backward_fast (const float *input, const float *d_output, float *d_input, size_t n)
 
void gelu_backward_fast_bf16 (const uint16_t *input, const uint16_t *d_output, uint16_t *d_input, size_t n, float *scratch_input, float *scratch_d_output, float *scratch_d_input)
 
void gelu_backward_scalar (const float *input, const float *d_output, float *d_input, size_t n)
 
void gelu_erf_bf16_storage (float *data, size_t n)
 
void gelu_erf_fp64_f32_inplace (float *data, size_t n)
 
void gelu_erf_fp64_f32_parallel_dispatch (float *data, size_t n)
 
void gelu_exact_inplace (float *data, size_t n)
 
void gelu_fast_inplace (float *data, size_t n)
 
void gelu_fast_inplace_bf16 (uint16_t *data, size_t n, float *scratch)
 
void gelu_ggml_inplace (float *data, size_t n)
 
void gelu_ggml_native_inplace (float *data, size_t n)
 
void gelu_pytorch_erf_f32_inplace (float *data, size_t n)
 
void gelu_pytorch_erf_sleef_bf16_storage (float *data, size_t n)
 
void gelu_pytorch_tanh_bf16_storage (float *data, size_t n)
 
void gemm_avx512_parallel (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_backward_bf16_mixed (const uint16_t *d_output, const uint16_t *input, const uint16_t *weight, float *d_input, float *d_weight, float *d_bias, int tokens, int in_dim, int out_dim)
 
void gemm_backward_f32_train_parallel_dispatch (const float *d_output, const float *input, const float *W, float *d_input, float *d_W, float *d_b, int T, int aligned_in, int aligned_out, int num_threads)
 
void gemm_backward_f32_train_parallel_dispatch_v2 (const float *d_output, const float *input, const float *W, float *d_input, float *d_W, float *d_b, int T, int aligned_in, int aligned_out, int num_threads)
 
void gemm_bias_gelu_fused (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_bias_relu_fused (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_bias_silu_fused (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_blocked_serial (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_blocked_serial_bf16 (const uint16_t *A, const uint16_t *B, const uint16_t *bias, uint16_t *C, int M, int N, int K)
 
void gemm_blocked_serial_train_parallel_dispatch (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_fine_grained_parallel (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_microkernel (const float *A, const float *B, float *C, int M, int N, int K, int B_transposed)
 
void gemm_microkernel_blocked (const float *A, const float *B, float *C, int M, int N, int K)
 
void gemm_microkernel_blocked_bt (const float *A, const float *B, float *C, int M, int N, int K)
 
void gemm_microkernel_packed (const float *A, const float *B, float *C, int M, int N, int K)
 
void gemm_naive_parallel (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nn_avx512 (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nn_blocked (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nn_parallel (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nn_simd (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_accurate_storage (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_accurate_storage_parallel_dispatch (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_accurate_storage_row_range (const float *A, const void *B, const float *bias, float *C, int M, int N, int K, int row_begin, int row_end)
 
void gemm_nt_bf16_amx_bf16_storage (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_amx_bf16_storage_workspace (const float *A, const void *B, const float *bias, float *C, int M, int N, int K, uint16_t *a_bf16, size_t a_bf16_bytes)
 
void gemm_nt_bf16_bf16_storage (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_bf16_storage_parallel_dispatch (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_bf16_storage_row_range (const float *A, const void *B, const float *bias, float *C, int M, int N, int K, int row_begin, int row_end)
 
void gemm_nt_bf16_native_bf16_storage (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_parallel_dispatch (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_prefill_shape_safe_bf16_storage (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_prefill_shape_safe_bf16_storage_workspace (const float *A, const void *B, const float *bias, float *C, int M, int N, int K, uint16_t *a_bf16, size_t a_bf16_bytes)
 
void gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage_workspace (const float *A, const void *B, const float *bias, float *C, int M, int N, int K, uint16_t *input_bf16, size_t input_bf16_bytes, uint16_t *output_bf16, size_t output_bf16_bytes, uint16_t *bias_bf16, size_t bias_bf16_bytes)
 
void gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_bf16_row_range (const float *A, const void *B, const float *bias, float *C, int M, int N, int K, int row_begin, int row_end)
 
void gemm_nt_f16 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 NT GEMM wrapper for FP16 weights with the engine's standard ABI.
 
void gemm_nt_f16_clipped (const float *A, const void *B, const float *bias, const float *input_min, const float *input_max, const float *output_min, const float *output_max, float *C, int M, int N, int K)
 
void gemm_nt_f32_llama_production (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_f32_llama_production_output_range (const float *A, const float *B, const float *bias, float *C, int M, int N, int K, int output_begin, int output_end)
 
void gemm_nt_fp32_exact_parallel_dispatch (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q4_0 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 Matrix-matrix multiply: C[M,N] = A[M,K] @ B[N,K]^T + bias.
 
void gemm_nt_q4_1 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 GEMM with transposed Q4_1 weights: C = A @ B^T.
 
void gemm_nt_q4_k (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q4_k_q8_k (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_0 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_1 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 GEMM with transposed Q5_1 weights: C = A @ B^T.
 
void gemm_nt_q5_1_q8_1 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_1_q8_1_m2 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_1_q8_1_ref (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_k (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_k_q8_k (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q5_k_q8_k_m2 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q6_k (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q6_k_q8_k (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q6_k_q8_k_m2 (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q6_k_q8_k_m4_tile (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)
 
void gemm_nt_q6_k_q8_k_tile (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)
 Compute one C[m0:m1, n0:n1] tile for Q8_K activations x Q6_K weights.
 
void gemm_nt_q6_k_q8_k_tiled (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 Experimental single-thread tiled NT GEMM wrapper.
 
void gemm_nt_q8_0 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q8_0_q8_0 (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 gemm_nt_q8_0_q8_0 with optional bias (matches header signature)
 
void gemm_nt_q8_0_q8_0_contract (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q8_0_q8_0_contract_m2 (const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q8_0_q8_0_m2n4 (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_nt_q8_0_q8_0_m2n4_tile (const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int ldc)
 
void gemm_q4_k (float *Y, const void *W, const float *X, int M, int N, int K)
 Auto-dispatch GEMM based on available SIMD.
 
void gemm_q4_k_q8_k (float *Y, const void *W, const void *X_q8, int M, int N, int K)
 
void gemm_q6_k (float *Y, const void *W, const float *X, int M, int N, int K)
 
void gemm_q6_k_q8_k (float *Y, const void *W, const void *X_q8, int M, int N, int K)
 GEMM: Y = W @ X^T where W is Q6_K and X is Q8_K.
 
void gemm_swiglu_fused (const float *x, const float *W_gate, const float *W_up, const float *b_gate, const float *b_up, float *output, int M, int N, int K)
 
void gemm_tn_avx512 (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_tn_blocked (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemm_tn_parallel (const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
 
void gemma4_final_logit_softcap_forward (float *logits, int tokens, int vocab_size, float cap)
 
void gemma4_per_layer_embed_forward (float *hidden, const float *per_layer_input, const float *inp_gate, const float *proj, const float *post_norm, const float *out_scale, int tokens, int layer, int num_layers, int embed_dim, int per_layer_dim, float eps, const int *segment_lengths, int num_segments, int singleton_tail)
 
void gemma4_per_layer_prepare_bf16_forward (float *per_layer_input, const float *hidden, const int32_t *token_ids, const uint16_t *per_layer_token_emb, const uint16_t *per_layer_model_proj, const float *per_layer_proj_norm, int tokens, int num_layers, int embed_dim, int per_layer_dim, int vocab_size, float eps)
 
void gemma4_per_layer_prepare_forward (float *per_layer_input, const float *hidden, const int32_t *token_ids, const void *per_layer_token_emb, const uint16_t *per_layer_model_proj, const float *per_layer_proj_norm, int tokens, int num_layers, int embed_dim, int per_layer_dim, int vocab_size, float eps)
 
void gemma4_v_norm_forward (const float *input, float *output, float *rstd_cache, int tokens, int num_kv_heads, int head_dim, float eps)
 
void gemma4_v_norm_forward_parallel_dispatch (const float *input, float *output, float *rstd_cache, int tokens, int num_kv_heads, int head_dim, float eps)
 
void gemma4_vision_projector_prep_forward (const float *input, float *output, int tokens, int dim, float scale, float eps)
 
void gemv_bf16 (float *y, const void *W, const float *x, int M, int K)
 
void gemv_bf16_bf16_storage (float *y, const void *W, const float *x, int M, int K)
 
void gemv_bf16_bf16_storage_parallel_dispatch (float *y, const void *W, const float *x, int M, int K)
 
void gemv_bf16_parallel_dispatch (float *y, const void *W, const float *x, int M, int K)
 
void gemv_fused_q5_0_bias_dispatch (float *y, const void *W, const float *x, const float *bias, int M, int K)
 
void gemv_fused_q8_0_bias_dispatch (float *y, const void *W, const float *x, const float *bias, int M, int K)
 
void gemv_q4_0 (float *y, const void *W, const float *x, int M, int K)
 Auto-dispatch GEMV.
 
void gemv_q4_k (float *y, const void *W, const float *x, int M, int K)
 Auto-dispatch GEMV based on available SIMD.
 
void gemv_q4_k_q8_k (float *y, const void *W, const void *x_q8, int M, int K)
 
void gemv_q4_k_q8_k_parallel (float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)
 
void gemv_q4_k_q8_k_parallel_simd (float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)
 
void gemv_q4_k_q8_k_ref (float *y, const void *W, const void *x_q8, int M, int K)
 
void gemv_q5_0 (float *y, const void *W, const float *x, int M, int K)
 Auto-dispatch GEMV for Q5_0 weights based on CPU features.
 
void gemv_q5_0_parallel (float *y, const void *W, const float *x, int M, int K, int ith, int nth)
 Parallel reference GEMV for Q5_0 × FP32.
 
void gemv_q5_0_parallel_simd (float *y, const void *W, const float *x, int M, int K, int ith, int nth)
 Parallel SIMD GEMV for Q5_0 × FP32 with prefetching.
 
void gemv_q5_0_q8_0 (float *y, const void *W, const void *x_q8, int M, int K)
 Matrix-vector multiply with Q5_0 weights and Q8_0 input.
 
void gemv_q5_1 (float *y, const void *W, const float *x, int M, int K)
 Auto-dispatch GEMV.
 
void gemv_q5_1_q8_1 (float *y, const void *W, const float *x, int M, int K)
 
void gemv_q5_1_q8_1_ref (float *y, const void *W, const void *x_q8, int M, int K)
 
void gemv_q5_k (float *y, const void *W, const float *x, int M, int K)
 
void gemv_q5_k_q8_k (float *y, const void *W, const void *x_q8, int M, int K)
 
void gemv_q6_k (float *y, const void *W, const float *x, int M, int K)
 
void gemv_q6_k_q8_k (float *y, const void *W, const void *x_q8, int M, int K)
 GEMV: y = W @ x where W is Q6_K and x is Q8_K.
 
void gemv_q6_k_q8_k_parallel (float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)
 Parallel reference GEMV for Q6_K × Q8_K.
 
void gemv_q6_k_q8_k_parallel_simd (float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)
 Parallel SIMD GEMV for Q6_K × Q8_K.
 
void gemv_q8_0 (float *y, const void *W, const float *x, int M, int K)
 Auto-dispatch GEMV for Q8_0 weights based on CPU features.
 
void gemv_q8_0_q8_0 (float *y, const void *W, const void *x_q8, int M, int K)
 Matrix-vector multiply with Q8_0 weights and Q8_0 input.
 
void gemv_q8_0_q8_0_contract (float *y, const void *W, const float *x, int M, int K)
 
void gemv_q8_0_q8_0_x4 (float *y, const void *W, const void *x_q8, int M, int K)
 
void gradient_accumulate_f32 (float *dst, const float *src, size_t numel)
 
void gradient_accumulate_multi_f32 (float *const *dsts, const float *const *srcs, const size_t *numels, int tensor_count)
 
float gradient_clip_norm_f32 (float *grad, size_t numel, float max_norm)
 Clip gradient norm (fp32)
 
float gradient_global_norm_multi_f32 (const float *const *grads, const size_t *numels, int tensor_count)
 
void gradient_scale_f32 (float *grad, size_t numel, float scale)
 
void group_limited_topk_router_sigmoid_f32 (const float *logits, const float *correction_bias, int *indices, float *weights, int rows, int n_experts, int top_k, int n_group, int topk_group, int norm_topk_prob, float routed_scaling_factor)
 
void hyper_connection_mix_bf16 (const float *hyper_input, const float *norm_weight, const uint16_t *mix_down_weight, const uint16_t *mix_up_weight, const uint16_t *inject_weight, float *mixed_output, float *injection_output, float *normalized_scratch, float *dynamic_scratch, float *mix_scratch, int rows, int streams, int hidden_dim, int dynamic_dim, float eps, int emit_injection)
 
void hyper_connection_mix_q4k_q5_0_q4k (const float *hyper_input, const float *norm_weight, const void *mix_down_weight, const void *mix_up_weight, const void *inject_weight, float *mixed_output, float *injection_output, float *normalized_scratch, float *dynamic_scratch, float *mix_scratch, int rows, int streams, int hidden_dim, int dynamic_dim, float eps, int emit_injection)
 
void hyper_connection_mix_q6k_q5_0_q4k (const float *hyper_input, const float *norm_weight, const void *mix_down_weight, const void *mix_up_weight, const void *inject_weight, float *mixed_output, float *injection_output, float *normalized_scratch, float *dynamic_scratch, float *mix_scratch, int rows, int streams, int hidden_dim, int dynamic_dim, float eps, int emit_injection)
 
void hyper_stream_expand_bf16 (const float *input, float *output, int rows, int streams, int hidden_dim)
 
void hyper_stream_expand_f32 (const float *input, float *output, int rows, int streams, int hidden_dim)
 
void hyper_stream_inject_bf16 (const float *hyper_input, const float *block_output, const float *injection_weight, float *output, int rows, int streams, int hidden_dim)
 
void hyper_stream_inject_f32 (const float *hyper_input, const float *block_output, const float *injection_weight, float *output, int rows, int streams, int hidden_dim)
 
void im2patch (const float *image, float *patches, int C, int H, int W, int P)
 
void im2patch_bf16 (const uint16_t *image, uint16_t *patches, int C, int H, int W, int P)
 
void kv_cache_repack_head_major_inplace (float *buf, int num_heads, int tokens, int cache_capacity, int aligned_head_dim)
 
void kv_cache_store (float *__restrict kv_cache_k, float *__restrict kv_cache_v, const float *__restrict k, const float *__restrict v, int layer, int pos, int num_kv_heads, int head_dim, int max_seq_len)
 
void kv_cache_store_batch_bf16 (uint16_t *__restrict kv_cache_k, uint16_t *__restrict kv_cache_v, const float *__restrict k, const float *__restrict v, int start_pos, int num_tokens, int num_kv_heads, int head_dim, int max_seq_len)
 
void kv_cache_store_batch_f16 (uint16_t *__restrict kv_cache_k, uint16_t *__restrict kv_cache_v, const float *__restrict k, const float *__restrict v, int start_pos, int num_tokens, int num_kv_heads, int head_dim, int max_seq_len)
 
void kv_cache_store_batch_f32 (float *__restrict kv_cache_k, float *__restrict kv_cache_v, const float *__restrict k, const float *__restrict v, int start_pos, int num_tokens, int num_kv_heads, int head_dim, int max_seq_len)
 
void kv_cache_store_bf16 (uint16_t *__restrict kv_cache_k, uint16_t *__restrict kv_cache_v, const float *__restrict k, const float *__restrict v, int layer, int pos, int num_kv_heads, int head_dim, int max_seq_len)
 
void kv_cache_store_f16 (uint16_t *__restrict kv_cache_k, uint16_t *__restrict kv_cache_v, const float *__restrict k, const float *__restrict v, int layer, int pos, int num_kv_heads, int head_dim, int max_seq_len)
 
void kv_cache_store_shared_q (float *__restrict kv_cache_k, float *__restrict kv_cache_v, const float *__restrict q, int layer, int pos, int num_heads, int head_dim, int max_seq_len)
 
void kv_cache_write_head_major (const float *__restrict k_token, const float *__restrict v_token, float *__restrict k_cache, float *__restrict v_cache, int num_kv_heads, int token_index, int cache_capacity, int head_dim, int aligned_head_dim)
 
void layernorm_backward_kernel (const float *d_output, const float *input, const float *gamma, const float *mean, const float *rstd, float *d_input, float *d_gamma, float *d_beta, int tokens, int d_model, int aligned_embed_dim)
 
void layernorm_backward_kernel_bf16 (const uint16_t *d_output, const uint16_t *input, const float *gamma, const float *mean, const float *rstd, uint16_t *d_input, float *d_gamma, float *d_beta, int tokens, int d_model, int aligned_embed_dim, float *scratch_d_output, float *scratch_input, float *scratch_d_input)
 
void layernorm_forward_rolled_slice (const float *__restrict input_slice_base, const float *__restrict gamma, const float *__restrict beta, float *__restrict output_slice_base, float *__restrict mean_cache_slice, float *__restrict rstd_cache_slice, int num_tokens_in_slice, int d_model, int aligned_embed_dim, float eps)
 
void layernorm_forward_rolled_slice_bf16 (const uint16_t *__restrict input_slice_base, const float *__restrict gamma, const float *__restrict beta, uint16_t *__restrict output_slice_base, float *__restrict mean_cache_slice, float *__restrict rstd_cache_slice, int num_tokens_in_slice, int d_model, int aligned_embed_dim, float eps, float *scratch_input, float *scratch_output)
 
void layernorm_forward_unrolled_slice (const float *__restrict input_slice_base, const float *__restrict gamma, const float *__restrict beta, float *__restrict output_slice_base, float *__restrict mean_cache_slice, float *__restrict rstd_cache_slice, int num_tokens_in_slice, int d_model, float eps)
 
void layernorm_forward_unrolled_slice_bf16 (const uint16_t *__restrict input_slice_base, const float *__restrict gamma, const float *__restrict beta, uint16_t *__restrict output_slice_base, float *__restrict mean_cache_slice, float *__restrict rstd_cache_slice, int num_tokens_in_slice, int d_model, float eps, float *scratch_input, float *scratch_output)
 
void layernorm_naive_serial (const float *input, const float *gamma, const float *beta, float *output, float *mean_cache, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void layernorm_naive_serial_bf16_storage (const float *input, const float *gamma, const float *beta, float *output, float *mean_cache, float *rstd_cache, int tokens, int d_model, float eps)
 
void layernorm_naive_serial_matched_precision (const float *input, const float *gamma, const float *beta, float *output, float *mean_cache, float *rstd_cache, int tokens, int d_model, float eps)
 
void layernorm_pytorch_welford_bf16_storage (const float *input, const float *gamma, const float *beta, float *output, float *mean_cache, float *rstd_cache, int tokens, int d_model, float eps)
 
void mamba2_conv1d_decode_f32 (const float *state_in, const float *x, const float *weight, const float *bias, float *conv_out, float *state_out, int rows, int conv_dim, int kernel_size)
 
void mamba2_conv1d_f32_channel_range (const float *state_in, const float *x, const float *weight, const float *bias, float *conv_out, float *state_out, int rows, int conv_dim, int kernel_size, int channel_begin, int channel_end)
 
void mamba2_conv1d_f32_parallel_dispatch (const float *state_in, const float *x, const float *weight, const float *bias, float *conv_out, float *state_out, int rows, int conv_dim, int kernel_size)
 
void mamba2_dt_softplus_f32 (const float *dt, const float *dt_bias, float *dt_out, int rows, int num_heads, float dt_min, float dt_max)
 
void mamba2_in_proj_split_f32 (const float *projected, float *gate, float *hidden_bc, float *dt, int rows, int d_mlp, int intermediate_dim, int conv_dim, int num_heads)
 
void mamba2_rmsnorm_gate_f32 (const float *x, const float *gate, const float *weight, float *out, int rows, int inner_dim, int group_size, float eps)
 
void mamba2_selective_scan_f32 (const float *state_init, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int batch, int seq_len, int num_heads, int head_dim, int state_dim, int num_groups)
 
void mamba2_selective_scan_f32_head_range (const float *state_init, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int batch, int seq_len, int num_heads, int head_dim, int state_dim, int num_groups, int head_begin, int head_end)
 
void mamba2_selective_scan_f32_parallel_dispatch (const float *state_init, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int batch, int seq_len, int num_heads, int head_dim, int state_dim, int num_groups)
 
void mamba2_selective_state_update_decode_f32 (const float *state_in, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int rows, int num_heads, int head_dim, int state_dim, int num_groups)
 
void mlp_token_parallel (const float *input, const float *W_fc1, const float *b_fc1, const float *W_fc2, const float *b_fc2, float *fc1_output, float *output, int T, int aligned_dim, int num_threads)
 
void mlp_token_parallel_bf16 (const uint16_t *input, const uint16_t *W_fc1, const uint16_t *b_fc1, const uint16_t *W_fc2, const uint16_t *b_fc2, float *fc1_output, float *output, int T, int aligned_dim, int num_threads, float *scratch_bias1_f, float *scratch_bias2_f, uint16_t *scratch_fc1_bf16)
 
void mlp_token_parallel_bf16_backward_mixed (const uint16_t *input, const uint16_t *W_fc1, const uint16_t *b_fc1, const uint16_t *W_fc2, const uint16_t *d_output, float *d_input, float *d_W_fc1, float *d_b_fc1, float *d_W_fc2, float *d_b_fc2, int T, int aligned_dim, int num_threads, float *scratch_fc1_pre, uint16_t *scratch_fc1_act_bf16, float *scratch_d_fc1)
 
void mlp_token_parallel_bf16_fp32act (const uint16_t *input, const uint16_t *W_fc1, const uint16_t *b_fc1, const uint16_t *W_fc2, const uint16_t *b_fc2, float *fc1_output, float *output, int T, int aligned_dim, int num_threads, float *scratch_input_f, float *scratch_bias1_f, float *scratch_bias2_f, uint16_t *scratch_fc1_bf16)
 
void mlp_token_parallel_exact (const float *input, const float *W_fc1, const float *b_fc1, const float *W_fc2, const float *b_fc2, float *fc1_output, float *output, int T, int aligned_dim, int num_threads)
 
void moe_accumulate_expert_f32 (float *output, const float *expert_output, float routing_weight, int hidden_dim)
 Accumulate expert output: output += routing_weight * expert_output.
 
void moe_relu2_expert_backward_f32 (const float *d_output, const float *hidden, const int *indices, const float *routing_weights, const float *expert_up, const float *expert_down, float *d_hidden, float *d_routing_weights, float *d_expert_up, float *d_expert_down, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
void moe_relu2_expert_forward_f32 (const float *hidden, const int *indices, const float *routing_weights, const float *expert_up, const float *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
void moe_relu2_expert_forward_q5_0_q5_0 (const float *hidden, const int *indices, const float *routing_weights, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
void moe_relu2_expert_forward_q5_0_q8_0 (const float *hidden, const int *indices, const float *routing_weights, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
void moe_relu2_shared_forward_q5_1_q8_0 (const float *hidden, const float *routed, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim)
 
int moe_softmax_topk_router_llama_f32_workspace (const float *logits, int *indices, float *weights, int rows, int n_experts, int top_k, float routed_scaling_factor, void *workspace, size_t workspace_bytes)
 
int moe_softmax_topk_router_pytorch_bf16_workspace (const float *logits, int *indices, float *weights, int rows, int n_experts, int top_k, float routed_scaling_factor, void *workspace, size_t workspace_bytes)
 
size_t moe_softmax_topk_router_workspace_bytes (int n_experts)
 
void moe_swiglu_expert_forward_bf16 (const float *hidden, const int *indices, const float *routing_weights, const uint16_t *expert_gate, const uint16_t *expert_up, const uint16_t *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
void moe_swiglu_expert_forward_bf16_parallel_dispatch (const float *hidden, const int *indices, const float *routing_weights, const uint16_t *expert_gate, const uint16_t *expert_up, const uint16_t *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
void moe_swiglu_expert_forward_bf16_row_range (const float *hidden, const int *indices, const float *routing_weights, const uint16_t *expert_gate, const uint16_t *expert_up, const uint16_t *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, int row_begin, int row_end)
 
void moe_swiglu_expert_forward_f32 (const float *hidden, const int *indices, const float *routing_weights, const float *expert_gate, const float *expert_up, const float *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
int moe_swiglu_expert_forward_q4k_q4k_parallel_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q4k_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5_0_parallel_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5_0_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5k_auto_prepared_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5k_auto_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5k_bucketed_prepared_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, const void *expert_gate_packed, const void *expert_up_packed, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5k_bucketed_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5k_parallel_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q5k_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q6k_parallel_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q6k_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q8_0_parallel_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_expert_forward_q4k_q8_0_workspace (const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
 
size_t moe_swiglu_expert_q4k_q5k_workspace_bytes (int hidden_dim, int intermediate_dim)
 
size_t moe_swiglu_expert_q4k_q8_0_workspace_bytes (int hidden_dim, int intermediate_dim)
 
void moe_swiglu_packed_expert_forward_bf16 (const float *hidden, const int *indices, const float *routing_weights, const uint16_t *expert_gate_up, const uint16_t *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k)
 
void moe_swiglu_shared_forward_bf16 (const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim)
 
void moe_swiglu_shared_forward_bf16_gated (const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, const uint16_t *shared_router, float *output, int rows, int hidden_dim, int intermediate_dim)
 
void moe_swiglu_shared_forward_bf16_gated_parallel_dispatch (const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, const uint16_t *shared_router, float *output, int rows, int hidden_dim, int intermediate_dim)
 
void moe_swiglu_shared_forward_bf16_gated_row_range (const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, const uint16_t *shared_router, float *output, int rows, int hidden_dim, int intermediate_dim, int row_begin, int row_end)
 
void moe_swiglu_shared_forward_bf16_parallel_dispatch (const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim)
 
void moe_swiglu_shared_forward_bf16_row_range (const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, int row_begin, int row_end)
 
void moe_swiglu_shared_forward_f32 (const float *hidden, const float *routed, const float *shared_gate, const float *shared_up, const float *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim)
 
int moe_swiglu_shared_forward_q4k_q4k_parallel_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q4k_q4k_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q4k_q5_0_gated_parallel_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q4k_q5_0_gated_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q4k_q6k_parallel_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q4k_q6k_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q4k_q8_0_gated_parallel_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q4k_q8_0_gated_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q8_0_gated_parallel_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
int moe_swiglu_shared_forward_q8_0_gated_workspace (const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
 
size_t moe_swiglu_shared_q4k_q8_0_gated_workspace_bytes (int hidden_dim, int intermediate_dim)
 
size_t moe_swiglu_shared_q8_0_gated_workspace_bytes (int hidden_dim, int intermediate_dim)
 
void mrope_qk_imrope_positions (float *q, float *k, const int32_t *positions, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_text (float *q, float *k, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_text_imrope (float *q, float *k, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_text_imrope_bf16_pytorch_storage (float *q, float *k, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_text_imrope_positions_bf16_pytorch_storage (float *q, float *k, const int32_t *positions, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_vision (float *q, float *k, const int32_t *positions, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_vision_bf16_pytorch_storage (float *q, float *k, const int32_t *positions, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_vision_bf16_storage (float *q, float *k, const int32_t *positions, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void mrope_qk_vision_fp16_storage (float *q, float *k, const int32_t *positions, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, int section_0, int section_1, int section_2, int section_3, int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)
 
void nemotron_group_limited_topk_router_f32 (const float *scores, const float *correction_bias, int *indices, float *weights, int rows, int n_experts, int top_k, int n_group, int topk_group, int norm_topk_prob, float routed_scaling_factor)
 
void patch2im (const float *d_patches, float *d_image, int C, int H, int W, int P)
 
void patch2im_bf16 (const uint16_t *d_patches, uint16_t *d_image, int C, int H, int W, int P)
 
void patch_projection_bf16_pytorch_onednn_conv3d_storage (const float *input, const void *weights, const float *bias, float *output, int batch, int out_channels, int in_channels, int temporal, int patch_h, int patch_w)
 
void patch_projection_image_bf16_native_storage (const float *image, const void *weights_t0, const void *weights_t1, const float *bias, float *output, int channels, int image_h, int image_w, int patch_size, int out_channels, int merge_size)
 
void patch_projection_image_bf16_pytorch_onednn_conv3d_storage (const float *image, const void *weights_t0, const void *weights_t1, const float *bias, float *output, int channels, int image_h, int image_w, int patch_size, int out_channels, int merge_size)
 
void position_embeddings_add (float *x, const float *position_embd, int num_tokens, int embed_dim, int num_positions)
 
void position_embeddings_add_at_offset (float *x, const float *position_embd, int num_tokens, int embed_dim, int num_positions, int start_position)
 
void position_embeddings_add_gemma4v_xy (float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int source_grid_size)
 
void position_embeddings_add_tiled_2d (float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
 
void position_embeddings_add_tiled_2d_align_corners (float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
 
void position_embeddings_add_tiled_2d_align_corners_bf16 (float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
 
void position_embeddings_add_tiled_2d_align_corners_fp32_interp_bf16 (float *x, const float *position_embd, int grid_h, int grid_w, int embed_dim, int merge_size, int source_grid_size)
 
void q_norm_forward (float *q, const float *q_gamma, int num_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_backward (const float *d_q_out, const float *d_k_out, const float *q_in, const float *k_in, const float *q_gamma, const float *k_gamma, float *d_q_in, float *d_k_in, float *d_q_gamma, float *d_k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
int qk_norm_backward_last_isa (void)
 
void qk_norm_forward (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_decode_exact (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_fp64_sum (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_llama_production (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_llama_production_parallel_dispatch (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_muse_unweighted_scaled_pytorch_bf16_storage (float *q, float *k, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps, float q_scale)
 
void qk_norm_forward_parallel_dispatch (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_prefill_exact (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_pytorch_bf16_storage (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void qk_norm_forward_qwen4_pytorch_bf16_storage (float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
 
void quantize_batch_q8_0 (const float *x, void *y, int num_rows, int k)
 Batch quantize FP32 to Q8_0 format (row-major output)
 
void quantize_batch_q8_k (const float *x, void *y, int num_rows, int k)
 Batch quantize FP32 to Q8_K format (row-major output)
 
void quantize_batch_q8_k_4row_nearest_even (const float *x, void *y, int num_rows, int k)
 
void quantize_row_q8_0 (const float *x, void *y, int k)
 Quantize FP32 to Q8_0 format (scalar reference)
 
void quantize_row_q8_k (const float *x, void *y, int k)
 
void qwen4_ple_gate_conv_inject_bf16 (const float *hyper_input, const float *key_projected, const float *value_projected, const float *norm_key_weight, const float *norm_query_weight, const float *norm_conv_weight, const uint16_t *conv_weight, float *hyper_output, float *key_norm_scratch, float *query_norm_scratch, float *gated_scratch, float *conv_norm_scratch, const float *conv_state_in, float *conv_state_out, int rows, int streams, int hidden_dim, int kernel_size, int dilation, float eps)
 
void qwen4_ple_gate_conv_inject_fp16 (const float *hyper_input, const float *key_projected, const float *value_projected, const float *norm_key_weight, const float *norm_query_weight, const float *norm_conv_weight, const uint16_t *conv_weight, float *hyper_output, float *key_norm_scratch, float *query_norm_scratch, float *gated_scratch, float *conv_norm_scratch, const float *conv_state_in, float *conv_state_out, int rows, int streams, int hidden_dim, int kernel_size, int dilation, float eps)
 
void qwen4_ple_gate_conv_inject_llama_fp16 (const float *hyper_input, const float *key_projected, const float *value_projected, const float *norm_key_weight, const float *norm_query_weight, const float *norm_conv_weight, const uint16_t *conv_weight, float *hyper_output, float *key_norm_scratch, float *query_norm_scratch, float *gated_scratch, float *conv_norm_scratch, const float *conv_state_in, float *conv_state_out, int rows, int streams, int hidden_dim, int kernel_size, int dilation, float eps)
 
void qwen4_ple_ngram_embed_bf16 (const int32_t *token_ids, const uint16_t *embedding, const int64_t *layer_multipliers, const int64_t *head_offsets, const int64_t *head_vocab_sizes, float *output, const float *token_state_in, float *token_state_out, int rows, int ngram_size, int heads_per_ngram, int head_dim, int eos_token_id, int position)
 
void qwen4_ple_ngram_embed_q5_0 (const int32_t *token_ids, const void *embedding, const int64_t *layer_multipliers, const int64_t *head_offsets, const int64_t *head_vocab_sizes, float *output, const float *token_state_in, float *token_state_out, int rows, int ngram_size, int heads_per_ngram, int head_dim, int eos_token_id, int position)
 
void qwen4_qsa_index_select_bf16 (const float *projected_qk, const float *index_key_cache_in, const float *q_norm_weight, const float *k_norm_weight, float *selected_indices, float *index_key_cache_out, float *q_norm_scratch, float *pooled_key_scratch, float *block_score_scratch, int32_t *block_index_scratch, int rows, int query_heads, int index_head_dim, int token_budget, int compress_ratio, int rotary_dim, int context_length, int position, float rope_theta, float eps)
 
void recurrent_conv_state_update_backward (const float *d_conv_x, const float *d_state_out, float *d_state_in, float *d_q, float *d_k, float *d_v, int history_len, int num_seqs, int num_tokens, int q_dim, int k_dim, int v_dim)
 
void recurrent_conv_state_update_backward_workspace (const float *d_conv_x, const float *d_state_out, float *d_state_in, float *d_q, float *d_k, float *d_v, float *d_conv_total, int history_len, int num_seqs, int num_tokens, int q_dim, int k_dim, int v_dim)
 
void recurrent_conv_state_update_forward (const float *state_in, const float *q, const float *k, const float *v, float *conv_x, float *state_out, int history_len, int num_seqs, int num_tokens, int q_dim, int k_dim, int v_dim)
 
void recurrent_dt_gate_backward (const float *d_gate, const float *alpha, const float *dt_bias, const float *a, float *d_alpha, float *d_dt_bias, float *d_a, int rows, int dim)
 
void recurrent_dt_gate_expanded_forward (const float *alpha, const float *dt_bias, const float *a, float *gate, int rows, int num_heads, int state_dim)
 
void recurrent_dt_gate_forward (const float *alpha, const float *dt_bias, const float *a, float *gate, int rows, int num_heads, int state_dim)
 
void recurrent_dt_gate_forward_pytorch_fp32 (const float *alpha, const float *dt_bias, const float *a, float *gate, int rows, int num_heads, int state_dim)
 
void recurrent_norm_gate_backward (const float *d_out, const float *x, const float *gate, const float *weight, float *d_x, float *d_gate, float *d_weight, int rows, int num_heads, int head_dim, float eps)
 
void recurrent_norm_gate_forward (const float *x, const float *gate, const float *weight, float *out, int rows, int num_heads, int head_dim, float eps)
 
void recurrent_norm_gate_llama_avx2_forward (const float *x, const float *gate, const float *weight, float *out, int rows, int num_heads, int head_dim, float eps)
 
void recurrent_norm_gate_pytorch_bf16_storage (const float *x, const float *gate, const float *weight, float *out, int rows, int num_heads, int head_dim, float eps)
 
void recurrent_norm_sigmoid_gate_llama_avx2_forward (const float *x, const float *gate, const float *weight, float *out, int rows, int num_heads, int head_dim, float eps)
 
void recurrent_norm_sigmoid_gate_pytorch_bf16_storage (const float *x, const float *gate, const float *weight, float *out, int rows, int num_heads, int head_dim, float eps)
 
void recurrent_qk_l2_norm_backward (const float *d_q_out, const float *d_k_out, const float *q, const float *k, float *d_q, float *d_k, int rows, int q_dim, int k_dim, int head_dim, float eps)
 
void recurrent_qk_l2_norm_forward (float *q, float *k, int rows, int q_dim, int k_dim, int head_dim, float eps)
 
void recurrent_qk_l2_norm_pytorch_bf16_storage (float *q, float *k, int rows, int q_dim, int k_dim, int expanded_heads, int head_dim, float eps)
 
void recurrent_qk_l2_norm_pytorch_fp32_output (float *q, float *k, int rows, int q_dim, int k_dim, int head_dim, float eps)
 
void recurrent_sigmoid_forward_ggml (const float *x, float *out, int rows, int dim)
 
void recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output (const float *x, float *out, int rows, int dim)
 
void recurrent_silu_backward (const float *d_out, const float *x, float *d_x, int rows, int dim)
 
void recurrent_silu_forward (const float *x, float *out, int rows, int dim)
 
void recurrent_silu_forward_ggml (const float *x, float *out, int rows, int dim)
 
void recurrent_silu_forward_pytorch_bf16_input_fp32_output (const float *x, float *out, int rows, int dim)
 
void recurrent_silu_forward_pytorch_bf16_storage (const float *x, float *out, int rows, int dim)
 
void recurrent_split_conv_qkv_backward (const float *d_q, const float *d_k, const float *d_v, float *d_packed_qkv, int rows, int q_dim, int k_dim, int v_dim)
 
void recurrent_split_conv_qkv_forward (const float *packed_qkv, float *q, float *k, float *v, int rows, int q_dim, int k_dim, int v_dim)
 
void recurrent_split_qkv_backward (const float *d_q, const float *d_k, const float *d_v, float *d_packed_qkv, int rows, int q_dim, int k_dim, int v_dim)
 
void recurrent_split_qkv_forward (const float *packed_qkv, float *q, float *k, float *v, int rows, int q_dim, int k_dim, int v_dim)
 
void relu2_backward (const float *input, const float *d_output, float *d_input, size_t n)
 
void relu2_forward (const float *input, float *output, size_t n)
 
void relu_backward (const float *input, const float *d_output, float *d_input, size_t n)
 
void relu_backward_bf16 (const uint16_t *input, const uint16_t *d_output, uint16_t *d_input, size_t n)
 
void relu_forward (const float *input, float *output, size_t n)
 
void relu_forward_bf16 (const uint16_t *input, uint16_t *output, size_t n)
 
void relu_forward_inplace (float *data, size_t n)
 
void relu_forward_inplace_bf16 (uint16_t *data, size_t n)
 
void rmsnorm_backward (const float *d_output, const float *input, const float *gamma, const float *rstd_cache, float *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim)
 
void rmsnorm_backward_bf16 (const uint16_t *d_output, const uint16_t *input, const float *gamma, const float *rstd_cache, uint16_t *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim)
 
void rmsnorm_backward_int4 (const uint8_t *d_output, const uint8_t *input, const float *gamma, const float *rstd_cache, uint8_t *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim, float *scratch_d_output, float *scratch_input, float *scratch_d_input)
 
void rmsnorm_backward_int8 (const int8_t *d_output, const int8_t *input, const float *gamma, const float *rstd_cache, int8_t *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim, float *scratch_d_output, float *scratch_input, float *scratch_d_input)
 
void rmsnorm_forward (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_bf16 (const uint16_t *input, const float *gamma, uint16_t *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_fp32_square_fp64_sum (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_fp64_sum (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_int4 (const uint8_t *input, const float *gamma, uint8_t *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps, float *scratch_input, float *scratch_output)
 
void rmsnorm_forward_int8 (const int8_t *input, const float *gamma, int8_t *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps, float *scratch_input, float *scratch_output)
 
void rmsnorm_forward_kv_lora (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_llama_production (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_muse_centered_pytorch_bf16_storage (const float *input, const float *zero_centered_weight, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_muse_unweighted_pytorch_bf16_storage (const float *input, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_muse_weighted_pytorch_bf16_storage (const float *input, const float *weight, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_no_weight (const float *input, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_no_weight_llama_production (const float *input, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_parallel_dispatch (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_pytorch_bf16_storage (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_qwen3next_pytorch_bf16_storage (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
 
void rmsnorm_forward_strided_f32 (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int input_stride, int output_stride, float eps)
 
void rmsnorm_forward_strided_pytorch_bf16_storage (const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int input_stride, int output_stride, float eps)
 
void rope_backward (const float *d_out, float *d_x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset)
 
void rope_backward_bf16 (const uint16_t *d_out, uint16_t *d_x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, float *scratch_d_out, float *scratch_d_x)
 
void rope_backward_inplace (float *d_x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset)
 
void rope_backward_qk (const float *d_q_out, const float *d_k_out, float *d_q, float *d_k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset)
 
void rope_backward_qk_bf16 (const uint16_t *d_q_out, const uint16_t *d_k_out, uint16_t *d_q, uint16_t *d_k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, float *scratch_dq_out, float *scratch_dq, float *scratch_dk_out, float *scratch_dk)
 
void rope_backward_qk_pairwise_with_rotary_dim (const float *d_q_out, const float *d_k_out, float *d_q, float *d_k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)
 
void rope_forward (float *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset)
 
void rope_forward_bf16 (uint16_t *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, float *scratch)
 
void rope_forward_bf16_with_rotary_dim (uint16_t *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float *scratch)
 
void rope_forward_q_split_direct_f32 (float *q, const float *freq_factors, int use_freq_factors, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)
 
void rope_forward_q_split_llama_f32 (float *q, const float *freq_factors, int use_freq_factors, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)
 
void rope_forward_qk (float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset)
 
void rope_forward_qk_bf16 (uint16_t *q, uint16_t *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, float *scratch_q, float *scratch_k)
 
void rope_forward_qk_bf16_with_rotary_dim (uint16_t *q, uint16_t *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float *scratch_q, float *scratch_k)
 
void rope_forward_qk_gemma4_direct (float *q, float *k, const float *freq_factors, int use_freq_factors, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)
 
void rope_forward_qk_gemma4v_vision_xy (float *q, float *k, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int grid_w, int rotary_dim, float freq_base)
 
void rope_forward_qk_pairwise_llama_cpu (float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)
 
void rope_forward_qk_pairwise_with_rotary_dim (float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)
 
void rope_forward_qk_split_direct_f32 (float *q, float *k, const float *freq_factors, int use_freq_factors, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)
 
void rope_forward_qk_split_direct_muse_pytorch_bf16_storage (float *q, float *k, const float *freq_factors, int use_freq_factors, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)
 
void rope_forward_qk_split_direct_token_range_f32 (float *q, float *k, const float *freq_factors, int use_freq_factors, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base, int token_begin, int token_end)
 
void rope_forward_qk_split_llama_token_range_f32 (float *q, float *k, const float *freq_factors, int use_freq_factors, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base, int token_begin, int token_end)
 
void rope_forward_qk_strided (float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int q_stride_tokens, int k_stride_tokens)
 
void rope_forward_qk_strided_with_rotary_dim (float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int q_stride_tokens, int k_stride_tokens, int rotary_dim)
 
void rope_forward_qk_with_rotary_dim (float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)
 
void rope_forward_qk_with_rotary_dim_cache_stride (float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, int cache_rotary_dim)
 
void rope_forward_strided (float *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int head_stride_tokens)
 
void rope_forward_strided_with_rotary_dim (float *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int head_stride_tokens, int rotary_dim)
 
void rope_forward_with_rotary_dim (float *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)
 
void rope_precompute_cache (float *cos_cache, float *sin_cache, int max_seq_len, int head_dim, float base, int rotary_dim, const char *scaling_type, float scaling_factor)
 
void rope_precompute_cache_llama_cpu (float *cos_cache, float *sin_cache, int max_seq_len, int head_dim, float base, int rotary_dim, const char *scaling_type, float scaling_factor)
 
void rope_precompute_cache_split (float *cos_cache, float *sin_cache, int max_seq_len, int head_dim, float base)
 
void rowwise_bias_add (float *x, const float *bias, int rows, int dim)
 
void scal_copy_f32 (float *y, const float *x, float alpha, int n)
 Scaled copy: y = alpha * x.
 
void sigmoid_backward (const float *input, const float *d_output, float *d_input, size_t n)
 
void sigmoid_backward_bf16 (const uint16_t *input, const uint16_t *d_output, uint16_t *d_input, size_t n, float *scratch_input, float *scratch_d_output, float *scratch_d_input)
 
void sigmoid_forward (const float *input, float *output, size_t n)
 
void sigmoid_forward_bf16 (const uint16_t *input, uint16_t *output, size_t n, float *scratch_input, float *scratch_output)
 
float sigmoid_scalar (float x)
 
void softmax_cross_entropy_loss (const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)
 
void softmax_cross_entropy_loss_bf16 (const uint16_t *logits, const int32_t *targets, int tokens, int vocab_size, uint16_t *d_logits, float *loss_out, float *scratch_logits, float *scratch_d_logits)
 
void softmax_cross_entropy_loss_ptref (const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)
 
void spatial_average_pool_contiguous (const float *input, float *output, int grid_h, int grid_w, int embed_dim, int merge_size)
 
void spatial_merge_2x2 (const float *input, float *output, int grid_h, int grid_w, int embed_dim)
 
void spatial_merge_contiguous_tiled (const float *input, float *output, int grid_h, int grid_w, int embed_dim, int merge_size)
 
void speculative_commit_one_i32 (int accepted, int verified_token, int *token_buffer, int *token_count, int max_tokens, int *target_position, int *draft_position, int *accepted_count, int *rejected_count)
 Commit one verified speculative token and update decode counters.
 
void speculative_verify_greedy_f32 (const float *target_logits, int vocab_size, int draft_token, int *accepted, int *verified_token)
 Greedy one-token speculative verification.
 
void split_q_gate_backward (const float *d_q, const float *d_gate, float *d_packed_qg, int rows, int q_dim, int gate_dim, int group_dim)
 
void split_q_gate_forward (const float *packed_qg, float *q, float *gate, int rows, int q_dim, int gate_dim, int group_dim)
 
void split_qkv_packed_head_major_forward (const float *packed_qkv, float *q, float *k, float *v, int rows, int q_dim, int k_dim, int v_dim, int num_heads, int num_kv_heads)
 
void ssm_conv1d_backward (const float *d_out, const float *conv_x, const float *kernel, float *d_conv_x, float *d_kernel, int kernel_size, int num_channels, int num_tokens, int num_seqs)
 
void ssm_conv1d_forward (const float *conv_x, const float *kernel, float *out, int kernel_size, int num_channels, int num_tokens, int num_seqs)
 
void ssm_conv1d_forward_llama_fma (const float *conv_x, const float *kernel, float *out, int kernel_size, int num_channels, int num_tokens, int num_seqs)
 
void ssm_conv1d_forward_llama_production (const float *conv_x, const float *kernel, float *out, int kernel_size, int num_channels, int num_tokens, int num_seqs)
 
void ssm_conv1d_forward_llama_production_serial (const float *conv_x, const float *kernel, float *out, int kernel_size, int num_channels, int num_tokens, int num_seqs)
 
void ssm_conv1d_forward_pytorch_bf16_storage (const float *conv_x, const float *kernel, float *out, int kernel_size, int num_channels, int num_tokens, int num_seqs)
 
void swiglu_backward (const float *input, const float *d_output, float *d_input, int tokens, int dim)
 
void swiglu_backward_bf16 (const uint16_t *input, const uint16_t *d_output, uint16_t *d_input, int tokens, int dim)
 
void swiglu_backward_exact (const float *input, const float *d_output, float *d_input, int tokens, int dim)
 
void swiglu_forward (const float *input, float *output, int tokens, int dim)
 
void swiglu_forward_bf16 (const uint16_t *input, uint16_t *output, int tokens, int dim)
 
void swiglu_forward_exact (const float *input, float *output, int tokens, int dim)
 
void swiglu_forward_ggml (const float *input, float *output, int tokens, int dim)
 
void swiglu_forward_ggml_split (const float *gate, const float *up, float *output, int tokens, int dim)
 
void swiglu_forward_pytorch_bf16_storage (const float *input, float *output, int tokens, int dim)
 
void swiglu_forward_q8_k (const float *input, void *output_q8, int tokens, int dim)
 
void topk_batched_f32 (const float *scores, int num_tokens, int n_experts, int k, int *indices, float *weights)
 Batched top-K selection for multiple tokens.
 
void topk_f32 (const float *scores, int n, int k, int *indices, float *values)
 Find top-K indices and values from a score vector.
 
void topk_softmax_backward_f32 (const int *indices, const float *weights, const float *d_weights, float *d_scores, int num_tokens, int n_experts_or_keys, int k)
 Backward for hard top-k followed by softmax over selected values.
 
void topk_softmax_f32 (const float *scores, int n, int k, int *indices, float *weights)
 Find top-K indices with softmax-normalized weights.
 
void unfused_rmsnorm_qkv_prefill (const float *x, const float *gamma, const float *Wq, const float *Wk, const float *Wv, float *x_norm, float *Q, float *K, float *V, int seq_len, int hidden, int q_dim, int kv_dim, float eps)
 Unfused version for benchmarking comparison.
 
void vec_dot_q6_k_q8_k (int n, float *s, const void *vx, const void *vy)
 Q6_K x Q8_K dot product (single row)
 
void vision_position_ids_2d_merge (int32_t *positions, int grid_h, int grid_w, int merge_size)
 
void weighted_sum_f32 (float *y, const float **vectors, const float *weights, int k, int n)
 Weighted sum of k vectors: y = sum_i(weights[i] * vectors[i])
 
void yarn_rope_cache_contiguous_positions_f32 (float *cos_cache, float *sin_cache, int num_tokens, int rotary_dim, float freq_base, float factor, int original_context, float beta_fast, float beta_slow, float mscale, float mscale_all_dim)
 
void yarn_rope_cache_explicit_positions_bf16 (uint16_t *cos_cache, uint16_t *sin_cache, const int32_t *positions, int num_tokens, int rotary_dim, float freq_base, float factor, int original_context, float beta_fast, float beta_slow, float mscale, float mscale_all_dim)
 
void yarn_rope_cache_explicit_positions_f32 (float *cos_cache, float *sin_cache, const int32_t *positions, int num_tokens, int rotary_dim, float freq_base, float factor, int original_context, float beta_fast, float beta_slow, float mscale, float mscale_all_dim)
 

Enumeration Type Documentation

◆ ck_attention_prefill_schedule_t

Enumerator
CK_ATTN_PREFILL_SCHEDULE_KV_HEADS 
CK_ATTN_PREFILL_SCHEDULE_QUERY_HEADS 
CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES 
CK_ATTN_PREFILL_SCHEDULE_KV_GROUP_QUERY_TILES 
CK_ATTN_PREFILL_SCHEDULE_GQA_SHARED_KV_TILES 

Definition at line 2296 of file ckernel_engine.h.

◆ ck_attention_reduction_t

Enumerator
CK_ATTN_REDUCTION_FP32_ONLINE 
CK_ATTN_REDUCTION_F16_ONLINE_FP32_MERGE 
CK_ATTN_REDUCTION_F16_ONLINE_SINGLE_RANGE 
CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64 
CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA 
CK_ATTN_REDUCTION_F16_REGULAR_NOSCALE 
CK_ATTN_REDUCTION_F16_FLASH_AUTO_QTILE64_REGULAR_TAIL_NOSCALE 

Definition at line 2284 of file ckernel_engine.h.

◆ ck_attention_status_t

Enumerator
CK_ATTENTION_STATUS_OK 
CK_ATTENTION_STATUS_INVALID_ARGUMENT 
CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT 
CK_ATTENTION_STATUS_INSUFFICIENT_WORKSPACE 

Definition at line 2304 of file ckernel_engine.h.

2304 {
ck_attention_status_t
@ CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT
@ CK_ATTENTION_STATUS_OK
@ CK_ATTENTION_STATUS_INVALID_ARGUMENT
@ CK_ATTENTION_STATUS_INSUFFICIENT_WORKSPACE

Function Documentation

◆ adamw_clip_update_multi_f32()

void adamw_clip_update_multi_f32 ( float *const *  grads,
float *const *  weights,
float *const *  m_states,
float *const *  v_states,
const size_t *  numels,
int  tensor_count,
float  lr,
float  beta1,
float  beta2,
float  eps,
float  weight_decay,
float  max_grad_norm,
int  step 
)

Definition at line 638 of file optimizer_kernels.c.

652{
653 if (!grads || !weights || !m_states || !v_states || !numels || tensor_count <= 0) {
654 return;
655 }
656
657 size_t total_numel = 0;
658 int valid_tensors = 0;
659 for (int i = 0; i < tensor_count; ++i) {
660 if (grads[i] && weights[i] && m_states[i] && v_states[i] && numels[i] > 0) {
661 total_numel += numels[i];
662 valid_tensors += 1;
663 }
664 }
665 if (valid_tensors == 0 || total_numel == 0) {
666 return;
667 }
668
669 float grad_scale = 1.0f;
670 if (max_grad_norm > 0.0f) {
671 float global_norm = gradient_global_norm_multi_f32((const float *const *)grads, numels, tensor_count);
672 if (global_norm > max_grad_norm) {
673 grad_scale = max_grad_norm / global_norm;
674 }
675 }
676
677 ck_threadpool_t *pool = ck_threadpool_global();
678 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
679
680 if (!pool || nth <= 1 || nth > CK_OPT_PAR_MAX_THREADS ||
681 total_numel < CK_OPT_PAR_MIN_NUMEL || valid_tensors < 2) {
682 for (int i = 0; i < tensor_count; ++i) {
683 float *g = grads[i];
684 float *w = weights[i];
685 float *m = m_states[i];
686 float *v = v_states[i];
687 size_t n = numels[i];
688 if (!g || !w || !m || !v || n == 0) {
689 continue;
690 }
691 if (grad_scale != 1.0f) {
692 gradient_scale_f32_impl(g, n, grad_scale);
693 }
694 adamw_update_f32_impl(g, w, m, v, n, lr, beta1, beta2, eps, weight_decay, step);
695 }
696 return;
697 }
698 int active_nth = ck_opt_pick_active_threads(nth, total_numel, CK_OPT_PAR_MIN_NUMEL);
699 if (active_nth > valid_tensors) {
700 active_nth = valid_tensors;
701 }
702 if (active_nth <= 1) {
703 for (int i = 0; i < tensor_count; ++i) {
704 float *g = grads[i];
705 float *w = weights[i];
706 float *m = m_states[i];
707 float *v = v_states[i];
708 size_t n = numels[i];
709 if (!g || !w || !m || !v || n == 0) {
710 continue;
711 }
712 if (grad_scale != 1.0f) {
713 gradient_scale_f32_impl(g, n, grad_scale);
714 }
715 adamw_update_f32_impl(g, w, m, v, n, lr, beta1, beta2, eps, weight_decay, step);
716 }
717 return;
718 }
719
720 ck_adamw_multi_parallel_args_t args = {
721 .grads = grads,
722 .weights = weights,
723 .m_states = m_states,
724 .v_states = v_states,
725 .numels = numels,
726 .tensor_count = tensor_count,
727 .lr = lr,
728 .beta1 = beta1,
729 .beta2 = beta2,
730 .eps = eps,
731 .weight_decay = weight_decay,
732 .grad_scale = grad_scale,
733 .step = step,
734 };
736}
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)
static void adamw_update_f32_impl(const float *grad, float *weight, float *m, float *v, size_t numel, float lr, float beta1, float beta2, float eps, float weight_decay, int step)
AdamW optimizer update (fp32 version)
static int ck_opt_pick_active_threads(int nth, size_t work_items, size_t min_chunk)
#define CK_OPT_PAR_MIN_NUMEL
float gradient_global_norm_multi_f32(const float *const *grads, const size_t *numels, int tensor_count)
static void ck_adamw_multi_parallel_work(int ith, int nth, void *argp)
static void gradient_scale_f32_impl(float *grad, size_t numel, float scale)
Scale gradients by a constant: grad *= scale (fp32)
#define CK_OPT_PAR_MAX_THREADS

References adamw_update_f32_impl(), ck_adamw_multi_parallel_work(), CK_OPT_PAR_MAX_THREADS, CK_OPT_PAR_MIN_NUMEL, ck_opt_pick_active_threads(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), gradient_global_norm_multi_f32(), and gradient_scale_f32_impl().

◆ adamw_update_f32()

void adamw_update_f32 ( const float *  grad,
float *  weight,
float *  m,
float *  v,
size_t  numel,
float  lr,
float  beta1,
float  beta2,
float  eps,
float  weight_decay,
int  step 
)

Definition at line 592 of file optimizer_kernels.c.

604{
605 if (!grad || !weight || !m || !v || numel == 0) {
606 return;
607 }
608
609 ck_threadpool_t *pool = ck_threadpool_global();
610 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
611 if (!pool || nth <= 1 || nth > CK_OPT_PAR_MAX_THREADS || numel < CK_OPT_PAR_MIN_NUMEL) {
612 adamw_update_f32_impl(grad, weight, m, v, numel, lr, beta1, beta2, eps, weight_decay, step);
613 return;
614 }
615 int active_nth = ck_opt_pick_active_threads(nth, numel, CK_OPT_PAR_MIN_NUMEL);
616 if (active_nth <= 1) {
617 adamw_update_f32_impl(grad, weight, m, v, numel, lr, beta1, beta2, eps, weight_decay, step);
618 return;
619 }
620
621 ck_adamw_parallel_args_t args = {
622 .grad = grad,
623 .weight = weight,
624 .m = m,
625 .v = v,
626 .numel = numel,
627 .lr = lr,
628 .beta1 = beta1,
629 .beta2 = beta2,
630 .eps = eps,
631 .weight_decay = weight_decay,
632 .step = step,
633 };
634 ck_threadpool_dispatch_n(pool, active_nth, ck_adamw_parallel_work, &args);
635}
static void ck_adamw_parallel_work(int ith, int nth, void *argp)

References adamw_update_f32_impl(), ck_adamw_parallel_work(), CK_OPT_PAR_MAX_THREADS, CK_OPT_PAR_MIN_NUMEL, ck_opt_pick_active_threads(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

◆ add_backward_bf16()

void add_backward_bf16 ( const uint16_t *  d_y,
uint16_t *  d_a,
uint16_t *  d_b,
size_t  n 
)

Definition at line 187 of file add_kernels_bf16.c.

191{
192 if (!d_y || n == 0) {
193 return;
194 }
195
196 size_t i = 0;
197
198 /* Copy to d_a if not in-place */
199 if (d_a && d_a != d_y) {
200#if defined(__AVX512F__)
201 for (; i + 32 <= n; i += 32) {
202 __m512i values = _mm512_loadu_si512((const __m512i*)&d_y[i]);
203 _mm512_storeu_si512((__m512i*)&d_a[i], values);
204 }
205#endif
206 for (; i < n; ++i) {
207 d_a[i] = d_y[i];
208 }
209 }
210
211 /* Copy to d_b if not in-place */
212 i = 0;
213 if (d_b && d_b != d_y) {
214#if defined(__AVX512F__)
215 for (; i + 32 <= n; i += 32) {
216 __m512i values = _mm512_loadu_si512((const __m512i*)&d_y[i]);
217 _mm512_storeu_si512((__m512i*)&d_b[i], values);
218 }
219#endif
220 for (; i < n; ++i) {
221 d_b[i] = d_y[i];
222 }
223 }
224}

◆ add_forward_2d_bf16()

void add_forward_2d_bf16 ( const uint16_t *  a,
const uint16_t *  b,
uint16_t *  y,
int  tokens,
int  dim,
int  aligned_dim 
)

Definition at line 231 of file add_kernels_bf16.c.

237{
238 if (!a || !b || !y || tokens <= 0 || dim <= 0) {
239 return;
240 }
241
242 for (int t = 0; t < tokens; ++t) {
243 const uint16_t *a_row = a + (size_t)t * aligned_dim;
244 const uint16_t *b_row = b + (size_t)t * aligned_dim;
245 uint16_t *y_row = y + (size_t)t * aligned_dim;
246
247 int d = 0;
248
249#if defined(__AVX512F__)
250 for (; d + 16 <= dim; d += 16) {
251 __m512 av = bf16_loadu_cvt_fp32(&a_row[d]);
252 __m512 bv = bf16_loadu_cvt_fp32(&b_row[d]);
253 __m512 yv = _mm512_add_ps(av, bv);
254 fp32_cvt_storeu_bf16(&y_row[d], yv);
255 }
256#endif
257
258 for (; d < dim; ++d) {
259 float af = bf16_to_float(a_row[d]);
260 float bf = bf16_to_float(b_row[d]);
261 y_row[d] = float_to_bf16(af + bf);
262 }
263 }
264}
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

References bf16_to_float(), and float_to_bf16().

◆ add_forward_bf16()

void add_forward_bf16 ( const uint16_t *  a,
const uint16_t *  b,
uint16_t *  y,
size_t  n 
)

Definition at line 38 of file add_kernels_bf16.c.

42{
43 if (!a || !b || !y || n == 0) {
44 return;
45 }
46
47 size_t i = 0;
48
49#if defined(__AVX512F__)
50 /* AVX-512: Process 16 bf16 elements at a time */
51 for (; i + 16 <= n; i += 16) {
52 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
53 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
54 __m512 yv = _mm512_add_ps(av, bv);
55 fp32_cvt_storeu_bf16(&y[i], yv);
56 }
57#endif
58
59 /* Scalar fallback */
60 for (; i < n; ++i) {
61 float af = bf16_to_float(a[i]);
62 float bf = bf16_to_float(b[i]);
63 y[i] = float_to_bf16(af + bf);
64 }
65}

References bf16_to_float(), and float_to_bf16().

◆ add_forward_f32()

void add_forward_f32 ( const float *  a,
const float *  b,
float *  y,
size_t  n 
)

Element-wise add: y = a + b

Test:

test_add.py::TestAddForward::test_add_forward_f32

test_add.py::TestAddForward::test_add_inplace_f32

test_multi_layer_parity.py::TestMultiLayerParity::test_residual_add

Element-wise addition of two vectors.

After changes: make test

Definition at line 280 of file add_kernels_bf16.c.

284{
285 if (!a || !b || !y || n == 0) {
286 return;
287 }
288
289 size_t i = 0;
290
291#if defined(__AVX512F__)
292 for (; i + 16 <= n; i += 16) {
293 __m512 av = _mm512_loadu_ps(&a[i]);
294 __m512 bv = _mm512_loadu_ps(&b[i]);
295 __m512 yv = _mm512_add_ps(av, bv);
296 _mm512_storeu_ps(&y[i], yv);
297 }
298#endif
299
300#if defined(__AVX2__)
301 for (; i + 8 <= n; i += 8) {
302 __m256 av = _mm256_loadu_ps(&a[i]);
303 __m256 bv = _mm256_loadu_ps(&b[i]);
304 __m256 yv = _mm256_add_ps(av, bv);
305 _mm256_storeu_ps(&y[i], yv);
306 }
307#endif
308
309 for (; i < n; ++i) {
310 y[i] = a[i] + b[i];
311 }
312}

◆ add_inplace_bf16()

void add_inplace_bf16 ( uint16_t *  a,
const uint16_t *  b,
size_t  n 
)

Definition at line 119 of file add_kernels_bf16.c.

122{
123 if (!a || !b || n == 0) {
124 return;
125 }
126
127 size_t i = 0;
128
129#if defined(__AVX512F__)
130 for (; i + 16 <= n; i += 16) {
131 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
132 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
133 __m512 yv = _mm512_add_ps(av, bv);
134 fp32_cvt_storeu_bf16(&a[i], yv);
135 }
136#endif
137
138 for (; i < n; ++i) {
139 float af = bf16_to_float(a[i]);
140 float bf = bf16_to_float(b[i]);
141 a[i] = float_to_bf16(af + bf);
142 }
143}

References bf16_to_float(), and float_to_bf16().

◆ add_inplace_f32()

void add_inplace_f32 ( float *  a,
const float *  b,
size_t  n 
)

Definition at line 314 of file add_kernels_bf16.c.

317{
318 if (!a || !b || n == 0) {
319 return;
320 }
321
322 size_t i = 0;
323
324#if defined(__AVX512F__)
325 for (; i + 16 <= n; i += 16) {
326 __m512 av = _mm512_loadu_ps(&a[i]);
327 __m512 bv = _mm512_loadu_ps(&b[i]);
328 __m512 yv = _mm512_add_ps(av, bv);
329 _mm512_storeu_ps(&a[i], yv);
330 }
331#endif
332
333#if defined(__AVX2__)
334 for (; i + 8 <= n; i += 8) {
335 __m256 av = _mm256_loadu_ps(&a[i]);
336 __m256 bv = _mm256_loadu_ps(&b[i]);
337 __m256 yv = _mm256_add_ps(av, bv);
338 _mm256_storeu_ps(&a[i], yv);
339 }
340#endif
341
342 for (; i < n; ++i) {
343 a[i] = a[i] + b[i];
344 }
345}

Referenced by mega_fused_outproj_mlp_prefill().

◆ add_scaled_forward_bf16()

void add_scaled_forward_bf16 ( const uint16_t *  a,
const uint16_t *  b,
uint16_t *  y,
float  alpha,
size_t  n 
)

Definition at line 86 of file add_kernels_bf16.c.

91{
92 if (!a || !b || !y || n == 0) {
93 return;
94 }
95
96 size_t i = 0;
97
98#if defined(__AVX512F__)
99 __m512 alpha_v = _mm512_set1_ps(alpha);
100 for (; i + 16 <= n; i += 16) {
101 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
102 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
103 __m512 yv = _mm512_fmadd_ps(bv, alpha_v, av); /* a + alpha * b */
104 fp32_cvt_storeu_bf16(&y[i], yv);
105 }
106#endif
107
108 for (; i < n; ++i) {
109 float af = bf16_to_float(a[i]);
110 float bf = bf16_to_float(b[i]);
111 y[i] = float_to_bf16(af + alpha * bf);
112 }
113}

References bf16_to_float(), and float_to_bf16().

◆ add_scaled_inplace_bf16()

void add_scaled_inplace_bf16 ( uint16_t *  a,
const uint16_t *  b,
float  alpha,
size_t  n 
)

Definition at line 149 of file add_kernels_bf16.c.

153{
154 if (!a || !b || n == 0) {
155 return;
156 }
157
158 size_t i = 0;
159
160#if defined(__AVX512F__)
161 __m512 alpha_v = _mm512_set1_ps(alpha);
162 for (; i + 16 <= n; i += 16) {
163 __m512 av = bf16_loadu_cvt_fp32(&a[i]);
164 __m512 bv = bf16_loadu_cvt_fp32(&b[i]);
165 __m512 yv = _mm512_fmadd_ps(bv, alpha_v, av);
166 fp32_cvt_storeu_bf16(&a[i], yv);
167 }
168#endif
169
170 for (; i < n; ++i) {
171 float af = bf16_to_float(a[i]);
172 float bf = bf16_to_float(b[i]);
173 a[i] = float_to_bf16(af + alpha * bf);
174 }
175}

References bf16_to_float(), and float_to_bf16().

◆ add_stream_inplace()

void add_stream_inplace ( float *  a,
const float *  b,
size_t  n 
)

Definition at line 713 of file vision_kernels.c.

716{
717 if (!a || !b || n == 0) {
718 return;
719 }
720
721 for (size_t i = 0; i < n; ++i) {
722 a[i] += b[i];
723 }
724}

◆ add_stream_reorder_2d()

void add_stream_reorder_2d ( float *  main_inout,
float *  aux_scratch,
int  grid_h,
int  grid_w,
int  embed_dim,
int  merge_size 
)

Definition at line 726 of file vision_kernels.c.

732{
733 if (!main_inout || !aux_scratch || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
734 return;
735 }
736
737 const int num_tokens = grid_h * grid_w;
738 const size_t total_elems = (size_t) num_tokens * (size_t) embed_dim;
739
740 for (size_t i = 0; i < total_elems; ++i) {
741 main_inout[i] += aux_scratch[i];
742 }
743
744 for (int tok = 0; tok < num_tokens; ++tok) {
745 const int src_tok = tile_order_index_2d(tok, grid_h, grid_w, merge_size);
746 const float *src_main = main_inout + (size_t) src_tok * (size_t) embed_dim;
747 float *dst = aux_scratch + (size_t) tok * (size_t) embed_dim;
748 for (int d = 0; d < embed_dim; ++d) {
749 dst[d] = src_main[d];
750 }
751 }
752
753 memcpy(main_inout, aux_scratch, total_elems * sizeof(float));
754}
static int tile_order_index_2d(int linear_idx, int grid_h, int grid_w, int merge_size)

References tile_order_index_2d().

◆ argmax_f32()

int argmax_f32 ( const float *  scores,
int  n 
)

Find index of maximum value.

Parameters
scoresInput scores [n]
nNumber of scores
Returns
Index of maximum value

Definition at line 500 of file topk_kernels.c.

501{
502 if (!scores || n <= 0) {
503 return -1;
504 }
505
506 int max_idx = 0;
507 float max_val = scores[0];
508
509#ifdef __AVX512F__
510 /* AVX-512 vectorized argmax for large arrays */
511 if (n >= 16) {
512 __m512 vmax = _mm512_set1_ps(-FLT_MAX);
513 __m512i vidx = _mm512_setzero_si512();
514 __m512i vcur_max_idx = _mm512_setzero_si512();
515
516 int i = 0;
517 for (; i + 16 <= n; i += 16) {
518 __m512 v = _mm512_loadu_ps(&scores[i]);
519 __m512i cur_idx = _mm512_add_epi32(
520 _mm512_set1_epi32(i),
521 _mm512_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
522 );
523
524 __mmask16 gt_mask = _mm512_cmp_ps_mask(v, vmax, _CMP_GT_OQ);
525 vmax = _mm512_mask_blend_ps(gt_mask, vmax, v);
526 vcur_max_idx = _mm512_mask_blend_epi32(gt_mask, vcur_max_idx, cur_idx);
527 }
528
529 /* Horizontal reduction */
530 float vals[16];
531 int idxs[16];
532 _mm512_storeu_ps(vals, vmax);
533 _mm512_storeu_si512(idxs, vcur_max_idx);
534
535 max_val = vals[0];
536 max_idx = idxs[0];
537 for (int j = 1; j < 16; j++) {
538 if (vals[j] > max_val) {
539 max_val = vals[j];
540 max_idx = idxs[j];
541 }
542 }
543
544 /* Handle remainder */
545 for (; i < n; i++) {
546 if (scores[i] > max_val) {
547 max_val = scores[i];
548 max_idx = i;
549 }
550 }
551
552 return max_idx;
553 }
554#endif
555
556 /* Scalar fallback */
557 for (int i = 1; i < n; i++) {
558 if (scores[i] > max_val) {
559 max_val = scores[i];
560 max_idx = i;
561 }
562 }
563
564 return max_idx;
565}

Referenced by speculative_verify_greedy_f32().

◆ assistant_layer_scale_forward()

void assistant_layer_scale_forward ( float *  hidden,
const float *  scale,
int  tokens,
int  embed_dim 
)

Definition at line 475 of file gemma4_per_layer_embed.c.

479{
480 if (!hidden || !scale || tokens <= 0 || embed_dim <= 0) {
481 return;
482 }
483
484 const float s = scale[0];
485 const size_t n = (size_t)tokens * (size_t)embed_dim;
486 for (size_t i = 0; i < n; ++i) {
487 hidden[i] *= s;
488 }
489}

◆ attention_backward_causal_head_major()

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

Causal attention backward (non-GQA version)

Test:

test_attention_backward.py::TestAttentionBackward::test_backward

test_attention_backward.py::TestAttentionBackward::test_backward_vs_separate

test_parity.py::test_attention_backward_parity

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

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

Definition at line 9931 of file attention_kernels.c.

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

References attention_backward_causal_head_major_gqa().

◆ attention_backward_causal_head_major_gqa()

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

GQA causal attention backward (score-matrix version)

Test:

test_attention_backward.py::TestAttentionBackwardGQA::test_gqa_backward

test_attention_backward.py::TestAttentionBackwardGQA::test_gqa_vs_separate

test_parity.py::test_attention_backward_parity

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

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

Definition at line 9792 of file attention_kernels.c.

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

References qkv_index(), and score_index().

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

◆ attention_backward_causal_head_major_gqa_bf16()

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

BF16 attention backward with caller-provided scratch buffers

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

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

After changes: make test

Definition at line 9739 of file attention_kernels.c.

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

References attention_backward_causal_head_major_gqa(), and convert_bf16_tensor_to_buf().

◆ attention_flash_decode()

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.

Parameters
outOutput [T_q, H, D_h]
qQuery [T_q, H, D_h]
kKey [T_k, H, D_h]
vValue [T_k, H, D_h]
T_qNumber of query tokens (1 for decode)
T_kNumber of key/value tokens (context length)
HNumber of heads
D_hHead dimension
scale1/sqrt(D_h)

Definition at line 696 of file attention_flash_true.c.

706{
707 if (!out || !q || !k || !v) {
708 return;
709 }
710 if (T_q <= 0 || T_k <= 0 || H <= 0 || D_h <= 0) {
711 return;
712 }
713
714 // Dispatch based on CPU features
715#if defined(__AVX512F__)
716 attention_flash_decode_avx512(out, q, k, v, T_q, T_k, H, D_h, scale);
717#elif defined(__AVX__) && !defined(__AVX512F__)
718 attention_flash_decode_avx(out, q, k, v, T_q, T_k, H, D_h, scale);
719#else
720 attention_flash_decode_scalar(out, q, k, v, T_q, T_k, H, D_h, scale);
721#endif
722}
static void attention_flash_decode_scalar(float *out, const float *q, const float *k, const float *v, int T_q, int T_k, int H, int D_h, float scale)
Scalar flash-style attention (online softmax)

References attention_flash_decode_scalar().

Referenced by attention_forward_chunk_head_major_gqa_flash_gemma4(), attention_forward_decode_head_major_gqa_flash(), attention_forward_decode_head_major_gqa_flash_f16cache(), attention_forward_decode_head_major_gqa_flash_gemma4(), ck_attention_flash_decode_wrapper(), mega_fused_attention_prefill(), and mega_fused_attention_prefill_q8_0().

◆ attention_forward_causal_head_major()

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

Causal attention forward (score-matrix version)

Test:

test_attention.py::TestAttentionForward::test_causal_forward

test_attention.py::TestAttentionForward::test_gqa_broadcast

test_attention.py::TestAttentionForward::test_exact_vs_fast

test_parity.py::test_attention_parity

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

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

Definition at line 1355 of file attention_kernels.c.

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

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

◆ attention_forward_causal_head_major_exact()

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

Causal attention forward (exact version using stdlib expf)

Test:

test_attention.py::TestAttentionForward::test_exact_single

test_attention.py::TestAttentionForward::test_exact_vs_fast

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

After changes: make test

Definition at line 1431 of file attention_kernels.c.

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

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

◆ attention_forward_causal_head_major_gqa()

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

GQA causal attention forward (score-matrix version)

Test:

test_attention.py::TestAttentionForward::test_gqa_forward

test_attention.py::TestAttentionForward::test_gqa_broadcast

test_attention_backward.py::TestAttentionBackwardGQA::test_gqa_backward

test_parity.py::test_attention_gqa_parity

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

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

Definition at line 1509 of file attention_kernels.c.

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

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

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

◆ attention_forward_causal_head_major_gqa_bf16()

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

BF16 GQA causal attention forward

Test:

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_forward

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_gqa

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_flash

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

After changes: make test

Definition at line 1651 of file attention_kernels.c.

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

References attention_forward_causal_head_major_gqa_exact(), and convert_bf16_tensor_to_buf().

◆ attention_forward_causal_head_major_gqa_exact()

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

GQA causal attention forward (exact version using stdlib expf)

Test:

test_attention.py::TestAttentionForward::test_gqa_exact

bf16/test_attention_bf16.py::TestAttentionBF16::test_bf16_gqa

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

After changes: make test

Definition at line 1579 of file attention_kernels.c.

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

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

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

◆ attention_forward_causal_head_major_gqa_flash()

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

Definition at line 4444 of file attention_kernels.c.

4453{
4455 num_heads, num_kv_heads,
4456 num_tokens, head_dim,
4457 aligned_head_dim,
4458 /*kv_stride_tokens=*/num_tokens,
4459 /*causal=*/1,
4460 /*round_full_kv_fp16=*/0,
4461 /*output_token_major=*/0,
4462 1.0f / sqrtf((float)head_dim));
4463}
static void attention_forward_head_major_gqa_flash_impl(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int causal, int round_full_kv_fp16, int output_token_major, float scale)

References attention_forward_head_major_gqa_flash_impl().

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

◆ attention_forward_causal_head_major_gqa_flash_strided()

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

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

Test:

test_flash_attention.py::TestFlashAttention::test_flash_strided

test_kv_cache_attention.py::TestKVCacheAttention::test_flash_attention

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

After changes: make test

Definition at line 4496 of file attention_kernels.c.

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

References attention_forward_head_major_gqa_flash_impl().

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

◆ attention_forward_causal_head_major_gqa_flash_strided_f16kv()

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

Definition at line 5417 of file attention_kernels.c.

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

References attention_forward_causal_head_major_gqa_flash_strided_f16kv_serial(), and attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace().

◆ attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace()

void attention_forward_causal_head_major_gqa_flash_strided_f16kv_workspace ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
float *  rounded_kv,
size_t  rounded_kv_bytes 
)

Definition at line 5377 of file attention_kernels.c.

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

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

Referenced by attention_forward_causal_head_major_gqa_flash_strided_f16kv().

◆ attention_forward_causal_head_major_gqa_flash_strided_gemma4()

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

Definition at line 5098 of file attention_kernels.c.

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

References attention_forward_head_major_gqa_flash_impl().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl(), and attention_forward_causal_head_major_shared_kv_gemma4().

◆ attention_forward_causal_head_major_gqa_flash_strided_gemma4_token_output()

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

Definition at line 5121 of file attention_kernels.c.

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

References attention_forward_head_major_gqa_flash_impl().

Referenced by attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

◆ attention_forward_causal_head_major_gqa_flash_strided_sliding()

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

Flash attention forward with sliding window (prefill)

Test:
test_attention.py::TestAttentionForward::test_sliding_window_prefill

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

After changes: make test

Definition at line 566 of file attention_kernels_sliding.c.

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

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

◆ attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4()

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

Definition at line 763 of file attention_kernels_sliding.c.

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

References attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

Referenced by attention_forward_causal_head_major_shared_kv_sliding_gemma4().

◆ attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_token_output()

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

Definition at line 782 of file attention_kernels_sliding.c.

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

References attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4_impl().

◆ attention_forward_causal_head_major_gqa_flash_strided_token_output()

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

Definition at line 4518 of file attention_kernels.c.

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

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_causal_head_major_gqa_llama_regular_strided_sliding_workspace()

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

Definition at line 6086 of file attention_kernels.c.

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

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

◆ attention_forward_causal_head_major_gqa_muse_eager_bf16_storage()

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

Definition at line 9206 of file attention_kernels.c.

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

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_causal_head_major_gqa_muse_eager_bf16_storage_sliding()

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

Definition at line 9224 of file attention_kernels.c.

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

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract()

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

Definition at line 9429 of file attention_kernels.c.

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

References attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, and CK_GGML_FA_TILE_Q.

◆ attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace()

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

Definition at line 9352 of file attention_kernels.c.

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

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

Referenced by attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace()

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

Definition at line 7686 of file attention_kernels.c.

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

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

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract()

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

Definition at line 8155 of file attention_kernels.c.

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

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

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace()

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

Definition at line 7770 of file attention_kernels.c.

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

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

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace(), and attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_gemma4_workspace()

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

Definition at line 7962 of file attention_kernels.c.

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

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config()

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

Definition at line 7585 of file attention_kernels.c.

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

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

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_auto_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_workspace_bytes()

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

Definition at line 7064 of file attention_kernels.c.

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

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

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_gqa_reuse_config().

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_qtile64_schedule()

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

Definition at line 7743 of file attention_kernels.c.

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

References ck_attention_f16_prefill_qtile64_dispatch(), CK_ATTENTION_STATUS_INVALID_ARGUMENT, and CK_GGML_FA_TILE_Q.

◆ attention_forward_causal_head_major_gqa_prefill_append_f16cache_sliding_gemma4_workspace()

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

Definition at line 7975 of file attention_kernels.c.

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

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_full_bf16cache_pytorch_contract()

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

Definition at line 9469 of file attention_kernels.c.

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

References CK_ATTENTION_STATUS_INVALID_ARGUMENT, CK_ATTENTION_STATUS_UNSUPPORTED_CONTRACT, and CK_ATTN_REDUCTION_BF16_PYTORCH_SDPA.

◆ attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_contract_workspace()

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

Definition at line 8130 of file attention_kernels.c.

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

References ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace(), and CK_ATTN_PREFILL_SCHEDULE_QUERY_TILES.

◆ attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_gemma4_workspace()

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

Definition at line 8003 of file attention_kernels.c.

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

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_sliding_gemma4_workspace()

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

Definition at line 7988 of file attention_kernels.c.

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

References ck_attention_prefill_append_f16cache_gemma4_workspace().

◆ attention_forward_causal_head_major_shared_kv_gemma4()

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

Definition at line 5144 of file attention_kernels.c.

5151{
5153 q, q, q, output, num_heads, num_heads, num_tokens,
5154 head_dim, aligned_head_dim, kv_stride_tokens
5155 );
5156}
void attention_forward_causal_head_major_gqa_flash_strided_gemma4(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens)

References attention_forward_causal_head_major_gqa_flash_strided_gemma4().

◆ attention_forward_causal_head_major_shared_kv_sliding_gemma4()

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

Definition at line 801 of file attention_kernels_sliding.c.

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

References attention_forward_causal_head_major_gqa_flash_strided_sliding_gemma4().

◆ attention_forward_chunk_head_major_gqa_flash_gemma4()

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

Definition at line 6299 of file attention_kernels.c.

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

References attention_flash_decode().

◆ attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_bf16cache_pytorch_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction 
)

Definition at line 9278 of file attention_kernels.c.

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

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

Referenced by attention_forward_causal_head_major_gqa_prefill_append_bf16cache_pytorch_contract_workspace().

◆ attention_forward_decode_head_major_gqa_f16cache_gemma4_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_gemma4_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction 
)

Definition at line 6910 of file attention_kernels.c.

6915{
6917 q_token, k_cache, v_cache, out_token, num_heads, num_kv_heads,
6918 kv_tokens, cache_capacity, head_dim, aligned_head_dim, 0, reduction);
6919}
static ck_attention_status_t ck_attention_forward_decode_f16cache_gemma4(const float *q_token, const uint16_t *k_cache, const uint16_t *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim, int sliding_window, ck_attention_reduction_t reduction)

References ck_attention_forward_decode_f16cache_gemma4().

◆ attention_forward_decode_head_major_gqa_f16cache_regular_noscale()

ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_regular_noscale ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window 
)

Definition at line 6844 of file attention_kernels.c.

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

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

Referenced by ck_attention_forward_decode_f16cache_gemma4().

◆ attention_forward_decode_head_major_gqa_f16cache_sliding_gemma4_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_f16cache_sliding_gemma4_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
ck_attention_reduction_t  reduction 
)

Definition at line 6921 of file attention_kernels.c.

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

References ck_attention_forward_decode_f16cache_gemma4().

◆ attention_forward_decode_head_major_gqa_flash()

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

Flash attention decode (single token attends to KV cache)

Test:

test_flash_attention.py::TestFlashAttention::test_flash_decode

test_kv_cache_attention.py::TestKVCacheAttention::test_flash_decode

test_fused_attention_decode.py::TestFusedAttentionDecode::test_flash_decode

test_attention.py::TestAttentionForward::test_flash_decode

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

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

Definition at line 6212 of file attention_kernels.c.

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

References attention_flash_decode().

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

◆ attention_forward_decode_head_major_gqa_flash_f16cache()

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

Definition at line 9506 of file attention_kernels.c.

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

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

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_contract().

◆ attention_forward_decode_head_major_gqa_flash_f16cache_contract()

ck_attention_status_t attention_forward_decode_head_major_gqa_flash_f16cache_contract ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
ck_attention_reduction_t  reduction 
)

Definition at line 6933 of file attention_kernels.c.

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

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

Referenced by attention_forward_causal_head_major_gqa_prefill_append_f16cache_contract_workspace(), and ck_attention_forward_causal_head_major_gqa_prefill_segmented_f16cache_schedule_workspace().

◆ attention_forward_decode_head_major_gqa_flash_f16cache_split()

void attention_forward_decode_head_major_gqa_flash_f16cache_split ( const float *  q_token,
const uint16_t *  k_cache,
const uint16_t *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  split_chunks 
)

Definition at line 6784 of file attention_kernels.c.

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

References attention_forward_decode_head_major_gqa_flash_f16cache_split_partitioned(), and ck_attention_strict_scale_f32().

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_contract().

◆ attention_forward_decode_head_major_gqa_flash_f16kv()

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

Definition at line 6361 of file attention_kernels.c.

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

References attention_flash_query_causal_exact_f16kv().

◆ attention_forward_decode_head_major_gqa_flash_gemma4()

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

Definition at line 6256 of file attention_kernels.c.

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

References attention_flash_decode().

Referenced by attention_forward_decode_head_major_gqa_flash_sliding_gemma4(), and attention_forward_decode_head_major_shared_kv_gemma4().

◆ attention_forward_decode_head_major_gqa_flash_sliding()

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

Definition at line 817 of file attention_kernels_sliding.c.

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

References attention_forward_decode_head_major_gqa_flash(), and SLIDING_DECODE_IMPL.

◆ attention_forward_decode_head_major_gqa_flash_sliding_gemma4()

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

Definition at line 903 of file attention_kernels_sliding.c.

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

References attention_forward_decode_head_major_gqa_flash_gemma4(), and SLIDING_DECODE_IMPL_GEMMA4.

Referenced by attention_forward_decode_head_major_shared_kv_sliding_gemma4().

◆ attention_forward_decode_head_major_gqa_llama_regular_sliding_workspace()

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

Definition at line 6185 of file attention_kernels.c.

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

References ck_attention_llama_regular_impl().

◆ attention_forward_decode_head_major_gqa_muse_eager_bf16_storage()

void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage ( const float *  q_token,
const float *  k_cache,
const float *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
float *  scores,
size_t  scores_bytes,
uint16_t *  key_rows,
size_t  key_rows_bytes,
uint16_t *  value_columns,
size_t  value_columns_bytes,
uint16_t *  gemm_rows,
size_t  gemm_rows_bytes,
uint16_t *  gemm_scores,
size_t  gemm_scores_bytes 
)

Definition at line 9242 of file attention_kernels.c.

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

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_decode_head_major_gqa_muse_eager_bf16_storage_sliding()

void attention_forward_decode_head_major_gqa_muse_eager_bf16_storage_sliding ( const float *  q_token,
const float *  k_cache,
const float *  v_cache,
float *  out_token,
int  num_heads,
int  num_kv_heads,
int  kv_tokens,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim,
int  sliding_window,
float *  scores,
size_t  scores_bytes,
uint16_t *  key_rows,
size_t  key_rows_bytes,
uint16_t *  value_columns,
size_t  value_columns_bytes,
uint16_t *  gemm_rows,
size_t  gemm_rows_bytes,
uint16_t *  gemm_scores,
size_t  gemm_scores_bytes 
)

Definition at line 9260 of file attention_kernels.c.

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

References ck_attention_muse_eager_bf16_storage_impl().

◆ attention_forward_decode_head_major_gqa_regular()

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

WARNING: This is NOT true flash attention!

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

TRUE flash attention is implemented in attention_flash_true.c

Test:

test_kv_cache_attention.py::TestKVCacheAttention::test_regular_decode

test_attention.py::TestAttentionForward::test_regular_decode

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

After changes: make test

Definition at line 9629 of file attention_kernels.c.

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

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

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

◆ attention_forward_decode_head_major_shared_kv_gemma4()

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

Definition at line 6345 of file attention_kernels.c.

6354{
6356 q_token, k_cache, v_cache, out_token, num_heads, num_heads,
6357 kv_tokens, cache_capacity, head_dim, aligned_head_dim
6358 );
6359}
void attention_forward_decode_head_major_gqa_flash_gemma4(const float *q_token, const float *k_cache, const float *v_cache, float *out_token, int num_heads, int num_kv_heads, int kv_tokens, int cache_capacity, int head_dim, int aligned_head_dim)

References attention_forward_decode_head_major_gqa_flash_gemma4().

◆ attention_forward_decode_head_major_shared_kv_sliding_gemma4()

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

Definition at line 976 of file attention_kernels_sliding.c.

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

References attention_forward_decode_head_major_gqa_flash_sliding_gemma4().

◆ attention_forward_full_head_major_gqa_exact_strided()

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

Definition at line 5446 of file attention_kernels.c.

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

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

◆ attention_forward_full_head_major_gqa_flash()

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

Definition at line 4465 of file attention_kernels.c.

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

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_full_head_major_gqa_flash_strided()

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

Definition at line 4541 of file attention_kernels.c.

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

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_full_head_major_gqa_flash_strided_bf16_storage()

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

Definition at line 4994 of file attention_kernels.c.

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

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

◆ attention_forward_full_head_major_gqa_flash_strided_gemma4()

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

Definition at line 5158 of file attention_kernels.c.

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

References attention_forward_head_major_gqa_flash_impl().

◆ attention_forward_full_head_major_gqa_ggml_strided()

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

Definition at line 5764 of file attention_kernels.c.

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

References attention_forward_full_head_major_gqa_ggml_strided_workspace().

◆ attention_forward_full_head_major_gqa_ggml_strided_workspace()

void attention_forward_full_head_major_gqa_ggml_strided_workspace ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
float *  score_rows,
size_t  score_rows_bytes,
float *  v_columns,
size_t  v_columns_bytes,
float *  probability_row,
size_t  probability_row_bytes 
)

Definition at line 5523 of file attention_kernels.c.

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

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

Referenced by attention_forward_full_head_major_gqa_ggml_strided().

◆ attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage()

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

Definition at line 5047 of file attention_kernels.c.

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

References ck_attention_full_bf16_pytorch_flash().

◆ attention_forward_full_head_major_gqa_pytorch_cpu_flash_bf16_storage_token_output()

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

Definition at line 5072 of file attention_kernels.c.

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

References ck_attention_full_bf16_pytorch_flash().

◆ attention_forward_full_head_major_gqa_sdpa_bf16_storage()

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

Definition at line 5022 of file attention_kernels.c.

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

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

◆ attention_forward_full_head_major_gqa_tiled336_f16kv_fp32_strided()

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

Definition at line 3638 of file attention_kernels.c.

3649{
3651 q, k, v, output, num_heads, num_kv_heads, num_tokens,
3652 head_dim, aligned_head_dim, kv_stride_tokens, CK_GGML_FA_TILE_Q_LARGE);
3653}
#define CK_GGML_FA_TILE_Q_LARGE
static void ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int query_tile_size)

References ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(), and CK_GGML_FA_TILE_Q_LARGE.

◆ attention_forward_full_head_major_gqa_tiled64_f16kv_fp32_strided()

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

Definition at line 3621 of file attention_kernels.c.

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

References ck_attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided(), and CK_GGML_FA_TILE_Q.

◆ attention_forward_full_head_major_gqa_tiled_f16kv_fp32_strided()

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

Definition at line 3601 of file attention_kernels.c.

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

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

◆ attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4()

void attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4 ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  visual_start,
int  visual_tokens 
)

Definition at line 5290 of file attention_kernels.c.

5295{
5297 q, k, v, output, num_heads, num_kv_heads, num_tokens, head_dim,
5298 aligned_head_dim, kv_stride_tokens, visual_start, visual_tokens,
5299 /*output_token_major=*/0);
5300}
static void attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int kv_stride_tokens, int visual_start, int visual_tokens, int output_token_major)

References attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl().

◆ attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_token_output()

void attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_token_output ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
int  visual_start,
int  visual_tokens 
)

Definition at line 5302 of file attention_kernels.c.

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

References attention_forward_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl().

◆ attention_forward_query_key_head_major_f32()

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

Definition at line 210 of file attention_kernels.c.

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

References ck_attention_forward_query_key_head_major_f32_run().

◆ attention_forward_query_key_head_major_f32_decode_heads()

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

Definition at line 260 of file attention_kernels.c.

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

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

◆ attention_forward_query_key_head_major_f32_packed_k()

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

Definition at line 301 of file attention_kernels.c.

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

References ck_attention_forward_query_key_head_major_f32_run().

◆ attention_forward_query_key_head_major_tiled_f16kv_fp32()

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

Definition at line 3655 of file attention_kernels.c.

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

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

◆ attention_forward_sparse_token_major_gqa_bf16cache_pytorch_cpu_flash_contract()

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

Definition at line 8966 of file attention_kernels.c.

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

References CK_ATTENTION_STATUS_OK.

◆ attn_gate_sigmoid_mul_backward()

void attn_gate_sigmoid_mul_backward ( const float *  d_out,
const float *  x,
const float *  gate,
float *  d_x,
float *  d_gate,
int  rows,
int  num_heads,
int  state_dim 
)

Definition at line 253 of file hybrid_attention_kernels.c.

260 {
261 const int dim = num_heads * state_dim;
262 for (int row = 0; row < rows; ++row) {
263 const float *d_out_row = d_out + (size_t) row * (size_t) dim;
264 const float *x_row = x + (size_t) row * (size_t) dim;
265 const float *gate_row = gate + (size_t) row * (size_t) dim;
266 float *d_x_row = d_x + (size_t) row * (size_t) dim;
267 float *d_gate_row = d_gate + (size_t) row * (size_t) dim;
268 for (int col = 0; col < dim; ++col) {
269 const float sig = hybrid_sigmoid(gate_row[col]);
270 d_x_row[col] = d_out_row[col] * sig;
271 d_gate_row[col] = d_out_row[col] * x_row[col] * sig * (1.0f - sig);
272 }
273 }
274}
static float hybrid_sigmoid(float x)

References hybrid_sigmoid().

◆ attn_gate_sigmoid_mul_forward()

void attn_gate_sigmoid_mul_forward ( const float *  x,
const float *  gate,
float *  out,
int  rows,
int  num_heads,
int  state_dim 
)

Definition at line 154 of file hybrid_attention_kernels.c.

159 {
160 if (!x || !gate || !out || rows <= 0 || num_heads <= 0 ||
161 state_dim <= 0 || num_heads > INT_MAX / state_dim) {
162 return;
163 }
164 const int dim = num_heads * state_dim;
165 const size_t elements = (size_t)rows * (size_t)dim;
166 ck_attn_gate_sigmoid_mul_args_t args = {x, gate, out, dim};
167 const size_t minimum_elements_per_thread = 32768u;
168
169 const int partial_x_overlap = out != x &&
170 hybrid_ranges_overlap(out, x, elements);
171 const int gate_overlap = hybrid_ranges_overlap(out, gate, elements);
172 if (partial_x_overlap || gate_overlap ||
173 elements < 2u * minimum_elements_per_thread) {
174 attn_gate_sigmoid_mul_row_range(0, rows, &args);
175 return;
176 }
177
178 ck_threadpool_t *pool = ck_threadpool_global();
179 int active = pool ? ck_threadpool_n_threads(pool) : 1;
180 size_t useful_threads =
181 (elements + minimum_elements_per_thread - 1u) /
182 minimum_elements_per_thread;
183 if ((size_t)active > useful_threads) {
184 active = (int)useful_threads;
185 }
186 if (active > rows) {
187 active = rows;
188 }
189
190 if (active > 1 && ck_threadpool_thread_id(pool) <= 0) {
192 pool, active, 0, rows, 4,
194 } else {
195 attn_gate_sigmoid_mul_row_range(0, rows, &args);
196 }
197}
void ck_threadpool_parallel_for_n(ck_threadpool_t *pool, int active_threads, int begin, int end, int grain_size, ck_range_fn_t fn, void *args)
static int hybrid_ranges_overlap(const float *lhs, const float *rhs, size_t elements)
static void attn_gate_sigmoid_mul_row_range(int begin, int end, void *opaque)

References attn_gate_sigmoid_mul_row_range(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), ck_threadpool_thread_id(), and hybrid_ranges_overlap().

◆ attn_gate_sigmoid_mul_pytorch_bf16_storage()

void attn_gate_sigmoid_mul_pytorch_bf16_storage ( const float *  x,
const float *  gate,
float *  out,
int  rows,
int  num_heads,
int  state_dim 
)

Definition at line 199 of file hybrid_attention_kernels.c.

204 {
205 if (!x || !gate || !out || rows <= 0 || num_heads <= 0 || state_dim <= 0) {
206 return;
207 }
208 const int dim = num_heads * state_dim;
209 for (int row = 0; row < rows; ++row) {
210 const float *x_row = x + (size_t)row * (size_t)dim;
211 const float *gate_row = gate + (size_t)row * (size_t)dim;
212 float *out_row = out + (size_t)row * (size_t)dim;
213 for (int col = 0; col < dim; col += 16) {
214 const int width = dim - col < 16 ? dim - col : 16;
215 float sigmoid[16];
217 gate_row + col, sigmoid, 1, width);
218 for (int lane = 0; lane < width; ++lane) {
219 const float x_bf16 = bf16_to_float(float_to_bf16(x_row[col + lane]));
220 const float sigmoid_bf16 = bf16_to_float(float_to_bf16(sigmoid[lane]));
221 out_row[col + lane] = bf16_to_float(float_to_bf16(
222 x_bf16 * sigmoid_bf16));
223 }
224 }
225 }
226}
void recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output(const float *x, float *out, int rows, int dim)

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

◆ attn_gate_softplus_mul_forward()

void attn_gate_softplus_mul_forward ( const float *  x,
const float *  gate,
float *  out,
int  rows,
int  num_heads,
int  state_dim 
)

Definition at line 228 of file hybrid_attention_kernels.c.

233 {
234 const int dim = num_heads * state_dim;
235 for (int row = 0; row < rows; ++row) {
236 const float *x_row = x + (size_t) row * (size_t) dim;
237 const float *gate_row = gate + (size_t) row * (size_t) num_heads;
238 float *out_row = out + (size_t) row * (size_t) dim;
239 for (int head = 0; head < num_heads; ++head) {
240 const float value = gate_row[head];
241 const float scale = value > 20.0f
242 ? value
243 : log1pf(expf(value));
244 const size_t base = (size_t) head * (size_t) state_dim;
245 for (int col = 0; col < state_dim; ++col) {
246 out_row[base + (size_t) col] =
247 x_row[base + (size_t) col] * scale;
248 }
249 }
250 }
251}

◆ axpy_2d_f32()

void axpy_2d_f32 ( float *  Y,
const float *  X,
float  alpha,
int  num_tokens,
int  dim,
int  y_stride,
int  x_stride 
)

Batched AXPY for 2D tensors: Y[t,:] += alpha * X[t,:].

Parameters
YOutput tensor [num_tokens, dim]
XInput tensor [num_tokens, dim]
alphaScalar multiplier
num_tokensNumber of tokens
dimHidden dimension
y_strideStride between Y rows (for alignment)
x_strideStride between X rows

Definition at line 272 of file axpy_kernels.c.

279{
280 if (!Y || !X || num_tokens <= 0 || dim <= 0) {
281 return;
282 }
283
284 /* Default strides if not specified */
285 if (y_stride <= 0) y_stride = dim;
286 if (x_stride <= 0) x_stride = dim;
287
288 for (int t = 0; t < num_tokens; t++) {
289 axpy_f32(Y + t * y_stride, X + t * x_stride, alpha, dim);
290 }
291}
void axpy_f32(float *y, const float *x, float alpha, int n)
In-place AXPY: y += alpha * x.

References axpy_f32().

◆ axpy_f32()

void axpy_f32 ( float *  y,
const float *  x,
float  alpha,
int  n 
)

In-place AXPY: y += alpha * x.

Test:

test_axpy.py::TestAXPY::test_axpy_f32

test_axpy.py::TestAXPY::test_axpy_vs_naive

In-place scaled vector addition: y += alpha * x BLAS-like axpy operation.

After changes: make test

Definition at line 105 of file axpy_kernels.c.

109{
110 if (!y || !x || n <= 0) {
111 return;
112 }
113
114 int i = 0;
115
116#ifdef __AVX512F__
117 __m512 valpha = _mm512_set1_ps(alpha);
118 for (; i + 16 <= n; i += 16) {
119 __m512 vy = _mm512_loadu_ps(&y[i]);
120 __m512 vx = _mm512_loadu_ps(&x[i]);
121 vy = _mm512_fmadd_ps(vx, valpha, vy); /* y = y + alpha * x */
122 _mm512_storeu_ps(&y[i], vy);
123 }
124#endif
125
126#ifdef __AVX2__
127 __m256 valpha256 = _mm256_set1_ps(alpha);
128 for (; i + 8 <= n; i += 8) {
129 __m256 vy = _mm256_loadu_ps(&y[i]);
130 __m256 vx = _mm256_loadu_ps(&x[i]);
131 vy = _mm256_fmadd_ps(vx, valpha256, vy);
132 _mm256_storeu_ps(&y[i], vy);
133 }
134#endif
135
136 /* Scalar remainder */
137 for (; i < n; i++) {
138 y[i] += alpha * x[i];
139 }
140}

Referenced by axpy_2d_f32(), axpy_zero_f32(), ck_moe_q4k_mixed_route_parallel(), ck_moe_q4k_q5k_bucket_work(), ck_moe_q4k_q5k_route_parallel(), moe_accumulate_expert_f32(), moe_swiglu_expert_forward_q4k_q4k_workspace(), moe_swiglu_expert_forward_q4k_q5k_workspace(), moe_swiglu_expert_forward_q4k_q6k_workspace(), and weighted_sum_f32().

◆ axpy_zero_f32()

void axpy_zero_f32 ( float *  y,
const float *  x,
float  alpha,
int  n 
)

Zero output then accumulate: y = 0; y += alpha * x.

Parameters
yOutput vector [n], zeroed then accumulated
xInput vector [n]
alphaScalar multiplier
nVector length

Definition at line 239 of file axpy_kernels.c.

243{
244 if (!y || n <= 0) {
245 return;
246 }
247
248 memset(y, 0, n * sizeof(float));
249
250 if (x) {
251 axpy_f32(y, x, alpha, n);
252 }
253}

References axpy_f32().

◆ backward_causal_softmax_head_major()

void backward_causal_softmax_head_major ( float *  d_scores,
const float *  weights,
int  num_heads,
int  num_tokens,
int  aligned_context_window 
)

Definition at line 382 of file softmax_kernels.c.

387{
388 int H = num_heads;
389 int T = num_tokens;
390
391 for (int h = 0; h < H; ++h) {
392 for (int i = 0; i < T; ++i) {
393 int base = h * aligned_context_window * aligned_context_window
394 + i * aligned_context_window;
395 float *drow = &d_scores[base];
396 const float *wrow = &weights[base];
397 int len = i + 1;
398
399#if defined(__AVX512F__)
400 // Compute dot product (vectorized)
401 __m512 dot_vec = _mm512_setzero_ps();
402 int j = 0;
403 for (; j + 16 <= len; j += 16) {
404 __m512 w = _mm512_loadu_ps(&wrow[j]);
405 __m512 dw = _mm512_loadu_ps(&drow[j]);
406 dot_vec = _mm512_fmadd_ps(w, dw, dot_vec);
407 }
408 float dot_product = _mm512_reduce_add_ps(dot_vec);
409 for (; j < len; ++j) {
410 dot_product += wrow[j] * drow[j];
411 }
412
413 // Compute gradient: d_scores = w * (dw - dot_product)
414 __m512 dot_broadcast = _mm512_set1_ps(dot_product);
415 j = 0;
416 for (; j + 16 <= len; j += 16) {
417 __m512 w = _mm512_loadu_ps(&wrow[j]);
418 __m512 dw = _mm512_loadu_ps(&drow[j]);
419 __m512 diff = _mm512_sub_ps(dw, dot_broadcast);
420 __m512 result = _mm512_mul_ps(w, diff);
421 _mm512_storeu_ps(&drow[j], result);
422 }
423 for (; j < len; ++j) {
424 drow[j] = wrow[j] * (drow[j] - dot_product);
425 }
426
427 // Zero out future tokens
428 __m512 zero = _mm512_setzero_ps();
429 for (; j + 16 <= T; j += 16) {
430 _mm512_storeu_ps(&drow[j], zero);
431 }
432 for (; j < T; ++j) {
433 drow[j] = 0.0f;
434 }
435
436#elif defined(__AVX__)
437 // Compute dot product (vectorized)
438 __m256 dot_vec = _mm256_setzero_ps();
439 int j = 0;
440 for (; j + 8 <= len; j += 8) {
441 __m256 w = _mm256_loadu_ps(&wrow[j]);
442 __m256 dw = _mm256_loadu_ps(&drow[j]);
443 // No FMA in AVX1: use mul + add
444 __m256 prod = _mm256_mul_ps(w, dw);
445 dot_vec = _mm256_add_ps(dot_vec, prod);
446 }
447 float dot_product = hsum256_ps_softmax(dot_vec);
448 for (; j < len; ++j) {
449 dot_product += wrow[j] * drow[j];
450 }
451
452 // Compute gradient: d_scores = w * (dw - dot_product)
453 __m256 dot_broadcast = _mm256_set1_ps(dot_product);
454 j = 0;
455 for (; j + 8 <= len; j += 8) {
456 __m256 w = _mm256_loadu_ps(&wrow[j]);
457 __m256 dw = _mm256_loadu_ps(&drow[j]);
458 __m256 diff = _mm256_sub_ps(dw, dot_broadcast);
459 __m256 result = _mm256_mul_ps(w, diff);
460 _mm256_storeu_ps(&drow[j], result);
461 }
462 for (; j < len; ++j) {
463 drow[j] = wrow[j] * (drow[j] - dot_product);
464 }
465
466 // Zero out future tokens
467 __m256 zero = _mm256_setzero_ps();
468 for (; j + 8 <= T; j += 8) {
469 _mm256_storeu_ps(&drow[j], zero);
470 }
471 for (; j < T; ++j) {
472 drow[j] = 0.0f;
473 }
474
475#else
476 // Scalar fallback
477 float dot_product = 0.0f;
478 for (int j = 0; j < len; ++j) {
479 dot_product += wrow[j] * drow[j];
480 }
481
482 for (int j = 0; j < len; ++j) {
483 drow[j] = wrow[j] * (drow[j] - dot_product);
484 }
485
486 for (int j = len; j < T; ++j) {
487 drow[j] = 0.0f;
488 }
489#endif
490 }
491 }
492}

Referenced by backward_causal_softmax_head_major_bf16().

◆ backward_causal_softmax_head_major_bf16()

void backward_causal_softmax_head_major_bf16 ( uint16_t *  d_scores,
const uint16_t *  weights,
int  num_heads,
int  num_tokens,
int  aligned_context_window,
float *  scratch_d_scores,
float *  scratch_weights 
)

Definition at line 53 of file softmax_kernels_bf16.c.

60{
61 if (!d_scores || !weights || num_heads <= 0 || num_tokens <= 0 || aligned_context_window <= 0) return;
62 if (!scratch_d_scores || !scratch_weights) return;
63
64 const size_t total = (size_t)num_heads *
65 (size_t)aligned_context_window *
66 (size_t)aligned_context_window;
67
68 bf16_tensor_to_float(d_scores, scratch_d_scores, total);
69 bf16_tensor_to_float(weights, scratch_weights, total);
70 backward_causal_softmax_head_major(scratch_d_scores, scratch_weights, num_heads, num_tokens, aligned_context_window);
71 float_tensor_to_bf16(scratch_d_scores, d_scores, total);
72}
static void float_tensor_to_bf16(const float *src, uint16_t *dst, size_t count)
Definition bf16_utils.h:271
static void bf16_tensor_to_float(const uint16_t *src, float *dst, size_t count)
Definition bf16_utils.h:250
void backward_causal_softmax_head_major(float *d_scores, const float *weights, int num_heads, int num_tokens, int aligned_context_window)

References backward_causal_softmax_head_major(), bf16_tensor_to_float(), and float_tensor_to_bf16().

◆ causal_softmax_head_major()

void causal_softmax_head_major ( float *  scores,
int  num_heads,
int  num_tokens,
int  aligned_context_window 
)

Causal softmax (in-place, row-wise)

Test:

test_softmax.py::TestSoftmaxForward::test_causal_softmax

test_softmax.py::TestSoftmaxForward::test_causal_vs_softmax

test_attention.py::TestAttentionForward::test_softmax_correctness

Applies causal mask (j > i => 0) and softmax to scores matrix. In-place on [num_heads, T, T] scores matrix.

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

Definition at line 144 of file softmax_kernels.c.

148{
149 for (int h = 0; h < num_heads; ++h) {
150 for (int i = 0; i < num_tokens; ++i) {
151 int base = h * aligned_context_window * aligned_context_window
152 + i * aligned_context_window;
153 float *row = &scores[base];
154 int len = i + 1; // Number of valid elements (0..i inclusive)
155
156#if defined(__AVX512F__)
157 // Find max (vectorized)
158 __m512 max_vec = _mm512_set1_ps(-INFINITY);
159 int j = 0;
160 for (; j + 16 <= len; j += 16) {
161 __m512 v = _mm512_loadu_ps(&row[j]);
162 max_vec = _mm512_max_ps(max_vec, v);
163 }
164 float max_val = _mm512_reduce_max_ps(max_vec);
165 for (; j < len; ++j) {
166 if (row[j] > max_val) max_val = row[j];
167 }
168
169 // Compute exp and sum (vectorized)
170 __m512 max_broadcast = _mm512_set1_ps(max_val);
171 __m512 sum_vec = _mm512_setzero_ps();
172 j = 0;
173 for (; j + 16 <= len; j += 16) {
174 __m512 v = _mm512_loadu_ps(&row[j]);
175 __m512 e = exp512_approx(_mm512_sub_ps(v, max_broadcast));
176 _mm512_storeu_ps(&row[j], e);
177 sum_vec = _mm512_add_ps(sum_vec, e);
178 }
179 float sum = _mm512_reduce_add_ps(sum_vec);
180 for (; j < len; ++j) {
181 float e = expf(row[j] - max_val);
182 row[j] = e;
183 sum += e;
184 }
185
186 // Normalize (vectorized)
187 float inv_sum = 1.0f / sum;
188 __m512 inv_sum_vec = _mm512_set1_ps(inv_sum);
189 j = 0;
190 for (; j + 16 <= len; j += 16) {
191 __m512 v = _mm512_loadu_ps(&row[j]);
192 _mm512_storeu_ps(&row[j], _mm512_mul_ps(v, inv_sum_vec));
193 }
194 for (; j < len; ++j) {
195 row[j] *= inv_sum;
196 }
197
198 // Zero out future tokens (vectorized)
199 __m512 zero = _mm512_setzero_ps();
200 for (; j + 16 <= num_tokens; j += 16) {
201 _mm512_storeu_ps(&row[j], zero);
202 }
203 for (; j < num_tokens; ++j) {
204 row[j] = 0.0f;
205 }
206
207#elif defined(__AVX2__)
208 // AVX2: Find max (vectorized)
209 __m256 max_vec = _mm256_set1_ps(-INFINITY);
210 int j = 0;
211 for (; j + 8 <= len; j += 8) {
212 __m256 v = _mm256_loadu_ps(&row[j]);
213 max_vec = _mm256_max_ps(max_vec, v);
214 }
215 float max_val = hmax256_ps(max_vec);
216 for (; j < len; ++j) {
217 if (row[j] > max_val) max_val = row[j];
218 }
219
220 // Compute exp and sum (vectorized with fast exp)
221 __m256 max_broadcast = _mm256_set1_ps(max_val);
222 __m256 sum_vec = _mm256_setzero_ps();
223 j = 0;
224 for (; j + 8 <= len; j += 8) {
225 __m256 v = _mm256_loadu_ps(&row[j]);
226 __m256 e = exp256_approx(_mm256_sub_ps(v, max_broadcast));
227 _mm256_storeu_ps(&row[j], e);
228 sum_vec = _mm256_add_ps(sum_vec, e);
229 }
230 float sum = hsum256_ps_softmax(sum_vec);
231 for (; j < len; ++j) {
232 float e = expf(row[j] - max_val);
233 row[j] = e;
234 sum += e;
235 }
236
237 // Normalize (vectorized)
238 float inv_sum = 1.0f / sum;
239 __m256 inv_sum_vec = _mm256_set1_ps(inv_sum);
240 j = 0;
241 for (; j + 8 <= len; j += 8) {
242 __m256 v = _mm256_loadu_ps(&row[j]);
243 _mm256_storeu_ps(&row[j], _mm256_mul_ps(v, inv_sum_vec));
244 }
245 for (; j < len; ++j) {
246 row[j] *= inv_sum;
247 }
248
249 // Zero out future tokens (vectorized)
250 __m256 zero = _mm256_setzero_ps();
251 for (; j + 8 <= num_tokens; j += 8) {
252 _mm256_storeu_ps(&row[j], zero);
253 }
254 for (; j < num_tokens; ++j) {
255 row[j] = 0.0f;
256 }
257
258#elif defined(__AVX__)
259 // AVX1: vectorized max/sum/normalize, scalar exp
260 __m256 max_vec = _mm256_set1_ps(-INFINITY);
261 int j = 0;
262 for (; j + 8 <= len; j += 8) {
263 __m256 v = _mm256_loadu_ps(&row[j]);
264 max_vec = _mm256_max_ps(max_vec, v);
265 }
266 float max_val = hmax256_ps(max_vec);
267 for (; j < len; ++j) {
268 if (row[j] > max_val) max_val = row[j];
269 }
270
271 // Compute exp and sum (scalar exp, no fast approx for AVX1)
272 float sum = 0.0f;
273 for (j = 0; j < len; ++j) {
274 float e = expf(row[j] - max_val);
275 row[j] = e;
276 sum += e;
277 }
278
279 // Normalize (vectorized)
280 float inv_sum = 1.0f / sum;
281 __m256 inv_sum_vec = _mm256_set1_ps(inv_sum);
282 j = 0;
283 for (; j + 8 <= len; j += 8) {
284 __m256 v = _mm256_loadu_ps(&row[j]);
285 _mm256_storeu_ps(&row[j], _mm256_mul_ps(v, inv_sum_vec));
286 }
287 for (; j < len; ++j) {
288 row[j] *= inv_sum;
289 }
290
291 // Zero out future tokens (vectorized)
292 __m256 zero = _mm256_setzero_ps();
293 for (; j + 8 <= num_tokens; j += 8) {
294 _mm256_storeu_ps(&row[j], zero);
295 }
296 for (; j < num_tokens; ++j) {
297 row[j] = 0.0f;
298 }
299
300#else
301 // Scalar fallback
302 float max_val = row[0];
303 for (int j = 1; j < len; ++j) {
304 if (row[j] > max_val) max_val = row[j];
305 }
306
307 float sum = 0.0f;
308 for (int j = 0; j < len; ++j) {
309 float e = expf(row[j] - max_val);
310 row[j] = e;
311 sum += e;
312 }
313
314 float inv_sum = 1.0f / sum;
315 for (int j = 0; j < len; ++j) {
316 row[j] *= inv_sum;
317 }
318
319 for (int j = len; j < num_tokens; ++j) {
320 row[j] = 0.0f;
321 }
322#endif
323 }
324 }
325}

Referenced by attention_forward_causal_head_major(), attention_forward_causal_head_major_gqa(), and causal_softmax_head_major_bf16().

◆ causal_softmax_head_major_bf16()

void causal_softmax_head_major_bf16 ( uint16_t *  scores,
int  num_heads,
int  num_tokens,
int  aligned_context_window,
float *  scratch 
)

Definition at line 31 of file softmax_kernels_bf16.c.

36{
37 if (!scores || num_heads <= 0 || num_tokens <= 0 || aligned_context_window <= 0) return;
38 if (!scratch) return;
39
40 const size_t total = (size_t)num_heads *
41 (size_t)aligned_context_window *
42 (size_t)aligned_context_window;
43
44 bf16_tensor_to_float(scores, scratch, total);
45 causal_softmax_head_major(scratch, num_heads, num_tokens, aligned_context_window);
46 float_tensor_to_bf16(scratch, scores, total);
47}

References bf16_tensor_to_float(), causal_softmax_head_major(), and float_tensor_to_bf16().

◆ causal_softmax_head_major_exact()

void causal_softmax_head_major_exact ( float *  scores,
int  num_heads,
int  num_tokens,
int  aligned_context_window 
)

Causal softmax (exact version using stdlib expf)

Test:

test_softmax.py::TestSoftmaxForward::test_causal_softmax_exact

test_softmax.py::TestSoftmaxForward::test_exact_vs_fast

Exact causal softmax using standard library expf for numerical accuracy reference.

After changes: make test

Definition at line 339 of file softmax_kernels.c.

343{
344 for (int h = 0; h < num_heads; ++h) {
345 for (int i = 0; i < num_tokens; ++i) {
346 int base = h * aligned_context_window * aligned_context_window
347 + i * aligned_context_window;
348 float *row = &scores[base];
349 int len = i + 1;
350
351 // Find max
352 float max_val = -INFINITY;
353 for (int j = 0; j < len; ++j) {
354 if (row[j] > max_val) max_val = row[j];
355 }
356
357 // Compute exp and sum using standard library expf
358 float sum = 0.0f;
359 for (int j = 0; j < len; ++j) {
360 float e = expf(row[j] - max_val);
361 row[j] = e;
362 sum += e;
363 }
364
365 // Normalize
366 float inv_sum = 1.0f / sum;
367 for (int j = 0; j < len; ++j) {
368 row[j] *= inv_sum;
369 }
370
371 // Zero out future tokens
372 for (int j = len; j < num_tokens; ++j) {
373 row[j] = 0.0f;
374 }
375 }
376 }
377}

Referenced by attention_forward_causal_head_major_exact(), and attention_forward_causal_head_major_gqa_exact().

◆ ck_attention_bf16_pytorch_gqa_available()

int ck_attention_bf16_pytorch_gqa_available ( void  )

Definition at line 9025 of file attention_kernels.c.

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

Referenced by ck_attention_sparse_bf16_pytorch_gqa_available().

◆ ck_attention_flash_decode_wrapper()

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

Wrapper to call TRUE flash attention from orchestration layer.

Parameters
q_tokenQuery token [H, D_h]
k_cacheCached keys [T_k, H, D_h]
v_cacheCached values [T_k, H, D_h]
out_tokenOutput [H, D_h]
num_headsNumber of heads
num_kv_headsNumber of KV heads (for GQA)
kv_tokensNumber of tokens in KV cache
cache_capacityCache capacity
head_dimHead dimension
aligned_head_dimAligned head dimension

Definition at line 72 of file ckernel_orchestration.c.

83{
84 if (!q_token || !k_cache || !v_cache || !out_token) {
85 return;
86 }
87 if (num_heads <= 0 || num_kv_heads <= 0 || kv_tokens <= 0 || cache_capacity <= 0) {
88 return;
89 }
90 if (kv_tokens > cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
91 return;
92 }
93
94 static int use_strict = -1;
95 if (use_strict < 0) {
96 const char *env = getenv("CK_FLASH_ATTN_STRICT");
97 use_strict = (env && env[0] && env[0] != '0') ? 1 : 0;
98 }
99
100 if (use_strict) {
102 k_cache,
103 v_cache,
104 out_token,
105 num_heads,
106 num_kv_heads,
107 kv_tokens,
108 cache_capacity,
109 head_dim,
110 aligned_head_dim);
111 return;
112 }
113
114 // Scale factor: 1/sqrt(head_dim)
115 const float scale = 1.0f / sqrtf((float)head_dim);
116 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
117
118#pragma omp parallel for schedule(static) if(num_heads > 1)
119 for (int h = 0; h < num_heads; ++h) {
120 const int kv_head = (int)((long long)h * (long long)num_kv_heads / (long long)num_heads);
121 const float *q_head = q_token + (size_t)h * (size_t)aligned_head_dim;
122 const float *k_head = k_cache + (size_t)kv_head * head_stride;
123 const float *v_head = v_cache + (size_t)kv_head * head_stride;
124 float *out_head = out_token + (size_t)h * (size_t)aligned_head_dim;
125
126 // Use aligned_head_dim as D_h so per-token stride matches the cache layout.
127 attention_flash_decode(out_head,
128 q_head,
129 k_head,
130 v_head,
131 1,
132 kv_tokens,
133 1,
134 aligned_head_dim,
135 scale);
136 }
137}
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!

References attention_flash_decode(), and attention_forward_decode_head_major_gqa_regular().

Referenced by ck_layer_forward_rmsnorm_swiglu_decode(), ck_layer_forward_rmsnorm_swiglu_decode_fused(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), and ck_layer_forward_rmsnorm_swiglu_decode_quant().

◆ ck_attention_pytorch_sdpa_scale_f32()

float ck_attention_pytorch_sdpa_scale_f32 ( int  head_dim)

Definition at line 4592 of file attention_kernels.c.

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

Referenced by ck_attention_full_bf16_sdpa_amx_range(), and ck_attention_full_bf16_sdpa_tiled_range().

◆ ck_attention_sparse_bf16_pytorch_gqa_available()

int ck_attention_sparse_bf16_pytorch_gqa_available ( void  )

Definition at line 9016 of file attention_kernels.c.

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

References ck_attention_bf16_pytorch_gqa_available().

◆ ck_flash_attn_choose_tile_k()

int ck_flash_attn_choose_tile_k ( int  D_h)

Definition at line 108 of file attention_flash_true.c.

108 {
109 return ck_flash_attn_tile_k(D_h);
110}
static int ck_flash_attn_tile_k(int D_h)

References ck_flash_attn_tile_k().

◆ ck_flash_attn_fast_exp_kind()

int ck_flash_attn_fast_exp_kind ( void  )

Definition at line 112 of file attention_flash_true.c.

112 {
113#if CK_FLASH_ATTN_FAST_EXP
114#if defined(__AVX512F__)
115 return 512;
116#elif defined(__AVX__)
117 return 256;
118#else
119 return 0;
120#endif
121#else
122 return 0;
123#endif
124}

◆ ck_gemm_bf16_amx_available()

int ck_gemm_bf16_amx_available ( void  )

Definition at line 1203 of file gemm_kernels_bf16.c.

1204{
1205#if HAVE_AMX_BF16
1206 return ck_amx_request_xtile_data();
1207#else
1208 return 0;
1209#endif
1210}

Referenced by ck_attention_full_bf16_sdpa_amx_range(), gemm_nt_bf16_prefill_shape_safe_bf16_storage(), and gemm_nt_bf16_prefill_shape_safe_bf16_storage_workspace().

◆ ck_gemm_bf16_fp32out_amx_raw()

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 
)

Definition at line 1212 of file gemm_kernels_bf16.c.

1217{
1218#if HAVE_AMX_BF16
1219 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0 ||
1220 (M % 16) != 0 || (N % 16) != 0 || (K % 2) != 0 ||
1221 !ck_amx_request_xtile_data()) {
1222 return 0;
1223 }
1224 /* Match oneDNN BRGEMM: largest even divisor of K no greater than 32. */
1225 int k_block = K < 32 ? K : 32;
1226 while (k_block > 2 && K % k_block != 0) k_block -= 2;
1227 ck_amx_config_bf16_16x16_kblock(k_block);
1228 uint16_t b_tile[16 * 32];
1229 for (int i = 0; i < M; i += 16) {
1230 for (int j = 0; j < N; j += 16) {
1231 if (accumulate) {
1232 _tile_loadd(2, C + (size_t)i * (size_t)N + (size_t)j,
1233 N * (int)sizeof(float));
1234 } else {
1235 _tile_zero(2);
1236 }
1237 for (int k = 0; k < K; k += k_block) {
1238 memset(b_tile, 0, sizeof(b_tile));
1239 for (int kp = 0; kp < k_block / 2; ++kp) {
1240 const int k0 = k + kp * 2;
1241 for (int nn = 0; nn < 16; ++nn) {
1242 b_tile[(size_t)kp * 32u + (size_t)nn * 2u] =
1243 B[(size_t)(j + nn) * (size_t)K + (size_t)k0];
1244 b_tile[(size_t)kp * 32u + (size_t)nn * 2u + 1u] =
1245 B[(size_t)(j + nn) * (size_t)K + (size_t)k0 + 1u];
1246 }
1247 }
1248 _tile_loadd(0, A + (size_t)i * (size_t)K + (size_t)k,
1249 K * (int)sizeof(uint16_t));
1250 _tile_loadd(1, b_tile, 32 * (int)sizeof(uint16_t));
1251 _tile_dpbf16ps(2, 0, 1);
1252 }
1253 _tile_stored(2, C + (size_t)i * (size_t)N + (size_t)j,
1254 N * (int)sizeof(float));
1255 }
1256 }
1257 _tile_release();
1258 return 1;
1259#else
1260 (void)A; (void)B; (void)C; (void)M; (void)N; (void)K; (void)accumulate;
1261 return 0;
1262#endif
1263}
#define C(color)
Definition show_config.c:39

References C.

Referenced by ck_attention_full_bf16_sdpa_amx_range().

◆ ck_gemm_nt_f16_ggml_oracle()

int ck_gemm_nt_f16_ggml_oracle ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 262 of file gemm_kernels_f16.c.

269{
270 return gemm_nt_f16_ggml_strict(A, B, bias, C, M, N, K);
271}
static int gemm_nt_f16_ggml_strict(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, and gemm_nt_f16_ggml_strict().

◆ ck_gemm_nt_f16_simd_lanes()

int ck_gemm_nt_f16_simd_lanes ( void  )

Definition at line 583 of file gemm_kernels_f16.c.

584{
585#if defined(__AVX512F__) && defined(__F16C__)
586 return 16;
587#elif defined(__F16C__) && defined(__AVX__)
588 return 8;
589#else
590 return 1;
591#endif
592}

◆ ck_gemm_nt_head_major_q5_0()

void ck_gemm_nt_head_major_q5_0 ( const float *  attn_out,
const void *  wo,
const float *  bias,
float *  output,
int  tokens,
int  embed_dim,
int  num_heads,
int  head_dim 
)

Output projection from head-major attention (auto-dispatch)

This replaces flatten_head_major() + ck_gemm_nt_quant() with a single strided-access kernel that reads head-major attention output directly.

Definition at line 290 of file gemm_head_major_output.c.

298{
299#if defined(__AVX__)
300 gemv_nt_q5_0_head_major_output_avx(output, attn_out, wo, bias,
301 tokens, embed_dim, num_heads, head_dim);
302#else
303 gemv_nt_q5_0_head_major_output(output, attn_out, wo, bias,
304 tokens, embed_dim, num_heads, head_dim);
305#endif
306}
void gemv_nt_q5_0_head_major_output(float *output, const float *attn_out, const void *wo, const float *bias, int tokens, int embed_dim, int num_heads, int head_dim)
Output projection reading head-major attention output (Q5_0 weights)

References gemv_nt_q5_0_head_major_output().

Referenced by mega_fused_attention_prefill().

◆ ck_gemm_nt_head_major_q8_0()

void ck_gemm_nt_head_major_q8_0 ( const float *  attn_out,
const void *  wo,
const float *  bias,
float *  output,
int  tokens,
int  embed_dim,
int  num_heads,
int  head_dim 
)

Output projection from head-major attention (Q8_0 weights)

Definition at line 315 of file gemm_head_major_output.c.

323{
324 if (!output || !attn_out || !wo) return;
325 if (tokens <= 0 || embed_dim <= 0 || num_heads <= 0 || head_dim <= 0) return;
326
327 const int blocks_per_head = head_dim / QK8_0;
328 const int blocks_per_row = embed_dim / QK8_0;
329 const block_q8_0 *weights = (const block_q8_0 *)wo;
330
331 const size_t token_stride = head_dim;
332 const size_t head_stride = (size_t)tokens * token_stride;
333
334 /* Initialize output */
335 if (bias) {
336 for (int t = 0; t < tokens; t++) {
337 float *out_row = output + (size_t)t * embed_dim;
338 for (int n = 0; n < embed_dim; n++) {
339 out_row[n] = bias[n];
340 }
341 }
342 } else {
343 memset(output, 0, (size_t)tokens * embed_dim * sizeof(float));
344 }
345
346 /* Accumulate from each head */
347 for (int h = 0; h < num_heads; h++) {
348 const float *head_data = attn_out + (size_t)h * head_stride;
349 const int head_offset = h * blocks_per_head;
350
351 for (int n_block = 0; n_block < blocks_per_head; n_block++) {
352 for (int n = 0; n < embed_dim; n++) {
353 const block_q8_0 *w_row = weights + (size_t)n * blocks_per_row + head_offset + n_block;
354 const float d = CK_FP16_TO_FP32(w_row->d);
355
356 for (int t = 0; t < tokens; t++) {
357 const float *token_vec = head_data + (size_t)t * token_stride + (size_t)n_block * QK8_0;
358 float sum = 0.0f;
359
360 for (int j = 0; j < QK8_0; j++) {
361 sum += d * (float)w_row->qs[j] * token_vec[j];
362 }
363
364 output[(size_t)t * embed_dim + n] += sum;
365 }
366 }
367 }
368 }
369}
#define QK8_0
int8_t qs[32]

References CK_FP16_TO_FP32, block_q8_0::d, QK8_0, and block_q8_0::qs.

Referenced by mega_fused_attention_prefill().

◆ ck_get_num_threads()

int ck_get_num_threads ( void  )

Definition at line 310 of file ckernel_strict.c.

311{
312 // Auto-initialize if not set
314 ck_set_num_threads(0); // Auto-detect
315 }
316 return g_num_threads;
317}
void ck_set_num_threads(int num_threads)
static int g_num_threads
static int g_threads_initialized

References ck_set_num_threads(), g_num_threads, and g_threads_initialized.

Referenced by attention_forward_decode_head_major_gqa_flash_f16cache_contract(), and gemm_blocked_serial().

◆ ck_get_physical_cores()

int ck_get_physical_cores ( void  )

Definition at line 170 of file ckernel_strict.c.

171{
172 int physical_cores = 0;
173 int logical_cores = (int)sysconf(_SC_NPROCESSORS_ONLN);
174 if (logical_cores <= 0) {
175 logical_cores = 1;
176 }
177
178 int cpu_cores_hint = 0;
179 int siblings_hint = 0;
180
181 // Read from /proc/cpuinfo (Linux) and count unique (physical id, core id) pairs.
182 FILE *f = fopen("/proc/cpuinfo", "r");
183 if (f) {
184 char line[256];
185 int physical_id = -1;
186 int core_id = -1;
187
188 struct {
189 int physical_id;
190 int core_id;
191 } seen[8192];
192 int seen_count = 0;
193
194 const int seen_cap = (int)(sizeof(seen) / sizeof(seen[0]));
195
196 // Helper: add (pid,cid) to set if not present.
197 #define CK_ADD_PAIR(pid, cid) \
198 do { \
199 if ((pid) >= 0 && (cid) >= 0) { \
200 int exists = 0; \
201 for (int ii = 0; ii < seen_count; ++ii) { \
202 if (seen[ii].physical_id == (pid) && \
203 seen[ii].core_id == (cid)) { \
204 exists = 1; \
205 break; \
206 } \
207 } \
208 if (!exists && seen_count < seen_cap) { \
209 seen[seen_count].physical_id = (pid); \
210 seen[seen_count].core_id = (cid); \
211 ++seen_count; \
212 } \
213 } \
214 } while (0)
215
216 while (fgets(line, sizeof(line), f)) {
217 int val;
218
219 // Blank line separates processor blocks.
220 if (line[0] == '\n' || line[0] == '\0') {
221 CK_ADD_PAIR(physical_id, core_id);
222 physical_id = -1;
223 core_id = -1;
224 continue;
225 }
226
227 if (sscanf(line, "physical id : %d", &val) == 1) {
228 physical_id = val;
229 continue;
230 }
231 if (sscanf(line, "core id : %d", &val) == 1) {
232 core_id = val;
233 continue;
234 }
235 if (sscanf(line, "cpu cores : %d", &val) == 1) {
236 if (val > cpu_cores_hint) cpu_cores_hint = val;
237 continue;
238 }
239 if (sscanf(line, "siblings : %d", &val) == 1) {
240 if (val > siblings_hint) siblings_hint = val;
241 continue;
242 }
243 }
244 fclose(f);
245
246 // Handle file without trailing blank line.
247 CK_ADD_PAIR(physical_id, core_id);
248
249 #undef CK_ADD_PAIR
250
251 physical_cores = seen_count;
252 }
253
254 // Fallback: infer threads-per-core from siblings/cpu cores when pair data
255 // is missing (common in containers/VMs).
256 if (physical_cores <= 1 && logical_cores > 1) {
257 int threads_per_core = 0;
258 if (siblings_hint > 0 && cpu_cores_hint > 0 && siblings_hint >= cpu_cores_hint) {
259 threads_per_core = siblings_hint / cpu_cores_hint;
260 }
261 if (threads_per_core > 1) {
262 int inferred_physical = logical_cores / threads_per_core;
263 if (inferred_physical > 1) {
264 return inferred_physical;
265 }
266 }
267 if (cpu_cores_hint > 1 && cpu_cores_hint <= logical_cores) {
268 return cpu_cores_hint;
269 }
270 return logical_cores;
271 }
272
273 if (physical_cores > 1) {
274 return physical_cores;
275 }
276
277 return logical_cores;
278}
#define CK_ADD_PAIR(pid, cid)

References CK_ADD_PAIR.

◆ ck_layout_head_to_token_f32()

void ck_layout_head_to_token_f32 ( const float *  src,
float *  dst,
int  heads,
int  tokens,
int  head_dim 
)

Definition at line 19 of file layout_kernels.c.

21{
22 if (!src || !dst || heads <= 0 || tokens <= 0 || head_dim <= 0) return;
23 for (int h = 0; h < heads; ++h) {
24 for (int t = 0; t < tokens; ++t) {
25 memcpy(dst + ((size_t)t * (size_t)heads + (size_t)h) * (size_t)head_dim,
26 src + ((size_t)h * (size_t)tokens + (size_t)t) * (size_t)head_dim,
27 (size_t)head_dim * sizeof(float));
28 }
29 }
30}

◆ ck_layout_token_to_head_f32()

void ck_layout_token_to_head_f32 ( const float *  src,
float *  dst,
int  tokens,
int  heads,
int  head_dim 
)

Definition at line 6 of file layout_kernels.c.

8{
9 if (!src || !dst || tokens <= 0 || heads <= 0 || head_dim <= 0) return;
10 for (int t = 0; t < tokens; ++t) {
11 for (int h = 0; h < heads; ++h) {
12 memcpy(dst + ((size_t)h * (size_t)tokens + (size_t)t) * (size_t)head_dim,
13 src + ((size_t)t * (size_t)heads + (size_t)h) * (size_t)head_dim,
14 (size_t)head_dim * sizeof(float));
15 }
16 }
17}

◆ ck_memcpy_parallel_dispatch()

void * ck_memcpy_parallel_dispatch ( void *  dst,
const void *  src,
size_t  size 
)

◆ ck_multimodal_mrope_positions_2d()

int ck_multimodal_mrope_positions_2d ( int32_t *  positions,
int  total_tokens,
int  prefix_start,
int  position_base,
int  prefix_tokens,
int  grid_x,
int  grid_y,
int  text_pos 
)

Definition at line 2982 of file rope_kernels.c.

2990{
2991 if (!positions || total_tokens <= 0 || prefix_tokens <= 0) {
2992 return -1;
2993 }
2994 if (grid_x <= 0 || grid_y <= 0 || grid_x * grid_y != prefix_tokens) {
2995 return -2;
2996 }
2997 if (prefix_start < 0 || prefix_start > total_tokens) {
2998 return -3;
2999 }
3000 if (prefix_tokens > total_tokens - prefix_start) {
3001 return -4;
3002 }
3003
3004 const int prefix_end = prefix_start + prefix_tokens;
3005 const int grid_extent = grid_x > grid_y ? grid_x : grid_y;
3006 const int resolved_text_pos = text_pos > 0
3007 ? text_pos
3008 : prefix_start + grid_extent;
3009
3010 for (int token = 0; token < total_tokens; ++token) {
3011 int32_t pos0;
3012 int32_t pos1;
3013 int32_t pos2;
3014 if (token < prefix_start) {
3015 pos0 = pos1 = pos2 = (int32_t)token;
3016 } else if (token < prefix_end) {
3017 const int local_token = token - prefix_start;
3018 pos0 = (int32_t)position_base;
3019 pos1 = (int32_t)(position_base + local_token / grid_x);
3020 pos2 = (int32_t)(position_base + local_token % grid_x);
3021 } else {
3022 pos0 = pos1 = pos2 = (int32_t)(resolved_text_pos + token - prefix_end);
3023 }
3024 positions[token] = pos0;
3025 positions[token + total_tokens] = pos1;
3026 positions[token + 2 * total_tokens] = pos2;
3027 positions[token + 3 * total_tokens] = 0;
3028 }
3029 return resolved_text_pos;
3030}

References token.

◆ ck_multimodal_prefix_insert_f32()

int ck_multimodal_prefix_insert_f32 ( const float *  source_rows,
int32_t *  token_ids,
float *  decoder_rows,
int  row_count,
int  source_row_stride,
int  decoder_row_stride,
int  copy_dim,
int  start_row,
int  decoder_capacity 
)

Definition at line 342 of file embedding_kernels.c.

351{
352 if (!source_rows || !token_ids || !decoder_rows || row_count <= 0) {
353 return -1;
354 }
355 if (source_row_stride < copy_dim || decoder_row_stride < copy_dim || copy_dim <= 0) {
356 return -2;
357 }
358 if (start_row < 0 || start_row >= decoder_capacity) {
359 return -3;
360 }
361 if (row_count > decoder_capacity - start_row) {
362 row_count = decoder_capacity - start_row;
363 }
364
365 for (int row = 0; row < row_count; ++row) {
366 const float *src = source_rows + (size_t)row * (size_t)source_row_stride;
367 float *dst = decoder_rows
368 + (size_t)(start_row + row) * (size_t)decoder_row_stride;
369 memcpy(dst, src, (size_t)copy_dim * sizeof(float));
370 token_ids[start_row + row] = 0;
371 }
372 return row_count;
373}

◆ ck_q6_k_prepared_provider_name()

const char * ck_q6_k_prepared_provider_name ( void  )

Definition at line 62 of file gemm_kernels_q6k_q8k.c.

63{
64#if defined(__AVX512F__) && defined(__AVX512BW__) && \
65 defined(__AVX512VNNI__)
66 return "q6_k_prepared_avx512_vnni_exact";
67#elif defined(__AVX2__)
68 return "q6_k_prepared_avx2_exact";
69#else
70 return "q6_k_prepared_unavailable";
71#endif
72}

◆ ck_q6_k_q8_k_provider_name()

const char * ck_q6_k_q8_k_provider_name ( void  )

Definition at line 1389 of file gemm_kernels_q6k_q8k.c.

1390{
1392 return "q6_k_q8_k_ref";
1393 }
1394#if defined(__AVX2__)
1395 return "q6_k_q8_k_avx2";
1396#elif defined(__AVX__)
1397 return "q6_k_q8_k_avx";
1398#elif defined(__SSE4_1__)
1399 return "q6_k_q8_k_sse";
1400#elif defined(__ARM_NEON) || defined(__aarch64__)
1401 return "q6_k_q8_k_neon";
1402#else
1403 return "q6_k_q8_k_ref";
1404#endif
1405}
static int ck_q6k_q8k_force_ref(void)

References ck_q6k_q8k_force_ref(), and ck_strict_parity_enabled().

◆ ck_residual_add_backward()

void ck_residual_add_backward ( const float *  d_out,
float *  d_a,
float *  d_b,
int  tokens,
int  aligned_embed_dim 
)

Definition at line 151 of file ckernel_orchestration.c.

156{
157 if (!d_out || !d_a || !d_b) {
158 return;
159 }
160 size_t total = (size_t)tokens * (size_t)aligned_embed_dim;
161 for (size_t i = 0; i < total; ++i) {
162 float v = d_out[i];
163 d_a[i] = v;
164 d_b[i] = v;
165 }
166}

◆ ck_residual_add_token_major()

void ck_residual_add_token_major ( const float *  a,
const float *  b,
float *  out,
int  tokens,
int  aligned_embed_dim 
)

Definition at line 139 of file ckernel_orchestration.c.

144{
145 size_t total = (size_t)tokens * (size_t)aligned_embed_dim;
146 for (size_t i = 0; i < total; ++i) {
147 out[i] = a[i] + b[i];
148 }
149}

Referenced by ck_layer_forward_rmsnorm_swiglu_decode_fused_attn_impl(), mega_fused_attention_prefill(), and mega_fused_attention_prefill_q8_0().

◆ ck_residual_add_token_major_bf16_storage()

void ck_residual_add_token_major_bf16_storage ( const float *  a,
const float *  b,
float *  out,
int  tokens,
int  aligned_embed_dim 
)

Definition at line 67 of file add_kernels_bf16.c.

72{
73 const size_t count = (size_t)tokens * (size_t)aligned_embed_dim;
74 for (size_t i = 0; i < count; ++i) {
75 const float av = bf16_to_float(float_to_bf16(a[i]));
76 const float bv = bf16_to_float(float_to_bf16(b[i]));
77 out[i] = bf16_to_float(float_to_bf16(av + bv));
78 }
79}

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

◆ ck_residual_add_token_major_parallel_dispatch()

void ck_residual_add_token_major_parallel_dispatch ( const float *  a,
const float *  b,
float *  out,
int  tokens,
int  aligned_embed_dim 
)

◆ ck_set_num_threads()

void ck_set_num_threads ( int  num_threads)

Definition at line 280 of file ckernel_strict.c.

281{
282 // 0 = auto-detect
283 if (num_threads <= 0) {
284 // Prefer explicit env controls when present:
285 // - CK_NUM_THREADS: engine-level override
286 // - OMP_NUM_THREADS: standard OpenMP control (set by `ck run --threads`)
287 int env_threads = ck_parse_env_int("CK_NUM_THREADS");
288 if (env_threads <= 0) {
289 env_threads = ck_parse_env_int("OMP_NUM_THREADS");
290 }
291 num_threads = env_threads > 0 ? env_threads : ck_get_physical_cores();
292 }
293
294 g_num_threads = num_threads;
296
297#ifdef _OPENMP
298 omp_set_dynamic(0); // Disable dynamic adjustment
299 omp_set_num_threads(num_threads);
300#endif
301
302#if defined(USE_MKL)
303 mkl_set_num_threads(num_threads);
304#endif
305
306 fprintf(stderr, "[CK] Set %d threads (auto=%d)\n",
307 num_threads, ck_get_physical_cores());
308}
static int ck_parse_env_int(const char *name)
int ck_get_physical_cores(void)

References ck_get_physical_cores(), ck_parse_env_int(), g_num_threads, and g_threads_initialized.

Referenced by ck_get_num_threads().

◆ ck_set_strict_parity()

void ck_set_strict_parity ( int  enabled)

Definition at line 28 of file ckernel_strict.c.

29{
30 ck_strict_parity = enabled ? 1 : 0;
31 if (!ck_strict_parity) {
34 }
35#ifdef _OPENMP
36 if (ck_strict_parity) {
37 omp_set_dynamic(0);
38 omp_set_num_threads(1);
39 }
40#endif
41}
static size_t ck_strict_next_gemm_a_size
static int ck_strict_parity
static int ck_strict_next_gemm_a_valid

References ck_strict_next_gemm_a_size, ck_strict_next_gemm_a_valid, and ck_strict_parity.

◆ ck_strict_consume_next_gemm_a()

const float * ck_strict_consume_next_gemm_a ( size_t  elems)

Definition at line 70 of file ckernel_strict.c.

71{
73 return NULL;
74 }
77}
static float * ck_strict_next_gemm_a

References ck_strict_next_gemm_a, ck_strict_next_gemm_a_size, ck_strict_next_gemm_a_valid, and ck_strict_parity.

Referenced by gemm_nt_q8_0_q8_0_contract().

◆ ck_strict_mtmd_clip_encode_planar_f32()

int ck_strict_mtmd_clip_encode_planar_f32 ( const float *  planar,
int  channels,
int  height,
int  width,
float *  out,
size_t  out_elems 
)

Definition at line 84 of file ckernel_strict.c.

90{
91 const char *gguf_path = getenv("CK_STRICT_GGUF_PATH");
92 const char *shim_path = getenv("CK_STRICT_MTMD_SHIM_SO");
93 if (!gguf_path || !gguf_path[0] || !shim_path || !shim_path[0]) {
94 return 0;
95 }
96 if (!planar || !out || channels != 3 || height <= 0 || width <= 0) {
97 return 0;
98 }
99
100 void *shim = dlopen(shim_path, RTLD_LAZY | RTLD_LOCAL);
101 if (!shim) {
102 return 0;
103 }
104
106 (ck_strict_mtmd_clip_init_fn) dlsym(shim, "ck_mtmd_clip_init");
108 (ck_strict_mtmd_clip_free_fn) dlsym(shim, "ck_mtmd_clip_free");
110 (ck_strict_mtmd_clip_embd_nbytes_by_img_fn) dlsym(shim, "ck_mtmd_clip_embd_nbytes_by_img");
112 (ck_strict_mtmd_clip_encode_float_image_fn) dlsym(shim, "ck_mtmd_clip_encode_float_image");
113
114 if (!init_fn || !free_fn || !embd_nbytes_fn || !encode_fn) {
115 dlclose(shim);
116 return 0;
117 }
118
119 const size_t pixel_count = (size_t) height * (size_t) width;
120 float *interleaved = (float *) malloc(pixel_count * (size_t) channels * sizeof(float));
121 if (!interleaved) {
122 dlclose(shim);
123 return 0;
124 }
125 for (size_t idx = 0; idx < pixel_count; ++idx) {
126 interleaved[idx * 3 + 0] = planar[idx];
127 interleaved[idx * 3 + 1] = planar[pixel_count + idx];
128 interleaved[idx * 3 + 2] = planar[2 * pixel_count + idx];
129 }
130
131 int ok = 0;
132 void *handle = init_fn(gguf_path, 0, 0, 0, 0, 0);
133 if (handle) {
134 const size_t needed_bytes = embd_nbytes_fn(handle, width, height);
135 if (needed_bytes > 0 && needed_bytes <= out_elems * sizeof(float)) {
136 ok = encode_fn(handle, 1, interleaved, height, width, out) ? 1 : 0;
137 }
138 free_fn(handle);
139 }
140
141 free(interleaved);
142 dlclose(shim);
143 return ok;
144}
void(* ck_strict_mtmd_clip_free_fn)(void *)
void *(* ck_strict_mtmd_clip_init_fn)(const char *, int, int, int, int, int)
size_t(* ck_strict_mtmd_clip_embd_nbytes_by_img_fn)(void *, int, int)
int(* ck_strict_mtmd_clip_encode_float_image_fn)(void *, int, float *, int, int, float *)

◆ ck_strict_parity_enabled()

int ck_strict_parity_enabled ( void  )

Definition at line 43 of file ckernel_strict.c.

44{
45 return ck_strict_parity;
46}

References ck_strict_parity.

Referenced by adamw_update_f32_impl(), 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_mixed_visual_chunk_head_major_gqa_flash_strided_gemma4_impl(), ck_dot_q6_k_q8_k_fast_or_ref(), ck_layer_forward_rmsnorm_swiglu(), ck_layer_forward_rmsnorm_swiglu_ref(), ck_mlp_swiglu_forward(), ck_mlp_swiglu_forward_ref(), ck_q6_k_q8_k_provider_name(), ck_q8k_activations_enabled(), ck_rmsnorm_provider_name(), gated_deltanet_autoregressive_forward(), gated_deltanet_impl_name(), geglu_forward_fp32(), gemm_avx512_parallel(), gemm_blocked_serial(), gemm_fine_grained_parallel(), gemm_naive_parallel(), gemm_nn_avx512(), gemm_nn_avx512_probe(), gemm_nn_blocked(), gemm_nn_parallel(), gemm_nt_f16(), gemm_nt_fp32_exact_parallel_dispatch(), gemm_nt_q6_k_q8_k(), gemm_nt_q6_k_q8_k_m4_tile(), gemm_nt_q8_0_q8_0_contract(), gemm_nt_q8_0_q8_0_contract_m2(), gemm_tn_avx512(), gemm_tn_blocked(), gemm_tn_parallel(), gemv_q4_k_q8_k_vnni(), gemv_q6_k_q8_k(), gemv_q6_k_q8_k_parallel_simd(), gemv_q8_0_q8_0_contract(), layernorm_forward_rolled_slice(), layernorm_forward_unrolled_slice(), mrope_qk_imrope_positions(), mrope_qk_vision(), rmsnorm_backward(), rmsnorm_forward_strided_f32(), softmax_cross_entropy_loss_index_mean_impl(), softmax_cross_entropy_loss_legacy_mean_impl(), swiglu_backward(), swiglu_forward(), and swiglu_forward_q8_k().

◆ ck_strict_store_next_gemm_a()

void ck_strict_store_next_gemm_a ( const float *  data,
size_t  elems 
)

Definition at line 48 of file ckernel_strict.c.

49{
50 if (!ck_strict_parity || !data || elems == 0) {
53 return;
54 }
55 if (elems > ck_strict_next_gemm_a_cap) {
56 float *next = (float *) realloc(ck_strict_next_gemm_a, elems * sizeof(float));
57 if (!next) {
60 return;
61 }
64 }
65 memcpy(ck_strict_next_gemm_a, data, elems * sizeof(float));
68}
static size_t ck_strict_next_gemm_a_cap

References ck_strict_next_gemm_a, ck_strict_next_gemm_a_cap, ck_strict_next_gemm_a_size, ck_strict_next_gemm_a_valid, and ck_strict_parity.

Referenced by ck_attention_full_ggml_graph_oracle_multihead().

◆ ckernel_backend_native()

CKMathBackend ckernel_backend_native ( void  )

Obtain the built-in native backend (single-node CPU, C + intrinsics).

Definition at line 39 of file backend_native.c.

40{
43 return b;
44}
static void ckernel_sgemm_native(int M, int N, int K, const float *A, int lda, const float *B, int ldb, const float *bias, float *C, int ldc)
void(* sgemm)(int M, int N, int K, const float *A, int lda, const float *B, int ldb, const float *bias, float *C, int ldc)

References ckernel_sgemm_native(), and CKMathBackend::sgemm.

◆ deepseek_csa_attention_backward_f32()

void deepseek_csa_attention_backward_f32 ( const float *  d_out,
const float *  q,
const float *  k,
const float *  v,
const int *  indices,
const float *  attn,
float *  d_q,
float *  d_k,
float *  d_v,
int  query_tokens,
int  key_tokens,
int  heads,
int  dim,
int  top_k,
float  scale 
)

Definition at line 621 of file deepseek_kernels.c.

636{
637 if (!d_out || !q || !k || !v || !indices || !attn || !d_q || !d_k || !d_v ||
638 query_tokens <= 0 || key_tokens <= 0 || heads <= 0 || dim <= 0 || top_k <= 0) return;
639
640 const size_t q_count = (size_t)query_tokens * (size_t)heads * (size_t)dim;
641 const size_t kv_count = (size_t)key_tokens * (size_t)heads * (size_t)dim;
642 for (size_t i = 0; i < q_count; ++i) d_q[i] = 0.0f;
643 for (size_t i = 0; i < kv_count; ++i) {
644 d_k[i] = 0.0f;
645 d_v[i] = 0.0f;
646 }
647
648 for (int tq = 0; tq < query_tokens; ++tq) {
649 for (int h = 0; h < heads; ++h) {
650 float d_attn[top_k];
651 float attn_dot = 0.0f;
652 for (int j = 0; j < top_k; ++j) {
653 const int tk = indices[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j];
654 float da = 0.0f;
655 if (tk >= 0 && tk < key_tokens) {
656 const float a = attn[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j];
657 for (int d = 0; d < dim; ++d) {
658 const float go = d_out[ds_qkv_idx(tq, h, d, heads, dim)];
659 da += go * v[ds_qkv_idx(tk, h, d, heads, dim)];
660 d_v[ds_qkv_idx(tk, h, d, heads, dim)] += a * go;
661 }
662 attn_dot += a * da;
663 }
664 d_attn[j] = da;
665 }
666
667 for (int j = 0; j < top_k; ++j) {
668 const int tk = indices[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j];
669 if (tk < 0 || tk >= key_tokens) continue;
670 const float a = attn[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j];
671 const float d_score = a * (d_attn[j] - attn_dot);
672 for (int d = 0; d < dim; ++d) {
673 const float qv = q[ds_qkv_idx(tq, h, d, heads, dim)];
674 const float kv = k[ds_qkv_idx(tk, h, d, heads, dim)];
675 d_q[ds_qkv_idx(tq, h, d, heads, dim)] += scale * d_score * kv;
676 d_k[ds_qkv_idx(tk, h, d, heads, dim)] += scale * d_score * qv;
677 }
678 }
679 }
680 }
681}
static size_t ds_qkv_idx(int token, int head, int d, int heads, int dim)

References ds_qkv_idx().

◆ deepseek_csa_attention_f32()

void deepseek_csa_attention_f32 ( const float *  q,
const float *  k,
const float *  v,
const int *  indices,
float *  out,
float *  attn,
int  query_tokens,
int  key_tokens,
int  heads,
int  dim,
int  top_k,
float  scale 
)

Definition at line 562 of file deepseek_kernels.c.

574{
575 if (!q || !k || !v || !indices || !out || query_tokens <= 0 || key_tokens <= 0 ||
576 heads <= 0 || dim <= 0 || top_k <= 0) return;
577
578 for (int tq = 0; tq < query_tokens; ++tq) {
579 for (int h = 0; h < heads; ++h) {
580 float local_scores[top_k];
581 int valid = 0;
582 for (int j = 0; j < top_k; ++j) {
583 const int tk = indices[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j];
584 if (tk < 0 || tk >= key_tokens) {
585 local_scores[j] = -FLT_MAX;
586 continue;
587 }
588 float dot = 0.0f;
589 for (int d = 0; d < dim; ++d) {
590 dot += q[ds_qkv_idx(tq, h, d, heads, dim)] * k[ds_qkv_idx(tk, h, d, heads, dim)];
591 }
592 local_scores[j] = dot * scale;
593 valid++;
594 }
595
596 float *out_row = out + ds_qkv_idx(tq, h, 0, heads, dim);
597 for (int d = 0; d < dim; ++d) out_row[d] = 0.0f;
598 if (valid == 0) {
599 if (attn) {
600 for (int j = 0; j < top_k; ++j) {
601 attn[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j] = 0.0f;
602 }
603 }
604 continue;
605 }
606
607 ds_softmax(local_scores, top_k);
608 for (int j = 0; j < top_k; ++j) {
609 const int tk = indices[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j];
610 const float a = (tk >= 0 && tk < key_tokens) ? local_scores[j] : 0.0f;
611 if (attn) attn[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)top_k + (size_t)j] = a;
612 if (a == 0.0f) continue;
613 for (int d = 0; d < dim; ++d) {
614 out_row[d] += a * v[ds_qkv_idx(tk, h, d, heads, dim)];
615 }
616 }
617 }
618 }
619}
static void ds_softmax(float *x, int n)

References ds_qkv_idx(), and ds_softmax().

Referenced by deepseek_hybrid_attention_f32().

◆ deepseek_dsa_topk_softmax_backward_f32()

void deepseek_dsa_topk_softmax_backward_f32 ( const int *  indices,
const float *  weights,
const float *  d_weights,
float *  d_scores,
int  tokens,
int  heads,
int  key_count,
int  top_k 
)

Definition at line 153 of file deepseek_kernels.c.

161{
162 if (!indices || !weights || !d_weights || !d_scores ||
163 tokens <= 0 || heads <= 0 || key_count <= 0 || top_k <= 0) return;
164
166 weights,
167 d_weights,
168 d_scores,
169 tokens * heads,
170 key_count,
171 top_k);
172}
void topk_softmax_backward_f32(const int *indices, const float *weights, const float *d_weights, float *d_scores, int num_tokens, int n_experts_or_keys, int k)
Backward for hard top-k followed by softmax over selected values.

References topk_softmax_backward_f32().

◆ deepseek_dsa_topk_softmax_f32()

void deepseek_dsa_topk_softmax_f32 ( const float *  scores,
int *  indices,
float *  weights,
int  tokens,
int  heads,
int  key_count,
int  top_k 
)

Definition at line 86 of file deepseek_kernels.c.

93{
94 if (!scores || !indices || !weights || tokens <= 0 || heads <= 0 ||
95 key_count <= 0 || top_k <= 0) return;
96
97 if (top_k > key_count) top_k = key_count;
98
99 for (int t = 0; t < tokens; ++t) {
100 for (int h = 0; h < heads; ++h) {
101 const float *row = scores + ((size_t)t * (size_t)heads + (size_t)h) * (size_t)key_count;
102 int *idx = indices + ((size_t)t * (size_t)heads + (size_t)h) * (size_t)top_k;
103 float *w = weights + ((size_t)t * (size_t)heads + (size_t)h) * (size_t)top_k;
104
105 for (int k = 0; k < top_k; ++k) {
106 idx[k] = -1;
107 w[k] = -FLT_MAX;
108 }
109
110 for (int j = 0; j < key_count; ++j) {
111 const float v = row[j];
112 int pos = -1;
113 for (int k = 0; k < top_k; ++k) {
114 if (idx[k] < 0 || v > w[k] || (v == w[k] && j < idx[k])) {
115 pos = k;
116 break;
117 }
118 }
119 if (pos >= 0) {
120 for (int k = top_k - 1; k > pos; --k) {
121 idx[k] = idx[k - 1];
122 w[k] = w[k - 1];
123 }
124 idx[pos] = j;
125 w[pos] = v;
126 }
127 }
128
129 float max_v = w[0];
130 for (int k = 1; k < top_k; ++k) if (w[k] > max_v) max_v = w[k];
131 float sum = 0.0f;
132 for (int k = 0; k < top_k; ++k) {
133 w[k] = expf(w[k] - max_v);
134 sum += w[k];
135 }
136 if (sum > 0.0f) {
137 const float inv = 1.0f / sum;
138 for (int k = 0; k < top_k; ++k) w[k] *= inv;
139 }
140 }
141 }
142}

◆ deepseek_hybrid_attention_f32()

void deepseek_hybrid_attention_f32 ( const float *  q,
const float *  k,
const float *  v,
const int *  indices,
float *  out,
float *  attn,
int  query_tokens,
int  key_tokens,
int  heads,
int  dim,
int  top_k,
float  scale,
int  mode 
)

Definition at line 683 of file deepseek_kernels.c.

696{
697 if (mode != 0) {
698 deepseek_csa_attention_f32(q, k, v, indices, out, attn,
699 query_tokens, key_tokens, heads, dim, top_k, scale);
700 return;
701 }
702
703 int dense_indices[query_tokens * heads * key_tokens];
704 for (int tq = 0; tq < query_tokens; ++tq) {
705 for (int h = 0; h < heads; ++h) {
706 for (int tk = 0; tk < key_tokens; ++tk) {
707 dense_indices[((size_t)tq * (size_t)heads + (size_t)h) * (size_t)key_tokens + (size_t)tk] = tk;
708 }
709 }
710 }
711 deepseek_csa_attention_f32(q, k, v, dense_indices, out, attn,
712 query_tokens, key_tokens, heads, dim, key_tokens, scale);
713}
void deepseek_csa_attention_f32(const float *q, const float *k, const float *v, const int *indices, float *out, float *attn, int query_tokens, int key_tokens, int heads, int dim, int top_k, float scale)

References deepseek_csa_attention_f32().

◆ deepseek_mhc_mix_backward_f32()

void deepseek_mhc_mix_backward_f32 ( const float *  d_out,
const float *  streams,
const float *  mix,
float *  d_streams,
float *  d_mix,
int  tokens,
int  n_streams,
int  dim 
)

Definition at line 53 of file deepseek_kernels.c.

61{
62 if (!d_out || !streams || !mix || !d_streams || !d_mix ||
63 tokens <= 0 || n_streams <= 0 || dim <= 0) return;
64
65 const size_t stream_count = (size_t)tokens * (size_t)n_streams * (size_t)dim;
66 const size_t mix_count = (size_t)tokens * (size_t)n_streams * (size_t)n_streams;
67 for (size_t i = 0; i < stream_count; ++i) d_streams[i] = 0.0f;
68 for (size_t i = 0; i < mix_count; ++i) d_mix[i] = 0.0f;
69
70 for (int t = 0; t < tokens; ++t) {
71 for (int os = 0; os < n_streams; ++os) {
72 for (int is = 0; is < n_streams; ++is) {
73 float d_mix_acc = 0.0f;
74 const float m = mix[ds_mix_idx(t, os, is, n_streams)];
75 for (int d = 0; d < dim; ++d) {
76 const float go = d_out[ds_mhc_idx(t, os, d, n_streams, dim)];
77 d_streams[ds_mhc_idx(t, is, d, n_streams, dim)] += m * go;
78 d_mix_acc += go * streams[ds_mhc_idx(t, is, d, n_streams, dim)];
79 }
80 d_mix[ds_mix_idx(t, os, is, n_streams)] = d_mix_acc;
81 }
82 }
83 }
84}
static size_t ds_mix_idx(int t, int out_s, int in_s, int n_streams)
static size_t ds_mhc_idx(int t, int s, int d, int n_streams, int dim)

References ds_mhc_idx(), and ds_mix_idx().

◆ deepseek_mhc_mix_f32()

void deepseek_mhc_mix_f32 ( const float *  streams,
const float *  mix,
float *  out,
int  tokens,
int  n_streams,
int  dim 
)

Definition at line 30 of file deepseek_kernels.c.

36{
37 if (!streams || !mix || !out || tokens <= 0 || n_streams <= 0 || dim <= 0) return;
38
39 for (int t = 0; t < tokens; ++t) {
40 for (int os = 0; os < n_streams; ++os) {
41 for (int d = 0; d < dim; ++d) {
42 float acc = 0.0f;
43 for (int is = 0; is < n_streams; ++is) {
44 acc += mix[ds_mix_idx(t, os, is, n_streams)] *
45 streams[ds_mhc_idx(t, is, d, n_streams, dim)];
46 }
47 out[ds_mhc_idx(t, os, d, n_streams, dim)] = acc;
48 }
49 }
50 }
51}

References ds_mhc_idx(), and ds_mix_idx().

◆ deepseek_mla_attention_bf16_phases_parallel_dispatch()

void deepseek_mla_attention_bf16_phases_parallel_dispatch ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  qk_head_dim,
int  v_head_dim,
float  scale,
float *  scores,
size_t  scores_bytes 
)

Definition at line 942 of file deepseek_kernels.c.

947{
948 ds_mla_attention_parallel_dispatch(q, k, v, output, num_heads,
949 num_kv_heads, num_tokens, qk_head_dim, v_head_dim,
950 scale, scores, scores_bytes, 1);
951}
static void ds_mla_attention_parallel_dispatch(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes, int bf16_phases)

References ds_mla_attention_parallel_dispatch().

◆ deepseek_mla_attention_bf16_phases_workspace()

void deepseek_mla_attention_bf16_phases_workspace ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  qk_head_dim,
int  v_head_dim,
float  scale,
float *  scores,
size_t  scores_bytes 
)

Definition at line 823 of file deepseek_kernels.c.

828{
829 if (!ds_mla_prefill_valid(q, k, v, output, num_heads, num_kv_heads,
830 num_tokens, qk_head_dim, v_head_dim, scale, scores,
831 scores_bytes)) return;
833 q, k, v, output, num_heads, num_kv_heads, num_tokens,
834 qk_head_dim, v_head_dim, scale, scores,
835 0, num_tokens * num_heads, 1, 1);
836}
static int ds_mla_prefill_valid(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)
static void ds_mla_attention_f32_query_range(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, int query_begin, int query_end, int query_step, int bf16_phases)

References ds_mla_attention_f32_query_range(), and ds_mla_prefill_valid().

Referenced by ds_mla_attention_parallel_dispatch().

◆ deepseek_mla_attention_decode_bf16_phases_workspace()

void deepseek_mla_attention_decode_bf16_phases_workspace ( const float *  q,
const float *  k_cache,
const float *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  cache_len,
int  qk_head_dim,
int  v_head_dim,
int  max_seq_len,
int  cache_stride,
float  scale,
float *  scores,
size_t  scores_bytes 
)

Definition at line 1144 of file deepseek_kernels.c.

1149{
1150 ds_mla_attention_decode_workspace(q, k_cache, v_cache, output,
1151 num_heads, num_kv_heads, cache_len, qk_head_dim, v_head_dim,
1152 max_seq_len, cache_stride, scale, scores, scores_bytes, 1);
1153}
static void ds_mla_attention_decode_workspace(const float *q, const float *k_cache, const float *v_cache, float *output, int num_heads, int num_kv_heads, int cache_len, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride, float scale, float *scores, size_t scores_bytes, int bf16_phases)

References ds_mla_attention_decode_workspace().

◆ deepseek_mla_attention_decode_f32()

void deepseek_mla_attention_decode_f32 ( const float *  q,
const float *  k_cache,
const float *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  cache_len,
int  qk_head_dim,
int  v_head_dim,
int  max_seq_len,
int  cache_stride 
)

Definition at line 1155 of file deepseek_kernels.c.

1166{
1167 if (cache_len <= 0 || (size_t)cache_len > SIZE_MAX / sizeof(float)) return;
1168 const size_t scores_bytes = (size_t)cache_len * sizeof(float);
1169 float *scores = (float *)malloc(scores_bytes);
1170 if (!scores) return;
1172 q, k_cache, v_cache, output, num_heads, num_kv_heads, cache_len,
1173 qk_head_dim, v_head_dim, max_seq_len, cache_stride,
1174 1.0f / sqrtf((float)qk_head_dim), scores, scores_bytes);
1175 free(scores);
1176}
void deepseek_mla_attention_decode_f32_workspace(const float *q, const float *k_cache, const float *v_cache, float *output, int num_heads, int num_kv_heads, int cache_len, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride, float scale, float *scores, size_t scores_bytes)

References deepseek_mla_attention_decode_f32_workspace().

◆ deepseek_mla_attention_decode_f32_workspace()

void deepseek_mla_attention_decode_f32_workspace ( const float *  q,
const float *  k_cache,
const float *  v_cache,
float *  output,
int  num_heads,
int  num_kv_heads,
int  cache_len,
int  qk_head_dim,
int  v_head_dim,
int  max_seq_len,
int  cache_stride,
float  scale,
float *  scores,
size_t  scores_bytes 
)

Definition at line 1133 of file deepseek_kernels.c.

1138{
1139 ds_mla_attention_decode_workspace(q, k_cache, v_cache, output,
1140 num_heads, num_kv_heads, cache_len, qk_head_dim, v_head_dim,
1141 max_seq_len, cache_stride, scale, scores, scores_bytes, 0);
1142}

References ds_mla_attention_decode_workspace().

Referenced by deepseek_mla_attention_decode_f32().

◆ deepseek_mla_attention_f32()

void deepseek_mla_attention_f32 ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  qk_head_dim,
int  v_head_dim 
)

Definition at line 953 of file deepseek_kernels.c.

962{
963 if (num_tokens <= 0 || (size_t)num_tokens > SIZE_MAX / sizeof(float)) return;
964 const size_t scores_bytes = (size_t)num_tokens * sizeof(float);
965 float *scores = (float *)malloc(scores_bytes);
966 if (!scores) return;
968 q, k, v, output, num_heads, num_kv_heads, num_tokens,
969 qk_head_dim, v_head_dim, 1.0f / sqrtf((float)qk_head_dim),
970 scores, scores_bytes);
971 free(scores);
972}
void deepseek_mla_attention_f32_workspace(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)

References deepseek_mla_attention_f32_workspace().

◆ deepseek_mla_attention_f32_parallel_dispatch()

void deepseek_mla_attention_f32_parallel_dispatch ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  qk_head_dim,
int  v_head_dim,
float  scale,
float *  scores,
size_t  scores_bytes 
)

Definition at line 931 of file deepseek_kernels.c.

936{
937 ds_mla_attention_parallel_dispatch(q, k, v, output, num_heads,
938 num_kv_heads, num_tokens, qk_head_dim, v_head_dim,
939 scale, scores, scores_bytes, 0);
940}

References ds_mla_attention_parallel_dispatch().

◆ deepseek_mla_attention_f32_workspace()

void deepseek_mla_attention_f32_workspace ( const float *  q,
const float *  k,
const float *  v,
float *  output,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  qk_head_dim,
int  v_head_dim,
float  scale,
float *  scores,
size_t  scores_bytes 
)

Definition at line 800 of file deepseek_kernels.c.

812{
813 if (!ds_mla_prefill_valid(q, k, v, output, num_heads, num_kv_heads,
814 num_tokens, qk_head_dim, v_head_dim, scale, scores,
815 scores_bytes)) return;
816
818 q, k, v, output, num_heads, num_kv_heads, num_tokens,
819 qk_head_dim, v_head_dim, scale, scores,
820 0, num_tokens * num_heads, 1, 0);
821}

References ds_mla_attention_f32_query_range(), and ds_mla_prefill_valid().

Referenced by deepseek_mla_attention_f32(), and ds_mla_attention_parallel_dispatch().

◆ deepseek_mla_kv_cache_batch_store_f32()

void deepseek_mla_kv_cache_batch_store_f32 ( float *  k_cache,
float *  v_cache,
const float *  k,
const float *  v,
int  num_tokens,
int  num_kv_heads,
int  qk_head_dim,
int  v_head_dim,
int  max_seq_len,
int  cache_stride 
)

Definition at line 974 of file deepseek_kernels.c.

984{
985 if (!k_cache || !v_cache || !k || !v || num_tokens <= 0 ||
986 num_kv_heads <= 0 || qk_head_dim <= 0 || v_head_dim <= 0 ||
987 max_seq_len <= 0 || cache_stride <= 0) {
988 return;
989 }
990 if (qk_head_dim > cache_stride || v_head_dim > cache_stride) {
991 return;
992 }
993 if (num_tokens > max_seq_len) {
994 num_tokens = max_seq_len;
995 }
996
997 for (int t = 0; t < num_tokens; ++t) {
998 for (int h = 0; h < num_kv_heads; ++h) {
999 const float *k_src = k + ((size_t)t * (size_t)num_kv_heads + (size_t)h) * (size_t)qk_head_dim;
1000 const float *v_src = v + ((size_t)t * (size_t)num_kv_heads + (size_t)h) * (size_t)v_head_dim;
1001 float *k_dst = k_cache + ((size_t)h * (size_t)max_seq_len + (size_t)t) * (size_t)cache_stride;
1002 float *v_dst = v_cache + ((size_t)h * (size_t)max_seq_len + (size_t)t) * (size_t)cache_stride;
1003 for (int d = 0; d < qk_head_dim; ++d) k_dst[d] = k_src[d];
1004 for (int d = qk_head_dim; d < cache_stride; ++d) k_dst[d] = 0.0f;
1005 for (int d = 0; d < v_head_dim; ++d) v_dst[d] = v_src[d];
1006 for (int d = v_head_dim; d < cache_stride; ++d) v_dst[d] = 0.0f;
1007 }
1008 }
1009}

◆ deepseek_mla_kv_cache_store_f32()

void deepseek_mla_kv_cache_store_f32 ( float *  k_cache,
float *  v_cache,
const float *  k,
const float *  v,
int  pos,
int  num_kv_heads,
int  qk_head_dim,
int  v_head_dim,
int  max_seq_len,
int  cache_stride 
)

Definition at line 1011 of file deepseek_kernels.c.

1021{
1022 if (!k_cache || !v_cache || !k || !v || pos < 0 ||
1023 num_kv_heads <= 0 || qk_head_dim <= 0 || v_head_dim <= 0 ||
1024 max_seq_len <= 0 || cache_stride <= 0) {
1025 return;
1026 }
1027 if (pos >= max_seq_len || qk_head_dim > cache_stride || v_head_dim > cache_stride) {
1028 return;
1029 }
1030
1031 for (int h = 0; h < num_kv_heads; ++h) {
1032 const float *k_src = k + ((size_t)h * (size_t)qk_head_dim);
1033 const float *v_src = v + ((size_t)h * (size_t)v_head_dim);
1034 float *k_dst = k_cache + ((size_t)h * (size_t)max_seq_len + (size_t)pos) * (size_t)cache_stride;
1035 float *v_dst = v_cache + ((size_t)h * (size_t)max_seq_len + (size_t)pos) * (size_t)cache_stride;
1036
1037 for (int d = 0; d < qk_head_dim; ++d) {
1038 k_dst[d] = k_src[d];
1039 }
1040 for (int d = qk_head_dim; d < cache_stride; ++d) {
1041 k_dst[d] = 0.0f;
1042 }
1043 for (int d = 0; d < v_head_dim; ++d) {
1044 v_dst[d] = v_src[d];
1045 }
1046 for (int d = v_head_dim; d < cache_stride; ++d) {
1047 v_dst[d] = 0.0f;
1048 }
1049 }
1050}

◆ deepseek_mla_kv_decompress_bf16()

void deepseek_mla_kv_decompress_bf16 ( const float *  compressed_kv,
const uint16_t *  kv_b_proj,
float *  k_nope,
float *  value,
int  tokens,
int  heads,
int  kv_lora_rank,
int  qk_nope_dim,
int  v_dim 
)

Definition at line 270 of file deepseek_kernels.c.

279{
280 if (tokens <= 0) return;
282 compressed_kv, kv_b_proj, k_nope, value, tokens, heads,
283 kv_lora_rank, qk_nope_dim, v_dim, 0, tokens);
284}
void deepseek_mla_kv_decompress_bf16_token_range(const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim, int token_begin, int token_end)

References deepseek_mla_kv_decompress_bf16_token_range().

Referenced by deepseek_mla_kv_decompress_bf16_parallel_dispatch().

◆ deepseek_mla_kv_decompress_bf16_parallel_dispatch()

void deepseek_mla_kv_decompress_bf16_parallel_dispatch ( const float *  compressed_kv,
const uint16_t *  kv_b_proj,
float *  k_nope,
float *  value,
int  tokens,
int  heads,
int  kv_lora_rank,
int  qk_nope_dim,
int  v_dim 
)

Definition at line 308 of file deepseek_kernels.c.

318{
319 ck_threadpool_t *pool = ck_threadpool_global();
320 const char *disabled = getenv("CK_DISABLE_MLA_PARALLEL_PREFILL");
321 if ((disabled && disabled[0] && strcmp(disabled, "0") != 0) ||
322 !pool || ck_threadpool_n_threads(pool) <= 1 || tokens < 2) {
324 compressed_kv, kv_b_proj, k_nope, value, tokens, heads,
325 kv_lora_rank, qk_nope_dim, v_dim);
326 return;
327 }
328 ds_mla_kv_decompress_bf16_args_t args = {
329 .compressed_kv = compressed_kv,
330 .kv_b_proj = kv_b_proj,
331 .k_nope = k_nope,
332 .value = value,
333 .tokens = tokens,
334 .heads = heads,
335 .kv_lora_rank = kv_lora_rank,
336 .qk_nope_dim = qk_nope_dim,
337 .v_dim = v_dim,
338 };
339 int active = ck_threadpool_n_threads(pool);
340 if (active > tokens) active = tokens;
341 int grain = tokens / (active * 4);
342 if (grain < 1) grain = 1;
344 pool, active, 0, tokens, grain, ds_mla_kv_decompress_bf16_rows, &args);
345}
void deepseek_mla_kv_decompress_bf16(const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim)
static void ds_mla_kv_decompress_bf16_rows(int begin, int end, void *opaque)

References ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), deepseek_mla_kv_decompress_bf16(), and ds_mla_kv_decompress_bf16_rows().

◆ deepseek_mla_kv_decompress_bf16_token_range()

void deepseek_mla_kv_decompress_bf16_token_range ( const float *  compressed_kv,
const uint16_t *  kv_b_proj,
float *  k_nope,
float *  value,
int  tokens,
int  heads,
int  kv_lora_rank,
int  qk_nope_dim,
int  v_dim,
int  token_begin,
int  token_end 
)

Definition at line 225 of file deepseek_kernels.c.

236{
237 if (!compressed_kv || !kv_b_proj || !k_nope || !value ||
238 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 || v_dim <= 0 ||
239 token_begin < 0 || token_begin >= token_end || token_end > tokens) {
240 return;
241 }
242
243 const int out_per_head = qk_nope_dim + v_dim;
244 for (int t = token_begin; t < token_end; ++t) {
245 for (int h = 0; h < heads; ++h) {
246 for (int d = 0; d < qk_nope_dim; ++d) {
247 const int out_col = h * out_per_head + d;
248 float acc = 0.0f;
249 for (int r = 0; r < kv_lora_rank; ++r) {
250 acc += bf16_to_float(kv_b_proj[(size_t)out_col * (size_t)kv_lora_rank + (size_t)r]) *
251 compressed_kv[ds_mla_tok_idx(t, r, kv_lora_rank)];
252 }
253 k_nope[ds_mla_thd_idx(t, h, d, heads, qk_nope_dim)] =
255 }
256 for (int d = 0; d < v_dim; ++d) {
257 const int out_col = h * out_per_head + qk_nope_dim + d;
258 float acc = 0.0f;
259 for (int r = 0; r < kv_lora_rank; ++r) {
260 acc += bf16_to_float(kv_b_proj[(size_t)out_col * (size_t)kv_lora_rank + (size_t)r]) *
261 compressed_kv[ds_mla_tok_idx(t, r, kv_lora_rank)];
262 }
263 value[ds_mla_thd_idx(t, h, d, heads, v_dim)] =
265 }
266 }
267 }
268}
static size_t ds_mla_thd_idx(int t, int h, int d, int heads, int dim)
static size_t ds_mla_tok_idx(int t, int d, int dim)

References bf16_to_float(), ds_mla_thd_idx(), ds_mla_tok_idx(), and float_to_bf16().

Referenced by deepseek_mla_kv_decompress_bf16(), and ds_mla_kv_decompress_bf16_rows().

◆ deepseek_mla_kv_decompress_f32()

void deepseek_mla_kv_decompress_f32 ( const float *  compressed_kv,
const float *  kv_b_proj,
float *  k_nope,
float *  value,
int  tokens,
int  heads,
int  kv_lora_rank,
int  qk_nope_dim,
int  v_dim 
)

Definition at line 185 of file deepseek_kernels.c.

194{
195 if (!compressed_kv || !kv_b_proj || !k_nope || !value ||
196 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 || v_dim <= 0) {
197 return;
198 }
199
200 const int out_per_head = qk_nope_dim + v_dim;
201 for (int t = 0; t < tokens; ++t) {
202 for (int h = 0; h < heads; ++h) {
203 for (int d = 0; d < qk_nope_dim; ++d) {
204 const int out_col = h * out_per_head + d;
205 float acc = 0.0f;
206 for (int r = 0; r < kv_lora_rank; ++r) {
207 acc += kv_b_proj[(size_t)out_col * (size_t)kv_lora_rank + (size_t)r] *
208 compressed_kv[ds_mla_tok_idx(t, r, kv_lora_rank)];
209 }
210 k_nope[ds_mla_thd_idx(t, h, d, heads, qk_nope_dim)] = acc;
211 }
212 for (int d = 0; d < v_dim; ++d) {
213 const int out_col = h * out_per_head + qk_nope_dim + d;
214 float acc = 0.0f;
215 for (int r = 0; r < kv_lora_rank; ++r) {
216 acc += kv_b_proj[(size_t)out_col * (size_t)kv_lora_rank + (size_t)r] *
217 compressed_kv[ds_mla_tok_idx(t, r, kv_lora_rank)];
218 }
219 value[ds_mla_thd_idx(t, h, d, heads, v_dim)] = acc;
220 }
221 }
222 }
223}

References ds_mla_thd_idx(), and ds_mla_tok_idx().

◆ deepseek_mla_partial_rope_concat_f32()

void deepseek_mla_partial_rope_concat_f32 ( const float *  q_nope,
const float *  q_pe,
const float *  k_nope,
const float *  k_pe,
const float *  cos,
const float *  sin,
float *  query,
float *  key,
int  tokens,
int  heads,
int  qk_nope_dim,
int  qk_rope_dim 
)

Definition at line 367 of file deepseek_kernels.c.

379{
380 if (!q_nope || !q_pe || !k_nope || !k_pe || !cos || !sin || !query || !key ||
381 tokens <= 0 || heads <= 0 || qk_nope_dim <= 0 || qk_rope_dim <= 0 || (qk_rope_dim % 2) != 0) {
382 return;
383 }
384
385 const int q_head_dim = qk_nope_dim + qk_rope_dim;
386 for (int t = 0; t < tokens; ++t) {
387 const float *cos_row = cos + (size_t)t * (size_t)(qk_rope_dim / 2);
388 const float *sin_row = sin + (size_t)t * (size_t)(qk_rope_dim / 2);
389 for (int h = 0; h < heads; ++h) {
390 float *q_out = query + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
391 float *k_out = key + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
392 const float *qn = q_nope + ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
393 const float *qp = q_pe + ds_mla_thd_idx(t, h, 0, heads, qk_rope_dim);
394 const float *kn = k_nope + ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
395 const float *kp = k_pe + ds_mla_tok_idx(t, 0, qk_rope_dim);
396 for (int d = 0; d < qk_nope_dim; ++d) {
397 q_out[d] = qn[d];
398 k_out[d] = kn[d];
399 }
400 ds_mla_apply_kimi_rope(qp, q_out + qk_nope_dim, cos_row, sin_row, qk_rope_dim);
401 ds_mla_apply_kimi_rope(kp, k_out + qk_nope_dim, cos_row, sin_row, qk_rope_dim);
402 }
403 }
404}
static void ds_mla_apply_kimi_rope(const float *src, float *dst, const float *cos_row, const float *sin_row, int dim)

References ds_mla_apply_kimi_rope(), ds_mla_thd_idx(), and ds_mla_tok_idx().

◆ deepseek_mla_partial_rope_concat_packed_bf16_storage()

void deepseek_mla_partial_rope_concat_packed_bf16_storage ( const float *  q_packed,
const float *  k_nope,
const float *  kv_a_packed,
const float *  cos,
const float *  sin,
float *  query,
float *  key,
int  tokens,
int  heads,
int  kv_lora_rank,
int  qk_nope_dim,
int  qk_rope_dim 
)

Definition at line 473 of file deepseek_kernels.c.

486{
487 if (!q_packed || !k_nope || !kv_a_packed || !cos || !sin || !query || !key ||
488 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 ||
489 qk_rope_dim <= 0 || (qk_rope_dim % 2) != 0) {
490 return;
491 }
492
493 const int q_head_dim = qk_nope_dim + qk_rope_dim;
494 const int kv_a_dim = kv_lora_rank + qk_rope_dim;
495 const int half = qk_rope_dim / 2;
496 for (int t = 0; t < tokens; ++t) {
497 const float *cos_row = cos + (size_t)t * (size_t)half;
498 const float *sin_row = sin + (size_t)t * (size_t)half;
499 const float *kp = kv_a_packed + (size_t)t * (size_t)kv_a_dim + (size_t)kv_lora_rank;
500 for (int h = 0; h < heads; ++h) {
501 const float *q_in = q_packed + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
502 const float *kn = k_nope + ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
503 float *q_out = query + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
504 float *k_out = key + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
505
506 for (int d = 0; d < qk_nope_dim; ++d) {
507 q_out[d] = ds_mla_bf16_round(q_in[d]);
508 k_out[d] = ds_mla_bf16_round(kn[d]);
509 }
510
511 float q_pe_tmp[256];
512 for (int i = 0; i < qk_rope_dim; ++i) {
513 q_pe_tmp[i] = ds_mla_bf16_round(q_in[qk_nope_dim + i]);
514 }
515 for (int i = 0; i < half; ++i) {
516 const float q_first = q_pe_tmp[2 * i];
517 const float q_second = q_pe_tmp[2 * i + 1];
518 const float k_first = ds_mla_bf16_round(kp[2 * i]);
519 const float k_second = ds_mla_bf16_round(kp[2 * i + 1]);
520 const float c = ds_mla_bf16_round(cos_row[i]);
521 const float s = ds_mla_bf16_round(sin_row[i]);
522
523 const float q_first_cos = ds_mla_bf16_round(q_first * c);
524 const float q_second_sin = ds_mla_bf16_round(q_second * s);
525 const float q_second_cos = ds_mla_bf16_round(q_second * c);
526 const float q_first_sin = ds_mla_bf16_round(q_first * s);
527 const float k_first_cos = ds_mla_bf16_round(k_first * c);
528 const float k_second_sin = ds_mla_bf16_round(k_second * s);
529 const float k_second_cos = ds_mla_bf16_round(k_second * c);
530 const float k_first_sin = ds_mla_bf16_round(k_first * s);
531
532 q_out[qk_nope_dim + i] = ds_mla_bf16_round(q_first_cos - q_second_sin);
533 q_out[qk_nope_dim + half + i] = ds_mla_bf16_round(q_second_cos + q_first_sin);
534 k_out[qk_nope_dim + i] = ds_mla_bf16_round(k_first_cos - k_second_sin);
535 k_out[qk_nope_dim + half + i] = ds_mla_bf16_round(k_second_cos + k_first_sin);
536 }
537 }
538 }
539}
static float ds_mla_bf16_round(float value)

References ds_mla_bf16_round(), and ds_mla_thd_idx().

◆ deepseek_mla_partial_rope_concat_packed_f32()

void deepseek_mla_partial_rope_concat_packed_f32 ( const float *  q_packed,
const float *  k_nope,
const float *  kv_a_packed,
const float *  cos,
const float *  sin,
float *  query,
float *  key,
int  tokens,
int  heads,
int  kv_lora_rank,
int  qk_nope_dim,
int  qk_rope_dim 
)

Definition at line 406 of file deepseek_kernels.c.

418{
419 if (!q_packed || !k_nope || !kv_a_packed || !cos || !sin || !query || !key ||
420 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 ||
421 qk_rope_dim <= 0 || qk_rope_dim > 256 || (qk_rope_dim % 2) != 0) {
422 return;
423 }
424
425 const int q_head_dim = qk_nope_dim + qk_rope_dim;
426 const int kv_a_dim = kv_lora_rank + qk_rope_dim;
427 const int half = qk_rope_dim / 2;
428 if (qk_rope_dim > 256) {
429 return;
430 }
431 for (int t = 0; t < tokens; ++t) {
432 const float *cos_row = cos + (size_t)t * (size_t)half;
433 const float *sin_row = sin + (size_t)t * (size_t)half;
434 const float *kp = kv_a_packed + (size_t)t * (size_t)kv_a_dim + (size_t)kv_lora_rank;
435 for (int h = 0; h < heads; ++h) {
436 const float *q_in = q_packed + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
437 const float *kn = k_nope + ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
438 float *q_out = query + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
439 float *k_out = key + ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
440
441 for (int d = 0; d < qk_nope_dim; ++d) {
442 q_out[d] = q_in[d];
443 k_out[d] = kn[d];
444 }
445
446 const float *qp = q_in + qk_nope_dim;
447 float q_pe_tmp[256];
448 if (qk_rope_dim > (int)(sizeof(q_pe_tmp) / sizeof(q_pe_tmp[0]))) {
449 return;
450 }
451 for (int i = 0; i < qk_rope_dim; ++i) q_pe_tmp[i] = qp[i];
452 for (int i = 0; i < half; ++i) {
453 const float q_first = q_pe_tmp[2 * i];
454 const float q_second = q_pe_tmp[2 * i + 1];
455 const float k_first = kp[2 * i];
456 const float k_second = kp[2 * i + 1];
457 const float c = cos_row[i];
458 const float ss = sin_row[i];
459 q_out[qk_nope_dim + i] = q_first * c - q_second * ss;
460 q_out[qk_nope_dim + half + i] = q_second * c + q_first * ss;
461 k_out[qk_nope_dim + i] = k_first * c - k_second * ss;
462 k_out[qk_nope_dim + half + i] = k_second * c + k_first * ss;
463 }
464 }
465 }
466}

References ds_mla_thd_idx().

◆ dequant_q4_0_row()

void dequant_q4_0_row ( const void *  src,
float *  dst,
size_t  n_elements 
)

Dequantize Q4_0 row (multiple blocks)

Parameters
srcQ4_0 data
dstFP32 output
n_elementsNumber of elements to dequantize

Definition at line 63 of file dequant_kernels.c.

64{
65 const block_q4_0 *blocks = (const block_q4_0 *)src;
66 const size_t n_blocks = n_elements / QK4_0;
67
68 for (size_t b = 0; b < n_blocks; b++) {
69 dequant_q4_0_block(&blocks[b], &dst[b * QK4_0]);
70 }
71}
#define QK4_0
void dequant_q4_0_block(const block_q4_0 *block, float *output)
Dequantize a single Q4_0 block to FP32.

References dequant_q4_0_block(), and QK4_0.

◆ dequant_q4_1_row()

void dequant_q4_1_row ( const void *  src,
float *  dst,
size_t  n_elements 
)

Dequantize Q4_1 row (multiple blocks)

Definition at line 141 of file dequant_kernels.c.

142{
143 const block_q4_1 *blocks = (const block_q4_1 *)src;
144 const size_t n_blocks = n_elements / QK4_1;
145
146 for (size_t b = 0; b < n_blocks; b++) {
147 dequant_q4_1_block(&blocks[b], &dst[b * QK4_1]);
148 }
149}
#define QK4_1
void dequant_q4_1_block(const block_q4_1 *block, float *output)
Dequantize a single Q4_1 block to FP32.

References dequant_q4_1_block(), and QK4_1.

Referenced by dequant_row().

◆ dequant_q4_k_row()

void dequant_q4_k_row ( const void *  src,
float *  dst,
size_t  n_elements 
)

Dequantize Q4_K row (multiple blocks)

Definition at line 372 of file dequant_kernels.c.

373{
374 const block_q4_K *blocks = (const block_q4_K *)src;
375 const size_t n_blocks = n_elements / QK_K;
376
377 for (size_t b = 0; b < n_blocks; b++) {
378 dequant_q4_k_block(&blocks[b], &dst[b * QK_K]);
379 }
380}
#define QK_K
void dequant_q4_k_block(const block_q4_K *block, float *output)
Dequantize a single Q4_K block to FP32.

References dequant_q4_k_block(), and QK_K.

Referenced by embedding_forward_q4_k().

◆ dequant_q5_0_row()

void dequant_q5_0_row ( const void *  src,
float *  dst,
size_t  n_elements 
)

Dequantize Q5_0 row (multiple blocks)

Definition at line 198 of file dequant_kernels.c.

199{
200 const block_q5_0 *blocks = (const block_q5_0 *)src;
201 const size_t n_blocks = n_elements / QK5_0;
202
203 for (size_t b = 0; b < n_blocks; b++) {
204 dequant_q5_0_block(&blocks[b], &dst[b * QK5_0]);
205 }
206}
#define QK5_0
void dequant_q5_0_block(const block_q5_0 *block, float *output)
Dequantize a single Q5_0 block to FP32.

References dequant_q5_0_block(), and QK5_0.

Referenced by embedding_forward_q5_0(), moe_relu2_expert_forward_q5_0_q5_0(), moe_relu2_expert_forward_q5_0_q8_0(), and qwen4_ple_ngram_embed_impl().

◆ dequant_q5_1_row()

void dequant_q5_1_row ( const void *  src,
float *  dst,
size_t  n_elements 
)

Dequantize Q5_1 row (multiple blocks)

Definition at line 257 of file dequant_kernels.c.

258{
259 const block_q5_1 *blocks = (const block_q5_1 *)src;
260 const size_t n_blocks = n_elements / QK5_1;
261
262 for (size_t b = 0; b < n_blocks; b++) {
263 dequant_q5_1_block(&blocks[b], &dst[b * QK5_1]);
264 }
265}
#define QK5_1
void dequant_q5_1_block(const block_q5_1 *block, float *output)
Dequantize a single Q5_1 block to FP32.

References dequant_q5_1_block(), and QK5_1.

Referenced by dequant_row(), and moe_relu2_shared_forward_q5_1_q8_0().

◆ dequant_q6_k_row()

void dequant_q6_k_row ( const void *  src,
float *  dst,
size_t  n_elements 
)

Dequantize Q6_K row (multiple blocks)

Definition at line 422 of file dequant_kernels.c.

423{
424 const block_q6_K *blocks = (const block_q6_K *)src;
425 const size_t n_blocks = n_elements / QK_K;
426
427 for (size_t b = 0; b < n_blocks; b++) {
428 dequant_q6_k_block(&blocks[b], &dst[b * QK_K]);
429 }
430}
void dequant_q6_k_block(const block_q6_K *block, float *output)
Dequantize a single Q6_K block to FP32.

References dequant_q6_k_block(), and QK_K.

Referenced by embedding_forward_q6_k().

◆ dequant_q8_0_row()

void dequant_q8_0_row ( const void *  src,
float *  dst,
size_t  n_elements 
)

Dequantize Q8_0 row (multiple blocks)

Definition at line 288 of file dequant_kernels.c.

289{
290 const block_q8_0 *blocks = (const block_q8_0 *)src;
291 const size_t n_blocks = n_elements / QK8_0;
292
293 for (size_t b = 0; b < n_blocks; b++) {
294 dequant_q8_0_block(&blocks[b], &dst[b * QK8_0]);
295 }
296}
void dequant_q8_0_block(const block_q8_0 *block, float *output)
Dequantize a single Q8_0 block to FP32.

References dequant_q8_0_block(), and QK8_0.

Referenced by dequant_row(), embedding_forward_q8_0(), moe_relu2_expert_forward_q5_0_q8_0(), and moe_relu2_shared_forward_q5_1_q8_0().

◆ embedding_backward()

void embedding_backward ( const int32_t *  token_ids,
int  token_count,
const float *  d_output,
float *  d_token_embeddings,
float *  d_pos_embeddings,
int  vocab_size,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 296 of file embedding_kernels.c.

306{
307 if (!token_ids || !d_output || !d_token_embeddings) {
308 return;
309 }
310
311 int tokens = token_count;
312 if (tokens < 0) {
313 tokens = 0;
314 }
315 if (tokens > context_window) {
316 tokens = context_window;
317 }
318
319 for (int t = 0; t < tokens; ++t) {
320 int id = token_ids[t];
321 if (id < 0 || id >= vocab_size) {
322 id = 0;
323 }
324
325 const float *d_out = d_output + (size_t)t * (size_t)aligned_embed_dim;
326 float *d_tok = d_token_embeddings + (size_t)id * (size_t)aligned_embed_dim;
327 float *d_pos = d_pos_embeddings ? (d_pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
328
329 for (int d = 0; d < embed_dim; ++d) {
330 float grad = d_out[d];
331 d_tok[d] += grad;
332 if (add_pos && d_pos) {
333 d_pos[d] += grad;
334 }
335 }
336 }
337}
int vocab_size
Definition true_bpe.h:197

References vocab_size.

◆ embedding_backward_bf16()

void embedding_backward_bf16 ( const int32_t *  token_ids,
int  token_count,
const uint16_t *  d_output,
uint16_t *  d_token_embeddings,
uint16_t *  d_pos_embeddings,
int  vocab_size,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 123 of file embedding_kernels_bf16.c.

133{
134 if (!token_ids || !d_output || !d_token_embeddings) {
135 return;
136 }
137
138 int tokens = token_count;
139 if (tokens < 0) tokens = 0;
140 if (tokens > context_window) tokens = context_window;
141
142 for (int t = 0; t < tokens; ++t) {
143 int id = token_ids[t];
144 if (id < 0 || id >= vocab_size) {
145 id = 0;
146 }
147
148 const uint16_t *d_out = d_output + (size_t)t * (size_t)aligned_embed_dim;
149 uint16_t *d_tok = d_token_embeddings + (size_t)id * (size_t)aligned_embed_dim;
150 uint16_t *d_pos = d_pos_embeddings ? (d_pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
151
152 for (int d = 0; d < embed_dim; ++d) {
153 float grad = bf16_to_float(d_out[d]);
154
155 float cur_tok = bf16_to_float(d_tok[d]);
156 d_tok[d] = float_to_bf16(cur_tok + grad);
157
158 if (add_pos && d_pos) {
159 float cur_pos = bf16_to_float(d_pos[d]);
160 d_pos[d] = float_to_bf16(cur_pos + grad);
161 }
162 }
163 }
164}

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

◆ embedding_backward_bf16_mixed()

void embedding_backward_bf16_mixed ( const int32_t *  token_ids,
int  token_count,
const uint16_t *  d_output,
float *  d_token_embeddings,
float *  d_pos_embeddings,
int  vocab_size,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 166 of file embedding_kernels_bf16.c.

176{
177 if (!token_ids || !d_output || !d_token_embeddings) {
178 return;
179 }
180
181 int tokens = token_count;
182 if (tokens < 0) tokens = 0;
183 if (tokens > context_window) tokens = context_window;
184
185 for (int t = 0; t < tokens; ++t) {
186 int id = token_ids[t];
187 if (id < 0 || id >= vocab_size) {
188 id = 0;
189 }
190
191 const uint16_t *d_out = d_output + (size_t)t * (size_t)aligned_embed_dim;
192 float *d_tok = d_token_embeddings + (size_t)id * (size_t)aligned_embed_dim;
193 float *d_pos = d_pos_embeddings ? (d_pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
194
195 for (int d = 0; d < embed_dim; ++d) {
196 const float grad = bf16_to_float(d_out[d]);
197 d_tok[d] += grad;
198 if (add_pos && d_pos) {
199 d_pos[d] += grad;
200 }
201 }
202 }
203}

References bf16_to_float(), and vocab_size.

◆ embedding_forward()

void embedding_forward ( const int32_t *  token_ids,
int  token_count,
int  vocab_size,
const float *  token_embeddings,
const float *  pos_embeddings,
float *  output,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 22 of file embedding_kernels.c.

32{
33 if (!token_ids || !token_embeddings || !output) {
34 return;
35 }
36
37 int tokens = token_count;
38 if (tokens < 0) {
39 tokens = 0;
40 }
41 if (tokens > context_window) {
42 tokens = context_window;
43 }
44
45 for (int t = 0; t < tokens; ++t) {
46 int id = token_ids[t];
47 if (id < 0 || id >= vocab_size) {
48 id = 0;
49 }
50
51 const float *tok = token_embeddings + (size_t)id * (size_t)aligned_embed_dim;
52 const float *pos = pos_embeddings ? (pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
53 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
54
55 if (add_pos && pos) {
56 for (int d = 0; d < embed_dim; ++d) {
57 out[d] = tok[d] + pos[d];
58 }
59 } else {
60 for (int d = 0; d < embed_dim; ++d) {
61 out[d] = tok[d];
62 }
63 }
64
65 for (int d = embed_dim; d < aligned_embed_dim; ++d) {
66 out[d] = 0.0f;
67 }
68 }
69
70 for (int t = tokens; t < context_window; ++t) {
71 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
72 memset(out, 0, (size_t)aligned_embed_dim * sizeof(float));
73 }
74}

References vocab_size.

◆ embedding_forward_bf16()

void embedding_forward_bf16 ( const int32_t *  token_ids,
int  token_count,
int  vocab_size,
const uint16_t *  token_embeddings,
const uint16_t *  pos_embeddings,
uint16_t *  output,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 21 of file embedding_kernels_bf16.c.

31{
32 if (!token_ids || !token_embeddings || !output) {
33 return;
34 }
35
36 int tokens = token_count;
37 if (tokens < 0) tokens = 0;
38 if (tokens > context_window) tokens = context_window;
39
40 for (int t = 0; t < tokens; ++t) {
41 int id = token_ids[t];
42 if (id < 0 || id >= vocab_size) {
43 id = 0;
44 }
45
46 const uint16_t *tok = token_embeddings + (size_t)id * (size_t)aligned_embed_dim;
47 const uint16_t *pos = pos_embeddings ? (pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
48 uint16_t *out = output + (size_t)t * (size_t)aligned_embed_dim;
49
50 if (add_pos && pos) {
51 for (int d = 0; d < embed_dim; ++d) {
52 float v = bf16_to_float(tok[d]) + bf16_to_float(pos[d]);
53 out[d] = float_to_bf16(v);
54 }
55 } else {
56 for (int d = 0; d < embed_dim; ++d) {
57 out[d] = tok[d];
58 }
59 }
60
61 for (int d = embed_dim; d < aligned_embed_dim; ++d) {
62 out[d] = 0;
63 }
64 }
65
66 for (int t = tokens; t < context_window; ++t) {
67 uint16_t *out = output + (size_t)t * (size_t)aligned_embed_dim;
68 memset(out, 0, (size_t)aligned_embed_dim * sizeof(uint16_t));
69 }
70}

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

◆ embedding_forward_bf16_fp32()

void embedding_forward_bf16_fp32 ( const int32_t *  token_ids,
int  token_count,
int  vocab_size,
const uint16_t *  token_embeddings,
const float *  pos_embeddings,
float *  output,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 73 of file embedding_kernels_bf16.c.

83{
84 if (!token_ids || !token_embeddings || !output) {
85 return;
86 }
87
88 int tokens = token_count;
89 if (tokens < 0) tokens = 0;
90 if (tokens > context_window) tokens = context_window;
91
92 for (int t = 0; t < tokens; ++t) {
93 int id = token_ids[t];
94 if (id < 0 || id >= vocab_size) {
95 id = 0;
96 }
97
98 const uint16_t *tok = token_embeddings + (size_t)id * (size_t)aligned_embed_dim;
99 const float *pos = pos_embeddings ? (pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
100 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
101
102 if (add_pos && pos) {
103 for (int d = 0; d < embed_dim; ++d) {
104 out[d] = bf16_to_float(tok[d]) + pos[d];
105 }
106 } else {
107 for (int d = 0; d < embed_dim; ++d) {
108 out[d] = bf16_to_float(tok[d]);
109 }
110 }
111
112 for (int d = embed_dim; d < aligned_embed_dim; ++d) {
113 out[d] = 0.0f;
114 }
115 }
116
117 for (int t = tokens; t < context_window; ++t) {
118 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
119 memset(out, 0, (size_t)aligned_embed_dim * sizeof(float));
120 }
121}

References bf16_to_float(), and vocab_size.

◆ embedding_forward_q4_k()

void embedding_forward_q4_k ( const int32_t *  token_ids,
int  token_count,
int  vocab_size,
const void *  token_embeddings,
const float *  pos_embeddings,
float *  output,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 76 of file embedding_kernels.c.

86{
87 if (!token_ids || !token_embeddings || !output) {
88 return;
89 }
90
91 int tokens = token_count;
92 if (tokens < 0) {
93 tokens = 0;
94 }
95 if (tokens > context_window) {
96 tokens = context_window;
97 }
98
99 const size_t row_bytes = ck_dtype_row_bytes(CK_DT_Q4_K, (size_t)aligned_embed_dim);
100 const uint8_t *base = (const uint8_t *)token_embeddings;
101
102 for (int t = 0; t < tokens; ++t) {
103 int id = token_ids[t];
104 if (id < 0 || id >= vocab_size) {
105 id = 0;
106 }
107
108 const void *tok = base + (size_t)id * row_bytes;
109 const float *pos = pos_embeddings ? (pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
110 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
111
112 dequant_q4_k_row(tok, out, (size_t)aligned_embed_dim);
113
114 if (add_pos && pos) {
115 for (int d = 0; d < embed_dim; ++d) {
116 out[d] += pos[d];
117 }
118 }
119
120 for (int d = embed_dim; d < aligned_embed_dim; ++d) {
121 out[d] = 0.0f;
122 }
123 }
124
125 for (int t = tokens; t < context_window; ++t) {
126 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
127 memset(out, 0, (size_t)aligned_embed_dim * sizeof(float));
128 }
129}
@ CK_DT_Q4_K
static size_t ck_dtype_row_bytes(CKDataType dt, size_t n_elements)
Calculate total bytes for n_elements of given dtype.
void dequant_q4_k_row(const void *src, float *dst, size_t n_elements)
Dequantize Q4_K row (multiple blocks)

References CK_DT_Q4_K, ck_dtype_row_bytes(), dequant_q4_k_row(), and vocab_size.

Referenced by model_decode_token(), model_decode_token(), model_decode_token(), model_decode_token(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), and qwen2_0_5b_decode_forward_prefill_impl().

◆ embedding_forward_q5_0()

void embedding_forward_q5_0 ( const int32_t *  token_ids,
int  token_count,
int  vocab_size,
const void *  token_embeddings,
const float *  pos_embeddings,
float *  output,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 131 of file embedding_kernels.c.

141{
142 if (!token_ids || !token_embeddings || !output) {
143 return;
144 }
145
146 int tokens = token_count;
147 if (tokens < 0) {
148 tokens = 0;
149 }
150 if (tokens > context_window) {
151 tokens = context_window;
152 }
153
154 const size_t row_bytes = ck_dtype_row_bytes(CK_DT_Q5_0, (size_t)aligned_embed_dim);
155 const uint8_t *base = (const uint8_t *)token_embeddings;
156
157 for (int t = 0; t < tokens; ++t) {
158 int id = token_ids[t];
159 if (id < 0 || id >= vocab_size) {
160 id = 0;
161 }
162
163 const void *tok = base + (size_t)id * row_bytes;
164 const float *pos = pos_embeddings ? (pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
165 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
166
167 dequant_q5_0_row(tok, out, (size_t)aligned_embed_dim);
168
169 if (add_pos && pos) {
170 for (int d = 0; d < embed_dim; ++d) {
171 out[d] += pos[d];
172 }
173 }
174
175 for (int d = embed_dim; d < aligned_embed_dim; ++d) {
176 out[d] = 0.0f;
177 }
178 }
179
180 for (int t = tokens; t < context_window; ++t) {
181 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
182 memset(out, 0, (size_t)aligned_embed_dim * sizeof(float));
183 }
184}
@ CK_DT_Q5_0
void dequant_q5_0_row(const void *src, float *dst, size_t n_elements)
Dequantize Q5_0 row (multiple blocks)

References CK_DT_Q5_0, ck_dtype_row_bytes(), dequant_q5_0_row(), and vocab_size.

◆ embedding_forward_q6_k()

void embedding_forward_q6_k ( const int32_t *  token_ids,
int  token_count,
int  vocab_size,
const void *  token_embeddings,
const float *  pos_embeddings,
float *  output,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 241 of file embedding_kernels.c.

251{
252 if (!token_ids || !token_embeddings || !output) {
253 return;
254 }
255
256 int tokens = token_count;
257 if (tokens < 0) {
258 tokens = 0;
259 }
260 if (tokens > context_window) {
261 tokens = context_window;
262 }
263
264 const size_t row_bytes = ck_dtype_row_bytes(CK_DT_Q6_K, (size_t)aligned_embed_dim);
265 const uint8_t *base = (const uint8_t *)token_embeddings;
266
267 for (int t = 0; t < tokens; ++t) {
268 int id = token_ids[t];
269 if (id < 0 || id >= vocab_size) {
270 id = 0;
271 }
272
273 const void *tok = base + (size_t)id * row_bytes;
274 const float *pos = pos_embeddings ? (pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
275 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
276
277 dequant_q6_k_row(tok, out, (size_t)aligned_embed_dim);
278
279 if (add_pos && pos) {
280 for (int d = 0; d < embed_dim; ++d) {
281 out[d] += pos[d];
282 }
283 }
284
285 for (int d = embed_dim; d < aligned_embed_dim; ++d) {
286 out[d] = 0.0f;
287 }
288 }
289
290 for (int t = tokens; t < context_window; ++t) {
291 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
292 memset(out, 0, (size_t)aligned_embed_dim * sizeof(float));
293 }
294}
@ CK_DT_Q6_K
void dequant_q6_k_row(const void *src, float *dst, size_t n_elements)
Dequantize Q6_K row (multiple blocks)

References CK_DT_Q6_K, ck_dtype_row_bytes(), dequant_q6_k_row(), and vocab_size.

◆ embedding_forward_q8_0()

void embedding_forward_q8_0 ( const int32_t *  token_ids,
int  token_count,
int  vocab_size,
const void *  token_embeddings,
const float *  pos_embeddings,
float *  output,
int  embed_dim,
int  aligned_embed_dim,
int  context_window,
int  add_pos 
)

Definition at line 186 of file embedding_kernels.c.

196{
197 if (!token_ids || !token_embeddings || !output) {
198 return;
199 }
200
201 int tokens = token_count;
202 if (tokens < 0) {
203 tokens = 0;
204 }
205 if (tokens > context_window) {
206 tokens = context_window;
207 }
208
209 const size_t row_bytes = ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)aligned_embed_dim);
210 const uint8_t *base = (const uint8_t *)token_embeddings;
211
212 for (int t = 0; t < tokens; ++t) {
213 int id = token_ids[t];
214 if (id < 0 || id >= vocab_size) {
215 id = 0;
216 }
217
218 const void *tok = base + (size_t)id * row_bytes;
219 const float *pos = pos_embeddings ? (pos_embeddings + (size_t)t * (size_t)aligned_embed_dim) : NULL;
220 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
221
222 dequant_q8_0_row(tok, out, (size_t)aligned_embed_dim);
223
224 if (add_pos && pos) {
225 for (int d = 0; d < embed_dim; ++d) {
226 out[d] += pos[d];
227 }
228 }
229
230 for (int d = embed_dim; d < aligned_embed_dim; ++d) {
231 out[d] = 0.0f;
232 }
233 }
234
235 for (int t = tokens; t < context_window; ++t) {
236 float *out = output + (size_t)t * (size_t)aligned_embed_dim;
237 memset(out, 0, (size_t)aligned_embed_dim * sizeof(float));
238 }
239}
@ CK_DT_Q8_0
void dequant_q8_0_row(const void *src, float *dst, size_t n_elements)
Dequantize Q8_0 row (multiple blocks)

References CK_DT_Q8_0, ck_dtype_row_bytes(), dequant_q8_0_row(), and vocab_size.

Referenced by qwen2_0_5b_decode_decode_token(), and qwen2_0_5b_decode_forward_prefill_impl().

◆ farskip_swiglu_shared_combine_bf16()

void farskip_swiglu_shared_combine_bf16 ( const float *  hidden,
const float *  routed,
const float *  post_attn_residual,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
float *  main_output,
float *  routed_free_output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

Definition at line 3405 of file axpy_kernels.c.

3416{
3417 if (rows <= 0) return;
3419 hidden, routed, post_attn_residual, shared_gate, shared_up, shared_down,
3420 main_output, routed_free_output, rows, hidden_dim, intermediate_dim,
3421 0, rows);
3422}
void farskip_swiglu_shared_combine_bf16_row_range(const float *hidden, const float *routed, const float *post_attn_residual, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *main_output, float *routed_free_output, int rows, int hidden_dim, int intermediate_dim, int row_begin, int row_end)

References farskip_swiglu_shared_combine_bf16_row_range().

◆ farskip_swiglu_shared_combine_bf16_parallel_dispatch()

void farskip_swiglu_shared_combine_bf16_parallel_dispatch ( const float *  hidden,
const float *  routed,
const float *  post_attn_residual,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
float *  main_output,
float *  routed_free_output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

◆ farskip_swiglu_shared_combine_bf16_row_range()

void farskip_swiglu_shared_combine_bf16_row_range ( const float *  hidden,
const float *  routed,
const float *  post_attn_residual,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
float *  main_output,
float *  routed_free_output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  row_begin,
int  row_end 
)

Definition at line 3352 of file axpy_kernels.c.

3366{
3367 if (!hidden || !routed || !post_attn_residual || !shared_gate || !shared_up ||
3368 !shared_down || !main_output || !routed_free_output || rows <= 0 ||
3369 hidden_dim <= 0 || intermediate_dim <= 0 || row_begin < 0 ||
3370 row_begin >= row_end || row_end > rows) {
3371 return;
3372 }
3373
3374 float act[intermediate_dim];
3375
3376 for (int r = row_begin; r < row_end; ++r) {
3377 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
3378 const float *route = routed + (size_t)r * (size_t)hidden_dim;
3379 const float *residual = post_attn_residual + (size_t)r * (size_t)hidden_dim;
3380 float *main = main_output + (size_t)r * (size_t)hidden_dim;
3381 float *routed_free = routed_free_output + (size_t)r * (size_t)hidden_dim;
3382
3383 for (int i = 0; i < intermediate_dim; ++i) {
3384 float gv = 0.0f;
3385 float uv = 0.0f;
3386 for (int h = 0; h < hidden_dim; ++h) {
3387 gv += bf16_to_float(shared_gate[(size_t)i * (size_t)hidden_dim + (size_t)h]) * x[h];
3388 uv += bf16_to_float(shared_up[(size_t)i * (size_t)hidden_dim + (size_t)h]) * x[h];
3389 }
3390 act[i] = ck_moe_silu_f32(gv) * uv;
3391 }
3392
3393 for (int h = 0; h < hidden_dim; ++h) {
3394 float shared = 0.0f;
3395 for (int i = 0; i < intermediate_dim; ++i) {
3396 shared += bf16_to_float(shared_down[(size_t)h * (size_t)intermediate_dim + (size_t)i]) * act[i];
3397 }
3398 const float mlp_output = route[h] + shared;
3399 routed_free[h] = residual[h] + shared;
3400 main[h] = residual[h] + mlp_output;
3401 }
3402 }
3403}
static float ck_moe_silu_f32(float x)
int main(int argc, char **argv)
Definition ck_cli_v5.c:110

References bf16_to_float(), ck_moe_silu_f32(), and main().

Referenced by farskip_swiglu_shared_combine_bf16().

◆ fc1_backward_kernel()

void fc1_backward_kernel ( const float *  d_output,
const float *  fc1_input,
const float *  W_fc1,
float *  d_input,
float *  d_W_fc1,
float *  d_b_fc1,
int  T,
int  aligned_in,
int  aligned_out,
int  num_threads 
)

Definition at line 174 of file mlp_kernels.c.

184{
185 (void)num_threads; // Threading handled by GEMM kernels
186
187 // 1. d_input[T, in] = d_output[T, out] @ W[out, in]
188 // Using gemm_nn: C[M,N] = A[M,K] @ B[K,N]
189 // A = d_output [T, out], B = W [out, in], C = d_input [T, in]
190 // M = T, N = aligned_in, K = aligned_out
191 gemm_nn_simd(d_output, W_fc1, NULL, d_input,
192 T, aligned_in, aligned_out);
193
194 // 2. d_W[out, in] = d_output[T, out].T @ fc1_input[T, in]
195 // Using gemm_tn: C[M,N] = A[K,M].T @ B[K,N]
196 // A = d_output [T, out] (stored as [K=T, M=out]), B = fc1_input [T, in]
197 // C = d_W [out, in], M = aligned_out, N = aligned_in, K = T
198 gemm_tn_parallel(d_output, fc1_input, NULL, d_W_fc1,
199 aligned_out, aligned_in, T);
200
201 // 3. d_b_fc1 = sum_over_T(d_output)
202 for (int out_idx = 0; out_idx < aligned_out; ++out_idx) {
203 float bias_grad = 0.0f;
204 for (int t = 0; t < T; ++t) {
205 bias_grad += d_output[(size_t)t * aligned_out + out_idx];
206 }
207 d_b_fc1[out_idx] += bias_grad;
208 }
209}
void gemm_tn_parallel(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
void gemm_nn_simd(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References gemm_nn_simd(), and gemm_tn_parallel().

Referenced by ck_layer_backward_rmsnorm_swiglu().

◆ fc2_backward_kernel()

void fc2_backward_kernel ( const float *  d_output,
const float *  fc2_input,
const float *  W_fc2,
float *  d_input,
float *  d_W_fc2,
float *  d_b_fc2,
int  T,
int  aligned_in,
int  aligned_out,
int  num_threads 
)

Definition at line 126 of file mlp_kernels.c.

136{
137 (void)num_threads; // Threading handled by GEMM kernels
138
139 // 1. d_input[T, in] = d_output[T, out] @ W[out, in]
140 // Using gemm_nn: C[M,N] = A[M,K] @ B[K,N]
141 // A = d_output [T, out], B = W [out, in], C = d_input [T, in]
142 // M = T, N = aligned_in, K = aligned_out
143 gemm_nn_simd(d_output, W_fc2, NULL, d_input,
144 T, aligned_in, aligned_out);
145
146 // 2. d_W[out, in] = d_output[T, out].T @ fc2_input[T, in]
147 // Using gemm_tn: C[M,N] = A[K,M].T @ B[K,N]
148 // A = d_output [T, out] (stored as [K=T, M=out]), B = fc2_input [T, in]
149 // C = d_W [out, in], M = aligned_out, N = aligned_in, K = T
150 // Note: gemm_tn overwrites, so we need to save and add if accumulating
151 // For now, assume d_W starts zeroed (gradient accumulation handled at higher level)
152 gemm_tn_parallel(d_output, fc2_input, NULL, d_W_fc2,
153 aligned_out, aligned_in, T);
154
155 // 3. d_b_fc2 = sum_over_T(d_output)
156 for (int out_idx = 0; out_idx < aligned_out; ++out_idx) {
157 float bias_grad = 0.0f;
158 for (int t = 0; t < T; ++t) {
159 bias_grad += d_output[(size_t)t * aligned_out + out_idx];
160 }
161 d_b_fc2[out_idx] += bias_grad;
162 }
163}

References gemm_nn_simd(), and gemm_tn_parallel().

Referenced by ck_attention_project_head_major_backward(), ck_layer_backward_rmsnorm_swiglu(), and ck_qkv_project_head_major_backward().

◆ feature_concat()

void feature_concat ( const float *  main_input,
const float *  branch_input,
float *  output,
int  rows,
int  main_dim,
int  branch_slice_dim,
int  num_branch_slices 
)

Definition at line 804 of file vision_kernels.c.

811{
812 if (!main_input || !output || rows <= 0 || main_dim < 0 || branch_slice_dim < 0 || num_branch_slices < 0) {
813 return;
814 }
815
816 const int branch_total_dim = branch_slice_dim * num_branch_slices;
817 const int out_dim = main_dim + branch_total_dim;
818
819 const int in_place_expand = (main_input == output) && (out_dim > main_dim);
820 const int row_start = in_place_expand ? rows - 1 : 0;
821 const int row_end = in_place_expand ? -1 : rows;
822 const int row_step = in_place_expand ? -1 : 1;
823
824 for (int row = row_start; row != row_end; row += row_step) {
825 const float *src_main = main_input + (size_t) row * (size_t) main_dim;
826 float *dst_row = output + (size_t) row * (size_t) out_dim;
827
828 if (main_dim > 0) {
829 memmove(dst_row, src_main, (size_t) main_dim * sizeof(float));
830 }
831
832 for (int slice = 0; slice < num_branch_slices; ++slice) {
833 const float *src_branch = branch_input
834 + (size_t) slice * (size_t) rows * (size_t) branch_slice_dim
835 + (size_t) row * (size_t) branch_slice_dim;
836 float *dst_branch = dst_row + (size_t) main_dim + (size_t) slice * (size_t) branch_slice_dim;
837 if (branch_slice_dim > 0) {
838 memcpy(dst_branch, src_branch, (size_t) branch_slice_dim * sizeof(float));
839 }
840 }
841 }
842}

Referenced by feature_concat_broadcast_rows_f32().

◆ feature_concat_2way()

void feature_concat_2way ( const float *  main_input,
const float *  branch_input,
float *  output,
int  rows,
int  main_dim,
int  branch_slice_dim,
int  num_branch_slices 
)

Definition at line 756 of file vision_kernels.c.

763{
764 if (!main_input || !branch_input || !output || rows <= 0 || main_dim <= 0 ||
765 branch_slice_dim < 0 || num_branch_slices < 0) {
766 return;
767 }
768
769 const int branch_dim = branch_slice_dim * num_branch_slices;
770 const size_t main_bytes = (size_t) main_dim * sizeof(float);
771 const size_t branch_bytes = (size_t) branch_dim * sizeof(float);
772 const size_t out_stride = (size_t) (main_dim + branch_dim);
773
774 for (int r = 0; r < rows; ++r) {
775 const float *src_main = main_input + ((size_t) r * (size_t) main_dim);
776 const float *src_branch = branch_input + ((size_t) r * (size_t) branch_dim);
777 float *dst = output + ((size_t) r * out_stride);
778 memcpy(dst, src_main, main_bytes);
779 memcpy(dst + main_dim, src_branch, branch_bytes);
780 }
781}

◆ feature_slice_copy()

void feature_slice_copy ( const float *  src,
float *  dst,
int  rows,
int  src_dim,
int  dst_dim,
int  dst_feature_offset 
)

Definition at line 783 of file vision_kernels.c.

789{
790 if (!src || !dst || rows <= 0 || src_dim <= 0 || dst_dim <= 0 || dst_feature_offset < 0) {
791 return;
792 }
793 if (dst_feature_offset + src_dim > dst_dim) {
794 return;
795 }
796
797 for (int row = 0; row < rows; ++row) {
798 const float *src_row = src + (size_t) row * (size_t) src_dim;
799 float *dst_row = dst + (size_t) row * (size_t) dst_dim + (size_t) dst_feature_offset;
800 memcpy(dst_row, src_row, (size_t) src_dim * sizeof(float));
801 }
802}

◆ final_logit_scale_f32()

void final_logit_scale_f32 ( float *  logits,
int  tokens,
int  vocab_size,
float  scale 
)

Definition at line 9 of file logit_kernels.c.

13{
14 if (!logits || tokens <= 0 || vocab_size <= 0) {
15 return;
16 }
17
18 const size_t total = (size_t) tokens * (size_t) vocab_size;
19 for (size_t i = 0; i < total; ++i) {
20 logits[i] *= scale;
21 }
22}

References vocab_size.

◆ final_logit_scale_muse_pytorch_bf16_storage()

void final_logit_scale_muse_pytorch_bf16_storage ( float *  logits,
int  tokens,
int  vocab_size,
float  scale 
)

Definition at line 24 of file logit_kernels.c.

28{
29 if (!logits || tokens <= 0 || vocab_size <= 0) {
30 return;
31 }
32
33 const size_t total = (size_t)tokens * (size_t)vocab_size;
34 for (size_t i = 0; i < total; ++i) {
35 const float value = bf16_to_float(float_to_bf16(logits[i]));
36 logits[i] = bf16_to_float(float_to_bf16(value * scale));
37 }
38}

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

◆ final_logit_softcap_muse_pytorch_bf16_storage()

void final_logit_softcap_muse_pytorch_bf16_storage ( float *  logits,
int  tokens,
int  vocab_size,
float  cap 
)

Definition at line 40 of file logit_kernels.c.

44{
45 if (!logits || tokens <= 0 || vocab_size <= 0 || cap <= 0.0f) {
46 return;
47 }
48
49 const size_t total = (size_t)tokens * (size_t)vocab_size;
50 for (size_t i = 0; i < total; ++i) {
51 const float value = bf16_to_float(float_to_bf16(logits[i]));
52 const float divided = bf16_to_float(float_to_bf16(value / cap));
53 const float activated = bf16_to_float(float_to_bf16(tanhf(divided)));
54 logits[i] = bf16_to_float(float_to_bf16(activated * cap));
55 }
56}

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

◆ fused_mlp_swiglu_decode()

void fused_mlp_swiglu_decode ( const float *  x,
const float *  W_gate,
const float *  W_up,
const float *  W_down,
const float *  b_gate,
const float *  b_up,
const float *  b_down,
float *  output,
int  D,
int  Hff 
)

Definition at line 154 of file mlp_fused_decode.c.

165{
166#if defined(__AVX512F__)
167 // Initialize output with bias or zero
168 if (b_down) {
169 memcpy(output, b_down, D * sizeof(float));
170 } else {
171 memset(output, 0, D * sizeof(float));
172 }
173
174 // Process intermediate dimension in tiles
175 // Each tile computes MLP_TILE_SIZE swiglu values and immediately
176 // accumulates them into the output
177
178 /* Bounds check for stack allocation */
179 if (D > 4096) return;
180
181 #pragma omp parallel
182 {
183 /* Thread-local accumulator on stack (no malloc!) */
184 float local_output[4096] __attribute__((aligned(64)));
185 memset(local_output, 0, D * sizeof(float));
186
187 #pragma omp for schedule(static)
188 for (int t = 0; t < Hff; t += MLP_TILE_SIZE) {
189 int tile_end = (t + MLP_TILE_SIZE < Hff) ? t + MLP_TILE_SIZE : Hff;
190 int tile_size = tile_end - t;
191
192 // Compute SwiGLU for this tile (stays in L1 cache)
193 float swiglu_tile[MLP_TILE_SIZE] __attribute__((aligned(64)));
194
195 for (int j = t; j < tile_end; j++) {
196 const float *wg_row = &W_gate[j * D];
197 const float *wu_row = &W_up[j * D];
198
199 // Compute gate = x @ W_gate[j] using AVX-512
200 __m512 gate_acc = _mm512_setzero_ps();
201 __m512 up_acc = _mm512_setzero_ps();
202
203 int k = 0;
204 for (; k <= D - 16; k += 16) {
205 __m512 x_vec = _mm512_loadu_ps(&x[k]);
206 __m512 wg_vec = _mm512_loadu_ps(&wg_row[k]);
207 __m512 wu_vec = _mm512_loadu_ps(&wu_row[k]);
208
209 gate_acc = _mm512_fmadd_ps(x_vec, wg_vec, gate_acc);
210 up_acc = _mm512_fmadd_ps(x_vec, wu_vec, up_acc);
211 }
212
213 float gate = hsum512_ps(gate_acc);
214 float up = hsum512_ps(up_acc);
215
216 // Scalar remainder
217 for (; k < D; k++) {
218 gate += x[k] * wg_row[k];
219 up += x[k] * wu_row[k];
220 }
221
222 // Add biases
223 if (b_gate) gate += b_gate[j];
224 if (b_up) up += b_up[j];
225
226 // SwiGLU: SiLU(gate) * up
227 swiglu_tile[j - t] = silu_scalar(gate) * up;
228 }
229
230 // Accumulate into output via W_down
231 // output[i] += sum_j(swiglu_tile[j] * W_down[i, t+j])
232 for (int i = 0; i < D; i++) {
233 const float *wd_row = &W_down[i * Hff + t];
234
235 __m512 acc = _mm512_setzero_ps();
236 int j = 0;
237 for (; j <= tile_size - 16; j += 16) {
238 __m512 sw_vec = _mm512_loadu_ps(&swiglu_tile[j]);
239 __m512 wd_vec = _mm512_loadu_ps(&wd_row[j]);
240 acc = _mm512_fmadd_ps(sw_vec, wd_vec, acc);
241 }
242
243 float sum = hsum512_ps(acc);
244 for (; j < tile_size; j++) {
245 sum += swiglu_tile[j] * wd_row[j];
246 }
247
248 local_output[i] += sum;
249 }
250 }
251
252 // Reduce thread-local outputs
253 #pragma omp critical
254 {
255 for (int i = 0; i < D; i++) {
256 output[i] += local_output[i];
257 }
258 }
259 /* No free - stack buffer auto-deallocates */
260 }
261
262#else
263 // Scalar fallback (same algorithm, no SIMD)
264 if (b_down) {
265 memcpy(output, b_down, D * sizeof(float));
266 } else {
267 memset(output, 0, D * sizeof(float));
268 }
269
270 for (int t = 0; t < Hff; t += MLP_TILE_SIZE) {
271 int tile_end = (t + MLP_TILE_SIZE < Hff) ? t + MLP_TILE_SIZE : Hff;
272 int tile_size = tile_end - t;
273
274 float swiglu_tile[MLP_TILE_SIZE];
275
276 for (int j = t; j < tile_end; j++) {
277 float gate = 0.0f;
278 float up = 0.0f;
279
280 for (int k = 0; k < D; k++) {
281 gate += x[k] * W_gate[j * D + k];
282 up += x[k] * W_up[j * D + k];
283 }
284
285 if (b_gate) gate += b_gate[j];
286 if (b_up) up += b_up[j];
287
288 swiglu_tile[j - t] = silu_scalar(gate) * up;
289 }
290
291 for (int i = 0; i < D; i++) {
292 for (int j = 0; j < tile_size; j++) {
293 output[i] += swiglu_tile[j] * W_down[i * Hff + t + j];
294 }
295 }
296 }
297#endif
298}
#define MLP_TILE_SIZE
static float silu_scalar(float x)
__attribute__((visibility("default"))) CKTokenizer *ck_tokenizer_create(CKTokenizerType type)

References __attribute__(), MLP_TILE_SIZE, and silu_scalar().

◆ fused_mlp_swiglu_decode_tiled()

void fused_mlp_swiglu_decode_tiled ( const float *  x,
const float *  W_gate,
const float *  W_up,
const float *  W_down,
const float *  b_gate,
const float *  b_up,
const float *  b_down,
float *  output,
int  D,
int  Hff 
)

Definition at line 429 of file mlp_fused_decode.c.

440{
441 // Tile size chosen to fit in L2 with W_down tile
442 // Tile of swiglu: 256 floats = 1KB
443 // Tile of W_down: 256 * D floats = 256 * 896 * 4 = 896KB
444 // Fits in 2MB L2 with room for x and prefetch
445 const int TILE = 256;
446
447#if defined(__AVX512F__)
448 // Initialize output
449 #pragma omp parallel for schedule(static)
450 for (int i = 0; i < D; i++) {
451 output[i] = b_down ? b_down[i] : 0.0f;
452 }
453
454 // Process tiles of intermediate dimension
455 for (int t = 0; t < Hff; t += TILE) {
456 int tile_end = (t + TILE < Hff) ? t + TILE : Hff;
457 int tile_size = tile_end - t;
458
459 // Compute swiglu tile
460 float swiglu_tile[256] __attribute__((aligned(64)));
461
462 #pragma omp parallel for schedule(static)
463 for (int jj = 0; jj < tile_size; jj++) {
464 int j = t + jj;
465 const float *wg_row = &W_gate[j * D];
466 const float *wu_row = &W_up[j * D];
467
468 __m512 gate_acc = _mm512_setzero_ps();
469 __m512 up_acc = _mm512_setzero_ps();
470
471 int k = 0;
472 for (; k <= D - 16; k += 16) {
473 __m512 x_vec = _mm512_loadu_ps(&x[k]);
474 __m512 wg_vec = _mm512_loadu_ps(&wg_row[k]);
475 __m512 wu_vec = _mm512_loadu_ps(&wu_row[k]);
476
477 gate_acc = _mm512_fmadd_ps(x_vec, wg_vec, gate_acc);
478 up_acc = _mm512_fmadd_ps(x_vec, wu_vec, up_acc);
479 }
480
481 float gate = hsum512_ps(gate_acc);
482 float up = hsum512_ps(up_acc);
483
484 for (; k < D; k++) {
485 gate += x[k] * wg_row[k];
486 up += x[k] * wu_row[k];
487 }
488
489 if (b_gate) gate += b_gate[j];
490 if (b_up) up += b_up[j];
491
492 swiglu_tile[jj] = silu_scalar(gate) * up;
493 }
494
495 // Accumulate into output (parallelize over D)
496 #pragma omp parallel for schedule(static)
497 for (int i = 0; i < D; i++) {
498 const float *wd_row = &W_down[i * Hff + t];
499
500 __m512 acc = _mm512_setzero_ps();
501 int j = 0;
502 for (; j <= tile_size - 16; j += 16) {
503 __m512 sw_vec = _mm512_loadu_ps(&swiglu_tile[j]);
504 __m512 wd_vec = _mm512_loadu_ps(&wd_row[j]);
505 acc = _mm512_fmadd_ps(sw_vec, wd_vec, acc);
506 }
507
508 float sum = hsum512_ps(acc);
509 for (; j < tile_size; j++) {
510 sum += swiglu_tile[j] * wd_row[j];
511 }
512
513 // Atomic add (or use thread-local buffers for better perf)
514 #pragma omp atomic
515 output[i] += sum;
516 }
517 }
518
519#else
520 // Scalar fallback
521 for (int i = 0; i < D; i++) {
522 output[i] = b_down ? b_down[i] : 0.0f;
523 }
524
525 for (int t = 0; t < Hff; t += TILE) {
526 int tile_end = (t + TILE < Hff) ? t + TILE : Hff;
527
528 float swiglu_tile[256];
529
530 for (int j = t; j < tile_end; j++) {
531 float gate = 0.0f, up = 0.0f;
532 for (int k = 0; k < D; k++) {
533 gate += x[k] * W_gate[j * D + k];
534 up += x[k] * W_up[j * D + k];
535 }
536 if (b_gate) gate += b_gate[j];
537 if (b_up) up += b_up[j];
538 swiglu_tile[j - t] = silu_scalar(gate) * up;
539 }
540
541 for (int i = 0; i < D; i++) {
542 for (int j = t; j < tile_end; j++) {
543 output[i] += swiglu_tile[j - t] * W_down[i * Hff + j];
544 }
545 }
546 }
547#endif
548}

References __attribute__(), and silu_scalar().

Referenced by fused_mlp_swiglu_decode_v2().

◆ fused_mlp_swiglu_decode_v2()

void fused_mlp_swiglu_decode_v2 ( const float *  x,
const float *  W_gate,
const float *  W_up,
const float *  W_down,
const float *  b_gate,
const float *  b_up,
const float *  b_down,
float *  output,
int  D,
int  Hff 
)

Definition at line 318 of file mlp_fused_decode.c.

329{
330 // For large Hff, use tiled version to avoid stack overflow
331 if (Hff > MAX_SWIGLU_STACK) {
332 fused_mlp_swiglu_decode_tiled(x, W_gate, W_up, W_down,
333 b_gate, b_up, b_down, output, D, Hff);
334 return;
335 }
336
337#if defined(__AVX512F__)
338 // Stack-allocated swiglu buffer (max 32KB)
339 float swiglu[MAX_SWIGLU_STACK] __attribute__((aligned(64)));
340
341 // Phase 1: Compute all swiglu values (parallelize over Hff)
342 #pragma omp parallel for schedule(static)
343 for (int j = 0; j < Hff; j++) {
344 const float *wg_row = &W_gate[j * D];
345 const float *wu_row = &W_up[j * D];
346
347 __m512 gate_acc = _mm512_setzero_ps();
348 __m512 up_acc = _mm512_setzero_ps();
349
350 int k = 0;
351 for (; k <= D - 16; k += 16) {
352 __m512 x_vec = _mm512_loadu_ps(&x[k]);
353 __m512 wg_vec = _mm512_loadu_ps(&wg_row[k]);
354 __m512 wu_vec = _mm512_loadu_ps(&wu_row[k]);
355
356 gate_acc = _mm512_fmadd_ps(x_vec, wg_vec, gate_acc);
357 up_acc = _mm512_fmadd_ps(x_vec, wu_vec, up_acc);
358 }
359
360 float gate = hsum512_ps(gate_acc);
361 float up = hsum512_ps(up_acc);
362
363 for (; k < D; k++) {
364 gate += x[k] * wg_row[k];
365 up += x[k] * wu_row[k];
366 }
367
368 if (b_gate) gate += b_gate[j];
369 if (b_up) up += b_up[j];
370
371 swiglu[j] = silu_scalar(gate) * up;
372 }
373
374 // Phase 2: Down projection (parallelize over D)
375 #pragma omp parallel for schedule(static)
376 for (int i = 0; i < D; i++) {
377 const float *wd_row = &W_down[i * Hff];
378
379 __m512 acc = _mm512_setzero_ps();
380 int j = 0;
381 for (; j <= Hff - 16; j += 16) {
382 __m512 sw_vec = _mm512_loadu_ps(&swiglu[j]);
383 __m512 wd_vec = _mm512_loadu_ps(&wd_row[j]);
384 acc = _mm512_fmadd_ps(sw_vec, wd_vec, acc);
385 }
386
387 float sum = hsum512_ps(acc);
388 for (; j < Hff; j++) {
389 sum += swiglu[j] * wd_row[j];
390 }
391
392 output[i] = sum + (b_down ? b_down[i] : 0.0f);
393 }
394
395#else
396 // Scalar fallback with stack buffer
397 float swiglu[MAX_SWIGLU_STACK];
398
399 for (int j = 0; j < Hff; j++) {
400 float gate = 0.0f, up = 0.0f;
401 for (int k = 0; k < D; k++) {
402 gate += x[k] * W_gate[j * D + k];
403 up += x[k] * W_up[j * D + k];
404 }
405 if (b_gate) gate += b_gate[j];
406 if (b_up) up += b_up[j];
407 swiglu[j] = silu_scalar(gate) * up;
408 }
409
410 for (int i = 0; i < D; i++) {
411 float sum = 0.0f;
412 for (int j = 0; j < Hff; j++) {
413 sum += swiglu[j] * W_down[i * Hff + j];
414 }
415 output[i] = sum + (b_down ? b_down[i] : 0.0f);
416 }
417#endif
418}
void fused_mlp_swiglu_decode_tiled(const float *x, const float *W_gate, const float *W_up, const float *W_down, const float *b_gate, const float *b_up, const float *b_down, float *output, int D, int Hff)
#define MAX_SWIGLU_STACK

References __attribute__(), fused_mlp_swiglu_decode_tiled(), MAX_SWIGLU_STACK, and silu_scalar().

Referenced by ck_mlp_swiglu_forward_fully_fused_token().

◆ fused_mlp_swiglu_prefill()

void fused_mlp_swiglu_prefill ( const float *  x,
const float *  W_gate,
const float *  W_up,
const float *  W_down,
float *  output,
int  seq_len,
int  hidden,
int  intermediate,
float *  scratch 
)

Fused MLP (Gate + Up + SwiGLU + Down) for prefill.

Tiles along token dimension to keep gate/up/hidden in L3 cache.

Parameters
scratchTemporary buffer from fused_mlp_swiglu_scratch_size()

Definition at line 878 of file prefill_fused_gemm.c.

888{
889 fused_mlp_swiglu_prefill_bias(x, W_gate, W_up, W_down,
890 NULL, NULL, NULL,
891 output, seq_len, hidden, intermediate,
892 scratch);
893}
void fused_mlp_swiglu_prefill_bias(const float *x, const float *W_gate, const float *W_up, const float *W_down, const float *B_gate, const float *B_up, const float *B_down, float *output, int seq_len, int hidden, int intermediate, float *scratch)
Fused MLP for prefill with proper tiling.

References fused_mlp_swiglu_prefill_bias().

◆ fused_mlp_swiglu_prefill_bias()

void fused_mlp_swiglu_prefill_bias ( const float *  x,
const float *  W_gate,
const float *  W_up,
const float *  W_down,
const float *  B_gate,
const float *  B_up,
const float *  B_down,
float *  output,
int  seq_len,
int  hidden,
int  intermediate,
float *  scratch 
)

Fused MLP (Gate + Up + SwiGLU + Down) for prefill with biases.

Fused MLP (Gate + Up + SwiGLU + Down) for prefill with biases.

Definition at line 746 of file prefill_fused_gemm.c.

759{
760 /* MLP is more complex because we have:
761 * gate = x @ W_gate
762 * up = x @ W_up
763 * hidden = silu(gate) * up
764 * out = hidden @ W_down
765 *
766 * The intermediate (gate, up, hidden) is large: seq_len × intermediate
767 * For Qwen2-0.5B: 1024 × 4864 × 4 = 19.4MB (way bigger than L3!)
768 *
769 * Strategy: Tile along intermediate dimension for gate/up,
770 * then fuse SwiGLU, then tile down projection.
771 */
772
773 /* scratch layout:
774 * [gate_tile: TILE_M × TILE_N_INTER]
775 * [up_tile: TILE_M × TILE_N_INTER]
776 */
777 const int TILE_N_INTER = 512; /* Intermediate tile size */
778 float *gate_tile = scratch;
779 float *up_tile = scratch + (size_t)PREFILL_TILE_M * TILE_N_INTER;
780 float *hidden_tile = gate_tile; /* Reuse gate_tile for hidden after SwiGLU */
781
782 /* For each chunk of intermediate dimension */
783 for (int inter_start = 0; inter_start < intermediate; inter_start += TILE_N_INTER) {
784 int tile_inter = (inter_start + TILE_N_INTER <= intermediate)
785 ? TILE_N_INTER : (intermediate - inter_start);
786
787 const float *W_gate_tile = W_gate + (size_t)inter_start * hidden;
788 const float *W_up_tile = W_up + (size_t)inter_start * hidden;
789
790 /* For each chunk of tokens */
791 for (int m_start = 0; m_start < seq_len; m_start += PREFILL_TILE_M) {
792 int tile_m = (m_start + PREFILL_TILE_M <= seq_len)
793 ? PREFILL_TILE_M : (seq_len - m_start);
794
795 const float *x_tile = x + (size_t)m_start * hidden;
796
797 /* Compute gate and up projections for this tile */
798 gemm_tile_nt_strided(x_tile, W_gate_tile, gate_tile,
799 tile_m, tile_inter, hidden, tile_inter);
800 gemm_tile_nt_strided(x_tile, W_up_tile, up_tile,
801 tile_m, tile_inter, hidden, tile_inter);
802 if (B_gate) {
803 add_bias_tile(gate_tile, B_gate + inter_start, tile_m, tile_inter);
804 }
805 if (B_up) {
806 add_bias_tile(up_tile, B_up + inter_start, tile_m, tile_inter);
807 }
808
809 /* Fused SwiGLU: hidden = silu(gate) * up */
810 for (int i = 0; i < tile_m; ++i) {
811 float *g = gate_tile + (size_t)i * tile_inter;
812 float *u = up_tile + (size_t)i * tile_inter;
813 for (int j = 0; j < tile_inter; ++j) {
814 float gv = g[j];
815 float silu = gv / (1.0f + expf(-gv));
816 g[j] = silu * u[j]; /* hidden_tile = gate_tile */
817 }
818 }
819
820 /* Down projection: accumulate into output
821 * out[m_start:, :] += hidden_tile @ W_down[inter_start:, :]^T
822 */
823 float *out_tile = output + (size_t)m_start * hidden;
824
825 /* This is trickier - W_down is [hidden × intermediate]
826 * We have hidden_tile[tile_m × tile_inter]
827 * We want out[tile_m × hidden] += hidden_tile × W_down[:, inter_start:inter_start+tile_inter]^T
828 *
829 * For proper accumulation, need to handle this carefully.
830 * For now, use a simpler approach: accumulate partial results.
831 */
832 for (int i = 0; i < tile_m; ++i) {
833 float *h = hidden_tile + (size_t)i * tile_inter;
834 float *o = out_tile + (size_t)i * hidden;
835
836 for (int d = 0; d < hidden; ++d) {
837 const float *w_row = W_down + (size_t)d * intermediate + inter_start;
838 float sum = (inter_start == 0)
839 ? (B_down ? B_down[d] : 0.0f)
840 : o[d];
841
842#if defined(__AVX512F__)
843 __m512 acc = _mm512_setzero_ps();
844 int j = 0;
845 for (; j + 16 <= tile_inter; j += 16) {
846 __m512 hv = _mm512_loadu_ps(h + j);
847 __m512 wv = _mm512_loadu_ps(w_row + j);
848 acc = _mm512_fmadd_ps(hv, wv, acc);
849 }
850 sum += _mm512_reduce_add_ps(acc);
851 for (; j < tile_inter; ++j) {
852 sum += h[j] * w_row[j];
853 }
854#elif defined(__AVX__)
855 __m256 acc = _mm256_setzero_ps();
856 int j = 0;
857 for (; j + 8 <= tile_inter; j += 8) {
858 __m256 hv = _mm256_loadu_ps(h + j);
859 __m256 wv = _mm256_loadu_ps(w_row + j);
860 acc = _mm256_add_ps(acc, _mm256_mul_ps(hv, wv));
861 }
862 sum += hsum256_prefill(acc);
863 for (; j < tile_inter; ++j) {
864 sum += h[j] * w_row[j];
865 }
866#else
867 for (int j = 0; j < tile_inter; ++j) {
868 sum += h[j] * w_row[j];
869 }
870#endif
871 o[d] = sum;
872 }
873 }
874 }
875 }
876}
#define PREFILL_TILE_M
static void add_bias_tile(float *out, const float *bias, int tile_m, int out_dim)
static void gemm_tile_nt_strided(const float *A, const float *B_tile, float *C, int tile_m, int tile_n, int K, int C_stride)
GEMM tile with N-dimension tiling (weight reuse)
static void silu(float *x, int n)

References add_bias_tile(), gemm_tile_nt_strided(), PREFILL_TILE_M, and silu().

Referenced by fused_mlp_swiglu_prefill().

◆ fused_mlp_swiglu_prefill_w1w2_quant()

void fused_mlp_swiglu_prefill_w1w2_quant ( const float *  x,
const void *  W1,
const float *  B1,
CKDataType  w1_dt,
const void *  W2,
const float *  B2,
CKDataType  w2_dt,
float *  output,
int  seq_len,
int  embed_dim,
int  aligned_embed_dim,
int  intermediate_dim,
int  aligned_intermediate_dim,
void *  scratch 
)

Quantized fused MLP for prefill (W1=gate+up, W2=down)

W1 uses Q8_0 activations (Q5_0/Q8_0 weights), W2 uses Q8_K activations (Q4_K/Q6_K weights).

Uses Q8_0 activations for W1 (Q5_0/Q8_0 weights) and Q8_K activations for W2 (Q4_K/Q6_K weights).

Definition at line 964 of file prefill_fused_gemm.c.

979{
980 if (!x || !W1 || !W2 || !output || !scratch) {
981 return;
982 }
983 if (seq_len <= 0 || embed_dim <= 0 || aligned_embed_dim <= 0 ||
984 intermediate_dim <= 0 || aligned_intermediate_dim <= 0) {
985 return;
986 }
987 if (aligned_embed_dim < embed_dim || aligned_intermediate_dim < intermediate_dim) {
988 return;
989 }
990 if ((aligned_embed_dim % 32) != 0 || (aligned_intermediate_dim % 256) != 0) {
991 return;
992 }
993 if (!mlp_q8_0_dtype_supported(w1_dt) || !mlp_q8_k_dtype_supported(w2_dt)) {
994 return;
995 }
996
997 const int tile_m_max = PREFILL_TILE_M;
998 const int inter = aligned_intermediate_dim;
999 const size_t q8_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)aligned_embed_dim);
1000 const size_t q8k_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)aligned_intermediate_dim);
1001 const size_t w1_row_bytes = ck_dtype_row_bytes(w1_dt, (size_t)aligned_embed_dim);
1002
1003 uint8_t *scratch_bytes = (uint8_t *)scratch;
1004 size_t q8_bytes = (size_t)tile_m_max * q8_row_bytes;
1005 size_t gate_bytes = (size_t)tile_m_max * (size_t)inter * sizeof(float);
1006 size_t up_bytes = gate_bytes;
1007 size_t gate_offset = align_up_size(q8_bytes, 64);
1008 size_t up_offset = gate_offset + align_up_size(gate_bytes, 64);
1009 size_t q8k_offset = up_offset + align_up_size(up_bytes, 64);
1010
1011 uint8_t *q8_tile = scratch_bytes;
1012 float *gate_tile = (float *)(scratch_bytes + gate_offset);
1013 float *up_tile = (float *)(scratch_bytes + up_offset);
1014 uint8_t *q8k_tile = scratch_bytes + q8k_offset;
1015
1016 const uint8_t *w1_base = (const uint8_t *)W1;
1017 const uint8_t *w_gate = w1_base;
1018 const uint8_t *w_up = w1_base + (size_t)inter * w1_row_bytes;
1019
1020 const float *b_gate = B1;
1021 const float *b_up = B1 ? (B1 + (size_t)inter) : NULL;
1022
1023 for (int m_start = 0; m_start < seq_len; m_start += tile_m_max) {
1024 int tile_m = (m_start + tile_m_max <= seq_len)
1025 ? tile_m_max : (seq_len - m_start);
1026
1027 const float *x_tile = x + (size_t)m_start * (size_t)aligned_embed_dim;
1028 float *out_tile = output + (size_t)m_start * (size_t)aligned_embed_dim;
1029
1030 for (int t = 0; t < tile_m; ++t) {
1031 const float *row = x_tile + (size_t)t * (size_t)aligned_embed_dim;
1033 q8_tile + (size_t)t * q8_row_bytes,
1034 aligned_embed_dim);
1035 }
1036
1037 gemm_nt_q8_0_mlp_dispatch(q8_tile, w_gate, b_gate, gate_tile,
1038 tile_m, inter, aligned_embed_dim, w1_dt);
1039 gemm_nt_q8_0_mlp_dispatch(q8_tile, w_up, b_up, up_tile,
1040 tile_m, inter, aligned_embed_dim, w1_dt);
1041
1042 for (int i = 0; i < tile_m; ++i) {
1043 float *g = gate_tile + (size_t)i * (size_t)inter;
1044 float *u = up_tile + (size_t)i * (size_t)inter;
1045 for (int j = 0; j < inter; ++j) {
1046 g[j] = silu_prefill(g[j]) * u[j];
1047 }
1048 }
1049
1050 for (int i = 0; i < tile_m; ++i) {
1051 const float *row = gate_tile + (size_t)i * (size_t)inter;
1053 q8k_tile + (size_t)i * q8k_row_bytes,
1054 aligned_intermediate_dim);
1055 }
1056
1057 gemm_nt_q8_k_mlp_dispatch(q8k_tile, W2, B2, out_tile,
1058 tile_m, aligned_embed_dim, aligned_intermediate_dim, w2_dt);
1059 }
1060}
@ CK_DT_Q8_K
void quantize_row_q8_k(const float *x, void *y, int k)
void quantize_row_q8_0(const float *x, void *y, int k)
Quantize FP32 to Q8_0 format (scalar reference)
static void gemm_nt_q8_0_mlp_dispatch(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, CKDataType dt)
static size_t align_up_size(size_t value, size_t align)
static int mlp_q8_k_dtype_supported(CKDataType dt)
static float silu_prefill(float x)
static int mlp_q8_0_dtype_supported(CKDataType dt)
static void gemm_nt_q8_k_mlp_dispatch(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, CKDataType dt)

References align_up_size(), CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), gemm_nt_q8_0_mlp_dispatch(), gemm_nt_q8_k_mlp_dispatch(), mlp_q8_0_dtype_supported(), mlp_q8_k_dtype_supported(), PREFILL_TILE_M, quantize_row_q8_0(), quantize_row_q8_k(), and silu_prefill().

Referenced by mega_fused_outproj_mlp_prefill().

◆ fused_mlp_swiglu_prefill_w1w2_quant_scratch_size()

size_t fused_mlp_swiglu_prefill_w1w2_quant_scratch_size ( int  aligned_embed_dim,
int  aligned_intermediate_dim 
)

Get scratch buffer size for fused_mlp_swiglu_prefill_w1w2_quant.

Definition at line 1062 of file prefill_fused_gemm.c.

1064{
1065 if (aligned_embed_dim <= 0 || aligned_intermediate_dim <= 0) {
1066 return 0;
1067 }
1068 const size_t q8_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)aligned_embed_dim);
1069 const size_t q8k_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)aligned_intermediate_dim);
1070 const size_t q8_bytes = (size_t)PREFILL_TILE_M * q8_row_bytes;
1071 const size_t gate_bytes = (size_t)PREFILL_TILE_M * (size_t)aligned_intermediate_dim * sizeof(float);
1072 const size_t up_bytes = gate_bytes;
1073 const size_t q8k_bytes = (size_t)PREFILL_TILE_M * q8k_row_bytes;
1074
1075 return align_up_size(q8_bytes, 64) +
1076 align_up_size(gate_bytes, 64) +
1077 align_up_size(up_bytes, 64) +
1078 align_up_size(q8k_bytes, 64);
1079}

References align_up_size(), CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), and PREFILL_TILE_M.

Referenced by mega_fused_outproj_mlp_prefill_scratch_size().

◆ fused_mlp_swiglu_scratch_size()

size_t fused_mlp_swiglu_scratch_size ( int  intermediate)

Get scratch buffer size for fused_mlp_swiglu_prefill.

Get scratch buffer size for fused_mlp_swiglu_prefill.

Definition at line 898 of file prefill_fused_gemm.c.

898 {
899 const int TILE_N_INTER = 512;
900 /* gate_tile + up_tile */
901 return 2 * (size_t)PREFILL_TILE_M * TILE_N_INTER * sizeof(float);
902}

References PREFILL_TILE_M.

◆ fused_rmsnorm_qkv_prefill()

void fused_rmsnorm_qkv_prefill ( const float *  x,
const float *  gamma,
const float *  Wq,
const float *  Wk,
const float *  Wv,
float *  Q,
float *  K,
float *  V,
int  seq_len,
int  hidden,
int  q_dim,
int  kv_dim,
float  eps,
float *  scratch 
)

Fused RMSNorm + QKV projection for prefill.

Tiles along token dimension to keep intermediate x_norm in L2 cache. Avoids ~7MB DRAM traffic per layer for seq_len=1024, hidden=896.

Parameters
scratchTemporary buffer from fused_rmsnorm_qkv_scratch_size()

Fused RMSNorm + QKV projection for prefill.

KEY INSIGHT: For Qwen2-0.5B, all QKV weights fit in L3: Wq (896×896) + Wk (128×896) + Wv (128×896) = 4.1MB < 6MB L3

So we use M-tiling (tokens) only:

  1. For each token tile: a. Compute RMSNorm ONCE into scratch (x_norm stays in L2) b. Do all three GEMMs (Q, K, V) against cached x_norm c. Weights stay hot in L3 across all token tiles

This avoids both:

  • Large x_norm intermediate buffer (only TILE_M × hidden in L2)
  • RMSNorm recomputation (done once per token tile, used 3×)

Definition at line 393 of file prefill_fused_gemm.c.

408{
409 /* scratch is x_norm tile: [TILE_M × hidden] fits in L2 */
410
411 /* Process token tiles - weights stay in L3 across all tiles */
412 for (int m_start = 0; m_start < seq_len; m_start += PREFILL_TILE_M) {
413 int tile_m = (m_start + PREFILL_TILE_M <= seq_len)
414 ? PREFILL_TILE_M : (seq_len - m_start);
415
416 const float *x_tile = x + (size_t)m_start * hidden;
417
418 /* Step 1: RMSNorm for this token tile (computed ONCE, used 3×) */
419 rmsnorm_tile(x_tile, gamma, scratch, tile_m, hidden, hidden, eps);
420
421 /* Step 2: Q projection - x_norm is hot in L2, Wq hot in L3 */
422 float *Q_tile = Q + (size_t)m_start * q_dim;
423 gemm_tile_nt_strided(scratch, Wq, Q_tile, tile_m, q_dim, hidden, q_dim);
424
425 /* Step 3: K projection - x_norm still hot, Wk displaces some Wq */
426 float *K_tile = K + (size_t)m_start * kv_dim;
427 gemm_tile_nt_strided(scratch, Wk, K_tile, tile_m, kv_dim, hidden, kv_dim);
428
429 /* Step 4: V projection - x_norm still hot, Wv displaces Wk */
430 float *V_tile = V + (size_t)m_start * kv_dim;
431 gemm_tile_nt_strided(scratch, Wv, V_tile, tile_m, kv_dim, hidden, kv_dim);
432 }
433}
static void rmsnorm_tile(const float *input, const float *gamma, float *output, int tile_m, int embed_dim, int aligned_embed_dim, float eps)
Compute RMSNorm for a tile of tokens.

References gemm_tile_nt_strided(), PREFILL_TILE_M, and rmsnorm_tile().

◆ fused_rmsnorm_qkv_prefill_head_major()

void fused_rmsnorm_qkv_prefill_head_major ( const float *  x,
const float *  gamma,
const float *  Wq,
const float *  Bq,
const float *  Wk,
const float *  Bk,
const float *  Wv,
const float *  Bv,
float *  Q,
float *  K,
float *  V,
int  seq_len,
int  embed_dim,
int  aligned_embed_dim,
int  num_heads,
int  num_kv_heads,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
float  eps,
float *  scratch 
)

Fused RMSNorm + QKV projection for prefill (head-major outputs)

Writes Q as [num_heads, seq_len, aligned_head_dim] and K/V with stride kv_stride_tokens for KV-cache compatibility.

Q is written as [num_heads, seq_len, aligned_head_dim]. K/V are written with kv_stride_tokens for KV-cache compatibility.

Definition at line 441 of file prefill_fused_gemm.c.

460{
461 if (!x || !gamma || !Wq || !Wk || !Wv || !Q || !K || !V || !scratch) {
462 return;
463 }
464 if (seq_len <= 0 || embed_dim <= 0 || aligned_embed_dim <= 0 ||
465 head_dim <= 0 || aligned_head_dim <= 0 ||
466 num_heads <= 0 || num_kv_heads <= 0) {
467 return;
468 }
469 if (kv_stride_tokens < seq_len) {
470 return;
471 }
472
473 const size_t q_head_stride = (size_t)seq_len * (size_t)aligned_head_dim;
474 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
475 const size_t head_w_stride = (size_t)aligned_head_dim * (size_t)aligned_embed_dim;
476
477 for (int m_start = 0; m_start < seq_len; m_start += PREFILL_TILE_M) {
478 int tile_m = (m_start + PREFILL_TILE_M <= seq_len)
479 ? PREFILL_TILE_M : (seq_len - m_start);
480
481 const float *x_tile = x + (size_t)m_start * (size_t)aligned_embed_dim;
482 rmsnorm_tile(x_tile, gamma, scratch, tile_m, embed_dim, aligned_embed_dim, eps);
483
484 for (int h = 0; h < num_heads; ++h) {
485 const float *wq_h = Wq + (size_t)h * head_w_stride;
486 const float *bq_h = Bq ? (Bq + (size_t)h * (size_t)aligned_head_dim) : NULL;
487 float *q_h = Q + (size_t)h * q_head_stride + (size_t)m_start * (size_t)aligned_head_dim;
488
489 gemm_tile_nt_strided(scratch, wq_h, q_h,
490 tile_m, aligned_head_dim, aligned_embed_dim, aligned_head_dim);
491 add_bias_tile(q_h, bq_h, tile_m, aligned_head_dim);
492 }
493
494 for (int h = 0; h < num_kv_heads; ++h) {
495 const float *wk_h = Wk + (size_t)h * head_w_stride;
496 const float *wv_h = Wv + (size_t)h * head_w_stride;
497 const float *bk_h = Bk ? (Bk + (size_t)h * (size_t)aligned_head_dim) : NULL;
498 const float *bv_h = Bv ? (Bv + (size_t)h * (size_t)aligned_head_dim) : NULL;
499 float *k_h = K + (size_t)h * kv_head_stride + (size_t)m_start * (size_t)aligned_head_dim;
500 float *v_h = V + (size_t)h * kv_head_stride + (size_t)m_start * (size_t)aligned_head_dim;
501
502 gemm_tile_nt_strided(scratch, wk_h, k_h,
503 tile_m, aligned_head_dim, aligned_embed_dim, aligned_head_dim);
504 add_bias_tile(k_h, bk_h, tile_m, aligned_head_dim);
505
506 gemm_tile_nt_strided(scratch, wv_h, v_h,
507 tile_m, aligned_head_dim, aligned_embed_dim, aligned_head_dim);
508 add_bias_tile(v_h, bv_h, tile_m, aligned_head_dim);
509 }
510 }
511}

References add_bias_tile(), gemm_tile_nt_strided(), PREFILL_TILE_M, and rmsnorm_tile().

Referenced by mega_fused_attention_prefill(), and mega_fused_attention_prefill_q8_0().

◆ fused_rmsnorm_qkv_prefill_head_major_quant()

void fused_rmsnorm_qkv_prefill_head_major_quant ( const float *  x,
const float *  gamma,
const void *  Wq,
const float *  Bq,
CKDataType  wq_dt,
const void *  Wk,
const float *  Bk,
CKDataType  wk_dt,
const void *  Wv,
const float *  Bv,
CKDataType  wv_dt,
float *  Q,
float *  K,
float *  V,
int  seq_len,
int  embed_dim,
int  aligned_embed_dim,
int  num_heads,
int  num_kv_heads,
int  head_dim,
int  aligned_head_dim,
int  kv_stride_tokens,
float  eps,
void *  scratch 
)

Fused RMSNorm + QKV projection for prefill (head-major, Q8 activations)

Supports Q5_0 or Q8_0 weights with Q8_0 activations.

Supports Q5_0 or Q8_0 weights with Q8_0 activations. Writes K/V directly into KV cache layout (kv_stride_tokens).

Definition at line 519 of file prefill_fused_gemm.c.

538{
539 if (!x || !gamma || !Wq || !Wk || !Wv || !Q || !K || !V || !scratch) {
540 return;
541 }
542 if (seq_len <= 0 || embed_dim <= 0 || aligned_embed_dim <= 0 ||
543 head_dim <= 0 || aligned_head_dim <= 0 ||
544 num_heads <= 0 || num_kv_heads <= 0) {
545 return;
546 }
547 if (aligned_embed_dim % 32 != 0) {
548 return;
549 }
550 if (kv_stride_tokens < seq_len) {
551 return;
552 }
553 /* Determine quantization path: Q8_0 activations for Q5_0/Q8_0 weights,
554 * Q8_K activations for Q4_K/Q6_K weights. All QKV weights must use
555 * the same quantization family. */
556 int use_q8_k_path = qkv_q8_k_dtype_supported(wq_dt);
557 int use_q8_0_path = qkv_q8_0_dtype_supported(wq_dt);
558
559 if (!use_q8_k_path && !use_q8_0_path) {
560 /* Unsupported dtype for wq */
561 return;
562 }
563
564 /* Verify all dtypes are from the same family */
565 if (use_q8_k_path) {
566 if (!qkv_q8_k_dtype_supported(wk_dt) || !qkv_q8_k_dtype_supported(wv_dt)) {
567 return; /* Mixed Q8_K and Q8_0 paths not supported */
568 }
569 } else {
570 if (!qkv_q8_0_dtype_supported(wk_dt) || !qkv_q8_0_dtype_supported(wv_dt)) {
571 return;
572 }
573 }
574
575 const size_t float_bytes = (size_t)PREFILL_TILE_M * (size_t)aligned_embed_dim * sizeof(float);
576 /* Q8_K has larger blocks (256) than Q8_0 (32), so use appropriate size */
577 const CKDataType act_quant_type = use_q8_k_path ? CK_DT_Q8_K : CK_DT_Q8_0;
578 const size_t q8_row_bytes = ck_dtype_row_bytes(act_quant_type, (size_t)aligned_embed_dim);
579 const size_t q8_bytes = (size_t)PREFILL_TILE_M * q8_row_bytes;
580 const size_t q8_offset = align_up_size(float_bytes, 64);
581
582 float *normed = (float *)scratch;
583 uint8_t *q8_tile = (uint8_t *)scratch + q8_offset;
584 (void)q8_bytes;
585
586 const size_t q_head_stride = (size_t)seq_len * (size_t)aligned_head_dim;
587 const size_t kv_head_stride = (size_t)kv_stride_tokens * (size_t)aligned_head_dim;
588 const size_t head_w_elems = (size_t)aligned_head_dim * (size_t)aligned_embed_dim;
589 const size_t wq_head_bytes = ck_dtype_row_bytes(wq_dt, head_w_elems);
590 const size_t wk_head_bytes = ck_dtype_row_bytes(wk_dt, head_w_elems);
591 const size_t wv_head_bytes = ck_dtype_row_bytes(wv_dt, head_w_elems);
592
593 for (int m_start = 0; m_start < seq_len; m_start += PREFILL_TILE_M) {
594 int tile_m = (m_start + PREFILL_TILE_M <= seq_len)
595 ? PREFILL_TILE_M : (seq_len - m_start);
596
597 const float *x_tile = x + (size_t)m_start * (size_t)aligned_embed_dim;
598 rmsnorm_tile(x_tile, gamma, normed, tile_m, embed_dim, aligned_embed_dim, eps);
599
600 /* Quantize activations to appropriate format */
601 for (int t = 0; t < tile_m; ++t) {
602 const float *row = normed + (size_t)t * (size_t)aligned_embed_dim;
603 if (use_q8_k_path) {
605 q8_tile + (size_t)t * q8_row_bytes,
606 aligned_embed_dim);
607 } else {
609 q8_tile + (size_t)t * q8_row_bytes,
610 aligned_embed_dim);
611 }
612 }
613
614 for (int h = 0; h < num_heads; ++h) {
615 const uint8_t *wq_h = (const uint8_t *)Wq + (size_t)h * wq_head_bytes;
616 const float *bq_h = Bq ? (Bq + (size_t)h * (size_t)aligned_head_dim) : NULL;
617 float *q_h = Q + (size_t)h * q_head_stride + (size_t)m_start * (size_t)aligned_head_dim;
618
619 if (use_q8_k_path) {
620 gemm_nt_q8_k_qkv_dispatch(q8_tile, wq_h, bq_h, q_h,
621 tile_m, aligned_head_dim, aligned_embed_dim, wq_dt);
622 } else {
623 gemm_nt_q8_0_dispatch(q8_tile, wq_h, bq_h, q_h,
624 tile_m, aligned_head_dim, aligned_embed_dim, wq_dt);
625 }
626 }
627
628 for (int h = 0; h < num_kv_heads; ++h) {
629 const uint8_t *wk_h = (const uint8_t *)Wk + (size_t)h * wk_head_bytes;
630 const uint8_t *wv_h = (const uint8_t *)Wv + (size_t)h * wv_head_bytes;
631 const float *bk_h = Bk ? (Bk + (size_t)h * (size_t)aligned_head_dim) : NULL;
632 const float *bv_h = Bv ? (Bv + (size_t)h * (size_t)aligned_head_dim) : NULL;
633 float *k_h = K + (size_t)h * kv_head_stride + (size_t)m_start * (size_t)aligned_head_dim;
634 float *v_h = V + (size_t)h * kv_head_stride + (size_t)m_start * (size_t)aligned_head_dim;
635
636 if (use_q8_k_path) {
637 gemm_nt_q8_k_qkv_dispatch(q8_tile, wk_h, bk_h, k_h,
638 tile_m, aligned_head_dim, aligned_embed_dim, wk_dt);
639 gemm_nt_q8_k_qkv_dispatch(q8_tile, wv_h, bv_h, v_h,
640 tile_m, aligned_head_dim, aligned_embed_dim, wv_dt);
641 } else {
642 gemm_nt_q8_0_dispatch(q8_tile, wk_h, bk_h, k_h,
643 tile_m, aligned_head_dim, aligned_embed_dim, wk_dt);
644 gemm_nt_q8_0_dispatch(q8_tile, wv_h, bv_h, v_h,
645 tile_m, aligned_head_dim, aligned_embed_dim, wv_dt);
646 }
647 }
648 }
649}
CKDataType
Supported data types in C-Kernel-Engine.
static void gemm_nt_q8_0_dispatch(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, CKDataType dt)
static int qkv_q8_k_dtype_supported(CKDataType dt)
static void gemm_nt_q8_k_qkv_dispatch(const void *A_q8k, const void *B, const float *bias, float *C, int M, int N, int K, CKDataType dt)
static int qkv_q8_0_dtype_supported(CKDataType dt)

References align_up_size(), CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), gemm_nt_q8_0_dispatch(), gemm_nt_q8_k_qkv_dispatch(), PREFILL_TILE_M, qkv_q8_0_dtype_supported(), qkv_q8_k_dtype_supported(), quantize_row_q8_0(), quantize_row_q8_k(), and rmsnorm_tile().

Referenced by mega_fused_attention_prefill(), and mega_fused_attention_prefill_q8_0().

◆ fused_rmsnorm_qkv_prefill_head_major_quant_scratch_size()

size_t fused_rmsnorm_qkv_prefill_head_major_quant_scratch_size ( int  aligned_embed_dim)

Get scratch buffer size for fused_rmsnorm_qkv_prefill_head_major_quant.

Definition at line 651 of file prefill_fused_gemm.c.

651 {
652 if (aligned_embed_dim <= 0) {
653 return 0;
654 }
655 const size_t float_bytes = (size_t)PREFILL_TILE_M * (size_t)aligned_embed_dim * sizeof(float);
656 /* Use max of Q8_0 and Q8_K sizes to support both paths */
657 const size_t q8_0_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)aligned_embed_dim);
658 const size_t q8_k_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)aligned_embed_dim);
659 const size_t q8_row_bytes = (q8_k_row_bytes > q8_0_row_bytes) ? q8_k_row_bytes : q8_0_row_bytes;
660 const size_t q8_bytes = (size_t)PREFILL_TILE_M * q8_row_bytes;
661 return align_up_size(float_bytes, 64) + q8_bytes;
662}

References align_up_size(), CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), and PREFILL_TILE_M.

Referenced by mega_fused_attention_prefill(), mega_fused_attention_prefill_q8_0(), mega_fused_attention_prefill_q8_0_scratch_size(), and mega_fused_attention_prefill_scratch_size().

◆ fused_rmsnorm_qkv_scratch_size()

size_t fused_rmsnorm_qkv_scratch_size ( int  hidden)

Get scratch buffer size for fused_rmsnorm_qkv_prefill.

Get scratch buffer size for fused_rmsnorm_qkv_prefill.

Definition at line 739 of file prefill_fused_gemm.c.

739 {
740 return (size_t)PREFILL_TILE_M * hidden * sizeof(float);
741}

References PREFILL_TILE_M.

◆ gated_deltanet_autoregressive_backward()

void gated_deltanet_autoregressive_backward ( const float *  d_out,
const float *  d_state_out,
const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
const float *  state_out,
float *  d_q,
float *  d_k,
float *  d_v,
float *  d_g,
float *  d_beta,
float *  d_state_in,
int  num_heads,
int  state_dim,
float  norm_eps 
)

Definition at line 2038 of file deltanet_kernels.c.

2056{
2057 if (!d_out || !d_state_out || !q || !k || !v || !g || !beta || !state_in || !state_out ||
2058 !d_q || !d_k || !d_v || !d_g || !d_beta || !d_state_in) {
2059 return;
2060 }
2061 if (num_heads <= 0 || state_dim <= 0 || state_dim > CK_DELTANET_MAX_STACK_DIM) {
2062 return;
2063 }
2064
2066 d_out,
2067 d_state_out,
2068 q,
2069 k,
2070 v,
2071 g,
2072 beta,
2073 state_in,
2074 state_out,
2075 d_q,
2076 d_k,
2077 d_v,
2078 d_g,
2079 d_beta,
2080 d_state_in,
2081 num_heads,
2082 state_dim,
2083 norm_eps);
2084}
#define CK_DELTANET_MAX_STACK_DIM
void gated_deltanet_autoregressive_backward_ref(const float *d_out, const float *d_state_out, const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, const float *state_out, float *d_q, float *d_k, float *d_v, float *d_g, float *d_beta, float *d_state_in, int num_heads, int state_dim, float norm_eps)

References CK_DELTANET_MAX_STACK_DIM, and gated_deltanet_autoregressive_backward_ref().

◆ gated_deltanet_autoregressive_forward()

void gated_deltanet_autoregressive_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  num_heads,
int  state_dim,
float  norm_eps 
)

Definition at line 1956 of file deltanet_kernels.c.

1967{
1968 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out) {
1969 return;
1970 }
1971 if (num_heads <= 0 || state_dim <= 0) {
1972 return;
1973 }
1974
1975 /*
1976 * q and k arrive pre-normalized by recurrent_qk_l2_norm, so the
1977 * ISA-specialized kernels can follow the same contract as the scalar ref.
1978 */
1981 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1982 return;
1983 }
1984#if defined(__AVX512F__)
1985 gated_deltanet_autoregressive_forward_avx512(
1986 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1987#elif defined(__AVX2__)
1988 gated_deltanet_autoregressive_forward_avx2(
1989 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1990#elif defined(__AVX__)
1991 gated_deltanet_autoregressive_forward_avx(
1992 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1993#else
1995 q, k, v, g, beta, state_in, state_out, out, num_heads, state_dim, norm_eps);
1996#endif
1997}
void gated_deltanet_autoregressive_forward_ref(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int state_dim, float norm_eps)
static int ck_deltanet_force_ref(void)

References ck_deltanet_force_ref(), ck_strict_parity_enabled(), and gated_deltanet_autoregressive_forward_ref().

◆ gated_deltanet_llama_avx2_forward()

void gated_deltanet_llama_avx2_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  num_heads,
int  group_count,
int  state_dim,
float  norm_eps 
)

Definition at line 817 of file deltanet_kernels.c.

829{
831 q, k, v, g, beta, state_in, state_out, out,
832 num_heads, group_count, state_dim, norm_eps, 0, num_heads);
833}
static void gated_deltanet_llama_avx2_grouped_forward_transposed_impl(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps, int head_begin, int head_end)

References gated_deltanet_llama_avx2_grouped_forward_transposed_impl().

Referenced by gated_deltanet_llama_avx2_prefill_forward().

◆ gated_deltanet_llama_avx2_prefill_forward()

void gated_deltanet_llama_avx2_prefill_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  rows,
int  num_heads,
int  group_count,
int  state_dim,
float  norm_eps 
)

Definition at line 1181 of file deltanet_kernels.c.

1194{
1195 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1196 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1197 num_heads % group_count != 0 || state_dim <= 0) {
1198 return;
1199 }
1200 const size_t qk_stride = (size_t) group_count * (size_t) state_dim;
1201 const size_t value_stride = (size_t) num_heads * (size_t) state_dim;
1202 const size_t gate_stride = (size_t) num_heads;
1203 for (int row = 0; row < rows; ++row) {
1205 q + (size_t) row * qk_stride,
1206 k + (size_t) row * qk_stride,
1207 v + (size_t) row * value_stride,
1208 g + (size_t) row * gate_stride,
1209 beta + (size_t) row * gate_stride,
1210 row == 0 ? state_in : state_out,
1211 state_out,
1212 out + (size_t) row * value_stride,
1213 num_heads, group_count, state_dim, norm_eps);
1214 }
1215}
void gated_deltanet_llama_avx2_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps)

References gated_deltanet_llama_avx2_forward().

Referenced by gated_deltanet_llama_chunk64_prefill_forward().

◆ gated_deltanet_llama_chunk64_head_forward()

void gated_deltanet_llama_chunk64_head_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  rows,
int  num_heads,
int  group_count,
int  head,
int  state_dim 
)

Definition at line 1252 of file deltanet_kernels.c.

1265{
1266#if defined(__AVX2__)
1267 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1268 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1269 num_heads % group_count != 0 || head < 0 || head >= num_heads ||
1270 state_dim <= 0 || state_dim > CK_DELTANET_LLAMA_CHUNK_MAX_DIM) {
1271 return;
1272 }
1273 gated_deltanet_llama_chunk64_head(
1274 q, k, v, g, beta, state_in, state_out, out,
1275 rows, num_heads, group_count, head, state_dim);
1276#else
1277 (void)q;
1278 (void)k;
1279 (void)v;
1280 (void)g;
1281 (void)beta;
1282 (void)state_in;
1283 (void)state_out;
1284 (void)out;
1285 (void)rows;
1286 (void)num_heads;
1287 (void)group_count;
1288 (void)head;
1289 (void)state_dim;
1290#endif
1291}
#define CK_DELTANET_LLAMA_CHUNK_MAX_DIM

References CK_DELTANET_LLAMA_CHUNK_MAX_DIM.

◆ gated_deltanet_llama_chunk64_prefill_forward()

void gated_deltanet_llama_chunk64_prefill_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  rows,
int  num_heads,
int  group_count,
int  state_dim,
float  norm_eps 
)

Definition at line 1217 of file deltanet_kernels.c.

1230{
1231 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1232 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1233 num_heads % group_count != 0 || state_dim <= 0) {
1234 return;
1235 }
1236#if defined(__AVX2__)
1237 (void)norm_eps;
1238 if (state_dim <= CK_DELTANET_LLAMA_CHUNK_MAX_DIM) {
1239 for (int head = 0; head < num_heads; ++head) {
1240 gated_deltanet_llama_chunk64_head(
1241 q, k, v, g, beta, state_in, state_out, out,
1242 rows, num_heads, group_count, head, state_dim);
1243 }
1244 return;
1245 }
1246#endif
1248 q, k, v, g, beta, state_in, state_out, out,
1249 rows, num_heads, group_count, state_dim, norm_eps);
1250}
void gated_deltanet_llama_avx2_prefill_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int rows, int num_heads, int group_count, int state_dim, float norm_eps)

References CK_DELTANET_LLAMA_CHUNK_MAX_DIM, and gated_deltanet_llama_avx2_prefill_forward().

◆ gated_deltanet_prefill_forward()

void gated_deltanet_prefill_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  rows,
int  num_heads,
int  state_dim,
float  norm_eps 
)

Definition at line 1999 of file deltanet_kernels.c.

2011{
2012 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out) {
2013 return;
2014 }
2015 if (rows <= 0 || num_heads <= 0 || state_dim <= 0) {
2016 return;
2017 }
2018
2019 const size_t vector_stride = (size_t)num_heads * (size_t)state_dim;
2020 const size_t gate_stride = (size_t)num_heads;
2021 for (int row = 0; row < rows; ++row) {
2022 const float *row_state_in = row == 0 ? state_in : state_out;
2024 q + (size_t)row * vector_stride,
2025 k + (size_t)row * vector_stride,
2026 v + (size_t)row * vector_stride,
2027 g + (size_t)row * gate_stride,
2028 beta + (size_t)row * gate_stride,
2029 row_state_in,
2030 state_out,
2031 out + (size_t)row * vector_stride,
2032 num_heads,
2033 state_dim,
2034 norm_eps);
2035 }
2036}
void gated_deltanet_autoregressive_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int state_dim, float norm_eps)

References gated_deltanet_autoregressive_forward().

◆ gated_deltanet_pytorch_grouped_bf16_forward()

void gated_deltanet_pytorch_grouped_bf16_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  num_heads,
int  group_count,
int  state_dim,
float  norm_eps 
)

Definition at line 1139 of file deltanet_kernels.c.

1151{
1153 q, k, v, g, beta, state_in, state_out, out,
1154 NULL, NULL, NULL,
1155 num_heads, group_count, state_dim, norm_eps);
1156}
static void gated_deltanet_pytorch_grouped_bf16_forward_impl(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, float *debug_decayed_state, float *debug_memory, float *debug_delta, int num_heads, int group_count, int state_dim, float norm_eps)

References gated_deltanet_pytorch_grouped_bf16_forward_impl().

Referenced by gated_deltanet_pytorch_grouped_bf16_prefill_forward().

◆ gated_deltanet_pytorch_grouped_bf16_prefill_forward()

void gated_deltanet_pytorch_grouped_bf16_prefill_forward ( const float *  q,
const float *  k,
const float *  v,
const float *  g,
const float *  beta,
const float *  state_in,
float *  state_out,
float *  out,
int  rows,
int  num_heads,
int  group_count,
int  state_dim,
float  norm_eps 
)

Definition at line 1293 of file deltanet_kernels.c.

1307{
1308 if (!q || !k || !v || !g || !beta || !state_in || !state_out || !out ||
1309 rows <= 0 || num_heads <= 0 || group_count <= 0 ||
1310 num_heads % group_count != 0 || state_dim <= 0) {
1311 return;
1312 }
1313 const size_t qk_stride = (size_t)group_count * (size_t)state_dim;
1314 const size_t value_stride = (size_t)num_heads * (size_t)state_dim;
1315 const size_t gate_stride = (size_t)num_heads;
1316 for (int row = 0; row < rows; ++row) {
1318 q + (size_t)row * qk_stride,
1319 k + (size_t)row * qk_stride,
1320 v + (size_t)row * value_stride,
1321 g + (size_t)row * gate_stride,
1322 beta + (size_t)row * gate_stride,
1323 row == 0 ? state_in : state_out,
1324 state_out,
1325 out + (size_t)row * value_stride,
1326 num_heads, group_count, state_dim, norm_eps);
1327 }
1328}
void gated_deltanet_pytorch_grouped_bf16_forward(const float *q, const float *k, const float *v, const float *g, const float *beta, const float *state_in, float *state_out, float *out, int num_heads, int group_count, int state_dim, float norm_eps)

References gated_deltanet_pytorch_grouped_bf16_forward().

◆ geglu_backward_bf16_mixed()

void geglu_backward_bf16_mixed ( const uint16_t *  x,
const uint16_t *  d_out,
float *  d_x,
int  tokens,
int  dim 
)

Definition at line 154 of file geglu_kernels.c.

159{
160 if (!x || !d_out || !d_x || tokens <= 0 || dim <= 0) {
161 return;
162 }
163
164 const float sqrt_2_over_pi = 0.7978845608f;
165 const float coeff = 0.044715f;
166 const int inner_dim = dim * 2;
167
168 for (int t = 0; t < tokens; ++t) {
169 const uint16_t *x_ptr = x + (size_t)t * (size_t)inner_dim;
170 const uint16_t *d_out_ptr = d_out + (size_t)t * (size_t)dim;
171 float *d_x_ptr = d_x + (size_t)t * (size_t)inner_dim;
172
173 for (int d = 0; d < dim; ++d) {
174 const float a = bf16_to_float(x_ptr[d]);
175 const float b = bf16_to_float(x_ptr[dim + d]);
176 const float dout = bf16_to_float(d_out_ptr[d]);
177
178 const float a2 = a * a;
179 const float a3 = a2 * a;
180 const float g = sqrt_2_over_pi * (a + coeff * a3);
181 const float tanh_g = tanhf(g);
182 const float sech2_g = 1.0f - tanh_g * tanh_g;
183 const float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * a2);
184
185 const float d_gelu = 0.5f * (1.0f + tanh_g) + 0.5f * a * sech2_g * g_prime;
186 d_x_ptr[d] = dout * d_gelu * b;
187
188 const float gelu_a = 0.5f * a * (1.0f + tanh_g);
189 d_x_ptr[dim + d] = dout * gelu_a;
190 }
191 }
192}

References bf16_to_float().

◆ geglu_backward_fp32()

void geglu_backward_fp32 ( const float *  x,
const float *  d_out,
float *  d_x,
int  tokens,
int  dim 
)

Definition at line 114 of file geglu_kernels.c.

119{
120 if (!x || !d_out || !d_x || tokens <= 0 || dim <= 0) {
121 return;
122 }
123
124 const float sqrt_2_over_pi = 0.7978845608f;
125 const float coeff = 0.044715f;
126 const int inner_dim = dim * 2;
127
128 for (int t = 0; t < tokens; ++t) {
129 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
130 const float *d_out_ptr = d_out + (size_t)t * (size_t)dim;
131 float *d_x_ptr = d_x + (size_t)t * (size_t)inner_dim;
132
133 for (int d = 0; d < dim; ++d) {
134 float a = x_ptr[d];
135 float b = x_ptr[dim + d];
136 float dout = d_out_ptr[d];
137
138 float a2 = a * a;
139 float a3 = a2 * a;
140 float g = sqrt_2_over_pi * (a + coeff * a3);
141 float tanh_g = tanhf(g);
142 float sech2_g = 1.0f - tanh_g * tanh_g;
143 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * a2);
144
145 float d_gelu = 0.5f * (1.0f + tanh_g) + 0.5f * a * sech2_g * g_prime;
146 d_x_ptr[d] = dout * d_gelu * b;
147
148 float gelu_a = 0.5f * a * (1.0f + tanh_g);
149 d_x_ptr[dim + d] = dout * gelu_a;
150 }
151 }
152}

◆ geglu_forward_bf16()

void geglu_forward_bf16 ( const uint16_t *  x,
uint16_t *  out,
int  tokens,
int  dim,
float *  scratch 
)

Definition at line 98 of file geglu_kernels.c.

99{
100 if (!x || !out || !scratch || tokens <= 0 || dim <= 0) {
101 return;
102 }
103
104 const size_t fp32_size = (size_t)tokens * (size_t)dim;
105 const size_t input_size = fp32_size * 2;
106 float *fp32_input = scratch;
107 float *fp32_output = scratch + input_size;
108
109 bf16_tensor_to_float(x, fp32_input, input_size);
110 geglu_forward_fp32(fp32_input, fp32_output, tokens, dim);
111 float_tensor_to_bf16(fp32_output, out, fp32_size);
112}
void geglu_forward_fp32(const float *x, float *out, int tokens, int dim)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and geglu_forward_fp32().

◆ geglu_forward_exact()

void geglu_forward_exact ( const float *  x,
float *  out,
int  tokens,
int  dim 
)

Definition at line 42 of file geglu_kernels.c.

43{
44 const int inner_dim = dim * 2;
45 for (int t = 0; t < tokens; ++t) {
46 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
47 float *out_ptr = out + (size_t)t * (size_t)dim;
48
49 for (int d = 0; d < dim; ++d) {
50 out_ptr[d] = ck_gelu_tanh_parity_f32(x_ptr[d]) * x_ptr[dim + d];
51 }
52 }
53}
static float ck_gelu_tanh_parity_f32(float x)

References ck_gelu_tanh_parity_f32().

Referenced by geglu_forward_fp32().

◆ geglu_forward_fp32()

void geglu_forward_fp32 ( const float *  x,
float *  out,
int  tokens,
int  dim 
)

Definition at line 70 of file geglu_kernels.c.

71{
72 if (!x || !out || tokens <= 0 || dim <= 0) {
73 return;
74 }
75
77 geglu_forward_exact(x, out, tokens, dim);
78 return;
79 }
80
81 const int inner_dim = dim * 2;
82 for (int t = 0; t < tokens; ++t) {
83 const float *x_ptr = x + (size_t)t * (size_t)inner_dim;
84 float *out_ptr = out + (size_t)t * (size_t)dim;
85
86 for (int d = 0; d < dim; ++d) {
87 out_ptr[d] = x_ptr[d];
88 }
89
90 gelu_fast_inplace(out_ptr, (size_t)dim);
91
92 for (int d = 0; d < dim; ++d) {
93 out_ptr[d] *= x_ptr[dim + d];
94 }
95 }
96}
void geglu_forward_exact(const float *x, float *out, int tokens, int dim)
void gelu_fast_inplace(float *data, size_t n)

References ck_strict_parity_enabled(), geglu_forward_exact(), and gelu_fast_inplace().

Referenced by geglu_forward_bf16().

◆ geglu_forward_ggml_native()

void geglu_forward_ggml_native ( const float *  x,
float *  out,
int  tokens,
int  dim 
)

Definition at line 17 of file geglu_kernels.c.

18{
19 if (!x || !out || tokens <= 0 || dim <= 0) return;
20 /* Preserve ascending compaction when output aliases the gate/up input. */
21 for (int t = 0; t < tokens; ++t) {
22 const float *row = x + (size_t)t * (size_t)dim * 2;
23 float *dst = out + (size_t)t * dim;
24 for (int d = 0; d < dim; ++d) {
25 const float gate = row[d], up = row[dim + d];
26 float value = gate;
27 gelu_ggml_native_inplace(&value, 1);
28 dst[d] = gate <= -10.0f ? 0.0f : value * up;
29 }
30 }
31}
void gelu_ggml_native_inplace(float *data, size_t n)

References gelu_ggml_native_inplace().

◆ geglu_forward_quick()

void geglu_forward_quick ( const float *  x,
float *  out,
int  tokens,
int  dim 
)

Definition at line 55 of file geglu_kernels.c.

56{
57 if (!x || !out || tokens <= 0 || dim <= 0) return;
58 const size_t inner_dim = (size_t)dim * 2u;
59 /* Ascending compaction also permits input and output to alias. */
60 for (int t = 0; t < tokens; ++t) {
61 const float *row = x + (size_t)t * inner_dim;
62 float *dst = out + (size_t)t * (size_t)dim;
63 for (int d = 0; d < dim; ++d) {
64 const float gate = row[d];
65 dst[d] = (gate * (1.0f / (1.0f + expf(-1.702f * gate)))) * row[dim + d];
66 }
67 }
68}

◆ gelu_backward_exact()

void gelu_backward_exact ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 369 of file gelu_kernels.c.

373{
374 const float sqrt_2_over_pi = 0.7978845608f;
375 const float coeff = 0.044715f;
376
377#if defined(__AVX512F__)
378 const __m512 sqrt_2_pi_vec = _mm512_set1_ps(sqrt_2_over_pi);
379 const __m512 coeff_vec = _mm512_set1_ps(coeff);
380 const __m512 coeff3_vec = _mm512_set1_ps(3.0f * coeff);
381 const __m512 half_vec = _mm512_set1_ps(0.5f);
382 const __m512 one_vec = _mm512_set1_ps(1.0f);
383
384 size_t i = 0;
385 for (; i + 16 <= n; i += 16) {
386 __m512 x = _mm512_loadu_ps(&input[i]);
387 __m512 dy = _mm512_loadu_ps(&d_output[i]);
388
389 __m512 x2 = _mm512_mul_ps(x, x);
390 __m512 x3 = _mm512_mul_ps(x2, x);
391
392 // g = sqrt(2/pi) * (x + 0.044715 * x^3)
393 __m512 g = _mm512_fmadd_ps(coeff_vec, x3, x);
394 g = _mm512_mul_ps(sqrt_2_pi_vec, g);
395
396 __m512 tanh_g = tanh512_fast(g);
397
398 // g' = sqrt(2/pi) * (1 + 3 * 0.044715 * x^2)
399 __m512 g_prime = _mm512_fmadd_ps(coeff3_vec, x2, one_vec);
400 g_prime = _mm512_mul_ps(sqrt_2_pi_vec, g_prime);
401
402 // sech^2(g) = 1 - tanh^2(g)
403 __m512 sech2_g = _mm512_fnmadd_ps(tanh_g, tanh_g, one_vec);
404
405 // gelu_derivative = 0.5 * (1 + tanh_g) + 0.5 * x * sech2_g * g_prime
406 __m512 term1 = _mm512_mul_ps(half_vec, _mm512_add_ps(one_vec, tanh_g));
407 __m512 term2 = _mm512_mul_ps(half_vec, _mm512_mul_ps(x, _mm512_mul_ps(sech2_g, g_prime)));
408 __m512 gelu_deriv = _mm512_add_ps(term1, term2);
409
410 __m512 result = _mm512_mul_ps(dy, gelu_deriv);
411 _mm512_storeu_ps(&d_input[i], result);
412 }
413 // Handle remaining elements
414 for (; i < n; ++i) {
415 float x = input[i];
416 float x3 = x * x * x;
417 float g = sqrt_2_over_pi * (x + coeff * x3);
418 float tanh_g = tanhf(g);
419 float x2 = x * x;
420 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
421 float sech2_g = 1.0f - tanh_g * tanh_g;
422 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
423 d_input[i] = d_output[i] * gelu_derivative;
424 }
425
426#elif defined(__AVX2__)
427 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
428 const __m256 coeff_vec = _mm256_set1_ps(coeff);
429 const __m256 coeff3_vec = _mm256_set1_ps(3.0f * coeff);
430 const __m256 half_vec = _mm256_set1_ps(0.5f);
431 const __m256 one_vec = _mm256_set1_ps(1.0f);
432
433 size_t i = 0;
434 for (; i + 8 <= n; i += 8) {
435 __m256 x = _mm256_loadu_ps(&input[i]);
436 __m256 dy = _mm256_loadu_ps(&d_output[i]);
437
438 __m256 x2 = _mm256_mul_ps(x, x);
439 __m256 x3 = _mm256_mul_ps(x2, x);
440
441 // g = sqrt(2/pi) * (x + 0.044715 * x^3)
442 __m256 g = _mm256_fmadd_ps(coeff_vec, x3, x);
443 g = _mm256_mul_ps(sqrt_2_pi_vec, g);
444
445 __m256 tanh_g = tanh256_fast(g);
446
447 // g' = sqrt(2/pi) * (1 + 3 * 0.044715 * x^2)
448 __m256 g_prime = _mm256_fmadd_ps(coeff3_vec, x2, one_vec);
449 g_prime = _mm256_mul_ps(sqrt_2_pi_vec, g_prime);
450
451 // sech^2(g) = 1 - tanh^2(g)
452 __m256 sech2_g = _mm256_fnmadd_ps(tanh_g, tanh_g, one_vec);
453
454 // gelu_derivative = 0.5 * (1 + tanh_g) + 0.5 * x * sech2_g * g_prime
455 __m256 term1 = _mm256_mul_ps(half_vec, _mm256_add_ps(one_vec, tanh_g));
456 __m256 term2 = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, _mm256_mul_ps(sech2_g, g_prime)));
457 __m256 gelu_deriv = _mm256_add_ps(term1, term2);
458
459 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
460 _mm256_storeu_ps(&d_input[i], result);
461 }
462 // Handle remaining elements
463 for (; i < n; ++i) {
464 float x = input[i];
465 float x3 = x * x * x;
466 float g = sqrt_2_over_pi * (x + coeff * x3);
467 float tanh_g = tanhf(g);
468 float x2 = x * x;
469 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
470 float sech2_g = 1.0f - tanh_g * tanh_g;
471 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
472 d_input[i] = d_output[i] * gelu_derivative;
473 }
474
475#elif defined(__AVX__)
476 // AVX1: Vectorize arithmetic, use scalar tanh
477 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
478 const __m256 coeff_vec = _mm256_set1_ps(coeff);
479 const __m256 coeff3_vec = _mm256_set1_ps(3.0f * coeff);
480 const __m256 half_vec = _mm256_set1_ps(0.5f);
481 const __m256 one_vec = _mm256_set1_ps(1.0f);
482
483 size_t i = 0;
484 float g_arr[8] __attribute__((aligned(32)));
485 float tanh_arr[8] __attribute__((aligned(32)));
486
487 for (; i + 8 <= n; i += 8) {
488 __m256 x = _mm256_loadu_ps(&input[i]);
489 __m256 dy = _mm256_loadu_ps(&d_output[i]);
490
491 __m256 x2 = _mm256_mul_ps(x, x);
492 __m256 x3 = _mm256_mul_ps(x2, x);
493
494 // g = sqrt(2/pi) * (x + 0.044715 * x^3)
495 __m256 coeff_x3 = _mm256_mul_ps(coeff_vec, x3);
496 __m256 g = _mm256_mul_ps(sqrt_2_pi_vec, _mm256_add_ps(x, coeff_x3));
497
498 // Compute tanh scalarly
499 _mm256_store_ps(g_arr, g);
500 for (int j = 0; j < 8; ++j) {
501 tanh_arr[j] = tanhf(g_arr[j]);
502 }
503 __m256 tanh_g = _mm256_load_ps(tanh_arr);
504
505 // g' = sqrt(2/pi) * (1 + 3 * 0.044715 * x^2)
506 __m256 coeff3_x2 = _mm256_mul_ps(coeff3_vec, x2);
507 __m256 g_prime = _mm256_mul_ps(sqrt_2_pi_vec, _mm256_add_ps(one_vec, coeff3_x2));
508
509 // sech^2(g) = 1 - tanh^2(g)
510 __m256 tanh_g_sq = _mm256_mul_ps(tanh_g, tanh_g);
511 __m256 sech2_g = _mm256_sub_ps(one_vec, tanh_g_sq);
512
513 // gelu_derivative = 0.5 * (1 + tanh_g) + 0.5 * x * sech2_g * g_prime
514 __m256 term1 = _mm256_mul_ps(half_vec, _mm256_add_ps(one_vec, tanh_g));
515 __m256 term2 = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, _mm256_mul_ps(sech2_g, g_prime)));
516 __m256 gelu_deriv = _mm256_add_ps(term1, term2);
517
518 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
519 _mm256_storeu_ps(&d_input[i], result);
520 }
521 // Handle remaining elements
522 for (; i < n; ++i) {
523 float x = input[i];
524 float x3 = x * x * x;
525 float g = sqrt_2_over_pi * (x + coeff * x3);
526 float tanh_g = tanhf(g);
527 float x2 = x * x;
528 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
529 float sech2_g = 1.0f - tanh_g * tanh_g;
530 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
531 d_input[i] = d_output[i] * gelu_derivative;
532 }
533
534#else
535 // Scalar fallback
536 for (size_t i = 0; i < n; ++i) {
537 float x = input[i];
538
539 float x3 = x * x * x;
540 float g = sqrt_2_over_pi * (x + coeff * x3);
541 float tanh_g = tanhf(g);
542
543 float x2 = x * x;
544 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
545
546 float sech2_g = 1.0f - tanh_g * tanh_g;
547 float gelu_derivative =
548 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
549
550 d_input[i] = d_output[i] * gelu_derivative;
551 }
552#endif
553}

References __attribute__().

◆ gelu_backward_exact_bf16()

void gelu_backward_exact_bf16 ( const uint16_t *  input,
const uint16_t *  d_output,
uint16_t *  d_input,
size_t  n,
float *  scratch_input,
float *  scratch_d_output,
float *  scratch_d_input 
)

Definition at line 46 of file gelu_kernels_bf16.c.

53{
54 if (!scratch_input || !scratch_d_output || !scratch_d_input) return;
55
56 bf16_tensor_to_float(input, scratch_input, n);
57 bf16_tensor_to_float(d_output, scratch_d_output, n);
58
59 // Use scalar exact version to avoid fast tanh approximation error
60 // accumulating with BF16 precision loss.
61 gelu_backward_scalar(scratch_input, scratch_d_output, scratch_d_input, n);
62
63 float_tensor_to_bf16(scratch_d_input, d_input, n);
64}
void gelu_backward_scalar(const float *input, const float *d_output, float *d_input, size_t n)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and gelu_backward_scalar().

◆ gelu_backward_fast()

void gelu_backward_fast ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 870 of file gelu_kernels.c.

874{
875 const float beta = 1.702f;
876
877#if defined(__AVX512F__)
878 const __m512 beta_vec = _mm512_set1_ps(beta);
879 const __m512 one_vec = _mm512_set1_ps(1.0f);
880 const __m512 neg_beta_vec = _mm512_set1_ps(-beta);
881
882 size_t i = 0;
883 for (; i + 16 <= n; i += 16) {
884 __m512 x = _mm512_loadu_ps(&input[i]);
885 __m512 dy = _mm512_loadu_ps(&d_output[i]);
886
887 // s = sigmoid(beta * x) = 1 / (1 + exp(-beta * x))
888 __m512 neg_beta_x = _mm512_mul_ps(neg_beta_vec, x);
889 __m512 exp_neg = exp512_fast(neg_beta_x);
890 __m512 s = _mm512_div_ps(one_vec, _mm512_add_ps(one_vec, exp_neg));
891
892 // gelu_derivative = s * (1 + x * (1 - s) * beta)
893 __m512 one_minus_s = _mm512_sub_ps(one_vec, s);
894 __m512 inner = _mm512_fmadd_ps(_mm512_mul_ps(x, one_minus_s), beta_vec, one_vec);
895 __m512 gelu_deriv = _mm512_mul_ps(s, inner);
896
897 __m512 result = _mm512_mul_ps(dy, gelu_deriv);
898 _mm512_storeu_ps(&d_input[i], result);
899 }
900 // Handle remaining elements
901 for (; i < n; ++i) {
902 float x = input[i];
903 float s = 1.0f / (1.0f + expf(-beta * x));
904 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
905 d_input[i] = d_output[i] * gelu_derivative;
906 }
907
908#elif defined(__AVX2__)
909 const __m256 beta_vec = _mm256_set1_ps(beta);
910 const __m256 one_vec = _mm256_set1_ps(1.0f);
911 const __m256 neg_beta_vec = _mm256_set1_ps(-beta);
912
913 size_t i = 0;
914 for (; i + 8 <= n; i += 8) {
915 __m256 x = _mm256_loadu_ps(&input[i]);
916 __m256 dy = _mm256_loadu_ps(&d_output[i]);
917
918 // s = sigmoid(beta * x) = 1 / (1 + exp(-beta * x))
919 __m256 neg_beta_x = _mm256_mul_ps(neg_beta_vec, x);
920 __m256 exp_neg = exp256_fast(neg_beta_x);
921 __m256 s = _mm256_div_ps(one_vec, _mm256_add_ps(one_vec, exp_neg));
922
923 // gelu_derivative = s * (1 + x * (1 - s) * beta)
924 __m256 one_minus_s = _mm256_sub_ps(one_vec, s);
925 __m256 inner = _mm256_fmadd_ps(_mm256_mul_ps(x, one_minus_s), beta_vec, one_vec);
926 __m256 gelu_deriv = _mm256_mul_ps(s, inner);
927
928 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
929 _mm256_storeu_ps(&d_input[i], result);
930 }
931 // Handle remaining elements
932 for (; i < n; ++i) {
933 float x = input[i];
934 float s = 1.0f / (1.0f + expf(-beta * x));
935 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
936 d_input[i] = d_output[i] * gelu_derivative;
937 }
938
939#elif defined(__AVX__)
940 // AVX1: Vectorize arithmetic, use scalar exp
941 const __m256 beta_vec = _mm256_set1_ps(beta);
942 const __m256 one_vec = _mm256_set1_ps(1.0f);
943 const __m256 neg_beta_vec = _mm256_set1_ps(-beta);
944
945 size_t i = 0;
946 float neg_beta_x_arr[8] __attribute__((aligned(32)));
947 float exp_arr[8] __attribute__((aligned(32)));
948
949 for (; i + 8 <= n; i += 8) {
950 __m256 x = _mm256_loadu_ps(&input[i]);
951 __m256 dy = _mm256_loadu_ps(&d_output[i]);
952
953 // s = sigmoid(beta * x) = 1 / (1 + exp(-beta * x))
954 __m256 neg_beta_x = _mm256_mul_ps(neg_beta_vec, x);
955
956 // Compute exp scalarly
957 _mm256_store_ps(neg_beta_x_arr, neg_beta_x);
958 for (int j = 0; j < 8; ++j) {
959 exp_arr[j] = expf(neg_beta_x_arr[j]);
960 }
961 __m256 exp_neg = _mm256_load_ps(exp_arr);
962
963 __m256 s = _mm256_div_ps(one_vec, _mm256_add_ps(one_vec, exp_neg));
964
965 // gelu_derivative = s * (1 + x * (1 - s) * beta)
966 __m256 one_minus_s = _mm256_sub_ps(one_vec, s);
967 __m256 x_one_minus_s = _mm256_mul_ps(x, one_minus_s);
968 __m256 x_one_minus_s_beta = _mm256_mul_ps(x_one_minus_s, beta_vec);
969 __m256 inner = _mm256_add_ps(one_vec, x_one_minus_s_beta);
970 __m256 gelu_deriv = _mm256_mul_ps(s, inner);
971
972 __m256 result = _mm256_mul_ps(dy, gelu_deriv);
973 _mm256_storeu_ps(&d_input[i], result);
974 }
975 // Handle remaining elements
976 for (; i < n; ++i) {
977 float x = input[i];
978 float s = 1.0f / (1.0f + expf(-beta * x));
979 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
980 d_input[i] = d_output[i] * gelu_derivative;
981 }
982
983#else
984 // Scalar fallback
985 for (size_t i = 0; i < n; ++i) {
986 float x = input[i];
987 float s = 1.0f / (1.0f + expf(-beta * x));
988 float gelu_derivative = s * (1.0f + x * (1.0f - s) * beta);
989 d_input[i] = d_output[i] * gelu_derivative;
990 }
991#endif
992}

References __attribute__().

Referenced by gelu_backward_fast_bf16().

◆ gelu_backward_fast_bf16()

void gelu_backward_fast_bf16 ( const uint16_t *  input,
const uint16_t *  d_output,
uint16_t *  d_input,
size_t  n,
float *  scratch_input,
float *  scratch_d_output,
float *  scratch_d_input 
)

Definition at line 69 of file gelu_kernels_bf16.c.

76{
77 if (!scratch_input || !scratch_d_output || !scratch_d_input) return;
78
79 bf16_tensor_to_float(input, scratch_input, n);
80 bf16_tensor_to_float(d_output, scratch_d_output, n);
81
82 gelu_backward_fast(scratch_input, scratch_d_output, scratch_d_input, n);
83
84 float_tensor_to_bf16(scratch_d_input, d_input, n);
85}
void gelu_backward_fast(const float *input, const float *d_output, float *d_input, size_t n)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and gelu_backward_fast().

◆ gelu_backward_scalar()

void gelu_backward_scalar ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 846 of file gelu_kernels.c.

850{
851 const float sqrt_2_over_pi = 0.7978845608f;
852 const float coeff = 0.044715f;
853
854 for (size_t i = 0; i < n; ++i) {
855 float x = input[i];
856 float x3 = x * x * x;
857 float g = sqrt_2_over_pi * (x + coeff * x3);
858 float tanh_g = tanhf(g);
859 float x2 = x * x;
860 float g_prime = sqrt_2_over_pi * (1.0f + 3.0f * coeff * x2);
861 float sech2_g = 1.0f - tanh_g * tanh_g;
862 float gelu_derivative = 0.5f * (1.0f + tanh_g) + 0.5f * x * sech2_g * g_prime;
863 d_input[i] = d_output[i] * gelu_derivative;
864 }
865}

Referenced by gelu_backward_exact_bf16().

◆ gelu_erf_bf16_storage()

void gelu_erf_bf16_storage ( float *  data,
size_t  n 
)

Definition at line 661 of file gelu_kernels.c.

662{
663 const double inv_sqrt_2 = 0.707106781186547524400844362104849039;
664 ck_gelu_math_f64_fn reference_erf = ck_gelu_system_erf();
665 for (size_t i = 0; i < n; ++i) {
666 const float x = bf16_to_float(float_to_bf16(data[i]));
667 const double scaled = (double)x * inv_sqrt_2;
668 const double erf_value = reference_erf ? reference_erf(scaled) : erf(scaled);
669 const float output = (float)(0.5 * (double)x * (1.0 + erf_value));
670 data[i] = bf16_to_float(float_to_bf16(output));
671 }
672}
double(* ck_gelu_math_f64_fn)(double)
static ck_gelu_math_f64_fn ck_gelu_system_erf(void)

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

◆ gelu_erf_fp64_f32_inplace()

void gelu_erf_fp64_f32_inplace ( float *  data,
size_t  n 
)

Definition at line 567 of file gelu_kernels.c.

568{
569 const double inv_sqrt_2 = 0.707106781186547524400844362104849039;
570 ck_gelu_math_f64_fn reference_erf = ck_gelu_system_erf();
571 for (size_t i = 0; i < n; ++i) {
572 const float x = data[i];
573 const double scaled = (double)x * inv_sqrt_2;
574 const double erf_value = reference_erf ? reference_erf(scaled) : erf(scaled);
575 data[i] = (float)(0.5 * (double)x * (1.0 + erf_value));
576 }
577}

References ck_gelu_system_erf().

Referenced by gelu_erf_fp64_f32_parallel_dispatch(), and gelu_pytorch_erf_f32_inplace().

◆ gelu_erf_fp64_f32_parallel_dispatch()

void gelu_erf_fp64_f32_parallel_dispatch ( float *  data,
size_t  n 
)

Definition at line 606 of file gelu_kernels.c.

607{
608 const size_t minimum_elements_per_thread = 32768u;
609 ck_threadpool_t *pool = ck_threadpool_global();
610 int active = pool ? ck_threadpool_n_threads(pool) : 1;
611
612 if (!data || n == 0) return;
613 if (!pool || active <= 1 || n < 2u * minimum_elements_per_thread ||
614 ck_threadpool_thread_id(pool) > 0) {
616 return;
617 }
618
619 const size_t useful_threads =
620 (n + minimum_elements_per_thread - 1u) / minimum_elements_per_thread;
621 if ((size_t)active > useful_threads) active = (int)useful_threads;
622 ck_gelu_erf_fp64_parallel_args_t args = {
623 .data = data,
624 .n = n,
625 .reference_erf = ck_gelu_system_erf(),
626 };
628}
void gelu_erf_fp64_f32_inplace(float *data, size_t n)
static void ck_gelu_erf_fp64_parallel_work(int ith, int nth, void *opaque)

References ck_gelu_erf_fp64_parallel_work(), ck_gelu_system_erf(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_thread_id(), and gelu_erf_fp64_f32_inplace().

◆ gelu_exact_inplace()

void gelu_exact_inplace ( float *  data,
size_t  n 
)

Definition at line 558 of file gelu_kernels.c.

559{
560 for (size_t i = 0; i < n; ++i) {
561 data[i] = ck_gelu_tanh_f32(data[i]);
562 }
563}
static float ck_gelu_tanh_f32(float x)

References ck_gelu_tanh_f32().

Referenced by gelu_fast_inplace_bf16(), gelu_rows_tanh_checked_f32(), and mlp_token_parallel_exact().

◆ gelu_fast_inplace()

void gelu_fast_inplace ( float *  data,
size_t  n 
)

GELU activation forward (fast approximation, in-place)

Test:

test_gelu.py::TestGELUForward::test_gelu_fast_inplace

test_gelu.py::TestGELUForward::test_gelu_vs_exact

test_parity.py::test_gelu_parity

Fast GELU approximation: 0.5 * x * (1 + tanh(sqrt(2/pi) * (x + 0.044715 * x^3))) In-place on contiguous buffer.

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

Definition at line 244 of file gelu_kernels.c.

245{
246 const float sqrt_2_over_pi = 0.7978845608f;
247 const float coeff = 0.044715f;
248
249#if defined(__AVX512F__)
250 const __m512 sqrt_2_pi_vec = _mm512_set1_ps(sqrt_2_over_pi);
251 const __m512 coeff_vec = _mm512_set1_ps(coeff);
252 const __m512 half_vec = _mm512_set1_ps(0.5f);
253 const __m512 one_vec = _mm512_set1_ps(1.0f);
254
255 size_t i = 0;
256 for (; i + 16 <= n; i += 16) {
257 __m512 x = _mm512_loadu_ps(&data[i]);
258 __m512 x2 = _mm512_mul_ps(x, x);
259 __m512 x3 = _mm512_mul_ps(x2, x);
260
261 // inner = sqrt(2/pi) * (x + 0.044715 * x^3)
262 __m512 inner = _mm512_fmadd_ps(coeff_vec, x3, x);
263 inner = _mm512_mul_ps(sqrt_2_pi_vec, inner);
264
265 // result = 0.5 * x * (1 + tanh(inner))
266 __m512 tanh_val = tanh512_fast(inner);
267 __m512 one_plus_tanh = _mm512_add_ps(one_vec, tanh_val);
268 __m512 result = _mm512_mul_ps(half_vec, _mm512_mul_ps(x, one_plus_tanh));
269
270 _mm512_storeu_ps(&data[i], result);
271 }
272 // Handle remaining elements
273 for (; i < n; ++i) {
274 float x = data[i];
275 float x3 = x * x * x;
276 float inner = sqrt_2_over_pi * (x + coeff * x3);
277 data[i] = 0.5f * x * (1.0f + tanhf(inner));
278 }
279
280#elif defined(__AVX2__)
281 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
282 const __m256 coeff_vec = _mm256_set1_ps(coeff);
283 const __m256 half_vec = _mm256_set1_ps(0.5f);
284 const __m256 one_vec = _mm256_set1_ps(1.0f);
285
286 size_t i = 0;
287 for (; i + 8 <= n; i += 8) {
288 __m256 x = _mm256_loadu_ps(&data[i]);
289 __m256 x2 = _mm256_mul_ps(x, x);
290 __m256 x3 = _mm256_mul_ps(x2, x);
291
292 // inner = sqrt(2/pi) * (x + 0.044715 * x^3)
293 __m256 inner = _mm256_fmadd_ps(coeff_vec, x3, x);
294 inner = _mm256_mul_ps(sqrt_2_pi_vec, inner);
295
296 // result = 0.5 * x * (1 + tanh(inner))
297 __m256 tanh_val = tanh256_fast(inner);
298 __m256 one_plus_tanh = _mm256_add_ps(one_vec, tanh_val);
299 __m256 result = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, one_plus_tanh));
300
301 _mm256_storeu_ps(&data[i], result);
302 }
303 // Handle remaining elements
304 for (; i < n; ++i) {
305 float x = data[i];
306 float x3 = x * x * x;
307 float inner = sqrt_2_over_pi * (x + coeff * x3);
308 data[i] = 0.5f * x * (1.0f + tanhf(inner));
309 }
310
311#elif defined(__AVX__)
312 // AVX1: Vectorize arithmetic, use scalar tanh
313 const __m256 sqrt_2_pi_vec = _mm256_set1_ps(sqrt_2_over_pi);
314 const __m256 coeff_vec = _mm256_set1_ps(coeff);
315 const __m256 half_vec = _mm256_set1_ps(0.5f);
316 const __m256 one_vec = _mm256_set1_ps(1.0f);
317
318 size_t i = 0;
319 float inner_arr[8] __attribute__((aligned(32)));
320 float tanh_arr[8] __attribute__((aligned(32)));
321
322 for (; i + 8 <= n; i += 8) {
323 __m256 x = _mm256_loadu_ps(&data[i]);
324 __m256 x2 = _mm256_mul_ps(x, x);
325 __m256 x3 = _mm256_mul_ps(x2, x);
326
327 // inner = sqrt(2/pi) * (x + 0.044715 * x^3)
328 __m256 coeff_x3 = _mm256_mul_ps(coeff_vec, x3);
329 __m256 inner = _mm256_mul_ps(sqrt_2_pi_vec, _mm256_add_ps(x, coeff_x3));
330
331 // Compute tanh scalarly
332 _mm256_store_ps(inner_arr, inner);
333 for (int j = 0; j < 8; ++j) {
334 tanh_arr[j] = tanhf(inner_arr[j]);
335 }
336 __m256 tanh_val = _mm256_load_ps(tanh_arr);
337
338 // result = 0.5 * x * (1 + tanh(inner))
339 __m256 one_plus_tanh = _mm256_add_ps(one_vec, tanh_val);
340 __m256 result = _mm256_mul_ps(half_vec, _mm256_mul_ps(x, one_plus_tanh));
341
342 _mm256_storeu_ps(&data[i], result);
343 }
344 // Handle remaining elements
345 for (; i < n; ++i) {
346 float x = data[i];
347 float x3 = x * x * x;
348 float inner = sqrt_2_over_pi * (x + coeff * x3);
349 data[i] = 0.5f * x * (1.0f + tanhf(inner));
350 }
351
352#else
353 // Scalar fallback
354 for (size_t i = 0; i < n; ++i) {
355 float x = data[i];
356 float x3 = x * x * x;
357 float inner = sqrt_2_over_pi * (x + coeff * x3);
358 data[i] = 0.5f * x * (1.0f + tanhf(inner));
359 }
360#endif
361}

References __attribute__().

Referenced by mlp_token_parallel().

◆ gelu_fast_inplace_bf16()

void gelu_fast_inplace_bf16 ( uint16_t *  data,
size_t  n,
float *  scratch 
)

Definition at line 31 of file gelu_kernels_bf16.c.

32{
33 if (!scratch) return;
34
35 bf16_tensor_to_float(data, scratch, n);
36 // Use exact version to avoid fast tanh approximation error accumulating
37 // with BF16 precision loss. Conversion overhead dominates anyway.
38 gelu_exact_inplace(scratch, n);
39 float_tensor_to_bf16(scratch, data, n);
40}
void gelu_exact_inplace(float *data, size_t n)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and gelu_exact_inplace().

◆ gelu_ggml_inplace()

void gelu_ggml_inplace ( float *  data,
size_t  n 
)

Definition at line 805 of file gelu_kernels.c.

806{
809 for (size_t i = 0; i < n; ++i) {
810 const float x = data[i];
811 if (x <= -10.0f) {
812 data[i] = 0.0f;
813 continue;
814 }
815 if (x >= 10.0f) {
816 data[i] = x;
817 continue;
818 }
819 const ck_half x_fp16 = ck_gelu_runtime_fp32_to_fp16(x);
820 const ck_half y_fp16 = ck_gelu_runtime_table_f16[(uint16_t) x_fp16];
821 data[i] = ck_gelu_runtime_fp16_to_fp32(y_fp16);
822 }
823 return;
824 }
825
827 for (size_t i = 0; i < n; ++i) {
828 const float x = data[i];
829 if (x <= -10.0f) {
830 data[i] = 0.0f;
831 continue;
832 }
833 if (x >= 10.0f) {
834 data[i] = x;
835 continue;
836 }
837 const ck_half x_fp16 = ggml_fp32_to_fp16(x);
838 const ck_half y_fp16 = ck_gelu_ggml_table_f16[(uint16_t) x_fp16];
839 data[i] = ggml_fp16_to_fp32(y_fp16);
840 }
841}
#define ggml_fp32_to_fp16
uint16_t ck_half
#define ggml_fp16_to_fp32
static void ck_gelu_ggml_runtime_init(void)
static const ck_half * ck_gelu_runtime_table_f16
static int ck_gelu_runtime_ready
static pthread_once_t ck_gelu_ggml_table_once
static ck_gelu_ggml_fp32_to_fp16_fn ck_gelu_runtime_fp32_to_fp16
static ck_gelu_ggml_fp16_to_fp32_fn ck_gelu_runtime_fp16_to_fp32
static void ck_gelu_ggml_table_init(void)
static ck_half ck_gelu_ggml_table_f16[1u<< 16]
static pthread_once_t ck_gelu_ggml_runtime_once

References ck_gelu_ggml_runtime_init(), ck_gelu_ggml_runtime_once, ck_gelu_ggml_table_f16, ck_gelu_ggml_table_init(), ck_gelu_ggml_table_once, ck_gelu_runtime_fp16_to_fp32, ck_gelu_runtime_fp32_to_fp16, ck_gelu_runtime_ready, ck_gelu_runtime_table_f16, ggml_fp16_to_fp32, and ggml_fp32_to_fp16.

◆ gelu_ggml_native_inplace()

void gelu_ggml_native_inplace ( float *  data,
size_t  n 
)

Definition at line 793 of file gelu_kernels.c.

794{
796 for (size_t i = 0; i < n; ++i) {
797 const float x = data[i];
798 if (x <= -10.0f) data[i] = 0.0f;
799 else if (x >= 10.0f) data[i] = x;
800 else data[i] = ggml_fp16_to_fp32(
802 }
803}

References ck_gelu_ggml_table_f16, ck_gelu_ggml_table_init(), ck_gelu_ggml_table_once, ggml_fp16_to_fp32, and ggml_fp32_to_fp16.

◆ gelu_pytorch_erf_f32_inplace()

void gelu_pytorch_erf_f32_inplace ( float *  data,
size_t  n 
)

Definition at line 632 of file gelu_kernels.c.

633{
635}

References gelu_erf_fp64_f32_inplace().

◆ gelu_pytorch_erf_sleef_bf16_storage()

void gelu_pytorch_erf_sleef_bf16_storage ( float *  data,
size_t  n 
)

Definition at line 734 of file gelu_kernels.c.

735{
736#if defined(__AVX512F__)
737 pthread_once(&ck_pytorch_sleef_once, ck_bind_pytorch_sleef);
738 if (!ck_pytorch_sleef_expf16) {
739 fprintf(stderr,
740 "[CK] PyTorch-exact BF16 GELU requires Sleef_expf16_u10; "
741 "set CK_SLEEF_LIBRARY to libtorch_cpu.so or libsleef.so\n");
742 abort();
743 }
744
745 const __m512 alpha = _mm512_set1_ps(0.70710678118654752440f);
746 const __m512 half = _mm512_set1_ps(0.5f);
747 const __m512 one = _mm512_set1_ps(1.0f);
748 const __m512 neg_zero = _mm512_set1_ps(-0.0f);
749 const __m512 p = _mm512_set1_ps(0.3275911f);
750 const __m512 p1 = _mm512_set1_ps(0.254829592f);
751 const __m512 p2 = _mm512_set1_ps(-0.284496736f);
752 const __m512 p3 = _mm512_set1_ps(1.421413741f);
753 const __m512 p4 = _mm512_set1_ps(-1.453152027f);
754 const __m512 p5 = _mm512_set1_ps(1.061405429f);
755 size_t i = 0;
756 for (; i + 16 <= n; i += 16) {
757 __m512 x = _mm512_loadu_ps(data + i);
758 __m512 erf_arg = _mm512_mul_ps(x, alpha);
759 __m512 sign = _mm512_and_ps(neg_zero, erf_arg);
760 __m512 abs_arg = _mm512_abs_ps(erf_arg);
761 __m512 t = _mm512_div_ps(one, _mm512_fmadd_ps(p, abs_arg, one));
762 __m512 r = _mm512_fmadd_ps(p5, t, p4);
763 r = _mm512_fmadd_ps(r, t, p3);
764 r = _mm512_fmadd_ps(r, t, p2);
765 r = _mm512_fmadd_ps(r, t, p1);
766 __m512 arg_sq = _mm512_mul_ps(erf_arg, erf_arg);
767 __m512 exp_neg_sq = ck_pytorch_sleef_expf16(_mm512_xor_ps(neg_zero, arg_sq));
768 __m512 neg_exp_t = _mm512_mul_ps(_mm512_xor_ps(neg_zero, exp_neg_sq), t);
769 __m512 erf_x = _mm512_xor_ps(sign, _mm512_fmadd_ps(neg_exp_t, r, one));
770 __m512 y = _mm512_mul_ps(_mm512_mul_ps(x, half), _mm512_add_ps(one, erf_x));
771 float lanes[16];
772 _mm512_storeu_ps(lanes, y);
773 for (size_t lane = 0; lane < 16; ++lane) {
774 const uint16_t input_code = float_to_bf16(data[i + lane]);
775 const uint16_t output_code = ck_pytorch_gelu_erf_bf16_edge(
776 input_code, float_to_bf16(lanes[lane]));
777 data[i + lane] = bf16_to_float(output_code);
778 }
779 }
780 for (; i < n; ++i) {
781 const float x = bf16_to_float(float_to_bf16(data[i]));
782 const float y = (x * 0.5f) * (1.0f + erff(x * 0.70710678118654752440f));
783 data[i] = bf16_to_float(float_to_bf16(y));
784 }
785#else
786 (void)data;
787 (void)n;
788 fprintf(stderr, "[CK] PyTorch-exact BF16 GELU requires an AVX-512 build\n");
789 abort();
790#endif
791}

References bf16_to_float(), and float_to_bf16().

◆ gelu_pytorch_tanh_bf16_storage()

void gelu_pytorch_tanh_bf16_storage ( float *  data,
size_t  n 
)

Definition at line 642 of file gelu_kernels.c.

643{
644 /* PyTorch's x86 BF16 kernel widens to FP32 and evaluates tanh through
645 * SLEEF's vector u10 provider. That provider saturates at this exact
646 * inner-argument boundary; libc tanhf retains a small tail and can round
647 * to a different BF16 code before the following projection. */
648 const float sleef_tanh_saturation = 8.664339742f;
649 for (size_t i = 0; i < n; ++i) {
650 const float x = bf16_to_float(float_to_bf16(data[i]));
651 const float x3 = x * x * x;
652 const float inner = 0.7978845608f * (x + 0.044715f * x3);
653 const float tanh_inner = fabsf(inner) > sleef_tanh_saturation
654 ? copysignf(1.0f, inner)
655 : tanhf(inner);
656 const float output = 0.5f * x * (1.0f + tanh_inner);
657 data[i] = bf16_to_float(float_to_bf16(output));
658 }
659}

References bf16_to_float(), and float_to_bf16().

◆ gemm_avx512_parallel()

void gemm_avx512_parallel ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 230 of file gemm_kernels.c.

235{
237 gemm_naive_serial_float(A, B, bias, C, M, N, K);
238 return;
239 }
240#if defined(__AVX512F__)
241#pragma omp parallel for
242 for (int i = 0; i < M; i++) {
243 for (int j = 0; j < N; j++) {
244 __m512 sum_vec = _mm512_setzero_ps();
245 int k;
246 for (k = 0; k <= K - 16; k += 16) {
247 __m512 a_vec = _mm512_loadu_ps(&A[i * K + k]);
248 __m512 b_vec = _mm512_loadu_ps(&B[j * K + k]);
249 sum_vec = _mm512_fmadd_ps(a_vec, b_vec, sum_vec);
250 }
251 float sum = _mm512_reduce_add_ps(sum_vec);
252 for (; k < K; k++) {
253 sum += A[i * K + k] * B[j * K + k];
254 }
255 float bias_val = bias ? bias[j] : 0.0f;
256 C[i * N + j] = sum + bias_val;
257 }
258 }
259#elif defined(__AVX__)
260 // AVX1 path: 256-bit vectors, no FMA (use mul + add)
261#pragma omp parallel for
262 for (int i = 0; i < M; i++) {
263 for (int j = 0; j < N; j++) {
264 __m256 sum_vec = _mm256_setzero_ps();
265 int k;
266 for (k = 0; k <= K - 8; k += 8) {
267 __m256 a_vec = _mm256_loadu_ps(&A[i * K + k]);
268 __m256 b_vec = _mm256_loadu_ps(&B[j * K + k]);
269 __m256 prod = _mm256_mul_ps(a_vec, b_vec);
270 sum_vec = _mm256_add_ps(sum_vec, prod);
271 }
272 float sum = hsum256_ps(sum_vec);
273 for (; k < K; k++) {
274 sum += A[i * K + k] * B[j * K + k];
275 }
276 float bias_val = bias ? bias[j] : 0.0f;
277 C[i * N + j] = sum + bias_val;
278 }
279 }
280#else
281 gemm_naive_parallel(A, B, bias, C, M, N, K);
282#endif
283}
void gemm_naive_parallel(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
static void gemm_naive_serial_float(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References C, ck_strict_parity_enabled(), gemm_naive_parallel(), and gemm_naive_serial_float().

◆ gemm_backward_bf16_mixed()

void gemm_backward_bf16_mixed ( const uint16_t *  d_output,
const uint16_t *  input,
const uint16_t *  weight,
float *  d_input,
float *  d_weight,
float *  d_bias,
int  tokens,
int  in_dim,
int  out_dim 
)

Definition at line 2194 of file gemm_kernels_bf16.c.

2203{
2204 if (!d_output || !input || !weight || tokens <= 0 || in_dim <= 0 || out_dim <= 0) {
2205 return;
2206 }
2207
2208 if (d_input) {
2209 for (int t = 0; t < tokens; ++t) {
2210 for (int i = 0; i < in_dim; ++i) {
2211 float sum = 0.0f;
2212 for (int o = 0; o < out_dim; ++o) {
2213 const float dy = bf16_to_float(d_output[(size_t)t * (size_t)out_dim + (size_t)o]);
2214 const float w = bf16_to_float(weight[(size_t)o * (size_t)in_dim + (size_t)i]);
2215 sum += dy * w;
2216 }
2217 d_input[(size_t)t * (size_t)in_dim + (size_t)i] = sum;
2218 }
2219 }
2220 }
2221
2222 if (d_weight) {
2223 for (int o = 0; o < out_dim; ++o) {
2224 for (int i = 0; i < in_dim; ++i) {
2225 float sum = 0.0f;
2226 for (int t = 0; t < tokens; ++t) {
2227 const float dy = bf16_to_float(d_output[(size_t)t * (size_t)out_dim + (size_t)o]);
2228 const float x = bf16_to_float(input[(size_t)t * (size_t)in_dim + (size_t)i]);
2229 sum += dy * x;
2230 }
2231 d_weight[(size_t)o * (size_t)in_dim + (size_t)i] = sum;
2232 }
2233 }
2234 }
2235
2236 if (d_bias) {
2237 for (int o = 0; o < out_dim; ++o) {
2238 float sum = 0.0f;
2239 for (int t = 0; t < tokens; ++t) {
2240 sum += bf16_to_float(d_output[(size_t)t * (size_t)out_dim + (size_t)o]);
2241 }
2242 d_bias[o] = sum;
2243 }
2244 }
2245}

References bf16_to_float().

◆ gemm_backward_f32_train_parallel_dispatch()

void gemm_backward_f32_train_parallel_dispatch ( const float *  d_output,
const float *  input,
const float *  W,
float *  d_input,
float *  d_W,
float *  d_b,
int  T,
int  aligned_in,
int  aligned_out,
int  num_threads 
)

Definition at line 610 of file ck_parallel_train.c.

619 {
620 if (!d_output || !input || !W || !d_input || !d_W) {
621 return;
622 }
623 if (T <= 0 || aligned_in <= 0 || aligned_out <= 0) {
624 return;
625 }
626
627 ck_threadpool_t *pool = ck_threadpool_global();
628 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
629 if (num_threads > 0 && num_threads < nth) {
630 nth = num_threads;
631 }
632
633 if (!pool || nth <= 1) {
634 ck_train_gemm_backward_serial(d_output, input, W, d_input, d_W, d_b, T, aligned_in, aligned_out);
635 return;
636 }
637
638 /* T=1 is the dominant runtime shape in generated train microsteps.
639 * Use vectorized d_input and parallel outer-product for dW/db. */
640 if (T == 1) {
641 gemm_nn_simd(d_output, W, NULL, d_input, 1, aligned_in, aligned_out);
642
643 const size_t outer_work = (size_t)aligned_out * (size_t)aligned_in;
644 if (aligned_out < nth * 2 || aligned_in < 64 || outer_work < (size_t)524288) {
645 ck_train_outer_t1_compute_range(d_output, input, d_W, d_b, 0, aligned_out, aligned_in);
646 } else {
647 const int active_outer = ck_train_pick_active_threads(nth, (size_t)aligned_out, (size_t)64);
648 ck_train_outer_t1_args_t t1_args = {
649 .d_output = d_output,
650 .input = input,
651 .d_W = d_W,
652 .d_b = d_b,
653 .aligned_in = aligned_in,
654 .aligned_out = aligned_out,
655 };
656 if (active_outer <= 1) {
657 ck_train_outer_t1_compute_range(d_output, input, d_W, d_b, 0, aligned_out, aligned_in);
658 } else {
659 ck_threadpool_dispatch_n(pool, active_outer, ck_train_outer_t1_work, &t1_args);
660 }
661 }
662 return;
663 }
664
665 const size_t nn_work = (size_t)T * (size_t)aligned_in * (size_t)aligned_out;
666 const size_t tn_work = (size_t)aligned_out * (size_t)aligned_in * (size_t)T;
667 if ((T < 2 && aligned_out < nth * 2) || (nn_work < (size_t)131072 && tn_work < (size_t)131072)) {
668 ck_train_gemm_backward_serial(d_output, input, W, d_input, d_W, d_b, T, aligned_in, aligned_out);
669 return;
670 }
671
672 ck_train_gemm_backward_args_t bw_args = {
673 .d_output = d_output,
674 .input = input,
675 .W = W,
676 .d_input = d_input,
677 .d_W = d_W,
678 .d_b = d_b,
679 .T = T,
680 .aligned_in = aligned_in,
681 .aligned_out = aligned_out,
682 };
683 {
684 const size_t bw_rows = (size_t)aligned_out > (size_t)T ? (size_t)aligned_out : (size_t)T;
685 const int active_bw = ck_train_pick_active_threads(nth, bw_rows, (size_t)64);
686 if (active_bw <= 1) {
687 ck_train_gemm_backward_serial(d_output, input, W, d_input, d_W, d_b, T, aligned_in, aligned_out);
688 } else {
689 ck_threadpool_dispatch_n(pool, active_bw, ck_train_gemm_backward_work, &bw_args);
690 }
691 }
692}
static void ck_train_outer_t1_compute_range(const float *d_output, const float *input, float *d_W, float *d_b, int out_start, int out_end, int aligned_in)
static void ck_train_gemm_backward_serial(const float *d_output, const float *input, const float *W, float *d_input, float *d_W, float *d_b, int T, int aligned_in, int aligned_out)
static int ck_train_pick_active_threads(int nth, size_t work_items, size_t min_chunk)
static void ck_train_gemm_backward_work(int ith, int nth, void *argp)
static void ck_train_outer_t1_work(int ith, int nth, void *argp)

References ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_train_gemm_backward_serial(), ck_train_gemm_backward_work(), ck_train_outer_t1_compute_range(), ck_train_outer_t1_work(), ck_train_pick_active_threads(), and gemm_nn_simd().

◆ gemm_backward_f32_train_parallel_dispatch_v2()

void gemm_backward_f32_train_parallel_dispatch_v2 ( const float *  d_output,
const float *  input,
const float *  W,
float *  d_input,
float *  d_W,
float *  d_b,
int  T,
int  aligned_in,
int  aligned_out,
int  num_threads 
)

Definition at line 699 of file ck_parallel_train.c.

708 {
709 if (!d_output || !input || !W || !d_input || !d_W) {
710 return;
711 }
712 if (T <= 0 || aligned_in <= 0 || aligned_out <= 0) {
713 return;
714 }
715
716 ck_threadpool_t *pool = ck_threadpool_global();
717 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
718 if (num_threads > 0 && num_threads < nth) {
719 nth = num_threads;
720 }
721
722 if (!pool || nth <= 1) {
723 ck_train_gemm_backward_serial(d_output, input, W, d_input, d_W, d_b, T, aligned_in, aligned_out);
724 return;
725 }
726
727 if (T == 1) {
728 const size_t nn_work = (size_t)aligned_in * (size_t)aligned_out;
729 if (aligned_in >= nth * 32 && nn_work >= (size_t)131072) {
730 const int active_nn = ck_train_pick_active_threads(nth, (size_t)aligned_in, (size_t)64);
731 ck_train_gemm_nn_args_t nn_args = {
732 .A = d_output,
733 .B = W,
734 .bias = NULL,
735 .C = d_input,
736 .M = 1,
737 .N = aligned_in,
738 .K = aligned_out,
739 .split_n = 1,
740 };
741 if (active_nn <= 1) {
742 gemm_nn_simd(d_output, W, NULL, d_input, 1, aligned_in, aligned_out);
743 } else {
744 ck_threadpool_dispatch_n(pool, active_nn, ck_train_gemm_nn_work, &nn_args);
745 }
746 } else {
747 gemm_nn_simd(d_output, W, NULL, d_input, 1, aligned_in, aligned_out);
748 }
749
750 const size_t outer_work = (size_t)aligned_out * (size_t)aligned_in;
751 if (aligned_out >= nth && outer_work >= (size_t)131072) {
752 const int active_outer = ck_train_pick_active_threads(nth, (size_t)aligned_out, (size_t)64);
753 ck_train_outer_t1_args_t t1_args = {
754 .d_output = d_output,
755 .input = input,
756 .d_W = d_W,
757 .d_b = d_b,
758 .aligned_in = aligned_in,
759 .aligned_out = aligned_out,
760 };
761 if (active_outer <= 1) {
762 ck_train_outer_t1_compute_range(d_output, input, d_W, d_b, 0, aligned_out, aligned_in);
763 } else {
764 ck_threadpool_dispatch_n(pool, active_outer, ck_train_outer_t1_work, &t1_args);
765 }
766 } else {
767 ck_train_outer_t1_compute_range(d_output, input, d_W, d_b, 0, aligned_out, aligned_in);
768 }
769 return;
770 }
771
772 const size_t nn_work = (size_t)T * (size_t)aligned_in * (size_t)aligned_out;
773 const size_t tn_work = (size_t)aligned_out * (size_t)aligned_in * (size_t)T;
774 if ((T < nth && aligned_out < nth) || (nn_work < (size_t)131072 && tn_work < (size_t)131072)) {
775 ck_train_gemm_backward_serial(d_output, input, W, d_input, d_W, d_b, T, aligned_in, aligned_out);
776 return;
777 }
778
779 ck_train_gemm_backward_args_t bw_args = {
780 .d_output = d_output,
781 .input = input,
782 .W = W,
783 .d_input = d_input,
784 .d_W = d_W,
785 .d_b = d_b,
786 .T = T,
787 .aligned_in = aligned_in,
788 .aligned_out = aligned_out,
789 };
790 {
791 const size_t bw_rows = (size_t)aligned_out > (size_t)T ? (size_t)aligned_out : (size_t)T;
792 const int active_bw = ck_train_pick_active_threads(nth, bw_rows, (size_t)64);
793 if (active_bw <= 1) {
794 ck_train_gemm_backward_serial(d_output, input, W, d_input, d_W, d_b, T, aligned_in, aligned_out);
795 } else {
796 ck_threadpool_dispatch_n(pool, active_bw, ck_train_gemm_backward_work, &bw_args);
797 }
798 }
799}
static void ck_train_gemm_nn_work(int ith, int nth, void *argp)

References ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_train_gemm_backward_serial(), ck_train_gemm_backward_work(), ck_train_gemm_nn_work(), ck_train_outer_t1_compute_range(), ck_train_outer_t1_work(), ck_train_pick_active_threads(), and gemm_nn_simd().

◆ gemm_bias_gelu_fused()

void gemm_bias_gelu_fused ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 131 of file gemm_fused_kernels.c.

136{
137#if defined(__AVX__)
138#pragma omp parallel for
139 for (int i = 0; i < M; i++) {
140 for (int j = 0; j < N; j++) {
141 __m256 sum_vec = _mm256_setzero_ps();
142 int k;
143 for (k = 0; k <= K - 8; k += 8) {
144 __m256 a_vec = _mm256_loadu_ps(&A[i * K + k]);
145 __m256 b_vec = _mm256_loadu_ps(&B[j * K + k]);
146 __m256 prod = _mm256_mul_ps(a_vec, b_vec);
147 sum_vec = _mm256_add_ps(sum_vec, prod);
148 }
149 float sum = hsum256_ps_fused(sum_vec);
150 for (; k < K; k++) {
151 sum += A[i * K + k] * B[j * K + k];
152 }
153 sum += bias[j];
154 C[i * N + j] = fast_gelu_scalar(sum);
155 }
156 }
157#else
158#pragma omp parallel for
159 for (int i = 0; i < M; i++) {
160 for (int j = 0; j < N; j++) {
161 float sum = 0.0f;
162 for (int k = 0; k < K; k++) {
163 sum += A[i * K + k] * B[j * K + k];
164 }
165 sum += bias[j];
166 C[i * N + j] = fast_gelu_scalar(sum);
167 }
168 }
169#endif
170}
static float fast_gelu_scalar(float x)

References C, and fast_gelu_scalar().

◆ gemm_bias_relu_fused()

void gemm_bias_relu_fused ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 84 of file gemm_fused_kernels.c.

89{
90#if defined(__AVX__)
91#pragma omp parallel for
92 for (int i = 0; i < M; i++) {
93 for (int j = 0; j < N; j++) {
94 __m256 sum_vec = _mm256_setzero_ps();
95 int k;
96 for (k = 0; k <= K - 8; k += 8) {
97 __m256 a_vec = _mm256_loadu_ps(&A[i * K + k]);
98 __m256 b_vec = _mm256_loadu_ps(&B[j * K + k]);
99 __m256 prod = _mm256_mul_ps(a_vec, b_vec);
100 sum_vec = _mm256_add_ps(sum_vec, prod);
101 }
102 float sum = hsum256_ps_fused(sum_vec);
103 for (; k < K; k++) {
104 sum += A[i * K + k] * B[j * K + k];
105 }
106 // Fused: add bias and ReLU while still in register
107 sum += bias[j];
108 C[i * N + j] = sum > 0.0f ? sum : 0.0f;
109 }
110 }
111#else
112#pragma omp parallel for
113 for (int i = 0; i < M; i++) {
114 for (int j = 0; j < N; j++) {
115 float sum = 0.0f;
116 for (int k = 0; k < K; k++) {
117 sum += A[i * K + k] * B[j * K + k];
118 }
119 sum += bias[j];
120 C[i * N + j] = sum > 0.0f ? sum : 0.0f;
121 }
122 }
123#endif
124}

References C.

◆ gemm_bias_silu_fused()

void gemm_bias_silu_fused ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 177 of file gemm_fused_kernels.c.

182{
183#if defined(__AVX__)
184#pragma omp parallel for
185 for (int i = 0; i < M; i++) {
186 for (int j = 0; j < N; j++) {
187 __m256 sum_vec = _mm256_setzero_ps();
188 int k;
189 for (k = 0; k <= K - 8; k += 8) {
190 __m256 a_vec = _mm256_loadu_ps(&A[i * K + k]);
191 __m256 b_vec = _mm256_loadu_ps(&B[j * K + k]);
192 __m256 prod = _mm256_mul_ps(a_vec, b_vec);
193 sum_vec = _mm256_add_ps(sum_vec, prod);
194 }
195 float sum = hsum256_ps_fused(sum_vec);
196 for (; k < K; k++) {
197 sum += A[i * K + k] * B[j * K + k];
198 }
199 sum += bias[j];
200 // SiLU: x * sigmoid(x)
201 float sig = 1.0f / (1.0f + expf(-sum));
202 C[i * N + j] = sum * sig;
203 }
204 }
205#else
206#pragma omp parallel for
207 for (int i = 0; i < M; i++) {
208 for (int j = 0; j < N; j++) {
209 float sum = 0.0f;
210 for (int k = 0; k < K; k++) {
211 sum += A[i * K + k] * B[j * K + k];
212 }
213 sum += bias[j];
214 float sig = 1.0f / (1.0f + expf(-sum));
215 C[i * N + j] = sum * sig;
216 }
217 }
218#endif
219}

References C.

◆ gemm_blocked_serial()

void gemm_blocked_serial ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 849 of file gemm_kernels.c.

854{
855 // Ensure threads are initialized (auto-detects on first call)
856 (void)ck_get_num_threads();
857
859 gemm_naive_serial_float(A, B, bias, C, M, N, K);
860 return;
861 }
862
863 // Decode-time matvec (M=1) is extremely common and benefits from parallelism over N.
864 // Lower threshold to parallelize more ops; OpenMP overhead is ~1-2μs per barrier.
865 // For N*K >= 64K elements, parallel is worthwhile.
866 if (M == 1 && (size_t)N * (size_t)K >= 65536) {
867 gemm_nt_matvec_parallel(A, B, bias, C, N, K);
868 return;
869 }
870
871 /*
872 * Use gemm_microkernel for large matrices - it uses MKL/oneDNN when available,
873 * which is substantially faster than our hand-written SIMD kernels.
874 * B is stored as [N x K] (transposed), so we pass B_transposed=1.
875 * Note: Use threshold of 32 to avoid numerical precision issues with small matrices.
876 */
877 if (M >= 32 && N >= 32 && K >= 32) {
878 gemm_microkernel(A, B, C, M, N, K, 1); // B_transposed=1
879 ck_gemm_add_bias(C, bias, M, N);
880 return;
881 }
882#if defined(__AVX512F__)
883 const int block_size = 64;
884#elif defined(__AVX__)
885 const int block_size = 32;
886#else
887 const int block_size = 32;
888#endif
889 for (int i = 0; i < M; i++) {
890 for (int j = 0; j < N; j++) {
891 C[i * N + j] = bias ? bias[j] : 0.0f;
892 }
893 }
894 for (int ii = 0; ii < M; ii += block_size) {
895 for (int jj = 0; jj < N; jj += block_size) {
896 for (int kk = 0; kk < K; kk += block_size) {
897 int i_end = ck_min(ii + block_size, M);
898 int j_end = ck_min(jj + block_size, N);
899 int k_end = ck_min(kk + block_size, K);
900
901 for (int i = ii; i < i_end; i++) {
902 for (int j = jj; j < j_end; j++) {
903#if defined(__AVX512F__)
904 __m512 sum_vec = _mm512_setzero_ps();
905 int k;
906 for (k = kk; k <= k_end - 16; k += 16) {
907 __m512 a_vec = _mm512_loadu_ps(&A[i * K + k]);
908 __m512 b_vec = _mm512_loadu_ps(&B[j * K + k]);
909 sum_vec = _mm512_fmadd_ps(a_vec, b_vec, sum_vec);
910 }
911 float partial_sum = _mm512_reduce_add_ps(sum_vec);
912 for (; k < k_end; k++) {
913 partial_sum += A[i * K + k] * B[j * K + k];
914 }
915#elif defined(__AVX__)
916 __m256 sum_vec = _mm256_setzero_ps();
917 int k;
918 for (k = kk; k <= k_end - 8; k += 8) {
919 __m256 a_vec = _mm256_loadu_ps(&A[i * K + k]);
920 __m256 b_vec = _mm256_loadu_ps(&B[j * K + k]);
921 __m256 prod = _mm256_mul_ps(a_vec, b_vec);
922 sum_vec = _mm256_add_ps(sum_vec, prod);
923 }
924 float partial_sum = hsum256_ps(sum_vec);
925 for (; k < k_end; k++) {
926 partial_sum += A[i * K + k] * B[j * K + k];
927 }
928#else
929 float partial_sum = 0.0f;
930 for (int k = kk; k < k_end; k++) {
931 partial_sum += A[i * K + k] * B[j * K + k];
932 }
933#endif
934 C[i * N + j] += partial_sum;
935 }
936 }
937 }
938 }
939 }
940}
void gemm_microkernel(const float *A, const float *B, float *C, int M, int N, int K, int B_transposed)
static int ck_min(int a, int b)
static void gemm_nt_matvec_parallel(const float *A, const float *B, const float *bias, float *C, int N, int K)
static void ck_gemm_add_bias(float *C, const float *bias, int M, int N)

References C, ck_gemm_add_bias(), ck_get_num_threads(), ck_min(), ck_strict_parity_enabled(), gemm_microkernel(), gemm_naive_serial_float(), and gemm_nt_matvec_parallel().

Referenced by ck_attention_project_head_major(), ck_gemm_nt_quant(), ck_mlp_swiglu_forward(), ck_mlp_swiglu_forward_fused_token(), ck_qkv_project_head_major(), ck_qkv_project_head_major_token(), ck_train_gemm_work(), gemm_blocked_serial_train_parallel_dispatch(), mlp_token_parallel(), and mlp_token_parallel_exact().

◆ gemm_blocked_serial_bf16()

void gemm_blocked_serial_bf16 ( const uint16_t *  A,
const uint16_t *  B,
const uint16_t *  bias,
uint16_t *  C,
int  M,
int  N,
int  K 
)

Definition at line 431 of file gemm_kernels_bf16.c.

436{
437 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0) {
438 return;
439 }
440
441#if HAVE_NATIVE_BF16
442 /* Native BF16 instructions available (Ice Lake / Sapphire Rapids+) */
443 gemm_bf16_native(A, B, bias, C, M, N, K);
444#elif defined(__AVX512F__)
445 /* Use AVX-512F with software BF16 conversion */
446 if (M * N > 4096) {
447 gemm_bf16_blocked_avx512(A, B, bias, C, M, N, K);
448 } else {
449 gemm_bf16_avx512(A, B, bias, C, M, N, K);
450 }
451#else
452 /* Scalar fallback */
453 gemm_bf16_scalar(A, B, bias, C, M, N, K);
454#endif
455}

References C.

◆ gemm_blocked_serial_train_parallel_dispatch()

void gemm_blocked_serial_train_parallel_dispatch ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 167 of file ck_parallel_train.c.

173 {
174 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0) {
175 return;
176 }
177
178 ck_threadpool_t *pool = ck_threadpool_global();
179 const int nth = pool ? ck_threadpool_n_threads(pool) : 1;
180
181 /* Keep small shapes on serial path to avoid dispatch overhead. */
182 const size_t work = (size_t)M * (size_t)N * (size_t)K;
183 if (!pool || nth <= 1 || work < (size_t)131072) {
184 gemm_blocked_serial(A, B, bias, C, M, N, K);
185 return;
186 }
187
188 int split_n = 0;
189 int active_nth = nth;
190 if (M == 1) {
191 /* Tensor-parallel decode-style split only when each worker has enough columns. */
192 const int cols_per_worker = (N + nth - 1) / nth;
193 if (cols_per_worker >= 256 && K >= 512 && work >= (size_t)2097152) {
194 split_n = 1;
195 } else {
196 gemm_blocked_serial(A, B, bias, C, M, N, K);
197 return;
198 }
199 } else {
200 /* Row split for prefill/train batches with coarser chunks. */
201 active_nth = M / 2;
202 if (active_nth > nth) {
203 active_nth = nth;
204 }
205 if (active_nth <= 1) {
206 gemm_blocked_serial(A, B, bias, C, M, N, K);
207 return;
208 }
209 }
210
211 ck_train_gemm_args_t args = {
212 .A = A,
213 .B = B,
214 .bias = bias,
215 .C = C,
216 .M = M,
217 .N = N,
218 .K = K,
219 .split_n = split_n,
220 };
221
222 ck_threadpool_dispatch_n(pool, active_nth, ck_train_gemm_work, &args);
223}
static void ck_train_gemm_work(int ith, int nth, void *argp)
void gemm_blocked_serial(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References C, ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_train_gemm_work(), and gemm_blocked_serial().

◆ gemm_fine_grained_parallel()

void gemm_fine_grained_parallel ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 286 of file gemm_kernels.c.

291{
293 gemm_naive_serial_float(A, B, bias, C, M, N, K);
294 return;
295 }
296#if defined(__AVX512F__)
297 const int block_size = 64;
298#pragma omp parallel for
299 for (int i = 0; i < M; i++) {
300 for (int j = 0; j < N; j++) {
301 C[i * N + j] = bias ? bias[j] : 0.0f;
302 }
303 }
304#pragma omp parallel for collapse(3)
305 for (int ii = 0; ii < M; ii += block_size) {
306 for (int jj = 0; jj < N; jj += block_size) {
307 for (int kk = 0; kk < K; kk += block_size) {
308 int i_end = ck_min(ii + block_size, M);
309 int j_end = ck_min(jj + block_size, N);
310 int k_end = ck_min(kk + block_size, K);
311
312 for (int i = ii; i < i_end; i++) {
313 for (int j = jj; j < j_end; j++) {
314 __m512 sum_vec = _mm512_setzero_ps();
315 int k;
316 for (k = kk; k <= k_end - 16; k += 16) {
317 __m512 a_vec = _mm512_loadu_ps(&A[i * K + k]);
318 __m512 b_vec = _mm512_loadu_ps(&B[j * K + k]);
319 sum_vec = _mm512_fmadd_ps(a_vec, b_vec, sum_vec);
320 }
321 float partial_sum = _mm512_reduce_add_ps(sum_vec);
322 for (; k < k_end; k++) {
323 partial_sum += A[i * K + k] * B[j * K + k];
324 }
325#pragma omp atomic
326 C[i * N + j] += partial_sum;
327 }
328 }
329 }
330 }
331 }
332#elif defined(__AVX__)
333 // AVX1 cache-blocked version
334 const int block_size = 32; // Smaller block for L1 cache
335#pragma omp parallel for
336 for (int i = 0; i < M; i++) {
337 for (int j = 0; j < N; j++) {
338 C[i * N + j] = bias ? bias[j] : 0.0f;
339 }
340 }
341#pragma omp parallel for collapse(3)
342 for (int ii = 0; ii < M; ii += block_size) {
343 for (int jj = 0; jj < N; jj += block_size) {
344 for (int kk = 0; kk < K; kk += block_size) {
345 int i_end = ck_min(ii + block_size, M);
346 int j_end = ck_min(jj + block_size, N);
347 int k_end = ck_min(kk + block_size, K);
348
349 for (int i = ii; i < i_end; i++) {
350 for (int j = jj; j < j_end; j++) {
351 __m256 sum_vec = _mm256_setzero_ps();
352 int k;
353 for (k = kk; k <= k_end - 8; k += 8) {
354 __m256 a_vec = _mm256_loadu_ps(&A[i * K + k]);
355 __m256 b_vec = _mm256_loadu_ps(&B[j * K + k]);
356 __m256 prod = _mm256_mul_ps(a_vec, b_vec);
357 sum_vec = _mm256_add_ps(sum_vec, prod);
358 }
359 float partial_sum = hsum256_ps(sum_vec);
360 for (; k < k_end; k++) {
361 partial_sum += A[i * K + k] * B[j * K + k];
362 }
363#pragma omp atomic
364 C[i * N + j] += partial_sum;
365 }
366 }
367 }
368 }
369 }
370#else
371 gemm_naive_parallel(A, B, bias, C, M, N, K);
372#endif
373}

References C, ck_min(), ck_strict_parity_enabled(), gemm_naive_parallel(), and gemm_naive_serial_float().

◆ gemm_microkernel()

void gemm_microkernel ( const float *  A,
const float *  B,
float *  C,
int  M,
int  N,
int  K,
int  B_transposed 
)

Definition at line 1134 of file gemm_microkernel.c.

1141{
1142 if (B_transposed) {
1143 gemm_microkernel_blocked_bt(A, B, C, M, N, K);
1144 } else {
1145 // Use packed version for large matrices
1146 if (M >= PACK_THRESHOLD && N >= PACK_THRESHOLD && K >= PACK_THRESHOLD) {
1147 gemm_microkernel_packed(A, B, C, M, N, K);
1148 } else {
1149 gemm_microkernel_blocked(A, B, C, M, N, K);
1150 }
1151 }
1152}
#define PACK_THRESHOLD
void gemm_microkernel_blocked(const float *A, const float *B, float *C, int M, int N, int K)
void gemm_microkernel_blocked_bt(const float *A, const float *B, float *C, int M, int N, int K)
void gemm_microkernel_packed(const float *A, const float *B, float *C, int M, int N, int K)

References C, gemm_microkernel_blocked(), gemm_microkernel_blocked_bt(), gemm_microkernel_packed(), and PACK_THRESHOLD.

Referenced by gemm_blocked_serial().

◆ gemm_microkernel_blocked()

void gemm_microkernel_blocked ( const float *  A,
const float *  B,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 934 of file gemm_microkernel.c.

940{
941 const int mr = MR;
942 const int nr = NR;
943
944 // Use sequential version for small matrices to avoid OpenMP overhead
945 // Threshold tuned for typical 4-8 core systems
946 if ((size_t)M * N * K <= 512ULL * 512 * 512) {
947 gemm_microkernel_sequential(A, B, C, M, N, K);
948 return;
949 }
950
951 // Initialize thread count to physical cores (once)
953
954 // Zero output first
955 #pragma omp parallel for schedule(static)
956 for (int i = 0; i < M; i++) {
957 memset(&C[i * N], 0, N * sizeof(float));
958 }
959
960 // Block over K (outermost - for accumulation across all threads)
961 for (int k0 = 0; k0 < K; k0 += KC) {
962 int kb = (k0 + KC <= K) ? KC : (K - k0);
963 int first_k = (k0 == 0);
964
965 // Parallelize over M rows - each thread gets a chunk of M
966 // This gives better cache locality than tile-level parallelism
967 #pragma omp parallel for schedule(static)
968 for (int m0 = 0; m0 < M; m0 += mr) {
969 int mr_actual = (m0 + mr <= M) ? mr : (M - m0);
970
971 // Each thread processes all N tiles for its M rows
972 for (int n0 = 0; n0 < N; n0 += nr) {
973 int nr_actual = (n0 + nr <= N) ? nr : (N - n0);
974
975 const float *A_tile = &A[m0 * K + k0];
976 const float *B_tile = &B[k0 * N + n0];
977 float *C_tile = &C[m0 * N + n0];
978
979 if (mr_actual == mr && nr_actual == nr) {
980#if defined(__AVX512F__)
981 gemm_microkernel_6x32_avx512(kb, A_tile, K, B_tile, N, C_tile, N, first_k);
982#elif defined(__FMA__)
983 gemm_microkernel_6x16_avx(kb, A_tile, K, B_tile, N, C_tile, N, first_k);
984#elif defined(__AVX__)
985 gemm_microkernel_4x16_avx(kb, A_tile, K, B_tile, N, C_tile, N, first_k);
986#else
987 gemm_microkernel_edge(mr_actual, nr_actual, kb, A_tile, K, B_tile, N, C_tile, N, first_k);
988#endif
989 } else {
990 gemm_microkernel_edge(mr_actual, nr_actual, kb, A_tile, K, B_tile, N, C_tile, N, first_k);
991 }
992 }
993 }
994 }
995}
static void gemm_microkernel_edge(int m, int n, int K, const float *A, int lda, const float *B, int ldb, float *C, int ldc, int first_k)
static void gemm_microkernel_sequential(const float *A, const float *B, float *C, int M, int N, int K)
static void gemm_init_threads(void)
#define KC
#define MR
#define NR

References C, gemm_init_threads(), gemm_microkernel_edge(), gemm_microkernel_sequential(), KC, MR, and NR.

Referenced by gemm_microkernel(), and gemm_microkernel_packed().

◆ gemm_microkernel_blocked_bt()

void gemm_microkernel_blocked_bt ( const float *  A,
const float *  B,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1058 of file gemm_microkernel.c.

1064{
1065 // Zero output first
1066 #pragma omp parallel for schedule(static)
1067 for (int i = 0; i < M; i++) {
1068 memset(&C[i * N], 0, N * sizeof(float));
1069 }
1070
1071 const int mr = MR;
1072 const int nr = NR;
1073
1074 #pragma omp parallel for schedule(dynamic) collapse(2)
1075 for (int m0 = 0; m0 < M; m0 += MC) {
1076 for (int n0 = 0; n0 < N; n0 += NC) {
1077 int mb = (m0 + MC <= M) ? MC : (M - m0);
1078 int nb = (n0 + NC <= N) ? NC : (N - n0);
1079
1080 for (int k0 = 0; k0 < K; k0 += KC) {
1081 int kb = (k0 + KC <= K) ? KC : (K - k0);
1082 int first_k = (k0 == 0);
1083
1084 for (int m1 = 0; m1 < mb; m1 += mr) {
1085 int mr_actual = (m1 + mr <= mb) ? mr : (mb - m1);
1086
1087 for (int n1 = 0; n1 < nb; n1 += nr) {
1088 int nr_actual = (n1 + nr <= nb) ? nr : (nb - n1);
1089
1090 const float *A_tile = &A[(m0 + m1) * K + k0];
1091 const float *B_tile = &B[(n0 + n1) * K + k0];
1092 float *C_tile = &C[(m0 + m1) * N + (n0 + n1)];
1093
1094 if (mr_actual == mr && nr_actual == nr) {
1095#if defined(__AVX512F__)
1096 gemm_microkernel_6x32_bt_avx512(kb, A_tile, K, B_tile, K, C_tile, N, first_k);
1097#else
1098 // Scalar fallback for B-transposed
1099 for (int i = 0; i < mr; i++) {
1100 for (int j = 0; j < nr; j++) {
1101 float sum = first_k ? 0.0f : C_tile[i * N + j];
1102 for (int kk = 0; kk < kb; kk++) {
1103 sum += A_tile[i * K + kk] * B_tile[j * K + kk];
1104 }
1105 C_tile[i * N + j] = sum;
1106 }
1107 }
1108#endif
1109 } else {
1110 // Edge case
1111 for (int i = 0; i < mr_actual; i++) {
1112 for (int j = 0; j < nr_actual; j++) {
1113 float sum = first_k ? 0.0f : C_tile[i * N + j];
1114 for (int kk = 0; kk < kb; kk++) {
1115 sum += A_tile[i * K + kk] * B_tile[j * K + kk];
1116 }
1117 C_tile[i * N + j] = sum;
1118 }
1119 }
1120 }
1121 }
1122 }
1123 }
1124 }
1125 }
1126}
#define NC
#define MC

References C, KC, MC, MR, NC, and NR.

Referenced by gemm_microkernel().

◆ gemm_microkernel_packed()

void gemm_microkernel_packed ( const float *  A,
const float *  B,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 840 of file gemm_microkernel.c.

846{
847 // Use tile-parallel blocked version - scales better on many-core systems
848 gemm_microkernel_blocked(A, B, C, M, N, K);
849}

References C, and gemm_microkernel_blocked().

Referenced by gemm_microkernel().

◆ gemm_naive_parallel()

void gemm_naive_parallel ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 206 of file gemm_kernels.c.

211{
213 gemm_naive_serial_float(A, B, bias, C, M, N, K);
214 return;
215 }
216#pragma omp parallel for
217 for (int i = 0; i < M; i++) {
218 for (int j = 0; j < N; j++) {
219 float sum = 0.0f;
220 for (int k = 0; k < K; k++) {
221 sum += A[i * K + k] * B[j * K + k];
222 }
223 float bias_val = bias ? bias[j] : 0.0f;
224 C[i * N + j] = sum + bias_val;
225 }
226 }
227}

References C, ck_strict_parity_enabled(), and gemm_naive_serial_float().

Referenced by ck_attention_project_head_major_ref(), ck_mlp_swiglu_forward_ref(), ck_qkv_project_head_major_ref(), gemm_avx512_parallel(), and gemm_fine_grained_parallel().

◆ gemm_nn_avx512()

void gemm_nn_avx512 ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 420 of file gemm_kernels.c.

425{
427 gemm_nn_serial_double(A, B, bias, C, M, N, K);
428 return;
429 }
430#if defined(__AVX512F__)
431 // For gemm_nn, we can't vectorize over K easily since B[k,j] has stride N.
432 // Instead, vectorize over N (output columns) when N >= 16.
433#pragma omp parallel for
434 for (int i = 0; i < M; i++) {
435 int j = 0;
436 // Process 16 output columns at a time
437 for (; j <= N - 16; j += 16) {
438 __m512 sum_vec = bias ? _mm512_loadu_ps(&bias[j]) : _mm512_setzero_ps();
439 for (int k = 0; k < K; k++) {
440 __m512 a_broadcast = _mm512_set1_ps(A[i * K + k]);
441 __m512 b_vec = _mm512_loadu_ps(&B[k * N + j]);
442 sum_vec = _mm512_fmadd_ps(a_broadcast, b_vec, sum_vec);
443 }
444 _mm512_storeu_ps(&C[i * N + j], sum_vec);
445 }
446 // Handle remaining columns
447 for (; j < N; j++) {
448 float sum = bias ? bias[j] : 0.0f;
449 for (int k = 0; k < K; k++) {
450 sum += A[i * K + k] * B[k * N + j];
451 }
452 C[i * N + j] = sum;
453 }
454 }
455#elif defined(__AVX__)
456 // AVX1: vectorize over N (8 columns at a time)
457#pragma omp parallel for
458 for (int i = 0; i < M; i++) {
459 int j = 0;
460 for (; j <= N - 8; j += 8) {
461 __m256 sum_vec = bias ? _mm256_loadu_ps(&bias[j]) : _mm256_setzero_ps();
462 for (int k = 0; k < K; k++) {
463 __m256 a_broadcast = _mm256_set1_ps(A[i * K + k]);
464 __m256 b_vec = _mm256_loadu_ps(&B[k * N + j]);
465 __m256 prod = _mm256_mul_ps(a_broadcast, b_vec);
466 sum_vec = _mm256_add_ps(sum_vec, prod);
467 }
468 _mm256_storeu_ps(&C[i * N + j], sum_vec);
469 }
470 for (; j < N; j++) {
471 float sum = bias ? bias[j] : 0.0f;
472 for (int k = 0; k < K; k++) {
473 sum += A[i * K + k] * B[k * N + j];
474 }
475 C[i * N + j] = sum;
476 }
477 }
478#else
479 gemm_nn_parallel(A, B, bias, C, M, N, K);
480#endif
481}
static void gemm_nn_serial_double(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
void gemm_nn_parallel(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References C, ck_strict_parity_enabled(), gemm_nn_parallel(), and gemm_nn_serial_double().

Referenced by gemm_nn_simd().

◆ gemm_nn_blocked()

void gemm_nn_blocked ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 590 of file gemm_kernels.c.

595{
597 gemm_nn_serial_double(A, B, bias, C, M, N, K);
598 return;
599 }
600#if defined(__AVX512F__)
601 const int block_size = 64;
602#elif defined(__AVX__)
603 const int block_size = 32;
604#else
605 const int block_size = 32;
606#endif
607 // Initialize C with bias (parallelized)
608#pragma omp parallel for
609 for (int i = 0; i < M; i++) {
610 for (int j = 0; j < N; j++) {
611 C[i * N + j] = bias ? bias[j] : 0.0f;
612 }
613 }
614 // Blocked multiply-accumulate (parallelized over M blocks)
615#pragma omp parallel for
616 for (int ii = 0; ii < M; ii += block_size) {
617 for (int kk = 0; kk < K; kk += block_size) {
618 for (int jj = 0; jj < N; jj += block_size) {
619 int i_end = ck_min(ii + block_size, M);
620 int k_end = ck_min(kk + block_size, K);
621 int j_end = ck_min(jj + block_size, N);
622
623 for (int i = ii; i < i_end; i++) {
624 for (int k = kk; k < k_end; k++) {
625 float a_val = A[i * K + k];
626#if defined(__AVX512F__)
627 __m512 a_broadcast = _mm512_set1_ps(a_val);
628 int j;
629 for (j = jj; j <= j_end - 16; j += 16) {
630 __m512 b_vec = _mm512_loadu_ps(&B[k * N + j]);
631 __m512 c_vec = _mm512_loadu_ps(&C[i * N + j]);
632 c_vec = _mm512_fmadd_ps(a_broadcast, b_vec, c_vec);
633 _mm512_storeu_ps(&C[i * N + j], c_vec);
634 }
635 for (; j < j_end; j++) {
636 C[i * N + j] += a_val * B[k * N + j];
637 }
638#elif defined(__AVX__)
639 __m256 a_broadcast = _mm256_set1_ps(a_val);
640 int j;
641 for (j = jj; j <= j_end - 8; j += 8) {
642 __m256 b_vec = _mm256_loadu_ps(&B[k * N + j]);
643 __m256 c_vec = _mm256_loadu_ps(&C[i * N + j]);
644 __m256 prod = _mm256_mul_ps(a_broadcast, b_vec);
645 c_vec = _mm256_add_ps(c_vec, prod);
646 _mm256_storeu_ps(&C[i * N + j], c_vec);
647 }
648 for (; j < j_end; j++) {
649 C[i * N + j] += a_val * B[k * N + j];
650 }
651#else
652 for (int j = jj; j < j_end; j++) {
653 C[i * N + j] += a_val * B[k * N + j];
654 }
655#endif
656 }
657 }
658 }
659 }
660 }
661}

References C, ck_min(), ck_strict_parity_enabled(), and gemm_nn_serial_double().

◆ gemm_nn_parallel()

void gemm_nn_parallel ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 398 of file gemm_kernels.c.

403{
405 gemm_nn_serial_double(A, B, bias, C, M, N, K);
406 return;
407 }
408#pragma omp parallel for
409 for (int i = 0; i < M; i++) {
410 for (int j = 0; j < N; j++) {
411 float sum = bias ? bias[j] : 0.0f;
412 for (int k = 0; k < K; k++) {
413 sum += A[i * K + k] * B[k * N + j];
414 }
415 C[i * N + j] = sum;
416 }
417 }
418}

References C, ck_strict_parity_enabled(), and gemm_nn_serial_double().

Referenced by gemm_nn_avx512(), and gemm_nn_avx512_probe().

◆ gemm_nn_simd()

void gemm_nn_simd ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 577 of file gemm_kernels.c.

582{
584 gemm_nn_avx512_probe(A, B, bias, C, M, N, K);
585 return;
586 }
587 gemm_nn_avx512(A, B, bias, C, M, N, K);
588}
static int ck_gemm_nn_impl_probe_enabled(void)
void gemm_nn_avx512_probe(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
void gemm_nn_avx512(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References C, ck_gemm_nn_impl_probe_enabled(), gemm_nn_avx512(), and gemm_nn_avx512_probe().

Referenced by fc1_backward_kernel(), fc2_backward_kernel(), gemm_backward_f32_train_parallel_dispatch(), and gemm_backward_f32_train_parallel_dispatch_v2().

◆ gemm_nt_bf16()

void gemm_nt_bf16 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 755 of file gemm_kernels_bf16.c.

760{
761 if (M <= 0) return;
762 gemm_nt_bf16_row_range(A, B, bias, C, M, N, K, 0, M);
763}
void gemm_nt_bf16_row_range(const float *A, const void *B, const float *bias, float *C, int M, int N, int K, int row_begin, int row_end)

References C, and gemm_nt_bf16_row_range().

Referenced by gemm_nt_bf16_parallel_dispatch().

◆ gemm_nt_bf16_accurate_storage()

void gemm_nt_bf16_accurate_storage ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 2185 of file gemm_kernels_bf16.c.

2190{
2192}
void gemm_nt_bf16_accurate_storage_parallel_dispatch(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, and gemm_nt_bf16_accurate_storage_parallel_dispatch().

◆ gemm_nt_bf16_accurate_storage_parallel_dispatch()

void gemm_nt_bf16_accurate_storage_parallel_dispatch ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 2161 of file gemm_kernels_bf16.c.

2166{
2167 ck_threadpool_t *pool = ck_threadpool_global();
2168 if (!pool || ck_threadpool_n_threads(pool) <= 1 || M < 2 ||
2169 (size_t)M * (size_t)N <= 4096) {
2170 gemm_nt_bf16_accurate_storage_row_range(A, B, bias, C, M, N, K, 0, M);
2171 return;
2172 }
2173
2174 ck_gemm_nt_bf16_exact_args_t args = {
2175 .A = A, .B = B, .bias = bias, .C = C, .M = M, .N = N, .K = K,
2176 };
2177 int active = ck_threadpool_n_threads(pool);
2178 if (active > M) active = M;
2179 int grain = M / (active * 4);
2180 if (grain < 1) grain = 1;
2182 pool, active, 0, M, grain, ck_gemm_nt_bf16_accurate_storage_rows, &args);
2183}
void gemm_nt_bf16_accurate_storage_row_range(const float *A, const void *B, const float *bias, float *C, int M, int N, int K, int row_begin, int row_end)
static void ck_gemm_nt_bf16_accurate_storage_rows(int begin, int end, void *opaque)

References C, ck_gemm_nt_bf16_accurate_storage_rows(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), and gemm_nt_bf16_accurate_storage_row_range().

Referenced by gemm_nt_bf16_accurate_storage().

◆ gemm_nt_bf16_accurate_storage_row_range()

void gemm_nt_bf16_accurate_storage_row_range ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
int  row_begin,
int  row_end 
)

Definition at line 2070 of file gemm_kernels_bf16.c.

2076{
2077 const uint16_t *w = (const uint16_t *)B;
2078 if (!A || !w || !C || M <= 0 || N <= 0 || K <= 0 ||
2079 row_begin < 0 || row_begin >= row_end || row_end > M) {
2080 return;
2081 }
2082 for (int row = row_begin; row < row_end; ++row) {
2083 const float *a_row = A + (size_t)row * (size_t)K;
2084 float *dst = C + (size_t)row * (size_t)N;
2085 for (int col = 0; col < N; ++col) {
2086 const uint16_t *w_row = w + (size_t)col * (size_t)K;
2087 /* BF16 products are exact in double. A single FP32 accumulator can
2088 * round a long dot across a BF16 midpoint before output storage;
2089 * that changes downstream routing. Keep the accumulation accurate
2090 * until the declared FP32 bias/output conversion boundary. */
2091 double even = 0.0;
2092 double odd = 0.0;
2093 int k = 0;
2094 for (; k + 1 < K; k += 2) {
2095 even += (double)bf16_to_float(float_to_bf16(a_row[k])) *
2096 (double)bf16_to_float(w_row[k]);
2097 odd += (double)bf16_to_float(float_to_bf16(a_row[k + 1])) *
2098 (double)bf16_to_float(w_row[k + 1]);
2099 }
2100 if (k < K) {
2101 even += (double)bf16_to_float(float_to_bf16(a_row[k])) *
2102 (double)bf16_to_float(w_row[k]);
2103 }
2104 const float sum = (float)((even + odd) + (bias ? bias[col] : 0.0f));
2105 dst[col] = bf16_to_float(float_to_bf16(sum));
2106 }
2107 }
2108}

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

Referenced by ck_gemm_nt_bf16_accurate_storage_rows(), and gemm_nt_bf16_accurate_storage_parallel_dispatch().

◆ gemm_nt_bf16_amx_bf16_storage()

void gemm_nt_bf16_amx_bf16_storage ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1318 of file gemm_kernels_bf16.c.

1323{
1324 size_t input_count = 0;
1325 if (M > 0 && K > 0 && (size_t)M <= SIZE_MAX / (size_t)K) {
1326 input_count = (size_t)M * (size_t)K;
1327 }
1328 uint16_t *workspace = input_count > 0 && input_count <= SIZE_MAX / sizeof(uint16_t)
1329 ? (uint16_t *)malloc(input_count * sizeof(uint16_t))
1330 : NULL;
1331 if (!workspace) {
1332 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: AMX BF16 compatibility workspace allocation failed\n");
1333 abort();
1334 }
1336 A, B, bias, C, M, N, K, workspace, input_count * sizeof(uint16_t));
1337 free(workspace);
1338}
void gemm_nt_bf16_amx_bf16_storage_workspace(const float *A, const void *B, const float *bias, float *C, int M, int N, int K, uint16_t *a_bf16, size_t a_bf16_bytes)

References C, and gemm_nt_bf16_amx_bf16_storage_workspace().

Referenced by gemm_nt_bf16_prefill_shape_safe_bf16_storage().

◆ gemm_nt_bf16_amx_bf16_storage_workspace()

void gemm_nt_bf16_amx_bf16_storage_workspace ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
uint16_t *  a_bf16,
size_t  a_bf16_bytes 
)

Definition at line 1265 of file gemm_kernels_bf16.c.

1272{
1273#if HAVE_AMX_BF16
1274 if (!A || !B || !C || M < 16 || N < 16 || K < 32 ||
1275 (M % 16) != 0 || (N % 16) != 0 || (K % 32) != 0) {
1276 fprintf(stderr,
1277 "HARD KERNEL CONTRACT FAULT: AMX BF16 GEMM requires non-null buffers "
1278 "and M%%16=N%%16=K%%32=0 (M=%d N=%d K=%d)\n",
1279 M, N, K);
1280 abort();
1281 }
1282 const size_t input_count = (size_t)M * K;
1283 if (!a_bf16 || input_count > SIZE_MAX / sizeof(uint16_t) ||
1284 a_bf16_bytes < input_count * sizeof(uint16_t)) {
1285 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: AMX BF16 activation workspace is too small\n");
1286 abort();
1287 }
1288 ck_threadpool_t *pool = ck_threadpool_global();
1289 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1290 if (active > 24) active = 24;
1291 ck_bf16_convert_args_t convert = {.src=A, .dst=a_bf16, .count=input_count};
1292 if (pool && active > 1) ck_threadpool_dispatch_n(pool, active, ck_bf16_convert_work, &convert);
1293 else ck_bf16_convert_work(0, 1, &convert);
1294 ck_gemm_bf16_amx_args_t gemm = {
1295 .A=a_bf16, .B=(const uint16_t *)B, .bias=bias, .C=C,
1296 .M=M, .N=N, .K=K, .failed=0
1297 };
1298 if (pool && active > 1) ck_threadpool_dispatch_n(pool, active, ck_gemm_bf16_amx_work, &gemm);
1299 else ck_gemm_bf16_amx_work(0, 1, &gemm);
1300 if (__atomic_load_n(&gemm.failed, __ATOMIC_RELAXED)) {
1301 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: AMX tile permission request failed\n");
1302 abort();
1303 }
1304 ck_bf16_round_args_t round = {.values=C, .count=(size_t)M * N};
1305 if (pool && active > 1) ck_threadpool_dispatch_n(pool, active, ck_bf16_round_work, &round);
1306 else ck_bf16_round_work(0, 1, &round);
1307 return;
1308#else
1309 (void)A; (void)B; (void)bias; (void)C; (void)M; (void)N; (void)K;
1310 (void)a_bf16; (void)a_bf16_bytes;
1311 fprintf(stderr,
1312 "HARD KERNEL CONTRACT FAULT: gemm_nt_bf16_amx_bf16_storage was selected "
1313 "without AMX BF16 support\n");
1314 abort();
1315#endif
1316}
static void ck_bf16_convert_work(int ith, int nth, void *opaque)
static void ck_bf16_round_work(int ith, int nth, void *opaque)
static void ck_gemm_bf16_amx_work(int ith, int nth, void *opaque)

References C, ck_bf16_convert_work(), ck_bf16_round_work(), ck_gemm_bf16_amx_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by gemm_nt_bf16_amx_bf16_storage(), and gemm_nt_bf16_prefill_shape_safe_bf16_storage_workspace().

◆ gemm_nt_bf16_bf16_storage()

void gemm_nt_bf16_bf16_storage ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 2152 of file gemm_kernels_bf16.c.

2157{
2158 gemm_nt_bf16_bf16_storage_parallel_dispatch(A, B, bias, C, M, N, K);
2159}
void gemm_nt_bf16_bf16_storage_parallel_dispatch(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, and gemm_nt_bf16_bf16_storage_parallel_dispatch().

◆ gemm_nt_bf16_bf16_storage_parallel_dispatch()

void gemm_nt_bf16_bf16_storage_parallel_dispatch ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 2128 of file gemm_kernels_bf16.c.

2133{
2134 ck_threadpool_t *pool = ck_threadpool_global();
2135 if (!pool || ck_threadpool_n_threads(pool) <= 1 || M < 2 ||
2136 (size_t)M * (size_t)N <= 4096) {
2137 gemm_nt_bf16_bf16_storage_row_range(A, B, bias, C, M, N, K, 0, M);
2138 return;
2139 }
2140
2141 ck_gemm_nt_bf16_exact_args_t args = {
2142 .A = A, .B = B, .bias = bias, .C = C, .M = M, .N = N, .K = K,
2143 };
2144 int active = ck_threadpool_n_threads(pool);
2145 if (active > M) active = M;
2146 int grain = M / (active * 4);
2147 if (grain < 1) grain = 1;
2149 pool, active, 0, M, grain, ck_gemm_nt_bf16_storage_exact_rows, &args);
2150}
void gemm_nt_bf16_bf16_storage_row_range(const float *A, const void *B, const float *bias, float *C, int M, int N, int K, int row_begin, int row_end)
static void ck_gemm_nt_bf16_storage_exact_rows(int begin, int end, void *opaque)

References C, ck_gemm_nt_bf16_storage_exact_rows(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), and gemm_nt_bf16_bf16_storage_row_range().

Referenced by gemm_nt_bf16_bf16_storage().

◆ gemm_nt_bf16_bf16_storage_row_range()

void gemm_nt_bf16_bf16_storage_row_range ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
int  row_begin,
int  row_end 
)

Definition at line 2054 of file gemm_kernels_bf16.c.

2060{
2061 gemm_nt_bf16_row_range(A, B, bias, C, M, N, K, row_begin, row_end);
2062 for (int row = row_begin; row < row_end; ++row) {
2063 float *dst = C + (size_t)row * (size_t)N;
2064 for (int col = 0; col < N; ++col) {
2065 dst[col] = bf16_to_float(float_to_bf16(dst[col]));
2066 }
2067 }
2068}

References bf16_to_float(), C, float_to_bf16(), and gemm_nt_bf16_row_range().

Referenced by ck_gemm_nt_bf16_storage_exact_rows(), and gemm_nt_bf16_bf16_storage_parallel_dispatch().

◆ gemm_nt_bf16_native_bf16_storage()

void gemm_nt_bf16_native_bf16_storage ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1078 of file gemm_kernels_bf16.c.

1083{
1084 const uint16_t *weights = (const uint16_t *)B;
1085 if (!A || !weights || !C || M <= 0 || N <= 0 || K <= 0) return;
1086
1087 ck_gemm_bf16_native_args_t args = {
1088 .A = A, .B = weights, .bias = bias, .C = C, .M = M, .N = N, .K = K
1089 };
1090 ck_threadpool_t *pool = ck_threadpool_global();
1091 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1092 if (active > M) active = M;
1093 if (active > 24) active = 24;
1094 if (!pool || active <= 1 || (size_t)M * (size_t)N <= 4096) {
1095 ck_gemm_bf16_native_work(0, 1, &args);
1096 return;
1097 }
1099}
static void ck_gemm_bf16_native_work(int ith, int nth, void *opaque)

References C, ck_gemm_bf16_native_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by gemm_nt_bf16_prefill_shape_safe_bf16_storage(), and gemm_nt_bf16_prefill_shape_safe_bf16_storage_workspace().

◆ gemm_nt_bf16_parallel_dispatch()

void gemm_nt_bf16_parallel_dispatch ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 784 of file gemm_kernels_bf16.c.

789{
790 ck_threadpool_t *pool = ck_threadpool_global();
791 const char *disabled = getenv("CK_DISABLE_BF16_GEMM_PARALLEL_PREFILL");
792 if ((disabled && disabled[0] && strcmp(disabled, "0") != 0) ||
793 !pool || ck_threadpool_n_threads(pool) <= 1 || M < 2 ||
794 (size_t)M * (size_t)N <= 4096) {
795 gemm_nt_bf16(A, B, bias, C, M, N, K);
796 return;
797 }
798
799 ck_gemm_nt_bf16_exact_args_t args = {
800 .A = A, .B = B, .bias = bias, .C = C, .M = M, .N = N, .K = K,
801 };
802 int active = ck_threadpool_n_threads(pool);
803 if (active > M) active = M;
804 int grain = M / (active * 4);
805 if (grain < 1) grain = 1;
807 pool, active, 0, M, grain, ck_gemm_nt_bf16_exact_rows, &args);
808}
void gemm_nt_bf16(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
static void ck_gemm_nt_bf16_exact_rows(int begin, int end, void *opaque)

References C, ck_gemm_nt_bf16_exact_rows(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), and gemm_nt_bf16().

◆ gemm_nt_bf16_prefill_shape_safe_bf16_storage()

void gemm_nt_bf16_prefill_shape_safe_bf16_storage ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1354 of file gemm_kernels_bf16.c.

1359{
1360 const int amx_shape = M >= 16 && N >= 16 && K >= 32 &&
1361 (M % 16) == 0 && (N % 16) == 0 && (K % 32) == 0;
1362 if (amx_shape && ck_gemm_bf16_amx_available()) {
1363 gemm_nt_bf16_amx_bf16_storage(A, B, bias, C, M, N, K);
1364 return;
1365 }
1366 gemm_nt_bf16_native_bf16_storage(A, B, bias, C, M, N, K);
1367}
int ck_gemm_bf16_amx_available(void)
void gemm_nt_bf16_native_bf16_storage(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
void gemm_nt_bf16_amx_bf16_storage(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, ck_gemm_bf16_amx_available(), gemm_nt_bf16_amx_bf16_storage(), and gemm_nt_bf16_native_bf16_storage().

◆ gemm_nt_bf16_prefill_shape_safe_bf16_storage_workspace()

void gemm_nt_bf16_prefill_shape_safe_bf16_storage_workspace ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
uint16_t *  a_bf16,
size_t  a_bf16_bytes 
)

Definition at line 1340 of file gemm_kernels_bf16.c.

1343{
1344 const int amx_shape = M >= 16 && N >= 16 && K >= 32 &&
1345 (M % 16) == 0 && (N % 16) == 0 && (K % 32) == 0;
1346 if (amx_shape && ck_gemm_bf16_amx_available()) {
1348 A, B, bias, C, M, N, K, a_bf16, a_bf16_bytes);
1349 return;
1350 }
1351 gemm_nt_bf16_native_bf16_storage(A, B, bias, C, M, N, K);
1352}

References C, ck_gemm_bf16_amx_available(), gemm_nt_bf16_amx_bf16_storage_workspace(), and gemm_nt_bf16_native_bf16_storage().

◆ gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage()

void gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1601 of file gemm_kernels_bf16.c.

1604{
1605#ifdef USE_ONEDNN
1606 ck_pytorch_brgemm_require_version(
1607 3, 12, 0, "80afa71049cd69a3df32adcccb623b12cd7baa22",
1608 "gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage", M, N, K);
1609#endif
1611 A, B, bias, C, M, N, K);
1612}
static void gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage_impl(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, and gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage_impl().

◆ gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage_workspace()

void gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage_workspace ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
uint16_t *  input_bf16,
size_t  input_bf16_bytes,
uint16_t *  output_bf16,
size_t  output_bf16_bytes,
uint16_t *  bias_bf16,
size_t  bias_bf16_bytes 
)

Definition at line 1614 of file gemm_kernels_bf16.c.

1620{
1621#ifdef USE_ONEDNN
1622 ck_pytorch_brgemm_require_version(
1623 3, 12, 0, "80afa71049cd69a3df32adcccb623b12cd7baa22",
1624 "gemm_nt_bf16_pytorch_onednn_3_12_brgemm_bf16_storage_workspace",
1625 M, N, K);
1626#endif
1628 A, B, bias, C, M, N, K,
1629 input_bf16, input_bf16_bytes, output_bf16, output_bf16_bytes,
1630 bias_bf16, bias_bf16_bytes);
1631}
static void gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage_workspace_impl(const float *A, const void *B, const float *bias, float *C, int M, int N, int K, uint16_t *input_bf16, size_t input_bf16_bytes, uint16_t *output_bf16, size_t output_bf16_bytes, uint16_t *bias_bf16, size_t bias_bf16_bytes)

References C, and gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage_workspace_impl().

Referenced by ck_attention_muse_eager_bf16_storage_impl().

◆ gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage()

void gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1586 of file gemm_kernels_bf16.c.

1591{
1592#ifdef USE_ONEDNN
1593 ck_pytorch_brgemm_require_version(
1594 3, 7, 1, "8d263e693366ef8db40acc569cc7d8edf644556d",
1595 "gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage", M, N, K);
1596#endif
1598 A, B, bias, C, M, N, K);
1599}

References C, and gemm_nt_bf16_pytorch_onednn_brgemm_bf16_storage_impl().

◆ gemm_nt_bf16_row_range()

void gemm_nt_bf16_row_range ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
int  row_begin,
int  row_end 
)

Definition at line 727 of file gemm_kernels_bf16.c.

733{
734 const uint16_t *w = (const uint16_t *)B;
735 if (!A || !w || !C || M <= 0 || N <= 0 || K <= 0 ||
736 row_begin < 0 || row_begin >= row_end || row_end > M) {
737 return;
738 }
739
740 for (int i = row_begin; i < row_end; ++i) {
741 const float *a_row = A + (size_t)i * (size_t)K;
742 float *c_row = C + (size_t)i * (size_t)N;
743 for (int j = 0; j < N; ++j) {
744 const uint16_t *w_row = w + (size_t)j * (size_t)K;
745 float sum = bias ? bias[j] : 0.0f;
746 for (int k = 0; k < K; ++k) {
747 const float ab = bf16_to_float(float_to_bf16(a_row[k]));
748 sum += ab * bf16_to_float(w_row[k]);
749 }
750 c_row[j] = sum;
751 }
752 }
753}

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

Referenced by ck_gemm_nt_bf16_exact_rows(), gemm_nt_bf16(), and gemm_nt_bf16_bf16_storage_row_range().

◆ gemm_nt_f16()

void gemm_nt_f16 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

NT GEMM wrapper for FP16 weights with the engine's standard ABI.

Contract: A: [M, K] fp32 activation matrix B: [N, K] fp16 weight matrix stored row-major (transposed layout) C: [M, N] fp32 output matrix

This wrapper follows llama.cpp's CPU F16 mul_mat contract: activation rows are rounded to FP16 first, then the dot runs as F16 x F16 with FP32 output accumulation. The lower-level gemm_f16() helper remains the direct F16-weight x FP32-activation operator for generic use.

Definition at line 970 of file gemm_kernels_f16.c.

975{
977 gemm_nt_f16_ggml_strict(A, B, bias, C, M, N, K)) {
978 return;
979 }
980
981 if (!gemm_f16_input_fp16_threadpool(C, (const uint16_t *)B, A, N, M, K)) {
982 gemm_f16_input_fp16_ref(C, (const uint16_t *)B, A, N, M, K);
983 }
984
985 if (!bias) {
986 return;
987 }
988
989#pragma omp parallel for schedule(static) if(M > 1)
990 for (int i = 0; i < M; ++i) {
991 float *c_row = C + (size_t)i * (size_t)N;
992 for (int j = 0; j < N; ++j) {
993 c_row[j] += bias[j];
994 }
995 }
996}
static void gemm_f16_input_fp16_ref(float *Y, const uint16_t *W, const float *X, int M, int N, int K)
static int gemm_f16_input_fp16_threadpool(float *Y, const uint16_t *W, const float *X, int M, int N, int K)

References C, ck_strict_parity_enabled(), gemm_f16_input_fp16_ref(), gemm_f16_input_fp16_threadpool(), and gemm_nt_f16_ggml_strict().

◆ gemm_nt_f16_clipped()

void gemm_nt_f16_clipped ( const float *  A,
const void *  B,
const float *  bias,
const float *  input_min,
const float *  input_max,
const float *  output_min,
const float *  output_max,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 998 of file gemm_kernels_f16.c.

1007{
1008 const float in_min = input_min ? input_min[0] : -3.4028234663852886e38f;
1009 const float in_max = input_max ? input_max[0] : 3.4028234663852886e38f;
1010 const float out_min = output_min ? output_min[0] : -3.4028234663852886e38f;
1011 const float out_max = output_max ? output_max[0] : 3.4028234663852886e38f;
1012 const uint16_t *W = (const uint16_t *)B;
1013
1014#pragma omp parallel for schedule(static) if(M > 1)
1015 for (int m = 0; m < M; ++m) {
1016 const float *a_row = A + (size_t)m * (size_t)K;
1017 uint16_t a_f16[K];
1018
1019 for (int k = 0; k < K; ++k) {
1020 float x = a_row[k];
1021 if (x < in_min) x = in_min;
1022 if (x > in_max) x = in_max;
1023 a_f16[k] = fp32_to_fp16(x);
1024 }
1025
1026 float *c_row = C + (size_t)m * (size_t)N;
1027 for (int n = 0; n < N; ++n) {
1028 const uint16_t *w_row = W + (size_t)n * (size_t)K;
1029 float sum = bias ? bias[n] : 0.0f;
1030 for (int k = 0; k < K; ++k) {
1031 sum += fp16_to_fp32(w_row[k]) * fp16_to_fp32(a_f16[k]);
1032 }
1033 if (sum < out_min) sum = out_min;
1034 if (sum > out_max) sum = out_max;
1035 c_row[n] = sum;
1036 }
1037 }
1038}
#define fp16_to_fp32(x)
#define fp32_to_fp16(x)

References C, fp16_to_fp32, and fp32_to_fp16.

◆ gemm_nt_f32_llama_production()

void gemm_nt_f32_llama_production ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1182 of file gemm_kernels.c.

1187{
1188 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0) {
1189 return;
1190 }
1191
1192#pragma omp parallel for schedule(static) if ((size_t)M * (size_t)N >= 96)
1193 for (int index = 0; index < M * N; ++index) {
1194 ck_gemm_nt_f32_llama_production_output(A, B, bias, C, M, N, K, index);
1195 }
1196}
static void ck_gemm_nt_f32_llama_production_output(const float *A, const float *B, const float *bias, float *C, int M, int N, int K, int index)

References C, and ck_gemm_nt_f32_llama_production_output().

Referenced by ck_moe_shared_q4k_gated_workspace(), and moe_swiglu_shared_forward_q8_0_gated_workspace().

◆ gemm_nt_f32_llama_production_output_range()

void gemm_nt_f32_llama_production_output_range ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
int  output_begin,
int  output_end 
)

Definition at line 1143 of file gemm_kernels.c.

1146{
1147 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0) return;
1148 const int total = M * N;
1149 if (output_begin < 0) output_begin = 0;
1150 if (output_end > total) output_end = total;
1151#if defined(__AVX__) && !defined(__AVX512F__)
1152 const int grouped_reduction = K % 8 == 0;
1153#elif defined(__AVX512F__)
1154 const int grouped_reduction = K % 16 == 0;
1155#endif
1156 int index = output_begin;
1157 while (index < output_end) {
1158#if defined(__AVX__) && !defined(__AVX512F__)
1159 const int row = index / N;
1160 const int col = index - row * N;
1161 if (grouped_reduction && M > 1 && col + 4 <= N && index + 4 <= output_end) {
1162 ck_gemm_nt_f32_llama_production_outputs4_avx2(
1163 A, B, bias, C, N, K, row, col);
1164 index += 4;
1165 continue;
1166 }
1167#elif defined(__AVX512F__)
1168 const int row = index / N;
1169 const int col = index - row * N;
1170 if (grouped_reduction && M > 1 && col + 4 <= N && index + 4 <= output_end) {
1171 ck_gemm_nt_f32_llama_production_outputs4_avx512(
1172 A, B, bias, C, N, K, row, col);
1173 index += 4;
1174 continue;
1175 }
1176#endif
1177 ck_gemm_nt_f32_llama_production_output(A, B, bias, C, M, N, K, index);
1178 ++index;
1179 }
1180}

References C, and ck_gemm_nt_f32_llama_production_output().

◆ gemm_nt_fp32_exact_parallel_dispatch()

void gemm_nt_fp32_exact_parallel_dispatch ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 179 of file gemm_kernels.c.

184{
185 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0) return;
186 ck_gemm_nt_fp32_exact_args_t args = {
187 .A = A, .B = B, .bias = bias, .C = C,
188 .M = M, .N = N, .K = K,
189 .bias_before_reduction = ck_strict_parity_enabled(),
190 };
191 ck_threadpool_t *pool = ck_threadpool_global();
192 if (!pool || ck_threadpool_n_threads(pool) <= 1 || M < 2 ||
193 (size_t)M * (size_t)N <= 4096) {
194 ck_gemm_nt_fp32_exact_rows(0, M, &args);
195 return;
196 }
197 int active = ck_threadpool_n_threads(pool);
198 if (active > M) active = M;
199 int grain = M / (active * 4);
200 if (grain < 1) grain = 1;
202 pool, active, 0, M, grain, ck_gemm_nt_fp32_exact_rows, &args);
203}
static void ck_gemm_nt_fp32_exact_rows(int begin, int end, void *opaque)

References C, ck_gemm_nt_fp32_exact_rows(), ck_strict_parity_enabled(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_parallel_for_n().

◆ gemm_nt_q4_0()

void gemm_nt_q4_0 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Matrix-matrix multiply: C[M,N] = A[M,K] @ B[N,K]^T + bias.

Parameters
AInput matrix [M x K], row-major FP32
BWeight matrix in Q4_0 format, [N x K] stored row-major
biasOptional bias [N], NULL if not used
COutput [M x N], row-major FP32
MBatch size (number of tokens)
NOutput dimension (number of rows in B)
KInput dimension

Definition at line 176 of file gemm_kernels_q4_0.c.

181{
182 const block_q4_0 *blocks = (const block_q4_0 *)B;
183 const int blocks_per_row = K / QK4_0;
184
185 for (int m = 0; m < M; m++) {
186 const float *a_row = &A[m * K];
187
188 for (int n = 0; n < N; n++) {
189 float sum = 0.0f;
190
191 for (int b = 0; b < blocks_per_row; b++) {
192 const block_q4_0 *block = &blocks[n * blocks_per_row + b];
193 const float d = CK_FP16_TO_FP32(block->d);
194 const float *ap = &a_row[b * QK4_0];
195
196 for (int i = 0; i < QK4_0 / 2; i++) {
197 const uint8_t packed = block->qs[i];
198 const int q0 = (packed & 0x0F) - 8;
199 const int q1 = (packed >> 4) - 8;
200
201 sum += d * (float)q0 * ap[2 * i + 0];
202 sum += d * (float)q1 * ap[2 * i + 1];
203 }
204 }
205
206 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
207 }
208 }
209}
uint8_t qs[32/2]

References C, CK_FP16_TO_FP32, block_q4_0::d, QK4_0, and block_q4_0::qs.

Referenced by ck_gemm_nt_quant().

◆ gemm_nt_q4_1()

void gemm_nt_q4_1 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

GEMM with transposed Q4_1 weights: C = A @ B^T.

Parameters
AInput activations [M x K], row-major FP32
BWeight matrix in Q4_1 format [N x K], row-major quantized
biasOptional bias [N], NULL if not used
COutput [M x N], row-major FP32
MBatch size (number of tokens)
NOutput dimension
KInput dimension

Definition at line 256 of file gemm_kernels_q4_1.c.

261{
262 const block_q4_1 *blocks = (const block_q4_1 *)B;
263 const int blocks_per_row = K / QK4_1;
264
265 for (int m = 0; m < M; m++) {
266 const float *a_row = &A[m * K];
267
268 for (int n = 0; n < N; n++) {
269 float sum = 0.0f;
270
271 for (int b = 0; b < blocks_per_row; b++) {
272 const block_q4_1 *block = &blocks[n * blocks_per_row + b];
273 const float d = CK_FP16_TO_FP32(block->d);
274 const float min = CK_FP16_TO_FP32(block->m);
275 const float *ap = &a_row[b * QK4_1];
276
277 for (int i = 0; i < QK4_1 / 2; i++) {
278 const uint8_t packed = block->qs[i];
279 const int q0 = (packed & 0x0F);
280 const int q1 = (packed >> 4);
281
282 const float w0 = d * (float)q0 + min;
283 const float w1 = d * (float)q1 + min;
284
285 sum += w0 * ap[2 * i + 0];
286 sum += w1 * ap[2 * i + 1];
287 }
288 }
289
290 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
291 }
292 }
293}
uint8_t qs[32/2]

References C, CK_FP16_TO_FP32, block_q4_1::d, block_q4_1::m, QK4_1, and block_q4_1::qs.

Referenced by ck_gemm_nt_quant().

◆ gemm_nt_q4_k()

void gemm_nt_q4_k ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 708 of file gemm_kernels_q4k.c.

713{
714 if (!A || !B || !C) {
715 return;
716 }
717 if (M <= 0 || N <= 0 || K <= 0) {
718 return;
719 }
720
721 /* gemm_q4_k produces Y as [batch x M_out]. Here:
722 * batch = M (tokens)
723 * M_out = N (output channels) */
724 gemm_q4_k(C, B, A, /*M_out=*/N, /*N_batch=*/M, K);
725
726 if (!bias) {
727 return;
728 }
729
730 for (int i = 0; i < M; ++i) {
731 float *row = C + (size_t)i * (size_t)N;
732 for (int j = 0; j < N; ++j) {
733 row[j] += bias[j];
734 }
735 }
736}
void gemm_q4_k(float *Y, const void *W, const float *X, int M, int N, int K)
Auto-dispatch GEMM based on available SIMD.

References C, and gemm_q4_k().

Referenced by ck_attention_project_head_major_q4_k(), ck_gemm_nt_quant(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), ck_mlp_swiglu_forward_q4_k(), ck_qkv_project_head_major_q4_k(), ck_qkv_project_head_major_token_q4_k(), model_decode_token(), model_decode_token(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), 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_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), 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_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), 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_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), 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_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), 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_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), 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_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), 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_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), 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_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), 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_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), 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_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), 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_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), 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_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_prefill(), qwen2_0_5b_decode_layer_9_prefill(), qwen2_0_5b_decode_layer_9_prefill(), and qwen2_0_5b_decode_layer_9_prefill().

◆ gemm_nt_q4_k_q8_k()

void gemm_nt_q4_k_q8_k ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 648 of file gemm_kernels_q4k_q8k.c.

653{
654 if (!A_q8 || !B || !C) {
655 return;
656 }
657 if (M <= 0 || N <= 0 || K <= 0) {
658 return;
659 }
660
661 gemm_q4_k_q8_k(C, B, A_q8, /*M_out=*/N, /*N_batch=*/M, K);
662
663 if (!bias) {
664 return;
665 }
666
667 for (int i = 0; i < M; ++i) {
668 float *row = C + (size_t)i * (size_t)N;
669 for (int j = 0; j < N; ++j) {
670 row[j] += bias[j];
671 }
672 }
673}
void gemm_q4_k_q8_k(float *Y, const void *W, const void *X_q8, int M, int N, int K)

References C, and gemm_q4_k_q8_k().

Referenced by ck_attention_project_head_major_q4_k_q8_k(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), ck_mlp_swiglu_forward_q4_k_q8_k(), ck_mlp_swiglu_forward_q4_k_q8_k_prefill(), ck_qkv_project_head_major_token_q4_k_q8_k(), gemm_nt_q8_k_mlp_dispatch(), gemm_nt_q8_k_qkv_dispatch(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), and qwen2_0_5b_decode_forward_prefill_impl().

◆ gemm_nt_q5_0()

void gemm_nt_q5_0 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 833 of file gemm_kernels_q5_0.c.

838{
839 /* For decode (M=1), use direct GEMV which has AVX optimization */
840 if (M == 1) {
841 /* gemm_q5_0 expects column-major output, but we need row-major
842 * So we call gemv_q5_0 directly for each output element */
843 gemv_q5_0(C, B, A, N, K);
844 if (bias) {
845 for (int n = 0; n < N; n++) {
846 C[n] += bias[n];
847 }
848 }
849 return;
850 }
851
852 /* For prefill (M>1), use GEMM which dispatches to GEMV with AVX/AVX512 */
853 /* gemm_q5_0 produces Y as [batch x M_out]. Here:
854 * batch = M (tokens)
855 * M_out = N (output channels) */
856 gemm_q5_0(C, B, A, /*M_out=*/N, /*N_batch=*/M, K);
857
858 if (bias) {
859 for (int m = 0; m < M; m++) {
860 float *row = C + (size_t)m * (size_t)N;
861 for (int n = 0; n < N; n++) {
862 row[n] += bias[n];
863 }
864 }
865 }
866}
void gemv_q5_0(float *y, const void *W, const float *x, int M, int K)
Auto-dispatch GEMV for Q5_0 weights based on CPU features.
void gemm_q5_0(float *Y, const void *W, const float *X, int M, int N, int K)
Matrix-matrix multiply with Q5_0 weights.

References C, gemm_q5_0(), and gemv_q5_0().

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

◆ gemm_nt_q5_1()

void gemm_nt_q5_1 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

GEMM with transposed Q5_1 weights: C = A @ B^T.

Parameters
AInput activations [M x K], row-major FP32
BWeight matrix in Q5_1 format [N x K], row-major quantized
biasOptional bias [N], NULL if not used
COutput [M x N], row-major FP32
MBatch size (number of tokens)
NOutput dimension
KInput dimension

Definition at line 314 of file gemm_kernels_q5_1.c.

319{
320 const block_q5_1 *blocks = (const block_q5_1 *)B;
321 const int blocks_per_row = K / QK5_1;
322
323 for (int m = 0; m < M; m++) {
324 const float *a_row = &A[m * K];
325
326 for (int n = 0; n < N; n++) {
327 float sum = 0.0f;
328
329 for (int b = 0; b < blocks_per_row; b++) {
330 const block_q5_1 *block = &blocks[n * blocks_per_row + b];
331 const float d = CK_FP16_TO_FP32(block->d);
332 const float min = CK_FP16_TO_FP32(block->m);
333 const float *ap = &a_row[b * QK5_1];
334
335 uint32_t qh;
336 memcpy(&qh, block->qh, sizeof(qh));
337
338 for (int i = 0; i < QK5_1 / 2; i++) {
339 const uint8_t packed = block->qs[i];
340 const int lo0 = (packed & 0x0F);
341 const int lo1 = (packed >> 4);
342 const int hi0 = ((qh >> (2 * i + 0)) & 1) << 4;
343 const int hi1 = ((qh >> (2 * i + 1)) & 1) << 4;
344 const int q0 = lo0 | hi0;
345 const int q1 = lo1 | hi1;
346
347 const float w0 = d * (float)q0 + min;
348 const float w1 = d * (float)q1 + min;
349
350 sum += w0 * ap[2 * i + 0];
351 sum += w1 * ap[2 * i + 1];
352 }
353 }
354
355 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
356 }
357 }
358}
uint8_t qs[32/2]
uint8_t qh[4]

References C, CK_FP16_TO_FP32, block_q5_1::d, block_q5_1::m, block_q5_1::qh, QK5_1, and block_q5_1::qs.

Referenced by ck_gemm_nt_quant().

◆ gemm_nt_q5_1_q8_1()

void gemm_nt_q5_1_q8_1 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 320 of file gemm_kernels_q5_1_q8_1.c.

327{
328 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0 || (K % QK5_1) != 0) {
329 return;
330 }
331
332 const int blocks_per_row = K / QK5_1;
333 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) {
334 return;
335 }
336
337 const block_q5_1 *W = (const block_q5_1 *)B;
338
339 for (int m = 0; m < M; ++m) {
340 block_q8_1 a_q8[CK_Q51_STACK_Q8_BLOCKS];
341 quantize_row_q8_1_scalar(&A[m * K], a_q8, K);
342 float *c_row = &C[(size_t)m * (size_t)N];
343
344 int n = 0;
345 for (; n + 7 < N; n += 8) {
346 const block_q5_1 *w0 = &W[(size_t)(n + 0) * (size_t)blocks_per_row];
347 const block_q5_1 *w1 = &W[(size_t)(n + 1) * (size_t)blocks_per_row];
348 const block_q5_1 *w2 = &W[(size_t)(n + 2) * (size_t)blocks_per_row];
349 const block_q5_1 *w3 = &W[(size_t)(n + 3) * (size_t)blocks_per_row];
350 const block_q5_1 *w4 = &W[(size_t)(n + 4) * (size_t)blocks_per_row];
351 const block_q5_1 *w5 = &W[(size_t)(n + 5) * (size_t)blocks_per_row];
352 const block_q5_1 *w6 = &W[(size_t)(n + 6) * (size_t)blocks_per_row];
353 const block_q5_1 *w7 = &W[(size_t)(n + 7) * (size_t)blocks_per_row];
354 float s0 = 0.0f;
355 float s1 = 0.0f;
356 float s2 = 0.0f;
357 float s3 = 0.0f;
358 float s4 = 0.0f;
359 float s5 = 0.0f;
360 float s6 = 0.0f;
361 float s7 = 0.0f;
362
363 for (int b = 0; b < blocks_per_row; ++b) {
364 const block_q8_1 *x = &a_q8[b];
365 s0 += dot_q5_1_q8_1_block(&w0[b], x);
366 s1 += dot_q5_1_q8_1_block(&w1[b], x);
367 s2 += dot_q5_1_q8_1_block(&w2[b], x);
368 s3 += dot_q5_1_q8_1_block(&w3[b], x);
369 s4 += dot_q5_1_q8_1_block(&w4[b], x);
370 s5 += dot_q5_1_q8_1_block(&w5[b], x);
371 s6 += dot_q5_1_q8_1_block(&w6[b], x);
372 s7 += dot_q5_1_q8_1_block(&w7[b], x);
373 }
374
375 c_row[n + 0] = s0 + (bias ? bias[n + 0] : 0.0f);
376 c_row[n + 1] = s1 + (bias ? bias[n + 1] : 0.0f);
377 c_row[n + 2] = s2 + (bias ? bias[n + 2] : 0.0f);
378 c_row[n + 3] = s3 + (bias ? bias[n + 3] : 0.0f);
379 c_row[n + 4] = s4 + (bias ? bias[n + 4] : 0.0f);
380 c_row[n + 5] = s5 + (bias ? bias[n + 5] : 0.0f);
381 c_row[n + 6] = s6 + (bias ? bias[n + 6] : 0.0f);
382 c_row[n + 7] = s7 + (bias ? bias[n + 7] : 0.0f);
383 }
384
385 for (; n < N; ++n) {
386 const block_q5_1 *w_row = &W[(size_t)n * (size_t)blocks_per_row];
387 float sum = 0.0f;
388 for (int b = 0; b < blocks_per_row; ++b) {
389 sum += dot_q5_1_q8_1_block(&w_row[b], &a_q8[b]);
390 }
391 c_row[n] = sum + (bias ? bias[n] : 0.0f);
392 }
393 }
394}
static void quantize_row_q8_1_scalar(const float *x, block_q8_1 *y, int k)
#define CK_Q51_STACK_Q8_BLOCKS
static float dot_q5_1_q8_1_block(const block_q5_1 *w, const block_q8_1 *x)

References C, CK_Q51_STACK_Q8_BLOCKS, dot_q5_1_q8_1_block(), QK5_1, and quantize_row_q8_1_scalar().

Referenced by gemm_nt_q5_1_q8_1_m4().

◆ gemm_nt_q5_1_q8_1_m2()

void gemm_nt_q5_1_q8_1_m2 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 396 of file gemm_kernels_q5_1_q8_1.c.

398{
399 if (!A || !B || !C || M != 2 || N <= 0 || K <= 0 || (K % QK5_1) != 0)
400 return;
401 const int blocks_per_row = K / QK5_1;
402 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) return;
403 block_q8_1 x[2][CK_Q51_STACK_Q8_BLOCKS];
404 quantize_row_q8_1_scalar(A, x[0], K);
405 quantize_row_q8_1_scalar(A + K, x[1], K);
406 const block_q5_1 *weights = (const block_q5_1 *)B;
407 for (int n = 0; n < N; ++n) {
408 const block_q5_1 *w = weights + (size_t)n * (size_t)blocks_per_row;
409 float sums[2] = {0.0f, 0.0f};
410 for (int b = 0; b < blocks_per_row; ++b) {
411#if defined(__AVX2__)
412 float partial[2];
413 dot_q5_1_q8_1_block_m2_avx2(w + b, x[0] + b, x[1] + b, partial);
414 sums[0] += partial[0];
415 sums[1] += partial[1];
416#else
417 sums[0] += dot_q5_1_q8_1_block(w + b, x[0] + b);
418 sums[1] += dot_q5_1_q8_1_block(w + b, x[1] + b);
419#endif
420 }
421 const float add = bias ? bias[n] : 0.0f;
422 C[n] = sums[0] + add;
423 C[(size_t)N + n] = sums[1] + add;
424 }
425}

References C, CK_Q51_STACK_Q8_BLOCKS, dot_q5_1_q8_1_block(), QK5_1, and quantize_row_q8_1_scalar().

◆ gemm_nt_q5_1_q8_1_ref()

void gemm_nt_q5_1_q8_1_ref ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 273 of file gemm_kernels_q5_1_q8_1.c.

278{
279 if (!A_q8 || !B || !C || M <= 0 || N <= 0 || K <= 0 || (K % QK5_1) != 0) {
280 return;
281 }
282
283 const block_q8_1 *A = (const block_q8_1 *)A_q8;
284 const block_q5_1 *W = (const block_q5_1 *)B;
285 const int blocks_per_row = K / QK5_1;
286
287 for (int m = 0; m < M; ++m) {
288 const block_q8_1 *a_row = &A[m * blocks_per_row];
289 for (int n = 0; n < N; ++n) {
290 const block_q5_1 *w_row = &W[n * blocks_per_row];
291 float sum = 0.0f;
292 for (int b = 0; b < blocks_per_row; ++b) {
293 sum += dot_q5_1_q8_1_block(&w_row[b], &a_row[b]);
294 }
295 C[m * N + n] = sum + (bias ? bias[n] : 0.0f);
296 }
297 }
298}

References C, dot_q5_1_q8_1_block(), and QK5_1.

◆ gemm_nt_q5_k()

void gemm_nt_q5_k ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1028 of file gemm_kernels_q5_k.c.

1033{
1034#if defined(__AVX512F__)
1035 /* TODO: AVX-512 implementation */
1036 gemm_nt_q5_k_ref(A, B, bias, C, M, N, K);
1037#elif defined(__AVX2__)
1038 /* TODO: AVX-2 implementation */
1039 gemm_nt_q5_k_ref(A, B, bias, C, M, N, K);
1040#elif defined(__AVX__)
1041 /* TODO: AVX implementation */
1042 gemm_nt_q5_k_ref(A, B, bias, C, M, N, K);
1043#elif defined(__SSE4_1__)
1044 /* TODO: SSE4.1 implementation */
1045 gemm_nt_q5_k_ref(A, B, bias, C, M, N, K);
1046#else
1047 gemm_nt_q5_k_ref(A, B, bias, C, M, N, K);
1048#endif
1049}
void gemm_nt_q5_k_ref(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)

References C, and gemm_nt_q5_k_ref().

◆ gemm_nt_q5_k_q8_k()

void gemm_nt_q5_k_q8_k ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 914 of file gemm_kernels_q5_k.c.

919{
920#if defined(__AVX512F__)
921 /* TODO: AVX-512 implementation */
922 gemm_nt_q5_k_q8_k_ref(A_q8, B, bias, C, M, N, K);
923#elif defined(__AVX2__)
924 /* TODO: AVX-2 implementation */
925 gemm_nt_q5_k_q8_k_ref(A_q8, B, bias, C, M, N, K);
926#elif defined(__AVX__)
927 /* TODO: AVX implementation */
928 gemm_nt_q5_k_q8_k_ref(A_q8, B, bias, C, M, N, K);
929#elif defined(__SSE4_1__)
930 /* TODO: SSE4.1 implementation */
931 gemm_nt_q5_k_q8_k_ref(A_q8, B, bias, C, M, N, K);
932#else
933 gemm_nt_q5_k_q8_k_ref(A_q8, B, bias, C, M, N, K);
934#endif
935}
void gemm_nt_q5_k_q8_k_ref(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)

References C, and gemm_nt_q5_k_q8_k_ref().

◆ gemm_nt_q5_k_q8_k_m2()

void gemm_nt_q5_k_q8_k_m2 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 985 of file gemm_kernels_q5_k.c.

988{
989 if (!A || !B || !C || M != 2 || N <= 0 || K <= 0 ||
990 (K % QK_K) != 0 || K / QK_K > CK_Q5K_STACK_Q8_BLOCKS) return;
992 gemv_q5_k_ref_fp32(C, B, A, N, K);
993 gemv_q5_k_ref_fp32(C + N, B, A + K, N, K);
994 } else {
996 quantize_row_q8_k(A, x[0], K);
997 quantize_row_q8_k(A + K, x[1], K);
998 const void *rows[4] = {x[0], x[1], NULL, NULL};
999 gemm_q5_k_q8_k_compact_rows4(C, N, B, rows, 2, N, K);
1000 }
1001 if (bias) {
1002 for (int n = 0; n < N; ++n) {
1003 C[n] += bias[n];
1004 C[(size_t)N + n] += bias[n];
1005 }
1006 }
1007}
void gemm_q5_k_q8_k_compact_rows4(float *output, int output_stride, const void *weights, const void *const input_rows[4], int rows, int output_dim, int input_dim)
void quantize_row_q8_k(const float *x, void *vy, int k)
static int ck_q5k_debug_fp32_fallback(void)
#define CK_Q5K_STACK_Q8_BLOCKS
static void gemv_q5_k_ref_fp32(float *y, const void *W, const float *x, int M, int K)
#define QK_K

References C, ck_q5k_debug_fp32_fallback(), CK_Q5K_STACK_Q8_BLOCKS, gemm_q5_k_q8_k_compact_rows4(), gemv_q5_k_ref_fp32(), QK_K, and quantize_row_q8_k().

◆ gemm_nt_q6_k()

void gemm_nt_q6_k ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 212 of file gemm_kernels_q6k.c.

217{
218 if (!A || !B || !C) {
219 return;
220 }
221 if (M <= 0 || N <= 0 || K <= 0) {
222 return;
223 }
224
225 /* gemm_q6_k produces Y as [batch x M_out] where:
226 * batch = M (tokens)
227 * M_out = N (output channels) */
228 gemm_q6_k(C, B, A, /*M_out=*/N, /*N_batch=*/M, K);
229
230 if (!bias) {
231 return;
232 }
233
234 for (int i = 0; i < M; ++i) {
235 float *row = C + (size_t)i * (size_t)N;
236 for (int j = 0; j < N; ++j) {
237 row[j] += bias[j];
238 }
239 }
240}
void gemm_q6_k(float *Y, const void *W, const float *X, int M, int N, int K)

References C, and gemm_q6_k().

Referenced by ck_gemm_nt_quant(), gemm_nt_q6_k_ref(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_8_decode(), and qwen2_0_5b_decode_layer_9_decode().

◆ gemm_nt_q6_k_q8_k()

void gemm_nt_q6_k_q8_k ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1548 of file gemm_kernels_q6k_q8k.c.

1553{
1554 if (!A_q8 || !B || !C) {
1555 return;
1556 }
1557 if (M <= 0 || N <= 0 || K <= 0) {
1558 return;
1559 }
1560#if defined(__AVX2__) && defined(__FMA__)
1561 if (M >= 8 && ck_strict_parity_enabled()) {
1562 gemm_nt_q6_k_q8_k_tiled_parity(A_q8, B, bias, C, M, N, K);
1563 return;
1564 }
1565#endif
1566
1567 /* Prefill GEMM uses the pinned x86 leaf reduction for short row groups
1568 * and the tiled reduction for strict batches of at least eight rows.
1569 * CK_DEBUG_Q6K_Q8K_REF=1 still forces the scalar reference leaf. */
1570 const block_q8_K *A = (const block_q8_K *)A_q8;
1571 const block_q6_K *W = (const block_q6_K *)B;
1572 const int blocks_per_vec = K / QK_K;
1573 const int blocks_per_row = K / QK_K;
1574
1575 for (int m = 0; m < M; ++m) {
1576 const block_q8_K *a_row = A + (size_t)m * (size_t)blocks_per_vec;
1577 float *c_row = C + (size_t)m * (size_t)N;
1578 for (int n = 0; n < N; ++n) {
1579 const block_q6_K *w_row = W + (size_t)n * (size_t)blocks_per_row;
1580 const float b = bias ? bias[n] : 0.0f;
1581 c_row[n] = ck_dot_q6_k_q8_k_fast_or_ref(w_row, a_row, K) + b;
1582 }
1583 }
1584}
void gemm_nt_q6_k_q8_k_tiled_parity(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K)
NT GEMM: C = A @ B^T where A is Q8_K and B is Q6_K.
static float ck_dot_q6_k_q8_k_fast_or_ref(const block_q6_K *w, const block_q8_K *x, int K)

References C, ck_dot_q6_k_q8_k_fast_or_ref(), ck_strict_parity_enabled(), gemm_nt_q6_k_q8_k_tiled_parity(), and QK_K.

Referenced by gemm_nt_q8_k_mlp_dispatch(), and gemm_nt_q8_k_qkv_dispatch().

◆ gemm_nt_q6_k_q8_k_m2()

void gemm_nt_q6_k_q8_k_m2 ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 1854 of file gemm_kernels_q6k_q8k.c.

1857{
1858 if (!A_q8 || !B || !C || M != 2 || N <= 0 || K <= 0 ||
1859 (K % QK_K) != 0) return;
1860 gemm_nt_q6_k_q8_k_m4_tile(A_q8, B, bias, C, M, N, K,
1861 0, M, 0, N);
1862}
void gemm_nt_q6_k_q8_k_m4_tile(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)

References C, gemm_nt_q6_k_q8_k_m4_tile(), and QK_K.

◆ gemm_nt_q6_k_q8_k_m4_tile()

void gemm_nt_q6_k_q8_k_m4_tile ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
int  m0,
int  m1,
int  n0,
int  n1 
)

Definition at line 1797 of file gemm_kernels_q6k_q8k.c.

1804{
1805 if (!A_q8 || !B || !C || M <= 0 || N <= 0 || K <= 0 ||
1806 K % QK_K != 0) {
1807 return;
1808 }
1809 if (m0 < 0) m0 = 0;
1810 if (n0 < 0) n0 = 0;
1811 if (m1 > M) m1 = M;
1812 if (n1 > N) n1 = N;
1813 if (m0 >= m1 || n0 >= n1) return;
1814
1815#if defined(__AVX2__)
1817 const block_q8_K *A = (const block_q8_K *)A_q8;
1818 const block_q6_K *W = (const block_q6_K *)B;
1819 const int blocks_per_vec = K / QK_K;
1820 for (int n = n0; n < n1; ++n) {
1821 const block_q6_K *w_row =
1822 W + (size_t)n * (size_t)blocks_per_vec;
1823 const float b = bias ? bias[n] : 0.0f;
1824 int m = m0;
1825 for (; m + 4 <= m1; m += 4) {
1826 float values[4];
1827 dot_q6_k_q8_k_avx2_m4(
1828 w_row, A + (size_t)m * (size_t)blocks_per_vec,
1829 blocks_per_vec, 4, K, values);
1830 for (int r = 0; r < 4; ++r) {
1831 C[(size_t)(m + r) * (size_t)N + (size_t)n] = values[r] + b;
1832 }
1833 }
1834 if (m < m1) {
1835 float values[4];
1836 const int rows = m1 - m;
1837 dot_q6_k_q8_k_avx2_m4(
1838 w_row, A + (size_t)m * (size_t)blocks_per_vec,
1839 blocks_per_vec, rows, K, values);
1840 for (int r = 0; r < rows; ++r) {
1841 C[(size_t)(m + r) * (size_t)N + (size_t)n] = values[r] + b;
1842 }
1843 }
1844 }
1845 return;
1846 }
1847#endif
1849 A_q8, B, bias, C, M, N, K, m0, m1, n0, n1);
1850}
void gemm_nt_q6_k_q8_k_tile(const void *A_q8, const void *B, const float *bias, float *C, int M, int N, int K, int m0, int m1, int n0, int n1)
Compute one C[m0:m1, n0:n1] tile for Q8_K activations x Q6_K weights.

References C, ck_q6k_q8k_force_ref(), ck_strict_parity_enabled(), gemm_nt_q6_k_q8_k_tile(), and QK_K.

Referenced by gemm_nt_q6_k_q8_k_m2().

◆ gemm_nt_q6_k_q8_k_tile()

void gemm_nt_q6_k_q8_k_tile ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
int  m0,
int  m1,
int  n0,
int  n1 
)

Compute one C[m0:m1, n0:n1] tile for Q8_K activations x Q6_K weights.

Pure tile math only: no threadpool, no global scheduling, no allocation. The orchestrator decides how to split tile jobs across cores.

Definition at line 1760 of file gemm_kernels_q6k_q8k.c.

1767{
1768 if (!A_q8 || !B || !C) {
1769 return;
1770 }
1771 if (M <= 0 || N <= 0 || K <= 0 || K % QK_K != 0) {
1772 return;
1773 }
1774 if (m0 < 0) m0 = 0;
1775 if (n0 < 0) n0 = 0;
1776 if (m1 > M) m1 = M;
1777 if (n1 > N) n1 = N;
1778 if (m0 >= m1 || n0 >= n1) {
1779 return;
1780 }
1781
1782 const block_q8_K *A = (const block_q8_K *)A_q8;
1783 const block_q6_K *W = (const block_q6_K *)B;
1784 const int blocks_per_vec = K / QK_K;
1785 const int blocks_per_row = K / QK_K;
1786
1787 for (int n = n0; n < n1; ++n) {
1788 const block_q6_K *w_row = W + (size_t)n * (size_t)blocks_per_row;
1789 const float b = bias ? bias[n] : 0.0f;
1790 for (int m = m0; m < m1; ++m) {
1791 const block_q8_K *a_row = A + (size_t)m * (size_t)blocks_per_vec;
1792 C[(size_t)m * (size_t)N + (size_t)n] = ck_dot_q6_k_q8_k_fast_or_ref(w_row, a_row, K) + b;
1793 }
1794 }
1795}

References C, ck_dot_q6_k_q8_k_fast_or_ref(), and QK_K.

Referenced by gemm_nt_q6_k_q8_k_m4_tile(), and gemm_nt_q6_k_q8_k_tiled().

◆ gemm_nt_q6_k_q8_k_tiled()

void gemm_nt_q6_k_q8_k_tiled ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Experimental single-thread tiled NT GEMM wrapper.

Kept as a separate symbol from gemm_nt_q6_k_q8_k for benchmarks and parity. Production prefill should prefer the v8 2D tile scheduler when enabled.

Definition at line 1870 of file gemm_kernels_q6k_q8k.c.

1875{
1876 enum { TILE_M = 8, TILE_N = 16 };
1877 for (int n0 = 0; n0 < N; n0 += TILE_N) {
1878 const int n1 = (n0 + TILE_N < N) ? (n0 + TILE_N) : N;
1879 for (int m0 = 0; m0 < M; m0 += TILE_M) {
1880 const int m1 = (m0 + TILE_M < M) ? (m0 + TILE_M) : M;
1881 gemm_nt_q6_k_q8_k_tile(A_q8, B, bias, C, M, N, K, m0, m1, n0, n1);
1882 }
1883 }
1884}

References C, and gemm_nt_q6_k_q8_k_tile().

◆ gemm_nt_q8_0()

void gemm_nt_q8_0 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 879 of file gemm_kernels_q8_0.c.

884{
885#if defined(__AVX512F__)
886 if (ck_q8_0_fp32_m4n4_enabled() && M >= 4 && N >= 4 && K % QK8_0 == 0) {
887 gemm_nt_q8_0_m4n4_avx512(A, B, bias, C, M, N, K);
888 return;
889 }
890#endif
891 gemm_nt_q8_0_rowloop(A, B, bias, C, M, N, K);
892}
static void gemm_nt_q8_0_rowloop(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
Matrix-matrix multiply: C[M,N] = A[M,K] @ B[N,K]^T + bias.
static int ck_q8_0_fp32_m4n4_enabled(void)

References C, ck_q8_0_fp32_m4n4_enabled(), gemm_nt_q8_0_rowloop(), and QK8_0.

Referenced by ck_gemm_nt_quant(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_8_decode(), and qwen2_0_5b_decode_layer_9_decode().

◆ gemm_nt_q8_0_q8_0()

void gemm_nt_q8_0_q8_0 ( const void *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

gemm_nt_q8_0_q8_0 with optional bias (matches header signature)

C[m,n] = A[m,K] @ B[n,K]^T + bias[n]

Definition at line 552 of file gemm_batch_int8.c.

558{
559 /* First compute GEMM */
560#if defined(__AVX2__)
561 /*
562 * The production contract is bit-exact with llama.cpp's eight-lane
563 * FP32 accumulation tree. AVX-512/VNNI changes the integer dot, but it
564 * must not silently replace that FP32 reduction with the scalar-per-block
565 * candidate above. The AVX2-named entry point delegates each activation
566 * row to the certified x4 provider, which also uses VNNI instructions when
567 * they are available while preserving the declared reduction order.
568 */
569 gemm_nt_q8_0_q8_0_avx2(A, B, C, M, N, K);
570#elif defined(__AVX__)
571 gemm_nt_q8_0_q8_0_avx(A, B, C, M, N, K);
572#else
573 gemm_nt_q8_0_q8_0_ref(A, B, C, M, N, K);
574#endif
575
576 /* Add bias if provided */
577 if (bias != NULL) {
578 for (int m = 0; m < M; m++) {
579 for (int n = 0; n < N; n++) {
580 C[(size_t)m * N + n] += bias[n];
581 }
582 }
583 }
584}
void gemm_nt_q8_0_q8_0_ref(const void *A, const void *B, float *C, int M, int N, int K)
Scalar reference: gemm_nt_q8_0_q8_0.

References C, and gemm_nt_q8_0_q8_0_ref().

Referenced by gemm_nt_q8_0_dispatch(), and gemm_nt_q8_0_mlp_dispatch().

◆ gemm_nt_q8_0_q8_0_contract()

void gemm_nt_q8_0_q8_0_contract ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 447 of file gemm_kernels_q8_0_q8_0_contract.c.

454{
455 if (!A || !B || !C || M <= 0 || N <= 0 || K <= 0) {
456 return;
457 }
458
459 const float *A_use = A;
460 const int strict = ck_strict_parity_enabled();
461 const int dump_enabled = strict && ck_q80_contract_dump_enabled();
462 int strict_cached_layer = -1;
463 int strict_dump_layer = -1;
465 const float *cached = ck_strict_consume_next_gemm_a((size_t) M * (size_t) K);
466 if (cached) {
467 A_use = cached;
468 strict_cached_layer = ck_q80_contract_cached_gemm_seq++;
469 }
470 }
471 if (dump_enabled) {
472 strict_dump_layer = strict_cached_layer >= 0
473 ? strict_cached_layer
475 }
476
477 if (dump_enabled && strict_dump_layer >= 0) {
478 ck_q80_contract_dump_tensor(strict_cached_layer >= 0
479 ? "strict_out_proj_input_cached"
480 : "strict_out_proj_input_live",
481 strict_dump_layer,
482 A_use,
483 (size_t) M * (size_t) K);
484 }
485
486 if (strict &&
487 gemm_nt_q8_0_q8_0_ggml_strict(A_use, B, bias, C, M, N, K)) {
488 if (dump_enabled && strict_dump_layer >= 0) {
489 ck_q80_contract_dump_tensor("strict_out_proj_output_ggml",
490 strict_dump_layer,
491 C,
492 (size_t) M * (size_t) N);
493 }
494 return;
495 }
496
497 if (!strict) {
498#pragma omp parallel for schedule(static) if(M > 1)
499 for (int m = 0; m < M; ++m) {
500 gemv_q8_0_q8_0_contract(&C[m * N], B, &A_use[m * K], N, K);
501 if (bias) {
502 for (int n = 0; n < N; ++n) {
503 C[m * N + n] += bias[n];
504 }
505 }
506 }
507 return;
508 }
509
510 for (int m = 0; m < M; ++m) {
511 gemv_q8_0_q8_0_contract(&C[m * N], B, &A_use[m * K], N, K);
512 if (bias) {
513 for (int n = 0; n < N; ++n) {
514 C[m * N + n] += bias[n];
515 }
516 }
517 }
518
519 if (dump_enabled && strict_dump_layer >= 0) {
520 ck_q80_contract_dump_tensor("strict_out_proj_output_fallback",
521 strict_dump_layer,
522 C,
523 (size_t) M * (size_t) N);
524 }
525}
const float * ck_strict_consume_next_gemm_a(size_t elems)
static int gemm_nt_q8_0_q8_0_ggml_strict(const float *A, const void *B, const float *bias, float *C, int M, int N, int K)
void gemv_q8_0_q8_0_contract(float *y, const void *W, const float *x, int M, int K)
static int ck_q80_contract_cached_input_enabled(void)
static void ck_q80_contract_dump_tensor(const char *name, int layer_id, const float *data, size_t elem_count)
static int ck_q80_contract_cached_gemm_seq
static int ck_q80_contract_dump_enabled(void)

References C, ck_q80_contract_cached_gemm_seq, ck_q80_contract_cached_input_enabled(), ck_q80_contract_dump_enabled(), ck_q80_contract_dump_tensor(), ck_strict_consume_next_gemm_a(), ck_strict_parity_enabled(), gemm_nt_q8_0_q8_0_ggml_strict(), and gemv_q8_0_q8_0_contract().

◆ gemm_nt_q8_0_q8_0_contract_m2()

void gemm_nt_q8_0_q8_0_contract_m2 ( const float *  A,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 418 of file gemm_kernels_q8_0_q8_0_contract.c.

421{
422 if (!A || !B || !C || M != 2 || N <= 0 || K <= 0 ||
423 (K % QK8_0) != 0 || K / QK8_0 > CK_Q80_STACK_Q8_BLOCKS) return;
424 const int nb = K / QK8_0;
428 quantize_row_q8_0_ref_local(A + K, x + nb, K);
429 } else {
430 quantize_row_q8_0(A, x, K);
431 quantize_row_q8_0(A + K, x + nb, K);
432 }
434 gemv_q8_0_q8_0_ref_rows(C, B, x, N, K);
435 gemv_q8_0_q8_0_ref_rows(C + N, B, x + nb, N, K);
436 } else {
437 gemm_q8_0_q8_0_m2n4_strided(C, N, B, x, 2, N, K);
438 }
439 if (bias) {
440 for (int n = 0; n < N; ++n) {
441 C[n] += bias[n];
442 C[(size_t)N + n] += bias[n];
443 }
444 }
445}
static void quantize_row_q8_0_ref_local(const float *x, block_q8_0 *y, int k)
static void gemv_q8_0_q8_0_ref_rows(float *y, const void *W, const void *x_q8, int M, int K)
#define CK_Q80_STACK_Q8_BLOCKS
void gemm_q8_0_q8_0_m2n4_strided(float *C, int ldc, const void *W, const void *A_q8, int M, int N, int K)

References C, CK_Q80_STACK_Q8_BLOCKS, ck_strict_parity_enabled(), gemm_q8_0_q8_0_m2n4_strided(), gemv_q8_0_q8_0_ref_rows(), QK8_0, quantize_row_q8_0(), and quantize_row_q8_0_ref_local().

◆ gemm_nt_q8_0_q8_0_m2n4()

void gemm_nt_q8_0_q8_0_m2n4 ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 586 of file gemm_batch_int8.c.

592{
593 gemm_q8_0_q8_0_m2n4(C, B, A, M, N, K);
594 if (bias != NULL) {
595 for (int m = 0; m < M; ++m) {
596 for (int n = 0; n < N; ++n) {
597 C[(size_t)m * (size_t)N + n] += bias[n];
598 }
599 }
600 }
601}
void gemm_q8_0_q8_0_m2n4(float *C, const void *W, const void *A_q8, int M, int N, int K)

References C, and gemm_q8_0_q8_0_m2n4().

◆ gemm_nt_q8_0_q8_0_m2n4_tile()

void gemm_nt_q8_0_q8_0_m2n4_tile ( const void *  A_q8,
const void *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K,
int  ldc 
)

Definition at line 603 of file gemm_batch_int8.c.

609{
610 gemm_q8_0_q8_0_m2n4_strided(C, ldc, B, A, M, N, K);
611 if (bias != NULL) {
612 for (int m = 0; m < M; ++m) {
613 for (int n = 0; n < N; ++n) {
614 C[(size_t)m * (size_t)ldc + n] += bias[n];
615 }
616 }
617 }
618}
void gemm_q8_0_q8_0_m2n4_strided(float *C, int ldc, const void *W, const void *A_q8, int M, int N, int K)

References C, and gemm_q8_0_q8_0_m2n4_strided().

◆ gemm_q4_k()

void gemm_q4_k ( float *  Y,
const void *  W,
const float *  X,
int  M,
int  N,
int  K 
)

Auto-dispatch GEMM based on available SIMD.

Definition at line 486 of file gemm_kernels_q4k.c.

490{
491 /* Use reference implementation for correctness
492 * TODO: Fix AVX-512 version to match llama.cpp layout */
493 gemm_q4_k_ref(Y, W, X, M, N, K);
494}
void gemm_q4_k_ref(float *Y, const void *W, const float *X, int M, int N, int K)
Matrix-matrix multiply with Q4_K weights (scalar reference)

References gemm_q4_k_ref().

Referenced by gemm_nt_q4_k().

◆ gemm_q4_k_q8_k()

void gemm_q4_k_q8_k ( float *  Y,
const void *  W,
const void *  X_q8,
int  M,
int  N,
int  K 
)

Definition at line 605 of file gemm_kernels_q4k_q8k.c.

609{
610 if (!Y || !W || !X_q8 || M <= 0 || N <= 0 || K <= 0) {
611 return;
612 }
613
614 const block_q8_K *X = (const block_q8_K *)X_q8;
615 const int blocks_per_vec = K / QK_K;
616 const int blocks_per_row = K / QK_K;
617 const size_t work_items = (size_t)M * (size_t)N;
618
619 if (work_items >= 4096u && M >= 512 && N > 1) {
620 ck_threadpool_t *pool = ck_threadpool_global();
621 const int pool_threads = pool ? ck_threadpool_n_threads(pool) : 1;
622 int active_threads = pool_threads;
623 if (active_threads > M) {
624 active_threads = M;
625 }
626 if (active_threads > 1) {
627 gemm_q4_k_q8_k_work_t work = {
628 .Y = Y,
629 .W = W,
630 .X = X,
631 .M_out = M,
632 .N_batch = N,
633 .K = K,
634 .blocks_per_vec = blocks_per_vec,
635 .blocks_per_row = blocks_per_row,
636 };
637 ck_threadpool_dispatch_n(pool, active_threads, gemm_q4_k_q8_k_thread_fn, &work);
638 return;
639 }
640 }
641
642 for (int n = 0; n < N; ++n) {
643 const block_q8_K *x_row = X + (size_t)n * (size_t)blocks_per_vec;
644 gemv_q4_k_q8_k(&Y[n * M], W, x_row, M, K);
645 }
646}
void gemv_q4_k_q8_k(float *y, const void *W, const void *x_q8, int M, int K)
static void gemm_q4_k_q8_k_thread_fn(int ith, int nth, void *args)

References ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), gemm_q4_k_q8_k_thread_fn(), gemv_q4_k_q8_k(), and QK_K.

Referenced by gemm_nt_q4_k_q8_k().

◆ gemm_q6_k()

void gemm_q6_k ( float *  Y,
const void *  W,
const float *  X,
int  M,
int  N,
int  K 
)

Definition at line 195 of file gemm_kernels_q6k.c.

199{
200 if (!Y || !W || !X) {
201 return;
202 }
203 if (M <= 0 || N <= 0 || K <= 0) {
204 return;
205 }
206
207 for (int n = 0; n < N; ++n) {
208 gemv_q6_k(&Y[n * M], W, &X[n * K], M, K);
209 }
210}
void gemv_q6_k(float *y, const void *W, const float *x, int M, int K)

References gemv_q6_k().

Referenced by gemm_nt_q6_k().

◆ gemm_q6_k_q8_k()

void gemm_q6_k_q8_k ( float *  Y,
const void *  W,
const void *  X_q8,
int  M,
int  N,
int  K 
)

GEMM: Y = W @ X^T where W is Q6_K and X is Q8_K.

Parameters
YOutput matrix [N x M] in row-major
WWeight matrix in Q6_K format [M x K]
X_q8Input matrix in Q8_K format [N x K]
MNumber of output rows (output dim)
NNumber of input vectors (batch size)
KInput dimension

Definition at line 1508 of file gemm_kernels_q6k_q8k.c.

1512{
1513 if (!Y || !W || !X_q8 || M <= 0 || N <= 0 || K <= 0) {
1514 return;
1515 }
1516
1517 const block_q8_K *X = (const block_q8_K *)X_q8;
1518 const int blocks_per_vec = K / QK_K;
1519
1520 for (int n = 0; n < N; ++n) {
1521 const block_q8_K *x_row = X + (size_t)n * (size_t)blocks_per_vec;
1522 gemv_q6_k_q8_k(&Y[n * M], W, x_row, M, K);
1523 }
1524}
void gemv_q6_k_q8_k(float *y, const void *W, const void *x_q8, int M, int K)
GEMV: y = W @ x where W is Q6_K and x is Q8_K.

References gemv_q6_k_q8_k(), and QK_K.

◆ gemm_swiglu_fused()

void gemm_swiglu_fused ( const float *  x,
const float *  W_gate,
const float *  W_up,
const float *  b_gate,
const float *  b_up,
float *  output,
int  M,
int  N,
int  K 
)

Definition at line 241 of file gemm_fused_kernels.c.

248{
249#if defined(__AVX__)
250#pragma omp parallel for
251 for (int i = 0; i < M; i++) {
252 const float *x_row = &x[i * K];
253 float *out_row = &output[i * N];
254
255 for (int j = 0; j < N; j++) {
256 const float *w_gate_row = &W_gate[j * K];
257 const float *w_up_row = &W_up[j * K];
258
259 // Compute both dot products in parallel using SIMD
260 __m256 gate_vec = _mm256_setzero_ps();
261 __m256 up_vec = _mm256_setzero_ps();
262
263 int k;
264 for (k = 0; k <= K - 8; k += 8) {
265 __m256 x_vec = _mm256_loadu_ps(&x_row[k]);
266 __m256 wg_vec = _mm256_loadu_ps(&w_gate_row[k]);
267 __m256 wu_vec = _mm256_loadu_ps(&w_up_row[k]);
268
269 // gate += x * W_gate
270 gate_vec = _mm256_add_ps(gate_vec, _mm256_mul_ps(x_vec, wg_vec));
271 // up += x * W_up
272 up_vec = _mm256_add_ps(up_vec, _mm256_mul_ps(x_vec, wu_vec));
273 }
274
275 // Horizontal sum
276 float gate = hsum256_ps_fused(gate_vec);
277 float up = hsum256_ps_fused(up_vec);
278
279 // Scalar remainder
280 for (; k < K; k++) {
281 gate += x_row[k] * w_gate_row[k];
282 up += x_row[k] * w_up_row[k];
283 }
284
285 // Add biases
286 if (b_gate) gate += b_gate[j];
287 if (b_up) up += b_up[j];
288
289 // SwiGLU: SiLU(gate) * up = gate * sigmoid(gate) * up
290 float sig = 1.0f / (1.0f + expf(-gate));
291 out_row[j] = gate * sig * up;
292 }
293 }
294#else
295 // Scalar fallback
296#pragma omp parallel for
297 for (int i = 0; i < M; i++) {
298 for (int j = 0; j < N; j++) {
299 float gate = 0.0f;
300 float up = 0.0f;
301
302 for (int k = 0; k < K; k++) {
303 gate += x[i * K + k] * W_gate[j * K + k];
304 up += x[i * K + k] * W_up[j * K + k];
305 }
306
307 if (b_gate) gate += b_gate[j];
308 if (b_up) up += b_up[j];
309
310 // SwiGLU: SiLU(gate) * up
311 float sig = 1.0f / (1.0f + expf(-gate));
312 output[i * N + j] = gate * sig * up;
313 }
314 }
315#endif
316}

Referenced by ck_mlp_swiglu_forward_fused_token().

◆ gemm_tn_avx512()

void gemm_tn_avx512 ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 709 of file gemm_kernels.c.

714{
716 gemm_tn_serial_double(A, B, bias, C, M, N, K);
717 return;
718 }
719#if defined(__AVX512F__)
720 // Vectorize over N (output columns)
721#pragma omp parallel for
722 for (int i = 0; i < M; i++) {
723 int j = 0;
724 for (; j <= N - 16; j += 16) {
725 __m512 sum_vec = bias ? _mm512_loadu_ps(&bias[j]) : _mm512_setzero_ps();
726 for (int k = 0; k < K; k++) {
727 __m512 a_broadcast = _mm512_set1_ps(A[k * M + i]);
728 __m512 b_vec = _mm512_loadu_ps(&B[k * N + j]);
729 sum_vec = _mm512_fmadd_ps(a_broadcast, b_vec, sum_vec);
730 }
731 _mm512_storeu_ps(&C[i * N + j], sum_vec);
732 }
733 for (; j < N; j++) {
734 float sum = bias ? bias[j] : 0.0f;
735 for (int k = 0; k < K; k++) {
736 sum += A[k * M + i] * B[k * N + j];
737 }
738 C[i * N + j] = sum;
739 }
740 }
741#elif defined(__AVX__)
742 // AVX1: vectorize over N (8 columns at a time)
743#pragma omp parallel for
744 for (int i = 0; i < M; i++) {
745 int j = 0;
746 for (; j <= N - 8; j += 8) {
747 __m256 sum_vec = bias ? _mm256_loadu_ps(&bias[j]) : _mm256_setzero_ps();
748 for (int k = 0; k < K; k++) {
749 __m256 a_broadcast = _mm256_set1_ps(A[k * M + i]);
750 __m256 b_vec = _mm256_loadu_ps(&B[k * N + j]);
751 __m256 prod = _mm256_mul_ps(a_broadcast, b_vec);
752 sum_vec = _mm256_add_ps(sum_vec, prod);
753 }
754 _mm256_storeu_ps(&C[i * N + j], sum_vec);
755 }
756 for (; j < N; j++) {
757 float sum = bias ? bias[j] : 0.0f;
758 for (int k = 0; k < K; k++) {
759 sum += A[k * M + i] * B[k * N + j];
760 }
761 C[i * N + j] = sum;
762 }
763 }
764#else
765 gemm_tn_parallel(A, B, bias, C, M, N, K);
766#endif
767}
void gemm_tn_parallel(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)
static void gemm_tn_serial_double(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References C, ck_strict_parity_enabled(), gemm_tn_parallel(), and gemm_tn_serial_double().

◆ gemm_tn_blocked()

void gemm_tn_blocked ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 769 of file gemm_kernels.c.

774{
776 gemm_tn_serial_double(A, B, bias, C, M, N, K);
777 return;
778 }
779#if defined(__AVX512F__)
780 const int block_size = 64;
781#elif defined(__AVX__)
782 const int block_size = 32;
783#else
784 const int block_size = 32;
785#endif
786 // Initialize C with bias (parallelized)
787#pragma omp parallel for
788 for (int i = 0; i < M; i++) {
789 for (int j = 0; j < N; j++) {
790 C[i * N + j] = bias ? bias[j] : 0.0f;
791 }
792 }
793 // Blocked multiply-accumulate (parallelized over M blocks)
794#pragma omp parallel for
795 for (int ii = 0; ii < M; ii += block_size) {
796 for (int kk = 0; kk < K; kk += block_size) {
797 for (int jj = 0; jj < N; jj += block_size) {
798 int i_end = ck_min(ii + block_size, M);
799 int k_end = ck_min(kk + block_size, K);
800 int j_end = ck_min(jj + block_size, N);
801
802 for (int k = kk; k < k_end; k++) {
803 for (int i = ii; i < i_end; i++) {
804 float a_val = A[k * M + i];
805#if defined(__AVX512F__)
806 __m512 a_broadcast = _mm512_set1_ps(a_val);
807 int j;
808 for (j = jj; j <= j_end - 16; j += 16) {
809 __m512 b_vec = _mm512_loadu_ps(&B[k * N + j]);
810 __m512 c_vec = _mm512_loadu_ps(&C[i * N + j]);
811 c_vec = _mm512_fmadd_ps(a_broadcast, b_vec, c_vec);
812 _mm512_storeu_ps(&C[i * N + j], c_vec);
813 }
814 for (; j < j_end; j++) {
815 C[i * N + j] += a_val * B[k * N + j];
816 }
817#elif defined(__AVX__)
818 __m256 a_broadcast = _mm256_set1_ps(a_val);
819 int j;
820 for (j = jj; j <= j_end - 8; j += 8) {
821 __m256 b_vec = _mm256_loadu_ps(&B[k * N + j]);
822 __m256 c_vec = _mm256_loadu_ps(&C[i * N + j]);
823 __m256 prod = _mm256_mul_ps(a_broadcast, b_vec);
824 c_vec = _mm256_add_ps(c_vec, prod);
825 _mm256_storeu_ps(&C[i * N + j], c_vec);
826 }
827 for (; j < j_end; j++) {
828 C[i * N + j] += a_val * B[k * N + j];
829 }
830#else
831 for (int j = jj; j < j_end; j++) {
832 C[i * N + j] += a_val * B[k * N + j];
833 }
834#endif
835 }
836 }
837 }
838 }
839 }
840}

References C, ck_min(), ck_strict_parity_enabled(), and gemm_tn_serial_double().

◆ gemm_tn_parallel()

void gemm_tn_parallel ( const float *  A,
const float *  B,
const float *  bias,
float *  C,
int  M,
int  N,
int  K 
)

Definition at line 687 of file gemm_kernels.c.

692{
694 gemm_tn_serial_double(A, B, bias, C, M, N, K);
695 return;
696 }
697#pragma omp parallel for
698 for (int i = 0; i < M; i++) {
699 for (int j = 0; j < N; j++) {
700 float sum = bias ? bias[j] : 0.0f;
701 for (int k = 0; k < K; k++) {
702 sum += A[k * M + i] * B[k * N + j];
703 }
704 C[i * N + j] = sum;
705 }
706 }
707}

References C, ck_strict_parity_enabled(), and gemm_tn_serial_double().

Referenced by fc1_backward_kernel(), fc2_backward_kernel(), and gemm_tn_avx512().

◆ gemma4_final_logit_softcap_forward()

void gemma4_final_logit_softcap_forward ( float *  logits,
int  tokens,
int  vocab_size,
float  cap 
)

Definition at line 491 of file gemma4_per_layer_embed.c.

495{
496 if (!logits || tokens <= 0 || vocab_size <= 0 || cap <= 0.0f) {
497 return;
498 }
499 const float inv_cap = 1.0f / cap;
500 const size_t total = (size_t)tokens * (size_t)vocab_size;
501 for (size_t i = 0; i < total; ++i) {
502 logits[i] = tanhf(logits[i] * inv_cap) * cap;
503 }
504}

References vocab_size.

◆ gemma4_per_layer_embed_forward()

void gemma4_per_layer_embed_forward ( float *  hidden,
const float *  per_layer_input,
const float *  inp_gate,
const float *  proj,
const float *  post_norm,
const float *  out_scale,
int  tokens,
int  layer,
int  num_layers,
int  embed_dim,
int  per_layer_dim,
float  eps,
const int *  segment_lengths,
int  num_segments,
int  singleton_tail 
)

Definition at line 417 of file gemma4_per_layer_embed.c.

432{
433 if (!hidden || !per_layer_input || !inp_gate || !proj || !post_norm ||
434 tokens <= 0 || layer < 0 || layer >= num_layers || embed_dim <= 0 ||
435 per_layer_dim != QK_K || embed_dim > 4096 ||
436 (segment_lengths == NULL) != (num_segments == 0) ||
437 (singleton_tail != 0 && singleton_tail != 1)) {
438 return;
439 }
440 if (segment_lengths) {
441 int remaining = tokens;
442 for (int i = 0; i < num_segments; ++i) {
443 if (segment_lengths[i] < 0 || segment_lengths[i] > remaining) return;
444 remaining -= segment_lengths[i];
445 }
446 if (remaining != 0) return;
447 }
448
449 ck_gemma4_embed_args_t args = {
450 .hidden = hidden,
451 .per_layer_input = per_layer_input,
452 .inp_gate = inp_gate,
453 .proj = proj,
454 .post_norm = post_norm,
455 .out_scale = out_scale,
456 .layer = layer,
457 .num_layers = num_layers,
458 .embed_dim = embed_dim,
459 .per_layer_dim = per_layer_dim,
460 .tokens = tokens,
461 .eps = eps,
462 .segment_lengths = segment_lengths,
463 .num_segments = num_segments,
464 .singleton_tail = singleton_tail,
465 };
466 ck_threadpool_t *pool = ck_threadpool_global();
467 int active = pool ? ck_threadpool_n_threads(pool) : 1;
468 const char *disabled = getenv("CK_DISABLE_GEMMA4_EMBED_PARALLEL");
469 if (disabled && disabled[0] && strcmp(disabled, "0") != 0) active = 1;
470 if (active > tokens) active = tokens;
472 pool, active, 0, tokens, 1, ck_gemma4_embed_range, &args);
473}
static void ck_gemma4_embed_range(int begin, int end, void *opaque)

References ck_gemma4_embed_range(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), and QK_K.

◆ gemma4_per_layer_prepare_bf16_forward()

void gemma4_per_layer_prepare_bf16_forward ( float *  per_layer_input,
const float *  hidden,
const int32_t *  token_ids,
const uint16_t *  per_layer_token_emb,
const uint16_t *  per_layer_model_proj,
const float *  per_layer_proj_norm,
int  tokens,
int  num_layers,
int  embed_dim,
int  per_layer_dim,
int  vocab_size,
float  eps 
)

Definition at line 309 of file gemma4_per_layer_embed.c.

321{
322 if (!per_layer_input || !hidden || !token_ids || !per_layer_token_emb ||
323 !per_layer_model_proj || !per_layer_proj_norm || tokens <= 0 ||
324 num_layers <= 0 || embed_dim <= 0 || embed_dim > CK_GEMMA4_MAX_EMBED_DIM ||
325 per_layer_dim <= 0 || vocab_size <= 0) {
326 return;
327 }
328
329 if (per_layer_dim > QK_K) {
330 return;
331 }
332 ck_gemma4_prepare_args_t args = {
333 .per_layer_input = per_layer_input,
334 .hidden = hidden,
335 .token_ids = token_ids,
336 .per_layer_token_emb = per_layer_token_emb,
337 .per_layer_model_proj = per_layer_model_proj,
338 .per_layer_proj_norm = per_layer_proj_norm,
339 .num_layers = num_layers,
340 .embed_dim = embed_dim,
341 .per_layer_dim = per_layer_dim,
342 .vocab_size = vocab_size,
343 .eps = eps,
344 };
346}
#define CK_GEMMA4_MAX_EMBED_DIM
static void ck_gemma4_prepare_parallel(int tokens, ck_range_fn_t fn, ck_gemma4_prepare_args_t *args)
static void ck_gemma4_prepare_bf16_range(int begin, int end, void *opaque)

References CK_GEMMA4_MAX_EMBED_DIM, ck_gemma4_prepare_bf16_range(), ck_gemma4_prepare_parallel(), QK_K, and vocab_size.

◆ gemma4_per_layer_prepare_forward()

void gemma4_per_layer_prepare_forward ( float *  per_layer_input,
const float *  hidden,
const int32_t *  token_ids,
const void *  per_layer_token_emb,
const uint16_t *  per_layer_model_proj,
const float *  per_layer_proj_norm,
int  tokens,
int  num_layers,
int  embed_dim,
int  per_layer_dim,
int  vocab_size,
float  eps 
)

Definition at line 272 of file gemma4_per_layer_embed.c.

284{
285 if (!per_layer_input || !hidden || !token_ids || !per_layer_token_emb ||
286 !per_layer_model_proj || !per_layer_proj_norm || tokens <= 0 ||
287 num_layers <= 0 || embed_dim <= 0 || embed_dim > CK_GEMMA4_MAX_EMBED_DIM ||
288 per_layer_dim != QK_K || vocab_size <= 0) {
289 return;
290 }
291
292 ck_gemma4_prepare_args_t args = {
293 .per_layer_input = per_layer_input,
294 .hidden = hidden,
295 .token_ids = token_ids,
296 .per_layer_token_emb = per_layer_token_emb,
297 .per_layer_model_proj = per_layer_model_proj,
298 .per_layer_proj_norm = per_layer_proj_norm,
299 .num_layers = num_layers,
300 .embed_dim = embed_dim,
301 .per_layer_dim = per_layer_dim,
302 .vocab_size = vocab_size,
303 .eps = eps,
304 };
306}
static void ck_gemma4_prepare_q5_range(int begin, int end, void *opaque)

References CK_GEMMA4_MAX_EMBED_DIM, ck_gemma4_prepare_parallel(), ck_gemma4_prepare_q5_range(), QK_K, and vocab_size.

◆ gemma4_v_norm_forward()

void gemma4_v_norm_forward ( const float *  input,
float *  output,
float *  rstd_cache,
int  tokens,
int  num_kv_heads,
int  head_dim,
float  eps 
)

Definition at line 839 of file rmsnorm_kernels.c.

846{
847 if (!input || !output || tokens <= 0 || num_kv_heads <= 0 || head_dim <= 0) {
848 return;
849 }
851 input, output, rstd_cache,
852 tokens * num_kv_heads, head_dim, head_dim, eps);
853}
void rmsnorm_forward_no_weight_llama_production(const float *input, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References rmsnorm_forward_no_weight_llama_production().

◆ gemma4_v_norm_forward_parallel_dispatch()

void gemma4_v_norm_forward_parallel_dispatch ( const float *  input,
float *  output,
float *  rstd_cache,
int  tokens,
int  num_kv_heads,
int  head_dim,
float  eps 
)

◆ gemma4_vision_projector_prep_forward()

void gemma4_vision_projector_prep_forward ( const float *  input,
float *  output,
int  tokens,
int  dim,
float  scale,
float  eps 
)

Definition at line 633 of file vision_kernels.c.

639{
640 if (input == NULL || output == NULL || tokens <= 0 || dim <= 0) return;
641 if (eps <= 0.0f) eps = 1.0e-6f;
642 for (int t = 0; t < tokens; ++t) {
643 const float *src = input + (size_t)t * (size_t)dim;
644 float *dst = output + (size_t)t * (size_t)dim;
645 double ss = 0.0;
646 for (int i = 0; i < dim; ++i) {
647 const float v = src[i] * scale;
648 ss += (double)v * (double)v;
649 }
650 const float inv_rms = 1.0f / sqrtf((float)(ss / (double)dim) + eps);
651 for (int i = 0; i < dim; ++i) {
652 dst[i] = (src[i] * scale) * inv_rms;
653 }
654 }
655}

◆ gemv_bf16()

void gemv_bf16 ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 629 of file gemm_kernels_bf16.c.

633{
635 y, (const uint16_t *)W, x, M, K, 0, M);
636}
static void gemv_bf16_row_range(float *y, const uint16_t *w, const float *x, int M, int K, int row_begin, int row_end)

References gemv_bf16_row_range().

Referenced by gemv_bf16_parallel_dispatch().

◆ gemv_bf16_bf16_storage()

void gemv_bf16_bf16_storage ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 719 of file gemm_kernels_bf16.c.

723{
725}
void gemv_bf16_bf16_storage_parallel_dispatch(float *y, const void *W, const float *x, int M, int K)

References gemv_bf16_bf16_storage_parallel_dispatch().

◆ gemv_bf16_bf16_storage_parallel_dispatch()

void gemv_bf16_bf16_storage_parallel_dispatch ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 695 of file gemm_kernels_bf16.c.

699{
700 ck_threadpool_t *pool = ck_threadpool_global();
701 if (!pool || ck_threadpool_n_threads(pool) <= 1 || M < 2 ||
702 (size_t)M * (size_t)K <= 65536) {
704 y, (const uint16_t *)W, x, M, K, 0, M);
705 return;
706 }
707
708 ck_gemv_bf16_args_t args = {
709 .y = y, .w = (const uint16_t *)W, .x = x, .M = M, .K = K,
710 };
711 int active = ck_threadpool_n_threads(pool);
712 if (active > M) active = M;
713 int grain = M / (active * 4);
714 if (grain < 1) grain = 1;
716 pool, active, 0, M, grain, ck_gemv_bf16_storage_rows, &args);
717}
static void gemv_bf16_bf16_storage_row_range(float *y, const uint16_t *w, const float *x, int M, int K, int row_begin, int row_end)
static void ck_gemv_bf16_storage_rows(int begin, int end, void *opaque)

References ck_gemv_bf16_storage_rows(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), and gemv_bf16_bf16_storage_row_range().

Referenced by gemv_bf16_bf16_storage().

◆ gemv_bf16_parallel_dispatch()

void gemv_bf16_parallel_dispatch ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 653 of file gemm_kernels_bf16.c.

657{
658 ck_threadpool_t *pool = ck_threadpool_global();
659 if (!pool || ck_threadpool_n_threads(pool) <= 1 || M < 2 ||
660 (size_t)M * (size_t)K <= 65536) {
661 gemv_bf16(y, W, x, M, K);
662 return;
663 }
664
665 ck_gemv_bf16_args_t args = {
666 .y = y, .w = (const uint16_t *)W, .x = x, .M = M, .K = K,
667 };
668 int active = ck_threadpool_n_threads(pool);
669 if (active > M) active = M;
670 int grain = M / (active * 4);
671 if (grain < 1) grain = 1;
673 pool, active, 0, M, grain, ck_gemv_bf16_rows, &args);
674}
static void ck_gemv_bf16_rows(int begin, int end, void *opaque)
void gemv_bf16(float *y, const void *W, const float *x, int M, int K)

References ck_gemv_bf16_rows(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), and gemv_bf16().

◆ gemv_fused_q5_0_bias_dispatch()

void gemv_fused_q5_0_bias_dispatch ( float *  y,
const void *  W,
const float *  x,
const float *  bias,
int  M,
int  K 
)

Definition at line 510 of file gemv_fused_quant_bias.c.

517{
518#if defined(__AVX__)
519 gemv_fused_q5_0_bias_avx(y, W, x, bias, M, K);
520#else
521 gemv_fused_q5_0_bias(y, W, x, bias, M, K);
522#endif
523}
void gemv_fused_q5_0_bias(float *y, const void *W, const float *x, const float *bias, int M, int K)

References gemv_fused_q5_0_bias().

◆ gemv_fused_q8_0_bias_dispatch()

void gemv_fused_q8_0_bias_dispatch ( float *  y,
const void *  W,
const float *  x,
const float *  bias,
int  M,
int  K 
)

Definition at line 525 of file gemv_fused_quant_bias.c.

532{
533#if defined(__AVX__)
534 gemv_fused_q8_0_bias_avx(y, W, x, bias, M, K);
535#else
536 gemv_fused_q8_0_bias(y, W, x, bias, M, K);
537#endif
538}
void gemv_fused_q8_0_bias(float *y, const void *W, const float *x, const float *bias, int M, int K)

References gemv_fused_q8_0_bias().

◆ gemv_q4_0()

void gemv_q4_0 ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Auto-dispatch GEMV.

Definition at line 132 of file gemm_kernels_q4_0.c.

136{
137#ifdef __AVX512F__
138 gemv_q4_0_avx512(y, W, x, M, K);
139#else
140 gemv_q4_0_ref(y, W, x, M, K);
141#endif
142}
void gemv_q4_0_ref(float *y, const void *W, const float *x, int M, int K)
Matrix-vector multiply with Q4_0 weights (scalar reference)

References gemv_q4_0_ref().

Referenced by dot_q4_0(), and gemm_q4_0().

◆ gemv_q4_k()

void gemv_q4_k ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Auto-dispatch GEMV based on available SIMD.

Definition at line 301 of file gemm_kernels_q4k.c.

305{
306 if (ck_q4k_debug_q8_contract() && K > 0 && (K % QK_K) == 0) {
307 const int nb = K / QK_K;
308 if (nb <= CK_Q4K_STACK_Q8_BLOCKS) {
310 quantize_row_q8_k(x, x_q8, K);
311 gemv_q4_k_q8_k(y, W, x_q8, M, K);
312 return;
313 }
314 }
315#ifdef __AVX512F__
316 gemv_q4_k_avx512(y, W, x, M, K);
317#elif defined(__AVX__)
318 gemv_q4_k_avx(y, W, x, M, K);
319#else
320 gemv_q4_k_ref(y, W, x, M, K);
321#endif
322}
void gemv_q4_k_ref(float *y, const void *W, const float *x, int M, int K)
Matrix-vector multiply with Q4_K weights (scalar reference)
#define CK_Q4K_STACK_Q8_BLOCKS
void quantize_row_q8_k(const float *x, void *vy, int k)
void gemv_q4_k_q8_k(float *y, const void *W, const void *x_q8, int M, int K)
static int ck_q4k_debug_q8_contract(void)

References ck_q4k_debug_q8_contract(), CK_Q4K_STACK_Q8_BLOCKS, gemv_q4_k_q8_k(), gemv_q4_k_ref(), QK_K, and quantize_row_q8_k().

Referenced by attention_mlp_fused_q4k(), dot_q4_k(), gemm_q4_k_ref(), layer_fused_attn_mlp_qkv_q4k(), and rmsnorm_qkv_q4k_fused().

◆ gemv_q4_k_q8_k()

void gemv_q4_k_q8_k ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Definition at line 497 of file gemm_kernels_q4k_q8k.c.

501{
502 if (ck_q4k_q8k_force_ref()) {
503 gemv_q4_k_q8_k_ref(y, W, x_q8, M, K);
504 return;
505 }
506#if defined(__AVX512VNNI__) && defined(__AVX512VL__) && !defined(CK_NO_AVX512_VNNI)
507 /* VNNI: Best for decode (single token) - INT8 dot product acceleration */
508 gemv_q4_k_q8_k_vnni(y, W, x_q8, M, K);
509#elif defined(__AVX2__)
510 gemv_q4_k_q8_k_avx2(y, W, x_q8, M, K);
511#elif defined(__AVX__)
512 /* AVX version uses maddubs_epi16 (more efficient than SSE) */
513 gemv_q4_k_q8_k_avx(y, W, x_q8, M, K);
514#elif defined(__SSE4_1__)
515 gemv_q4_k_q8_k_sse(y, W, x_q8, M, K);
516#elif defined(__ARM_FEATURE_DOTPROD)
517 /* SDOT NEON is integer-exact against the scalar reference (identical
518 * block arithmetic and FP32 epilogue); CK_DEBUG_Q4K_Q8_REF=1 still
519 * forces the reference above. Baseline armv8-a builds (no dot-product
520 * extension) keep the reference path, which the compiler already
521 * autovectorizes well. */
522 gemv_q4_k_q8_k_neon(y, W, x_q8, M, K);
523#else
524 gemv_q4_k_q8_k_ref(y, W, x_q8, M, K);
525#endif
526}
void gemv_q4_k_q8_k_avx2(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q4_k_q8_k_vnni(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q4_k_q8_k_ref(float *y, const void *W, const void *x_q8, int M, int K)
static int ck_q4k_q8k_force_ref(void)
void gemv_q4_k_q8_k_avx(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q4_k_q8_k_sse(float *y, const void *W, const void *x_q8, int M, int K)

References ck_q4k_q8k_force_ref(), gemv_q4_k_q8_k_avx(), gemv_q4_k_q8_k_avx2(), gemv_q4_k_q8_k_ref(), gemv_q4_k_q8_k_sse(), and gemv_q4_k_q8_k_vnni().

Referenced by ck_moe_q4k_llama_projection(), ck_moe_q4k_mixed_route_work(), ck_moe_q4k_q5k_bucket_work(), ck_moe_q4k_q5k_route_work(), gemm_q4_k_q8_k_compact_rows4(), hyper_injection_q4k_q8k_llama_dispatch(), model_decode_token(), model_decode_token(), model_layer_0_decode(), model_layer_0_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_9_decode(), model_layer_9_decode(), moe_swiglu_expert_forward_q4k_q4k_workspace(), moe_swiglu_expert_forward_q4k_q5k_workspace(), moe_swiglu_expert_forward_q4k_q6k_workspace(), moe_swiglu_shared_forward_q4k_q4k_workspace(), moe_swiglu_shared_forward_q4k_q6k_workspace(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), 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().

◆ gemv_q4_k_q8_k_parallel()

void gemv_q4_k_q8_k_parallel ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K,
int  ith,
int  nth 
)

Definition at line 464 of file gemm_kernels_q4k_q8k.c.

469{
470 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
471 return;
472 }
473 if (ith < 0 || nth <= 0 || ith >= nth) {
474 return;
475 }
476
477 /* Compute row range for this thread */
478 const int dr = (M + nth - 1) / nth;
479 const int r0 = dr * ith;
480 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
481
482 if (r0 >= M) {
483 return; /* This thread has no work */
484 }
485
486 const block_q4_K *blocks = (const block_q4_K *)W;
487 const block_q8_K *x = (const block_q8_K *)x_q8;
488 const int blocks_per_row = K / QK_K;
489
490 /* Only process rows [r0, r1) */
491 for (int row = r0; row < r1; ++row) {
492 const block_q4_K *w_row = blocks + (size_t)row * (size_t)blocks_per_row;
493 y[row] = dot_q4_k_q8_k_ref(w_row, x, K);
494 }
495}
static float dot_q4_k_q8_k_ref(const block_q4_K *w, const block_q8_K *x, int k)

References dot_q4_k_q8_k_ref(), and QK_K.

◆ gemv_q4_k_q8_k_parallel_simd()

void gemv_q4_k_q8_k_parallel_simd ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K,
int  ith,
int  nth 
)

Definition at line 263 of file gemm_kernels_q4k_avx.c.

268{
269 /* Fall back to reference parallel version */
270 gemv_q4_k_q8_k_parallel(y, W, x_q8, M, K, ith, nth);
271}
void gemv_q4_k_q8_k_parallel(float *y, const void *W, const void *x_q8, int M, int K, int ith, int nth)

References gemv_q4_k_q8_k_parallel().

Referenced by decode_layer_parallel(), mlp_parallel(), and qkv_projection_parallel().

◆ gemv_q4_k_q8_k_ref()

void gemv_q4_k_q8_k_ref ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Definition at line 425 of file gemm_kernels_q4k_q8k.c.

429{
430 if (!y || !W || !x_q8 || M <= 0 || K <= 0) {
431 return;
432 }
433
434 const block_q4_K *blocks = (const block_q4_K *)W;
435 const block_q8_K *x = (const block_q8_K *)x_q8;
436 const int blocks_per_row = K / QK_K;
437
438 for (int row = 0; row < M; ++row) {
439 const block_q4_K *w_row = blocks + (size_t)row * (size_t)blocks_per_row;
440 y[row] = dot_q4_k_q8_k_ref(w_row, x, K);
441 }
442}

References dot_q4_k_q8_k_ref(), and QK_K.

◆ gemv_q5_0()

void gemv_q5_0 ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Auto-dispatch GEMV for Q5_0 weights based on CPU features.

Dispatch priority (best available):

  1. AVX-512 (512-bit vectors) - Intel Skylake-X+
  2. AVX2+FMA (256-bit vectors) - Intel Haswell+
  3. AVX (256-bit vectors) - Intel Sandy Bridge+
  4. SSE4.1 (128-bit vectors) - Intel Nehalem+
  5. Reference (scalar) - Fallback

Uses ck_features.h for standardized feature detection.

Parameters
yOutput vector [M]
WWeight matrix in Q5_0 format [M x K]
xInput vector [K]
MNumber of output rows
KNumber of input columns (hidden dimension)

Definition at line 550 of file gemm_kernels_q5_0.c.

554{
555// Dispatch order: AVX512 > AVX2 > AVX > SSE > ref
556#if defined(__AVX512F__)
557 gemv_q5_0_avx512(y, W, x, M, K);
558#elif defined(__AVX2__)
559 gemv_q5_0_avx2(y, W, x, M, K);
560#elif defined(__AVX__)
561 gemv_q5_0_avx(y, W, x, M, K);
562#elif defined(__SSE4_1__)
563 gemv_q5_0_ref(y, W, x, M, K);
564#else
565 gemv_q5_0_ref(y, W, x, M, K);
566#endif
567}
void gemv_q5_0_ref(float *y, const void *W, const float *x, int M, int K)
Matrix-vector multiply with Q5_0 weights (scalar reference)

References gemv_q5_0_ref().

◆ gemv_q5_0_parallel()

void gemv_q5_0_parallel ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K,
int  ith,
int  nth 
)

Parallel reference GEMV for Q5_0 × FP32.

Definition at line 579 of file gemm_kernels_q5_0.c.

584{
585 if (!y || !W || !x || M <= 0 || K <= 0) return;
586 if (ith < 0 || nth <= 0 || ith >= nth) return;
587
588 const int dr = (M + nth - 1) / nth;
589 const int r0 = dr * ith;
590 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
591
592 if (r0 >= M) return;
593
594 const block_q5_0 *blocks = (const block_q5_0 *)W;
595 const int blocks_per_row = K / QK5_0;
596
597 for (int row = r0; row < r1; row++) {
598 float sum = 0.0f;
599 for (int b = 0; b < blocks_per_row; b++) {
600 const block_q5_0 *block = &blocks[row * blocks_per_row + b];
601 const float d = CK_FP16_TO_FP32(block->d);
602 const float *xp = &x[b * QK5_0];
603
604 uint32_t qh;
605 memcpy(&qh, block->qh, sizeof(qh));
606
607 for (int j = 0; j < QK5_0 / 2; j++) {
608 const uint8_t packed = block->qs[j];
609 const int lo = (packed & 0x0F);
610 const int hi = (packed >> 4);
611 const int xh_0 = ((qh >> (j + 0)) << 4) & 0x10;
612 const int xh_1 = ((qh >> (j + 12))) & 0x10;
613 const int w0 = (lo | xh_0) - 16;
614 const int w1 = (hi | xh_1) - 16;
615 sum += d * (w0 * xp[j] + w1 * xp[j + QK5_0/2]);
616 }
617 }
618 y[row] = sum;
619 }
620}
uint8_t qh[4]
uint8_t qs[32/2]

References CK_FP16_TO_FP32, block_q5_0::d, block_q5_0::qh, QK5_0, and block_q5_0::qs.

Referenced by gemv_q5_0_parallel_simd().

◆ gemv_q5_0_parallel_simd()

void gemv_q5_0_parallel_simd ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K,
int  ith,
int  nth 
)

Parallel SIMD GEMV for Q5_0 × FP32 with prefetching.

Definition at line 625 of file gemm_kernels_q5_0.c.

630{
631 if (!y || !W || !x || M <= 0 || K <= 0) return;
632 if (ith < 0 || nth <= 0 || ith >= nth) return;
633
634 const int dr = (M + nth - 1) / nth;
635 const int r0 = dr * ith;
636 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
637
638 if (r0 >= M) return;
639
640#if defined(__AVX__) || defined(__SSE4_1__)
641 const block_q5_0 *blocks = (const block_q5_0 *)W;
642 const int blocks_per_row = K / QK5_0;
643 /* Prefetch first few rows */
644 const int PREFETCH_ROWS = 4;
645 for (int p = 0; p < PREFETCH_ROWS && r0 + p < r1; ++p) {
646 const char *row_ptr = (const char *)(blocks + (r0 + p) * blocks_per_row);
647 _mm_prefetch(row_ptr, _MM_HINT_T0);
648 _mm_prefetch(row_ptr + 64, _MM_HINT_T0);
649 }
650
651 for (int row = r0; row < r1; ++row) {
652 /* Prefetch rows ahead */
653 if (row + PREFETCH_ROWS < r1) {
654 const char *prefetch_ptr = (const char *)(blocks + (row + PREFETCH_ROWS) * blocks_per_row);
655 _mm_prefetch(prefetch_ptr, _MM_HINT_T0);
656 _mm_prefetch(prefetch_ptr + 64, _MM_HINT_T0);
657 }
658
659 /* Use SIMD dot product for this row */
660#if defined(__AVX512F__)
661 /* Call single-row AVX512 implementation */
662 gemv_q5_0_avx512(&y[row], (const char *)blocks + row * blocks_per_row * sizeof(block_q5_0), x, 1, K);
663#elif defined(__AVX2__)
664 gemv_q5_0_avx2(&y[row], (const char *)blocks + row * blocks_per_row * sizeof(block_q5_0), x, 1, K);
665#elif defined(__AVX__)
666 gemv_q5_0_avx(&y[row], (const char *)blocks + row * blocks_per_row * sizeof(block_q5_0), x, 1, K);
667#else
668 gemv_q5_0_ref(&y[row], (const char *)blocks + row * blocks_per_row * sizeof(block_q5_0), x, 1, K);
669#endif
670 }
671#else
672 /* Fallback to reference parallel */
673 gemv_q5_0_parallel(y, W, x, M, K, ith, nth);
674#endif
675}
void gemv_q5_0_parallel(float *y, const void *W, const float *x, int M, int K, int ith, int nth)
Parallel reference GEMV for Q5_0 × FP32.

References gemv_q5_0_parallel(), gemv_q5_0_ref(), and QK5_0.

◆ gemv_q5_0_q8_0()

void gemv_q5_0_q8_0 ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Matrix-vector multiply with Q5_0 weights and Q8_0 input.

Parameters
yOutput vector [M]
WWeight matrix in Q5_0 format [M x K]
x_q8Input vector in Q8_0 format [K]
MNumber of output rows
KNumber of columns (must be multiple of 32)

Definition at line 1640 of file gemm_kernels_q5_0.c.

1644{
1645 const block_q5_0 *w_blocks = (const block_q5_0 *)W;
1646 const block_q8_0 *x_blocks = (const block_q8_0 *)x_q8;
1647 const int blocks_per_row = K / QK5_0;
1648
1649 for (int row = 0; row < M; row++) {
1650 vec_dot_q5_0_q8_0(K, &y[row],
1651 &w_blocks[row * blocks_per_row],
1652 x_blocks);
1653 }
1654}
void vec_dot_q5_0_q8_0(int n, float *s, const void *vx, const void *vy)
Auto-dispatch quantized dot product Q5_0 x Q8_0.

References QK5_0, and vec_dot_q5_0_q8_0().

Referenced by ck_moe_q4k_mixed_route_work(), moe_swiglu_expert_forward_q4k_q5_0_workspace(), and moe_swiglu_shared_forward_q4k_q5_0_gated_workspace().

◆ gemv_q5_1()

void gemv_q5_1 ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Auto-dispatch GEMV.

Definition at line 187 of file gemm_kernels_q5_1.c.

191{
192#ifdef __AVX512F__
193 gemv_q5_1_avx512(y, W, x, M, K);
194#else
195 gemv_q5_1_ref(y, W, x, M, K);
196#endif
197}
void gemv_q5_1_ref(float *y, const void *W, const float *x, int M, int K)
Matrix-vector multiply with Q5_1 weights (scalar reference)

References gemv_q5_1_ref().

Referenced by dot_q5_1(), and gemm_q5_1().

◆ gemv_q5_1_q8_1()

void gemv_q5_1_q8_1 ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 300 of file gemm_kernels_q5_1_q8_1.c.

305{
306 if (!y || !W || !x || M <= 0 || K <= 0 || (K % QK5_1) != 0) {
307 return;
308 }
309
310 const int blocks_per_row = K / QK5_1;
311 if (blocks_per_row > CK_Q51_STACK_Q8_BLOCKS) {
312 return;
313 }
314
315 block_q8_1 x_q8[CK_Q51_STACK_Q8_BLOCKS];
316 quantize_row_q8_1_scalar(x, x_q8, K);
317 gemv_q5_1_q8_1_ref(y, W, x_q8, M, K);
318}
void gemv_q5_1_q8_1_ref(float *y, const void *W, const void *x_q8, int M, int K)

References CK_Q51_STACK_Q8_BLOCKS, gemv_q5_1_q8_1_ref(), QK5_1, and quantize_row_q8_1_scalar().

◆ gemv_q5_1_q8_1_ref()

void gemv_q5_1_q8_1_ref ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Definition at line 250 of file gemm_kernels_q5_1_q8_1.c.

254{
255 if (!y || !W || !x_q8 || M <= 0 || K <= 0 || (K % QK5_1) != 0) {
256 return;
257 }
258
259 const block_q5_1 *blocks = (const block_q5_1 *)W;
260 const block_q8_1 *x = (const block_q8_1 *)x_q8;
261 const int blocks_per_row = K / QK5_1;
262
263 for (int row = 0; row < M; ++row) {
264 const block_q5_1 *w_row = &blocks[row * blocks_per_row];
265 float sum = 0.0f;
266 for (int b = 0; b < blocks_per_row; ++b) {
267 sum += dot_q5_1_q8_1_block(&w_row[b], &x[b]);
268 }
269 y[row] = sum;
270 }
271}

References dot_q5_1_q8_1_block(), and QK5_1.

Referenced by gemv_q5_1_q8_1().

◆ gemv_q5_k()

void gemv_q5_k ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 1009 of file gemm_kernels_q5_k.c.

1010{
1011#if defined(__AVX512F__)
1012 /* TODO: AVX-512 implementation */
1013 gemv_q5_k_ref(y, W, x, M, K);
1014#elif defined(__AVX2__)
1015 /* TODO: AVX-2 implementation */
1016 gemv_q5_k_ref(y, W, x, M, K);
1017#elif defined(__AVX__)
1018 /* TODO: AVX implementation */
1019 gemv_q5_k_ref(y, W, x, M, K);
1020#elif defined(__SSE4_1__)
1021 /* TODO: SSE4.1 implementation */
1022 gemv_q5_k_ref(y, W, x, M, K);
1023#else
1024 gemv_q5_k_ref(y, W, x, M, K);
1025#endif
1026}
void gemv_q5_k_ref(float *y, const void *W, const float *x, int M, int K)

References gemv_q5_k_ref().

◆ gemv_q5_k_q8_k()

void gemv_q5_k_q8_k ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Definition at line 892 of file gemm_kernels_q5_k.c.

896{
897#if defined(__AVX512F__)
898 /* TODO: AVX-512 implementation */
899 gemv_q5_k_q8_k_ref(y, W, x_q8, M, K);
900#elif defined(__AVX2__)
901 /* TODO: AVX-2 implementation */
902 gemv_q5_k_q8_k_ref(y, W, x_q8, M, K);
903#elif defined(__AVX__)
904 /* TODO: AVX implementation */
905 gemv_q5_k_q8_k_ref(y, W, x_q8, M, K);
906#elif defined(__SSE4_1__)
907 /* TODO: SSE4.1 implementation */
908 gemv_q5_k_q8_k_ref(y, W, x_q8, M, K);
909#else
910 gemv_q5_k_q8_k_ref(y, W, x_q8, M, K);
911#endif
912}
void gemv_q5_k_q8_k_ref(float *y, const void *W, const void *x_q8, int M, int K)

References gemv_q5_k_q8_k_ref().

Referenced by ck_moe_q4k_q5k_route_work(), gemm_q5_k_q8_k_compact_rows4(), and moe_swiglu_expert_forward_q4k_q5k_workspace().

◆ gemv_q6_k()

void gemv_q6_k ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 169 of file gemm_kernels_q6k.c.

173{
174 if (!y || !W || !x) {
175 return;
176 }
177 if (M <= 0 || K <= 0) {
178 return;
179 }
180 // TEMPORARILY DISABLE NEW AVX KERNELS - USE REFERENCE ONLY
181
182 const block_q6_K *blocks = (const block_q6_K *)W;
183 const int blocks_per_row = K / QK_K;
184
185 for (int row = 0; row < M; ++row) {
186 const block_q6_K *w_row = blocks + (size_t)row * (size_t)blocks_per_row;
187#if defined(__AVX__) && !defined(__AVX512F__)
188 y[row] = dot_q6_k_avx(w_row, x, K);
189#else
190 y[row] = dot_q6_k_ref(w_row, x, K);
191#endif
192 }
193}
static float dot_q6_k_ref(const block_q6_K *w, const float *x, int K)

References dot_q6_k_ref(), and QK_K.

Referenced by gemm_q6_k().

◆ gemv_q6_k_q8_k()

void gemv_q6_k_q8_k ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

GEMV: y = W @ x where W is Q6_K and x is Q8_K.

Definition at line 1356 of file gemm_kernels_q6k_q8k.c.

1360{
1362 gemv_q6_k_q8_k_ref(y, W, x_q8, M, K);
1363 return;
1364 }
1365
1366#if defined(__AVX2__)
1367 /* llama.cpp's x86 Q6_K production graph keeps the AVX2 reduction order
1368 * even when AVX-512 is available. Wider ISA availability is not a license
1369 * to change this numerical contract. */
1370 gemv_q6_k_q8_k_avx2(y, W, x_q8, M, K);
1371 return;
1372#elif defined(__AVX__)
1373 gemv_q6_k_q8_k_avx(y, W, x_q8, M, K);
1374 return;
1375#elif defined(__SSE4_1__)
1376 gemv_q6_k_q8_k_sse(y, W, x_q8, M, K);
1377 return;
1378#elif defined(__ARM_NEON) || defined(__aarch64__)
1379 /* NEON keeps the same integer-exact per-block dot as the scalar
1380 * reference but accumulates the FP32 block contributions sequentially
1381 * instead of through eight partial lanes, so strict parity mode (handled
1382 * above) still uses the reference reduction order. */
1383 gemv_q6_k_q8_k_neon(y, W, x_q8, M, K);
1384 return;
1385#endif
1386 gemv_q6_k_q8_k_ref(y, W, x_q8, M, K);
1387}
void gemv_q6_k_q8_k_ref(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q6_k_q8_k_sse(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q6_k_q8_k_avx(float *y, const void *W, const void *x_q8, int M, int K)
void gemv_q6_k_q8_k_avx2(float *y, const void *W, const void *x_q8, int M, int K)

References ck_q6k_q8k_force_ref(), ck_strict_parity_enabled(), gemv_q6_k_q8_k_avx(), gemv_q6_k_q8_k_avx2(), gemv_q6_k_q8_k_ref(), and gemv_q6_k_q8_k_sse().

Referenced by ck_moe_q4k_mixed_route_work(), moe_swiglu_expert_forward_q4k_q6k_workspace(), and moe_swiglu_shared_forward_q4k_q6k_workspace().

◆ gemv_q6_k_q8_k_parallel()

void gemv_q6_k_q8_k_parallel ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K,
int  ith,
int  nth 
)

Parallel reference GEMV for Q6_K × Q8_K.

Caller provides ith (thread index) and nth (total threads). Each thread processes rows [r0, r1).

Definition at line 1422 of file gemm_kernels_q6k_q8k.c.

1427{
1428 if (!y || !W || !x_q8 || M <= 0 || K <= 0) return;
1429 if (ith < 0 || nth <= 0 || ith >= nth) return;
1430
1431 /* Compute row range for this thread */
1432 const int dr = (M + nth - 1) / nth;
1433 const int r0 = dr * ith;
1434 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
1435
1436 if (r0 >= M) return;
1437
1438 const block_q6_K *blocks = (const block_q6_K *)W;
1439 const block_q8_K *x = (const block_q8_K *)x_q8;
1440 const int blocks_per_row = K / QK_K;
1441
1442 for (int row = r0; row < r1; ++row) {
1443 const block_q6_K *w_row = blocks + (size_t)row * (size_t)blocks_per_row;
1444 y[row] = dot_q6_k_q8_k_ref(w_row, x, K);
1445 }
1446}
static float dot_q6_k_q8_k_ref(const block_q6_K *w, const block_q8_K *x, int K)
Scalar dot product for Q6_K x Q8_K.

References dot_q6_k_q8_k_ref(), and QK_K.

◆ gemv_q6_k_q8_k_parallel_simd()

void gemv_q6_k_q8_k_parallel_simd ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K,
int  ith,
int  nth 
)

Parallel SIMD GEMV for Q6_K × Q8_K.

Uses best available SIMD (AVX/SSE) with row prefetching. Caller provides ith/nth from OpenMP region.

Definition at line 1454 of file gemm_kernels_q6k_q8k.c.

1459{
1460 if (!y || !W || !x_q8 || M <= 0 || K <= 0) return;
1461 if (ith < 0 || nth <= 0 || ith >= nth) return;
1462
1463 const int dr = (M + nth - 1) / nth;
1464 const int r0 = dr * ith;
1465 const int r1 = (r0 + dr < M) ? (r0 + dr) : M;
1466
1467 if (r0 >= M) return;
1468
1469 const block_q6_K *blocks = (const block_q6_K *)W;
1470 const block_q8_K *x = (const block_q8_K *)x_q8;
1471 const int blocks_per_row = K / QK_K;
1472 const int strict = ck_strict_parity_enabled() || ck_q6k_q8k_force_ref();
1473
1474 for (int row = r0; row < r1; ++row) {
1475 const block_q6_K *w_row = blocks + (size_t)row * (size_t)blocks_per_row;
1476#if defined(__AVX2__)
1477 y[row] = strict ? dot_q6_k_q8_k_ref(w_row, x, K)
1478 : dot_q6_k_q8_k_avx2(w_row, x, K);
1479#elif defined(__AVX__)
1480 y[row] = strict ? dot_q6_k_q8_k_ref(w_row, x, K)
1481 : dot_q6_k_q8_k_avx(w_row, x, K);
1482#elif defined(__SSE4_1__)
1483 y[row] = strict ? dot_q6_k_q8_k_ref(w_row, x, K)
1484 : dot_q6_k_q8_k_sse(w_row, x, K);
1485#elif defined(__ARM_NEON) || defined(__aarch64__)
1486 y[row] = strict ? dot_q6_k_q8_k_ref(w_row, x, K)
1487 : dot_q6_k_q8_k_neon(w_row, x, K);
1488#else
1489 y[row] = dot_q6_k_q8_k_ref(w_row, x, K);
1490#endif
1491 }
1492}

References ck_q6k_q8k_force_ref(), ck_strict_parity_enabled(), dot_q6_k_q8_k_ref(), and QK_K.

◆ gemv_q8_0()

void gemv_q8_0 ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Auto-dispatch GEMV for Q8_0 weights based on CPU features.

Dispatch priority (best available):

  1. AVX-512 (512-bit vectors) - Intel Skylake-X+
  2. AVX2+FMA (256-bit vectors) - Intel Haswell+
  3. AVX (256-bit vectors) - Intel Sandy Bridge+
  4. SSE4.1 (128-bit vectors) - Intel Nehalem+
  5. Reference (scalar) - Fallback

Uses ck_features.h for standardized feature detection.

Parameters
yOutput vector [M]
WWeight matrix in Q8_0 format [M x K]
xInput vector [K]
MNumber of output rows
KNumber of input columns (hidden dimension)

Definition at line 694 of file gemm_kernels_q8_0.c.

698{
699 if (ck_q8_0_debug_ref()) {
700 gemv_q8_0_ref(y, W, x, M, K);
701 return;
702 }
703
704// Dispatch order: AVX512 > AVX2 > AVX > SSE > ref
705#if defined(__AVX512F__)
706 gemv_q8_0_avx512(y, W, x, M, K);
707#elif defined(__AVX2__)
708 gemv_q8_0_avx2(y, W, x, M, K);
709#elif defined(__AVX__)
710 gemv_q8_0_avx(y, W, x, M, K);
711#elif defined(__SSE4_1__)
712 gemv_q8_0_sse(y, W, x, M, K);
713#else
714 gemv_q8_0_ref(y, W, x, M, K);
715#endif
716}
static int ck_q8_0_debug_ref(void)
void gemv_q8_0_ref(float *y, const void *W, const float *x, int M, int K)
Matrix-vector multiply with Q8_0 weights (scalar reference)

References ck_q8_0_debug_ref(), and gemv_q8_0_ref().

Referenced by gemv_q8_0_q8_0_contract().

◆ gemv_q8_0_q8_0()

void gemv_q8_0_q8_0 ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Matrix-vector multiply with Q8_0 weights and Q8_0 input.

Parameters
yOutput vector [M]
WWeight matrix in Q8_0 format [M x K]
x_q8Input vector in Q8_0 format [K]
MNumber of output rows
KNumber of columns (must be multiple of 32)

Definition at line 1405 of file gemm_kernels_q8_0.c.

1409{
1410 const block_q8_0 *w_blocks = (const block_q8_0 *)W;
1411 const block_q8_0 *x_blocks = (const block_q8_0 *)x_q8;
1412 const int blocks_per_row = K / QK8_0;
1413
1414 for (int row = 0; row < M; row++) {
1415 vec_dot_q8_0_q8_0(K, &y[row],
1416 &w_blocks[row * blocks_per_row],
1417 x_blocks);
1418 }
1419}
void vec_dot_q8_0_q8_0(int n, float *s, const void *vx, const void *vy)
Auto-dispatch quantized dot product Q8_0 x Q8_0.

References QK8_0, and vec_dot_q8_0_q8_0().

Referenced by ck_moe_q4k_mixed_route_work(), moe_swiglu_expert_forward_q4k_q8_0_workspace(), moe_swiglu_shared_forward_q4k_q8_0_gated_workspace(), and moe_swiglu_shared_forward_q8_0_gated_workspace().

◆ gemv_q8_0_q8_0_contract()

void gemv_q8_0_q8_0_contract ( float *  y,
const void *  W,
const float *  x,
int  M,
int  K 
)

Definition at line 385 of file gemm_kernels_q8_0_q8_0_contract.c.

390{
391 if (!y || !W || !x || M <= 0 || K <= 0) {
392 return;
393 }
394
395 if ((K % QK8_0) != 0) {
396 gemv_q8_0(y, W, x, M, K);
397 return;
398 }
399
400 const int blocks_per_row = K / QK8_0;
401 if (blocks_per_row > CK_Q80_STACK_Q8_BLOCKS) {
402 gemv_q8_0(y, W, x, M, K);
403 return;
404 }
405
408 quantize_row_q8_0_ref_local(x, x_q8, K);
409 gemv_q8_0_q8_0_ref_rows(y, W, x_q8, M, K);
410 return;
411 }
412 quantize_row_q8_0(x, x_q8, K);
413 gemv_q8_0_q8_0_x4(y, W, x_q8, M, K);
414}
void gemv_q8_0(float *y, const void *W, const float *x, int M, int K)
Auto-dispatch GEMV for Q8_0 weights based on CPU features.
void gemv_q8_0_q8_0_x4(float *y, const void *W, const void *x_q8, int M, int K)

References CK_Q80_STACK_Q8_BLOCKS, ck_strict_parity_enabled(), gemv_q8_0(), gemv_q8_0_q8_0_ref_rows(), gemv_q8_0_q8_0_x4(), QK8_0, quantize_row_q8_0(), and quantize_row_q8_0_ref_local().

Referenced by gemm_nt_q8_0_q8_0_contract().

◆ gemv_q8_0_q8_0_x4()

void gemv_q8_0_q8_0_x4 ( float *  y,
const void *  W,
const void *  x_q8,
int  M,
int  K 
)

Definition at line 1428 of file gemm_kernels_q8_0.c.

1432{
1433#if defined(__AVX2__) || defined(__AVX512F__)
1434 if (ck_q8_0_q8_0_debug_ref() || (K % QK8_0) != 0) {
1435 gemv_q8_0_q8_0(y, W, x_q8, M, K);
1436 return;
1437 }
1438
1439 const block_q8_0 *w = (const block_q8_0 *)W;
1440 const block_q8_0 *x = (const block_q8_0 *)x_q8;
1441 const int nb = K / QK8_0;
1442 int row = 0;
1443 for (; row + 3 < M; row += 4) {
1444 __m256 acc0 = _mm256_setzero_ps();
1445 __m256 acc1 = _mm256_setzero_ps();
1446 __m256 acc2 = _mm256_setzero_ps();
1447 __m256 acc3 = _mm256_setzero_ps();
1448 const block_q8_0 *w0 = w + (size_t)(row + 0) * (size_t)nb;
1449 const block_q8_0 *w1 = w + (size_t)(row + 1) * (size_t)nb;
1450 const block_q8_0 *w2 = w + (size_t)(row + 2) * (size_t)nb;
1451 const block_q8_0 *w3 = w + (size_t)(row + 3) * (size_t)nb;
1452
1453 for (int ib = 0; ib < nb; ++ib) {
1454 const __m256i qx = _mm256_loadu_si256((const __m256i *)x[ib].qs);
1455 const float dx = CK_FP16_TO_FP32(x[ib].d);
1456 const __m256i qw0 = _mm256_loadu_si256((const __m256i *)w0[ib].qs);
1457 const __m256i qw1 = _mm256_loadu_si256((const __m256i *)w1[ib].qs);
1458 const __m256i qw2 = _mm256_loadu_si256((const __m256i *)w2[ib].qs);
1459 const __m256i qw3 = _mm256_loadu_si256((const __m256i *)w3[ib].qs);
1460 const __m256 p0 = mul_sum_i8_pairs_float_q8_0_avx2(qw0, qx);
1461 const __m256 p1 = mul_sum_i8_pairs_float_q8_0_avx2(qw1, qx);
1462 const __m256 p2 = mul_sum_i8_pairs_float_q8_0_avx2(qw2, qx);
1463 const __m256 p3 = mul_sum_i8_pairs_float_q8_0_avx2(qw3, qx);
1464 const __m256 d0 = _mm256_set1_ps(CK_FP16_TO_FP32(w0[ib].d) * dx);
1465 const __m256 d1 = _mm256_set1_ps(CK_FP16_TO_FP32(w1[ib].d) * dx);
1466 const __m256 d2 = _mm256_set1_ps(CK_FP16_TO_FP32(w2[ib].d) * dx);
1467 const __m256 d3 = _mm256_set1_ps(CK_FP16_TO_FP32(w3[ib].d) * dx);
1468#if defined(__FMA__)
1469 acc0 = _mm256_fmadd_ps(d0, p0, acc0);
1470 acc1 = _mm256_fmadd_ps(d1, p1, acc1);
1471 acc2 = _mm256_fmadd_ps(d2, p2, acc2);
1472 acc3 = _mm256_fmadd_ps(d3, p3, acc3);
1473#else
1474 acc0 = _mm256_add_ps(_mm256_mul_ps(d0, p0), acc0);
1475 acc1 = _mm256_add_ps(_mm256_mul_ps(d1, p1), acc1);
1476 acc2 = _mm256_add_ps(_mm256_mul_ps(d2, p2), acc2);
1477 acc3 = _mm256_add_ps(_mm256_mul_ps(d3, p3), acc3);
1478#endif
1479 }
1480 y[row + 0] = hsum_float_8_q8_0(acc0);
1481 y[row + 1] = hsum_float_8_q8_0(acc1);
1482 y[row + 2] = hsum_float_8_q8_0(acc2);
1483 y[row + 3] = hsum_float_8_q8_0(acc3);
1484 }
1485 if (row < M) {
1486 gemv_q8_0_q8_0(y + row, w + (size_t)row * (size_t)nb,
1487 x, M - row, K);
1488 }
1489#else
1490 gemv_q8_0_q8_0(y, W, x_q8, M, K);
1491#endif
1492}
static int ck_q8_0_q8_0_debug_ref(void)
void gemv_q8_0_q8_0(float *y, const void *W, const void *x_q8, int M, int K)
Matrix-vector multiply with Q8_0 weights and Q8_0 input.

References CK_FP16_TO_FP32, ck_q8_0_q8_0_debug_ref(), gemv_q8_0_q8_0(), and QK8_0.

Referenced by gemv_q8_0_q8_0_contract().

◆ gradient_accumulate_f32()

void gradient_accumulate_f32 ( float *  dst,
const float *  src,
size_t  numel 
)

Definition at line 925 of file optimizer_kernels.c.

926{
927 if (!dst || !src || numel == 0) {
928 return;
929 }
930
931 ck_threadpool_t *pool = ck_threadpool_global();
932 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
933 if (!pool || nth <= 1 || nth > CK_OPT_PAR_MAX_THREADS || numel < CK_OPT_PAR_MIN_NUMEL) {
934 gradient_accumulate_f32_impl(dst, src, numel);
935 return;
936 }
937 int active_nth = ck_opt_pick_active_threads(nth, numel, CK_OPT_PAR_MIN_NUMEL);
938 if (active_nth <= 1) {
939 gradient_accumulate_f32_impl(dst, src, numel);
940 return;
941 }
942
943 ck_accum_parallel_args_t args = {
944 .dst = dst,
945 .src = src,
946 .numel = numel,
947 };
948 ck_threadpool_dispatch_n(pool, active_nth, ck_accum_parallel_work, &args);
949}
static void gradient_accumulate_f32_impl(float *dst, const float *src, size_t numel)
Accumulate gradients: dst += src (fp32)
static void ck_accum_parallel_work(int ith, int nth, void *argp)

References ck_accum_parallel_work(), CK_OPT_PAR_MAX_THREADS, CK_OPT_PAR_MIN_NUMEL, ck_opt_pick_active_threads(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and gradient_accumulate_f32_impl().

◆ gradient_accumulate_multi_f32()

void gradient_accumulate_multi_f32 ( float *const *  dsts,
const float *const *  srcs,
const size_t *  numels,
int  tensor_count 
)

Definition at line 951 of file optimizer_kernels.c.

956{
957 if (!dsts || !srcs || !numels || tensor_count <= 0) {
958 return;
959 }
960
961 size_t total_numel = 0;
962 int valid_tensors = 0;
963 for (int i = 0; i < tensor_count; ++i) {
964 float *dst = dsts[i];
965 const float *src = srcs[i];
966 size_t n = numels[i];
967 if (!dst || !src || n == 0) {
968 continue;
969 }
970 total_numel += n;
971 valid_tensors += 1;
972 }
973 if (total_numel == 0 || valid_tensors == 0) {
974 return;
975 }
976
977 ck_threadpool_t *pool = ck_threadpool_global();
978 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
979 if (!pool || nth <= 1 || nth > CK_OPT_PAR_MAX_THREADS || total_numel < CK_OPT_PAR_MIN_NUMEL) {
980 for (int i = 0; i < tensor_count; ++i) {
981 float *dst = dsts[i];
982 const float *src = srcs[i];
983 size_t n = numels[i];
984 if (!dst || !src || n == 0) {
985 continue;
986 }
987 gradient_accumulate_f32_impl(dst, src, n);
988 }
989 return;
990 }
991
992 int active_nth = ck_opt_pick_active_threads(nth, total_numel, CK_OPT_PAR_MIN_NUMEL);
993 if (active_nth <= 1) {
994 for (int i = 0; i < tensor_count; ++i) {
995 float *dst = dsts[i];
996 const float *src = srcs[i];
997 size_t n = numels[i];
998 if (!dst || !src || n == 0) {
999 continue;
1000 }
1001 gradient_accumulate_f32_impl(dst, src, n);
1002 }
1003 return;
1004 }
1005
1006 ck_accum_multi_parallel_args_t args = {
1007 .dsts = dsts,
1008 .srcs = srcs,
1009 .numels = numels,
1010 .tensor_count = tensor_count,
1011 .total_numel = total_numel,
1012 };
1014}
static void ck_accum_multi_parallel_work(int ith, int nth, void *argp)

References ck_accum_multi_parallel_work(), CK_OPT_PAR_MAX_THREADS, CK_OPT_PAR_MIN_NUMEL, ck_opt_pick_active_threads(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and gradient_accumulate_f32_impl().

◆ gradient_clip_norm_f32()

float gradient_clip_norm_f32 ( float *  grad,
size_t  numel,
float  max_norm 
)

Clip gradient norm (fp32)

If ||grad||_2 > max_norm, scale grad so that ||grad||_2 = max_norm

Parameters
gradGradient tensor to clip (in-place) [numel]
numelNumber of elements
max_normMaximum allowed L2 norm
Returns
The original L2 norm before clipping

Definition at line 1169 of file optimizer_kernels.c.

1170{
1171 if (!grad || numel == 0 || max_norm <= 0.0f) {
1172 return 0.0f;
1173 }
1174
1175 double sum_sq = 0.0;
1176 ck_threadpool_t *pool = ck_threadpool_global();
1177 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
1178
1179 if (pool && nth > 1 && nth <= CK_OPT_PAR_MAX_THREADS && numel >= CK_OPT_PAR_MIN_NUMEL) {
1180 int active_nth = ck_opt_pick_active_threads(nth, numel, CK_OPT_PAR_MIN_NUMEL);
1181 if (active_nth <= 1) {
1182 sum_sq = gradient_sum_sq_f32_impl(grad, numel);
1183 } else {
1184 ck_sum_sq_parallel_args_t args;
1185 args.grad = grad;
1186 args.numel = numel;
1187 for (int i = 0; i < CK_OPT_PAR_MAX_THREADS; ++i) {
1188 args.partial[i] = 0.0;
1189 }
1190 ck_threadpool_dispatch_n(pool, active_nth, ck_sum_sq_parallel_work, &args);
1191 for (int i = 0; i < active_nth; ++i) {
1192 sum_sq += args.partial[i];
1193 }
1194 }
1195 } else {
1196 sum_sq = gradient_sum_sq_f32_impl(grad, numel);
1197 }
1198
1199 float norm = sqrtf((float)sum_sq);
1200 if (norm > max_norm) {
1201 float scale = max_norm / norm;
1202 gradient_scale_f32(grad, numel, scale);
1203 }
1204 return norm;
1205}
static double gradient_sum_sq_f32_impl(const float *grad, size_t numel)
static void ck_sum_sq_parallel_work(int ith, int nth, void *argp)
void gradient_scale_f32(float *grad, size_t numel, float scale)

References CK_OPT_PAR_MAX_THREADS, CK_OPT_PAR_MIN_NUMEL, ck_opt_pick_active_threads(), ck_sum_sq_parallel_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), gradient_scale_f32(), and gradient_sum_sq_f32_impl().

◆ gradient_global_norm_multi_f32()

float gradient_global_norm_multi_f32 ( const float *const *  grads,
const size_t *  numels,
int  tensor_count 
)

Definition at line 1207 of file optimizer_kernels.c.

1208{
1209 if (!grads || !numels || tensor_count <= 0) {
1210 return 0.0f;
1211 }
1212
1213 size_t total_numel = 0;
1214 int valid_tensors = 0;
1215 for (int i = 0; i < tensor_count; ++i) {
1216 if (!grads[i] || numels[i] == 0) {
1217 continue;
1218 }
1219 total_numel += numels[i];
1220 valid_tensors += 1;
1221 }
1222 if (total_numel == 0 || valid_tensors == 0) {
1223 return 0.0f;
1224 }
1225
1226 double sum_sq = 0.0;
1227 ck_threadpool_t *pool = ck_threadpool_global();
1228 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
1229
1230 if (pool && nth > 1 && nth <= CK_OPT_PAR_MAX_THREADS &&
1231 total_numel >= CK_OPT_PAR_MIN_NUMEL && valid_tensors > 1) {
1232 int active_nth = ck_opt_pick_active_threads(nth, total_numel, CK_OPT_PAR_MIN_NUMEL);
1233 if (active_nth > valid_tensors) {
1234 active_nth = valid_tensors;
1235 }
1236 if (active_nth <= 1) {
1237 for (int i = 0; i < tensor_count; ++i) {
1238 const float *g = grads[i];
1239 size_t n = numels[i];
1240 if (!g || n == 0) {
1241 continue;
1242 }
1243 sum_sq += gradient_sum_sq_f32_impl(g, n);
1244 }
1245 } else {
1246 ck_sum_sq_multi_parallel_args_t args;
1247 args.grads = grads;
1248 args.numels = numels;
1249 args.tensor_count = tensor_count;
1250 for (int i = 0; i < CK_OPT_PAR_MAX_THREADS; ++i) {
1251 args.partial[i] = 0.0;
1252 }
1254 for (int i = 0; i < active_nth; ++i) {
1255 sum_sq += args.partial[i];
1256 }
1257 }
1258 } else {
1259 for (int i = 0; i < tensor_count; ++i) {
1260 const float *g = grads[i];
1261 size_t n = numels[i];
1262 if (!g || n == 0) {
1263 continue;
1264 }
1265 sum_sq += gradient_sum_sq_f32_impl(g, n);
1266 }
1267 }
1268
1269 if (!(sum_sq > 0.0)) {
1270 return 0.0f;
1271 }
1272 return sqrtf((float)sum_sq);
1273}
static void ck_sum_sq_multi_parallel_work(int ith, int nth, void *argp)

References CK_OPT_PAR_MAX_THREADS, CK_OPT_PAR_MIN_NUMEL, ck_opt_pick_active_threads(), ck_sum_sq_multi_parallel_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and gradient_sum_sq_f32_impl().

Referenced by adamw_clip_update_multi_f32().

◆ gradient_scale_f32()

void gradient_scale_f32 ( float *  grad,
size_t  numel,
float  scale 
)

Definition at line 1073 of file optimizer_kernels.c.

1074{
1075 if (!grad || numel == 0) {
1076 return;
1077 }
1078
1079 ck_threadpool_t *pool = ck_threadpool_global();
1080 int nth = pool ? ck_threadpool_n_threads(pool) : 1;
1081 if (!pool || nth <= 1 || nth > CK_OPT_PAR_MAX_THREADS || numel < CK_OPT_PAR_MIN_NUMEL) {
1082 gradient_scale_f32_impl(grad, numel, scale);
1083 return;
1084 }
1085 int active_nth = ck_opt_pick_active_threads(nth, numel, CK_OPT_PAR_MIN_NUMEL);
1086 if (active_nth <= 1) {
1087 gradient_scale_f32_impl(grad, numel, scale);
1088 return;
1089 }
1090
1091 ck_scale_parallel_args_t args = {
1092 .grad = grad,
1093 .numel = numel,
1094 .scale = scale,
1095 };
1096 ck_threadpool_dispatch_n(pool, active_nth, ck_scale_parallel_work, &args);
1097}
static void ck_scale_parallel_work(int ith, int nth, void *argp)

References CK_OPT_PAR_MAX_THREADS, CK_OPT_PAR_MIN_NUMEL, ck_opt_pick_active_threads(), ck_scale_parallel_work(), ck_threadpool_dispatch_n(), ck_threadpool_global(), ck_threadpool_n_threads(), and gradient_scale_f32_impl().

◆ group_limited_topk_router_sigmoid_f32()

void group_limited_topk_router_sigmoid_f32 ( const float *  logits,
const float *  correction_bias,
int *  indices,
float *  weights,
int  rows,
int  n_experts,
int  top_k,
int  n_group,
int  topk_group,
int  norm_topk_prob,
float  routed_scaling_factor 
)

Definition at line 798 of file topk_kernels.c.

809{
811 logits, correction_bias, indices, weights, rows, n_experts, top_k,
812 n_group, topk_group, norm_topk_prob, routed_scaling_factor, 1
813 );
814}
static void group_limited_topk_router_f32_impl(const float *scores, const float *correction_bias, int *indices, float *weights, int rows, int n_experts, int top_k, int n_group, int topk_group, int norm_topk_prob, float routed_scaling_factor, int apply_sigmoid)

References group_limited_topk_router_f32_impl().

◆ hyper_connection_mix_bf16()

void hyper_connection_mix_bf16 ( const float *  hyper_input,
const float *  norm_weight,
const uint16_t *  mix_down_weight,
const uint16_t *  mix_up_weight,
const uint16_t *  inject_weight,
float *  mixed_output,
float *  injection_output,
float *  normalized_scratch,
float *  dynamic_scratch,
float *  mix_scratch,
int  rows,
int  streams,
int  hidden_dim,
int  dynamic_dim,
float  eps,
int  emit_injection 
)

Definition at line 73 of file hyper_connection_kernels.c.

88 {
89 if (!hyper_input || !norm_weight || !mix_down_weight || !mix_up_weight ||
90 !mixed_output || !normalized_scratch || !dynamic_scratch || !mix_scratch ||
91 rows <= 0 || streams <= 0 || hidden_dim <= 0 || dynamic_dim <= 0) {
92 return;
93 }
94 if (emit_injection && (!inject_weight || !injection_output)) {
95 return;
96 }
97
98 const int hyper_dim = streams * hidden_dim;
99 const float inv_streams = 1.0f / (float)streams;
100
101 for (int row = 0; row < rows; ++row) {
102 const float *input_row =
103 hyper_input + (size_t)row * (size_t)hyper_dim;
104 float *norm_row =
105 normalized_scratch + (size_t)row * (size_t)hyper_dim;
106 float *dynamic_row =
107 dynamic_scratch + (size_t)row * (size_t)dynamic_dim;
108 float *mix_row = mix_scratch + (size_t)row * (size_t)hyper_dim;
109
110 for (int stream = 0; stream < streams; ++stream) {
111 const int base = stream * hidden_dim;
113 input_row + base,
114 norm_weight + base,
115 norm_row + base,
116 NULL,
117 1,
118 hidden_dim,
119 hidden_dim,
120 eps
121 );
122 }
123
124 for (int out = 0; out < dynamic_dim; ++out) {
125 const uint16_t *weight_row =
126 mix_down_weight + (size_t)out * (size_t)hyper_dim;
127 float sum = 0.0f;
128 for (int col = 0; col < hyper_dim; ++col) {
129 sum += norm_row[col] * bf16_to_float(weight_row[col]);
130 }
131 const float projected = ck_bf16_round(sum * inv_streams);
132 dynamic_row[out] = ck_bf16_round(
133 projected / (1.0f + expf(-projected)));
134 }
135
136 for (int out = 0; out < hyper_dim; ++out) {
137 const uint16_t *weight_row =
138 mix_up_weight + (size_t)out * (size_t)dynamic_dim;
139 float sum = 0.0f;
140 for (int col = 0; col < dynamic_dim; ++col) {
141 sum += dynamic_row[col] * bf16_to_float(weight_row[col]);
142 }
143 mix_row[out] = ck_sigmoid_bf16(ck_bf16_round(sum));
144 }
145
146 float *mixed_row =
147 mixed_output + (size_t)row * (size_t)hidden_dim;
148 for (int col = 0; col < hidden_dim; ++col) {
149 float sum = 0.0f;
150 for (int stream = 0; stream < streams; ++stream) {
151 const int index = stream * hidden_dim + col;
152 sum += ck_bf16_round(norm_row[index] * mix_row[index]);
153 }
154 mixed_row[col] = ck_bf16_round(sum * inv_streams);
155 }
156
157 if (emit_injection) {
158 float *injection_row =
159 injection_output + (size_t)row * (size_t)streams;
160 for (int stream = 0; stream < streams; ++stream) {
161 const uint16_t *weight_row =
162 inject_weight + (size_t)stream * (size_t)hyper_dim;
163 float sum = 0.0f;
164 for (int col = 0; col < hyper_dim; ++col) {
165 sum += norm_row[col] * bf16_to_float(weight_row[col]);
166 }
167 injection_row[stream] = ck_bf16_round(
168 2.0f * ck_sigmoid_bf16(ck_bf16_round(sum * inv_streams)));
169 }
170 }
171 }
172}
void rmsnorm_forward_qwen3next_pytorch_bf16_storage(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
static float ck_sigmoid_bf16(float value)
static float ck_bf16_round(float value)

References bf16_to_float(), ck_bf16_round(), ck_sigmoid_bf16(), and rmsnorm_forward_qwen3next_pytorch_bf16_storage().

◆ hyper_connection_mix_q4k_q5_0_q4k()

void hyper_connection_mix_q4k_q5_0_q4k ( const float *  hyper_input,
const float *  norm_weight,
const void *  mix_down_weight,
const void *  mix_up_weight,
const void *  inject_weight,
float *  mixed_output,
float *  injection_output,
float *  normalized_scratch,
float *  dynamic_scratch,
float *  mix_scratch,
int  rows,
int  streams,
int  hidden_dim,
int  dynamic_dim,
float  eps,
int  emit_injection 
)

Definition at line 350 of file hyper_connection_kernels.c.

365 {
367 hyper_input, norm_weight, mix_down_weight, mix_up_weight, inject_weight,
368 mixed_output, injection_output, normalized_scratch, dynamic_scratch,
369 mix_scratch, rows, streams, hidden_dim, dynamic_dim, eps,
372}
void gemm_nt_q4_k_q8_k_pairwise_split_min_parallel_dispatch(const void *A, const void *B, const float *bias, float *C, int M, int N, int K)
static void hyper_connection_mix_quantized(const float *hyper_input, const float *norm_weight, const void *mix_down_weight, const void *mix_up_weight, const void *inject_weight, float *mixed_output, float *injection_output, float *normalized_scratch, float *dynamic_scratch, float *mix_scratch, int rows, int streams, int hidden_dim, int dynamic_dim, float eps, int emit_injection, ck_hyper_q8k_gemm_fn injection_gemm, ck_hyper_q8k_gemm_fn down_gemm)
static void hyper_injection_q4k_q8k_llama_dispatch(const void *input, const void *weight, const float *bias, float *output, int rows, int output_dim, int input_dim)

References gemm_nt_q4_k_q8_k_pairwise_split_min_parallel_dispatch(), hyper_connection_mix_quantized(), and hyper_injection_q4k_q8k_llama_dispatch().

◆ hyper_connection_mix_q6k_q5_0_q4k()

void hyper_connection_mix_q6k_q5_0_q4k ( const float *  hyper_input,
const float *  norm_weight,
const void *  mix_down_weight,
const void *  mix_up_weight,
const void *  inject_weight,
float *  mixed_output,
float *  injection_output,
float *  normalized_scratch,
float *  dynamic_scratch,
float *  mix_scratch,
int  rows,
int  streams,
int  hidden_dim,
int  dynamic_dim,
float  eps,
int  emit_injection 
)

Definition at line 374 of file hyper_connection_kernels.c.

389 {
391 hyper_input, norm_weight, mix_down_weight, mix_up_weight, inject_weight,
392 mixed_output, injection_output, normalized_scratch, dynamic_scratch,
393 mix_scratch, rows, streams, hidden_dim, dynamic_dim, eps,
396}
void gemm_nt_q6_k_q8_k_parallel_dispatch(const void *A, const void *B, const float *bias, float *C, int M, int N, int K)

References gemm_nt_q6_k_q8_k_parallel_dispatch(), hyper_connection_mix_quantized(), and hyper_injection_q4k_q8k_llama_dispatch().

◆ hyper_stream_expand_bf16()

void hyper_stream_expand_bf16 ( const float *  input,
float *  output,
int  rows,
int  streams,
int  hidden_dim 
)

Definition at line 53 of file hyper_connection_kernels.c.

57 {
58 if (!input || !output || rows <= 0 || streams <= 0 || hidden_dim <= 0) {
59 return;
60 }
61 for (int row = 0; row < rows; ++row) {
62 const float *src = input + (size_t)row * (size_t)hidden_dim;
63 float *dst = output + (size_t)row * (size_t)streams * (size_t)hidden_dim;
64 for (int stream = 0; stream < streams; ++stream) {
65 for (int col = 0; col < hidden_dim; ++col) {
66 dst[(size_t)stream * (size_t)hidden_dim + (size_t)col] =
67 ck_bf16_round(src[col]);
68 }
69 }
70 }
71}

References ck_bf16_round().

◆ hyper_stream_expand_f32()

void hyper_stream_expand_f32 ( const float *  input,
float *  output,
int  rows,
int  streams,
int  hidden_dim 
)

Definition at line 34 of file hyper_connection_kernels.c.

38 {
39 if (!input || !output || rows <= 0 || streams <= 0 || hidden_dim <= 0) {
40 return;
41 }
42 for (int row = 0; row < rows; ++row) {
43 const float *src = input + (size_t)row * (size_t)hidden_dim;
44 float *dst = output + (size_t)row * (size_t)streams * (size_t)hidden_dim;
45 for (int stream = 0; stream < streams; ++stream) {
46 for (int col = 0; col < hidden_dim; ++col) {
47 dst[(size_t)stream * (size_t)hidden_dim + (size_t)col] = src[col];
48 }
49 }
50 }
51}

◆ hyper_stream_inject_bf16()

void hyper_stream_inject_bf16 ( const float *  hyper_input,
const float *  block_output,
const float *  injection_weight,
float *  output,
int  rows,
int  streams,
int  hidden_dim 
)

Definition at line 398 of file hyper_connection_kernels.c.

404 {
405 if (!hyper_input || !block_output || !injection_weight || !output ||
406 rows <= 0 || streams <= 0 || hidden_dim <= 0) {
407 return;
408 }
409 const int hyper_dim = streams * hidden_dim;
410 for (int row = 0; row < rows; ++row) {
411 const float *hyper_row =
412 hyper_input + (size_t)row * (size_t)hyper_dim;
413 const float *block_row =
414 block_output + (size_t)row * (size_t)hidden_dim;
415 const float *inject_row =
416 injection_weight + (size_t)row * (size_t)streams;
417 float *output_row = output + (size_t)row * (size_t)hyper_dim;
418 for (int stream = 0; stream < streams; ++stream) {
419 for (int col = 0; col < hidden_dim; ++col) {
420 const int index = stream * hidden_dim + col;
421 output_row[index] = ck_bf16_round(
422 hyper_row[index] +
423 ck_bf16_round(block_row[col] * inject_row[stream]));
424 }
425 }
426 }
427}

References ck_bf16_round().

◆ hyper_stream_inject_f32()

void hyper_stream_inject_f32 ( const float *  hyper_input,
const float *  block_output,
const float *  injection_weight,
float *  output,
int  rows,
int  streams,
int  hidden_dim 
)

Definition at line 429 of file hyper_connection_kernels.c.

435 {
436 if (!hyper_input || !block_output || !injection_weight || !output ||
437 rows <= 0 || streams <= 0 || hidden_dim <= 0) {
438 return;
439 }
440 const int hyper_dim = streams * hidden_dim;
441 for (int row = 0; row < rows; ++row) {
442 const float *hyper_row =
443 hyper_input + (size_t)row * (size_t)hyper_dim;
444 const float *block_row =
445 block_output + (size_t)row * (size_t)hidden_dim;
446 const float *inject_row =
447 injection_weight + (size_t)row * (size_t)streams;
448 float *output_row = output + (size_t)row * (size_t)hyper_dim;
449 for (int stream = 0; stream < streams; ++stream) {
450 for (int col = 0; col < hidden_dim; ++col) {
451 const int index = stream * hidden_dim + col;
452 volatile const float weighted =
453 block_row[col] * inject_row[stream];
454 output_row[index] = hyper_row[index] + weighted;
455 }
456 }
457 }
458}

◆ im2patch()

void im2patch ( const float *  image,
float *  patches,
int  C,
int  H,
int  W,
int  P 
)

im2patch: Transforms an image into a sequence of flattened patches.

Image Layout: [C, H, W] (Row-major: W is fastest moving) Output Layout: [num_patches, C * P * P]

num_patches = (H/P) * (W/P) P = patch_size

Definition at line 82 of file vision_kernels.c.

85{
86 int num_patches_h = H / P;
87 int num_patches_w = W / P;
88 int patch_dim = C * P * P;
89
90 // ph, pw: patch grid coordinates
91 for (int ph = 0; ph < num_patches_h; ++ph) {
92 for (int pw = 0; pw < num_patches_w; ++pw) {
93
94 int patch_idx = ph * num_patches_w + pw;
95 float *dst_patch = patches + (size_t)patch_idx * patch_dim;
96
97 // For each patch, grab pixels from all channels
98 for (int c = 0; c < C; ++c) {
99 for (int py = 0; py < P; ++py) {
100 int y = ph * P + py;
101 int x = pw * P;
102
103 // Input row start in the image
104 const float *src_row = image + (size_t)c * H * W + (size_t)y * W + x;
105
106 // Destination row in the flattened patch sequence
107 float *dst_row = dst_patch + (size_t)c * P * P + (size_t)py * P;
108
109 // Copy P pixels (one row of the patch)
110 memcpy(dst_row, src_row, P * sizeof(float));
111 }
112 }
113 }
114 }
115}

References C.

◆ im2patch_bf16()

void im2patch_bf16 ( const uint16_t *  image,
uint16_t *  patches,
int  C,
int  H,
int  W,
int  P 
)

Definition at line 22 of file vision_kernels_bf16.c.

28{
29 if (!image || !patches || C <= 0 || H <= 0 || W <= 0 || P <= 0) {
30 return;
31 }
32
33 int num_patches_h = H / P;
34 int num_patches_w = W / P;
35 int patch_dim = C * P * P;
36
37 for (int ph = 0; ph < num_patches_h; ++ph) {
38 for (int pw = 0; pw < num_patches_w; ++pw) {
39 int patch_idx = ph * num_patches_w + pw;
40 uint16_t *dst_patch = patches + (size_t)patch_idx * (size_t)patch_dim;
41
42 for (int c = 0; c < C; ++c) {
43 for (int py = 0; py < P; ++py) {
44 int y = ph * P + py;
45 int x = pw * P;
46
47 const uint16_t *src_row = image + (size_t)c * (size_t)H * (size_t)W + (size_t)y * (size_t)W + (size_t)x;
48 uint16_t *dst_row = dst_patch + (size_t)c * (size_t)P * (size_t)P + (size_t)py * (size_t)P;
49
50 memcpy(dst_row, src_row, (size_t)P * sizeof(uint16_t));
51 }
52 }
53 }
54 }
55}

References C.

◆ kv_cache_repack_head_major_inplace()

void kv_cache_repack_head_major_inplace ( float *  buf,
int  num_heads,
int  tokens,
int  cache_capacity,
int  aligned_head_dim 
)

Definition at line 49 of file kv_cache_kernels.c.

54{
55 if (!buf) {
56 return;
57 }
58 if (num_heads <= 0 || tokens <= 0 || cache_capacity <= 0 || aligned_head_dim <= 0) {
59 return;
60 }
61 if (tokens > cache_capacity) {
62 tokens = cache_capacity;
63 }
64 if (tokens == cache_capacity) {
65 return;
66 }
67
68 const size_t old_head_stride = (size_t)tokens * (size_t)aligned_head_dim;
69 const size_t new_head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
70 const size_t bytes = (size_t)tokens * (size_t)aligned_head_dim * sizeof(float);
71
72 // Move head blocks from high to low to avoid overwriting source data
73 // for heads that have not yet been moved.
74 for (int h = num_heads - 1; h >= 0; --h) {
75 float *src = buf + (size_t)h * old_head_stride;
76 float *dst = buf + (size_t)h * new_head_stride;
77 memmove(dst, src, bytes);
78 }
79}

Referenced by qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), and qwen2_0_5b_decode_forward_prefill_impl().

◆ kv_cache_store()

void kv_cache_store ( float *__restrict  kv_cache_k,
float *__restrict  kv_cache_v,
const float *__restrict  k,
const float *__restrict  v,
int  layer,
int  pos,
int  num_kv_heads,
int  head_dim,
int  max_seq_len 
)

Definition at line 122 of file kv_cache_kernels.c.

131{
132 (void)layer;
134 kv_cache_k, kv_cache_v,
135 num_kv_heads,
136 pos,
137 max_seq_len,
138 head_dim,
139 head_dim);
140}
void kv_cache_write_head_major(const float *__restrict k_token, const float *__restrict v_token, float *__restrict k_cache, float *__restrict v_cache, int num_kv_heads, int token_index, int cache_capacity, int head_dim, int aligned_head_dim)

References kv_cache_write_head_major().

◆ kv_cache_store_batch_bf16()

void kv_cache_store_batch_bf16 ( uint16_t *__restrict  kv_cache_k,
uint16_t *__restrict  kv_cache_v,
const float *__restrict  k,
const float *__restrict  v,
int  start_pos,
int  num_tokens,
int  num_kv_heads,
int  head_dim,
int  max_seq_len 
)

Definition at line 291 of file kv_cache_kernels.c.

300{
301 if (!kv_cache_k || !kv_cache_v || !k || !v ||
302 start_pos < 0 || num_tokens <= 0 || num_kv_heads <= 0 ||
303 head_dim <= 0 || max_seq_len <= 0 ||
304 start_pos > max_seq_len - num_tokens) {
305 return;
306 }
307
308 const size_t compact_head_stride = (size_t)num_tokens * (size_t)head_dim;
309 const size_t cache_head_stride = (size_t)max_seq_len * (size_t)head_dim;
310 for (int h = 0; h < num_kv_heads; ++h) {
311 const float *k_head = k + (size_t)h * compact_head_stride;
312 const float *v_head = v + (size_t)h * compact_head_stride;
313 uint16_t *k_head_cache = kv_cache_k + (size_t)h * cache_head_stride;
314 uint16_t *v_head_cache = kv_cache_v + (size_t)h * cache_head_stride;
315 for (int t = 0; t < num_tokens; ++t) {
316 const size_t src_offset = (size_t)t * (size_t)head_dim;
317 const size_t dst_offset = (size_t)(start_pos + t) * (size_t)head_dim;
318 ck_local_fp32_to_bf16_row(k_head + src_offset, k_head_cache + dst_offset, head_dim);
319 ck_local_fp32_to_bf16_row(v_head + src_offset, v_head_cache + dst_offset, head_dim);
320 }
321 }
322}
static void ck_local_fp32_to_bf16_row(const float *src, uint16_t *dst, int n)

References ck_local_fp32_to_bf16_row().

◆ kv_cache_store_batch_f16()

void kv_cache_store_batch_f16 ( uint16_t *__restrict  kv_cache_k,
uint16_t *__restrict  kv_cache_v,
const float *__restrict  k,
const float *__restrict  v,
int  start_pos,
int  num_tokens,
int  num_kv_heads,
int  head_dim,
int  max_seq_len 
)

Definition at line 255 of file kv_cache_kernels.c.

264{
265 if (!kv_cache_k || !kv_cache_v || !k || !v) {
266 return;
267 }
268 if (start_pos < 0 || num_tokens <= 0 || num_kv_heads <= 0 ||
269 head_dim <= 0 || max_seq_len <= 0 ||
270 start_pos > max_seq_len - num_tokens) {
271 return;
272 }
273
274 const size_t compact_head_stride = (size_t)num_tokens * (size_t)head_dim;
275 const size_t cache_head_stride = (size_t)max_seq_len * (size_t)head_dim;
276
277 for (int h = 0; h < num_kv_heads; ++h) {
278 const float *k_head = k + (size_t)h * compact_head_stride;
279 const float *v_head = v + (size_t)h * compact_head_stride;
280 uint16_t *k_head_cache = kv_cache_k + (size_t)h * cache_head_stride;
281 uint16_t *v_head_cache = kv_cache_v + (size_t)h * cache_head_stride;
282 for (int t = 0; t < num_tokens; ++t) {
283 const size_t src_offset = (size_t)t * (size_t)head_dim;
284 const size_t dst_offset = (size_t)(start_pos + t) * (size_t)head_dim;
285 ck_local_fp32_to_fp16_row(k_head + src_offset, k_head_cache + dst_offset, head_dim);
286 ck_local_fp32_to_fp16_row(v_head + src_offset, v_head_cache + dst_offset, head_dim);
287 }
288 }
289}
static void ck_local_fp32_to_fp16_row(const float *src, uint16_t *dst, int n)

References ck_local_fp32_to_fp16_row().

◆ kv_cache_store_batch_f32()

void kv_cache_store_batch_f32 ( float *__restrict  kv_cache_k,
float *__restrict  kv_cache_v,
const float *__restrict  k,
const float *__restrict  v,
int  start_pos,
int  num_tokens,
int  num_kv_heads,
int  head_dim,
int  max_seq_len 
)

Definition at line 223 of file kv_cache_kernels.c.

232{
233 if (!kv_cache_k || !kv_cache_v || !k || !v ||
234 start_pos < 0 || num_tokens <= 0 || num_kv_heads <= 0 ||
235 head_dim <= 0 || max_seq_len <= 0 ||
236 start_pos > max_seq_len - num_tokens) {
237 return;
238 }
239
240 const size_t compact_head_stride = (size_t)num_tokens * (size_t)head_dim;
241 const size_t cache_head_stride = (size_t)max_seq_len * (size_t)head_dim;
242 const size_t token_bytes = (size_t)num_tokens * (size_t)head_dim * sizeof(float);
243 for (int h = 0; h < num_kv_heads; ++h) {
244 const float *k_head = k + (size_t)h * compact_head_stride;
245 const float *v_head = v + (size_t)h * compact_head_stride;
246 float *k_head_cache = kv_cache_k + (size_t)h * cache_head_stride
247 + (size_t)start_pos * (size_t)head_dim;
248 float *v_head_cache = kv_cache_v + (size_t)h * cache_head_stride
249 + (size_t)start_pos * (size_t)head_dim;
250 memcpy(k_head_cache, k_head, token_bytes);
251 memcpy(v_head_cache, v_head, token_bytes);
252 }
253}

◆ kv_cache_store_bf16()

void kv_cache_store_bf16 ( uint16_t *__restrict  kv_cache_k,
uint16_t *__restrict  kv_cache_v,
const float *__restrict  k,
const float *__restrict  v,
int  layer,
int  pos,
int  num_kv_heads,
int  head_dim,
int  max_seq_len 
)

Definition at line 195 of file kv_cache_kernels.c.

204{
205 (void)layer;
206 if (!kv_cache_k || !kv_cache_v || !k || !v ||
207 num_kv_heads <= 0 || pos < 0 || pos >= max_seq_len ||
208 head_dim <= 0 || max_seq_len <= 0) {
209 return;
210 }
211
212 const size_t head_stride = (size_t)max_seq_len * (size_t)head_dim;
213 for (int h = 0; h < num_kv_heads; ++h) {
214 const float *k_src = k + (size_t)h * (size_t)head_dim;
215 const float *v_src = v + (size_t)h * (size_t)head_dim;
216 uint16_t *k_dst = kv_cache_k + (size_t)h * head_stride + (size_t)pos * (size_t)head_dim;
217 uint16_t *v_dst = kv_cache_v + (size_t)h * head_stride + (size_t)pos * (size_t)head_dim;
218 ck_local_fp32_to_bf16_row(k_src, k_dst, head_dim);
219 ck_local_fp32_to_bf16_row(v_src, v_dst, head_dim);
220 }
221}

References ck_local_fp32_to_bf16_row().

◆ kv_cache_store_f16()

void kv_cache_store_f16 ( uint16_t *__restrict  kv_cache_k,
uint16_t *__restrict  kv_cache_v,
const float *__restrict  k,
const float *__restrict  v,
int  layer,
int  pos,
int  num_kv_heads,
int  head_dim,
int  max_seq_len 
)

Definition at line 161 of file kv_cache_kernels.c.

170{
171 (void)layer;
172 if (!kv_cache_k || !kv_cache_v || !k || !v) {
173 return;
174 }
175 if (num_kv_heads <= 0 || pos < 0 || head_dim <= 0 || max_seq_len <= 0) {
176 return;
177 }
178 if (pos >= max_seq_len) {
179 return;
180 }
181
182 const size_t head_stride = (size_t)max_seq_len * (size_t)head_dim;
183 const size_t token_stride = (size_t)head_dim;
184
185 for (int h = 0; h < num_kv_heads; ++h) {
186 const float *k_src = k + (size_t)h * token_stride;
187 const float *v_src = v + (size_t)h * token_stride;
188 uint16_t *k_dst = kv_cache_k + (size_t)h * head_stride + (size_t)pos * token_stride;
189 uint16_t *v_dst = kv_cache_v + (size_t)h * head_stride + (size_t)pos * token_stride;
190 ck_local_fp32_to_fp16_row(k_src, k_dst, head_dim);
191 ck_local_fp32_to_fp16_row(v_src, v_dst, head_dim);
192 }
193}

References ck_local_fp32_to_fp16_row().

◆ kv_cache_store_shared_q()

void kv_cache_store_shared_q ( float *__restrict  kv_cache_k,
float *__restrict  kv_cache_v,
const float *__restrict  q,
int  layer,
int  pos,
int  num_heads,
int  head_dim,
int  max_seq_len 
)

Definition at line 142 of file kv_cache_kernels.c.

150{
151 (void)layer;
153 kv_cache_k, kv_cache_v,
154 num_heads,
155 pos,
156 max_seq_len,
157 head_dim,
158 head_dim);
159}

References kv_cache_write_head_major().

◆ kv_cache_write_head_major()

void kv_cache_write_head_major ( const float *__restrict  k_token,
const float *__restrict  v_token,
float *__restrict  k_cache,
float *__restrict  v_cache,
int  num_kv_heads,
int  token_index,
int  cache_capacity,
int  head_dim,
int  aligned_head_dim 
)

Definition at line 81 of file kv_cache_kernels.c.

90{
91 if (!k_token || !v_token || !k_cache || !v_cache) {
92 return;
93 }
94 if (num_kv_heads <= 0 || token_index < 0 || cache_capacity <= 0) {
95 return;
96 }
97 if (token_index >= cache_capacity || head_dim <= 0 || aligned_head_dim <= 0) {
98 return;
99 }
100
101 const size_t head_stride = (size_t)cache_capacity * (size_t)aligned_head_dim;
102 const size_t token_stride = (size_t)aligned_head_dim;
103
104 for (int h = 0; h < num_kv_heads; ++h) {
105 const float *k_src = k_token + (size_t)h * token_stride;
106 const float *v_src = v_token + (size_t)h * token_stride;
107
108 float *k_dst = k_cache + (size_t)h * head_stride + (size_t)token_index * token_stride;
109 float *v_dst = v_cache + (size_t)h * head_stride + (size_t)token_index * token_stride;
110
111 for (int d = 0; d < head_dim; ++d) {
112 k_dst[d] = k_src[d];
113 v_dst[d] = v_src[d];
114 }
115 for (int d = head_dim; d < aligned_head_dim; ++d) {
116 k_dst[d] = 0.0f;
117 v_dst[d] = 0.0f;
118 }
119 }
120}

Referenced by ck_layer_forward_rmsnorm_swiglu_decode(), ck_layer_forward_rmsnorm_swiglu_decode_fused(), ck_layer_forward_rmsnorm_swiglu_decode_fused_attn_impl(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), ck_layer_forward_rmsnorm_swiglu_decode_quant(), kv_cache_store(), kv_cache_store_shared_q(), mega_fused_attention_decode_workspace(), 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().

◆ layernorm_backward_kernel()

void layernorm_backward_kernel ( const float *  d_output,
const float *  input,
const float *  gamma,
const float *  mean,
const float *  rstd,
float *  d_input,
float *  d_gamma,
float *  d_beta,
int  tokens,
int  d_model,
int  aligned_embed_dim 
)

Definition at line 1007 of file layernorm_kernels.c.

1016{
1017 int T = tokens;
1018 int D = d_model;
1019 int aligned_D = aligned_embed_dim;
1020
1021 // Per-token input gradients
1022 for (int t = 0; t < T; ++t) {
1023 float mean_t = mean[t];
1024 float rstd_t = rstd[t];
1025
1026 float d_y_gamma_sum = 0.0f;
1027 float d_y_gamma_xhat_sum = 0.0f;
1028
1029 // First pass: compute sums
1030 for (int d = 0; d < D; ++d) {
1031 float x = input[t * aligned_D + d];
1032 float x_hat = (x - mean_t) * rstd_t;
1033 float d_y = d_output[t * aligned_D + d];
1034 float d_y_gamma = d_y * gamma[d];
1035
1036 d_y_gamma_sum += d_y_gamma;
1037 d_y_gamma_xhat_sum += d_y_gamma * x_hat;
1038 }
1039
1040 // Second pass: compute input gradients
1041 float scale = rstd_t / (float)D;
1042 for (int d = 0; d < D; ++d) {
1043 float x = input[t * aligned_D + d];
1044 float x_hat = (x - mean_t) * rstd_t;
1045 float d_y = d_output[t * aligned_D + d];
1046
1047 d_input[t * aligned_D + d] =
1048 scale * ((float)D * d_y * gamma[d] - d_y_gamma_sum - x_hat * d_y_gamma_xhat_sum);
1049 }
1050
1051 // Zero padding for aligned dimension beyond D
1052 for (int d = D; d < aligned_D; ++d) {
1053 d_input[t * aligned_D + d] = 0.0f;
1054 }
1055 }
1056
1057 // Parameter gradients (gamma, beta)
1058 for (int d = 0; d < D; ++d) {
1059 float gamma_grad = 0.0f;
1060 float beta_grad = 0.0f;
1061
1062 for (int t = 0; t < T; ++t) {
1063 float x = input[t * aligned_D + d];
1064 float x_hat = (x - mean[t]) * rstd[t];
1065 float d_y = d_output[t * aligned_D + d];
1066
1067 gamma_grad += d_y * x_hat;
1068 beta_grad += d_y;
1069 }
1070
1071 d_gamma[d] += gamma_grad;
1072 d_beta[d] += beta_grad;
1073 }
1074}

Referenced by layernorm_backward_kernel_bf16().

◆ layernorm_backward_kernel_bf16()

void layernorm_backward_kernel_bf16 ( const uint16_t *  d_output,
const uint16_t *  input,
const float *  gamma,
const float *  mean,
const float *  rstd,
uint16_t *  d_input,
float *  d_gamma,
float *  d_beta,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float *  scratch_d_output,
float *  scratch_input,
float *  scratch_d_input 
)

Definition at line 84 of file layernorm_kernels_bf16.c.

96{
97 if (!scratch_d_output || !scratch_input || !scratch_d_input) return;
98
99 size_t total = (size_t)tokens * (size_t)aligned_embed_dim;
100
101 bf16_tensor_to_float(d_output, scratch_d_output, total);
102 bf16_tensor_to_float(input, scratch_input, total);
103
104 layernorm_backward_kernel(scratch_d_output, scratch_input, gamma, mean, rstd,
105 scratch_d_input, d_gamma, d_beta,
106 tokens, d_model, aligned_embed_dim);
107
108 float_tensor_to_bf16(scratch_d_input, d_input, total);
109}
void layernorm_backward_kernel(const float *d_output, const float *input, const float *gamma, const float *mean, const float *rstd, float *d_input, float *d_gamma, float *d_beta, int tokens, int d_model, int aligned_embed_dim)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and layernorm_backward_kernel().

◆ layernorm_forward_rolled_slice()

void layernorm_forward_rolled_slice ( const float *__restrict  input_slice_base,
const float *__restrict  gamma,
const float *__restrict  beta,
float *__restrict  output_slice_base,
float *__restrict  mean_cache_slice,
float *__restrict  rstd_cache_slice,
int  num_tokens_in_slice,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 398 of file layernorm_kernels.c.

408{
410 layernorm_forward_ggml_exact(input_slice_base, gamma, beta,
411 output_slice_base, mean_cache_slice, rstd_cache_slice,
412 num_tokens_in_slice, d_model,
413 aligned_embed_dim, aligned_embed_dim, aligned_embed_dim, eps);
414 return;
415 }
416
417#if defined(__AVX512F__)
418 layernorm_forward_rolled_slice_avx512(input_slice_base, gamma, beta,
419 output_slice_base, mean_cache_slice, rstd_cache_slice,
420 num_tokens_in_slice, d_model, aligned_embed_dim, eps);
421#elif defined(__AVX2__) || defined(__AVX__)
422 layernorm_forward_rolled_slice_avx256(input_slice_base, gamma, beta,
423 output_slice_base, mean_cache_slice, rstd_cache_slice,
424 num_tokens_in_slice, d_model, aligned_embed_dim, eps);
425#else
426 layernorm_naive_serial(input_slice_base, gamma, beta,
427 output_slice_base, mean_cache_slice, rstd_cache_slice,
428 num_tokens_in_slice, d_model, aligned_embed_dim, eps);
429#endif
430}
static void layernorm_forward_ggml_exact(const float *input, const float *gamma, const float *beta, float *output, float *mean_cache, float *rstd_cache, int tokens, int d_model, int input_stride, int output_stride, int aligned_embed_dim, float eps)
void layernorm_naive_serial(const float *input, const float *gamma, const float *beta, float *output, float *mean_cache, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References ck_strict_parity_enabled(), layernorm_forward_ggml_exact(), and layernorm_naive_serial().

Referenced by layernorm_forward_rolled_slice_bf16().

◆ layernorm_forward_rolled_slice_bf16()

void layernorm_forward_rolled_slice_bf16 ( const uint16_t *__restrict  input_slice_base,
const float *__restrict  gamma,
const float *__restrict  beta,
uint16_t *__restrict  output_slice_base,
float *__restrict  mean_cache_slice,
float *__restrict  rstd_cache_slice,
int  num_tokens_in_slice,
int  d_model,
int  aligned_embed_dim,
float  eps,
float *  scratch_input,
float *  scratch_output 
)

Definition at line 30 of file layernorm_kernels_bf16.c.

42{
43 if (!scratch_input || !scratch_output) return;
44
45 size_t total = (size_t)num_tokens_in_slice * (size_t)aligned_embed_dim;
46
47 bf16_tensor_to_float(input_slice_base, scratch_input, total);
48 layernorm_forward_rolled_slice(scratch_input, gamma, beta,
49 scratch_output, mean_cache_slice, rstd_cache_slice,
50 num_tokens_in_slice, d_model, aligned_embed_dim, eps);
51 float_tensor_to_bf16(scratch_output, output_slice_base, total);
52}
void layernorm_forward_rolled_slice(const float *__restrict input_slice_base, const float *__restrict gamma, const float *__restrict beta, float *__restrict output_slice_base, float *__restrict mean_cache_slice, float *__restrict rstd_cache_slice, int num_tokens_in_slice, int d_model, int aligned_embed_dim, float eps)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and layernorm_forward_rolled_slice().

◆ layernorm_forward_unrolled_slice()

void layernorm_forward_unrolled_slice ( const float *__restrict  input_slice_base,
const float *__restrict  gamma,
const float *__restrict  beta,
float *__restrict  output_slice_base,
float *__restrict  mean_cache_slice,
float *__restrict  rstd_cache_slice,
int  num_tokens_in_slice,
int  d_model,
float  eps 
)

Definition at line 730 of file layernorm_kernels.c.

739{
741 layernorm_forward_ggml_exact(input_slice_base, gamma, beta,
742 output_slice_base, mean_cache_slice, rstd_cache_slice,
743 num_tokens_in_slice, d_model,
744 d_model, d_model, d_model, eps);
745 return;
746 }
747
748#if defined(__AVX512F__)
749 layernorm_forward_unrolled_slice_avx512(input_slice_base, gamma, beta,
750 output_slice_base, mean_cache_slice, rstd_cache_slice,
751 num_tokens_in_slice, d_model, eps);
752#elif defined(__AVX2__) || defined(__AVX__)
753 layernorm_forward_unrolled_slice_avx256(input_slice_base, gamma, beta,
754 output_slice_base, mean_cache_slice, rstd_cache_slice,
755 num_tokens_in_slice, d_model, eps);
756#else
757 layernorm_forward_unrolled_slice_scalar(input_slice_base, gamma, beta,
758 output_slice_base, mean_cache_slice, rstd_cache_slice,
759 num_tokens_in_slice, d_model, eps);
760#endif
761}
static void layernorm_forward_unrolled_slice_scalar(const float *__restrict input_slice_base, const float *__restrict gamma, const float *__restrict beta, float *__restrict output_slice_base, float *__restrict mean_cache_slice, float *__restrict rstd_cache_slice, int num_tokens_in_slice, int d_model, float eps)

References ck_strict_parity_enabled(), layernorm_forward_ggml_exact(), and layernorm_forward_unrolled_slice_scalar().

Referenced by layernorm_forward_unrolled_slice_bf16().

◆ layernorm_forward_unrolled_slice_bf16()

void layernorm_forward_unrolled_slice_bf16 ( const uint16_t *__restrict  input_slice_base,
const float *__restrict  gamma,
const float *__restrict  beta,
uint16_t *__restrict  output_slice_base,
float *__restrict  mean_cache_slice,
float *__restrict  rstd_cache_slice,
int  num_tokens_in_slice,
int  d_model,
float  eps,
float *  scratch_input,
float *  scratch_output 
)

Definition at line 57 of file layernorm_kernels_bf16.c.

68{
69 if (!scratch_input || !scratch_output) return;
70
71 size_t total = (size_t)num_tokens_in_slice * (size_t)d_model;
72
73 bf16_tensor_to_float(input_slice_base, scratch_input, total);
74 layernorm_forward_unrolled_slice(scratch_input, gamma, beta,
75 scratch_output, mean_cache_slice, rstd_cache_slice,
76 num_tokens_in_slice, d_model, eps);
77 float_tensor_to_bf16(scratch_output, output_slice_base, total);
78}
void layernorm_forward_unrolled_slice(const float *__restrict input_slice_base, const float *__restrict gamma, const float *__restrict beta, float *__restrict output_slice_base, float *__restrict mean_cache_slice, float *__restrict rstd_cache_slice, int num_tokens_in_slice, int d_model, float eps)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and layernorm_forward_unrolled_slice().

◆ layernorm_naive_serial()

void layernorm_naive_serial ( const float *  input,
const float *  gamma,
const float *  beta,
float *  output,
float *  mean_cache,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 175 of file layernorm_kernels.c.

183{
184 for (int t = 0; t < tokens; ++t) {
185 const float *in_ptr = input + t * aligned_embed_dim;
186 float *out_ptr = output + t * aligned_embed_dim;
187
188 float sum_val = 0.0f;
189 for (int i = 0; i < d_model; ++i) {
190 sum_val += in_ptr[i];
191 }
192 float mean = sum_val / (float)d_model;
193
194 float sum_sq_diff = 0.0f;
195 for (int i = 0; i < d_model; ++i) {
196 float diff = in_ptr[i] - mean;
197 sum_sq_diff += diff * diff;
198 }
199 float variance = sum_sq_diff / (float)d_model + eps;
200
201 double var_double = (double)variance;
202 float inv_std = (float)(1.0 / sqrt(var_double));
203
204 for (int i = 0; i < d_model; ++i) {
205 float normalized_val = (in_ptr[i] - mean) * inv_std;
206 out_ptr[i] = normalized_val * gamma[i] + beta[i];
207 }
208
209 if (mean_cache) {
210 mean_cache[t] = mean;
211 }
212 if (rstd_cache) {
213 rstd_cache[t] = inv_std;
214 }
215 /* Keep aligned padding quiet so future GEMMs see deterministic memory. */
216 if (aligned_embed_dim > d_model) {
217 /* Keep padded lanes zeroed so subsequent GEMMs never read stale data. */
218 for (int i = d_model; i < aligned_embed_dim; ++i) {
219 out_ptr[i] = 0.0f;
220 }
221 }
222 }
223}

Referenced by layernorm_forward_rolled_slice().

◆ layernorm_naive_serial_bf16_storage()

void layernorm_naive_serial_bf16_storage ( const float *  input,
const float *  gamma,
const float *  beta,
float *  output,
float *  mean_cache,
float *  rstd_cache,
int  tokens,
int  d_model,
float  eps 
)

Definition at line 786 of file layernorm_kernels.c.

793{
794 const size_t count = (size_t)tokens * (size_t)d_model;
795 for (size_t i = 0; i < count; ++i) {
796 output[i] = bf16_to_float(float_to_bf16(input[i]));
797 }
798 layernorm_forward_ggml_exact(output, gamma, beta,
799 output, mean_cache, rstd_cache,
800 tokens, d_model,
801 d_model, d_model, d_model, eps);
802 for (size_t i = 0; i < count; ++i) {
803 output[i] = bf16_to_float(float_to_bf16(output[i]));
804 }
805}

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

◆ layernorm_naive_serial_matched_precision()

void layernorm_naive_serial_matched_precision ( const float *  input,
const float *  gamma,
const float *  beta,
float *  output,
float *  mean_cache,
float *  rstd_cache,
int  tokens,
int  d_model,
float  eps 
)

Definition at line 764 of file layernorm_kernels.c.

771{
772 layernorm_forward_ggml_exact(input, gamma, beta,
773 output, mean_cache, rstd_cache,
774 tokens, d_model,
775 d_model, d_model, d_model, eps);
776}

References layernorm_forward_ggml_exact().

Referenced by layernorm_rows_checked_f32().

◆ layernorm_pytorch_welford_bf16_storage()

void layernorm_pytorch_welford_bf16_storage ( const float *  input,
const float *  gamma,
const float *  beta,
float *  output,
float *  mean_cache,
float *  rstd_cache,
int  tokens,
int  d_model,
float  eps 
)

Definition at line 952 of file layernorm_kernels.c.

961{
962#if !defined(__AVX2__) || !defined(__FMA__)
963 (void)input; (void)gamma; (void)beta; (void)output;
964 (void)mean_cache; (void)rstd_cache; (void)tokens; (void)d_model; (void)eps;
965 abort();
966#else
967 for (int t = 0; t < tokens; ++t) {
968 const float *x = input + (size_t)t * (size_t)d_model;
969 float *y = output + (size_t)t * (size_t)d_model;
970 float mean;
971 float variance;
972 layernorm_pytorch_bf16_rowwise_moments_avx2(x, d_model, &mean, &variance);
973 const float rstd = 1.0f / sqrtf(variance + eps);
974 const float bias = -rstd * mean;
975 int i = 0;
976 for (; i + 7 < d_model; i += 8) {
977 const __m256 x_vec = _mm256_loadu_ps(x + i);
978 const __m256 gamma_vec = gamma ? _mm256_loadu_ps(gamma + i) : _mm256_set1_ps(1.0f);
979 const __m256 beta_vec = beta ? _mm256_loadu_ps(beta + i) : _mm256_setzero_ps();
980 const __m256 normalized = _mm256_fmadd_ps(
981 x_vec, _mm256_set1_ps(rstd), _mm256_set1_ps(bias));
982 const __m256 transformed = _mm256_fmadd_ps(normalized, gamma_vec, beta_vec);
983 float lanes[8];
984 _mm256_storeu_ps(lanes, transformed);
985 for (int lane = 0; lane < 8; ++lane) {
986 y[i + lane] = bf16_to_float(float_to_bf16(lanes[lane]));
987 }
988 }
989 for (; i < d_model; ++i) {
990 const float gamma_v = gamma ? gamma[i] : 1.0f;
991 const float beta_v = beta ? beta[i] : 0.0f;
992 const float value = fmaf(fmaf(x[i], rstd, bias), gamma_v, beta_v);
993 y[i] = bf16_to_float(float_to_bf16(value));
994 }
995 if (mean_cache) {
996 mean_cache[t] = mean;
997 }
998 if (rstd_cache) {
999 rstd_cache[t] = rstd;
1000 }
1001 }
1002#endif
1003}

References bf16_to_float(), and float_to_bf16().

◆ mamba2_conv1d_decode_f32()

void mamba2_conv1d_decode_f32 ( const float *  state_in,
const float *  x,
const float *  weight,
const float *  bias,
float *  conv_out,
float *  state_out,
int  rows,
int  conv_dim,
int  kernel_size 
)

Definition at line 148 of file mamba2_kernels.c.

156 {
157 if (!state_in || !x || !weight || !conv_out || !state_out ||
158 rows <= 0 || conv_dim <= 0 || kernel_size <= 0) {
159 return;
160 }
161
162 ck_mamba_debug_finite("conv.state_in", state_in, (size_t)conv_dim * (size_t)kernel_size);
163 ck_mamba_debug_finite("conv.x[0]", x, (size_t)conv_dim);
165 state_in, x, weight, bias, conv_out, state_out,
166 rows, conv_dim, kernel_size, 0, conv_dim);
167 ck_mamba_debug_finite("conv.out[0]", conv_out, (size_t)conv_dim);
168 ck_mamba_debug_finite("conv.state_out", state_out, (size_t)conv_dim * (size_t)kernel_size);
169}
void mamba2_conv1d_f32_channel_range(const float *state_in, const float *x, const float *weight, const float *bias, float *conv_out, float *state_out, int rows, int conv_dim, int kernel_size, int channel_begin, int channel_end)
static void ck_mamba_debug_finite(const char *name, const float *x, size_t n)

References ck_mamba_debug_finite(), and mamba2_conv1d_f32_channel_range().

◆ mamba2_conv1d_f32_channel_range()

void mamba2_conv1d_f32_channel_range ( const float *  state_in,
const float *  x,
const float *  weight,
const float *  bias,
float *  conv_out,
float *  state_out,
int  rows,
int  conv_dim,
int  kernel_size,
int  channel_begin,
int  channel_end 
)

Definition at line 102 of file mamba2_kernels.c.

112 {
113 if (!state_in || !x || !weight || !conv_out || !state_out ||
114 rows <= 0 || conv_dim <= 0 || kernel_size <= 0 ||
115 channel_begin < 0 || channel_begin >= channel_end ||
116 channel_end > conv_dim) {
117 return;
118 }
119
120 /* Time rows are dependent, but channels are independent. Keeping one
121 * channel's rolling state local preserves its exact update order while
122 * allowing disjoint channel ranges to execute concurrently.
123 */
124 for (int ch = channel_begin; ch < channel_end; ++ch) {
125 float state_work[(size_t)kernel_size];
126 const size_t base = (size_t)ch * (size_t)kernel_size;
127 memcpy(state_work, state_in + base,
128 (size_t)kernel_size * sizeof(float));
129 for (int row = 0; row < rows; ++row) {
130 for (int k = 0; k < kernel_size - 1; ++k) {
131 state_work[(size_t)k] = state_work[(size_t)k + 1u];
132 }
133 state_work[(size_t)kernel_size - 1u] =
134 x[(size_t)row * (size_t)conv_dim + (size_t)ch];
135
136 float acc = bias ? bias[ch] : 0.0f;
137 for (int k = 0; k < kernel_size; ++k) {
138 acc += state_work[(size_t)k] *
139 weight[(size_t)ch * (size_t)kernel_size + (size_t)k];
140 }
141 conv_out[(size_t)row * (size_t)conv_dim + (size_t)ch] = mamba2_silu_f32(acc);
142 }
143 memcpy(state_out + base, state_work,
144 (size_t)kernel_size * sizeof(float));
145 }
146}
static float mamba2_silu_f32(float x)

References mamba2_silu_f32().

Referenced by mamba2_conv1d_decode_f32().

◆ mamba2_conv1d_f32_parallel_dispatch()

void mamba2_conv1d_f32_parallel_dispatch ( const float *  state_in,
const float *  x,
const float *  weight,
const float *  bias,
float *  conv_out,
float *  state_out,
int  rows,
int  conv_dim,
int  kernel_size 
)

◆ mamba2_dt_softplus_f32()

void mamba2_dt_softplus_f32 ( const float *  dt,
const float *  dt_bias,
float *  dt_out,
int  rows,
int  num_heads,
float  dt_min,
float  dt_max 
)

Definition at line 171 of file mamba2_kernels.c.

177 {
178 if (!dt || !dt_out || rows <= 0 || num_heads <= 0) {
179 return;
180 }
181
182 ck_mamba_debug_finite("dt.in[0]", dt, (size_t)num_heads);
183 ck_mamba_debug_finite("dt.bias", dt_bias, (size_t)num_heads);
184 for (int row = 0; row < rows; ++row) {
185 for (int h = 0; h < num_heads; ++h) {
186 float v = dt[(size_t)row * (size_t)num_heads + (size_t)h];
187 if (dt_bias) {
188 v += dt_bias[h];
189 }
190 v = mamba2_softplus_f32(v);
191 if (dt_min < dt_max) {
192 if (v < dt_min) {
193 v = dt_min;
194 } else if (v > dt_max) {
195 v = dt_max;
196 }
197 }
198 dt_out[(size_t)row * (size_t)num_heads + (size_t)h] = v;
199 }
200 }
201 ck_mamba_debug_finite("dt.out[0]", dt_out, (size_t)num_heads);
202}
static float mamba2_softplus_f32(float x)

References ck_mamba_debug_finite(), and mamba2_softplus_f32().

◆ mamba2_in_proj_split_f32()

void mamba2_in_proj_split_f32 ( const float *  projected,
float *  gate,
float *  hidden_bc,
float *  dt,
int  rows,
int  d_mlp,
int  intermediate_dim,
int  conv_dim,
int  num_heads 
)

Definition at line 65 of file mamba2_kernels.c.

73 {
74 if (!projected || !gate || !hidden_bc || !dt ||
75 rows <= 0 || d_mlp < 0 || intermediate_dim <= 0 || conv_dim <= 0 || num_heads <= 0) {
76 return;
77 }
78
79 const int projection_dim = 2 * d_mlp + intermediate_dim + conv_dim + num_heads;
80 const int gate_offset = 2 * d_mlp;
81 const int hidden_bc_offset = gate_offset + intermediate_dim;
82 const int dt_offset = hidden_bc_offset + conv_dim;
83
84 ck_mamba_debug_finite("split.projected[0]", projected, (size_t)projection_dim);
85 for (int row = 0; row < rows; ++row) {
86 const float *src = projected + (size_t)row * (size_t)projection_dim;
87 memcpy(gate + (size_t)row * (size_t)intermediate_dim,
88 src + gate_offset,
89 (size_t)intermediate_dim * sizeof(float));
90 memcpy(hidden_bc + (size_t)row * (size_t)conv_dim,
91 src + hidden_bc_offset,
92 (size_t)conv_dim * sizeof(float));
93 memcpy(dt + (size_t)row * (size_t)num_heads,
94 src + dt_offset,
95 (size_t)num_heads * sizeof(float));
96 }
97 ck_mamba_debug_finite("split.gate[0]", gate, (size_t)intermediate_dim);
98 ck_mamba_debug_finite("split.hidden_bc[0]", hidden_bc, (size_t)conv_dim);
99 ck_mamba_debug_finite("split.dt[0]", dt, (size_t)num_heads);
100}

References ck_mamba_debug_finite().

◆ mamba2_rmsnorm_gate_f32()

void mamba2_rmsnorm_gate_f32 ( const float *  x,
const float *  gate,
const float *  weight,
float *  out,
int  rows,
int  inner_dim,
int  group_size,
float  eps 
)

Definition at line 373 of file mamba2_kernels.c.

380 {
381 if (!x || !gate || !weight || !out || rows <= 0 || inner_dim <= 0 || group_size <= 0) {
382 return;
383 }
384
385 ck_mamba_debug_finite("rmsgate.x[0]", x, (size_t)inner_dim);
386 ck_mamba_debug_finite("rmsgate.gate[0]", gate, (size_t)inner_dim);
387 ck_mamba_debug_finite("rmsgate.weight", weight, (size_t)inner_dim);
388 for (int row = 0; row < rows; ++row) {
389 const float *x_row = x + (size_t)row * (size_t)inner_dim;
390 const float *gate_row = gate + (size_t)row * (size_t)inner_dim;
391 float *out_row = out + (size_t)row * (size_t)inner_dim;
392
393 for (int start = 0; start < inner_dim; start += group_size) {
394 int end = start + group_size;
395 if (end > inner_dim) {
396 end = inner_dim;
397 }
398 const int count = end - start;
399 float ms = 0.0f;
400 for (int col = start; col < end; ++col) {
401 const float gated = x_row[col] * mamba2_silu_f32(gate_row[col]);
402 ms += gated * gated;
403 }
404 const float inv_rms = 1.0f / sqrtf(ms / (float)count + eps);
405 for (int col = start; col < end; ++col) {
406 const float gated = x_row[col] * mamba2_silu_f32(gate_row[col]);
407 out_row[col] = gated * inv_rms * weight[col];
408 }
409 }
410 }
411 ck_mamba_debug_finite("rmsgate.out[0]", out, (size_t)inner_dim);
412}
uint32_t end
Definition utf8.c:215
uint32_t start
Definition utf8.c:214

References ck_mamba_debug_finite(), count, end, mamba2_silu_f32(), and start.

◆ mamba2_selective_scan_f32()

void mamba2_selective_scan_f32 ( const float *  state_init,
const float *  x,
const float *  dt,
const float *  a,
const float *  b,
const float *  c,
const float *  d,
float *  state_out,
float *  y,
int  batch,
int  seq_len,
int  num_heads,
int  head_dim,
int  state_dim,
int  num_groups 
)

Definition at line 339 of file mamba2_kernels.c.

353 {
354 if (!state_init || !x || !dt || !a || !b || !c || !d || !state_out || !y ||
355 batch <= 0 || seq_len <= 0 || num_heads <= 0 || head_dim <= 0 || state_dim <= 0 || num_groups <= 0) {
356 return;
357 }
358
359 const size_t state_per_batch = (size_t)num_heads * (size_t)head_dim * (size_t)state_dim;
360 ck_mamba_debug_finite("scan.state_init", state_init, state_per_batch);
361 ck_mamba_debug_finite("scan.x[0]", x, (size_t)num_heads * (size_t)head_dim + 2u * (size_t)num_groups * (size_t)state_dim);
362 ck_mamba_debug_finite("scan.dt[0]", dt, (size_t)num_heads);
363 ck_mamba_debug_finite("scan.a", a, (size_t)num_heads);
364 ck_mamba_debug_finite("scan.d", d, (size_t)num_heads);
366 state_init, x, dt, a, b, c, d, state_out, y,
367 batch, seq_len, num_heads, head_dim, state_dim, num_groups,
368 0, num_heads);
369 ck_mamba_debug_finite("scan.state_out", state_out, (size_t)batch * state_per_batch);
370 ck_mamba_debug_finite("scan.y[0]", y, (size_t)num_heads * (size_t)head_dim);
371}
void mamba2_selective_scan_f32_head_range(const float *state_init, const float *x, const float *dt, const float *a, const float *b, const float *c, const float *d, float *state_out, float *y, int batch, int seq_len, int num_heads, int head_dim, int state_dim, int num_groups, int head_begin, int head_end)

References ck_mamba_debug_finite(), and mamba2_selective_scan_f32_head_range().

◆ mamba2_selective_scan_f32_head_range()

void mamba2_selective_scan_f32_head_range ( const float *  state_init,
const float *  x,
const float *  dt,
const float *  a,
const float *  b,
const float *  c,
const float *  d,
float *  state_out,
float *  y,
int  batch,
int  seq_len,
int  num_heads,
int  head_dim,
int  state_dim,
int  num_groups,
int  head_begin,
int  head_end 
)

Definition at line 264 of file mamba2_kernels.c.

280 {
281 if (!state_init || !x || !dt || !a || !b || !c || !d || !state_out || !y ||
282 batch <= 0 || seq_len <= 0 || num_heads <= 0 || head_dim <= 0 ||
283 state_dim <= 0 || num_groups <= 0 || head_begin < 0 ||
284 head_begin >= head_end || head_end > num_heads) {
285 return;
286 }
287
288 const size_t state_per_batch = (size_t)num_heads * (size_t)head_dim * (size_t)state_dim;
289 const size_t head_state = (size_t)head_dim * (size_t)state_dim;
290 const int packed_xbc = (x == b && b == c);
291 const size_t inner_dim = (size_t)num_heads * (size_t)head_dim;
292 const size_t bc_dim = (size_t)num_groups * (size_t)state_dim;
293 const size_t packed_stride = inner_dim + 2u * bc_dim;
294 const int heads_per_group = (num_heads + num_groups - 1) / num_groups;
295
296 for (int bs = 0; bs < batch; ++bs) {
297 float *state_batch = state_out + (size_t)bs * state_per_batch;
298 memcpy(state_batch + (size_t)head_begin * head_state,
299 state_init + (size_t)bs * state_per_batch + (size_t)head_begin * head_state,
300 (size_t)(head_end - head_begin) * head_state * sizeof(float));
301 for (int t = 0; t < seq_len; ++t) {
302 for (int h = head_begin; h < head_end; ++h) {
303 /* Nemotron-H prefill and decode both use the repeating
304 * B/C group map from repeat_interleave semantics. Keeping
305 * this in sync is required for full-prefix and incremental
306 * decode equivalence.
307 */
308 int group = h / heads_per_group;
309 if (group >= num_groups) group = num_groups - 1;
310 const float dt_h = dt[((size_t)bs * (size_t)seq_len + (size_t)t) * (size_t)num_heads + (size_t)h];
311 const float d_a = expf(dt_h * a[h]);
312 const float d_h = d[h];
313 const float *packed_row = x + ((size_t)bs * (size_t)seq_len + (size_t)t) * packed_stride;
314 const float *b_row = packed_xbc
315 ? (packed_row + inner_dim + (size_t)group * (size_t)state_dim)
316 : (b + (((size_t)bs * (size_t)seq_len + (size_t)t) * (size_t)num_groups + (size_t)group) * (size_t)state_dim);
317 const float *c_row = packed_xbc
318 ? (packed_row + inner_dim + bc_dim + (size_t)group * (size_t)state_dim)
319 : (c + (((size_t)bs * (size_t)seq_len + (size_t)t) * (size_t)num_groups + (size_t)group) * (size_t)state_dim);
320
321 for (int hd = 0; hd < head_dim; ++hd) {
322 const size_t x_idx = (((size_t)bs * (size_t)seq_len + (size_t)t) * (size_t)num_heads + (size_t)h) * (size_t)head_dim + (size_t)hd;
323 const float x_val = packed_xbc ? packed_row[(size_t)h * (size_t)head_dim + (size_t)hd] : x[x_idx];
324 const size_t state_base = ((size_t)h * (size_t)head_dim + (size_t)hd) * (size_t)state_dim;
325 float acc = 0.0f;
326 for (int st = 0; st < state_dim; ++st) {
327 const size_t si = state_base + (size_t)st;
328 const float new_state = state_batch[si] * d_a + dt_h * b_row[st] * x_val;
329 state_batch[si] = new_state;
330 acc += new_state * c_row[st];
331 }
332 y[x_idx] = acc + d_h * x_val;
333 }
334 }
335 }
336 }
337}

Referenced by mamba2_selective_scan_f32().

◆ mamba2_selective_scan_f32_parallel_dispatch()

void mamba2_selective_scan_f32_parallel_dispatch ( const float *  state_init,
const float *  x,
const float *  dt,
const float *  a,
const float *  b,
const float *  c,
const float *  d,
float *  state_out,
float *  y,
int  batch,
int  seq_len,
int  num_heads,
int  head_dim,
int  state_dim,
int  num_groups 
)

◆ mamba2_selective_state_update_decode_f32()

void mamba2_selective_state_update_decode_f32 ( const float *  state_in,
const float *  x,
const float *  dt,
const float *  a,
const float *  b,
const float *  c,
const float *  d,
float *  state_out,
float *  y,
int  rows,
int  num_heads,
int  head_dim,
int  state_dim,
int  num_groups 
)

Definition at line 204 of file mamba2_kernels.c.

217 {
218 if (!state_in || !x || !dt || !a || !b || !c || !d || !state_out || !y ||
219 rows <= 0 || num_heads <= 0 || head_dim <= 0 || state_dim <= 0 || num_groups <= 0) {
220 return;
221 }
222
223 const int packed_xbc = (x == b && b == c);
224 const size_t inner_dim = (size_t)num_heads * (size_t)head_dim;
225 const size_t bc_dim = (size_t)num_groups * (size_t)state_dim;
226 const size_t packed_stride = inner_dim + 2u * bc_dim;
227
228 for (int row = 0; row < rows; ++row) {
229 const float *packed_row = packed_xbc ? x + (size_t)row * packed_stride : NULL;
230 for (int h = 0; h < num_heads; ++h) {
231 const int heads_per_group = (num_heads + num_groups - 1) / num_groups;
232 int group = h / heads_per_group;
233 if (group >= num_groups) group = num_groups - 1;
234 const float dt_h = dt[(size_t)row * (size_t)num_heads + (size_t)h];
235 const float d_a = expf(dt_h * a[h]);
236 const float d_h = d[h];
237 const float *b_row = packed_xbc
238 ? (packed_row + inner_dim + (size_t)group * (size_t)state_dim)
239 : (b + ((size_t)row * (size_t)num_groups + (size_t)group) * (size_t)state_dim);
240 const float *c_row = packed_xbc
241 ? (packed_row + inner_dim + bc_dim + (size_t)group * (size_t)state_dim)
242 : (c + ((size_t)row * (size_t)num_groups + (size_t)group) * (size_t)state_dim);
243
244 for (int hd = 0; hd < head_dim; ++hd) {
245 const size_t x_idx = ((size_t)row * (size_t)num_heads + (size_t)h) * (size_t)head_dim + (size_t)hd;
246 const float x_val = packed_xbc ? packed_row[(size_t)h * (size_t)head_dim + (size_t)hd] : x[x_idx];
247 const size_t state_base =
248 (((size_t)row * (size_t)num_heads + (size_t)h) * (size_t)head_dim + (size_t)hd) *
249 (size_t)state_dim;
250 float acc = 0.0f;
251 for (int s = 0; s < state_dim; ++s) {
252 const size_t si = state_base + (size_t)s;
253 const float new_state = state_in[si] * d_a + dt_h * b_row[s] * x_val;
254 state_out[si] = new_state;
255 acc += new_state * c_row[s];
256 }
257 y[x_idx] = acc + d_h * x_val;
258 }
259 }
260 }
261}

◆ mlp_token_parallel()

void mlp_token_parallel ( const float *  input,
const float *  W_fc1,
const float *  b_fc1,
const float *  W_fc2,
const float *  b_fc2,
float *  fc1_output,
float *  output,
int  T,
int  aligned_dim,
int  num_threads 
)

Definition at line 49 of file mlp_kernels.c.

59{
60 int D = aligned_dim;
61 int fourD = 4 * D;
62
63 // FC1: [T × D] · [D × 4D] -> [T × 4D]
64 // Our GEMM layout: A[M×K], B[N×K], so B is [4D × D].
65 gemm_blocked_serial(input, W_fc1, b_fc1,
66 fc1_output,
67 T, // M
68 fourD, // N
69 D); // K
70
71 // GELU in-place on FC1 output
72 gelu_fast_inplace(fc1_output, (size_t)T * (size_t)fourD);
73
74 // FC2: [T × 4D] · [4D × D] -> [T × D]
75 gemm_blocked_serial(fc1_output, W_fc2, b_fc2,
76 output,
77 T, // M
78 D, // N
79 fourD); // K
80}
void gelu_fast_inplace(float *data, size_t n)

References gelu_fast_inplace(), and gemm_blocked_serial().

◆ mlp_token_parallel_bf16()

void mlp_token_parallel_bf16 ( const uint16_t *  input,
const uint16_t *  W_fc1,
const uint16_t *  b_fc1,
const uint16_t *  W_fc2,
const uint16_t *  b_fc2,
float *  fc1_output,
float *  output,
int  T,
int  aligned_dim,
int  num_threads,
float *  scratch_bias1_f,
float *  scratch_bias2_f,
uint16_t *  scratch_fc1_bf16 
)

Optimized MLP Forward (BF16 weights, FP32 activations)

Caller-provided scratch buffers: scratch_bias1_f: [4*D] floats scratch_bias2_f: [D] floats scratch_fc1_bf16: [T * 4*D] uint16_t (BF16)

Definition at line 104 of file mlp_kernels_bf16.c.

117{
118 if (!input || !W_fc1 || !b_fc1 || !W_fc2 || !b_fc2 || !fc1_output || !output) return;
119 if (!scratch_bias1_f || !scratch_bias2_f || !scratch_fc1_bf16) return;
120
121 (void)num_threads;
122 const int D = aligned_dim;
123 const int fourD = 4 * D;
124
125 /* Convert biases to FP32 */
126 for (int i = 0; i < fourD; ++i) {
127 scratch_bias1_f[i] = bf16_to_float(b_fc1[i]);
128 }
129 for (int i = 0; i < D; ++i) {
130 scratch_bias2_f[i] = bf16_to_float(b_fc2[i]);
131 }
132
133 /* FC1: [T, D] x [4D, D].T -> [T, 4D] */
134 gemm_bf16_fp32out(input, W_fc1, scratch_bias1_f, fc1_output, T, fourD, D);
135
136 /* GELU activation */
137#if defined(__AVX512F__)
138 #pragma omp parallel for
139 for (int t = 0; t < T; ++t) {
140 float *row = fc1_output + (size_t)t * fourD;
141 int j = 0;
142 for (; j <= fourD - 16; j += 16) {
143 __m512 x = _mm512_loadu_ps(row + j);
144 _mm512_storeu_ps(row + j, gelu_avx512(x));
145 }
146 for (; j < fourD; ++j) {
147 row[j] = gelu_scalar(row[j]);
148 }
149 }
150#else
151 for (int t = 0; t < T; ++t) {
152 for (int j = 0; j < fourD; ++j) {
153 fc1_output[t * fourD + j] = gelu_scalar(fc1_output[t * fourD + j]);
154 }
155 }
156#endif
157
158 /* Convert FP32 activations to BF16 */
159#if defined(__AVX512F__)
160 #pragma omp parallel for
161 for (int t = 0; t < T; ++t) {
162 float *src = fc1_output + (size_t)t * fourD;
163 uint16_t *dst = scratch_fc1_bf16 + (size_t)t * fourD;
164 int j = 0;
165 for (; j <= fourD - 16; j += 16) {
166 __m512 fp32 = _mm512_loadu_ps(src + j);
167 __m512i as_int = _mm512_castps_si512(fp32);
168 __m512i lsb = _mm512_srli_epi32(as_int, 16);
169 lsb = _mm512_and_si512(lsb, _mm512_set1_epi32(1));
170 __m512i rounding = _mm512_add_epi32(_mm512_set1_epi32(0x7FFF), lsb);
171 __m512i rounded = _mm512_add_epi32(as_int, rounding);
172 __m512i shifted = _mm512_srli_epi32(rounded, 16);
173 __m256i bf16 = _mm512_cvtepi32_epi16(shifted);
174 _mm256_storeu_si256((__m256i *)(dst + j), bf16);
175 }
176 for (; j < fourD; ++j) {
177 dst[j] = float_to_bf16(src[j]);
178 }
179 }
180#else
181 for (size_t i = 0; i < (size_t)T * fourD; ++i) {
182 scratch_fc1_bf16[i] = float_to_bf16(fc1_output[i]);
183 }
184#endif
185
186 /* FC2: BF16 GEMM with FP32 output */
187 gemm_bf16_fp32out(scratch_fc1_bf16, W_fc2, scratch_bias2_f, output, T, D, fourD);
188}
static float gelu_scalar(float x)
void gemm_bf16_fp32out(const uint16_t *A, const uint16_t *B, const float *bias, float *C, int M, int N, int K)

References bf16_to_float(), float_to_bf16(), gelu_scalar(), and gemm_bf16_fp32out().

◆ mlp_token_parallel_bf16_backward_mixed()

void mlp_token_parallel_bf16_backward_mixed ( const uint16_t *  input,
const uint16_t *  W_fc1,
const uint16_t *  b_fc1,
const uint16_t *  W_fc2,
const uint16_t *  d_output,
float *  d_input,
float *  d_W_fc1,
float *  d_b_fc1,
float *  d_W_fc2,
float *  d_b_fc2,
int  T,
int  aligned_dim,
int  num_threads,
float *  scratch_fc1_pre,
uint16_t *  scratch_fc1_act_bf16,
float *  scratch_d_fc1 
)

BF16 MLP backward with FP32 gradient accumulation.

Forward contract matched here: z1 = input_bf16 @ W_fc1_bf16.T + b_fc1_bf16 h = GELU(z1) hq = round_to_bf16(h) y = hq @ W_fc2_bf16.T + b_fc2_bf16

Gradients are accumulated and written as FP32. The BF16 activation cast is treated like PyTorch's mixed-precision cast: gradient flows through to h, while d_W_fc2 uses the rounded hq values that FC2 actually consumed.

Definition at line 268 of file mlp_kernels_bf16.c.

284{
285 if (!input || !W_fc1 || !b_fc1 || !W_fc2 || !d_output) return;
286 if (!scratch_fc1_pre || !scratch_fc1_act_bf16 || !scratch_d_fc1) return;
287 if (T <= 0 || aligned_dim <= 0) return;
288
289 (void)num_threads;
290 const int D = aligned_dim;
291 const int fourD = 4 * D;
292
293 /* Recompute FC1 pre-activation and the rounded activation consumed by FC2. */
294 for (int t = 0; t < T; ++t) {
295 for (int j = 0; j < fourD; ++j) {
296 float sum = bf16_to_float(b_fc1[j]);
297 for (int i = 0; i < D; ++i) {
298 const float x = bf16_to_float(input[(size_t)t * (size_t)D + (size_t)i]);
299 const float w = bf16_to_float(W_fc1[(size_t)j * (size_t)D + (size_t)i]);
300 sum += x * w;
301 }
302 scratch_fc1_pre[(size_t)t * (size_t)fourD + (size_t)j] = sum;
303 scratch_fc1_act_bf16[(size_t)t * (size_t)fourD + (size_t)j] = float_to_bf16(gelu_scalar(sum));
304 }
305 }
306
307 if (d_input) {
308 for (int t = 0; t < T; ++t) {
309 for (int i = 0; i < D; ++i) {
310 d_input[(size_t)t * (size_t)D + (size_t)i] = 0.0f;
311 }
312 }
313 }
314 if (d_W_fc1) {
315 for (size_t i = 0; i < (size_t)fourD * (size_t)D; ++i) d_W_fc1[i] = 0.0f;
316 }
317 if (d_b_fc1) {
318 for (int j = 0; j < fourD; ++j) d_b_fc1[j] = 0.0f;
319 }
320 if (d_W_fc2) {
321 for (size_t i = 0; i < (size_t)D * (size_t)fourD; ++i) d_W_fc2[i] = 0.0f;
322 }
323 if (d_b_fc2) {
324 for (int o = 0; o < D; ++o) d_b_fc2[o] = 0.0f;
325 }
326
327 /* d_W_fc2, d_b_fc2, and d_h = d_output @ W_fc2. */
328 for (int t = 0; t < T; ++t) {
329 for (int j = 0; j < fourD; ++j) {
330 float dh = 0.0f;
331 const float hq = bf16_to_float(scratch_fc1_act_bf16[(size_t)t * (size_t)fourD + (size_t)j]);
332 for (int o = 0; o < D; ++o) {
333 const float dy = bf16_to_float(d_output[(size_t)t * (size_t)D + (size_t)o]);
334 const float w2 = bf16_to_float(W_fc2[(size_t)o * (size_t)fourD + (size_t)j]);
335 dh += dy * w2;
336 if (d_W_fc2) {
337 d_W_fc2[(size_t)o * (size_t)fourD + (size_t)j] += dy * hq;
338 }
339 }
340 const float z = scratch_fc1_pre[(size_t)t * (size_t)fourD + (size_t)j];
341 scratch_d_fc1[(size_t)t * (size_t)fourD + (size_t)j] = dh * gelu_derivative_scalar(z);
342 }
343 if (d_b_fc2) {
344 for (int o = 0; o < D; ++o) {
345 d_b_fc2[o] += bf16_to_float(d_output[(size_t)t * (size_t)D + (size_t)o]);
346 }
347 }
348 }
349
350 /* Backprop through FC1. */
351 for (int t = 0; t < T; ++t) {
352 for (int j = 0; j < fourD; ++j) {
353 const float dz = scratch_d_fc1[(size_t)t * (size_t)fourD + (size_t)j];
354 if (d_b_fc1) d_b_fc1[j] += dz;
355 for (int i = 0; i < D; ++i) {
356 const float x = bf16_to_float(input[(size_t)t * (size_t)D + (size_t)i]);
357 const float w1 = bf16_to_float(W_fc1[(size_t)j * (size_t)D + (size_t)i]);
358 if (d_W_fc1) d_W_fc1[(size_t)j * (size_t)D + (size_t)i] += dz * x;
359 if (d_input) d_input[(size_t)t * (size_t)D + (size_t)i] += dz * w1;
360 }
361 }
362 }
363}
static float gelu_derivative_scalar(float x)

References bf16_to_float(), float_to_bf16(), gelu_derivative_scalar(), and gelu_scalar().

◆ mlp_token_parallel_bf16_fp32act()

void mlp_token_parallel_bf16_fp32act ( const uint16_t *  input,
const uint16_t *  W_fc1,
const uint16_t *  b_fc1,
const uint16_t *  W_fc2,
const uint16_t *  b_fc2,
float *  fc1_output,
float *  output,
int  T,
int  aligned_dim,
int  num_threads,
float *  scratch_input_f,
float *  scratch_bias1_f,
float *  scratch_bias2_f,
uint16_t *  scratch_fc1_bf16 
)

Alternative: Fully FP32 activations throughout

Caller-provided scratch buffers: scratch_input_f: [T * D] floats scratch_bias1_f: [4*D] floats scratch_bias2_f: [D] floats scratch_fc1_bf16: [T * 4*D] uint16_t (BF16)

Definition at line 199 of file mlp_kernels_bf16.c.

213{
214 if (!input || !W_fc1 || !b_fc1 || !W_fc2 || !b_fc2 || !fc1_output || !output) return;
215 if (!scratch_input_f || !scratch_bias1_f || !scratch_bias2_f || !scratch_fc1_bf16) return;
216
217 (void)num_threads;
218 const int D = aligned_dim;
219 const int fourD = 4 * D;
220
221 /* Convert input and biases to FP32 */
222 bf16_tensor_to_float(input, scratch_input_f, (size_t)T * D);
223 bf16_tensor_to_float(b_fc1, scratch_bias1_f, fourD);
224 bf16_tensor_to_float(b_fc2, scratch_bias2_f, D);
225
226 /* FC1 */
227 gemm_bf16_fp32out(input, W_fc1, scratch_bias1_f, fc1_output, T, fourD, D);
228
229 /* GELU */
230#if defined(__AVX512F__)
231 #pragma omp parallel for
232 for (int t = 0; t < T; ++t) {
233 float *row = fc1_output + (size_t)t * fourD;
234 int j = 0;
235 for (; j <= fourD - 16; j += 16) {
236 __m512 x = _mm512_loadu_ps(row + j);
237 _mm512_storeu_ps(row + j, gelu_avx512(x));
238 }
239 for (; j < fourD; ++j) {
240 row[j] = gelu_scalar(row[j]);
241 }
242 }
243#else
244 for (size_t i = 0; i < (size_t)T * fourD; ++i) {
245 fc1_output[i] = gelu_scalar(fc1_output[i]);
246 }
247#endif
248
249 /* Convert fc1_output to BF16 for FC2 */
250 float_tensor_to_bf16(fc1_output, scratch_fc1_bf16, (size_t)T * fourD);
251 gemm_bf16_fp32out(scratch_fc1_bf16, W_fc2, scratch_bias2_f, output, T, D, fourD);
252}

References bf16_tensor_to_float(), float_tensor_to_bf16(), gelu_scalar(), and gemm_bf16_fp32out().

◆ mlp_token_parallel_exact()

void mlp_token_parallel_exact ( const float *  input,
const float *  W_fc1,
const float *  b_fc1,
const float *  W_fc2,
const float *  b_fc2,
float *  fc1_output,
float *  output,
int  T,
int  aligned_dim,
int  num_threads 
)

Definition at line 84 of file mlp_kernels.c.

94{
95 (void)num_threads;
96 int D = aligned_dim;
97 int fourD = 4 * D;
98
99 // FC1: [T × D] · [D × 4D] -> [T × 4D]
100 gemm_blocked_serial(input, W_fc1, b_fc1,
101 fc1_output,
102 T, // M
103 fourD, // N
104 D); // K
105
106 // Exact GELU using standard library tanhf
107 gelu_exact_inplace(fc1_output, (size_t)T * (size_t)fourD);
108
109 // FC2: [T × 4D] · [4D × D] -> [T × D]
110 gemm_blocked_serial(fc1_output, W_fc2, b_fc2,
111 output,
112 T, // M
113 D, // N
114 fourD); // K
115}

References gelu_exact_inplace(), and gemm_blocked_serial().

◆ moe_accumulate_expert_f32()

void moe_accumulate_expert_f32 ( float *  output,
const float *  expert_output,
float  routing_weight,
int  hidden_dim 
)

Accumulate expert output: output += routing_weight * expert_output.

Parameters
outputToken output buffer [hidden_dim], accumulated in place
expert_outputExpert's output for this token [hidden_dim]
routing_weightSoftmax routing weight for this expert
hidden_dimHidden dimension

Definition at line 307 of file axpy_kernels.c.

311{
312 axpy_f32(output, expert_output, routing_weight, hidden_dim);
313}

References axpy_f32().

◆ moe_relu2_expert_backward_f32()

void moe_relu2_expert_backward_f32 ( const float *  d_output,
const float *  hidden,
const int *  indices,
const float *  routing_weights,
const float *  expert_up,
const float *  expert_down,
float *  d_hidden,
float *  d_routing_weights,
float *  d_expert_up,
float *  d_expert_down,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

Definition at line 3730 of file axpy_kernels.c.

3745{
3746 if (!d_output || !hidden || !indices || !routing_weights || !expert_up || !expert_down ||
3747 !d_hidden || !d_routing_weights || !d_expert_up || !d_expert_down ||
3748 rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0 || n_experts <= 0 || top_k <= 0) {
3749 return;
3750 }
3751
3752 for (size_t p = 0; p < (size_t)rows * (size_t)hidden_dim; ++p) d_hidden[p] = 0.0f;
3753 for (size_t p = 0; p < (size_t)rows * (size_t)top_k; ++p) d_routing_weights[p] = 0.0f;
3754 for (size_t p = 0; p < (size_t)n_experts * (size_t)intermediate_dim * (size_t)hidden_dim; ++p) d_expert_up[p] = 0.0f;
3755 for (size_t p = 0; p < (size_t)n_experts * (size_t)hidden_dim * (size_t)intermediate_dim; ++p) d_expert_down[p] = 0.0f;
3756
3757 float pre[intermediate_dim];
3758 float act[intermediate_dim];
3759 float d_act[intermediate_dim];
3760 float d_pre[intermediate_dim];
3761 float expert_out[hidden_dim];
3762
3763 for (int r = 0; r < rows; ++r) {
3764 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
3765 const float *dy = d_output + (size_t)r * (size_t)hidden_dim;
3766 float *dx = d_hidden + (size_t)r * (size_t)hidden_dim;
3767
3768 for (int slot = 0; slot < top_k; ++slot) {
3769 const int e = indices[(size_t)r * (size_t)top_k + (size_t)slot];
3770 if (e < 0 || e >= n_experts) continue;
3771 const float route_w = routing_weights[(size_t)r * (size_t)top_k + (size_t)slot];
3772
3773 for (int i = 0; i < intermediate_dim; ++i) {
3774 float v = 0.0f;
3775 for (int h = 0; h < hidden_dim; ++h) {
3776 v += expert_up[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)] * x[h];
3777 }
3778 pre[i] = v;
3779 act[i] = (v > 0.0f) ? v * v : 0.0f;
3780 d_act[i] = 0.0f;
3781 }
3782
3783 for (int h = 0; h < hidden_dim; ++h) {
3784 float v = 0.0f;
3785 for (int i = 0; i < intermediate_dim; ++i) {
3786 v += expert_down[ck_moe_down_idx(e, h, i, hidden_dim, intermediate_dim)] * act[i];
3787 }
3788 expert_out[h] = v;
3789 }
3790
3791 float d_route = 0.0f;
3792 for (int h = 0; h < hidden_dim; ++h) {
3793 const float d_expert_out = dy[h] * route_w;
3794 d_route += dy[h] * expert_out[h];
3795 for (int i = 0; i < intermediate_dim; ++i) {
3796 d_expert_down[ck_moe_down_idx(e, h, i, hidden_dim, intermediate_dim)] += d_expert_out * act[i];
3797 d_act[i] += d_expert_out * expert_down[ck_moe_down_idx(e, h, i, hidden_dim, intermediate_dim)];
3798 }
3799 }
3800 d_routing_weights[(size_t)r * (size_t)top_k + (size_t)slot] += d_route;
3801
3802 for (int i = 0; i < intermediate_dim; ++i) {
3803 d_pre[i] = (pre[i] > 0.0f) ? d_act[i] * 2.0f * pre[i] : 0.0f;
3804 }
3805
3806 for (int i = 0; i < intermediate_dim; ++i) {
3807 const float dpi = d_pre[i];
3808 for (int h = 0; h < hidden_dim; ++h) {
3809 d_expert_up[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)] += dpi * x[h];
3810 dx[h] += dpi * expert_up[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)];
3811 }
3812 }
3813 }
3814 }
3815}
static size_t ck_moe_up_idx(int e, int i, int h, int intermediate_dim, int hidden_dim)
static size_t ck_moe_down_idx(int e, int h, int i, int hidden_dim, int intermediate_dim)

References ck_moe_down_idx(), and ck_moe_up_idx().

◆ moe_relu2_expert_forward_f32()

void moe_relu2_expert_forward_f32 ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const float *  expert_up,
const float *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

Definition at line 374 of file axpy_kernels.c.

385{
386 if (!hidden || !indices || !routing_weights || !expert_up || !expert_down || !output ||
387 rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0 || n_experts <= 0 || top_k <= 0) {
388 return;
389 }
390
391 const size_t out_count = (size_t)rows * (size_t)hidden_dim;
392 for (size_t p = 0; p < out_count; ++p) output[p] = 0.0f;
393
394 float pre[intermediate_dim];
395 float gate[intermediate_dim];
396 float up[intermediate_dim];
397 float act[intermediate_dim];
398
399 for (int r = 0; r < rows; ++r) {
400 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
401 float *y = output + (size_t)r * (size_t)hidden_dim;
402 for (int slot = 0; slot < top_k; ++slot) {
403 const int e = indices[(size_t)r * (size_t)top_k + (size_t)slot];
404 if (e < 0 || e >= n_experts) continue;
405 const float route_w = routing_weights[(size_t)r * (size_t)top_k + (size_t)slot];
406
407 for (int i = 0; i < intermediate_dim; ++i) {
408 float v = 0.0f;
409 for (int h = 0; h < hidden_dim; ++h) {
410 v += expert_up[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)] * x[h];
411 }
412 pre[i] = v;
413 act[i] = (v > 0.0f) ? v * v : 0.0f;
414 }
415
416 for (int h = 0; h < hidden_dim; ++h) {
417 float v = 0.0f;
418 for (int i = 0; i < intermediate_dim; ++i) {
419 v += expert_down[ck_moe_down_idx(e, h, i, hidden_dim, intermediate_dim)] * act[i];
420 }
421 y[h] += route_w * v;
422 }
423 }
424 }
425}

References ck_moe_down_idx(), and ck_moe_up_idx().

◆ moe_relu2_expert_forward_q5_0_q5_0()

void moe_relu2_expert_forward_q5_0_q5_0 ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

Definition at line 3581 of file axpy_kernels.c.

3592{
3593 if (!hidden || !indices || !routing_weights || !expert_up || !expert_down || !output ||
3594 rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0 || n_experts <= 0 || top_k <= 0) {
3595 return;
3596 }
3597
3598 const size_t out_count = (size_t)rows * (size_t)hidden_dim;
3599 for (size_t p = 0; p < out_count; ++p) output[p] = 0.0f;
3600
3601 const size_t up_row_bytes = ck_dtype_row_bytes(CK_DT_Q5_0, (size_t)hidden_dim);
3602 const size_t down_row_bytes = ck_dtype_row_bytes(CK_DT_Q5_0, (size_t)intermediate_dim);
3603 const uint8_t *up_base = (const uint8_t *)expert_up;
3604 const uint8_t *down_base = (const uint8_t *)expert_down;
3605
3606 float up_row[hidden_dim];
3607 float down_row[intermediate_dim];
3608 float act[intermediate_dim];
3609
3610 for (int r = 0; r < rows; ++r) {
3611 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
3612 float *y = output + (size_t)r * (size_t)hidden_dim;
3613 if (ck_moe_debug_enabled() && r == 0) {
3614 fprintf(stderr,
3615 "[CK_DEBUG_MOE] routed_q5q5 rows=%d hidden=%d intermediate=%d experts=%d top_k=%d up_row_bytes=%zu down_row_bytes=%zu\n",
3616 rows,
3617 hidden_dim,
3618 intermediate_dim,
3619 n_experts,
3620 top_k,
3621 up_row_bytes,
3622 down_row_bytes);
3623 fprintf(stderr, "[CK_DEBUG_MOE] routed slots:");
3624 for (int dbg_slot = 0; dbg_slot < top_k; ++dbg_slot) {
3625 fprintf(stderr,
3626 " (%d,%g)",
3627 indices[(size_t)r * (size_t)top_k + (size_t)dbg_slot],
3628 routing_weights[(size_t)r * (size_t)top_k + (size_t)dbg_slot]);
3629 }
3630 fprintf(stderr, "\n");
3631 ck_moe_debug_finite("routed.hidden[0]", x, (size_t)hidden_dim);
3632 ck_moe_debug_finite("routed.hidden_all", hidden, (size_t)rows * (size_t)hidden_dim);
3633 }
3634 for (int slot = 0; slot < top_k; ++slot) {
3635 const int e = indices[(size_t)r * (size_t)top_k + (size_t)slot];
3636 if (e < 0 || e >= n_experts) continue;
3637 const float route_w = routing_weights[(size_t)r * (size_t)top_k + (size_t)slot];
3638 const uint8_t *expert_up_base = up_base + (size_t)e * (size_t)intermediate_dim * up_row_bytes;
3639 const uint8_t *expert_down_base = down_base + (size_t)e * (size_t)hidden_dim * down_row_bytes;
3640
3641 for (int i = 0; i < intermediate_dim; ++i) {
3642 dequant_q5_0_row(expert_up_base + (size_t)i * up_row_bytes, up_row, (size_t)hidden_dim);
3643 float v = 0.0f;
3644 for (int h = 0; h < hidden_dim; ++h) v += up_row[h] * x[h];
3645 act[i] = (v > 0.0f) ? v * v : 0.0f;
3646 }
3647
3648 for (int h = 0; h < hidden_dim; ++h) {
3649 dequant_q5_0_row(expert_down_base + (size_t)h * down_row_bytes, down_row, (size_t)intermediate_dim);
3650 float v = 0.0f;
3651 for (int i = 0; i < intermediate_dim; ++i) v += down_row[i] * act[i];
3652 y[h] += route_w * v;
3653 }
3654 }
3655 if (ck_moe_debug_enabled() && r == 0) {
3656 ck_moe_debug_finite("routed.output[0]", y, (size_t)hidden_dim);
3657 ck_moe_debug_finite("routed.output_all", output, (size_t)rows * (size_t)hidden_dim);
3658 }
3659 }
3660}
static int ck_moe_debug_enabled(void)
static void ck_moe_debug_finite(const char *name, const float *x, size_t n)

References CK_DT_Q5_0, ck_dtype_row_bytes(), ck_moe_debug_enabled(), ck_moe_debug_finite(), and dequant_q5_0_row().

◆ moe_relu2_expert_forward_q5_0_q8_0()

void moe_relu2_expert_forward_q5_0_q8_0 ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

Definition at line 3499 of file axpy_kernels.c.

3510{
3511 if (!hidden || !indices || !routing_weights || !expert_up || !expert_down || !output ||
3512 rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0 || n_experts <= 0 || top_k <= 0) {
3513 return;
3514 }
3515
3516 const size_t out_count = (size_t)rows * (size_t)hidden_dim;
3517 for (size_t p = 0; p < out_count; ++p) output[p] = 0.0f;
3518
3519 const size_t up_row_bytes = ck_dtype_row_bytes(CK_DT_Q5_0, (size_t)hidden_dim);
3520 const size_t down_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim);
3521 const uint8_t *up_base = (const uint8_t *)expert_up;
3522 const uint8_t *down_base = (const uint8_t *)expert_down;
3523
3524 float up_row[hidden_dim];
3525 float down_row[intermediate_dim];
3526 float act[intermediate_dim];
3527
3528 for (int r = 0; r < rows; ++r) {
3529 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
3530 float *y = output + (size_t)r * (size_t)hidden_dim;
3531 if (ck_moe_debug_enabled() && r == 0) {
3532 fprintf(stderr,
3533 "[CK_DEBUG_MOE] routed_q5q8 rows=%d hidden=%d intermediate=%d experts=%d top_k=%d up_row_bytes=%zu down_row_bytes=%zu\n",
3534 rows,
3535 hidden_dim,
3536 intermediate_dim,
3537 n_experts,
3538 top_k,
3539 up_row_bytes,
3540 down_row_bytes);
3541 fprintf(stderr, "[CK_DEBUG_MOE] routed slots:");
3542 for (int dbg_slot = 0; dbg_slot < top_k; ++dbg_slot) {
3543 fprintf(stderr,
3544 " (%d,%g)",
3545 indices[(size_t)r * (size_t)top_k + (size_t)dbg_slot],
3546 routing_weights[(size_t)r * (size_t)top_k + (size_t)dbg_slot]);
3547 }
3548 fprintf(stderr, "\n");
3549 ck_moe_debug_finite("routed.hidden[0]", x, (size_t)hidden_dim);
3550 ck_moe_debug_finite("routed.hidden_all", hidden, (size_t)rows * (size_t)hidden_dim);
3551 }
3552 for (int slot = 0; slot < top_k; ++slot) {
3553 const int e = indices[(size_t)r * (size_t)top_k + (size_t)slot];
3554 if (e < 0 || e >= n_experts) continue;
3555 const float route_w = routing_weights[(size_t)r * (size_t)top_k + (size_t)slot];
3556 const uint8_t *expert_up_base = up_base + (size_t)e * (size_t)intermediate_dim * up_row_bytes;
3557 const uint8_t *expert_down_base = down_base + (size_t)e * (size_t)hidden_dim * down_row_bytes;
3558
3559 for (int i = 0; i < intermediate_dim; ++i) {
3560 dequant_q5_0_row(expert_up_base + (size_t)i * up_row_bytes, up_row, (size_t)hidden_dim);
3561 float v = 0.0f;
3562 for (int h = 0; h < hidden_dim; ++h) v += up_row[h] * x[h];
3563 act[i] = (v > 0.0f) ? v * v : 0.0f;
3564 }
3565
3566 for (int h = 0; h < hidden_dim; ++h) {
3567 dequant_q8_0_row(expert_down_base + (size_t)h * down_row_bytes, down_row, (size_t)intermediate_dim);
3568 float v = 0.0f;
3569 for (int i = 0; i < intermediate_dim; ++i) v += down_row[i] * act[i];
3570 y[h] += route_w * v;
3571 }
3572 }
3573 if (ck_moe_debug_enabled() && r == 0) {
3574 ck_moe_debug_finite("routed.output[0]", y, (size_t)hidden_dim);
3575 ck_moe_debug_finite("routed.output_all", output, (size_t)rows * (size_t)hidden_dim);
3576 }
3577 }
3578}

References CK_DT_Q5_0, CK_DT_Q8_0, ck_dtype_row_bytes(), ck_moe_debug_enabled(), ck_moe_debug_finite(), dequant_q5_0_row(), and dequant_q8_0_row().

◆ moe_relu2_shared_forward_q5_1_q8_0()

void moe_relu2_shared_forward_q5_1_q8_0 ( const float *  hidden,
const float *  routed,
const void *  shared_up,
const void *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

Definition at line 3662 of file axpy_kernels.c.

3670{
3671 if (!hidden || !shared_up || !shared_down || !output || rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0) {
3672 return;
3673 }
3674
3675 const size_t up_row_bytes = ck_dtype_row_bytes(CK_DT_Q5_1, (size_t)hidden_dim);
3676 const size_t down_row_bytes = ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim);
3677 const uint8_t *up_base = (const uint8_t *)shared_up;
3678 const uint8_t *down_base = (const uint8_t *)shared_down;
3679
3680 float up_row[hidden_dim];
3681 float down_row[intermediate_dim];
3682 float act[intermediate_dim];
3683
3684 for (int r = 0; r < rows; ++r) {
3685 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
3686 const float *route = routed ? (routed + (size_t)r * (size_t)hidden_dim) : NULL;
3687 float *y = output + (size_t)r * (size_t)hidden_dim;
3688 float x_alias[hidden_dim];
3689 if (output == hidden) {
3690 memcpy(x_alias, x, (size_t)hidden_dim * sizeof(float));
3691 x = x_alias;
3692 }
3693
3694 if (ck_moe_debug_enabled() && r == 0) {
3695 fprintf(stderr,
3696 "[CK_DEBUG_MOE] shared_q5q8 rows=%d hidden=%d intermediate=%d up_row_bytes=%zu down_row_bytes=%zu alias=%d\n",
3697 rows,
3698 hidden_dim,
3699 intermediate_dim,
3700 up_row_bytes,
3701 down_row_bytes,
3702 output == hidden);
3703 ck_moe_debug_finite("shared.hidden[0]", x, (size_t)hidden_dim);
3704 ck_moe_debug_finite("shared.hidden_all", hidden, (size_t)rows * (size_t)hidden_dim);
3705 ck_moe_debug_finite("shared.routed[0]", route, (size_t)hidden_dim);
3706 if (routed) ck_moe_debug_finite("shared.routed_all", routed, (size_t)rows * (size_t)hidden_dim);
3707 }
3708
3709 for (int i = 0; i < intermediate_dim; ++i) {
3710 dequant_q5_1_row(up_base + (size_t)i * up_row_bytes, up_row, (size_t)hidden_dim);
3711 float v = 0.0f;
3712 for (int h = 0; h < hidden_dim; ++h) v += up_row[h] * x[h];
3713 act[i] = (v > 0.0f) ? v * v : 0.0f;
3714 }
3715
3716 for (int h = 0; h < hidden_dim; ++h) {
3717 dequant_q8_0_row(down_base + (size_t)h * down_row_bytes, down_row, (size_t)intermediate_dim);
3718 float v = route ? route[h] : 0.0f;
3719 for (int i = 0; i < intermediate_dim; ++i) v += down_row[i] * act[i];
3720 y[h] = v;
3721 }
3722
3723 if (ck_moe_debug_enabled() && r == 0) {
3724 ck_moe_debug_finite("shared.output[0]", y, (size_t)hidden_dim);
3725 ck_moe_debug_finite("shared.output_all", output, (size_t)rows * (size_t)hidden_dim);
3726 }
3727 }
3728}
@ CK_DT_Q5_1
void dequant_q5_1_row(const void *src, float *dst, size_t n_elements)
Dequantize Q5_1 row (multiple blocks)

References CK_DT_Q5_1, CK_DT_Q8_0, ck_dtype_row_bytes(), ck_moe_debug_enabled(), ck_moe_debug_finite(), dequant_q5_1_row(), and dequant_q8_0_row().

◆ moe_softmax_topk_router_llama_f32_workspace()

int moe_softmax_topk_router_llama_f32_workspace ( const float *  logits,
int *  indices,
float *  weights,
int  rows,
int  n_experts,
int  top_k,
float  routed_scaling_factor,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 316 of file topk_kernels.c.

326{
327 const size_t required = moe_softmax_topk_router_workspace_bytes(n_experts);
328 if (!logits || !indices || !weights || !workspace || rows <= 0 ||
329 n_experts <= 0 || top_k <= 0 || top_k > n_experts ||
330 !isfinite(routed_scaling_factor) || required == 0 ||
331 workspace_bytes < required) {
332 return -1;
333 }
334
335 float *probabilities = (float *)workspace;
336 for (int row = 0; row < rows; ++row) {
337 const float *row_logits = logits + (size_t)row * (size_t)n_experts;
338 int *row_indices = indices + (size_t)row * (size_t)top_k;
339 float *row_weights = weights + (size_t)row * (size_t)top_k;
340 float max_value = -INFINITY;
341 for (int expert = 0; expert < n_experts; ++expert) {
342 if (!isfinite(row_logits[expert])) {
343 return -2;
344 }
345 if (row_logits[expert] > max_value) {
346 max_value = row_logits[expert];
347 }
348 }
349
350 const double softmax_sum = ck_moe_llama_softmax_row(
351 probabilities, row_logits, n_experts, max_value);
352 const float inverse_softmax_sum = (float)(1.0 / softmax_sum);
353 for (int expert = 0; expert < n_experts; ++expert) {
354 probabilities[expert] *= inverse_softmax_sum;
355 }
356
357 topk_f32(probabilities, n_experts, top_k, row_indices, NULL);
358 double selected_sum_f64 = 0.0;
359 for (int slot = 0; slot < top_k; ++slot) {
360 row_weights[slot] = probabilities[row_indices[slot]];
361 selected_sum_f64 += (double)row_weights[slot];
362 }
363 float selected_sum = (float)selected_sum_f64;
364 if (selected_sum < 6.103515625e-5f) {
365 selected_sum = 6.103515625e-5f;
366 }
367 for (int slot = 0; slot < top_k; ++slot) {
368 row_weights[slot] =
369 (row_weights[slot] / selected_sum) * routed_scaling_factor;
370 }
371 }
372 return 0;
373}
static double ck_moe_llama_softmax_row(float *probabilities, const float *logits, int n_experts, float max_value)
size_t moe_softmax_topk_router_workspace_bytes(int n_experts)
void topk_f32(const float *scores, int n, int k, int *indices, float *values)
Find top-K indices and values from a score vector.

References ck_moe_llama_softmax_row(), moe_softmax_topk_router_workspace_bytes(), and topk_f32().

Referenced by moe_softmax_topk_router_pytorch_bf16_workspace().

◆ moe_softmax_topk_router_pytorch_bf16_workspace()

int moe_softmax_topk_router_pytorch_bf16_workspace ( const float *  logits,
int *  indices,
float *  weights,
int  rows,
int  n_experts,
int  top_k,
float  routed_scaling_factor,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 375 of file topk_kernels.c.

385{
387 logits, indices, weights, rows, n_experts, top_k,
388 routed_scaling_factor, workspace, workspace_bytes);
389 if (status != 0) {
390 return status;
391 }
392 for (size_t index = 0; index < (size_t)rows * (size_t)top_k; ++index) {
393 weights[index] = bf16_to_float(float_to_bf16(weights[index]));
394 }
395 return 0;
396}
int moe_softmax_topk_router_llama_f32_workspace(const float *logits, int *indices, float *weights, int rows, int n_experts, int top_k, float routed_scaling_factor, void *workspace, size_t workspace_bytes)

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

◆ moe_softmax_topk_router_workspace_bytes()

size_t moe_softmax_topk_router_workspace_bytes ( int  n_experts)

Definition at line 177 of file topk_kernels.c.

178{
179 if (n_experts <= 0) {
180 return 0;
181 }
182 return ((size_t)n_experts * sizeof(float) + 63u) & ~(size_t)63u;
183}

Referenced by moe_softmax_topk_router_llama_f32_workspace().

◆ moe_swiglu_expert_forward_bf16()

void moe_swiglu_expert_forward_bf16 ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const uint16_t *  expert_gate,
const uint16_t *  expert_up,
const uint16_t *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

Definition at line 563 of file axpy_kernels.c.

575{
576 if (rows <= 0) return;
578 hidden, indices, routing_weights, expert_gate, expert_up, expert_down,
579 output, rows, hidden_dim, intermediate_dim, n_experts, top_k, 0, rows);
580}
void moe_swiglu_expert_forward_bf16_row_range(const float *hidden, const int *indices, const float *routing_weights, const uint16_t *expert_gate, const uint16_t *expert_up, const uint16_t *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, int row_begin, int row_end)

References moe_swiglu_expert_forward_bf16_row_range().

◆ moe_swiglu_expert_forward_bf16_parallel_dispatch()

void moe_swiglu_expert_forward_bf16_parallel_dispatch ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const uint16_t *  expert_gate,
const uint16_t *  expert_up,
const uint16_t *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

◆ moe_swiglu_expert_forward_bf16_row_range()

void moe_swiglu_expert_forward_bf16_row_range ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const uint16_t *  expert_gate,
const uint16_t *  expert_up,
const uint16_t *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
int  row_begin,
int  row_end 
)

Definition at line 505 of file axpy_kernels.c.

520{
521 if (!hidden || !indices || !routing_weights || !expert_gate || !expert_up || !expert_down || !output ||
522 rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0 || n_experts <= 0 || top_k <= 0 ||
523 row_begin < 0 || row_begin >= row_end || row_end > rows) {
524 return;
525 }
526
527 float gate[intermediate_dim];
528 float up[intermediate_dim];
529 float act[intermediate_dim];
530
531 for (int r = row_begin; r < row_end; ++r) {
532 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
533 float *y = output + (size_t)r * (size_t)hidden_dim;
534 for (int h = 0; h < hidden_dim; ++h) y[h] = 0.0f;
535 for (int slot = 0; slot < top_k; ++slot) {
536 const int e = indices[(size_t)r * (size_t)top_k + (size_t)slot];
537 if (e < 0 || e >= n_experts) continue;
538 const float route_w = routing_weights[(size_t)r * (size_t)top_k + (size_t)slot];
539
540 for (int i = 0; i < intermediate_dim; ++i) {
541 float gv = 0.0f;
542 float uv = 0.0f;
543 for (int h = 0; h < hidden_dim; ++h) {
544 gv += bf16_to_float(expert_gate[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)]) * x[h];
545 uv += bf16_to_float(expert_up[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)]) * x[h];
546 }
547 gate[i] = gv;
548 up[i] = uv;
549 act[i] = ck_moe_silu_f32(gv) * uv;
550 }
551
552 for (int h = 0; h < hidden_dim; ++h) {
553 float v = 0.0f;
554 for (int i = 0; i < intermediate_dim; ++i) {
555 v += bf16_to_float(expert_down[ck_moe_down_idx(e, h, i, hidden_dim, intermediate_dim)]) * act[i];
556 }
557 y[h] += route_w * v;
558 }
559 }
560 }
561}

References bf16_to_float(), ck_moe_down_idx(), ck_moe_silu_f32(), and ck_moe_up_idx().

Referenced by moe_swiglu_expert_forward_bf16().

◆ moe_swiglu_expert_forward_f32()

void moe_swiglu_expert_forward_f32 ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const float *  expert_gate,
const float *  expert_up,
const float *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

Definition at line 450 of file axpy_kernels.c.

462{
463 if (!hidden || !indices || !routing_weights || !expert_gate || !expert_up || !expert_down || !output ||
464 rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0 || n_experts <= 0 || top_k <= 0) {
465 return;
466 }
467
468 for (size_t p = 0; p < (size_t)rows * (size_t)hidden_dim; ++p) output[p] = 0.0f;
469
470 float gate[intermediate_dim];
471 float up[intermediate_dim];
472 float act[intermediate_dim];
473
474 for (int r = 0; r < rows; ++r) {
475 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
476 float *y = output + (size_t)r * (size_t)hidden_dim;
477 for (int slot = 0; slot < top_k; ++slot) {
478 const int e = indices[(size_t)r * (size_t)top_k + (size_t)slot];
479 if (e < 0 || e >= n_experts) continue;
480 const float route_w = routing_weights[(size_t)r * (size_t)top_k + (size_t)slot];
481
482 for (int i = 0; i < intermediate_dim; ++i) {
483 float gv = 0.0f;
484 float uv = 0.0f;
485 for (int h = 0; h < hidden_dim; ++h) {
486 gv += expert_gate[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)] * x[h];
487 uv += expert_up[ck_moe_up_idx(e, i, h, intermediate_dim, hidden_dim)] * x[h];
488 }
489 gate[i] = gv;
490 up[i] = uv;
491 act[i] = ck_moe_silu_f32(gv) * uv;
492 }
493
494 for (int h = 0; h < hidden_dim; ++h) {
495 float v = 0.0f;
496 for (int i = 0; i < intermediate_dim; ++i) {
497 v += expert_down[ck_moe_down_idx(e, h, i, hidden_dim, intermediate_dim)] * act[i];
498 }
499 y[h] += route_w * v;
500 }
501 }
502 }
503}

References ck_moe_down_idx(), ck_moe_silu_f32(), and ck_moe_up_idx().

◆ moe_swiglu_expert_forward_q4k_q4k_parallel_workspace()

int moe_swiglu_expert_forward_q4k_q4k_parallel_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1881 of file axpy_kernels.c.

1896{
1898 hidden, indices, routing_weights, expert_gate, expert_up, expert_down,
1899 output, rows, hidden_dim, intermediate_dim, n_experts, top_k,
1900 workspace, workspace_bytes,
1902}
int moe_swiglu_expert_forward_q4k_q4k_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
static int ck_moe_q4k_mixed_parallel_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes, ck_moe_expert_workspace_fn serial_fn, ck_moe_down_kind_t down_kind)
@ CK_MOE_DOWN_Q4_K

References CK_MOE_DOWN_Q4_K, ck_moe_q4k_mixed_parallel_workspace(), and moe_swiglu_expert_forward_q4k_q4k_workspace().

◆ moe_swiglu_expert_forward_q4k_q4k_workspace()

int moe_swiglu_expert_forward_q4k_q4k_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1108 of file axpy_kernels.c.

1123{
1124 const size_t required = moe_swiglu_expert_q4k_q5k_workspace_bytes(
1125 hidden_dim, intermediate_dim);
1126 if (!hidden || !indices || !routing_weights || !expert_gate ||
1127 !expert_up || !expert_down || !output || !workspace || required == 0 ||
1128 workspace_bytes < required || rows <= 0 || n_experts <= 0 ||
1129 top_k <= 0 || top_k > n_experts) {
1130 return -1;
1131 }
1132
1133 const size_t hidden_q8_bytes = ck_moe_align64(
1134 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
1135 const size_t gate_up_bytes = ck_moe_align64(
1136 2u * (size_t)intermediate_dim * sizeof(float));
1137 const size_t act_q8_bytes = ck_moe_align64(
1138 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)intermediate_dim));
1139 uint8_t *cursor = (uint8_t *)workspace;
1140 void *hidden_q8 = cursor;
1141 cursor += hidden_q8_bytes;
1142 float *gate_up = (float *)cursor;
1143 cursor += gate_up_bytes;
1144 void *act_q8 = cursor;
1145 cursor += act_q8_bytes;
1146 float *expert_output = (float *)cursor;
1147
1148 const size_t gate_row_bytes = ck_dtype_row_bytes(
1149 CK_DT_Q4_K, (size_t)hidden_dim);
1150 const size_t down_row_bytes = ck_dtype_row_bytes(
1151 CK_DT_Q4_K, (size_t)intermediate_dim);
1152 const uint8_t *gate_base = (const uint8_t *)expert_gate;
1153 const uint8_t *up_base = (const uint8_t *)expert_up;
1154 const uint8_t *down_base = (const uint8_t *)expert_down;
1155
1156 memset(output, 0, (size_t)rows * (size_t)hidden_dim * sizeof(float));
1157 for (int row = 0; row < rows; ++row) {
1158 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
1159 float *y = output + (size_t)row * (size_t)hidden_dim;
1160 quantize_row_q8_k(x, hidden_q8, hidden_dim);
1161 for (int slot = 0; slot < top_k; ++slot) {
1162 const size_t route_index =
1163 (size_t)row * (size_t)top_k + (size_t)slot;
1164 const int expert = indices[route_index];
1165 if (expert < 0 || expert >= n_experts) return -2;
1166 const size_t up_offset =
1167 (size_t)expert * (size_t)intermediate_dim * gate_row_bytes;
1168 const size_t down_offset =
1169 (size_t)expert * (size_t)hidden_dim * down_row_bytes;
1170 gemv_q4_k_q8_k(gate_up, gate_base + up_offset, hidden_q8,
1171 intermediate_dim, hidden_dim);
1172 gemv_q4_k_q8_k(gate_up + intermediate_dim,
1173 up_base + up_offset, hidden_q8,
1174 intermediate_dim, hidden_dim);
1175 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
1176 quantize_row_q8_k(gate_up, act_q8, intermediate_dim);
1177 gemv_q4_k_q8_k(expert_output, down_base + down_offset, act_q8,
1178 hidden_dim, intermediate_dim);
1179 axpy_f32(y, expert_output, routing_weights[route_index], hidden_dim);
1180 }
1181 }
1182 return 0;
1183}
size_t moe_swiglu_expert_q4k_q5k_workspace_bytes(int hidden_dim, int intermediate_dim)
static size_t ck_moe_align64(size_t value)
void gemv_q4_k_q8_k(float *y, const void *W, const void *x_q8, int M, int K)
void swiglu_forward_ggml(const float *input, float *output, int tokens, int dim)

References axpy_f32(), CK_DT_Q4_K, CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), gemv_q4_k_q8_k(), moe_swiglu_expert_q4k_q5k_workspace_bytes(), quantize_row_q8_k(), and swiglu_forward_ggml().

Referenced by moe_swiglu_expert_forward_q4k_q4k_parallel_workspace().

◆ moe_swiglu_expert_forward_q4k_q5_0_parallel_workspace()

int moe_swiglu_expert_forward_q4k_q5_0_parallel_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1927 of file axpy_kernels.c.

1942{
1944 hidden, indices, routing_weights, expert_gate, expert_up, expert_down,
1945 output, rows, hidden_dim, intermediate_dim, n_experts, top_k,
1946 workspace, workspace_bytes,
1948}
int moe_swiglu_expert_forward_q4k_q5_0_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
@ CK_MOE_DOWN_Q5_0

References CK_MOE_DOWN_Q5_0, ck_moe_q4k_mixed_parallel_workspace(), and moe_swiglu_expert_forward_q4k_q5_0_workspace().

◆ moe_swiglu_expert_forward_q4k_q5_0_workspace()

int moe_swiglu_expert_forward_q4k_q5_0_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1027 of file axpy_kernels.c.

1042{
1043 const size_t required = moe_swiglu_expert_q4k_q8_0_workspace_bytes(
1044 hidden_dim, intermediate_dim);
1045 if (!hidden || !indices || !routing_weights || !expert_gate ||
1046 !expert_up || !expert_down || !output || !workspace || required == 0 ||
1047 workspace_bytes < required || rows <= 0 || n_experts <= 0 ||
1048 top_k <= 0 || top_k > n_experts) {
1049 return -1;
1050 }
1051
1052 const size_t hidden_q8_bytes = ck_moe_align64(
1053 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
1054 const size_t gate_up_bytes = ck_moe_align64(
1055 2u * (size_t)intermediate_dim * sizeof(float));
1056 const size_t act_q8_bytes = ck_moe_align64(
1057 ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim));
1058 uint8_t *cursor = (uint8_t *)workspace;
1059 void *hidden_q8 = cursor;
1060 cursor += hidden_q8_bytes;
1061 float *gate_up = (float *)cursor;
1062 cursor += gate_up_bytes;
1063 void *act_q8 = cursor;
1064 cursor += act_q8_bytes;
1065 float *expert_output = (float *)cursor;
1066 cursor += ck_moe_align64((size_t)hidden_dim * sizeof(float));
1067 void *projection_scratch = cursor;
1068
1069 const size_t gate_row_bytes = ck_dtype_row_bytes(
1070 CK_DT_Q4_K, (size_t)hidden_dim);
1071 const size_t down_row_bytes = ck_dtype_row_bytes(
1072 CK_DT_Q5_0, (size_t)intermediate_dim);
1073 const uint8_t *gate_base = (const uint8_t *)expert_gate;
1074 const uint8_t *up_base = (const uint8_t *)expert_up;
1075 const uint8_t *down_base = (const uint8_t *)expert_down;
1076
1077 memset(output, 0, (size_t)rows * (size_t)hidden_dim * sizeof(float));
1078 for (int row = 0; row < rows; ++row) {
1079 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
1080 float *y = output + (size_t)row * (size_t)hidden_dim;
1081 quantize_row_q8_k(x, hidden_q8, hidden_dim);
1082 for (int slot = 0; slot < top_k; ++slot) {
1083 const size_t route_index =
1084 (size_t)row * (size_t)top_k + (size_t)slot;
1085 const int expert = indices[route_index];
1086 if (expert < 0 || expert >= n_experts) return -2;
1087 const size_t gate_offset =
1088 (size_t)expert * (size_t)intermediate_dim * gate_row_bytes;
1089 const size_t down_offset =
1090 (size_t)expert * (size_t)hidden_dim * down_row_bytes;
1092 gate_up, gate_base + gate_offset, hidden_q8,
1093 intermediate_dim, hidden_dim, projection_scratch);
1095 gate_up + intermediate_dim, up_base + gate_offset, hidden_q8,
1096 intermediate_dim, hidden_dim, projection_scratch);
1097 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
1098 quantize_row_q8_0(gate_up, act_q8, intermediate_dim);
1099 gemv_q5_0_q8_0(expert_output, down_base + down_offset, act_q8,
1100 hidden_dim, intermediate_dim);
1102 y, expert_output, routing_weights[route_index], hidden_dim);
1103 }
1104 }
1105 return 0;
1106}
static void ck_moe_q4k_llama_projection(float *output, const void *weights, const void *input_q8, int output_dim, int input_dim, void *scratch)
static void ck_moe_llama_weighted_accumulate(float *output, const float *expert_output, float route_weight, int n)
size_t moe_swiglu_expert_q4k_q8_0_workspace_bytes(int hidden_dim, int intermediate_dim)
void gemv_q5_0_q8_0(float *y, const void *W, const void *x_q8, int M, int K)
Matrix-vector multiply with Q5_0 weights and Q8_0 input.

References CK_DT_Q4_K, CK_DT_Q5_0, CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), ck_moe_llama_weighted_accumulate(), ck_moe_q4k_llama_projection(), gemv_q5_0_q8_0(), moe_swiglu_expert_q4k_q8_0_workspace_bytes(), quantize_row_q8_0(), quantize_row_q8_k(), and swiglu_forward_ggml().

Referenced by moe_swiglu_expert_forward_q4k_q5_0_parallel_workspace().

◆ moe_swiglu_expert_forward_q4k_q5k_auto_prepared_workspace()

int moe_swiglu_expert_forward_q4k_q5k_auto_prepared_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

◆ moe_swiglu_expert_forward_q4k_q5k_auto_workspace()

int moe_swiglu_expert_forward_q4k_q5k_auto_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2619 of file axpy_kernels.c.

2634{
2635 if (rows < 512) {
2637 hidden, indices, routing_weights,
2638 expert_gate, expert_up, expert_down, output,
2639 rows, hidden_dim, intermediate_dim, n_experts, top_k,
2640 workspace, workspace_bytes);
2641 }
2643 hidden, indices, routing_weights,
2644 expert_gate, expert_up, expert_down, output,
2645 rows, hidden_dim, intermediate_dim, n_experts, top_k,
2646 workspace, workspace_bytes);
2647}
int moe_swiglu_expert_forward_q4k_q5k_parallel_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
int moe_swiglu_expert_forward_q4k_q5k_bucketed_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)

References moe_swiglu_expert_forward_q4k_q5k_bucketed_workspace(), and moe_swiglu_expert_forward_q4k_q5k_parallel_workspace().

◆ moe_swiglu_expert_forward_q4k_q5k_bucketed_prepared_workspace()

int moe_swiglu_expert_forward_q4k_q5k_bucketed_prepared_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
const void *  expert_gate_packed,
const void *  expert_up_packed,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2593 of file axpy_kernels.c.

2610{
2612 hidden, indices, routing_weights,
2613 expert_gate, expert_up, expert_down,
2614 expert_gate_packed, expert_up_packed, output,
2615 rows, hidden_dim, intermediate_dim, n_experts, top_k,
2616 workspace, workspace_bytes);
2617}
static int ck_moe_swiglu_expert_forward_q4k_q5k_bucketed_impl(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, const void *expert_gate_packed, const void *expert_up_packed, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)

References ck_moe_swiglu_expert_forward_q4k_q5k_bucketed_impl().

◆ moe_swiglu_expert_forward_q4k_q5k_bucketed_workspace()

int moe_swiglu_expert_forward_q4k_q5k_bucketed_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2570 of file axpy_kernels.c.

2585{
2587 hidden, indices, routing_weights,
2588 expert_gate, expert_up, expert_down, NULL, NULL, output,
2589 rows, hidden_dim, intermediate_dim, n_experts, top_k,
2590 workspace, workspace_bytes);
2591}

References ck_moe_swiglu_expert_forward_q4k_q5k_bucketed_impl().

Referenced by moe_swiglu_expert_forward_q4k_q5k_auto_workspace().

◆ moe_swiglu_expert_forward_q4k_q5k_parallel_workspace()

int moe_swiglu_expert_forward_q4k_q5k_parallel_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1470 of file axpy_kernels.c.

1485{
1486 const size_t stride = moe_swiglu_expert_q4k_q5k_workspace_bytes(
1487 hidden_dim, intermediate_dim);
1488 if (!hidden || !indices || !routing_weights || !expert_gate || !expert_up ||
1489 !expert_down || !output || !workspace || stride == 0 || rows <= 0 ||
1490 n_experts <= 0 || top_k <= 0 || top_k > n_experts) {
1491 return -1;
1492 }
1493
1494 ck_threadpool_t *pool = ck_threadpool_global();
1495 if (rows == 1) {
1496 const int route_status = ck_moe_q4k_q5k_route_parallel(
1497 hidden, indices, routing_weights,
1498 expert_gate, expert_up, expert_down, output,
1499 hidden_dim, intermediate_dim, n_experts, top_k,
1500 workspace, workspace_bytes, stride, pool);
1501 if (route_status <= 0) return route_status;
1502 }
1503
1504 int active = pool ? ck_threadpool_n_threads(pool) : 1;
1505 if (active > rows) active = rows;
1507 const size_t workspace_workers = workspace_bytes / stride;
1508 if (workspace_workers == 0) return -1;
1509 if ((size_t)active > workspace_workers) active = (int)workspace_workers;
1510 if (active <= 1) {
1512 hidden, indices, routing_weights, expert_gate, expert_up, expert_down,
1513 output, rows, hidden_dim, intermediate_dim, n_experts, top_k,
1514 workspace, stride);
1515 }
1516
1517 ck_moe_q4k_q5k_parallel_args_t args = {
1518 .hidden = hidden,
1519 .indices = indices,
1520 .routing_weights = routing_weights,
1521 .expert_gate = expert_gate,
1522 .expert_up = expert_up,
1523 .expert_down = expert_down,
1524 .output = output,
1525 .rows = rows,
1526 .hidden_dim = hidden_dim,
1527 .intermediate_dim = intermediate_dim,
1528 .n_experts = n_experts,
1529 .top_k = top_k,
1530 .workspace = (uint8_t *)workspace,
1531 .workspace_stride = stride,
1532 .status = {0},
1533 };
1535 for (int ith = 0; ith < active; ++ith) {
1536 if (args.status[ith] != 0) return args.status[ith];
1537 }
1538 return 0;
1539}
static void ck_moe_q4k_q5k_parallel_work(int ith, int nth, void *opaque)
int moe_swiglu_expert_forward_q4k_q5k_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
static int ck_moe_q4k_q5k_route_parallel(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes, size_t workspace_stride, ck_threadpool_t *pool)
#define CK_THREADPOOL_MAX_THREADS

References ck_moe_q4k_q5k_parallel_work(), ck_moe_q4k_q5k_route_parallel(), ck_threadpool_dispatch_n(), ck_threadpool_global(), CK_THREADPOOL_MAX_THREADS, ck_threadpool_n_threads(), moe_swiglu_expert_forward_q4k_q5k_workspace(), and moe_swiglu_expert_q4k_q5k_workspace_bytes().

Referenced by moe_swiglu_expert_forward_q4k_q5k_auto_workspace().

◆ moe_swiglu_expert_forward_q4k_q5k_workspace()

int moe_swiglu_expert_forward_q4k_q5k_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 781 of file axpy_kernels.c.

796{
797 const size_t required = moe_swiglu_expert_q4k_q5k_workspace_bytes(
798 hidden_dim, intermediate_dim);
799 if (!hidden || !indices || !routing_weights || !expert_gate || !expert_up ||
800 !expert_down || !output || !workspace || required == 0 ||
801 workspace_bytes < required || rows <= 0 || n_experts <= 0 ||
802 top_k <= 0 || top_k > n_experts) {
803 return -1;
804 }
805
806 const size_t hidden_q8_bytes = ck_moe_align64(
807 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
808 const size_t gate_up_bytes = ck_moe_align64(
809 2u * (size_t)intermediate_dim * sizeof(float));
810 const size_t act_q8_bytes = ck_moe_align64(
811 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)intermediate_dim));
812 uint8_t *cursor = (uint8_t *)workspace;
813 void *hidden_q8 = cursor;
814 cursor += hidden_q8_bytes;
815 float *gate_up = (float *)cursor;
816 cursor += gate_up_bytes;
817 void *act_q8 = cursor;
818 cursor += act_q8_bytes;
819 float *expert_output = (float *)cursor;
820
821 const size_t q4_row_bytes = ck_dtype_row_bytes(CK_DT_Q4_K, (size_t)hidden_dim);
822 const size_t q5_row_bytes = ck_dtype_row_bytes(CK_DT_Q5_K, (size_t)intermediate_dim);
823 const uint8_t *gate_base = (const uint8_t *)expert_gate;
824 const uint8_t *up_base = (const uint8_t *)expert_up;
825 const uint8_t *down_base = (const uint8_t *)expert_down;
826
827 memset(output, 0, (size_t)rows * (size_t)hidden_dim * sizeof(float));
828 for (int row = 0; row < rows; ++row) {
829 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
830 float *y = output + (size_t)row * (size_t)hidden_dim;
831 quantize_row_q8_k(x, hidden_q8, hidden_dim);
832
833 for (int slot = 0; slot < top_k; ++slot) {
834 const size_t route_index = (size_t)row * (size_t)top_k + (size_t)slot;
835 const int expert = indices[route_index];
836 if (expert < 0 || expert >= n_experts) {
837 return -2;
838 }
839
840 const size_t up_expert_offset =
841 (size_t)expert * (size_t)intermediate_dim * q4_row_bytes;
842 const size_t down_expert_offset =
843 (size_t)expert * (size_t)hidden_dim * q5_row_bytes;
844 gemv_q4_k_q8_k(gate_up,
845 gate_base + up_expert_offset,
846 hidden_q8,
847 intermediate_dim,
848 hidden_dim);
849 gemv_q4_k_q8_k(gate_up + intermediate_dim,
850 up_base + up_expert_offset,
851 hidden_q8,
852 intermediate_dim,
853 hidden_dim);
854 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
855 quantize_row_q8_k(gate_up, act_q8, intermediate_dim);
856 gemv_q5_k_q8_k(expert_output,
857 down_base + down_expert_offset,
858 act_q8,
859 hidden_dim,
860 intermediate_dim);
861
862 const float route_weight = routing_weights[route_index];
863 axpy_f32(y, expert_output, route_weight, hidden_dim);
864 }
865 }
866 return 0;
867}
@ CK_DT_Q5_K
void gemv_q5_k_q8_k(float *y, const void *W, const void *x_q8, int M, int K)

References axpy_f32(), CK_DT_Q4_K, CK_DT_Q5_K, CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), gemv_q4_k_q8_k(), gemv_q5_k_q8_k(), moe_swiglu_expert_q4k_q5k_workspace_bytes(), quantize_row_q8_k(), and swiglu_forward_ggml().

Referenced by ck_moe_q4k_q5k_parallel_work(), and moe_swiglu_expert_forward_q4k_q5k_parallel_workspace().

◆ moe_swiglu_expert_forward_q4k_q6k_parallel_workspace()

int moe_swiglu_expert_forward_q4k_q6k_parallel_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1858 of file axpy_kernels.c.

1873{
1875 hidden, indices, routing_weights, expert_gate, expert_up, expert_down,
1876 output, rows, hidden_dim, intermediate_dim, n_experts, top_k,
1877 workspace, workspace_bytes,
1879}
int moe_swiglu_expert_forward_q4k_q6k_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
@ CK_MOE_DOWN_Q6_K

References CK_MOE_DOWN_Q6_K, ck_moe_q4k_mixed_parallel_workspace(), and moe_swiglu_expert_forward_q4k_q6k_workspace().

◆ moe_swiglu_expert_forward_q4k_q6k_workspace()

int moe_swiglu_expert_forward_q4k_q6k_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 869 of file axpy_kernels.c.

884{
885 const size_t required = moe_swiglu_expert_q4k_q5k_workspace_bytes(
886 hidden_dim, intermediate_dim);
887 if (!hidden || !indices || !routing_weights || !expert_gate ||
888 !expert_up || !expert_down || !output || !workspace || required == 0 ||
889 workspace_bytes < required || rows <= 0 || n_experts <= 0 ||
890 top_k <= 0 || top_k > n_experts) {
891 return -1;
892 }
893
894 const size_t hidden_q8_bytes = ck_moe_align64(
895 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
896 const size_t gate_up_bytes = ck_moe_align64(
897 2u * (size_t)intermediate_dim * sizeof(float));
898 const size_t act_q8_bytes = ck_moe_align64(
899 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)intermediate_dim));
900 uint8_t *cursor = (uint8_t *)workspace;
901 void *hidden_q8 = cursor;
902 cursor += hidden_q8_bytes;
903 float *gate_up = (float *)cursor;
904 cursor += gate_up_bytes;
905 void *act_q8 = cursor;
906 cursor += act_q8_bytes;
907 float *expert_output = (float *)cursor;
908
909 const size_t q4_row_bytes = ck_dtype_row_bytes(
910 CK_DT_Q4_K, (size_t)hidden_dim);
911 const size_t q6_row_bytes = ck_dtype_row_bytes(
912 CK_DT_Q6_K, (size_t)intermediate_dim);
913 const uint8_t *gate_base = (const uint8_t *)expert_gate;
914 const uint8_t *up_base = (const uint8_t *)expert_up;
915 const uint8_t *down_base = (const uint8_t *)expert_down;
916
917 memset(output, 0, (size_t)rows * (size_t)hidden_dim * sizeof(float));
918 for (int row = 0; row < rows; ++row) {
919 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
920 float *y = output + (size_t)row * (size_t)hidden_dim;
921 quantize_row_q8_k(x, hidden_q8, hidden_dim);
922 for (int slot = 0; slot < top_k; ++slot) {
923 const size_t route_index =
924 (size_t)row * (size_t)top_k + (size_t)slot;
925 const int expert = indices[route_index];
926 if (expert < 0 || expert >= n_experts) return -2;
927 const size_t up_offset =
928 (size_t)expert * (size_t)intermediate_dim * q4_row_bytes;
929 const size_t down_offset =
930 (size_t)expert * (size_t)hidden_dim * q6_row_bytes;
931 gemv_q4_k_q8_k(gate_up, gate_base + up_offset, hidden_q8,
932 intermediate_dim, hidden_dim);
933 gemv_q4_k_q8_k(gate_up + intermediate_dim,
934 up_base + up_offset, hidden_q8,
935 intermediate_dim, hidden_dim);
936 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
937 quantize_row_q8_k(gate_up, act_q8, intermediate_dim);
938 gemv_q6_k_q8_k(expert_output, down_base + down_offset, act_q8,
939 hidden_dim, intermediate_dim);
940 axpy_f32(y, expert_output, routing_weights[route_index], hidden_dim);
941 }
942 }
943 return 0;
944}
void gemv_q6_k_q8_k(float *y, const void *W, const void *x_q8, int M, int K)
GEMV: y = W @ x where W is Q6_K and x is Q8_K.

References axpy_f32(), CK_DT_Q4_K, CK_DT_Q6_K, CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), gemv_q4_k_q8_k(), gemv_q6_k_q8_k(), moe_swiglu_expert_q4k_q5k_workspace_bytes(), quantize_row_q8_k(), and swiglu_forward_ggml().

Referenced by moe_swiglu_expert_forward_q4k_q6k_parallel_workspace().

◆ moe_swiglu_expert_forward_q4k_q8_0_parallel_workspace()

int moe_swiglu_expert_forward_q4k_q8_0_parallel_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1904 of file axpy_kernels.c.

1919{
1921 hidden, indices, routing_weights, expert_gate, expert_up, expert_down,
1922 output, rows, hidden_dim, intermediate_dim, n_experts, top_k,
1923 workspace, workspace_bytes,
1925}
int moe_swiglu_expert_forward_q4k_q8_0_workspace(const float *hidden, const int *indices, const float *routing_weights, const void *expert_gate, const void *expert_up, const void *expert_down, float *output, int rows, int hidden_dim, int intermediate_dim, int n_experts, int top_k, void *workspace, size_t workspace_bytes)
@ CK_MOE_DOWN_Q8_0

References CK_MOE_DOWN_Q8_0, ck_moe_q4k_mixed_parallel_workspace(), and moe_swiglu_expert_forward_q4k_q8_0_workspace().

◆ moe_swiglu_expert_forward_q4k_q8_0_workspace()

int moe_swiglu_expert_forward_q4k_q8_0_workspace ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const void *  expert_gate,
const void *  expert_up,
const void *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 946 of file axpy_kernels.c.

961{
962 const size_t required = moe_swiglu_expert_q4k_q8_0_workspace_bytes(
963 hidden_dim, intermediate_dim);
964 if (!hidden || !indices || !routing_weights || !expert_gate ||
965 !expert_up || !expert_down || !output || !workspace || required == 0 ||
966 workspace_bytes < required || rows <= 0 || n_experts <= 0 ||
967 top_k <= 0 || top_k > n_experts) {
968 return -1;
969 }
970
971 const size_t hidden_q8_bytes = ck_moe_align64(
972 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
973 const size_t gate_up_bytes = ck_moe_align64(
974 2u * (size_t)intermediate_dim * sizeof(float));
975 const size_t act_q8_bytes = ck_moe_align64(
976 ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim));
977 uint8_t *cursor = (uint8_t *)workspace;
978 void *hidden_q8 = cursor;
979 cursor += hidden_q8_bytes;
980 float *gate_up = (float *)cursor;
981 cursor += gate_up_bytes;
982 void *act_q8 = cursor;
983 cursor += act_q8_bytes;
984 float *expert_output = (float *)cursor;
985 cursor += ck_moe_align64((size_t)hidden_dim * sizeof(float));
986 void *projection_scratch = cursor;
987
988 const size_t gate_row_bytes = ck_dtype_row_bytes(
989 CK_DT_Q4_K, (size_t)hidden_dim);
990 const size_t down_row_bytes = ck_dtype_row_bytes(
991 CK_DT_Q8_0, (size_t)intermediate_dim);
992 const uint8_t *gate_base = (const uint8_t *)expert_gate;
993 const uint8_t *up_base = (const uint8_t *)expert_up;
994 const uint8_t *down_base = (const uint8_t *)expert_down;
995
996 memset(output, 0, (size_t)rows * (size_t)hidden_dim * sizeof(float));
997 for (int row = 0; row < rows; ++row) {
998 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
999 float *y = output + (size_t)row * (size_t)hidden_dim;
1000 quantize_row_q8_k(x, hidden_q8, hidden_dim);
1001 for (int slot = 0; slot < top_k; ++slot) {
1002 const size_t route_index =
1003 (size_t)row * (size_t)top_k + (size_t)slot;
1004 const int expert = indices[route_index];
1005 if (expert < 0 || expert >= n_experts) return -2;
1006 const size_t gate_offset =
1007 (size_t)expert * (size_t)intermediate_dim * gate_row_bytes;
1008 const size_t down_offset =
1009 (size_t)expert * (size_t)hidden_dim * down_row_bytes;
1011 gate_up, gate_base + gate_offset, hidden_q8,
1012 intermediate_dim, hidden_dim, projection_scratch);
1014 gate_up + intermediate_dim, up_base + gate_offset, hidden_q8,
1015 intermediate_dim, hidden_dim, projection_scratch);
1016 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
1017 quantize_row_q8_0(gate_up, act_q8, intermediate_dim);
1018 gemv_q8_0_q8_0(expert_output, down_base + down_offset, act_q8,
1019 hidden_dim, intermediate_dim);
1021 y, expert_output, routing_weights[route_index], hidden_dim);
1022 }
1023 }
1024 return 0;
1025}
void gemv_q8_0_q8_0(float *y, const void *W, const void *x_q8, int M, int K)
Matrix-vector multiply with Q8_0 weights and Q8_0 input.

References CK_DT_Q4_K, CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), ck_moe_llama_weighted_accumulate(), ck_moe_q4k_llama_projection(), gemv_q8_0_q8_0(), moe_swiglu_expert_q4k_q8_0_workspace_bytes(), quantize_row_q8_0(), quantize_row_q8_k(), and swiglu_forward_ggml().

Referenced by moe_swiglu_expert_forward_q4k_q8_0_parallel_workspace().

◆ moe_swiglu_expert_q4k_q5k_workspace_bytes()

size_t moe_swiglu_expert_q4k_q5k_workspace_bytes ( int  hidden_dim,
int  intermediate_dim 
)

Definition at line 727 of file axpy_kernels.c.

729{
730 if (hidden_dim <= 0 || intermediate_dim <= 0 ||
731 hidden_dim % 256 != 0 || intermediate_dim % 256 != 0) {
732 return 0;
733 }
734
735 size_t bytes = ck_moe_align64(ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
736 bytes += ck_moe_align64(2u * (size_t)intermediate_dim * sizeof(float));
737 bytes += ck_moe_align64(ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)intermediate_dim));
738 bytes += ck_moe_align64((size_t)hidden_dim * sizeof(float));
739 return bytes;
740}

References CK_DT_Q8_K, ck_dtype_row_bytes(), and ck_moe_align64().

Referenced by ck_moe_q4k_mixed_parallel_workspace(), ck_moe_shared_q4k_parallel_workspace(), moe_swiglu_expert_forward_q4k_q4k_workspace(), moe_swiglu_expert_forward_q4k_q5k_parallel_workspace(), moe_swiglu_expert_forward_q4k_q5k_workspace(), moe_swiglu_expert_forward_q4k_q6k_workspace(), moe_swiglu_shared_forward_q4k_q4k_workspace(), and moe_swiglu_shared_forward_q4k_q6k_workspace().

◆ moe_swiglu_expert_q4k_q8_0_workspace_bytes()

size_t moe_swiglu_expert_q4k_q8_0_workspace_bytes ( int  hidden_dim,
int  intermediate_dim 
)

Definition at line 742 of file axpy_kernels.c.

744{
745 if (hidden_dim <= 0 || intermediate_dim <= 0 ||
746 hidden_dim % 256 != 0 || intermediate_dim % QK8_0 != 0) {
747 return 0;
748 }
749
750 size_t bytes = ck_moe_align64(
751 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
752 bytes += ck_moe_align64(2u * (size_t)intermediate_dim * sizeof(float));
753 bytes += ck_moe_align64(
754 ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim));
755 bytes += ck_moe_align64((size_t)hidden_dim * sizeof(float));
757 intermediate_dim, hidden_dim);
758 return bytes;
759}
static size_t ck_moe_q4k_llama_projection_scratch_bytes(int output_dim, int input_dim)

References CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), ck_moe_q4k_llama_projection_scratch_bytes(), and QK8_0.

Referenced by ck_moe_q4k_mixed_parallel_workspace(), moe_swiglu_expert_forward_q4k_q5_0_workspace(), and moe_swiglu_expert_forward_q4k_q8_0_workspace().

◆ moe_swiglu_packed_expert_forward_bf16()

void moe_swiglu_packed_expert_forward_bf16 ( const float *  hidden,
const int *  indices,
const float *  routing_weights,
const uint16_t *  expert_gate_up,
const uint16_t *  expert_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  n_experts,
int  top_k 
)

Definition at line 582 of file axpy_kernels.c.

594{
595 if (!hidden || !indices || !routing_weights || !expert_gate_up ||
596 !expert_down || !output || rows <= 0 || hidden_dim <= 0 ||
597 intermediate_dim <= 0 || n_experts <= 0 || top_k <= 0) {
598 return;
599 }
600
601 float projection[2 * intermediate_dim];
602 float activation[intermediate_dim];
603 const size_t packed_expert_stride =
604 (size_t)2 * (size_t)intermediate_dim * (size_t)hidden_dim;
605 const size_t packed_up_offset =
606 (size_t)intermediate_dim * (size_t)hidden_dim;
607 for (int row = 0; row < rows; ++row) {
608 float *y = output + (size_t)row * (size_t)hidden_dim;
609 for (int hidden_col = 0; hidden_col < hidden_dim; ++hidden_col) {
610 y[hidden_col] = 0.0f;
611 }
612 }
613 for (int row = 0; row < rows; ++row) {
614 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
615 float *y = output + (size_t)row * (size_t)hidden_dim;
616 for (int slot = 0; slot < top_k; ++slot) {
617 const size_t route_index =
618 (size_t)row * (size_t)top_k + (size_t)slot;
619 const int expert = indices[route_index];
620 if (expert < 0 || expert >= n_experts) continue;
621 const uint16_t *packed =
622 expert_gate_up + (size_t)expert * packed_expert_stride;
623 const uint16_t *gate = packed;
624 const uint16_t *up = packed + packed_up_offset;
625 for (int intermediate = 0; intermediate < intermediate_dim;
626 ++intermediate) {
627 float gate_value = 0.0f;
628 float up_value = 0.0f;
629 const size_t row_offset =
630 (size_t)intermediate * (size_t)hidden_dim;
631 for (int hidden_col = 0; hidden_col < hidden_dim;
632 ++hidden_col) {
633 const float input =
634 ck_moe_bf16_round(x[hidden_col]);
635 gate_value +=
636 bf16_to_float(gate[row_offset + hidden_col]) * input;
637 up_value +=
638 bf16_to_float(up[row_offset + hidden_col]) * input;
639 }
640 projection[intermediate] =
641 ck_moe_bf16_round(gate_value);
642 projection[intermediate_dim + intermediate] =
643 ck_moe_bf16_round(up_value);
644 }
646 projection, activation, 1, intermediate_dim);
647
648 const float route_weight =
649 ck_moe_bf16_round(routing_weights[route_index]);
650 for (int hidden_col = 0; hidden_col < hidden_dim;
651 ++hidden_col) {
652 float value = 0.0f;
653 for (int intermediate = 0;
654 intermediate < intermediate_dim; ++intermediate) {
655 value += bf16_to_float(expert_down[
656 ck_moe_down_idx(expert, hidden_col, intermediate,
657 hidden_dim, intermediate_dim)]) *
658 activation[intermediate];
659 }
660 const float down_stored = ck_moe_bf16_round(value);
661 const float weighted = ck_moe_bf16_round(
662 down_stored * route_weight);
663 y[hidden_col] += weighted;
664 }
665 }
666 for (int hidden_col = 0; hidden_col < hidden_dim; ++hidden_col) {
667 y[hidden_col] = ck_moe_bf16_round(y[hidden_col]);
668 }
669 }
670}
static float ck_moe_bf16_round(float x)
void swiglu_forward_pytorch_bf16_storage(const float *input, float *output, int tokens, int dim)

References bf16_to_float(), ck_moe_bf16_round(), ck_moe_down_idx(), and swiglu_forward_pytorch_bf16_storage().

◆ moe_swiglu_shared_forward_bf16()

void moe_swiglu_shared_forward_bf16 ( const float *  hidden,
const float *  routed,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

Definition at line 3229 of file axpy_kernels.c.

3238{
3239 if (rows <= 0) return;
3241 hidden, routed, shared_gate, shared_up, shared_down, output,
3242 rows, hidden_dim, intermediate_dim, 0, rows);
3243}
void moe_swiglu_shared_forward_bf16_row_range(const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, int row_begin, int row_end)

References moe_swiglu_shared_forward_bf16_row_range().

◆ moe_swiglu_shared_forward_bf16_gated()

void moe_swiglu_shared_forward_bf16_gated ( const float *  hidden,
const float *  routed,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
const uint16_t *  shared_router,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

Definition at line 3322 of file axpy_kernels.c.

3333{
3334 if (rows <= 0) return;
3336 hidden, routed, shared_gate, shared_up, shared_down, shared_router,
3337 output, rows, hidden_dim, intermediate_dim, 0, rows);
3338}
void moe_swiglu_shared_forward_bf16_gated_row_range(const float *hidden, const float *routed, const uint16_t *shared_gate, const uint16_t *shared_up, const uint16_t *shared_down, const uint16_t *shared_router, float *output, int rows, int hidden_dim, int intermediate_dim, int row_begin, int row_end)

References moe_swiglu_shared_forward_bf16_gated_row_range().

◆ moe_swiglu_shared_forward_bf16_gated_parallel_dispatch()

void moe_swiglu_shared_forward_bf16_gated_parallel_dispatch ( const float *  hidden,
const float *  routed,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
const uint16_t *  shared_router,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

◆ moe_swiglu_shared_forward_bf16_gated_row_range()

void moe_swiglu_shared_forward_bf16_gated_row_range ( const float *  hidden,
const float *  routed,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
const uint16_t *  shared_router,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  row_begin,
int  row_end 
)

Definition at line 3245 of file axpy_kernels.c.

3258{
3259 if (!hidden || !shared_gate || !shared_up || !shared_down ||
3260 !shared_router || !output || rows <= 0 || hidden_dim <= 0 ||
3261 intermediate_dim <= 0 || row_begin < 0 || row_begin >= row_end ||
3262 row_end > rows) {
3263 return;
3264 }
3265
3266 float activation[intermediate_dim];
3267 for (int row = row_begin; row < row_end; ++row) {
3268 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
3269 const float *route = routed
3270 ? routed + (size_t)row * (size_t)hidden_dim
3271 : NULL;
3272 float *y = output + (size_t)row * (size_t)hidden_dim;
3273
3274 for (int intermediate = 0; intermediate < intermediate_dim;
3275 ++intermediate) {
3276 float gate_sum = 0.0f;
3277 float up_sum = 0.0f;
3278 const size_t weight_base =
3279 (size_t)intermediate * (size_t)hidden_dim;
3280 for (int hidden_col = 0; hidden_col < hidden_dim; ++hidden_col) {
3281 const float value = ck_moe_bf16_round(x[hidden_col]);
3282 gate_sum += bf16_to_float(
3283 shared_gate[weight_base + (size_t)hidden_col]) * value;
3284 up_sum += bf16_to_float(
3285 shared_up[weight_base + (size_t)hidden_col]) * value;
3286 }
3287 const float gate_value = ck_moe_bf16_round(gate_sum);
3288 const float up_value = ck_moe_bf16_round(up_sum);
3289 const float silu = ck_moe_bf16_round(
3290 ck_moe_silu_f32(gate_value));
3291 activation[intermediate] = ck_moe_bf16_round(silu * up_value);
3292 }
3293
3294 float router_sum = 0.0f;
3295 for (int hidden_col = 0; hidden_col < hidden_dim; ++hidden_col) {
3296 router_sum += bf16_to_float(shared_router[hidden_col]) *
3297 ck_moe_bf16_round(x[hidden_col]);
3298 }
3299 const float shared_scale = ck_moe_bf16_round(
3301
3302 for (int hidden_col = 0; hidden_col < hidden_dim; ++hidden_col) {
3303 float down_sum = 0.0f;
3304 const size_t weight_base =
3305 (size_t)hidden_col * (size_t)intermediate_dim;
3306 for (int intermediate = 0; intermediate < intermediate_dim;
3307 ++intermediate) {
3308 down_sum += bf16_to_float(
3309 shared_down[weight_base + (size_t)intermediate]) *
3310 activation[intermediate];
3311 }
3312 const float shared = ck_moe_bf16_round(down_sum);
3313 const float gated_shared = ck_moe_bf16_round(shared * shared_scale);
3314 const float routed_value = route
3315 ? ck_moe_bf16_round(route[hidden_col])
3316 : 0.0f;
3317 y[hidden_col] = ck_moe_bf16_round(routed_value + gated_shared);
3318 }
3319 }
3320}
static float ck_moe_sigmoid_f32(float x)

References bf16_to_float(), ck_moe_bf16_round(), ck_moe_sigmoid_f32(), ck_moe_silu_f32(), and silu().

Referenced by moe_swiglu_shared_forward_bf16_gated().

◆ moe_swiglu_shared_forward_bf16_parallel_dispatch()

void moe_swiglu_shared_forward_bf16_parallel_dispatch ( const float *  hidden,
const float *  routed,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

◆ moe_swiglu_shared_forward_bf16_row_range()

void moe_swiglu_shared_forward_bf16_row_range ( const float *  hidden,
const float *  routed,
const uint16_t *  shared_gate,
const uint16_t *  shared_up,
const uint16_t *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
int  row_begin,
int  row_end 
)

Definition at line 3181 of file axpy_kernels.c.

3193{
3194 if (!hidden || !shared_gate || !shared_up || !shared_down || !output ||
3195 rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0 ||
3196 row_begin < 0 || row_begin >= row_end || row_end > rows) {
3197 return;
3198 }
3199
3200 float gate[intermediate_dim];
3201 float up[intermediate_dim];
3202 float act[intermediate_dim];
3203
3204 for (int r = row_begin; r < row_end; ++r) {
3205 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
3206 const float *route = routed ? (routed + (size_t)r * (size_t)hidden_dim) : NULL;
3207 float *y = output + (size_t)r * (size_t)hidden_dim;
3208 for (int i = 0; i < intermediate_dim; ++i) {
3209 float gv = 0.0f;
3210 float uv = 0.0f;
3211 for (int h = 0; h < hidden_dim; ++h) {
3212 gv += bf16_to_float(shared_gate[(size_t)i * (size_t)hidden_dim + (size_t)h]) * x[h];
3213 uv += bf16_to_float(shared_up[(size_t)i * (size_t)hidden_dim + (size_t)h]) * x[h];
3214 }
3215 gate[i] = gv;
3216 up[i] = uv;
3217 act[i] = ck_moe_silu_f32(gv) * uv;
3218 }
3219 for (int h = 0; h < hidden_dim; ++h) {
3220 float v = route ? route[h] : 0.0f;
3221 for (int i = 0; i < intermediate_dim; ++i) {
3222 v += bf16_to_float(shared_down[(size_t)h * (size_t)intermediate_dim + (size_t)i]) * act[i];
3223 }
3224 y[h] = v;
3225 }
3226 }
3227}

References bf16_to_float(), and ck_moe_silu_f32().

Referenced by moe_swiglu_shared_forward_bf16().

◆ moe_swiglu_shared_forward_f32()

void moe_swiglu_shared_forward_f32 ( const float *  hidden,
const float *  routed,
const float *  shared_gate,
const float *  shared_up,
const float *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim 
)

Definition at line 3140 of file axpy_kernels.c.

3149{
3150 if (!hidden || !shared_gate || !shared_up || !shared_down || !output || rows <= 0 || hidden_dim <= 0 || intermediate_dim <= 0) {
3151 return;
3152 }
3153
3154 float gate[intermediate_dim];
3155 float up[intermediate_dim];
3156 float act[intermediate_dim];
3157
3158 for (int r = 0; r < rows; ++r) {
3159 const float *x = hidden + (size_t)r * (size_t)hidden_dim;
3160 const float *route = routed ? (routed + (size_t)r * (size_t)hidden_dim) : NULL;
3161 float *y = output + (size_t)r * (size_t)hidden_dim;
3162 for (int i = 0; i < intermediate_dim; ++i) {
3163 float gv = 0.0f;
3164 float uv = 0.0f;
3165 for (int h = 0; h < hidden_dim; ++h) {
3166 gv += shared_gate[(size_t)i * (size_t)hidden_dim + (size_t)h] * x[h];
3167 uv += shared_up[(size_t)i * (size_t)hidden_dim + (size_t)h] * x[h];
3168 }
3169 act[i] = ck_moe_silu_f32(gv) * uv;
3170 }
3171 for (int h = 0; h < hidden_dim; ++h) {
3172 float v = route ? route[h] : 0.0f;
3173 for (int i = 0; i < intermediate_dim; ++i) {
3174 v += shared_down[(size_t)h * (size_t)intermediate_dim + (size_t)i] * act[i];
3175 }
3176 y[h] = v;
3177 }
3178 }
3179}

References ck_moe_silu_f32().

◆ moe_swiglu_shared_forward_q4k_q4k_parallel_workspace()

int moe_swiglu_shared_forward_q4k_q4k_parallel_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2071 of file axpy_kernels.c.

2083{
2085 hidden, routed, shared_gate, shared_up, shared_down, output, rows,
2086 hidden_dim, intermediate_dim, workspace, workspace_bytes,
2088}
static int ck_moe_shared_q4k_parallel_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes, ck_moe_shared_workspace_fn serial_fn)
int moe_swiglu_shared_forward_q4k_q4k_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)

References ck_moe_shared_q4k_parallel_workspace(), and moe_swiglu_shared_forward_q4k_q4k_workspace().

◆ moe_swiglu_shared_forward_q4k_q4k_workspace()

int moe_swiglu_shared_forward_q4k_q4k_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1242 of file axpy_kernels.c.

1254{
1255 const size_t required = moe_swiglu_expert_q4k_q5k_workspace_bytes(
1256 hidden_dim, intermediate_dim);
1257 if (!hidden || !shared_gate || !shared_up || !shared_down || !output ||
1258 !workspace || required == 0 || workspace_bytes < required || rows <= 0) {
1259 return -1;
1260 }
1261
1262 const size_t hidden_q8_bytes = ck_moe_align64(
1263 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
1264 const size_t gate_up_bytes = ck_moe_align64(
1265 2u * (size_t)intermediate_dim * sizeof(float));
1266 const size_t act_q8_bytes = ck_moe_align64(
1267 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)intermediate_dim));
1268 uint8_t *cursor = (uint8_t *)workspace;
1269 void *hidden_q8 = cursor;
1270 cursor += hidden_q8_bytes;
1271 float *gate_up = (float *)cursor;
1272 cursor += gate_up_bytes;
1273 void *act_q8 = cursor;
1274 cursor += act_q8_bytes;
1275 float *shared_output = (float *)cursor;
1276
1277 for (int row = 0; row < rows; ++row) {
1278 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
1279 float *y = output + (size_t)row * (size_t)hidden_dim;
1280 quantize_row_q8_k(x, hidden_q8, hidden_dim);
1281 gemv_q4_k_q8_k(gate_up, shared_gate, hidden_q8,
1282 intermediate_dim, hidden_dim);
1283 gemv_q4_k_q8_k(gate_up + intermediate_dim, shared_up, hidden_q8,
1284 intermediate_dim, hidden_dim);
1285 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
1286 quantize_row_q8_k(gate_up, act_q8, intermediate_dim);
1287 gemv_q4_k_q8_k(shared_output, shared_down, act_q8,
1288 hidden_dim, intermediate_dim);
1289 const float *route = routed
1290 ? routed + (size_t)row * (size_t)hidden_dim
1291 : NULL;
1292 for (int col = 0; col < hidden_dim; ++col) {
1293 y[col] = shared_output[col] + (route ? route[col] : 0.0f);
1294 }
1295 }
1296 return 0;
1297}

References CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), gemv_q4_k_q8_k(), moe_swiglu_expert_q4k_q5k_workspace_bytes(), quantize_row_q8_k(), and swiglu_forward_ggml().

Referenced by moe_swiglu_shared_forward_q4k_q4k_parallel_workspace().

◆ moe_swiglu_shared_forward_q4k_q5_0_gated_parallel_workspace()

int moe_swiglu_shared_forward_q4k_q5_0_gated_parallel_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
const float *  shared_gate_input,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 3023 of file axpy_kernels.c.

3036{
3037 /* See the Q8_0-down variant above: inner projection dispatch owns the
3038 * pool so nested row dispatch would deadlock. */
3040 hidden, routed, shared_gate, shared_up, shared_down, shared_gate_input,
3041 output, rows, hidden_dim, intermediate_dim, workspace, workspace_bytes);
3042}
int moe_swiglu_shared_forward_q4k_q5_0_gated_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)

References moe_swiglu_shared_forward_q4k_q5_0_gated_workspace().

◆ moe_swiglu_shared_forward_q4k_q5_0_gated_workspace()

int moe_swiglu_shared_forward_q4k_q5_0_gated_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
const float *  shared_gate_input,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2852 of file axpy_kernels.c.

2865{
2867 hidden, routed, shared_gate, shared_up, shared_down, shared_gate_input,
2868 output, rows, hidden_dim, intermediate_dim, workspace, workspace_bytes,
2870}
static int ck_moe_shared_q4k_gated_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes, void(*down_projection)(float *, const void *, const void *, int, int))

References ck_moe_shared_q4k_gated_workspace(), and gemv_q5_0_q8_0().

Referenced by moe_swiglu_shared_forward_q4k_q5_0_gated_parallel_workspace().

◆ moe_swiglu_shared_forward_q4k_q6k_parallel_workspace()

int moe_swiglu_shared_forward_q4k_q6k_parallel_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2052 of file axpy_kernels.c.

2064{
2066 hidden, routed, shared_gate, shared_up, shared_down, output, rows,
2067 hidden_dim, intermediate_dim, workspace, workspace_bytes,
2069}
int moe_swiglu_shared_forward_q4k_q6k_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)

References ck_moe_shared_q4k_parallel_workspace(), and moe_swiglu_shared_forward_q4k_q6k_workspace().

◆ moe_swiglu_shared_forward_q4k_q6k_workspace()

int moe_swiglu_shared_forward_q4k_q6k_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 1185 of file axpy_kernels.c.

1197{
1198 const size_t required = moe_swiglu_expert_q4k_q5k_workspace_bytes(
1199 hidden_dim, intermediate_dim);
1200 if (!hidden || !shared_gate || !shared_up || !shared_down || !output ||
1201 !workspace || required == 0 || workspace_bytes < required || rows <= 0) {
1202 return -1;
1203 }
1204
1205 const size_t hidden_q8_bytes = ck_moe_align64(
1206 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
1207 const size_t gate_up_bytes = ck_moe_align64(
1208 2u * (size_t)intermediate_dim * sizeof(float));
1209 const size_t act_q8_bytes = ck_moe_align64(
1210 ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)intermediate_dim));
1211 uint8_t *cursor = (uint8_t *)workspace;
1212 void *hidden_q8 = cursor;
1213 cursor += hidden_q8_bytes;
1214 float *gate_up = (float *)cursor;
1215 cursor += gate_up_bytes;
1216 void *act_q8 = cursor;
1217 cursor += act_q8_bytes;
1218 float *shared_output = (float *)cursor;
1219
1220 for (int row = 0; row < rows; ++row) {
1221 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
1222 float *y = output + (size_t)row * (size_t)hidden_dim;
1223 quantize_row_q8_k(x, hidden_q8, hidden_dim);
1224 gemv_q4_k_q8_k(gate_up, shared_gate, hidden_q8,
1225 intermediate_dim, hidden_dim);
1226 gemv_q4_k_q8_k(gate_up + intermediate_dim, shared_up, hidden_q8,
1227 intermediate_dim, hidden_dim);
1228 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
1229 quantize_row_q8_k(gate_up, act_q8, intermediate_dim);
1230 gemv_q6_k_q8_k(shared_output, shared_down, act_q8,
1231 hidden_dim, intermediate_dim);
1232 const float *route = routed
1233 ? routed + (size_t)row * (size_t)hidden_dim
1234 : NULL;
1235 for (int col = 0; col < hidden_dim; ++col) {
1236 y[col] = shared_output[col] + (route ? route[col] : 0.0f);
1237 }
1238 }
1239 return 0;
1240}

References CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), gemv_q4_k_q8_k(), gemv_q6_k_q8_k(), moe_swiglu_expert_q4k_q5k_workspace_bytes(), quantize_row_q8_k(), and swiglu_forward_ggml().

Referenced by moe_swiglu_shared_forward_q4k_q6k_parallel_workspace().

◆ moe_swiglu_shared_forward_q4k_q8_0_gated_parallel_workspace()

int moe_swiglu_shared_forward_q4k_q8_0_gated_parallel_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
const float *  shared_gate_input,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 3002 of file axpy_kernels.c.

3015{
3016 /* Gate/up use the output-parallel pairwise Q4_K provider. Do not wrap
3017 * that provider in a second dispatch on the same persistent pool. */
3019 hidden, routed, shared_gate, shared_up, shared_down, shared_gate_input,
3020 output, rows, hidden_dim, intermediate_dim, workspace, workspace_bytes);
3021}
int moe_swiglu_shared_forward_q4k_q8_0_gated_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)

References moe_swiglu_shared_forward_q4k_q8_0_gated_workspace().

◆ moe_swiglu_shared_forward_q4k_q8_0_gated_workspace()

int moe_swiglu_shared_forward_q4k_q8_0_gated_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
const float *  shared_gate_input,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2839 of file axpy_kernels.c.

2845{
2847 hidden, routed, shared_gate, shared_up, shared_down, shared_gate_input,
2848 output, rows, hidden_dim, intermediate_dim, workspace, workspace_bytes,
2850}

References ck_moe_shared_q4k_gated_workspace(), and gemv_q8_0_q8_0().

Referenced by moe_swiglu_shared_forward_q4k_q8_0_gated_parallel_workspace().

◆ moe_swiglu_shared_forward_q8_0_gated_parallel_workspace()

int moe_swiglu_shared_forward_q8_0_gated_parallel_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
const float *  shared_gate_input,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2981 of file axpy_kernels.c.

2994{
2996 hidden, routed, shared_gate, shared_up, shared_down, shared_gate_input,
2997 output, rows, hidden_dim, intermediate_dim, workspace, workspace_bytes,
2998 moe_swiglu_shared_q8_0_gated_workspace_bytes(hidden_dim, intermediate_dim),
3000}
int moe_swiglu_shared_forward_q8_0_gated_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes)
static int ck_moe_shared_gated_parallel_workspace(const float *hidden, const float *routed, const void *shared_gate, const void *shared_up, const void *shared_down, const float *shared_gate_input, float *output, int rows, int hidden_dim, int intermediate_dim, void *workspace, size_t workspace_bytes, size_t stride, ck_moe_shared_gated_workspace_fn serial_fn)
size_t moe_swiglu_shared_q8_0_gated_workspace_bytes(int hidden_dim, int intermediate_dim)

References ck_moe_shared_gated_parallel_workspace(), moe_swiglu_shared_forward_q8_0_gated_workspace(), and moe_swiglu_shared_q8_0_gated_workspace_bytes().

◆ moe_swiglu_shared_forward_q8_0_gated_workspace()

int moe_swiglu_shared_forward_q8_0_gated_workspace ( const float *  hidden,
const float *  routed,
const void *  shared_gate,
const void *  shared_up,
const void *  shared_down,
const float *  shared_gate_input,
float *  output,
int  rows,
int  hidden_dim,
int  intermediate_dim,
void *  workspace,
size_t  workspace_bytes 
)

Definition at line 2666 of file axpy_kernels.c.

2679{
2680 const size_t required = moe_swiglu_shared_q8_0_gated_workspace_bytes(
2681 hidden_dim, intermediate_dim);
2682 if (!hidden || !shared_gate || !shared_up || !shared_down ||
2683 !shared_gate_input || !output || !workspace || required == 0 ||
2684 workspace_bytes < required || rows <= 0) {
2685 return -1;
2686 }
2687
2688 const size_t hidden_q8_bytes = ck_moe_align64(
2689 ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)hidden_dim));
2690 const size_t gate_up_bytes = ck_moe_align64(
2691 2u * (size_t)intermediate_dim * sizeof(float));
2692 const size_t activation_q8_bytes = ck_moe_align64(
2693 ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim));
2694 uint8_t *cursor = (uint8_t *)workspace;
2695 void *hidden_q8 = cursor;
2696 cursor += hidden_q8_bytes;
2697 float *gate_up = (float *)cursor;
2698 cursor += gate_up_bytes;
2699 void *activation_q8 = cursor;
2700 cursor += activation_q8_bytes;
2701 float *shared_output = (float *)cursor;
2702
2703 for (int row = 0; row < rows; ++row) {
2704 const float *x = hidden + (size_t)row * (size_t)hidden_dim;
2705 const float *routed_row = routed
2706 ? routed + (size_t)row * (size_t)hidden_dim
2707 : NULL;
2708 float *output_row = output + (size_t)row * (size_t)hidden_dim;
2709
2710 quantize_row_q8_0(x, hidden_q8, hidden_dim);
2711 gemv_q8_0_q8_0(gate_up, shared_gate, hidden_q8,
2712 intermediate_dim, hidden_dim);
2713 gemv_q8_0_q8_0(gate_up + intermediate_dim, shared_up, hidden_q8,
2714 intermediate_dim, hidden_dim);
2715 swiglu_forward_ggml(gate_up, gate_up, 1, intermediate_dim);
2716 quantize_row_q8_0(gate_up, activation_q8, intermediate_dim);
2717 gemv_q8_0_q8_0(shared_output, shared_down, activation_q8,
2718 hidden_dim, intermediate_dim);
2719
2720 float gate_value = 0.0f;
2722 x, shared_gate_input, NULL, &gate_value, 1, 1, hidden_dim);
2723 const float gate_scale = 1.0f / (1.0f + expf(-gate_value));
2724 for (int h = 0; h < hidden_dim; ++h) {
2725 const float routed_value = routed_row ? routed_row[h] : 0.0f;
2726 volatile float gated_shared = shared_output[h] * gate_scale;
2727 output_row[h] = routed_value + gated_shared;
2728 }
2729 }
2730 return 0;
2731}
void gemm_nt_f32_llama_production(const float *A, const float *B, const float *bias, float *C, int M, int N, int K)

References CK_DT_Q8_0, ck_dtype_row_bytes(), ck_moe_align64(), gemm_nt_f32_llama_production(), gemv_q8_0_q8_0(), moe_swiglu_shared_q8_0_gated_workspace_bytes(), quantize_row_q8_0(), and swiglu_forward_ggml().

Referenced by moe_swiglu_shared_forward_q8_0_gated_parallel_workspace().

◆ moe_swiglu_shared_q4k_q8_0_gated_workspace_bytes()

size_t moe_swiglu_shared_q4k_q8_0_gated_workspace_bytes ( int  hidden_dim,
int  intermediate_dim 
)

Definition at line 761 of file axpy_kernels.c.

763{
764 enum { batch_rows = 4 };
765 if (hidden_dim <= 0 || intermediate_dim <= 0 ||
766 hidden_dim % 256 != 0 || intermediate_dim % QK8_0 != 0) {
767 return 0;
768 }
769
770 size_t bytes = ck_moe_align64(
771 batch_rows * ck_dtype_row_bytes(CK_DT_Q8_K, (size_t)hidden_dim));
772 bytes += 2u * ck_moe_align64(
773 batch_rows * (size_t)intermediate_dim * sizeof(float));
774 bytes += ck_moe_align64(
775 batch_rows * ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim));
776 bytes += ck_moe_align64(
777 batch_rows * (size_t)hidden_dim * sizeof(float));
778 return bytes;
779}

References CK_DT_Q8_0, CK_DT_Q8_K, ck_dtype_row_bytes(), ck_moe_align64(), and QK8_0.

Referenced by ck_moe_shared_q4k_gated_workspace().

◆ moe_swiglu_shared_q8_0_gated_workspace_bytes()

size_t moe_swiglu_shared_q8_0_gated_workspace_bytes ( int  hidden_dim,
int  intermediate_dim 
)

Definition at line 2649 of file axpy_kernels.c.

2651{
2652 if (hidden_dim <= 0 || intermediate_dim <= 0 ||
2653 hidden_dim % 32 != 0 || intermediate_dim % 32 != 0) {
2654 return 0;
2655 }
2656
2657 size_t bytes = ck_moe_align64(
2658 ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)hidden_dim));
2659 bytes += ck_moe_align64(2u * (size_t)intermediate_dim * sizeof(float));
2660 bytes += ck_moe_align64(
2661 ck_dtype_row_bytes(CK_DT_Q8_0, (size_t)intermediate_dim));
2662 bytes += ck_moe_align64((size_t)hidden_dim * sizeof(float));
2663 return bytes;
2664}

References CK_DT_Q8_0, ck_dtype_row_bytes(), and ck_moe_align64().

Referenced by moe_swiglu_shared_forward_q8_0_gated_parallel_workspace(), and moe_swiglu_shared_forward_q8_0_gated_workspace().

◆ mrope_qk_imrope_positions()

void mrope_qk_imrope_positions ( float *  q,
float *  k,
const int32_t *  positions,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2776 of file rope_kernels.c.

2796{
2797 if (!q || !k || !positions || num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
2798 return;
2799 }
2800
2801 const int sections[4] = {section_0, section_1, section_2, section_3};
2802
2804 const int q_ok = explicit_mrope_apply_ggml_exact(
2805 q, positions, num_heads, num_tokens, head_dim, aligned_head_dim, n_dims, sections,
2806 n_ctx_orig, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow, GGML_ROPE_TYPE_IMROPE);
2807 const int k_ok = explicit_mrope_apply_ggml_exact(
2808 k, positions, num_kv_heads, num_tokens, head_dim, aligned_head_dim, n_dims, sections,
2809 n_ctx_orig, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow, GGML_ROPE_TYPE_IMROPE);
2810 if (q_ok && k_ok) {
2811 return;
2812 }
2813 }
2814
2815 const size_t q_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2816 const size_t k_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2817
2818 for (int h = 0; h < num_heads; ++h) {
2820 q + (size_t) h * q_head_stride,
2821 positions,
2822 num_tokens,
2823 head_dim,
2824 aligned_head_dim,
2825 n_dims,
2826 sections,
2827 n_ctx_orig,
2828 freq_base,
2829 freq_scale,
2830 ext_factor,
2831 attn_factor,
2832 beta_fast,
2833 beta_slow,
2834 1
2835 );
2836 }
2837
2838 for (int h = 0; h < num_kv_heads; ++h) {
2840 k + (size_t) h * k_head_stride,
2841 positions,
2842 num_tokens,
2843 head_dim,
2844 aligned_head_dim,
2845 n_dims,
2846 sections,
2847 n_ctx_orig,
2848 freq_base,
2849 freq_scale,
2850 ext_factor,
2851 attn_factor,
2852 beta_fast,
2853 beta_slow,
2854 1
2855 );
2856 }
2857}
#define GGML_ROPE_TYPE_IMROPE
static int explicit_mrope_apply_ggml_exact(float *x, const int32_t *positions, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, const int sections[4], int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow, int rope_type)
static void explicit_mrope_apply_head(float *x, const int32_t *positions, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, const int sections[4], int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow, int is_imrope)

References ck_strict_parity_enabled(), explicit_mrope_apply_ggml_exact(), explicit_mrope_apply_head(), and GGML_ROPE_TYPE_IMROPE.

◆ mrope_qk_text()

void mrope_qk_text ( float *  q,
float *  k,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2293 of file rope_kernels.c.

2313{
2314 if (!q || !k || num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
2315 return;
2316 }
2317
2318 const int sections[4] = {section_0, section_1, section_2, section_3};
2319 const size_t q_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2320 const size_t k_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2321
2322 for (int h = 0; h < num_heads; ++h) {
2324 q + (size_t) h * q_head_stride,
2325 num_tokens,
2326 head_dim,
2327 aligned_head_dim,
2328 pos_offset,
2329 n_dims,
2330 sections,
2331 n_ctx_orig,
2332 freq_base,
2333 freq_scale,
2334 ext_factor,
2335 attn_factor,
2336 beta_fast,
2337 beta_slow,
2338 0
2339 );
2340 }
2341
2342 for (int h = 0; h < num_kv_heads; ++h) {
2344 k + (size_t) h * k_head_stride,
2345 num_tokens,
2346 head_dim,
2347 aligned_head_dim,
2348 pos_offset,
2349 n_dims,
2350 sections,
2351 n_ctx_orig,
2352 freq_base,
2353 freq_scale,
2354 ext_factor,
2355 attn_factor,
2356 beta_fast,
2357 beta_slow,
2358 0
2359 );
2360 }
2361}
static void text_mrope_apply_head(float *x, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int n_dims, const int sections[4], int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow, int is_imrope)

References text_mrope_apply_head().

◆ mrope_qk_text_imrope()

void mrope_qk_text_imrope ( float *  q,
float *  k,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2363 of file rope_kernels.c.

2383{
2384 if (!q || !k || num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
2385 return;
2386 }
2387
2388 const int sections[4] = {section_0, section_1, section_2, section_3};
2389 const size_t q_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2390 const size_t k_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2391
2392 for (int h = 0; h < num_heads; ++h) {
2394 q + (size_t) h * q_head_stride,
2395 num_tokens,
2396 head_dim,
2397 aligned_head_dim,
2398 pos_offset,
2399 n_dims,
2400 sections,
2401 n_ctx_orig,
2402 freq_base,
2403 freq_scale,
2404 ext_factor,
2405 attn_factor,
2406 beta_fast,
2407 beta_slow,
2408 1
2409 );
2410 }
2411
2412 for (int h = 0; h < num_kv_heads; ++h) {
2414 k + (size_t) h * k_head_stride,
2415 num_tokens,
2416 head_dim,
2417 aligned_head_dim,
2418 pos_offset,
2419 n_dims,
2420 sections,
2421 n_ctx_orig,
2422 freq_base,
2423 freq_scale,
2424 ext_factor,
2425 attn_factor,
2426 beta_fast,
2427 beta_slow,
2428 1
2429 );
2430 }
2431}

References text_mrope_apply_head().

◆ mrope_qk_text_imrope_bf16_pytorch_storage()

void mrope_qk_text_imrope_bf16_pytorch_storage ( float *  q,
float *  k,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2586 of file rope_kernels.c.

2606{
2607 (void)section_0;
2608 (void)section_1;
2609 (void)section_2;
2610 (void)section_3;
2611 (void)n_ctx_orig;
2612 (void)ext_factor;
2613 (void)attn_factor;
2614 (void)beta_fast;
2615 (void)beta_slow;
2616 text_mrope_apply_pytorch_bf16_storage(q, num_heads, num_tokens, head_dim,
2617 aligned_head_dim, pos_offset, n_dims,
2618 freq_base, freq_scale);
2619 text_mrope_apply_pytorch_bf16_storage(k, num_kv_heads, num_tokens, head_dim,
2620 aligned_head_dim, pos_offset, n_dims,
2621 freq_base, freq_scale);
2622}
static void text_mrope_apply_pytorch_bf16_storage(float *x, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int n_dims, float freq_base, float freq_scale)

References text_mrope_apply_pytorch_bf16_storage().

◆ mrope_qk_text_imrope_positions_bf16_pytorch_storage()

void mrope_qk_text_imrope_positions_bf16_pytorch_storage ( float *  q,
float *  k,
const int32_t *  positions,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2550 of file rope_kernels.c.

2571{
2572 (void)n_ctx_orig;
2573 (void)ext_factor;
2574 (void)attn_factor;
2575 (void)beta_fast;
2576 (void)beta_slow;
2577 const int sections[4] = {section_0, section_1, section_2, section_3};
2579 q, positions, num_heads, num_tokens, head_dim, aligned_head_dim, n_dims,
2580 sections, freq_base, freq_scale);
2582 k, positions, num_kv_heads, num_tokens, head_dim, aligned_head_dim, n_dims,
2583 sections, freq_base, freq_scale);
2584}
static void text_mrope_apply_positions_pytorch_bf16_storage(float *x, const int32_t *positions, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, const int sections[4], float freq_base, float freq_scale)

References text_mrope_apply_positions_pytorch_bf16_storage().

◆ mrope_qk_vision()

void mrope_qk_vision ( float *  q,
float *  k,
const int32_t *  positions,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2624 of file rope_kernels.c.

2644{
2645 if (!q || !k || !positions || num_heads <= 0 || num_kv_heads <= 0 || num_tokens <= 0) {
2646 return;
2647 }
2648
2649 const int sections[4] = {section_0, section_1, section_2, section_3};
2650
2653 q, positions, num_heads, num_tokens, head_dim, aligned_head_dim, n_dims, sections,
2654 n_ctx_orig, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow, GGML_ROPE_TYPE_VISION) &&
2656 k, positions, num_kv_heads, num_tokens, head_dim, aligned_head_dim, n_dims, sections,
2657 n_ctx_orig, freq_base, freq_scale, ext_factor, attn_factor, beta_fast, beta_slow, GGML_ROPE_TYPE_VISION)) {
2658 return;
2659 }
2660 }
2661
2662 const size_t q_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2663 const size_t k_head_stride = (size_t) num_tokens * (size_t) aligned_head_dim;
2664
2665 for (int h = 0; h < num_heads; ++h) {
2667 q + (size_t) h * q_head_stride,
2668 positions,
2669 num_tokens,
2670 head_dim,
2671 aligned_head_dim,
2672 n_dims,
2673 sections,
2674 n_ctx_orig,
2675 freq_base,
2676 freq_scale,
2677 ext_factor,
2678 attn_factor,
2679 beta_fast,
2680 beta_slow
2681 );
2682 }
2683
2684 for (int h = 0; h < num_kv_heads; ++h) {
2686 k + (size_t) h * k_head_stride,
2687 positions,
2688 num_tokens,
2689 head_dim,
2690 aligned_head_dim,
2691 n_dims,
2692 sections,
2693 n_ctx_orig,
2694 freq_base,
2695 freq_scale,
2696 ext_factor,
2697 attn_factor,
2698 beta_fast,
2699 beta_slow
2700 );
2701 }
2702}
#define GGML_ROPE_TYPE_VISION
static void vision_mrope_apply_head(float *x, const int32_t *positions, int num_tokens, int head_dim, int aligned_head_dim, int n_dims, const int sections[4], int n_ctx_orig, float freq_base, float freq_scale, float ext_factor, float attn_factor, float beta_fast, float beta_slow)

References ck_strict_parity_enabled(), explicit_mrope_apply_ggml_exact(), GGML_ROPE_TYPE_VISION, and vision_mrope_apply_head().

◆ mrope_qk_vision_bf16_pytorch_storage()

void mrope_qk_vision_bf16_pytorch_storage ( float *  q,
float *  k,
const int32_t *  positions,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

◆ mrope_qk_vision_bf16_storage()

void mrope_qk_vision_bf16_storage ( float *  q,
float *  k,
const int32_t *  positions,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2735 of file rope_kernels.c.

◆ mrope_qk_vision_fp16_storage()

void mrope_qk_vision_fp16_storage ( float *  q,
float *  k,
const int32_t *  positions,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  n_dims,
int  section_0,
int  section_1,
int  section_2,
int  section_3,
int  n_ctx_orig,
float  freq_base,
float  freq_scale,
float  ext_factor,
float  attn_factor,
float  beta_fast,
float  beta_slow 
)

Definition at line 2736 of file rope_kernels.c.

◆ nemotron_group_limited_topk_router_f32()

void nemotron_group_limited_topk_router_f32 ( const float *  scores,
const float *  correction_bias,
int *  indices,
float *  weights,
int  rows,
int  n_experts,
int  top_k,
int  n_group,
int  topk_group,
int  norm_topk_prob,
float  routed_scaling_factor 
)

Definition at line 780 of file topk_kernels.c.

791{
793 scores, correction_bias, indices, weights, rows, n_experts, top_k,
794 n_group, topk_group, norm_topk_prob, routed_scaling_factor, 0
795 );
796}

References group_limited_topk_router_f32_impl().

◆ patch2im()

void patch2im ( const float *  d_patches,
float *  d_image,
int  C,
int  H,
int  W,
int  P 
)

patch2im: Accumulates gradients from patches back into the image. (Backward pass)

d_patches: [num_patches, C * P * P] d_image: [C, H, W] (Accumulated)

Definition at line 123 of file vision_kernels.c.

126{
127 int num_patches_h = H / P;
128 int num_patches_w = W / P;
129 int patch_dim = C * P * P;
130
131 // Zero out the image first as we are accumulating gradients
132 memset(d_image, 0, (size_t)C * H * W * sizeof(float));
133
134 for (int ph = 0; ph < num_patches_h; ++ph) {
135 for (int pw = 0; pw < num_patches_w; ++pw) {
136
137 int patch_idx = ph * num_patches_w + pw;
138 const float *src_patch = d_patches + (size_t)patch_idx * patch_dim;
139
140 for (int c = 0; c < C; ++c) {
141 for (int py = 0; py < P; ++py) {
142 int y = ph * P + py;
143 int x = pw * P;
144
145 float *dst_row = d_image + (size_t)c * H * W + (size_t)y * W + x;
146 const float *src_row = src_patch + (size_t)c * P * P + (size_t)py * P;
147
148 // Add the patch gradient to the image gradient
149 for (int px = 0; px < P; ++px) {
150 dst_row[px] += src_row[px];
151 }
152 }
153 }
154 }
155 }
156}

References C.

◆ patch2im_bf16()

void patch2im_bf16 ( const uint16_t *  d_patches,
uint16_t *  d_image,
int  C,
int  H,
int  W,
int  P 
)

Definition at line 57 of file vision_kernels_bf16.c.

63{
64 if (!d_patches || !d_image || C <= 0 || H <= 0 || W <= 0 || P <= 0) {
65 return;
66 }
67
68 int num_patches_h = H / P;
69 int num_patches_w = W / P;
70 int patch_dim = C * P * P;
71
72 memset(d_image, 0, (size_t)C * (size_t)H * (size_t)W * sizeof(uint16_t));
73
74 for (int ph = 0; ph < num_patches_h; ++ph) {
75 for (int pw = 0; pw < num_patches_w; ++pw) {
76 int patch_idx = ph * num_patches_w + pw;
77 const uint16_t *src_patch = d_patches + (size_t)patch_idx * (size_t)patch_dim;
78
79 for (int c = 0; c < C; ++c) {
80 for (int py = 0; py < P; ++py) {
81 int y = ph * P + py;
82 int x = pw * P;
83
84 uint16_t *dst_row = d_image + (size_t)c * (size_t)H * (size_t)W + (size_t)y * (size_t)W + (size_t)x;
85 const uint16_t *src_row = src_patch + (size_t)c * (size_t)P * (size_t)P + (size_t)py * (size_t)P;
86
87 for (int px = 0; px < P; ++px) {
88 float acc = bf16_to_float(dst_row[px]) + bf16_to_float(src_row[px]);
89 dst_row[px] = float_to_bf16(acc);
90 }
91 }
92 }
93 }
94 }
95}

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

◆ patch_projection_bf16_pytorch_onednn_conv3d_storage()

void patch_projection_bf16_pytorch_onednn_conv3d_storage ( const float *  input,
const void *  weights,
const float *  bias,
float *  output,
int  batch,
int  out_channels,
int  in_channels,
int  temporal,
int  patch_h,
int  patch_w 
)

Definition at line 1633 of file gemm_kernels_bf16.c.

1637{
1638#ifdef USE_ONEDNN
1639 if (!input || !weights || !bias || !output || batch <= 0 ||
1640 out_channels <= 0 || in_channels <= 0 || temporal <= 0 ||
1641 patch_h <= 0 || patch_w <= 0) {
1642 ck_pytorch_brgemm_fault("invalid Conv3D patch contract", batch,
1643 out_channels, in_channels * temporal * patch_h * patch_w);
1644 }
1645 pthread_once(&ck_pytorch_brgemm_once, ck_pytorch_brgemm_init);
1646 if (ck_pytorch_brgemm_init_status != 0) {
1647 ck_pytorch_brgemm_fault("could not initialize oneDNN Conv3D", batch,
1648 out_channels, in_channels * temporal * patch_h * patch_w);
1649 }
1650 ck_pytorch_brgemm_require_version(
1651 3, 7, 1, "8d263e693366ef8db40acc569cc7d8edf644556d",
1652 "patch_projection_bf16_pytorch_onednn_conv3d_storage",
1653 batch, out_channels, in_channels * temporal * patch_h * patch_w);
1654
1655 const size_t input_count = (size_t)batch * (size_t)in_channels *
1656 (size_t)temporal * (size_t)patch_h * (size_t)patch_w;
1657 const size_t output_count = (size_t)batch * (size_t)out_channels;
1658 uint16_t *input_bf16 = (uint16_t *)malloc(input_count * sizeof(*input_bf16));
1659 uint16_t *bias_bf16 = (uint16_t *)malloc((size_t)out_channels * sizeof(*bias_bf16));
1660 uint16_t *output_bf16 = (uint16_t *)malloc(output_count * sizeof(*output_bf16));
1661 if (!input_bf16 || !bias_bf16 || !output_bf16) {
1662 free(output_bf16);
1663 free(bias_bf16);
1664 free(input_bf16);
1665 ck_pytorch_brgemm_fault("Conv3D workspace allocation failed", batch,
1666 out_channels, in_channels * temporal * patch_h * patch_w);
1667 }
1668 for (size_t i = 0; i < input_count; ++i) input_bf16[i] = float_to_bf16(input[i]);
1669 for (int i = 0; i < out_channels; ++i) bias_bf16[i] = float_to_bf16(bias[i]);
1670
1671 dnnl_dims_t src_dims = {batch, in_channels, temporal, patch_h, patch_w};
1672 dnnl_dims_t weight_dims = {
1673 out_channels, in_channels, temporal, patch_h, patch_w};
1674 dnnl_dims_t bias_dims = {out_channels};
1675 dnnl_dims_t dst_dims = {batch, out_channels, 1, 1, 1};
1676 dnnl_dims_t strides = {temporal, patch_h, patch_w};
1677 dnnl_dims_t dilates = {0, 0, 0};
1678 dnnl_dims_t padding = {0, 0, 0};
1679
1680 dnnl_memory_desc_t user_src_md = NULL, user_weight_md = NULL;
1681 dnnl_memory_desc_t bias_md = NULL, user_dst_md = NULL;
1682 dnnl_memory_desc_t any_src_md = NULL, any_weight_md = NULL, any_dst_md = NULL;
1683 dnnl_primitive_desc_t conv_pd = NULL;
1684 dnnl_primitive_t conv = NULL;
1685 dnnl_primitive_desc_t reorder_pd = NULL;
1686 dnnl_primitive_t reorder = NULL;
1687 dnnl_exec_arg_t reorder_args[2];
1688 dnnl_memory_t user_src = NULL, user_weight = NULL, bias_mem = NULL, user_dst = NULL;
1689 dnnl_memory_t conv_src = NULL, conv_weight = NULL, conv_dst = NULL;
1690 dnnl_status_t status = dnnl_success;
1691
1692#define CK_DNNL_CONV(call) do { status = (call); if (status != dnnl_success) goto cleanup_conv; } while (0)
1693 pthread_mutex_lock(&ck_pytorch_brgemm_lock);
1694 CK_DNNL_CONV(dnnl_memory_desc_create_with_tag(
1695 &user_src_md, 5, src_dims, dnnl_bf16, dnnl_ncdhw));
1696 CK_DNNL_CONV(dnnl_memory_desc_create_with_tag(
1697 &user_weight_md, 5, weight_dims, dnnl_bf16, dnnl_oidhw));
1698 CK_DNNL_CONV(dnnl_memory_desc_create_with_tag(
1699 &bias_md, 1, bias_dims, dnnl_bf16, dnnl_x));
1700 CK_DNNL_CONV(dnnl_memory_desc_create_with_tag(
1701 &user_dst_md, 5, dst_dims, dnnl_bf16, dnnl_ncdhw));
1702 CK_DNNL_CONV(dnnl_memory_desc_create_with_tag(
1703 &any_src_md, 5, src_dims, dnnl_bf16, dnnl_format_tag_any));
1704 CK_DNNL_CONV(dnnl_memory_desc_create_with_tag(
1705 &any_weight_md, 5, weight_dims, dnnl_bf16, dnnl_format_tag_any));
1706 CK_DNNL_CONV(dnnl_memory_desc_create_with_tag(
1707 &any_dst_md, 5, dst_dims, dnnl_bf16, dnnl_format_tag_any));
1708 CK_DNNL_CONV(dnnl_convolution_forward_primitive_desc_create(
1709 &conv_pd, ck_pytorch_brgemm_engine, dnnl_forward_training,
1710 dnnl_convolution_direct, any_src_md, any_weight_md, bias_md, any_dst_md,
1711 strides, dilates, padding, padding, NULL));
1712
1713 const_dnnl_memory_desc_t conv_src_md =
1714 dnnl_primitive_desc_query_md(conv_pd, dnnl_query_src_md, 0);
1715 const_dnnl_memory_desc_t conv_weight_md =
1716 dnnl_primitive_desc_query_md(conv_pd, dnnl_query_weights_md, 0);
1717 const_dnnl_memory_desc_t conv_dst_md =
1718 dnnl_primitive_desc_query_md(conv_pd, dnnl_query_dst_md, 0);
1719 CK_DNNL_CONV(dnnl_memory_create(
1720 &user_src, user_src_md, ck_pytorch_brgemm_engine, input_bf16));
1721 CK_DNNL_CONV(dnnl_memory_create(
1722 &user_weight, user_weight_md, ck_pytorch_brgemm_engine, (void *)weights));
1723 CK_DNNL_CONV(dnnl_memory_create(
1724 &bias_mem, bias_md, ck_pytorch_brgemm_engine, bias_bf16));
1725 CK_DNNL_CONV(dnnl_memory_create(
1726 &user_dst, user_dst_md, ck_pytorch_brgemm_engine, output_bf16));
1727 CK_DNNL_CONV(dnnl_memory_create(
1728 &conv_src, conv_src_md, ck_pytorch_brgemm_engine, DNNL_MEMORY_ALLOCATE));
1729 CK_DNNL_CONV(dnnl_memory_create(
1730 &conv_weight, conv_weight_md, ck_pytorch_brgemm_engine, DNNL_MEMORY_ALLOCATE));
1731 CK_DNNL_CONV(dnnl_memory_create(
1732 &conv_dst, conv_dst_md, ck_pytorch_brgemm_engine, DNNL_MEMORY_ALLOCATE));
1733
1734 CK_DNNL_CONV(dnnl_reorder_primitive_desc_create(
1735 &reorder_pd, user_src_md, ck_pytorch_brgemm_engine,
1736 conv_src_md, ck_pytorch_brgemm_engine, NULL));
1737 CK_DNNL_CONV(dnnl_primitive_create(&reorder, reorder_pd));
1738 reorder_args[0] = (dnnl_exec_arg_t){DNNL_ARG_FROM, user_src};
1739 reorder_args[1] = (dnnl_exec_arg_t){DNNL_ARG_TO, conv_src};
1740 CK_DNNL_CONV(dnnl_primitive_execute(
1741 reorder, ck_pytorch_brgemm_stream, 2, reorder_args));
1742 dnnl_primitive_destroy(reorder); reorder = NULL;
1743 dnnl_primitive_desc_destroy(reorder_pd); reorder_pd = NULL;
1744
1745 CK_DNNL_CONV(dnnl_reorder_primitive_desc_create(
1746 &reorder_pd, user_weight_md, ck_pytorch_brgemm_engine,
1747 conv_weight_md, ck_pytorch_brgemm_engine, NULL));
1748 CK_DNNL_CONV(dnnl_primitive_create(&reorder, reorder_pd));
1749 reorder_args[0] = (dnnl_exec_arg_t){DNNL_ARG_FROM, user_weight};
1750 reorder_args[1] = (dnnl_exec_arg_t){DNNL_ARG_TO, conv_weight};
1751 CK_DNNL_CONV(dnnl_primitive_execute(
1752 reorder, ck_pytorch_brgemm_stream, 2, reorder_args));
1753 dnnl_primitive_destroy(reorder); reorder = NULL;
1754 dnnl_primitive_desc_destroy(reorder_pd); reorder_pd = NULL;
1755
1756 CK_DNNL_CONV(dnnl_primitive_create(&conv, conv_pd));
1757 dnnl_exec_arg_t conv_args[] = {
1758 {DNNL_ARG_SRC, conv_src},
1759 {DNNL_ARG_WEIGHTS, conv_weight},
1760 {DNNL_ARG_BIAS, bias_mem},
1761 {DNNL_ARG_DST, conv_dst},
1762 };
1763 CK_DNNL_CONV(dnnl_primitive_execute(
1764 conv, ck_pytorch_brgemm_stream,
1765 (int)(sizeof(conv_args) / sizeof(conv_args[0])), conv_args));
1766
1767 CK_DNNL_CONV(dnnl_reorder_primitive_desc_create(
1768 &reorder_pd, conv_dst_md, ck_pytorch_brgemm_engine,
1769 user_dst_md, ck_pytorch_brgemm_engine, NULL));
1770 CK_DNNL_CONV(dnnl_primitive_create(&reorder, reorder_pd));
1771 reorder_args[0] = (dnnl_exec_arg_t){DNNL_ARG_FROM, conv_dst};
1772 reorder_args[1] = (dnnl_exec_arg_t){DNNL_ARG_TO, user_dst};
1773 CK_DNNL_CONV(dnnl_primitive_execute(
1774 reorder, ck_pytorch_brgemm_stream, 2, reorder_args));
1775 CK_DNNL_CONV(dnnl_stream_wait(ck_pytorch_brgemm_stream));
1776
1777cleanup_conv:
1778 if (reorder) dnnl_primitive_destroy(reorder);
1779 if (reorder_pd) dnnl_primitive_desc_destroy(reorder_pd);
1780 if (conv) dnnl_primitive_destroy(conv);
1781 if (conv_dst) dnnl_memory_destroy(conv_dst);
1782 if (conv_weight) dnnl_memory_destroy(conv_weight);
1783 if (conv_src) dnnl_memory_destroy(conv_src);
1784 if (user_dst) dnnl_memory_destroy(user_dst);
1785 if (bias_mem) dnnl_memory_destroy(bias_mem);
1786 if (user_weight) dnnl_memory_destroy(user_weight);
1787 if (user_src) dnnl_memory_destroy(user_src);
1788 if (conv_pd) dnnl_primitive_desc_destroy(conv_pd);
1789 if (any_dst_md) dnnl_memory_desc_destroy(any_dst_md);
1790 if (any_weight_md) dnnl_memory_desc_destroy(any_weight_md);
1791 if (any_src_md) dnnl_memory_desc_destroy(any_src_md);
1792 if (user_dst_md) dnnl_memory_desc_destroy(user_dst_md);
1793 if (bias_md) dnnl_memory_desc_destroy(bias_md);
1794 if (user_weight_md) dnnl_memory_desc_destroy(user_weight_md);
1795 if (user_src_md) dnnl_memory_desc_destroy(user_src_md);
1796 pthread_mutex_unlock(&ck_pytorch_brgemm_lock);
1797#undef CK_DNNL_CONV
1798
1799 if (status != dnnl_success) {
1800 free(output_bf16);
1801 free(bias_bf16);
1802 free(input_bf16);
1803 ck_pytorch_brgemm_fault("oneDNN Conv3D execution failed", batch,
1804 out_channels, in_channels * temporal * patch_h * patch_w);
1805 }
1806 for (size_t i = 0; i < output_count; ++i) output[i] = bf16_to_float(output_bf16[i]);
1807 free(output_bf16);
1808 free(bias_bf16);
1809 free(input_bf16);
1810#else
1811 (void)input; (void)weights; (void)bias; (void)output; (void)batch;
1812 (void)out_channels; (void)in_channels; (void)temporal; (void)patch_h; (void)patch_w;
1813 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: PyTorch oneDNN BF16 Conv3D "
1814 "was selected without USE_ONEDNN=1\n");
1815 abort();
1816#endif
1817}
static void ck_pytorch_brgemm_fault(const char *message, int M, int N, int K)

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

Referenced by patch_projection_image_bf16_pytorch_onednn_conv3d_storage().

◆ patch_projection_image_bf16_native_storage()

void patch_projection_image_bf16_native_storage ( const float *  image,
const void *  weights_t0,
const void *  weights_t1,
const float *  bias,
float *  output,
int  channels,
int  image_h,
int  image_w,
int  patch_size,
int  out_channels,
int  merge_size 
)

Definition at line 2009 of file gemm_kernels_bf16.c.

2013{
2014 if (!image || !weights_t0 || !weights_t1 || !output || channels <= 0 ||
2015 image_h <= 0 || image_w <= 0 || patch_size <= 0 || out_channels <= 0 ||
2016 merge_size <= 0 || image_h % patch_size != 0 ||
2017 image_w % patch_size != 0) {
2018 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid native BF16 image patch projection\n");
2019 abort();
2020 }
2021 const int grid_h = image_h / patch_size;
2022 const int grid_w = image_w / patch_size;
2023 if (grid_h % merge_size != 0 || grid_w % merge_size != 0) {
2024 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: native BF16 patch grid is not merge aligned\n");
2025 abort();
2026 }
2027 ck_patch_projection_bf16_native_args_t args = {
2028 .image = image,
2029 .weights_t0 = (const uint16_t *)weights_t0,
2030 .weights_t1 = (const uint16_t *)weights_t1,
2031 .bias = bias,
2032 .output = output,
2033 .channels = channels,
2034 .image_h = image_h,
2035 .image_w = image_w,
2036 .patch_size = patch_size,
2037 .out_channels = out_channels,
2038 .merge_size = merge_size,
2039 .grid_w = grid_w,
2040 .batch = grid_h * grid_w,
2041 };
2042 ck_threadpool_t *pool = ck_threadpool_global();
2043 int active = pool ? ck_threadpool_n_threads(pool) : 1;
2044 if (active > args.batch) active = args.batch;
2045 if (active > 24) active = 24;
2046 if (pool && active > 1) {
2048 pool, active, ck_patch_projection_bf16_native_work, &args);
2049 } else {
2051 }
2052}
static void ck_patch_projection_bf16_native_work(int ith, int nth, void *opaque)

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

◆ patch_projection_image_bf16_pytorch_onednn_conv3d_storage()

void patch_projection_image_bf16_pytorch_onednn_conv3d_storage ( const float *  image,
const void *  weights_t0,
const void *  weights_t1,
const float *  bias,
float *  output,
int  channels,
int  image_h,
int  image_w,
int  patch_size,
int  out_channels,
int  merge_size 
)

Definition at line 1819 of file gemm_kernels_bf16.c.

1823{
1824#ifdef USE_ONEDNN
1825 if (!image || !weights_t0 || !weights_t1 || !bias || !output ||
1826 channels <= 0 || image_h <= 0 || image_w <= 0 || patch_size <= 0 ||
1827 out_channels <= 0 || merge_size <= 0 || image_h % patch_size != 0 ||
1828 image_w % patch_size != 0) {
1829 ck_pytorch_brgemm_fault("invalid image patch projection contract",
1830 image_h, image_w, patch_size);
1831 }
1832 const int grid_h = image_h / patch_size;
1833 const int grid_w = image_w / patch_size;
1834 if (grid_h % merge_size != 0 || grid_w % merge_size != 0) {
1835 ck_pytorch_brgemm_fault("patch grid is not merge-tile aligned",
1836 grid_h, grid_w, merge_size);
1837 }
1838 const int batch = grid_h * grid_w;
1839 const int temporal = 2;
1840 const int half_k = channels * patch_size * patch_size;
1841 const int full_k = temporal * half_k;
1842 float *patches = (float *)malloc((size_t)batch * (size_t)full_k * sizeof(*patches));
1843 uint16_t *weights = (uint16_t *)malloc(
1844 (size_t)out_channels * (size_t)full_k * sizeof(*weights));
1845 if (!patches || !weights) {
1846 free(weights);
1847 free(patches);
1848 ck_pytorch_brgemm_fault("image patch projection workspace allocation failed",
1849 batch, out_channels, full_k);
1850 }
1851
1852 for (int tok = 0; tok < batch; ++tok) {
1853 const int tiles_per_row = grid_w / merge_size;
1854 const int tile_area = merge_size * merge_size;
1855 const int tile = tok / tile_area;
1856 const int within = tok % tile_area;
1857 const int patch_y = (tile / tiles_per_row) * merge_size + within / merge_size;
1858 const int patch_x = (tile % tiles_per_row) * merge_size + within % merge_size;
1859 float *dst = patches + (size_t)tok * (size_t)full_k;
1860 for (int c = 0; c < channels; ++c) {
1861 for (int t = 0; t < temporal; ++t) {
1862 for (int py = 0; py < patch_size; ++py) {
1863 const float *src = image +
1864 ((size_t)c * (size_t)image_h +
1865 (size_t)(patch_y * patch_size + py)) * (size_t)image_w +
1866 (size_t)(patch_x * patch_size);
1867 memcpy(dst, src, (size_t)patch_size * sizeof(*dst));
1868 dst += patch_size;
1869 }
1870 }
1871 }
1872 }
1873
1874 const uint16_t *w0 = (const uint16_t *)weights_t0;
1875 const uint16_t *w1 = (const uint16_t *)weights_t1;
1876 for (int n = 0; n < out_channels; ++n) {
1877 uint16_t *dst = weights + (size_t)n * (size_t)full_k;
1878 for (int c = 0; c < channels; ++c) {
1879 const size_t channel_offset =
1880 (size_t)n * (size_t)half_k +
1881 (size_t)c * (size_t)patch_size * (size_t)patch_size;
1882 const size_t plane_bytes =
1883 (size_t)patch_size * (size_t)patch_size * sizeof(*dst);
1884 memcpy(dst, w0 + channel_offset, plane_bytes);
1885 dst += patch_size * patch_size;
1886 memcpy(dst, w1 + channel_offset, plane_bytes);
1887 dst += patch_size * patch_size;
1888 }
1889 }
1890
1892 patches, weights, bias, output, batch, out_channels, channels,
1893 temporal, patch_size, patch_size);
1894 free(weights);
1895 free(patches);
1896#else
1897 (void)image; (void)weights_t0; (void)weights_t1; (void)bias; (void)output;
1898 (void)channels; (void)image_h; (void)image_w; (void)patch_size;
1899 (void)out_channels; (void)merge_size;
1900 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: PyTorch oneDNN BF16 image "
1901 "patch projection was selected without USE_ONEDNN=1\n");
1902 abort();
1903#endif
1904}
void patch_projection_bf16_pytorch_onednn_conv3d_storage(const float *input, const void *weights, const float *bias, float *output, int batch, int out_channels, int in_channels, int temporal, int patch_h, int patch_w)

References ck_pytorch_brgemm_fault(), and patch_projection_bf16_pytorch_onednn_conv3d_storage().

◆ position_embeddings_add()

void position_embeddings_add ( float *  x,
const float *  position_embd,
int  num_tokens,
int  embed_dim,
int  num_positions 
)

Add learned absolute position embeddings in-place.

x layout: [num_tokens, embed_dim] position_embd: [num_positions, embed_dim]

This first v8 vision path intentionally assumes native resized embeddings are already materialized in the weight tensor, so token i maps directly to position_embd[i]. This is the correct contract for fixed-size bring-up.

Definition at line 168 of file vision_kernels.c.

173{
174 if (x == NULL || position_embd == NULL || num_tokens <= 0 || embed_dim <= 0) {
175 return;
176 }
177 const int limit = num_tokens < num_positions ? num_tokens : num_positions;
178 for (int tok = 0; tok < limit; ++tok) {
179 float *dst = x + (size_t)tok * embed_dim;
180 const float *src = position_embd + (size_t)tok * embed_dim;
181 for (int d = 0; d < embed_dim; ++d) {
182 dst[d] += src[d];
183 }
184 }
185}

◆ position_embeddings_add_at_offset()

void position_embeddings_add_at_offset ( float *  x,
const float *  position_embd,
int  num_tokens,
int  embed_dim,
int  num_positions,
int  start_position 
)

Definition at line 187 of file vision_kernels.c.

193{
194 if (x == NULL || position_embd == NULL || num_tokens <= 0 || embed_dim <= 0 ||
195 num_positions <= 0 || start_position < 0 || start_position >= num_positions) {
196 return;
197 }
198 const int available = num_positions - start_position;
199 const int limit = num_tokens < available ? num_tokens : available;
200 for (int tok = 0; tok < limit; ++tok) {
201 float *dst = x + (size_t)tok * embed_dim;
202 const float *src = position_embd + (size_t)(start_position + tok) * embed_dim;
203 for (int d = 0; d < embed_dim; ++d) {
204 dst[d] += src[d];
205 }
206 }
207}

◆ position_embeddings_add_gemma4v_xy()

void position_embeddings_add_gemma4v_xy ( float *  x,
const float *  position_embd,
int  grid_h,
int  grid_w,
int  embed_dim,
int  source_grid_size 
)

Definition at line 209 of file vision_kernels.c.

215{
216 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0) {
217 return;
218 }
219 if (source_grid_size <= 0) {
220 source_grid_size = grid_w > grid_h ? grid_w : grid_h;
221 }
222
223 const size_t table_stride = (size_t) source_grid_size * (size_t) embed_dim;
224 const float *table_x = position_embd;
225 const float *table_y = position_embd + table_stride;
226
227 for (int y = 0; y < grid_h; ++y) {
228 const int yy = y < source_grid_size ? y : (source_grid_size - 1);
229 const float *row_y = table_y + (size_t) yy * (size_t) embed_dim;
230 for (int x_pos = 0; x_pos < grid_w; ++x_pos) {
231 const int xx = x_pos < source_grid_size ? x_pos : (source_grid_size - 1);
232 const float *row_x = table_x + (size_t) xx * (size_t) embed_dim;
233 float *dst = x + ((size_t) y * (size_t) grid_w + (size_t) x_pos) * (size_t) embed_dim;
234 for (int d = 0; d < embed_dim; ++d) {
235 dst[d] += row_x[d] + row_y[d];
236 }
237 }
238 }
239}

◆ position_embeddings_add_tiled_2d()

void position_embeddings_add_tiled_2d ( float *  x,
const float *  position_embd,
int  grid_h,
int  grid_w,
int  embed_dim,
int  merge_size,
int  source_grid_size 
)

Definition at line 248 of file vision_kernels.c.

255{
256 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
257 return;
258 }
259
260 if (source_grid_size <= 0) {
261 source_grid_size = grid_h == grid_w ? grid_h : (grid_h > grid_w ? grid_h : grid_w);
262 }
263
264 const int num_tokens = grid_h * grid_w;
265 const int source_tokens = source_grid_size * source_grid_size;
266 const int needs_resize = source_grid_size != grid_h || source_grid_size != grid_w;
267
268 if (!needs_resize) {
269 for (int tok = 0; tok < num_tokens; ++tok) {
270 const int flat = tile_order_index_2d(tok, grid_h, grid_w, merge_size);
271 if (flat < 0 || flat >= source_tokens) {
272 continue;
273 }
274 float *dst = x + (size_t) tok * (size_t) embed_dim;
275 const float *src = position_embd + (size_t) flat * (size_t) embed_dim;
276 for (int d = 0; d < embed_dim; ++d) {
277 dst[d] += src[d];
278 }
279 }
280 return;
281 }
282
283 const float sf_x = (float) grid_w / (float) source_grid_size;
284 const float sf_y = (float) grid_h / (float) source_grid_size;
285 const float pixel_offset = 0.5f;
286 const float support_x = fmaxf(1.0f, 1.0f / sf_x);
287 const float support_y = fmaxf(1.0f, 1.0f / sf_y);
288 const float invscale_x = 1.0f / support_x;
289 const float invscale_y = 1.0f / support_y;
290
291 /* Preserve ggml's channel -> row -> column loop nesting. The destination
292 * index converts the row-major interpolation result directly to CK's
293 * merge-tiled token layout without allocating an intermediate tensor. */
294 for (int d = 0; d < embed_dim; ++d) {
295 for (int dst_y = 0; dst_y < grid_h; ++dst_y) {
296 const float y_src = ((float) dst_y + pixel_offset) / sf_y;
297 int y_min = (int) (y_src - support_y + pixel_offset);
298 int y_max = (int) (y_src + support_y + pixel_offset);
299 if (y_min < 0) y_min = 0;
300 if (y_max > source_grid_size) y_max = source_grid_size;
301
302 for (int dst_x = 0; dst_x < grid_w; ++dst_x) {
303 const float x_src = ((float) dst_x + pixel_offset) / sf_x;
304 int x_min = (int) (x_src - support_x + pixel_offset);
305 int x_max = (int) (x_src + support_x + pixel_offset);
306 if (x_min < 0) x_min = 0;
307 if (x_max > source_grid_size) x_max = source_grid_size;
308 float val = 0.0f;
309 float total_weight = 0.0f;
310 for (int sy = y_min; sy < y_max; ++sy) {
311 const float wy_arg = ((float) sy - y_src + pixel_offset) * invscale_y;
312 const float wy = fmaxf(1.0f - fabsf(wy_arg), 0.0f);
313 if (wy <= 0.0f) {
314 continue;
315 }
316 for (int sx = x_min; sx < x_max; ++sx) {
317 const float wx_arg = ((float) sx - x_src + pixel_offset) * invscale_x;
318 const float wx = fmaxf(1.0f - fabsf(wx_arg), 0.0f);
319 const float weight = wx * wy;
320 if (weight <= 0.0f) {
321 continue;
322 }
323 const float sample = position_embd[((size_t) sy * (size_t) source_grid_size + (size_t) sx) * (size_t) embed_dim + (size_t) d];
324 val = fmaf(sample, weight, val);
325 total_weight += weight;
326 }
327 }
328 if (total_weight > 0.0f) {
329 val /= total_weight;
330 const int tok = tile_order_linear_index_2d(
331 dst_y, dst_x, grid_h, grid_w, merge_size);
332 x[(size_t) tok * (size_t) embed_dim + (size_t) d] += val;
333 }
334 }
335 }
336 }
337}
static int tile_order_linear_index_2d(int y, int x, int grid_h, int grid_w, int merge_size)

References tile_order_index_2d(), and tile_order_linear_index_2d().

◆ position_embeddings_add_tiled_2d_align_corners()

void position_embeddings_add_tiled_2d_align_corners ( float *  x,
const float *  position_embd,
int  grid_h,
int  grid_w,
int  embed_dim,
int  merge_size,
int  source_grid_size 
)

Definition at line 342 of file vision_kernels.c.

349{
350 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 ||
351 embed_dim <= 0 || merge_size <= 0 || source_grid_size <= 0) {
352 return;
353 }
354
355 const float y_scale = grid_h > 1
356 ? (float)(source_grid_size - 1) / (float)(grid_h - 1)
357 : 0.0f;
358 const float x_scale = grid_w > 1
359 ? (float)(source_grid_size - 1) / (float)(grid_w - 1)
360 : 0.0f;
361
362 for (int tok = 0; tok < grid_h * grid_w; ++tok) {
363 const int row_major = tile_order_index_2d(tok, grid_h, grid_w, merge_size);
364 const int dst_y = row_major / grid_w;
365 const int dst_x = row_major % grid_w;
366 const float src_y = (float)dst_y * y_scale;
367 const float src_x = (float)dst_x * x_scale;
368 const int y0 = (int)src_y;
369 const int x0 = (int)src_x;
370 const int y1 = y0 + 1 < source_grid_size ? y0 + 1 : y0;
371 const int x1 = x0 + 1 < source_grid_size ? x0 + 1 : x0;
372 const float dy = src_y - (float)y0;
373 const float dx = src_x - (float)x0;
374 const float w00 = (1.0f - dy) * (1.0f - dx);
375 const float w01 = (1.0f - dy) * dx;
376 const float w10 = dy * (1.0f - dx);
377 const float w11 = dy * dx;
378 const float *p00 = position_embd + ((size_t)y0 * source_grid_size + x0) * embed_dim;
379 const float *p01 = position_embd + ((size_t)y0 * source_grid_size + x1) * embed_dim;
380 const float *p10 = position_embd + ((size_t)y1 * source_grid_size + x0) * embed_dim;
381 const float *p11 = position_embd + ((size_t)y1 * source_grid_size + x1) * embed_dim;
382 float *dst = x + (size_t)tok * embed_dim;
383
384 for (int d = 0; d < embed_dim; ++d) {
385 const float pos = p00[d] * w00 + p01[d] * w01 + p10[d] * w10 + p11[d] * w11;
386 dst[d] += pos;
387 }
388 }
389}

References tile_order_index_2d().

◆ position_embeddings_add_tiled_2d_align_corners_bf16()

void position_embeddings_add_tiled_2d_align_corners_bf16 ( float *  x,
const float *  position_embd,
int  grid_h,
int  grid_w,
int  embed_dim,
int  merge_size,
int  source_grid_size 
)

Definition at line 397 of file vision_kernels.c.

404{
405 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 ||
406 embed_dim <= 0 || merge_size <= 0 || source_grid_size <= 0) {
407 return;
408 }
409
410 for (int tok = 0; tok < grid_h * grid_w; ++tok) {
411 const int row_major = tile_order_index_2d(tok, grid_h, grid_w, merge_size);
412 const int dst_y = row_major / grid_w;
413 const int dst_x = row_major % grid_w;
414 /* torch.linspace computes each rational coordinate before FP32 storage. */
415 const float src_y = grid_h > 1
416 ? (float)((double)dst_y * (double)(source_grid_size - 1) / (double)(grid_h - 1))
417 : 0.0f;
418 const float src_x = grid_w > 1
419 ? (float)((double)dst_x * (double)(source_grid_size - 1) / (double)(grid_w - 1))
420 : 0.0f;
421 const int y0 = (int)src_y;
422 const int x0 = (int)src_x;
423 const int y1 = y0 + 1 < source_grid_size ? y0 + 1 : y0;
424 const int x1 = x0 + 1 < source_grid_size ? x0 + 1 : x0;
425 const float dy = src_y - (float)y0;
426 const float dx = src_x - (float)x0;
427 const float w00 = bf16_to_float(float_to_bf16((1.0f - dy) * (1.0f - dx)));
428 const float w01 = bf16_to_float(float_to_bf16((1.0f - dy) * dx));
429 const float w10 = bf16_to_float(float_to_bf16(dy * (1.0f - dx)));
430 const float w11 = bf16_to_float(float_to_bf16(dy * dx));
431 const float *p00 = position_embd + ((size_t)y0 * source_grid_size + x0) * embed_dim;
432 const float *p01 = position_embd + ((size_t)y0 * source_grid_size + x1) * embed_dim;
433 const float *p10 = position_embd + ((size_t)y1 * source_grid_size + x0) * embed_dim;
434 const float *p11 = position_embd + ((size_t)y1 * source_grid_size + x1) * embed_dim;
435 float *dst = x + (size_t)tok * embed_dim;
436
437 for (int d = 0; d < embed_dim; ++d) {
438 const float v00 = bf16_to_float(float_to_bf16(p00[d] * w00));
439 const float v01 = bf16_to_float(float_to_bf16(p01[d] * w01));
440 const float v10 = bf16_to_float(float_to_bf16(p10[d] * w10));
441 const float v11 = bf16_to_float(float_to_bf16(p11[d] * w11));
442 float pos = bf16_to_float(float_to_bf16(v00 + v01));
443 pos = bf16_to_float(float_to_bf16(pos + v10));
444 pos = bf16_to_float(float_to_bf16(pos + v11));
445 const float hidden = bf16_to_float(float_to_bf16(dst[d]));
446 dst[d] = bf16_to_float(float_to_bf16(hidden + pos));
447 }
448 }
449}

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

◆ position_embeddings_add_tiled_2d_align_corners_fp32_interp_bf16()

void position_embeddings_add_tiled_2d_align_corners_fp32_interp_bf16 ( float *  x,
const float *  position_embd,
int  grid_h,
int  grid_w,
int  embed_dim,
int  merge_size,
int  source_grid_size 
)

Definition at line 458 of file vision_kernels.c.

466{
467 if (x == NULL || position_embd == NULL || grid_h <= 0 || grid_w <= 0 ||
468 embed_dim <= 0 || merge_size <= 0 || source_grid_size <= 0) {
469 return;
470 }
471
472 for (int tok = 0; tok < grid_h * grid_w; ++tok) {
473 const int row_major = tile_order_index_2d(tok, grid_h, grid_w, merge_size);
474 const int dst_y = row_major / grid_w;
475 const int dst_x = row_major % grid_w;
476 const float src_y = grid_h > 1
477 ? (float)dst_y * (float)(source_grid_size - 1) / (float)(grid_h - 1)
478 : 0.0f;
479 const float src_x = grid_w > 1
480 ? (float)dst_x * (float)(source_grid_size - 1) / (float)(grid_w - 1)
481 : 0.0f;
482 const int y0 = (int)src_y;
483 const int x0 = (int)src_x;
484 const int y1 = y0 + 1 < source_grid_size ? y0 + 1 : y0;
485 const int x1 = x0 + 1 < source_grid_size ? x0 + 1 : x0;
486 const float y_distance0 = fabsf(src_y - (float)y0);
487 const float y_distance1 = fabsf(src_y - (float)y0 - 1.0f);
488 const float x_distance0 = fabsf(src_x - (float)x0);
489 const float x_distance1 = fabsf(src_x - (float)x0 - 1.0f);
490 const float wy0 = fmaxf(1.0f - y_distance0, 0.0f);
491 const float wy1 = fmaxf(1.0f - y_distance1, 0.0f);
492 const float wx0 = fmaxf(1.0f - x_distance0, 0.0f);
493 const float wx1 = fmaxf(1.0f - x_distance1, 0.0f);
494 const float w00 = wy0 * wx0;
495 const float w01 = wy0 * wx1;
496 const float w10 = wy1 * wx0;
497 const float w11 = wy1 * wx1;
498 const float *p00 = position_embd + ((size_t)y0 * source_grid_size + x0) * embed_dim;
499 const float *p01 = position_embd + ((size_t)y0 * source_grid_size + x1) * embed_dim;
500 const float *p10 = position_embd + ((size_t)y1 * source_grid_size + x0) * embed_dim;
501 const float *p11 = position_embd + ((size_t)y1 * source_grid_size + x1) * embed_dim;
502 float *dst = x + (size_t)tok * embed_dim;
503
504 for (int d = 0; d < embed_dim; ++d) {
505 /* Materialize products before the reduction, as torch.sum does. */
506 volatile float v00 = p00[d] * w00;
507 volatile float v01 = p01[d] * w01;
508 volatile float v10 = p10[d] * w10;
509 volatile float v11 = p11[d] * w11;
510 volatile float pos01 = v00 + v01;
511 volatile float pos012 = pos01 + v10;
512 const float pos = pos012 + v11;
513 const float pos_bf16 = bf16_to_float(float_to_bf16(pos));
514 const float hidden = bf16_to_float(float_to_bf16(dst[d]));
515 dst[d] = bf16_to_float(float_to_bf16(hidden + pos_bf16));
516 }
517 }
518}

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

◆ q_norm_forward()

void q_norm_forward ( float *  q,
const float *  q_gamma,
int  num_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

Forward pass for Gemma4-assistant q-only per-head RMSNorm.

Some Gemma4 assistant/drafter checkpoints project only Q and then reuse Q as the shared K/V stream. This wrapper keeps that public kernel contract explicit while reusing the same row-wise RMSNorm implementation as qk_norm_forward.

Definition at line 434 of file qk_norm_kernels.c.

440{
441 rmsnorm_forward(q, q_gamma, q, NULL,
442 num_heads * num_tokens, head_dim, head_dim, eps);
443}
void rmsnorm_forward(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References rmsnorm_forward().

◆ qk_norm_backward()

void qk_norm_backward ( const float *  d_q_out,
const float *  d_k_out,
const float *  q_in,
const float *  k_in,
const float *  q_gamma,
const float *  k_gamma,
float *  d_q_in,
float *  d_k_in,
float *  d_q_gamma,
float *  d_k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

Backward pass for per-head QK RMSNorm.

This computes:

  • d_q / d_k for the Q and K activations
  • d_q_gamma / d_k_gamma for shared per-head gamma vectors

Implementation is reference-first and deterministic: 1) recompute row rstd values from saved q/k inputs 2) call rmsnorm_backward on flattened [rows, head_dim] views

Definition at line 456 of file qk_norm_kernels.c.

463{
464 int q_rows = num_heads * num_tokens;
465 int k_rows = num_kv_heads * num_tokens;
466
467 if (q_rows > 0) {
468 float q_rstd_cache[q_rows];
469 qk_norm_compute_rstd(q_in, q_rstd_cache, q_rows, head_dim, eps);
470 rmsnorm_backward(d_q_out, q_in, q_gamma, q_rstd_cache,
471 d_q_in, d_q_gamma, q_rows, head_dim, head_dim);
472 }
473
474 if (k_rows > 0) {
475 float k_rstd_cache[k_rows];
476 qk_norm_compute_rstd(k_in, k_rstd_cache, k_rows, head_dim, eps);
477 rmsnorm_backward(d_k_out, k_in, k_gamma, k_rstd_cache,
478 d_k_in, d_k_gamma, k_rows, head_dim, head_dim);
479 }
480}
static void qk_norm_compute_rstd(const float *input, float *rstd_cache, int rows, int head_dim, float eps)
void rmsnorm_backward(const float *d_output, const float *input, const float *gamma, const float *rstd_cache, float *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim)

References qk_norm_compute_rstd(), and rmsnorm_backward().

◆ qk_norm_backward_last_isa()

int qk_norm_backward_last_isa ( void  )

Definition at line 120 of file qk_norm_kernels.c.

121{
122 return g_qk_norm_last_isa;
123}
static int g_qk_norm_last_isa

References g_qk_norm_last_isa.

◆ qk_norm_forward()

void qk_norm_forward ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

Per-head RMSNorm on Q and K.

Parameters
qQ scratch buffer [num_heads * num_tokens * head_dim], in-place
kK scratch buffer [num_kv_heads * num_tokens * head_dim], in-place
q_gammaQ norm gamma weights [head_dim]
k_gammaK norm gamma weights [head_dim]
num_headsNumber of query heads (e.g. 32 for Qwen3-8B)
num_kv_headsNumber of KV heads (e.g. 8 for Qwen3-8B with GQA)
num_tokensNumber of tokens (1 for decode, T for prefill)
head_dimDimension per head (e.g. 128)
epsRMSNorm epsilon (e.g. 1e-6)
Test:
unittest/test_qk_norm.py

Definition at line 335 of file qk_norm_kernels.c.

339{
340 /* Q norm: [num_heads * num_tokens] rows of [head_dim]
341 * Each row is one head's vector for one token. */
342 rmsnorm_forward(q, q_gamma, q, NULL,
343 num_heads * num_tokens, head_dim, head_dim, eps);
344
345 /* K norm: [num_kv_heads * num_tokens] rows of [head_dim]
346 * Same logic, fewer rows when using GQA. */
347 rmsnorm_forward(k, k_gamma, k, NULL,
348 num_kv_heads * num_tokens, head_dim, head_dim, eps);
349}

References rmsnorm_forward().

◆ qk_norm_forward_decode_exact()

void qk_norm_forward_decode_exact ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

◆ qk_norm_forward_fp64_sum()

void qk_norm_forward_fp64_sum ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

Definition at line 351 of file qk_norm_kernels.c.

355{
356 rmsnorm_forward_fp64_sum(q, q_gamma, q, NULL,
357 num_heads * num_tokens, head_dim, head_dim, eps);
358 rmsnorm_forward_fp64_sum(k, k_gamma, k, NULL,
359 num_kv_heads * num_tokens, head_dim, head_dim, eps);
360}
void rmsnorm_forward_fp64_sum(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References rmsnorm_forward_fp64_sum().

◆ qk_norm_forward_llama_production()

void qk_norm_forward_llama_production ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

Definition at line 362 of file qk_norm_kernels.c.

366{
368 q, q_gamma, q, NULL,
369 num_heads * num_tokens, head_dim, head_dim, eps);
371 k, k_gamma, k, NULL,
372 num_kv_heads * num_tokens, head_dim, head_dim, eps);
373}
void rmsnorm_forward_llama_production(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References rmsnorm_forward_llama_production().

◆ qk_norm_forward_llama_production_parallel_dispatch()

void qk_norm_forward_llama_production_parallel_dispatch ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

◆ qk_norm_forward_muse_unweighted_scaled_pytorch_bf16_storage()

void qk_norm_forward_muse_unweighted_scaled_pytorch_bf16_storage ( float *  q,
float *  k,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps,
float  q_scale 
)

Definition at line 407 of file qk_norm_kernels.c.

416{
417 const int q_elements = num_heads * num_tokens * head_dim;
419 q, q, NULL, num_heads * num_tokens, head_dim, head_dim, eps);
421 k, k, NULL, num_kv_heads * num_tokens, head_dim, head_dim, eps);
422 for (int index = 0; index < q_elements; ++index) {
423 q[index] = bf16_to_float(float_to_bf16(q[index] * q_scale));
424 }
425}
void rmsnorm_forward_muse_unweighted_pytorch_bf16_storage(const float *input, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

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

◆ qk_norm_forward_parallel_dispatch()

void qk_norm_forward_parallel_dispatch ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

◆ qk_norm_forward_prefill_exact()

void qk_norm_forward_prefill_exact ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

◆ qk_norm_forward_pytorch_bf16_storage()

void qk_norm_forward_pytorch_bf16_storage ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

Definition at line 375 of file qk_norm_kernels.c.

381{
383 q, q_gamma, q, NULL,
384 num_heads * num_tokens, head_dim, head_dim, eps);
386 k, k_gamma, k, NULL,
387 num_kv_heads * num_tokens, head_dim, head_dim, eps);
388}
void rmsnorm_forward_pytorch_bf16_storage(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References rmsnorm_forward_pytorch_bf16_storage().

◆ qk_norm_forward_qwen4_pytorch_bf16_storage()

void qk_norm_forward_qwen4_pytorch_bf16_storage ( float *  q,
float *  k,
const float *  q_gamma,
const float *  k_gamma,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
float  eps 
)

Definition at line 390 of file qk_norm_kernels.c.

398{
400 q, q_gamma, q, NULL,
401 num_heads * num_tokens, head_dim, head_dim, eps);
403 k, k_gamma, k, NULL,
404 num_kv_heads * num_tokens, head_dim, head_dim, eps);
405}
void rmsnorm_forward_qwen3next_pytorch_bf16_storage(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References rmsnorm_forward_qwen3next_pytorch_bf16_storage().

◆ quantize_batch_q8_0()

void quantize_batch_q8_0 ( const float *  x,
void *  vy,
int  num_rows,
int  k 
)

Batch quantize FP32 to Q8_0 format (row-major output)

Quantizes multiple rows of FP32 data to Q8_0 format, placing each row's Q8_0 output at the correct byte offset for GEMM compatibility.

Memory layout: Input: [num_rows, k] FP32, row-major (stride = k * sizeof(float)) Output: [num_rows, q8_row_bytes] Q8_0, row-major (stride = q8_row_bytes)

where q8_row_bytes = (k / 32) * sizeof(block_q8_0) = (k / 32) * 34

Parameters
xInput FP32 values [num_rows * k]
vyOutput Q8_0 blocks [num_rows * (k/32) blocks]
num_rowsNumber of rows (batch size / tokens)
kElements per row (must be multiple of 32)

Definition at line 256 of file gemm_kernels_q8_0.c.

257{
258 const size_t row_bytes_in = (size_t)k * sizeof(float);
259 const size_t row_bytes_out = (size_t)(k / QK8_0) * sizeof(block_q8_0);
260
261 uint8_t *out = (uint8_t *)vy;
262 const uint8_t *in = (const uint8_t *)x;
263
264 for (int row = 0; row < num_rows; ++row) {
266 (const float *)(in + row * row_bytes_in),
267 (void *)(out + row * row_bytes_out),
268 k
269 );
270 }
271}
void quantize_row_q8_0(const float *x, void *vy, int k)
Quantize FP32 to Q8_0 format (scalar reference)

References QK8_0, and quantize_row_q8_0().

◆ quantize_batch_q8_k()

void quantize_batch_q8_k ( const float *  x,
void *  vy,
int  num_rows,
int  k 
)

Batch quantize FP32 to Q8_K format (row-major output)

Same as quantize_batch_q8_0 but for Q8_K format (super-blocks).

Parameters
xInput FP32 values [num_rows * k]
vyOutput Q8_K blocks
num_rowsNumber of rows (batch size / tokens)
kElements per row (must be multiple of 256)

Definition at line 283 of file gemm_kernels_q8_0.c.

284{
285 /* Q8_K: 256 elements per super-block, each block is larger */
286 const size_t row_bytes_in = (size_t)k * sizeof(float);
287 /* Q8_K block size = 2 (d) + 256 (qs) + 32 (bsums/2) = ~274 bytes for 256 elements */
288 /* Actual: sizeof(block_q8_K) from ckernel_quant.h */
289 const size_t row_bytes_out = (size_t)(k / 256) * sizeof(block_q8_K);
290
291 uint8_t *out = (uint8_t *)vy;
292 const uint8_t *in = (const uint8_t *)x;
293
294 for (int row = 0; row < num_rows; ++row) {
296 (const float *)(in + row * row_bytes_in),
297 (void *)(out + row * row_bytes_out),
298 k
299 );
300 }
301}
void quantize_row_q8_k(const float *x, void *vy, int k)

References quantize_row_q8_k().

◆ quantize_batch_q8_k_4row_nearest_even()

void quantize_batch_q8_k_4row_nearest_even ( const float *  x,
void *  y,
int  num_rows,
int  k 
)

Definition at line 270 of file gemm_kernels_q4k_q8k.c.

271 {
272 if (!x || !vy || num_rows <= 0 || k <= 0) {
273 return;
274 }
275 assert(k % QK_K == 0);
276
277 block_q8_K *y = (block_q8_K *)vy;
278 const int blocks_per_row = k / QK_K;
279
280 /* Q8_K bytes are a numerical ABI. The previous four-row AVX2 path used
281 * a different max/scale evaluation order and changed real Qwen3-VL
282 * visual-prefix scales by one FP32 ULP. Keep this public grouped ABI on
283 * the canonical row provider until an optimized implementation is
284 * byte-exact against llama.cpp on both synthetic and production inputs. */
285 for (int row = 0; row < num_rows; ++row) {
287 x + (size_t)row * (size_t)k,
288 y + (size_t)row * (size_t)blocks_per_row,
289 k);
290 }
291}
void quantize_row_q8_k(const float *x, void *vy, int k)

References QK_K, and quantize_row_q8_k().

◆ quantize_row_q8_0()

void quantize_row_q8_0 ( const float *  x,
void *  vy,
int  k 
)

Quantize FP32 to Q8_0 format (scalar reference)

Parameters
xInput FP32 values
vyOutput Q8_0 blocks
kNumber of elements (must be multiple of 32)

Definition at line 125 of file gemm_kernels_q8_0.c.

126{
127 block_q8_0 *y = (block_q8_0 *)vy;
128 const int nb = k / QK8_0; /* QK8_0 = 32 */
129
130#if defined(__AVX__)
131 const __m256 sign_bit = _mm256_set1_ps(-0.0f);
132
133 for (int i = 0; i < nb; i++) {
134 __m256 v0 = _mm256_loadu_ps(x + 0);
135 __m256 v1 = _mm256_loadu_ps(x + 8);
136 __m256 v2 = _mm256_loadu_ps(x + 16);
137 __m256 v3 = _mm256_loadu_ps(x + 24);
138 x += QK8_0;
139
140 __m256 max_abs = _mm256_andnot_ps(sign_bit, v0);
141 max_abs = _mm256_max_ps(max_abs, _mm256_andnot_ps(sign_bit, v1));
142 max_abs = _mm256_max_ps(max_abs, _mm256_andnot_ps(sign_bit, v2));
143 max_abs = _mm256_max_ps(max_abs, _mm256_andnot_ps(sign_bit, v3));
144
145 __m128 max4 = _mm_max_ps(_mm256_extractf128_ps(max_abs, 1),
146 _mm256_castps256_ps128(max_abs));
147 max4 = _mm_max_ps(max4, _mm_movehl_ps(max4, max4));
148 max4 = _mm_max_ss(max4, _mm_movehdup_ps(max4));
149 const float max_scalar = _mm_cvtss_f32(max4);
150
151#if defined(__INTEL_LLVM_COMPILER)
152 const float d = ck_q8_0_div_rounded_f32(max_scalar, 127.0f);
153 const float id = max_scalar != 0.0f
154 ? ck_q8_0_div_rounded_f32(127.0f, max_scalar)
155 : 0.0f;
156#else
157 const float d = max_scalar / 127.0f;
158 const float id = max_scalar != 0.0f ? 127.0f / max_scalar : 0.0f;
159#endif
160 y[i].d = CK_FP32_TO_FP16(d);
161
162 const __m256 mul = _mm256_set1_ps(id);
163 v0 = _mm256_mul_ps(v0, mul);
164 v1 = _mm256_mul_ps(v1, mul);
165 v2 = _mm256_mul_ps(v2, mul);
166 v3 = _mm256_mul_ps(v3, mul);
167
168 /* Match llama.cpp x86 Q8 quantization: nearest-even rounding. */
169 v0 = _mm256_round_ps(v0, _MM_ROUND_NEAREST);
170 v1 = _mm256_round_ps(v1, _MM_ROUND_NEAREST);
171 v2 = _mm256_round_ps(v2, _MM_ROUND_NEAREST);
172 v3 = _mm256_round_ps(v3, _MM_ROUND_NEAREST);
173
174 __m256i i0 = _mm256_cvtps_epi32(v0);
175 __m256i i1 = _mm256_cvtps_epi32(v1);
176 __m256i i2 = _mm256_cvtps_epi32(v2);
177 __m256i i3 = _mm256_cvtps_epi32(v3);
178
179#if defined(__AVX2__)
180 i0 = _mm256_packs_epi32(i0, i1);
181 i2 = _mm256_packs_epi32(i2, i3);
182 i0 = _mm256_packs_epi16(i0, i2);
183
184 const __m256i perm = _mm256_setr_epi32(0, 4, 1, 5, 2, 6, 3, 7);
185 i0 = _mm256_permutevar8x32_epi32(i0, perm);
186 _mm256_storeu_si256((__m256i *)y[i].qs, i0);
187#else
188 __m128i ni0 = _mm256_castsi256_si128(i0);
189 __m128i ni1 = _mm256_extractf128_si256(i0, 1);
190 __m128i ni2 = _mm256_castsi256_si128(i1);
191 __m128i ni3 = _mm256_extractf128_si256(i1, 1);
192 __m128i ni4 = _mm256_castsi256_si128(i2);
193 __m128i ni5 = _mm256_extractf128_si256(i2, 1);
194 __m128i ni6 = _mm256_castsi256_si128(i3);
195 __m128i ni7 = _mm256_extractf128_si256(i3, 1);
196
197 ni0 = _mm_packs_epi32(ni0, ni1);
198 ni2 = _mm_packs_epi32(ni2, ni3);
199 ni4 = _mm_packs_epi32(ni4, ni5);
200 ni6 = _mm_packs_epi32(ni6, ni7);
201
202 ni0 = _mm_packs_epi16(ni0, ni2);
203 ni4 = _mm_packs_epi16(ni4, ni6);
204
205 _mm_storeu_si128((__m128i *)(y[i].qs + 0), ni0);
206 _mm_storeu_si128((__m128i *)(y[i].qs + 16), ni4);
207#endif
208 }
209#else
210 for (int i = 0; i < nb; i++) {
211 const float *xb = x + i * QK8_0;
212
213 /* Find max absolute value in block */
214 float amax = 0.0f;
215 for (int j = 0; j < QK8_0; j++) {
216 float av = xb[j] >= 0 ? xb[j] : -xb[j];
217 if (av > amax) amax = av;
218 }
219
220 /* Compute scale: d = max / 127 */
221 float d = amax / 127.0f;
222 float id = d != 0.0f ? 127.0f / amax : 0.0f;
223
224 /* Store scale as FP16 */
225 y[i].d = CK_FP32_TO_FP16(d);
226
227 /* Quantize values */
228 for (int j = 0; j < QK8_0; j++) {
229 float v = xb[j] * id;
230 int q = ck_nearest_int_q8_0(v);
231 if (q > 127) q = 127;
232 if (q < -127) q = -127;
233 y[i].qs[j] = (int8_t)q;
234 }
235 }
236#endif
237}
static int ck_nearest_int_q8_0(float fval)
int32_t id
Definition tokenizer.h:316

References CK_FP32_TO_FP16, ck_nearest_int_q8_0(), block_q8_0::d, id, QK8_0, and block_q8_0::qs.

Referenced by ck_moe_q4k_mixed_route_work(), ck_moe_shared_q4k_gated_workspace(), ck_moe_swiglu_nvfp4_projection(), fused_mlp_swiglu_prefill_w1w2_quant(), fused_rmsnorm_qkv_prefill_head_major_quant(), gemm_nt_q8_0_q8_0_contract_m2(), gemv_q8_0_q8_0_contract(), hyper_connection_mix_quantized(), moe_swiglu_expert_forward_q4k_q5_0_workspace(), moe_swiglu_expert_forward_q4k_q8_0_workspace(), moe_swiglu_shared_forward_q8_0_gated_workspace(), quantize_attn_out_head_major_q8_0(), quantize_attn_out_head_major_q8_0(), and quantize_attn_out_head_major_q8_0().

◆ quantize_row_q8_k()

void quantize_row_q8_k ( const float *  x,
void *  y,
int  k 
)

Definition at line 229 of file gemm_kernels_q4k_q8k.c.

229 {
230 const char *ref_env = getenv("CK_DEBUG_Q8K_REF");
231 if (ref_env && atoi(ref_env) != 0) {
232 quantize_row_q8_k_ref(x, vy, k);
233 return;
234 }
235#if defined(__AVX512F__) && defined(__AVX512BW__)
236 quantize_row_q8_k_avx512(x, vy, k);
237#elif defined(__AVX2__)
238 quantize_row_q8_k_avx2(x, vy, k);
239#elif defined(__AVX__)
240 quantize_row_q8_k_avx(x, vy, k);
241#elif defined(__SSE4_1__)
242 quantize_row_q8_k_sse(x, vy, k);
243#elif defined(__ARM_NEON) || defined(__aarch64__)
244 quantize_row_q8_k_neon(x, vy, k);
245#else
246 quantize_row_q8_k_ref(x, vy, k);
247#endif
248}
void quantize_row_q8_k_avx512(const float *x, void *vy, int k)
void quantize_row_q8_k_avx2(const float *x, void *vy, int k)
void quantize_row_q8_k_avx(const float *x, void *vy, int k)
void quantize_row_q8_k_sse(const float *x, void *vy, int k)
void quantize_row_q8_k_ref(const float *x, void *vy, int k)

References quantize_row_q8_k_avx(), quantize_row_q8_k_avx2(), quantize_row_q8_k_avx512(), quantize_row_q8_k_ref(), and quantize_row_q8_k_sse().

Referenced by ck_attention_project_head_major_q4_k_q8_k(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), ck_mlp_swiglu_forward_q4_k_q8_k(), ck_mlp_swiglu_forward_q4_k_q8_k_prefill(), ck_moe_q4k_mixed_route_parallel(), ck_moe_q4k_mixed_route_work(), ck_moe_q4k_q5k_bucket_work(), ck_moe_q4k_q5k_quantize_work(), ck_moe_q4k_q5k_route_parallel(), ck_moe_q4k_q5k_route_work(), ck_moe_shared_q4k_gated_workspace(), ck_qkv_project_head_major_q4_k_q8_k(), decode_layer_parallel(), fused_mlp_swiglu_prefill_w1w2_quant(), fused_rmsnorm_qkv_prefill_head_major_quant(), hyper_connection_mix_quantized(), mlp_parallel(), model_decode_token(), model_decode_token(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_layer_0_decode(), model_layer_0_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_9_decode(), model_layer_9_decode(), moe_swiglu_expert_forward_q4k_q4k_workspace(), moe_swiglu_expert_forward_q4k_q5_0_workspace(), moe_swiglu_expert_forward_q4k_q5k_workspace(), moe_swiglu_expert_forward_q4k_q6k_workspace(), moe_swiglu_expert_forward_q4k_q8_0_workspace(), moe_swiglu_shared_forward_q4k_q4k_workspace(), moe_swiglu_shared_forward_q4k_q6k_workspace(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), 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(), qwen2_0_5b_decode_layer_9_decode(), swiglu_forward_q8_k(), and unfused_rmsnorm_linear_q4k_ref().

◆ qwen4_ple_gate_conv_inject_bf16()

void qwen4_ple_gate_conv_inject_bf16 ( const float *  hyper_input,
const float *  key_projected,
const float *  value_projected,
const float *  norm_key_weight,
const float *  norm_query_weight,
const float *  norm_conv_weight,
const uint16_t *  conv_weight,
float *  hyper_output,
float *  key_norm_scratch,
float *  query_norm_scratch,
float *  gated_scratch,
float *  conv_norm_scratch,
const float *  conv_state_in,
float *  conv_state_out,
int  rows,
int  streams,
int  hidden_dim,
int  kernel_size,
int  dilation,
float  eps 
)

Definition at line 402 of file qwen4_exp_kernels.c.

410 {
412 hyper_input, key_projected, value_projected, norm_key_weight,
413 norm_query_weight, norm_conv_weight, conv_weight, hyper_output,
414 key_norm_scratch, query_norm_scratch, gated_scratch, conv_norm_scratch,
415 conv_state_in, conv_state_out, rows, streams, hidden_dim, kernel_size,
416 dilation, eps, 0, 0);
417}
static void qwen4_ple_gate_conv_inject_impl(const float *hyper_input, const float *key_projected, const float *value_projected, const float *norm_key_weight, const float *norm_query_weight, const float *norm_conv_weight, const void *conv_weight, float *hyper_output, float *key_norm_scratch, float *query_norm_scratch, float *gated_scratch, float *conv_norm_scratch, const float *conv_state_in, float *conv_state_out, int rows, int streams, int hidden_dim, int kernel_size, int dilation, float eps, int conv_weight_is_fp16, int llama_fp32_arithmetic)

References qwen4_ple_gate_conv_inject_impl().

◆ qwen4_ple_gate_conv_inject_fp16()

void qwen4_ple_gate_conv_inject_fp16 ( const float *  hyper_input,
const float *  key_projected,
const float *  value_projected,
const float *  norm_key_weight,
const float *  norm_query_weight,
const float *  norm_conv_weight,
const uint16_t *  conv_weight,
float *  hyper_output,
float *  key_norm_scratch,
float *  query_norm_scratch,
float *  gated_scratch,
float *  conv_norm_scratch,
const float *  conv_state_in,
float *  conv_state_out,
int  rows,
int  streams,
int  hidden_dim,
int  kernel_size,
int  dilation,
float  eps 
)

Definition at line 419 of file qwen4_exp_kernels.c.

427 {
429 hyper_input, key_projected, value_projected, norm_key_weight,
430 norm_query_weight, norm_conv_weight, conv_weight, hyper_output,
431 key_norm_scratch, query_norm_scratch, gated_scratch, conv_norm_scratch,
432 conv_state_in, conv_state_out, rows, streams, hidden_dim, kernel_size,
433 dilation, eps, 1, 0);
434}

References qwen4_ple_gate_conv_inject_impl().

◆ qwen4_ple_gate_conv_inject_llama_fp16()

void qwen4_ple_gate_conv_inject_llama_fp16 ( const float *  hyper_input,
const float *  key_projected,
const float *  value_projected,
const float *  norm_key_weight,
const float *  norm_query_weight,
const float *  norm_conv_weight,
const uint16_t *  conv_weight,
float *  hyper_output,
float *  key_norm_scratch,
float *  query_norm_scratch,
float *  gated_scratch,
float *  conv_norm_scratch,
const float *  conv_state_in,
float *  conv_state_out,
int  rows,
int  streams,
int  hidden_dim,
int  kernel_size,
int  dilation,
float  eps 
)

Definition at line 436 of file qwen4_exp_kernels.c.

444 {
446 hyper_input, key_projected, value_projected, norm_key_weight,
447 norm_query_weight, norm_conv_weight, conv_weight, hyper_output,
448 key_norm_scratch, query_norm_scratch, gated_scratch, conv_norm_scratch,
449 conv_state_in, conv_state_out, rows, streams, hidden_dim, kernel_size,
450 dilation, eps, 1, 1);
451}

References qwen4_ple_gate_conv_inject_impl().

◆ qwen4_ple_ngram_embed_bf16()

void qwen4_ple_ngram_embed_bf16 ( const int32_t *  token_ids,
const uint16_t *  embedding,
const int64_t *  layer_multipliers,
const int64_t *  head_offsets,
const int64_t *  head_vocab_sizes,
float *  output,
const float *  token_state_in,
float *  token_state_out,
int  rows,
int  ngram_size,
int  heads_per_ngram,
int  head_dim,
int  eos_token_id,
int  position 
)

Definition at line 121 of file qwen4_exp_kernels.c.

134 {
136 token_ids, embedding, layer_multipliers, head_offsets,
137 head_vocab_sizes, output, token_state_in, token_state_out, rows,
138 ngram_size, heads_per_ngram, head_dim, eos_token_id, position_offset, 0);
139}
static void qwen4_ple_ngram_embed_impl(const int32_t *token_ids, const void *embedding, const int64_t *layer_multipliers, const int64_t *head_offsets, const int64_t *head_vocab_sizes, float *output, const float *token_state_in, float *token_state_out, int rows, int ngram_size, int heads_per_ngram, int head_dim, int eos_token_id, int position_offset, int embedding_is_q5_0)

References qwen4_ple_ngram_embed_impl().

◆ qwen4_ple_ngram_embed_q5_0()

void qwen4_ple_ngram_embed_q5_0 ( const int32_t *  token_ids,
const void *  embedding,
const int64_t *  layer_multipliers,
const int64_t *  head_offsets,
const int64_t *  head_vocab_sizes,
float *  output,
const float *  token_state_in,
float *  token_state_out,
int  rows,
int  ngram_size,
int  heads_per_ngram,
int  head_dim,
int  eos_token_id,
int  position 
)

Definition at line 141 of file qwen4_exp_kernels.c.

154 {
156 token_ids, embedding, layer_multipliers, head_offsets,
157 head_vocab_sizes, output, token_state_in, token_state_out, rows,
158 ngram_size, heads_per_ngram, head_dim, eos_token_id, position_offset, 1);
159}

References qwen4_ple_ngram_embed_impl().

◆ qwen4_qsa_index_select_bf16()

void qwen4_qsa_index_select_bf16 ( const float *  projected_qk,
const float *  index_key_cache_in,
const float *  q_norm_weight,
const float *  k_norm_weight,
float *  selected_indices,
float *  index_key_cache_out,
float *  q_norm_scratch,
float *  pooled_key_scratch,
float *  block_score_scratch,
int32_t *  block_index_scratch,
int  rows,
int  query_heads,
int  index_head_dim,
int  token_budget,
int  compress_ratio,
int  rotary_dim,
int  context_length,
int  position,
float  rope_theta,
float  eps 
)

Definition at line 488 of file qwen4_exp_kernels.c.

508 {
509 if (!projected_qk || !index_key_cache_in || !q_norm_weight || !k_norm_weight ||
510 !selected_indices || !index_key_cache_out || !q_norm_scratch ||
511 !pooled_key_scratch || !block_score_scratch || !block_index_scratch ||
512 rows <= 0 || query_heads <= 0 || index_head_dim <= 0 || token_budget <= 0 ||
513 compress_ratio <= 0 || rotary_dim <= 0 || rotary_dim > index_head_dim ||
514 context_length <= 0 || position < 0 || rows > context_length - position) return;
515
516 const int projected_dim = (query_heads + 1) * index_head_dim;
517 const int selection_width = token_budget + compress_ratio - 1;
518 const int block_topk = token_budget / compress_ratio;
519 if (index_key_cache_out != index_key_cache_in && position > 0) {
520 memcpy(index_key_cache_out, index_key_cache_in,
521 (size_t)position * index_head_dim * sizeof(*index_key_cache_out));
522 }
523
524 for (int row = 0; row < rows; ++row) {
525 const int absolute_position = position + row;
526 const float *projected = projected_qk + (size_t)row * projected_dim;
527 float *query_normed = q_norm_scratch;
528 qwen4_shared_head_rmsnorm(projected, q_norm_weight, query_normed,
529 query_heads, index_head_dim, eps);
530 for (int head = 0; head < query_heads; ++head) {
531 qwen4_rope_split_inplace(query_normed + (size_t)head * index_head_dim,
532 rotary_dim, absolute_position, rope_theta);
533 }
534 float *raw_key = index_key_cache_out + (size_t)absolute_position * index_head_dim;
535 const float *projected_key = projected + (size_t)query_heads * index_head_dim;
536 for (int col = 0; col < index_head_dim; ++col) {
537 raw_key[col] = qwen4_bf16_round(projected_key[col]);
538 }
539
540 float *selected_row = selected_indices + (size_t)row * selection_width;
541 for (int slot = 0; slot < selection_width; ++slot) selected_row[slot] = -1.0f;
542 const int visible = absolute_position + 1;
543 const int complete_blocks = visible / compress_ratio;
544 const int selected_blocks = complete_blocks < block_topk ? complete_blocks : block_topk;
545 for (int slot = 0; slot < selected_blocks; ++slot) {
546 block_score_scratch[slot] = -INFINITY;
547 block_index_scratch[slot] = -1;
548 }
549
550 for (int block = 0; block < complete_blocks; ++block) {
551 const int block_start = block * compress_ratio;
552 for (int col = 0; col < index_head_dim; ++col) {
553 float sum = 0.0f;
554 for (int token = 0; token < compress_ratio; ++token) {
555 sum += index_key_cache_out[
556 (size_t)(block_start + token) * index_head_dim + col];
557 }
558 pooled_key_scratch[col] = qwen4_bf16_round(sum / (float)compress_ratio);
559 }
560 qwen4_shared_head_rmsnorm(pooled_key_scratch, k_norm_weight,
561 pooled_key_scratch, 1, index_head_dim, eps);
562 qwen4_rope_split_inplace(pooled_key_scratch, rotary_dim, block_start, rope_theta);
563 float score = 0.0f;
564 for (int head = 0; head < query_heads; ++head) {
565 const float *query_head = query_normed + (size_t)head * index_head_dim;
566 float dot = 0.0f;
567 for (int col = 0; col < index_head_dim; ++col) {
568 dot += query_head[col] * pooled_key_scratch[col];
569 }
570 if (dot > 0.0f) score += dot;
571 }
572 score /= sqrtf((float)index_head_dim);
573 int target = -1;
574 for (int slot = 0; slot < selected_blocks; ++slot) {
575 if (target < 0 || block_score_scratch[slot] < block_score_scratch[target]) target = slot;
576 }
577 if (target >= 0 && score > block_score_scratch[target]) {
578 block_score_scratch[target] = score;
579 block_index_scratch[target] = block;
580 }
581 }
582
583 for (int outer = 1; outer < selected_blocks; ++outer) {
584 const int32_t value = block_index_scratch[outer];
585 int inner = outer - 1;
586 while (inner >= 0 && block_index_scratch[inner] > value) {
587 block_index_scratch[inner + 1] = block_index_scratch[inner];
588 --inner;
589 }
590 block_index_scratch[inner + 1] = value;
591 }
592 int output_count = 0;
593 for (int slot = 0; slot < selected_blocks; ++slot) {
594 const int block = block_index_scratch[slot];
595 if (block < 0) continue;
596 for (int token = 0; token < compress_ratio; ++token) {
597 selected_row[output_count++] = (float)(block * compress_ratio + token);
598 }
599 }
600 for (int token = complete_blocks * compress_ratio;
601 token < visible && output_count < selection_width; ++token) {
602 selected_row[output_count++] = (float)token;
603 }
604 }
605}
static float qwen4_bf16_round(float value)
static void qwen4_rope_split_inplace(float *vector, int rotary_dim, int position, float theta)
static void qwen4_shared_head_rmsnorm(const float *input, const float *weight, float *output, int heads, int head_dim, float eps)

References qwen4_bf16_round(), qwen4_rope_split_inplace(), qwen4_shared_head_rmsnorm(), score, and token.

◆ recurrent_conv_state_update_backward()

void recurrent_conv_state_update_backward ( const float *  d_conv_x,
const float *  d_state_out,
float *  d_state_in,
float *  d_q,
float *  d_k,
float *  d_v,
int  history_len,
int  num_seqs,
int  num_tokens,
int  q_dim,
int  k_dim,
int  v_dim 
)

Definition at line 257 of file recurrent_state_kernels.c.

268 {
269 int channels = 0;
270 int total_len = 0;
271 size_t elements = 0;
273 history_len, num_seqs, num_tokens, q_dim, k_dim, v_dim,
274 &channels, &total_len, &elements) ||
275 elements > SIZE_MAX / sizeof(float)) {
276 return;
277 }
278 (void)channels;
279 (void)total_len;
280 float *workspace = (float *)malloc(elements * sizeof(float));
281 if (!workspace) {
282 return;
283 }
285 d_conv_x, d_state_out, d_state_in, d_q, d_k, d_v, workspace,
286 history_len, num_seqs, num_tokens, q_dim, k_dim, v_dim);
287 free(workspace);
288}
static int recurrent_conv_backward_extents(int history_len, int num_seqs, int num_tokens, int q_dim, int k_dim, int v_dim, int *channels_out, int *total_len_out, size_t *elements_out)
void recurrent_conv_state_update_backward_workspace(const float *d_conv_x, const float *d_state_out, float *d_state_in, float *d_q, float *d_k, float *d_v, float *d_conv_total, int history_len, int num_seqs, int num_tokens, int q_dim, int k_dim, int v_dim)

References recurrent_conv_backward_extents(), and recurrent_conv_state_update_backward_workspace().

◆ recurrent_conv_state_update_backward_workspace()

void recurrent_conv_state_update_backward_workspace ( const float *  d_conv_x,
const float *  d_state_out,
float *  d_state_in,
float *  d_q,
float *  d_k,
float *  d_v,
float *  d_conv_total,
int  history_len,
int  num_seqs,
int  num_tokens,
int  q_dim,
int  k_dim,
int  v_dim 
)

Definition at line 188 of file recurrent_state_kernels.c.

200 {
201 int channels = 0;
202 int total_len = 0;
203 size_t elements = 0;
204 if (!d_conv_x || !d_state_out || !d_state_in || !d_q || !d_k || !d_v ||
205 !d_conv_total || !recurrent_conv_backward_extents(
206 history_len, num_seqs, num_tokens, q_dim, k_dim, v_dim,
207 &channels, &total_len, &elements)) {
208 return;
209 }
210 if (elements > SIZE_MAX / sizeof(float)) {
211 return;
212 }
213
214 memcpy(d_conv_total, d_conv_x, elements * sizeof(float));
215
216 for (int seq = 0; seq < num_seqs; ++seq) {
217 const float *d_state_out_seq = d_state_out + (size_t) seq * (size_t) channels * (size_t) history_len;
218 float *d_conv_seq = d_conv_total + (size_t) seq * (size_t) channels * (size_t) total_len;
219 for (int ch = 0; ch < channels; ++ch) {
220 float *dst = d_conv_seq + (size_t) ch * (size_t) total_len + (size_t) num_tokens;
221 const float *src = d_state_out_seq + (size_t) ch * (size_t) history_len;
222 for (int idx = 0; idx < history_len; ++idx) {
223 dst[idx] += src[idx];
224 }
225 }
226 }
227
228 for (int seq = 0; seq < num_seqs; ++seq) {
229 const float *d_conv_seq = d_conv_total + (size_t) seq * (size_t) channels * (size_t) total_len;
230 float *d_state_in_seq = d_state_in + (size_t) seq * (size_t) channels * (size_t) history_len;
231
232 for (int ch = 0; ch < channels; ++ch) {
233 memcpy(
234 d_state_in_seq + (size_t) ch * (size_t) history_len,
235 d_conv_seq + (size_t) ch * (size_t) total_len,
236 (size_t) history_len * sizeof(float));
237 }
238
239 for (int tok = 0; tok < num_tokens; ++tok) {
240 const int row = seq * num_tokens + tok;
241 float *d_q_row = d_q + (size_t) row * (size_t) q_dim;
242 float *d_k_row = d_k + (size_t) row * (size_t) k_dim;
243 float *d_v_row = d_v + (size_t) row * (size_t) v_dim;
244 for (int col = 0; col < q_dim; ++col) {
245 d_q_row[col] = d_conv_seq[(size_t) col * (size_t) total_len + (size_t) (history_len + tok)];
246 }
247 for (int col = 0; col < k_dim; ++col) {
248 d_k_row[col] = d_conv_seq[(size_t) (q_dim + col) * (size_t) total_len + (size_t) (history_len + tok)];
249 }
250 for (int col = 0; col < v_dim; ++col) {
251 d_v_row[col] = d_conv_seq[(size_t) (q_dim + k_dim + col) * (size_t) total_len + (size_t) (history_len + tok)];
252 }
253 }
254 }
255}

References recurrent_conv_backward_extents().

Referenced by recurrent_conv_state_update_backward().

◆ recurrent_conv_state_update_forward()

void recurrent_conv_state_update_forward ( const float *  state_in,
const float *  q,
const float *  k,
const float *  v,
float *  conv_x,
float *  state_out,
int  history_len,
int  num_seqs,
int  num_tokens,
int  q_dim,
int  k_dim,
int  v_dim 
)

Definition at line 100 of file recurrent_state_kernels.c.

111 {
112 if (!state_in || !q || !k || !v || !conv_x || !state_out ||
113 history_len < 0 || num_seqs <= 0 || num_tokens < 0 ||
114 q_dim < 0 || k_dim < 0 || v_dim < 0 ||
115 q_dim > INT_MAX - k_dim || q_dim + k_dim > INT_MAX - v_dim ||
116 history_len > INT_MAX - num_tokens) {
117 return;
118 }
119 const int channels = q_dim + k_dim + v_dim;
120 const int total_len = history_len + num_tokens;
121 if (channels <= 0 || total_len <= 0 || num_seqs > INT_MAX / channels ||
122 (num_tokens > 0 && num_seqs > INT_MAX / num_tokens)) {
123 return;
124 }
125
126 ck_recurrent_conv_state_args_t args = {
127 state_in, q, k, v, conv_x, state_out,
128 history_len, num_tokens, q_dim, k_dim, v_dim, channels, total_len,
129 };
130 const int jobs = num_seqs * channels;
131 const size_t elements = (size_t)jobs * (size_t)num_tokens;
132 const size_t minimum_elements_per_thread = 32768u;
133 if (num_tokens <= 1 || elements < 2u * minimum_elements_per_thread) {
135 return;
136 }
137
138 ck_threadpool_t *pool = ck_threadpool_global();
139 int active = pool ? ck_threadpool_n_threads(pool) : 1;
140 size_t useful_threads =
141 (elements + minimum_elements_per_thread - 1u) /
142 minimum_elements_per_thread;
143 if ((size_t)active > useful_threads) active = (int)useful_threads;
144 if (active > jobs) active = jobs;
145
146 if (active > 1 && ck_threadpool_thread_id(pool) <= 0) {
148 pool, active, 0, jobs, 32,
150 } else {
152 }
153}
static void ck_recurrent_conv_state_channel_range(int begin, int end, void *opaque)

References ck_recurrent_conv_state_channel_range(), ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), and ck_threadpool_thread_id().

◆ recurrent_dt_gate_backward()

void recurrent_dt_gate_backward ( const float *  d_gate,
const float *  alpha,
const float *  dt_bias,
const float *  a,
float *  d_alpha,
float *  d_dt_bias,
float *  d_a,
int  rows,
int  dim 
)

Definition at line 105 of file recurrent_gate_kernels.c.

113 {
114 for (int col = 0; col < dim; ++col) {
115 d_dt_bias[col] = 0.0f;
116 d_a[col] = 0.0f;
117 }
118
119 for (int row = 0; row < rows; ++row) {
120 const float *d_gate_row = d_gate + (size_t) row * (size_t) dim;
121 const float *alpha_row = alpha + (size_t) row * (size_t) dim;
122 float *d_alpha_row = d_alpha + (size_t) row * (size_t) dim;
123 for (int col = 0; col < dim; ++col) {
124 const float x = alpha_row[col] + dt_bias[col];
125 const float sp = recurrent_softplus(x);
126 const float sig = recurrent_sigmoid(x);
127 const float d_out = d_gate_row[col];
128 d_a[col] += d_out * sp;
129 {
130 const float d_x = d_out * a[col] * sig;
131 d_alpha_row[col] = d_x;
132 d_dt_bias[col] += d_x;
133 }
134 }
135 }
136}
static float recurrent_softplus(float x)
static float recurrent_sigmoid(float x)

References recurrent_sigmoid(), and recurrent_softplus().

◆ recurrent_dt_gate_expanded_forward()

void recurrent_dt_gate_expanded_forward ( const float *  alpha,
const float *  dt_bias,
const float *  a,
float *  gate,
int  rows,
int  num_heads,
int  state_dim 
)

Definition at line 84 of file recurrent_gate_kernels.c.

90 {
91 for (int row = 0; row < rows; ++row) {
92 const float *alpha_row = alpha + (size_t) row * (size_t) num_heads;
93 float *gate_row = gate + (size_t) row * (size_t) num_heads * (size_t) state_dim;
94 for (int h = 0; h < num_heads; ++h) {
95 const float sp = recurrent_softplus(alpha_row[h] + dt_bias[h]);
96 const float *a_head = a + (size_t) h * (size_t) state_dim;
97 float *gate_head = gate_row + (size_t) h * (size_t) state_dim;
98 for (int col = 0; col < state_dim; ++col) {
99 gate_head[col] = sp * a_head[col];
100 }
101 }
102 }
103}

References recurrent_softplus().

◆ recurrent_dt_gate_forward()

void recurrent_dt_gate_forward ( const float *  alpha,
const float *  dt_bias,
const float *  a,
float *  gate,
int  rows,
int  num_heads,
int  state_dim 
)

Definition at line 66 of file recurrent_gate_kernels.c.

72 {
73 const int dim = num_heads * state_dim;
74 for (int row = 0; row < rows; ++row) {
75 const float *alpha_row = alpha + (size_t) row * (size_t) dim;
76 float *gate_row = gate + (size_t) row * (size_t) dim;
77 for (int col = 0; col < dim; ++col) {
78 const float x = alpha_row[col] + dt_bias[col];
79 gate_row[col] = recurrent_softplus(x) * a[col];
80 }
81 }
82}

References recurrent_softplus().

◆ recurrent_dt_gate_forward_pytorch_fp32()

void recurrent_dt_gate_forward_pytorch_fp32 ( const float *  alpha,
const float *  dt_bias,
const float *  a,
float *  gate,
int  rows,
int  num_heads,
int  state_dim 
)

Definition at line 180 of file recurrent_gate_kernels.c.

187{
188 if (!alpha || !dt_bias || !a || !gate || rows < 0 || num_heads < 0 || state_dim != 1) {
189 fprintf(stderr,
190 "HARD KERNEL CONTRACT FAULT: invalid PyTorch FP32 recurrent dt-gate arguments\n");
191 abort();
192 }
193#if defined(__AVX512F__)
194 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
195 if (!ck_recurrent_pytorch_expf16 || !ck_recurrent_pytorch_log1pf16) {
196 fprintf(stderr,
197 "HARD KERNEL CONTRACT FAULT: PyTorch FP32 recurrent dt gate requires "
198 "SLEEF Sleef_expf16_u10 and Sleef_log1pf16_u10; set CK_SLEEF_LIBRARY\n");
199 abort();
200 }
201 if ((num_heads & 15) != 0) {
202 fprintf(stderr,
203 "HARD KERNEL CONTRACT FAULT: PyTorch AVX-512 recurrent dt gate requires "
204 "a head count divisible by 16 (got %d)\n",
205 num_heads);
206 abort();
207 }
210 fprintf(stderr,
211 "HARD KERNEL CONTRACT FAULT: PyTorch FP32 recurrent dt gate requires "
212 "log1pf from libm.so.6\n");
213 abort();
214 }
215 const __m512 threshold = _mm512_set1_ps(20.0f);
216 const int count = rows * num_heads;
217 int index = 0;
218 for (; index + 32 <= count; index += 32) {
219 for (int half = 0; half < 2; ++half) {
220 float x_lanes[16] __attribute__((aligned(64)));
221 float a_lanes[16] __attribute__((aligned(64)));
222 const int base = index + half * 16;
223 for (int lane = 0; lane < 16; ++lane) {
224 const int head = (base + lane) % num_heads;
225 x_lanes[lane] = alpha[base + lane] + dt_bias[head];
226 a_lanes[lane] = a[head];
227 }
228 const __m512 x = _mm512_load_ps(x_lanes);
229 const __m512 softplus = _mm512_mask_blend_ps(
230 _mm512_cmp_ps_mask(x, threshold, _CMP_GT_OQ),
231 ck_recurrent_pytorch_log1pf16(ck_recurrent_pytorch_expf16(x)),
232 x);
233 _mm512_storeu_ps(
234 gate + base,
235 _mm512_mul_ps(softplus, _mm512_load_ps(a_lanes)));
236 }
237 }
238 for (; index < count; ++index) {
239 const int head = index % num_heads;
240 const float x = alpha[index] + dt_bias[head];
241 const float softplus = x > 20.0f
242 ? x
244 gate[index] = softplus * a[head];
245 }
246#else
247 fprintf(stderr,
248 "HARD KERNEL CONTRACT FAULT: PyTorch FP32 recurrent dt gate requires AVX-512\n");
249 abort();
250#endif
251}
static ck_recurrent_libm_f32_fn ck_recurrent_pytorch_log1pf
static void ck_bind_recurrent_llama_libm(void)
static ck_recurrent_libm_f32_fn ck_recurrent_llama_expf
static pthread_once_t ck_recurrent_libm_once

References __attribute__(), ck_bind_recurrent_llama_libm(), ck_recurrent_libm_once, ck_recurrent_llama_expf, ck_recurrent_pytorch_log1pf, and count.

◆ recurrent_norm_gate_backward()

void recurrent_norm_gate_backward ( const float *  d_out,
const float *  x,
const float *  gate,
const float *  weight,
float *  d_x,
float *  d_gate,
float *  d_weight,
int  rows,
int  num_heads,
int  head_dim,
float  eps 
)

Definition at line 182 of file recurrent_norm_kernels.c.

192 {
193 const int inner_dim = num_heads * head_dim;
194 memset(d_weight, 0, (size_t) head_dim * sizeof(float));
195
196 for (int row = 0; row < rows; ++row) {
197 const float *d_out_row = d_out + (size_t) row * (size_t) inner_dim;
198 const float *x_row = x + (size_t) row * (size_t) inner_dim;
199 const float *gate_row = gate + (size_t) row * (size_t) inner_dim;
200 float *d_x_row = d_x + (size_t) row * (size_t) inner_dim;
201 float *d_gate_row = d_gate + (size_t) row * (size_t) inner_dim;
202
203 for (int head = 0; head < num_heads; ++head) {
204 const float *x_head = x_row + (size_t) head * (size_t) head_dim;
205 const float *gate_head = gate_row + (size_t) head * (size_t) head_dim;
206 const float *d_out_head = d_out_row + (size_t) head * (size_t) head_dim;
207 float *d_x_head = d_x_row + (size_t) head * (size_t) head_dim;
208 float *d_gate_head = d_gate_row + (size_t) head * (size_t) head_dim;
209
210 float ms = 0.0f;
211 for (int col = 0; col < head_dim; ++col) {
212 ms += x_head[col] * x_head[col];
213 }
214 ms /= (float) head_dim;
215 const float inv_rms = 1.0f / sqrtf(ms + eps);
216 const float inv_rms3_over_dim = (inv_rms * inv_rms * inv_rms) / (float) head_dim;
217
218 float dot = 0.0f;
219 for (int col = 0; col < head_dim; ++col) {
220 const float g = gate_head[col];
221 const float sig = recurrent_sigmoid_local(g);
222 const float silu = g * sig;
223 dot += d_out_head[col] * weight[col] * silu * x_head[col];
224 }
225
226 for (int col = 0; col < head_dim; ++col) {
227 const float g = gate_head[col];
228 const float sig = recurrent_sigmoid_local(g);
229 const float silu = g * sig;
230 const float scaled = inv_rms * weight[col] * silu;
231 d_x_head[col] = d_out_head[col] * scaled - x_head[col] * inv_rms3_over_dim * dot;
232 d_weight[col] += d_out_head[col] * (x_head[col] * inv_rms) * silu;
233 d_gate_head[col] = d_out_head[col] * (x_head[col] * inv_rms * weight[col]) *
234 (sig + g * sig * (1.0f - sig));
235 }
236 }
237 }
238}
static float recurrent_sigmoid_local(float x)

References recurrent_sigmoid_local(), and silu().

◆ recurrent_norm_gate_forward()

void recurrent_norm_gate_forward ( const float *  x,
const float *  gate,
const float *  weight,
float *  out,
int  rows,
int  num_heads,
int  head_dim,
float  eps 
)

Definition at line 18 of file recurrent_norm_kernels.c.

25 {
26 const int inner_dim = num_heads * head_dim;
27 for (int row = 0; row < rows; ++row) {
28 const float *x_row = x + (size_t) row * (size_t) inner_dim;
29 const float *gate_row = gate + (size_t) row * (size_t) inner_dim;
30 float *out_row = out + (size_t) row * (size_t) inner_dim;
31
32 for (int head = 0; head < num_heads; ++head) {
33 const float *x_head = x_row + (size_t) head * (size_t) head_dim;
34 const float *gate_head = gate_row + (size_t) head * (size_t) head_dim;
35 float *out_head = out_row + (size_t) head * (size_t) head_dim;
36
37 float ms = 0.0f;
38 for (int col = 0; col < head_dim; ++col) {
39 ms += x_head[col] * x_head[col];
40 }
41 ms /= (float) head_dim;
42 const float inv_rms = 1.0f / sqrtf(ms + eps);
43
44 for (int col = 0; col < head_dim; ++col) {
45 const float g = gate_head[col];
46 const float silu = g * recurrent_sigmoid_local(g);
47 out_head[col] = x_head[col] * inv_rms * weight[col] * silu;
48 }
49 }
50 }
51}

References recurrent_sigmoid_local(), and silu().

◆ recurrent_norm_gate_llama_avx2_forward()

void recurrent_norm_gate_llama_avx2_forward ( const float *  x,
const float *  gate,
const float *  weight,
float *  out,
int  rows,
int  num_heads,
int  head_dim,
float  eps 
)

Definition at line 53 of file recurrent_norm_kernels.c.

60 {
61 if (!x || !gate || !weight || !out || rows <= 0 || num_heads <= 0 ||
62 head_dim <= 0 || head_dim > 4096) {
63 return;
64 }
65 const int inner_dim = num_heads * head_dim;
66 float normalized[4096];
67 float silu[4096];
68 for (int row = 0; row < rows; ++row) {
69 for (int head = 0; head < num_heads; ++head) {
70 const size_t offset = (size_t) row * (size_t) inner_dim
71 + (size_t) head * (size_t) head_dim;
73 x + offset, weight, normalized, NULL, 1, head_dim, head_dim, eps);
74 recurrent_silu_forward_ggml(gate + offset, silu, 1, head_dim);
75 for (int col = 0; col < head_dim; ++col) {
76 out[offset + (size_t) col] = normalized[col] * silu[col];
77 }
78 }
79 }
80}
void rmsnorm_forward_llama_production(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
void recurrent_silu_forward_ggml(const float *x, float *out, int rows, int dim)

References recurrent_silu_forward_ggml(), rmsnorm_forward_llama_production(), and silu().

◆ recurrent_norm_gate_pytorch_bf16_storage()

void recurrent_norm_gate_pytorch_bf16_storage ( const float *  x,
const float *  gate,
const float *  weight,
float *  out,
int  rows,
int  num_heads,
int  head_dim,
float  eps 
)

Definition at line 111 of file recurrent_norm_kernels.c.

119{
120 if (!x || !gate || !weight || !out || rows <= 0 || num_heads <= 0 ||
121 head_dim <= 0 || head_dim > 4096) {
122 return;
123 }
124 const int inner_dim = num_heads * head_dim;
125 float normalized[4096];
126 float silu[4096];
127 for (int row = 0; row < rows; ++row) {
128 for (int head = 0; head < num_heads; ++head) {
129 const size_t offset = (size_t)row * (size_t)inner_dim +
130 (size_t)head * (size_t)head_dim;
131 /*
132 * Qwen3Next order:
133 * FP32 RMS statistics -> BF16 normalized value -> BF16 weight
134 * multiply -> FP32 SiLU(gate) -> BF16 final output.
135 */
137 x + offset, weight, normalized, NULL,
138 1, head_dim, head_dim, eps);
140 gate + offset, silu, 1, head_dim);
141 for (int col = 0; col < head_dim; ++col) {
142 out[offset + (size_t)col] = bf16_to_float(float_to_bf16(
143 normalized[col] * silu[col]));
144 }
145 }
146 }
147}
void recurrent_silu_forward_pytorch_bf16_input_fp32_output(const float *x, float *out, int rows, int dim)
void rmsnorm_forward_pytorch_bf16_storage(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References bf16_to_float(), float_to_bf16(), recurrent_silu_forward_pytorch_bf16_input_fp32_output(), rmsnorm_forward_pytorch_bf16_storage(), and silu().

◆ recurrent_norm_sigmoid_gate_llama_avx2_forward()

void recurrent_norm_sigmoid_gate_llama_avx2_forward ( const float *  x,
const float *  gate,
const float *  weight,
float *  out,
int  rows,
int  num_heads,
int  head_dim,
float  eps 
)

Definition at line 82 of file recurrent_norm_kernels.c.

89 {
90 if (!x || !gate || !weight || !out || rows <= 0 || num_heads <= 0 ||
91 head_dim <= 0 || head_dim > 4096) {
92 return;
93 }
94 const int inner_dim = num_heads * head_dim;
95 float normalized[4096];
96 float sigmoid[4096];
97 for (int row = 0; row < rows; ++row) {
98 for (int head = 0; head < num_heads; ++head) {
99 const size_t offset = (size_t) row * (size_t) inner_dim
100 + (size_t) head * (size_t) head_dim;
102 x + offset, weight, normalized, NULL, 1, head_dim, head_dim, eps);
103 recurrent_sigmoid_forward_ggml(gate + offset, sigmoid, 1, head_dim);
104 for (int col = 0; col < head_dim; ++col) {
105 out[offset + (size_t) col] = normalized[col] * sigmoid[col];
106 }
107 }
108 }
109}
void recurrent_sigmoid_forward_ggml(const float *x, float *out, int rows, int dim)

References recurrent_sigmoid_forward_ggml(), and rmsnorm_forward_llama_production().

◆ recurrent_norm_sigmoid_gate_pytorch_bf16_storage()

void recurrent_norm_sigmoid_gate_pytorch_bf16_storage ( const float *  x,
const float *  gate,
const float *  weight,
float *  out,
int  rows,
int  num_heads,
int  head_dim,
float  eps 
)

Definition at line 149 of file recurrent_norm_kernels.c.

157{
158 if (!x || !gate || !weight || !out || rows <= 0 || num_heads <= 0 ||
159 head_dim <= 0 || head_dim > 4096) {
160 return;
161 }
162 const int inner_dim = num_heads * head_dim;
163 float normalized[4096];
164 float sigmoid[4096];
165 for (int row = 0; row < rows; ++row) {
166 for (int head = 0; head < num_heads; ++head) {
167 const size_t offset = (size_t)row * (size_t)inner_dim +
168 (size_t)head * (size_t)head_dim;
170 x + offset, weight, normalized, NULL,
171 1, head_dim, head_dim, eps);
173 gate + offset, sigmoid, 1, head_dim);
174 for (int col = 0; col < head_dim; ++col) {
175 out[offset + (size_t)col] = bf16_to_float(float_to_bf16(
176 normalized[col] * sigmoid[col]));
177 }
178 }
179 }
180}

References bf16_to_float(), float_to_bf16(), recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output(), and rmsnorm_forward_pytorch_bf16_storage().

◆ recurrent_qk_l2_norm_backward()

void recurrent_qk_l2_norm_backward ( const float *  d_q_out,
const float *  d_k_out,
const float *  q,
const float *  k,
float *  d_q,
float *  d_k,
int  rows,
int  q_dim,
int  k_dim,
int  head_dim,
float  eps 
)

Definition at line 472 of file recurrent_qk_norm_kernels.c.

482 {
483 recurrent_l2_norm_rows_backward_one(d_q_out, q, d_q, rows, q_dim, head_dim, eps);
484 recurrent_l2_norm_rows_backward_one(d_k_out, k, d_k, rows, k_dim, head_dim, eps);
485}
static void recurrent_l2_norm_rows_backward_one(const float *d_out, const float *x, float *d_x, int rows, int dim, int head_dim, float eps)

References recurrent_l2_norm_rows_backward_one().

◆ recurrent_qk_l2_norm_forward()

void recurrent_qk_l2_norm_forward ( float *  q,
float *  k,
int  rows,
int  q_dim,
int  k_dim,
int  head_dim,
float  eps 
)

Definition at line 124 of file recurrent_qk_norm_kernels.c.

130 {
131 if (!q || !k || rows <= 0 || q_dim <= 0 || k_dim <= 0 ||
132 head_dim <= 0 || q_dim % head_dim != 0 || k_dim % head_dim != 0) {
133 return;
134 }
135 const int q_heads = q_dim / head_dim;
136 const int k_heads = k_dim / head_dim;
137 if (q_heads > INT_MAX - k_heads) {
138 return;
139 }
140 const int heads_per_row = q_heads + k_heads;
141 if (rows > INT_MAX / heads_per_row) {
142 return;
143 }
144
145 ck_recurrent_qk_l2_args_t args = {
146 q, k, q_heads, k_heads, head_dim, eps,
147 };
148 const int jobs = rows * heads_per_row;
149 const size_t elements = (size_t)jobs * (size_t)head_dim;
150 const size_t minimum_elements_per_thread = 32768u;
151 const uintptr_t q_begin = (uintptr_t)q;
152 const uintptr_t q_end = q_begin +
153 (size_t)rows * (size_t)q_dim * sizeof(float);
154 const uintptr_t k_begin = (uintptr_t)k;
155 const uintptr_t k_end = k_begin +
156 (size_t)rows * (size_t)k_dim * sizeof(float);
157 const int ranges_overlap = q_begin < k_end && k_begin < q_end;
158 if (ranges_overlap || elements < 2u * minimum_elements_per_thread) {
159 recurrent_l2_norm_rows_forward_one(q, rows, q_dim, head_dim, eps);
160 recurrent_l2_norm_rows_forward_one(k, rows, k_dim, head_dim, eps);
161 return;
162 }
163
164 ck_threadpool_t *pool = ck_threadpool_global();
165 int active = pool ? ck_threadpool_n_threads(pool) : 1;
166 size_t useful_threads =
167 (elements + minimum_elements_per_thread - 1u) /
168 minimum_elements_per_thread;
169 if ((size_t)active > useful_threads) {
170 active = (int)useful_threads;
171 }
172 if (active > jobs) {
173 active = jobs;
174 }
175
176 if (active > 1 && ck_threadpool_thread_id(pool) <= 0) {
178 pool, active, 0, jobs, 8,
180 } else {
181 recurrent_l2_norm_rows_forward_one(q, rows, q_dim, head_dim, eps);
182 recurrent_l2_norm_rows_forward_one(k, rows, k_dim, head_dim, eps);
183 }
184}
static void recurrent_qk_l2_norm_head_range(int begin, int end, void *opaque)
static void recurrent_l2_norm_rows_forward_one(float *x, int rows, int dim, int head_dim, float eps)

References ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), ck_threadpool_thread_id(), recurrent_l2_norm_rows_forward_one(), and recurrent_qk_l2_norm_head_range().

◆ recurrent_qk_l2_norm_pytorch_bf16_storage()

void recurrent_qk_l2_norm_pytorch_bf16_storage ( float *  q,
float *  k,
int  rows,
int  q_dim,
int  k_dim,
int  expanded_heads,
int  head_dim,
float  eps 
)

Definition at line 457 of file recurrent_qk_norm_kernels.c.

465{
467 q, rows, q_dim, expanded_heads, head_dim, eps);
469 k, rows, k_dim, expanded_heads, head_dim, eps);
470}
static void recurrent_pytorch_bf16_l2_rows(float *x, int rows, int dim, int expanded_heads, int head_dim, float eps)

References recurrent_pytorch_bf16_l2_rows().

◆ recurrent_qk_l2_norm_pytorch_fp32_output()

void recurrent_qk_l2_norm_pytorch_fp32_output ( float *  q,
float *  k,
int  rows,
int  q_dim,
int  k_dim,
int  head_dim,
float  eps 
)

Definition at line 335 of file recurrent_qk_norm_kernels.c.

342{
343 recurrent_pytorch_fp32_l2_rows(q, rows, q_dim, head_dim, eps);
344 recurrent_pytorch_fp32_l2_rows(k, rows, k_dim, head_dim, eps);
345}
static void recurrent_pytorch_fp32_l2_rows(float *x, int rows, int dim, int head_dim, float eps)

References recurrent_pytorch_fp32_l2_rows().

◆ recurrent_sigmoid_forward_ggml()

void recurrent_sigmoid_forward_ggml ( const float *  x,
float *  out,
int  rows,
int  dim 
)

Definition at line 543 of file recurrent_gate_kernels.c.

546 {
547 float (*volatile llama_expf)(float) = expf;
548 for (int row = 0; row < rows; ++row) {
549 const float *x_row = x + (size_t) row * (size_t) dim;
550 float *out_row = out + (size_t) row * (size_t) dim;
551 for (int col = 0; col < dim; ++col) {
552 out_row[col] = 1.0f / (1.0f + llama_expf(-x_row[col]));
553 }
554 }
555}

Referenced by hyper_connection_mix_quantized(), and recurrent_norm_sigmoid_gate_llama_avx2_forward().

◆ recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output()

void recurrent_sigmoid_forward_pytorch_bf16_input_fp32_output ( const float *  x,
float *  out,
int  rows,
int  dim 
)

Definition at line 340 of file recurrent_gate_kernels.c.

345{
346 if (!x || !out || rows < 0 || dim < 0) {
347 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid BF16-input FP32-output sigmoid arguments\n");
348 abort();
349 }
350#if defined(__AVX512F__)
351 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
352 if (!ck_recurrent_pytorch_expf16) {
353 fprintf(stderr,
354 "HARD KERNEL CONTRACT FAULT: PyTorch BF16-input sigmoid requires "
355 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
356 abort();
357 }
358#endif
359 const int count = rows * dim;
360 int i = 0;
361#if defined(__AVX512F__)
362 for (; i + 16 <= count; i += 16) {
363 float lanes[16] __attribute__((aligned(64)));
364 for (int lane = 0; lane < 16; ++lane) {
365 lanes[lane] = bf16_to_float(float_to_bf16(x[i + lane]));
366 }
367 const __m512 values = _mm512_load_ps(lanes);
368 const __m512 denominator = _mm512_add_ps(
369 _mm512_set1_ps(1.0f),
370 ck_recurrent_pytorch_expf16(
371 _mm512_sub_ps(_mm512_setzero_ps(), values)));
372 _mm512_storeu_ps(out + i,
373 _mm512_div_ps(_mm512_set1_ps(1.0f), denominator));
374 }
375#endif
376 for (; i < count; ++i) {
377 const float value = bf16_to_float(float_to_bf16(x[i]));
378 out[i] = 1.0f / (1.0f + expf(-value));
379 }
380}

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

Referenced by attn_gate_sigmoid_mul_pytorch_bf16_storage(), and recurrent_norm_sigmoid_gate_pytorch_bf16_storage().

◆ recurrent_silu_backward()

void recurrent_silu_backward ( const float *  d_out,
const float *  x,
float *  d_x,
int  rows,
int  dim 
)

Definition at line 557 of file recurrent_gate_kernels.c.

561 {
562 for (int row = 0; row < rows; ++row) {
563 const float *d_out_row = d_out + (size_t) row * (size_t) dim;
564 const float *x_row = x + (size_t) row * (size_t) dim;
565 float *d_x_row = d_x + (size_t) row * (size_t) dim;
566 for (int col = 0; col < dim; ++col) {
567 const float xv = x_row[col];
568 const float sig = recurrent_sigmoid(xv);
569 d_x_row[col] = d_out_row[col] * (sig + xv * sig * (1.0f - sig));
570 }
571 }
572}

References recurrent_sigmoid().

◆ recurrent_silu_forward()

void recurrent_silu_forward ( const float *  x,
float *  out,
int  rows,
int  dim 
)

Definition at line 138 of file recurrent_gate_kernels.c.

141 {
142 for (int row = 0; row < rows; ++row) {
143 const float *x_row = x + (size_t) row * (size_t) dim;
144 float *out_row = out + (size_t) row * (size_t) dim;
145 for (int col = 0; col < dim; ++col) {
146 const float xv = x_row[col];
147 out_row[col] = xv * recurrent_sigmoid(xv);
148 }
149 }
150}

References recurrent_sigmoid().

◆ recurrent_silu_forward_ggml()

void recurrent_silu_forward_ggml ( const float *  x,
float *  out,
int  rows,
int  dim 
)

Definition at line 510 of file recurrent_gate_kernels.c.

513 {
514 if (!x || !out || rows <= 0 || dim <= 0) {
515 return;
516 }
517
518 ck_recurrent_silu_ggml_args_t args = {x, out, dim};
519 const size_t elements = (size_t)rows * (size_t)dim;
520 const size_t minimum_elements_per_thread = 65536u;
521 if (rows < 2 || elements < 2u * minimum_elements_per_thread) {
522 recurrent_silu_forward_ggml_rows(0, rows, &args);
523 return;
524 }
525
526 ck_threadpool_t *pool = ck_threadpool_global();
527 int active = pool ? ck_threadpool_n_threads(pool) : 1;
528 size_t useful_threads =
529 (elements + minimum_elements_per_thread - 1u) /
530 minimum_elements_per_thread;
531 if ((size_t)active > useful_threads) active = (int)useful_threads;
532 if (active > rows) active = rows;
533
534 if (active > 1 && ck_threadpool_thread_id(pool) <= 0) {
536 pool, active, 0, rows, 1,
538 } else {
539 recurrent_silu_forward_ggml_rows(0, rows, &args);
540 }
541}
static void recurrent_silu_forward_ggml_rows(int begin, int end, void *opaque)

References ck_threadpool_global(), ck_threadpool_n_threads(), ck_threadpool_parallel_for_n(), ck_threadpool_thread_id(), and recurrent_silu_forward_ggml_rows().

Referenced by hyper_connection_mix_quantized(), qwen4_ple_gate_conv_inject_impl(), and recurrent_norm_gate_llama_avx2_forward().

◆ recurrent_silu_forward_pytorch_bf16_input_fp32_output()

void recurrent_silu_forward_pytorch_bf16_input_fp32_output ( const float *  x,
float *  out,
int  rows,
int  dim 
)

Definition at line 300 of file recurrent_gate_kernels.c.

304{
305 if (!x || !out || rows < 0 || dim < 0) {
306 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid BF16-input FP32-output SiLU arguments\n");
307 abort();
308 }
309#if defined(__AVX512F__)
310 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
311 if (!ck_recurrent_pytorch_expf16) {
312 fprintf(stderr,
313 "HARD KERNEL CONTRACT FAULT: PyTorch BF16-input SiLU requires "
314 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
315 abort();
316 }
317#endif
318 const int count = rows * dim;
319 int i = 0;
320#if defined(__AVX512F__)
321 for (; i + 16 <= count; i += 16) {
322 float lanes[16] __attribute__((aligned(64)));
323 for (int lane = 0; lane < 16; ++lane) {
324 lanes[lane] = bf16_to_float(float_to_bf16(x[i + lane]));
325 }
326 const __m512 values = _mm512_load_ps(lanes);
327 const __m512 denominator = _mm512_add_ps(
328 _mm512_set1_ps(1.0f),
329 ck_recurrent_pytorch_expf16(
330 _mm512_sub_ps(_mm512_setzero_ps(), values)));
331 _mm512_storeu_ps(out + i, _mm512_div_ps(values, denominator));
332 }
333#endif
334 for (; i < count; ++i) {
335 const float value = bf16_to_float(float_to_bf16(x[i]));
336 out[i] = value / (1.0f + expf(-value));
337 }
338}

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

Referenced by recurrent_norm_gate_pytorch_bf16_storage().

◆ recurrent_silu_forward_pytorch_bf16_storage()

void recurrent_silu_forward_pytorch_bf16_storage ( const float *  x,
float *  out,
int  rows,
int  dim 
)

Definition at line 253 of file recurrent_gate_kernels.c.

257{
258 if (!x || !out || rows < 0 || dim < 0) {
259 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid PyTorch BF16 recurrent SiLU arguments\n");
260 abort();
261 }
262#if defined(__AVX512F__)
263 pthread_once(&ck_recurrent_sleef_once, ck_bind_recurrent_pytorch_sleef);
264 if (!ck_recurrent_pytorch_expf16) {
265 fprintf(stderr,
266 "HARD KERNEL CONTRACT FAULT: PyTorch BF16 recurrent SiLU requires "
267 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
268 abort();
269 }
270#endif
271 for (int row = 0; row < rows; ++row) {
272 const float *src = x + (size_t)row * (size_t)dim;
273 float *dst = out + (size_t)row * (size_t)dim;
274 int col = 0;
275#if defined(__AVX512F__)
276 for (; col + 16 <= dim; col += 16) {
277 float lanes[16] __attribute__((aligned(64)));
278 for (int lane = 0; lane < 16; ++lane) {
279 lanes[lane] = bf16_to_float(float_to_bf16(src[col + lane]));
280 }
281 const __m512 values = _mm512_load_ps(lanes);
282 const __m512 denominator = _mm512_add_ps(
283 _mm512_set1_ps(1.0f),
284 ck_recurrent_pytorch_expf16(
285 _mm512_sub_ps(_mm512_setzero_ps(), values)));
286 _mm512_store_ps(lanes, _mm512_div_ps(values, denominator));
287 for (int lane = 0; lane < 16; ++lane) {
288 dst[col + lane] = bf16_to_float(float_to_bf16(lanes[lane]));
289 }
290 }
291#endif
292 for (; col < dim; ++col) {
293 const float value = bf16_to_float(float_to_bf16(src[col]));
294 const float silu = value / (1.0f + expf(-value));
295 dst[col] = bf16_to_float(float_to_bf16(silu));
296 }
297 }
298}

References __attribute__(), bf16_to_float(), float_to_bf16(), and silu().

◆ recurrent_split_conv_qkv_backward()

void recurrent_split_conv_qkv_backward ( const float *  d_q,
const float *  d_k,
const float *  d_v,
float *  d_packed_qkv,
int  rows,
int  q_dim,
int  k_dim,
int  v_dim 
)

Definition at line 108 of file recurrent_split_kernels.c.

115 {
116 recurrent_split_qkv_backward(d_q, d_k, d_v, d_packed_qkv, rows, q_dim, k_dim, v_dim);
117}
void recurrent_split_qkv_backward(const float *d_q, const float *d_k, const float *d_v, float *d_packed_qkv, int rows, int q_dim, int k_dim, int v_dim)

References recurrent_split_qkv_backward().

◆ recurrent_split_conv_qkv_forward()

void recurrent_split_conv_qkv_forward ( const float *  packed_qkv,
float *  q,
float *  k,
float *  v,
int  rows,
int  q_dim,
int  k_dim,
int  v_dim 
)

Definition at line 97 of file recurrent_split_kernels.c.

104 {
105 recurrent_split_qkv_forward(packed_qkv, q, k, v, rows, q_dim, k_dim, v_dim);
106}
void recurrent_split_qkv_forward(const float *packed_qkv, float *q, float *k, float *v, int rows, int q_dim, int k_dim, int v_dim)

References recurrent_split_qkv_forward().

◆ recurrent_split_qkv_backward()

void recurrent_split_qkv_backward ( const float *  d_q,
const float *  d_k,
const float *  d_v,
float *  d_packed_qkv,
int  rows,
int  q_dim,
int  k_dim,
int  v_dim 
)

Definition at line 77 of file recurrent_split_kernels.c.

84 {
85 const int packed_dim = q_dim + k_dim + v_dim;
86 for (int row = 0; row < rows; ++row) {
87 const float *dq_src = d_q + (size_t) row * (size_t) q_dim;
88 const float *dk_src = d_k + (size_t) row * (size_t) k_dim;
89 const float *dv_src = d_v + (size_t) row * (size_t) v_dim;
90 float *dst = d_packed_qkv + (size_t) row * (size_t) packed_dim;
91 memcpy(dst, dq_src, (size_t) q_dim * sizeof(float));
92 memcpy(dst + q_dim, dk_src, (size_t) k_dim * sizeof(float));
93 memcpy(dst + q_dim + k_dim, dv_src, (size_t) v_dim * sizeof(float));
94 }
95}

Referenced by recurrent_split_conv_qkv_backward().

◆ recurrent_split_qkv_forward()

void recurrent_split_qkv_forward ( const float *  packed_qkv,
float *  q,
float *  k,
float *  v,
int  rows,
int  q_dim,
int  k_dim,
int  v_dim 
)

Definition at line 5 of file recurrent_split_kernels.c.

12 {
13 const int packed_dim = q_dim + k_dim + v_dim;
14 for (int row = 0; row < rows; ++row) {
15 const float *src = packed_qkv + (size_t) row * (size_t) packed_dim;
16 float *q_dst = q + (size_t) row * (size_t) q_dim;
17 float *k_dst = k + (size_t) row * (size_t) k_dim;
18 float *v_dst = v + (size_t) row * (size_t) v_dim;
19 memcpy(q_dst, src, (size_t) q_dim * sizeof(float));
20 memcpy(k_dst, src + q_dim, (size_t) k_dim * sizeof(float));
21 memcpy(v_dst, src + q_dim + k_dim, (size_t) v_dim * sizeof(float));
22 }
23}

◆ relu2_backward()

void relu2_backward ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 147 of file relu_kernels.c.

151{
152 size_t i = 0;
153
154#if defined(__AVX512F__)
155 const __m512 vzero = _mm512_setzero_ps();
156 const __m512 vtwo = _mm512_set1_ps(2.0f);
157 for (; i + 15 < n; i += 16) {
158 const __m512 vx = _mm512_loadu_ps(input + i);
159 const __m512 vdy = _mm512_loadu_ps(d_output + i);
160 const __mmask16 mask = _mm512_cmp_ps_mask(vx, vzero, _CMP_GT_OQ);
161 const __m512 vdx = _mm512_mul_ps(_mm512_mul_ps(vtwo, vx), vdy);
162 _mm512_storeu_ps(d_input + i, _mm512_maskz_mov_ps(mask, vdx));
163 }
164#elif defined(__AVX2__) || defined(__AVX__)
165 const __m256 vzero = _mm256_setzero_ps();
166 const __m256 vtwo = _mm256_set1_ps(2.0f);
167 for (; i + 7 < n; i += 8) {
168 const __m256 vx = _mm256_loadu_ps(input + i);
169 const __m256 vdy = _mm256_loadu_ps(d_output + i);
170 const __m256 mask = _mm256_cmp_ps(vx, vzero, _CMP_GT_OQ);
171 const __m256 vdx = _mm256_mul_ps(_mm256_mul_ps(vtwo, vx), vdy);
172 _mm256_storeu_ps(d_input + i, _mm256_and_ps(mask, vdx));
173 }
174#endif
175
176 for (; i < n; ++i) {
177 const float x = input[i];
178 d_input[i] = (x > 0.0f) ? d_output[i] * 2.0f * x : 0.0f;
179 }
180}
int32_t int32_t int32_t int32_t int32_t mask
Definition tokenizer.h:234

References mask.

◆ relu2_forward()

void relu2_forward ( const float *  input,
float *  output,
size_t  n 
)

Definition at line 120 of file relu_kernels.c.

121{
122 size_t i = 0;
123
124#if defined(__AVX512F__)
125 const __m512 vzero = _mm512_setzero_ps();
126 for (; i + 15 < n; i += 16) {
127 const __m512 vx = _mm512_loadu_ps(input + i);
128 const __m512 vr = _mm512_max_ps(vx, vzero);
129 _mm512_storeu_ps(output + i, _mm512_mul_ps(vr, vr));
130 }
131#elif defined(__AVX2__) || defined(__AVX__)
132 const __m256 vzero = _mm256_setzero_ps();
133 for (; i + 7 < n; i += 8) {
134 const __m256 vx = _mm256_loadu_ps(input + i);
135 const __m256 vr = _mm256_max_ps(vx, vzero);
136 _mm256_storeu_ps(output + i, _mm256_mul_ps(vr, vr));
137 }
138#endif
139
140 for (; i < n; ++i) {
141 const float x = input[i];
142 output[i] = (x > 0.0f) ? x * x : 0.0f;
143 }
144}

◆ relu_backward()

void relu_backward ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 84 of file relu_kernels.c.

88{
89 size_t i = 0;
90
91#if defined(__AVX512F__)
92 __m512 vzero = _mm512_setzero_ps();
93 for (; i + 15 < n; i += 16) {
94 __m512 vx = _mm512_loadu_ps(input + i);
95 __m512 vdy = _mm512_loadu_ps(d_output + i);
96 __mmask16 mask = _mm512_cmp_ps_mask(vx, vzero, _CMP_GT_OQ);
97 __m512 vdx = _mm512_maskz_mov_ps(mask, vdy);
98 _mm512_storeu_ps(d_input + i, vdx);
99 }
100#elif defined(__AVX2__) || defined(__AVX__)
101 __m256 vzero = _mm256_setzero_ps();
102 for (; i + 7 < n; i += 8) {
103 __m256 vx = _mm256_loadu_ps(input + i);
104 __m256 vdy = _mm256_loadu_ps(d_output + i);
105 // Result is all 1s (0xFFFFFFFF) if true, 0 if false.
106 __m256 mask = _mm256_cmp_ps(vx, vzero, _CMP_GT_OQ);
107 __m256 vdx = _mm256_and_ps(mask, vdy);
108 _mm256_storeu_ps(d_input + i, vdx);
109 }
110#endif
111
112 // Scalar fallback
113 for (; i < n; ++i) {
114 d_input[i] = (input[i] > 0.0f) ? d_output[i] : 0.0f;
115 }
116}

References mask.

◆ relu_backward_bf16()

void relu_backward_bf16 ( const uint16_t *  input,
const uint16_t *  d_output,
uint16_t *  d_input,
size_t  n 
)

Definition at line 69 of file relu_kernels_bf16.c.

73{
74 if (!input || !d_output || !d_input) {
75 return;
76 }
77
78 size_t i = 0;
79#if defined(__AVX2__)
80 const __m256i zero = _mm256_setzero_si256();
81 for (; i + 16 <= n; i += 16) {
82 const __m256i x = _mm256_loadu_si256((const __m256i *)(input + i));
83 const __m256i dy = _mm256_loadu_si256((const __m256i *)(d_output + i));
84 const __m256i mask = _mm256_cmpgt_epi16(x, zero);
85 const __m256i dx = _mm256_and_si256(dy, mask);
86 _mm256_storeu_si256((__m256i *)(d_input + i), dx);
87 }
88#endif
89 for (; i < n; ++i) {
90 d_input[i] = ((input[i] & 0x8000u) == 0u && (input[i] & 0x7fffu) != 0u) ? d_output[i] : 0u;
91 }
92}

References mask.

◆ relu_forward()

void relu_forward ( const float *  input,
float *  output,
size_t  n 
)

Definition at line 26 of file relu_kernels.c.

27{
28 size_t i = 0;
29
30#if defined(__AVX512F__)
31 __m512 vzero = _mm512_setzero_ps();
32 for (; i + 15 < n; i += 16) {
33 __m512 vx = _mm512_loadu_ps(input + i);
34 __m512 vy = _mm512_max_ps(vx, vzero);
35 _mm512_storeu_ps(output + i, vy);
36 }
37#elif defined(__AVX2__) || defined(__AVX__)
38 __m256 vzero = _mm256_setzero_ps();
39 for (; i + 7 < n; i += 8) {
40 __m256 vx = _mm256_loadu_ps(input + i);
41 __m256 vy = _mm256_max_ps(vx, vzero);
42 _mm256_storeu_ps(output + i, vy);
43 }
44#endif
45
46 // Scalar fallback
47 for (; i < n; ++i) {
48 float x = input[i];
49 output[i] = (x > 0.0f) ? x : 0.0f;
50 }
51}

◆ relu_forward_bf16()

void relu_forward_bf16 ( const uint16_t *  input,
uint16_t *  output,
size_t  n 
)

Definition at line 27 of file relu_kernels_bf16.c.

28{
29 if (!input || !output) {
30 return;
31 }
32
33 size_t i = 0;
34#if defined(__AVX2__)
35 const __m256i zero = _mm256_setzero_si256();
36 for (; i + 16 <= n; i += 16) {
37 const __m256i x = _mm256_loadu_si256((const __m256i *)(input + i));
38 const __m256i mask = _mm256_cmpgt_epi16(x, zero);
39 const __m256i y = _mm256_and_si256(x, mask);
40 _mm256_storeu_si256((__m256i *)(output + i), y);
41 }
42#endif
43 for (; i < n; ++i) {
44 output[i] = (input[i] & 0x8000u) ? 0u : input[i];
45 }
46}

References mask.

◆ relu_forward_inplace()

void relu_forward_inplace ( float *  data,
size_t  n 
)

Definition at line 54 of file relu_kernels.c.

55{
56 size_t i = 0;
57
58#if defined(__AVX512F__)
59 __m512 vzero = _mm512_setzero_ps();
60 for (; i + 15 < n; i += 16) {
61 __m512 vx = _mm512_loadu_ps(data + i);
62 __m512 vy = _mm512_max_ps(vx, vzero);
63 _mm512_storeu_ps(data + i, vy);
64 }
65#elif defined(__AVX2__) || defined(__AVX__)
66 __m256 vzero = _mm256_setzero_ps();
67 for (; i + 7 < n; i += 8) {
68 __m256 vx = _mm256_loadu_ps(data + i);
69 __m256 vy = _mm256_max_ps(vx, vzero);
70 _mm256_storeu_ps(data + i, vy);
71 }
72#endif
73
74 // Scalar fallback
75 for (; i < n; ++i) {
76 float x = data[i];
77 if (x < 0.0f) {
78 data[i] = 0.0f;
79 }
80 }
81}

◆ relu_forward_inplace_bf16()

void relu_forward_inplace_bf16 ( uint16_t *  data,
size_t  n 
)

Definition at line 48 of file relu_kernels_bf16.c.

49{
50 if (!data) {
51 return;
52 }
53
54 size_t i = 0;
55#if defined(__AVX2__)
56 const __m256i zero = _mm256_setzero_si256();
57 for (; i + 16 <= n; i += 16) {
58 const __m256i x = _mm256_loadu_si256((const __m256i *)(data + i));
59 const __m256i mask = _mm256_cmpgt_epi16(x, zero);
60 const __m256i y = _mm256_and_si256(x, mask);
61 _mm256_storeu_si256((__m256i *)(data + i), y);
62 }
63#endif
64 for (; i < n; ++i) {
65 data[i] = (data[i] & 0x8000u) ? 0u : data[i];
66 }
67}

References mask.

◆ rmsnorm_backward()

void rmsnorm_backward ( const float *  d_output,
const float *  input,
const float *  gamma,
const float *  rstd_cache,
float *  d_input,
float *  d_gamma,
int  tokens,
int  d_model,
int  aligned_embed_dim 
)

RMSNorm backward pass

Test:

test_rmsnorm.py::TestRMSNormBackward::test_backward_tokens

test_rmsnorm.py::TestRMSNormBackward::test_backward_single

test_parity.py::test_rmsnorm_backward_parity

Computes dX and dGamma given dY, X, gamma, and cached rstd. dX_i = rstd * (dY_i * gamma_i - x_hat_i * m) dGamma_i = sum_t (dY_i * x_hat_i)

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

Definition at line 888 of file rmsnorm_kernels.c.

897{
898 int T = tokens;
899 int D = d_model;
900 int aligned = aligned_embed_dim;
901
903 rmsnorm_backward_strict_scalar(d_output, input, gamma, rstd_cache, d_input, d_gamma, T, D, aligned);
904 return;
905 }
906
907 // Zero parameter gradients
908#if defined(__AVX512F__)
909 {
910 int d = 0;
911 for (; d + 16 <= D; d += 16) {
912 _mm512_storeu_ps(&d_gamma[d], _mm512_setzero_ps());
913 }
914 for (; d < D; ++d) {
915 d_gamma[d] = 0.0f;
916 }
917 }
918#elif defined(__AVX__)
919 {
920 int d = 0;
921 for (; d + 8 <= D; d += 8) {
922 _mm256_storeu_ps(&d_gamma[d], _mm256_setzero_ps());
923 }
924 for (; d < D; ++d) {
925 d_gamma[d] = 0.0f;
926 }
927 }
928#else
929 for (int d = 0; d < D; ++d) {
930 d_gamma[d] = 0.0f;
931 }
932#endif
933
934 for (int t = 0; t < T; ++t) {
935 const float *x = input + (size_t)t * aligned;
936 const float *dY = d_output + (size_t)t * aligned;
937 float *dX = d_input + (size_t)t * aligned;
938
939 float rstd = rstd_cache[t];
940
941#if defined(__AVX512F__)
942 // Compute m = (1/D) * sum_j (dY_j * gamma_j * x_hat_j)
943 __m512 rstd_vec = _mm512_set1_ps(rstd);
944 __m512 sum_vec = _mm512_setzero_ps();
945 int d = 0;
946
947 for (; d + 16 <= D; d += 16) {
948 __m512 xv = _mm512_loadu_ps(&x[d]);
949 __m512 dyv = _mm512_loadu_ps(&dY[d]);
950 __m512 gv = _mm512_loadu_ps(&gamma[d]);
951 __m512 x_hat = _mm512_mul_ps(xv, rstd_vec);
952 // sum += dY * gamma * x_hat
953 __m512 prod = _mm512_mul_ps(dyv, gv);
954 sum_vec = _mm512_fmadd_ps(prod, x_hat, sum_vec);
955 }
956 float sum_dY_g_xhat = _mm512_reduce_add_ps(sum_vec);
957
958 // Handle remaining elements
959 for (; d < D; ++d) {
960 float x_hat = x[d] * rstd;
961 sum_dY_g_xhat += dY[d] * gamma[d] * x_hat;
962 }
963 float m = sum_dY_g_xhat / (float)D;
964
965 // Compute dX and accumulate dGamma (vectorized)
966 __m512 m_vec = _mm512_set1_ps(m);
967 d = 0;
968 for (; d + 16 <= D; d += 16) {
969 __m512 xv = _mm512_loadu_ps(&x[d]);
970 __m512 dyv = _mm512_loadu_ps(&dY[d]);
971 __m512 gv = _mm512_loadu_ps(&gamma[d]);
972 __m512 dgv = _mm512_loadu_ps(&d_gamma[d]);
973
974 __m512 x_hat = _mm512_mul_ps(xv, rstd_vec);
975
976 // dX = rstd * (dY * gamma - x_hat * m)
977 __m512 dy_g = _mm512_mul_ps(dyv, gv);
978 __m512 xhat_m = _mm512_mul_ps(x_hat, m_vec);
979 __m512 diff = _mm512_sub_ps(dy_g, xhat_m);
980 __m512 dxv = _mm512_mul_ps(rstd_vec, diff);
981 _mm512_storeu_ps(&dX[d], dxv);
982
983 // d_gamma += dY * x_hat
984 dgv = _mm512_fmadd_ps(dyv, x_hat, dgv);
985 _mm512_storeu_ps(&d_gamma[d], dgv);
986 }
987 // Handle remaining elements
988 for (; d < D; ++d) {
989 float x_hat = x[d] * rstd;
990 float dy = dY[d];
991 dX[d] = rstd * (dy * gamma[d] - x_hat * m);
992 d_gamma[d] += dy * x_hat;
993 }
994
995#elif defined(__AVX__)
996 // Compute m = (1/D) * sum_j (dY_j * gamma_j * x_hat_j)
997 __m256 rstd_vec = _mm256_set1_ps(rstd);
998 __m256 sum_vec = _mm256_setzero_ps();
999 int d = 0;
1000
1001 for (; d + 8 <= D; d += 8) {
1002 __m256 xv = _mm256_loadu_ps(&x[d]);
1003 __m256 dyv = _mm256_loadu_ps(&dY[d]);
1004 __m256 gv = _mm256_loadu_ps(&gamma[d]);
1005 __m256 x_hat = _mm256_mul_ps(xv, rstd_vec);
1006 // sum += dY * gamma * x_hat (no FMA, use mul + mul + add)
1007 __m256 prod = _mm256_mul_ps(dyv, gv);
1008 __m256 prod2 = _mm256_mul_ps(prod, x_hat);
1009 sum_vec = _mm256_add_ps(sum_vec, prod2);
1010 }
1011 float sum_dY_g_xhat = hsum256_ps_rmsnorm(sum_vec);
1012
1013 // Handle remaining elements
1014 for (; d < D; ++d) {
1015 float x_hat = x[d] * rstd;
1016 sum_dY_g_xhat += dY[d] * gamma[d] * x_hat;
1017 }
1018 float m = sum_dY_g_xhat / (float)D;
1019
1020 // Compute dX and accumulate dGamma (vectorized)
1021 __m256 m_vec = _mm256_set1_ps(m);
1022 d = 0;
1023 for (; d + 8 <= D; d += 8) {
1024 __m256 xv = _mm256_loadu_ps(&x[d]);
1025 __m256 dyv = _mm256_loadu_ps(&dY[d]);
1026 __m256 gv = _mm256_loadu_ps(&gamma[d]);
1027 __m256 dgv = _mm256_loadu_ps(&d_gamma[d]);
1028
1029 __m256 x_hat = _mm256_mul_ps(xv, rstd_vec);
1030
1031 // dX = rstd * (dY * gamma - x_hat * m)
1032 __m256 dy_g = _mm256_mul_ps(dyv, gv);
1033 __m256 xhat_m = _mm256_mul_ps(x_hat, m_vec);
1034 __m256 diff = _mm256_sub_ps(dy_g, xhat_m);
1035 __m256 dxv = _mm256_mul_ps(rstd_vec, diff);
1036 _mm256_storeu_ps(&dX[d], dxv);
1037
1038 // d_gamma += dY * x_hat
1039 __m256 dy_xhat = _mm256_mul_ps(dyv, x_hat);
1040 dgv = _mm256_add_ps(dgv, dy_xhat);
1041 _mm256_storeu_ps(&d_gamma[d], dgv);
1042 }
1043 // Handle remaining elements
1044 for (; d < D; ++d) {
1045 float x_hat = x[d] * rstd;
1046 float dy = dY[d];
1047 dX[d] = rstd * (dy * gamma[d] - x_hat * m);
1048 d_gamma[d] += dy * x_hat;
1049 }
1050
1051#else
1052 // Scalar fallback
1053 // Compute m = (1/D) * sum_j (dY_j * gamma_j * x_hat_j)
1054 float sum_dY_g_xhat = 0.0f;
1055 for (int d = 0; d < D; ++d) {
1056 float x_hat = x[d] * rstd;
1057 sum_dY_g_xhat += dY[d] * gamma[d] * x_hat;
1058 }
1059 float m = sum_dY_g_xhat / (float)D;
1060
1061 // Compute dX and accumulate dGamma
1062 for (int d = 0; d < D; ++d) {
1063 float x_hat = x[d] * rstd;
1064 float dy = dY[d];
1065 dX[d] = rstd * (dy * gamma[d] - x_hat * m);
1066 d_gamma[d] += dy * x_hat;
1067 }
1068#endif
1069
1070 // Zero padding gradients (if any)
1071 for (int d = D; d < aligned; ++d) {
1072 dX[d] = 0.0f;
1073 }
1074 }
1075}
static void rmsnorm_backward_strict_scalar(const float *d_output, const float *input, const float *gamma, const float *rstd_cache, float *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim)

References ck_strict_parity_enabled(), and rmsnorm_backward_strict_scalar().

Referenced by ck_layer_backward_rmsnorm_swiglu(), rmsnorm_backward_int4(), and rmsnorm_backward_int8().

◆ rmsnorm_backward_bf16()

void rmsnorm_backward_bf16 ( const uint16_t *  d_output,
const uint16_t *  input,
const float *  gamma,
const float *  rstd_cache,
uint16_t *  d_input,
float *  d_gamma,
int  tokens,
int  d_model,
int  aligned_embed_dim 
)

Definition at line 113 of file rmsnorm_kernels_bf16.c.

122{
123 int T = tokens;
124 int D = d_model;
125 int aligned = aligned_embed_dim;
126
127 if (!d_output || !input || !gamma || !rstd_cache || !d_input || !d_gamma) {
128 return;
129 }
130
131 // Zero parameter gradients
132#if defined(__AVX512F__)
133 {
134 int d = 0;
135 for (; d + 16 <= D; d += 16) {
136 _mm512_storeu_ps(&d_gamma[d], _mm512_setzero_ps());
137 }
138 for (; d < D; ++d) {
139 d_gamma[d] = 0.0f;
140 }
141 }
142#else
143 for (int d = 0; d < D; ++d) {
144 d_gamma[d] = 0.0f;
145 }
146#endif
147
148 for (int t = 0; t < T; ++t) {
149 const uint16_t *x_bf16 = input + (size_t)t * aligned;
150 const uint16_t *dY_bf16 = d_output + (size_t)t * aligned;
151 uint16_t *dX_bf16 = d_input + (size_t)t * aligned;
152 float rstd = rstd_cache[t];
153
154#if defined(__AVX512F__)
155 // Compute m = (1/D) * sum_j (dY_j * gamma_j * x_hat_j)
156 __m512 rstd_vec = _mm512_set1_ps(rstd);
157 __m512 sum_vec = _mm512_setzero_ps();
158 int d = 0;
159
160 for (; d + 16 <= D; d += 16) {
161 __m512 xv = bf16_loadu_cvt_fp32(&x_bf16[d]);
162 __m512 dyv = bf16_loadu_cvt_fp32(&dY_bf16[d]);
163 __m512 gv = _mm512_loadu_ps(&gamma[d]);
164 __m512 x_hat = _mm512_mul_ps(xv, rstd_vec);
165 // sum += dY * gamma * x_hat
166 __m512 prod = _mm512_mul_ps(dyv, gv);
167 sum_vec = _mm512_fmadd_ps(prod, x_hat, sum_vec);
168 }
169 float sum_dY_g_xhat = _mm512_reduce_add_ps(sum_vec);
170
171 // Handle remaining elements
172 for (; d < D; ++d) {
173 float x = bf16_to_float(x_bf16[d]);
174 float x_hat = x * rstd;
175 float dy = bf16_to_float(dY_bf16[d]);
176 sum_dY_g_xhat += dy * gamma[d] * x_hat;
177 }
178 float m = sum_dY_g_xhat / (float)D;
179
180 // Compute dX and accumulate dGamma (vectorized)
181 __m512 m_vec = _mm512_set1_ps(m);
182 d = 0;
183 for (; d + 16 <= D; d += 16) {
184 __m512 xv = bf16_loadu_cvt_fp32(&x_bf16[d]);
185 __m512 dyv = bf16_loadu_cvt_fp32(&dY_bf16[d]);
186 __m512 gv = _mm512_loadu_ps(&gamma[d]);
187 __m512 dgv = _mm512_loadu_ps(&d_gamma[d]);
188
189 __m512 x_hat = _mm512_mul_ps(xv, rstd_vec);
190
191 // dX = rstd * (dY * gamma - x_hat * m)
192 __m512 dy_g = _mm512_mul_ps(dyv, gv);
193 __m512 xhat_m = _mm512_mul_ps(x_hat, m_vec);
194 __m512 diff = _mm512_sub_ps(dy_g, xhat_m);
195 __m512 dxv = _mm512_mul_ps(rstd_vec, diff);
196 fp32_cvt_storeu_bf16(&dX_bf16[d], dxv);
197
198 // d_gamma += dY * x_hat
199 dgv = _mm512_fmadd_ps(dyv, x_hat, dgv);
200 _mm512_storeu_ps(&d_gamma[d], dgv);
201 }
202 // Handle remaining elements
203 for (; d < D; ++d) {
204 float x = bf16_to_float(x_bf16[d]);
205 float x_hat = x * rstd;
206 float dy = bf16_to_float(dY_bf16[d]);
207 float dx = rstd * (dy * gamma[d] - x_hat * m);
208 dX_bf16[d] = float_to_bf16(dx);
209 d_gamma[d] += dy * x_hat;
210 }
211
212#else
213 // Scalar fallback
214 double sum_dY_g_xhat = 0.0;
215 for (int d = 0; d < D; ++d) {
216 float x = bf16_to_float(x_bf16[d]);
217 float x_hat = x * rstd;
218 float dy = bf16_to_float(dY_bf16[d]);
219 sum_dY_g_xhat += (double)dy * (double)gamma[d] * (double)x_hat;
220 }
221 float m = (float)(sum_dY_g_xhat / (double)D);
222
223 for (int d = 0; d < D; ++d) {
224 float x = bf16_to_float(x_bf16[d]);
225 float x_hat = x * rstd;
226 float dy = bf16_to_float(dY_bf16[d]);
227 float dx = rstd * (dy * gamma[d] - x_hat * m);
228 dX_bf16[d] = float_to_bf16(dx);
229 d_gamma[d] += dy * x_hat;
230 }
231#endif
232
233 // Zero padding gradients
234 for (int d = D; d < aligned; ++d) {
235 dX_bf16[d] = 0;
236 }
237 }
238}

References bf16_to_float(), and float_to_bf16().

◆ rmsnorm_backward_int4()

void rmsnorm_backward_int4 ( const uint8_t *  d_output,
const uint8_t *  input,
const float *  gamma,
const float *  rstd_cache,
uint8_t *  d_input,
float *  d_gamma,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float *  scratch_d_output,
float *  scratch_input,
float *  scratch_d_input 
)

Definition at line 104 of file rmsnorm_kernels_int4.c.

116{
117 if (!d_output || !input || !gamma || !rstd_cache || !d_input || !d_gamma) return;
118 if (!scratch_d_output || !scratch_input || !scratch_d_input) return;
119
120 size_t total = (size_t)tokens * (size_t)aligned_embed_dim;
121
122 convert_int4_to_float(d_output, scratch_d_output, total);
123 convert_int4_to_float(input, scratch_input, total);
124
125 for (int d = 0; d < d_model; ++d) {
126 d_gamma[d] = 0.0f;
127 }
128
129 rmsnorm_backward(scratch_d_output,
130 scratch_input,
131 gamma,
132 rstd_cache,
133 scratch_d_input,
134 d_gamma,
135 tokens,
136 d_model,
137 aligned_embed_dim);
138
139 convert_float_to_int4(scratch_d_input, d_input, total);
140}
void rmsnorm_backward(const float *d_output, const float *input, const float *gamma, const float *rstd_cache, float *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim)
static void convert_int4_to_float(const uint8_t *src, float *dst, size_t count)
static void convert_float_to_int4(const float *src, uint8_t *dst, size_t count)

References convert_float_to_int4(), convert_int4_to_float(), and rmsnorm_backward().

◆ rmsnorm_backward_int8()

void rmsnorm_backward_int8 ( const int8_t *  d_output,
const int8_t *  input,
const float *  gamma,
const float *  rstd_cache,
int8_t *  d_input,
float *  d_gamma,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float *  scratch_d_output,
float *  scratch_input,
float *  scratch_d_input 
)

Definition at line 84 of file rmsnorm_kernels_int8.c.

96{
97 if (!d_output || !input || !gamma || !rstd_cache || !d_input || !d_gamma) return;
98 if (!scratch_d_output || !scratch_input || !scratch_d_input) return;
99
100 size_t total = (size_t)tokens * (size_t)aligned_embed_dim;
101
102 convert_int8_to_float(d_output, scratch_d_output, total);
103 convert_int8_to_float(input, scratch_input, total);
104
105 // Zero gamma gradient before accumulation.
106 for (int d = 0; d < d_model; ++d) {
107 d_gamma[d] = 0.0f;
108 }
109
110 rmsnorm_backward(scratch_d_output,
111 scratch_input,
112 gamma,
113 rstd_cache,
114 scratch_d_input,
115 d_gamma,
116 tokens,
117 d_model,
118 aligned_embed_dim);
119
120 convert_float_to_int8(scratch_d_input, d_input, total);
121}
static void convert_int8_to_float(const int8_t *src, float *dst, size_t count)
static void convert_float_to_int8(const float *src, int8_t *dst, size_t count)

References convert_float_to_int8(), convert_int8_to_float(), and rmsnorm_backward().

◆ rmsnorm_forward()

void rmsnorm_forward ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 735 of file rmsnorm_kernels.c.

743{
745 input,
746 gamma,
747 output,
748 rstd_cache,
749 tokens,
750 d_model,
751 aligned_embed_dim,
752 aligned_embed_dim,
753 eps
754 );
755}
void rmsnorm_forward_strided_f32(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int input_stride, int output_stride, float eps)

References rmsnorm_forward_strided_f32().

Referenced by ck_layer_forward_rmsnorm_swiglu(), ck_layer_forward_rmsnorm_swiglu_decode(), ck_layer_forward_rmsnorm_swiglu_decode_fused(), ck_layer_forward_rmsnorm_swiglu_decode_fused_attn_impl(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), ck_layer_forward_rmsnorm_swiglu_decode_quant(), ck_layer_forward_rmsnorm_swiglu_q4_k(), ck_layer_forward_rmsnorm_swiglu_quant(), ck_layer_forward_rmsnorm_swiglu_ref(), mega_fused_outproj_mlp_prefill(), model_decode_token(), model_decode_token(), model_decode_token(), model_decode_token(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_forward_prefill_impl(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_decode_token(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), qwen2_0_5b_decode_forward_prefill_impl(), 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_0_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), 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_10_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), 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_11_decode(), qwen2_0_5b_decode_layer_11_decode(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), 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_12_decode(), qwen2_0_5b_decode_layer_12_decode(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), 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_13_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), 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_14_decode(), qwen2_0_5b_decode_layer_14_decode(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), 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_15_decode(), qwen2_0_5b_decode_layer_15_decode(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), 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_16_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), 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_17_decode(), qwen2_0_5b_decode_layer_17_decode(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), 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_18_decode(), qwen2_0_5b_decode_layer_18_decode(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), 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_19_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), 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_1_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), 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_20_decode(), qwen2_0_5b_decode_layer_20_decode(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), 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_21_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), 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_22_decode(), qwen2_0_5b_decode_layer_22_decode(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), 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_23_decode(), qwen2_0_5b_decode_layer_23_decode(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), 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_2_decode(), qwen2_0_5b_decode_layer_2_decode(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), 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_3_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), 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_4_decode(), qwen2_0_5b_decode_layer_4_decode(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), 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_5_decode(), qwen2_0_5b_decode_layer_5_decode(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), 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_6_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), 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_7_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), 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_8_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_prefill(), qwen2_0_5b_decode_layer_9_prefill(), qwen2_0_5b_decode_layer_9_prefill(), qwen2_0_5b_decode_layer_9_prefill(), rmsnorm_forward_int4(), and rmsnorm_forward_int8().

◆ rmsnorm_forward_bf16()

void rmsnorm_forward_bf16 ( const uint16_t *  input,
const float *  gamma,
uint16_t *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 24 of file rmsnorm_kernels_bf16.c.

32{
33 int T = tokens;
34 int D = d_model;
35 int aligned = aligned_embed_dim;
36
37 for (int t = 0; t < T; ++t) {
38 const uint16_t *x_bf16 = input + (size_t)t * aligned;
39 float *rstd_ptr = rstd_cache ? (rstd_cache + t) : NULL;
40 uint16_t *out_bf16 = output + (size_t)t * aligned;
41
42#if defined(__AVX512F__)
43 // AVX-512: Process 16 floats at a time
44 __m512 sum_sq_vec = _mm512_setzero_ps();
45 int d = 0;
46
47 // Vectorized sum of squares
48 for (; d + 16 <= D; d += 16) {
49 __m512 xv = bf16_loadu_cvt_fp32(&x_bf16[d]);
50 sum_sq_vec = _mm512_fmadd_ps(xv, xv, sum_sq_vec);
51 }
52 float sum_sq = _mm512_reduce_add_ps(sum_sq_vec);
53
54 // Handle remaining elements
55 for (; d < D; ++d) {
56 float x = bf16_to_float(x_bf16[d]);
57 sum_sq += x * x;
58 }
59
60 float mean_sq = sum_sq / (float)D;
61 float rstd = 1.0f / sqrtf(mean_sq + eps);
62 if (rstd_ptr) {
63 *rstd_ptr = rstd;
64 }
65
66 // Apply normalization and scale (vectorized)
67 __m512 rstd_vec = _mm512_set1_ps(rstd);
68 d = 0;
69 for (; d + 16 <= D; d += 16) {
70 __m512 xv = bf16_loadu_cvt_fp32(&x_bf16[d]);
71 __m512 gv = _mm512_loadu_ps(&gamma[d]);
72 __m512 x_hat = _mm512_mul_ps(xv, rstd_vec);
73 __m512 yv = _mm512_mul_ps(x_hat, gv);
74 fp32_cvt_storeu_bf16(&out_bf16[d], yv);
75 }
76 // Handle remaining elements
77 for (; d < D; ++d) {
78 float x = bf16_to_float(x_bf16[d]);
79 float y = x * rstd * gamma[d];
80 out_bf16[d] = float_to_bf16(y);
81 }
82
83#else
84 // Scalar fallback
85 double sum_sq = 0.0;
86 for (int d = 0; d < D; ++d) {
87 float x = bf16_to_float(x_bf16[d]);
88 sum_sq += (double)x * (double)x;
89 }
90 double mean_sq = sum_sq / (double)D;
91 double r = sqrt(mean_sq + (double)eps);
92 float rstd = (float)(1.0 / r);
93 if (rstd_ptr) {
94 *rstd_ptr = rstd;
95 }
96
97 for (int d = 0; d < D; ++d) {
98 float x = bf16_to_float(x_bf16[d]);
99 float x_hat = x * rstd;
100 float y = x_hat * gamma[d];
101 out_bf16[d] = float_to_bf16(y);
102 }
103#endif
104
105 // Zero padding
106 for (int d = D; d < aligned; ++d) {
107 out_bf16[d] = 0;
108 }
109 }
110}

References bf16_to_float(), and float_to_bf16().

◆ rmsnorm_forward_fp32_square_fp64_sum()

void rmsnorm_forward_fp32_square_fp64_sum ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

◆ rmsnorm_forward_fp64_sum()

void rmsnorm_forward_fp64_sum ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 154 of file rmsnorm_kernels.c.

162{
163 for (int t = 0; t < tokens; ++t) {
164 const float *x = input + (size_t)t * (size_t)aligned_embed_dim;
165 float *y = output + (size_t)t * (size_t)aligned_embed_dim;
166 /* This provider's contract requires an ascending scalar reduction.
167 * Keep the accumulator volatile so whole-program optimization cannot
168 * reassociate the sum or replace it with SIMD partial reductions. */
169 volatile double sum_sq = 0.0;
170 for (int d = 0; d < d_model; ++d) {
171 const float square = x[d] * x[d];
172 sum_sq = sum_sq + (double)square;
173 }
174 const float mean_sq = (float)(sum_sq / (double)d_model);
175 const float rstd = 1.0f / sqrtf(mean_sq + eps);
176 if (rstd_cache) {
177 rstd_cache[t] = rstd;
178 }
179 for (int d = 0; d < d_model; ++d) {
180 const float normalized = x[d] * rstd;
181 y[d] = normalized * gamma[d];
182 }
183 for (int d = d_model; d < aligned_embed_dim; ++d) {
184 y[d] = 0.0f;
185 }
186 }
187}

◆ rmsnorm_forward_int4()

void rmsnorm_forward_int4 ( const uint8_t *  input,
const float *  gamma,
uint8_t *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps,
float *  scratch_input,
float *  scratch_output 
)

Definition at line 78 of file rmsnorm_kernels_int4.c.

88{
89 if (!input || !gamma || !output) return;
90 if (!scratch_input || !scratch_output) return;
91
92 size_t total = (size_t)tokens * (size_t)aligned_embed_dim;
93
94 convert_int4_to_float(input, scratch_input, total);
95 rmsnorm_forward(scratch_input, gamma, scratch_output, rstd_cache,
96 tokens, d_model, aligned_embed_dim, eps);
97 convert_float_to_int4(scratch_output, output, total);
98}
void rmsnorm_forward(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References convert_float_to_int4(), convert_int4_to_float(), and rmsnorm_forward().

◆ rmsnorm_forward_int8()

void rmsnorm_forward_int8 ( const int8_t *  input,
const float *  gamma,
int8_t *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps,
float *  scratch_input,
float *  scratch_output 
)

Definition at line 58 of file rmsnorm_kernels_int8.c.

68{
69 if (!input || !gamma || !output) return;
70 if (!scratch_input || !scratch_output) return;
71
72 size_t total = (size_t)tokens * (size_t)aligned_embed_dim;
73
74 convert_int8_to_float(input, scratch_input, total);
75 rmsnorm_forward(scratch_input, gamma, scratch_output, rstd_cache,
76 tokens, d_model, aligned_embed_dim, eps);
77 convert_float_to_int8(scratch_output, output, total);
78}

References convert_float_to_int8(), convert_int8_to_float(), and rmsnorm_forward().

◆ rmsnorm_forward_kv_lora()

void rmsnorm_forward_kv_lora ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 757 of file rmsnorm_kernels.c.

765{
766 rmsnorm_forward(input, gamma, output, rstd_cache, tokens, d_model, aligned_embed_dim, eps);
767}
void rmsnorm_forward(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)

References rmsnorm_forward().

◆ rmsnorm_forward_llama_production()

void rmsnorm_forward_llama_production ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 213 of file rmsnorm_kernels.c.

221{
222 for (int t = 0; t < tokens; ++t) {
223 const float *x = input + (size_t)t * (size_t)aligned_embed_dim;
224 float *y = output + (size_t)t * (size_t)aligned_embed_dim;
225 volatile double sum_sq = 0.0;
226 for (int d = 0; d < d_model; ++d) {
227 const float square = x[d] * x[d];
228 sum_sq = sum_sq + (double)square;
229 }
230 const float mean_sq = (float)(sum_sq / (double)d_model);
231 const float rstd = rmsnorm_llama_production_rstd(mean_sq + eps);
232 if (rstd_cache) {
233 rstd_cache[t] = rstd;
234 }
235 for (int d = 0; d < d_model; ++d) {
236 /*
237 * Keep the RMSNorm + scale expression fused at the source level.
238 * llama.cpp's CPU graph fuses GGML_OP_RMS_NORM followed by
239 * GGML_OP_MUL and evaluates this left-associative expression in
240 * one kernel. Materializing the normalized value as a named
241 * float introduces a store/load rounding boundary under ICX and
242 * differs by one ULP for otherwise identical inputs.
243 */
244 y[d] = x[d] * rstd * gamma[d];
245 }
246 for (int d = d_model; d < aligned_embed_dim; ++d) {
247 y[d] = 0.0f;
248 }
249 }
250}
static float rmsnorm_llama_production_rstd(float mean_eps)

References rmsnorm_llama_production_rstd().

Referenced by qwen4_group_rmsnorm_llama(), recurrent_norm_gate_llama_avx2_forward(), and recurrent_norm_sigmoid_gate_llama_avx2_forward().

◆ rmsnorm_forward_muse_centered_pytorch_bf16_storage()

void rmsnorm_forward_muse_centered_pytorch_bf16_storage ( const float *  input,
const float *  zero_centered_weight,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 470 of file rmsnorm_kernels.c.

479{
481 input, zero_centered_weight, output, rstd_cache, tokens, d_model,
482 aligned_embed_dim, aligned_embed_dim, eps, 2, 0);
483}
static void rmsnorm_forward_pytorch_bf16_storage_impl(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int input_stride, int output_stride, float eps, int weight_mode, int use_pow_inverse)

References rmsnorm_forward_pytorch_bf16_storage_impl().

◆ rmsnorm_forward_muse_unweighted_pytorch_bf16_storage()

void rmsnorm_forward_muse_unweighted_pytorch_bf16_storage ( const float *  input,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 500 of file rmsnorm_kernels.c.

508{
510 input, NULL, output, rstd_cache, tokens, d_model,
511 aligned_embed_dim, aligned_embed_dim, eps, 3, 0);
512}

References rmsnorm_forward_pytorch_bf16_storage_impl().

◆ rmsnorm_forward_muse_weighted_pytorch_bf16_storage()

void rmsnorm_forward_muse_weighted_pytorch_bf16_storage ( const float *  input,
const float *  weight,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 485 of file rmsnorm_kernels.c.

494{
496 input, weight, output, rstd_cache, tokens, d_model,
497 aligned_embed_dim, aligned_embed_dim, eps, 1, 0);
498}

References rmsnorm_forward_pytorch_bf16_storage_impl().

◆ rmsnorm_forward_no_weight()

void rmsnorm_forward_no_weight ( const float *  input,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 769 of file rmsnorm_kernels.c.

776{
777 if (!input || !output || tokens <= 0 || d_model <= 0 || aligned_embed_dim <= 0) {
778 return;
779 }
780 const float inv_d = 1.0f / (float)d_model;
781 for (int t = 0; t < tokens; ++t) {
782 const float *x = input + (size_t)t * (size_t)aligned_embed_dim;
783 float *y = output + (size_t)t * (size_t)aligned_embed_dim;
784 double sum_sq = 0.0;
785 for (int d = 0; d < d_model; ++d) {
786 sum_sq += (double)x[d] * (double)x[d];
787 }
788 const float rstd = 1.0f / sqrtf((float)(sum_sq * (double)inv_d) + eps);
789 if (rstd_cache) {
790 rstd_cache[t] = rstd;
791 }
792 for (int d = 0; d < d_model; ++d) {
793 y[d] = x[d] * rstd;
794 }
795 for (int d = d_model; d < aligned_embed_dim; ++d) {
796 y[d] = 0.0f;
797 }
798 }
799}

◆ rmsnorm_forward_no_weight_llama_production()

void rmsnorm_forward_no_weight_llama_production ( const float *  input,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 806 of file rmsnorm_kernels.c.

813{
814 if (!input || !output || tokens <= 0 || d_model <= 0 || aligned_embed_dim < d_model) {
815 return;
816 }
817 for (int t = 0; t < tokens; ++t) {
818 const float *x = input + (size_t)t * (size_t)aligned_embed_dim;
819 float *y = output + (size_t)t * (size_t)aligned_embed_dim;
820 volatile double sum_sq = 0.0;
821 for (int d = 0; d < d_model; ++d) {
822 const float square = x[d] * x[d];
823 sum_sq = sum_sq + (double)square;
824 }
825 const float mean_sq = (float)(sum_sq / (double)d_model);
826 const float rstd = rmsnorm_llama_production_rstd(mean_sq + eps);
827 if (rstd_cache) {
828 rstd_cache[t] = rstd;
829 }
830 for (int d = 0; d < d_model; ++d) {
831 y[d] = x[d] * rstd;
832 }
833 for (int d = d_model; d < aligned_embed_dim; ++d) {
834 y[d] = 0.0f;
835 }
836 }
837}

References rmsnorm_llama_production_rstd().

Referenced by gemma4_v_norm_forward().

◆ rmsnorm_forward_parallel_dispatch()

void rmsnorm_forward_parallel_dispatch ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

◆ rmsnorm_forward_pytorch_bf16_storage()

void rmsnorm_forward_pytorch_bf16_storage ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 426 of file rmsnorm_kernels.c.

434{
436 input, gamma, output, rstd_cache, tokens, d_model,
437 aligned_embed_dim, aligned_embed_dim, eps, 0, 0);
438}

References rmsnorm_forward_pytorch_bf16_storage_impl().

Referenced by recurrent_norm_gate_pytorch_bf16_storage(), and recurrent_norm_sigmoid_gate_pytorch_bf16_storage().

◆ rmsnorm_forward_qwen3next_pytorch_bf16_storage()

void rmsnorm_forward_qwen3next_pytorch_bf16_storage ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  aligned_embed_dim,
float  eps 
)

Definition at line 455 of file rmsnorm_kernels.c.

464{
466 input, gamma, output, rstd_cache, tokens, d_model,
467 aligned_embed_dim, aligned_embed_dim, eps, 1, 0);
468}

References rmsnorm_forward_pytorch_bf16_storage_impl().

Referenced by hyper_connection_mix_bf16(), and qwen4_group_rmsnorm_pytorch_bf16().

◆ rmsnorm_forward_strided_f32()

void rmsnorm_forward_strided_f32 ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  input_stride,
int  output_stride,
float  eps 
)

RMSNorm forward pass

Test:

test_rmsnorm.py::TestRMSNormForward::test_fp32_tokens

test_rmsnorm.py::TestRMSNormForward::test_fp32_single

test_rmsnorm.py::TestRMSNormForward::test_perf_rolled

test_layernorm.py::TestLayerNormForward::test_rmsnorm_compat

test_parity.py::test_rmsnorm_parity

RMSNorm: y[i] = gamma[i] * x[i] / sqrt(mean(x^2) + eps)

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

Definition at line 567 of file rmsnorm_kernels.c.

576{
577 int T = tokens;
578 int D = d_model;
579
580 const char *exact_env = getenv("CK_RMSNORM_EXACT");
581 if (ck_strict_parity_enabled() || (exact_env && atoi(exact_env) != 0)) {
583 input, gamma, output, rstd_cache, T, D, input_stride, output_stride, eps
584 );
585 return;
586 }
587
588 for (int t = 0; t < T; ++t) {
589 const float *x = input + (size_t)t * (size_t)input_stride;
590 float *y = output + (size_t)t * (size_t)output_stride;
591
592#if defined(__AVX512F__)
593 // AVX-512: Process 16 floats at a time
594 __m512 sum_sq_vec = _mm512_setzero_ps();
595 int d = 0;
596
597 // Vectorized sum of squares
598 for (; d + 16 <= D; d += 16) {
599 __m512 xv = _mm512_loadu_ps(&x[d]);
600 sum_sq_vec = _mm512_fmadd_ps(xv, xv, sum_sq_vec);
601 }
602 float sum_sq = _mm512_reduce_add_ps(sum_sq_vec);
603
604 // Handle remaining elements
605 for (; d < D; ++d) {
606 sum_sq += x[d] * x[d];
607 }
608
609 float mean_sq = sum_sq / (float)D;
610 float rstd = 1.0f / sqrtf(mean_sq + eps);
611 if (rstd_cache) {
612 rstd_cache[t] = rstd;
613 }
614
615 // Apply normalization and scale (vectorized)
616 __m512 rstd_vec = _mm512_set1_ps(rstd);
617 d = 0;
618 for (; d + 16 <= D; d += 16) {
619 __m512 xv = _mm512_loadu_ps(&x[d]);
620 __m512 gv = _mm512_loadu_ps(&gamma[d]);
621 __m512 x_hat = _mm512_mul_ps(xv, rstd_vec);
622 __m512 yv = _mm512_mul_ps(x_hat, gv);
623 _mm512_storeu_ps(&y[d], yv);
624 }
625 // Handle remaining elements
626 for (; d < D; ++d) {
627 y[d] = x[d] * rstd * gamma[d];
628 }
629
630#elif defined(__AVX__)
631 // AVX: Process 8 floats at a time
632 __m256 sum_sq_vec = _mm256_setzero_ps();
633 int d = 0;
634
635 // Vectorized sum of squares (no FMA in AVX1, use mul + add)
636 for (; d + 8 <= D; d += 8) {
637 __m256 xv = _mm256_loadu_ps(&x[d]);
638 __m256 xv_sq = _mm256_mul_ps(xv, xv);
639 sum_sq_vec = _mm256_add_ps(sum_sq_vec, xv_sq);
640 }
641 float sum_sq = hsum256_ps_rmsnorm(sum_sq_vec);
642
643 // Handle remaining elements
644 for (; d < D; ++d) {
645 sum_sq += x[d] * x[d];
646 }
647
648 float mean_sq = sum_sq / (float)D;
649 float rstd = 1.0f / sqrtf(mean_sq + eps);
650 if (rstd_cache) {
651 rstd_cache[t] = rstd;
652 }
653
654 // Apply normalization and scale (vectorized)
655 __m256 rstd_vec = _mm256_set1_ps(rstd);
656 d = 0;
657 for (; d + 8 <= D; d += 8) {
658 __m256 xv = _mm256_loadu_ps(&x[d]);
659 __m256 gv = _mm256_loadu_ps(&gamma[d]);
660 __m256 x_hat = _mm256_mul_ps(xv, rstd_vec);
661 __m256 yv = _mm256_mul_ps(x_hat, gv);
662 _mm256_storeu_ps(&y[d], yv);
663 }
664 // Handle remaining elements
665 for (; d < D; ++d) {
666 y[d] = x[d] * rstd * gamma[d];
667 }
668
669#elif defined(__ARM_NEON) || defined(__aarch64__)
670 /* NEON: 4 floats at a time. The sum-of-squares is reassociated
671 * through four lanes (FMA accumulation, like the AVX-512 branch),
672 * so results differ from the ascending scalar order by FP32
673 * reassociation noise only; CK_RMSNORM_EXACT / strict parity mode
674 * above still selects the scalar reference. */
675 float32x4_t sum_sq_vec = vdupq_n_f32(0.0f);
676 int d = 0;
677
678 for (; d + 4 <= D; d += 4) {
679 const float32x4_t xv = vld1q_f32(&x[d]);
680 sum_sq_vec = vfmaq_f32(sum_sq_vec, xv, xv);
681 }
682 float sum_sq = hsum128_ps_rmsnorm(sum_sq_vec);
683
684 for (; d < D; ++d) {
685 sum_sq += x[d] * x[d];
686 }
687
688 float mean_sq = sum_sq / (float)D;
689 float rstd = 1.0f / sqrtf(mean_sq + eps);
690 if (rstd_cache) {
691 rstd_cache[t] = rstd;
692 }
693
694 const float32x4_t rstd_vec = vdupq_n_f32(rstd);
695 d = 0;
696 for (; d + 4 <= D; d += 4) {
697 const float32x4_t xv = vld1q_f32(&x[d]);
698 const float32x4_t gv = vld1q_f32(&gamma[d]);
699 /* Keep the two separate rounding boundaries of the scalar tail:
700 * x_hat = x * rstd, then y = x_hat * gamma (no FMA fusion). */
701 const float32x4_t x_hat = vmulq_f32(xv, rstd_vec);
702 vst1q_f32(&y[d], vmulq_f32(x_hat, gv));
703 }
704 for (; d < D; ++d) {
705 y[d] = x[d] * rstd * gamma[d];
706 }
707
708#else
709 // Scalar fallback
710 float sum_sq = 0.0f;
711 for (int d = 0; d < D; ++d) {
712 float v = x[d];
713 sum_sq += v * v;
714 }
715 float mean_sq = sum_sq / (float)D;
716 float rstd = 1.0f / sqrtf(mean_sq + eps);
717 if (rstd_cache) {
718 rstd_cache[t] = rstd;
719 }
720
721 // Apply normalization and scale
722 for (int d = 0; d < D; ++d) {
723 float x_hat = x[d] * rstd;
724 y[d] = x_hat * gamma[d];
725 }
726#endif
727
728 // Zero padding (if any)
729 for (int d = D; d < output_stride; ++d) {
730 y[d] = 0.0f;
731 }
732 }
733}
static void rmsnorm_forward_strict_scalar(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int input_stride, int output_stride, float eps)

References ck_strict_parity_enabled(), and rmsnorm_forward_strict_scalar().

Referenced by rmsnorm_forward().

◆ rmsnorm_forward_strided_pytorch_bf16_storage()

void rmsnorm_forward_strided_pytorch_bf16_storage ( const float *  input,
const float *  gamma,
float *  output,
float *  rstd_cache,
int  tokens,
int  d_model,
int  input_stride,
int  output_stride,
float  eps 
)

Definition at line 440 of file rmsnorm_kernels.c.

449{
451 input, gamma, output, rstd_cache, tokens, d_model,
452 input_stride, output_stride, eps, 0, 0);
453}

References rmsnorm_forward_pytorch_bf16_storage_impl().

◆ rope_backward()

void rope_backward ( const float *  d_out,
float *  d_x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset 
)

RoPE backward (inverse rotation)

Test:

test_rope.py::TestRoPEBackward::test_rope_backward

test_rope.py::TestRoPEBackward::test_rope_backward_vs_separate

RoPE backward: inverse rotation (rotate by -θ). Since cos(-θ) = cos(θ) and sin(-θ) = -sin(θ): d_x[2i] = d0 * c + d1 * s d_x[2i+1] = -d0 * s + d1 * c

After changes: make test

Definition at line 884 of file rope_kernels.c.

893{
894 size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
895 int half_dim = head_dim / 2;
896
897 for (int h = 0; h < num_heads; ++h) {
898 for (int t = 0; t < num_tokens; ++t) {
899 int pos = pos_offset + t;
900 const float *cos_row = cos_cache + pos * half_dim;
901 const float *sin_row = sin_cache + pos * half_dim;
902
903 size_t idx = h * head_stride + (size_t)t * (size_t)aligned_head_dim;
904 const float *d_out_row = d_out + idx;
905 float *d_x_row = d_x + idx;
906
907#if defined(__AVX512F__)
908 int i = 0;
909 for (; i + 16 <= half_dim; i += 16) {
910 __m512 d0 = _mm512_loadu_ps(&d_out_row[i]);
911 __m512 d1 = _mm512_loadu_ps(&d_out_row[i + half_dim]);
912 __m512 c = _mm512_loadu_ps(&cos_row[i]);
913 __m512 s = _mm512_loadu_ps(&sin_row[i]);
914
915 // Inverse: d_x[i] = d0 * c + d1 * s
916 __m512 r0 = _mm512_fmadd_ps(d0, c, _mm512_mul_ps(d1, s));
917 // Inverse: d_x[i+half] = -d0 * s + d1 * c
918 __m512 r1 = _mm512_fmsub_ps(d1, c, _mm512_mul_ps(d0, s));
919
920 _mm512_storeu_ps(&d_x_row[i], r0);
921 _mm512_storeu_ps(&d_x_row[i + half_dim], r1);
922 }
923 for (; i < half_dim; ++i) {
924 float d0 = d_out_row[i];
925 float d1 = d_out_row[i + half_dim];
926 float c = cos_row[i];
927 float s = sin_row[i];
928 d_x_row[i] = d0 * c + d1 * s;
929 d_x_row[i + half_dim] = -d0 * s + d1 * c;
930 }
931
932#elif defined(__AVX__)
933 int i = 0;
934 for (; i + 8 <= half_dim; i += 8) {
935 __m256 d0 = _mm256_loadu_ps(&d_out_row[i]);
936 __m256 d1 = _mm256_loadu_ps(&d_out_row[i + half_dim]);
937 __m256 c = _mm256_loadu_ps(&cos_row[i]);
938 __m256 s = _mm256_loadu_ps(&sin_row[i]);
939
940 // Inverse: d_x[i] = d0 * c + d1 * s
941 __m256 d0c = _mm256_mul_ps(d0, c);
942 __m256 d1s = _mm256_mul_ps(d1, s);
943 __m256 r0 = _mm256_add_ps(d0c, d1s);
944
945 // Inverse: d_x[i+half] = -d0 * s + d1 * c = d1 * c - d0 * s
946 __m256 d1c = _mm256_mul_ps(d1, c);
947 __m256 d0s = _mm256_mul_ps(d0, s);
948 __m256 r1 = _mm256_sub_ps(d1c, d0s);
949
950 _mm256_storeu_ps(&d_x_row[i], r0);
951 _mm256_storeu_ps(&d_x_row[i + half_dim], r1);
952 }
953 for (; i < half_dim; ++i) {
954 float d0 = d_out_row[i];
955 float d1 = d_out_row[i + half_dim];
956 float c = cos_row[i];
957 float s = sin_row[i];
958 d_x_row[i] = d0 * c + d1 * s;
959 d_x_row[i + half_dim] = -d0 * s + d1 * c;
960 }
961
962#else
963 for (int i = 0; i < half_dim; ++i) {
964 float d0 = d_out_row[i];
965 float d1 = d_out_row[i + half_dim];
966 float c = cos_row[i];
967 float s = sin_row[i];
968
969 // Inverse rotation: rotate by -θ
970 d_x_row[i] = d0 * c + d1 * s;
971 d_x_row[i + half_dim] = -d0 * s + d1 * c;
972 }
973#endif
974
975 for (int i = head_dim; i < aligned_head_dim; ++i) {
976 d_x_row[i] = 0.0f;
977 }
978 }
979 }
980}

Referenced by rope_backward_bf16(), and rope_backward_qk().

◆ rope_backward_bf16()

void rope_backward_bf16 ( const uint16_t *  d_out,
uint16_t *  d_x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
float *  scratch_d_out,
float *  scratch_d_x 
)

Definition at line 67 of file rope_kernels_bf16.c.

78{
79 if (!scratch_d_out || !scratch_d_x) return;
80
81 size_t total = (size_t)num_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
82
83 bf16_tensor_to_float(d_out, scratch_d_out, total);
84 rope_backward(scratch_d_out, scratch_d_x, cos_cache, sin_cache,
85 num_heads, num_tokens, head_dim, aligned_head_dim, pos_offset);
86 float_tensor_to_bf16(scratch_d_x, d_x, total);
87}
void rope_backward(const float *d_out, float *d_x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and rope_backward().

Referenced by rope_backward_qk_bf16().

◆ rope_backward_inplace()

void rope_backward_inplace ( float *  d_x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset 
)

RoPE backward in-place (overwrite with inverse rotation)

Test:
test_rope.py::TestRoPEBackward::test_rope_backward_inplace

In-place backward: overwrite d_out with inverse-rotated gradients. Useful when d_x == d_out is acceptable (saves memory).

After changes: make test

Definition at line 991 of file rope_kernels.c.

999{
1000 size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
1001 int half_dim = head_dim / 2;
1002
1003 for (int h = 0; h < num_heads; ++h) {
1004 for (int t = 0; t < num_tokens; ++t) {
1005 int pos = pos_offset + t;
1006 const float *cos_row = cos_cache + pos * half_dim;
1007 const float *sin_row = sin_cache + pos * half_dim;
1008
1009 float *d_row = d_x + h * head_stride + (size_t)t * (size_t)aligned_head_dim;
1010
1011#if defined(__AVX512F__)
1012 int i = 0;
1013 for (; i + 16 <= half_dim; i += 16) {
1014 __m512 d0 = _mm512_loadu_ps(&d_row[i]);
1015 __m512 d1 = _mm512_loadu_ps(&d_row[i + half_dim]);
1016 __m512 c = _mm512_loadu_ps(&cos_row[i]);
1017 __m512 s = _mm512_loadu_ps(&sin_row[i]);
1018
1019 __m512 r0 = _mm512_fmadd_ps(d0, c, _mm512_mul_ps(d1, s));
1020 __m512 r1 = _mm512_fmsub_ps(d1, c, _mm512_mul_ps(d0, s));
1021
1022 _mm512_storeu_ps(&d_row[i], r0);
1023 _mm512_storeu_ps(&d_row[i + half_dim], r1);
1024 }
1025 for (; i < half_dim; ++i) {
1026 float d0 = d_row[i];
1027 float d1 = d_row[i + half_dim];
1028 float c = cos_row[i];
1029 float s = sin_row[i];
1030 d_row[i] = d0 * c + d1 * s;
1031 d_row[i + half_dim] = -d0 * s + d1 * c;
1032 }
1033
1034#elif defined(__AVX__)
1035 int i = 0;
1036 for (; i + 8 <= half_dim; i += 8) {
1037 __m256 d0 = _mm256_loadu_ps(&d_row[i]);
1038 __m256 d1 = _mm256_loadu_ps(&d_row[i + half_dim]);
1039 __m256 c = _mm256_loadu_ps(&cos_row[i]);
1040 __m256 s = _mm256_loadu_ps(&sin_row[i]);
1041
1042 __m256 d0c = _mm256_mul_ps(d0, c);
1043 __m256 d1s = _mm256_mul_ps(d1, s);
1044 __m256 r0 = _mm256_add_ps(d0c, d1s);
1045
1046 __m256 d1c = _mm256_mul_ps(d1, c);
1047 __m256 d0s = _mm256_mul_ps(d0, s);
1048 __m256 r1 = _mm256_sub_ps(d1c, d0s);
1049
1050 _mm256_storeu_ps(&d_row[i], r0);
1051 _mm256_storeu_ps(&d_row[i + half_dim], r1);
1052 }
1053 for (; i < half_dim; ++i) {
1054 float d0 = d_row[i];
1055 float d1 = d_row[i + half_dim];
1056 float c = cos_row[i];
1057 float s = sin_row[i];
1058 d_row[i] = d0 * c + d1 * s;
1059 d_row[i + half_dim] = -d0 * s + d1 * c;
1060 }
1061
1062#else
1063 for (int i = 0; i < half_dim; ++i) {
1064 float d0 = d_row[i];
1065 float d1 = d_row[i + half_dim];
1066 float c = cos_row[i];
1067 float s = sin_row[i];
1068
1069 // Inverse rotation: rotate by -θ
1070 d_row[i] = d0 * c + d1 * s;
1071 d_row[i + half_dim] = -d0 * s + d1 * c;
1072 }
1073#endif
1074
1075 for (int i = head_dim; i < aligned_head_dim; ++i) {
1076 d_row[i] = 0.0f;
1077 }
1078 }
1079 }
1080}

◆ rope_backward_qk()

void rope_backward_qk ( const float *  d_q_out,
const float *  d_k_out,
float *  d_q,
float *  d_k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset 
)

RoPE backward for both dQ and dK

Test:
test_rope.py::TestRoPEBackward::test_rope_backward_qk

Combined RoPE backward for both dQ and dK gradients.

After changes: make test

Definition at line 2916 of file rope_kernels.c.

2928{
2929 rope_backward(d_q_out, d_q, cos_cache, sin_cache, num_heads, num_tokens, head_dim, aligned_head_dim, pos_offset);
2930 rope_backward(d_k_out, d_k, cos_cache, sin_cache, num_kv_heads, num_tokens, head_dim, aligned_head_dim, pos_offset);
2931}
void rope_backward(const float *d_out, float *d_x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset)

References rope_backward().

Referenced by ck_layer_backward_rmsnorm_swiglu().

◆ rope_backward_qk_bf16()

void rope_backward_qk_bf16 ( const uint16_t *  d_q_out,
const uint16_t *  d_k_out,
uint16_t *  d_q,
uint16_t *  d_k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
float *  scratch_dq_out,
float *  scratch_dq,
float *  scratch_dk_out,
float *  scratch_dk 
)

Definition at line 139 of file rope_kernels_bf16.c.

155{
156 if (!d_q_out || !d_k_out || !d_q || !d_k) return;
157
158 rope_backward_bf16(d_q_out, d_q, cos_cache, sin_cache,
159 num_heads, num_tokens, head_dim, aligned_head_dim, pos_offset,
160 scratch_dq_out, scratch_dq);
161 rope_backward_bf16(d_k_out, d_k, cos_cache, sin_cache,
162 num_kv_heads, num_tokens, head_dim, aligned_head_dim, pos_offset,
163 scratch_dk_out, scratch_dk);
164}
void rope_backward_bf16(const uint16_t *d_out, uint16_t *d_x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, float *scratch_d_out, float *scratch_d_x)

References rope_backward_bf16().

◆ rope_backward_qk_pairwise_with_rotary_dim()

void rope_backward_qk_pairwise_with_rotary_dim ( const float *  d_q_out,
const float *  d_k_out,
float *  d_q,
float *  d_k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim 
)

Definition at line 2933 of file rope_kernels.c.

2946{
2947 size_t q_head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
2948 size_t k_head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
2949
2950 for (int h = 0; h < num_heads; ++h) {
2952 d_q_out + (size_t)h * q_head_stride,
2953 d_q + (size_t)h * q_head_stride,
2954 cos_cache,
2955 sin_cache,
2956 num_tokens,
2957 head_dim,
2958 aligned_head_dim,
2959 pos_offset,
2960 rotary_dim
2961 );
2962 }
2963
2964 for (int h = 0; h < num_kv_heads; ++h) {
2966 d_k_out + (size_t)h * k_head_stride,
2967 d_k + (size_t)h * k_head_stride,
2968 cos_cache,
2969 sin_cache,
2970 num_tokens,
2971 head_dim,
2972 aligned_head_dim,
2973 pos_offset,
2974 rotary_dim
2975 );
2976 }
2977}
static void rope_backward_apply_head_pairwise(const float *d_out, float *d_x, const float *cos_cache, const float *sin_cache, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)

References rope_backward_apply_head_pairwise().

◆ rope_forward()

void rope_forward ( float *  x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset 
)

RoPE forward (head-major layout, in-place)

Test:

test_rope.py::TestRoPEForward::test_rope_forward

test_rope.py::TestRoPEForward::test_rope_vs_separate

test_parity.py::test_rope_parity

Applies rotary position embeddings in-place to Q or K tensor. x: [num_heads, num_tokens, head_dim] head-major

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

Definition at line 796 of file rope_kernels.c.

804{
805 rope_forward_with_rotary_dim(x, cos_cache, sin_cache, num_heads, num_tokens,
806 head_dim, aligned_head_dim, pos_offset, head_dim);
807}
void rope_forward_with_rotary_dim(float *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)

References rope_forward_with_rotary_dim().

Referenced by 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().

◆ rope_forward_bf16()

void rope_forward_bf16 ( uint16_t *  x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
float *  scratch 
)

Definition at line 28 of file rope_kernels_bf16.c.

37{
38 rope_forward_bf16_with_rotary_dim(x, cos_cache, sin_cache, num_heads, num_tokens,
39 head_dim, aligned_head_dim, pos_offset, head_dim, scratch);
40}
void rope_forward_bf16_with_rotary_dim(uint16_t *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float *scratch)

References rope_forward_bf16_with_rotary_dim().

◆ rope_forward_bf16_with_rotary_dim()

void rope_forward_bf16_with_rotary_dim ( uint16_t *  x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float *  scratch 
)

Definition at line 42 of file rope_kernels_bf16.c.

52{
53 if (!scratch) return;
54
55 size_t total = (size_t)num_heads * (size_t)num_tokens * (size_t)aligned_head_dim;
56
57 bf16_tensor_to_float(x, scratch, total);
58 rope_forward_with_rotary_dim(scratch, cos_cache, sin_cache,
59 num_heads, num_tokens, head_dim, aligned_head_dim, pos_offset, rotary_dim);
60 float_tensor_to_bf16(scratch, x, total);
61}
void rope_forward_with_rotary_dim(float *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and rope_forward_with_rotary_dim().

Referenced by rope_forward_bf16(), and rope_forward_qk_bf16_with_rotary_dim().

◆ rope_forward_q_split_direct_f32()

void rope_forward_q_split_direct_f32 ( float *  q,
const float *  freq_factors,
int  use_freq_factors,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float  freq_base 
)

Definition at line 1374 of file rope_kernels.c.

1384{
1385 rope_forward_split_direct_one(q, freq_factors, use_freq_factors,
1386 num_heads, num_tokens, head_dim, aligned_head_dim,
1387 pos_offset, rotary_dim, freq_base);
1388}
static void rope_forward_split_direct_one(float *x, const float *freq_factors, int use_freq_factors, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)

References rope_forward_split_direct_one().

◆ rope_forward_q_split_llama_f32()

void rope_forward_q_split_llama_f32 ( float *  q,
const float *  freq_factors,
int  use_freq_factors,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float  freq_base 
)

Definition at line 1390 of file rope_kernels.c.

1400{
1402 q, NULL, freq_factors, use_freq_factors,
1403 num_heads, 0, num_tokens, head_dim, aligned_head_dim,
1404 pos_offset, rotary_dim, freq_base, 0, num_tokens);
1405}
void rope_forward_qk_split_llama_token_range_f32(float *q, float *k, const float *freq_factors, int use_freq_factors, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base, int token_begin, int token_end)

References rope_forward_qk_split_llama_token_range_f32().

◆ rope_forward_qk()

void rope_forward_qk ( float *  q,
float *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset 
)

RoPE forward for both Q and K (common inference pattern)

Test:

test_rope.py::TestRoPEForward::test_rope_forward_qk

test_fused_attention_decode.py::TestFusedAttentionDecode::test_qk_rope

test_parity.py::test_rope_qk_parity

Combined RoPE forward for both Q and K in one call. q: [num_heads, num_tokens, head_dim] k: [num_kv_heads, num_tokens, head_dim]

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

Definition at line 1094 of file rope_kernels.c.

1104{
1105 rope_forward_qk_with_rotary_dim(q, k, cos_cache, sin_cache, num_heads, num_kv_heads,
1106 num_tokens, head_dim, aligned_head_dim, pos_offset, head_dim);
1107}
void rope_forward_qk_with_rotary_dim(float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)

References rope_forward_qk_with_rotary_dim().

Referenced by ck_layer_forward_rmsnorm_swiglu(), ck_layer_forward_rmsnorm_swiglu_decode(), ck_layer_forward_rmsnorm_swiglu_decode_fused(), ck_layer_forward_rmsnorm_swiglu_decode_fused_attn_impl(), ck_layer_forward_rmsnorm_swiglu_decode_q4_k(), ck_layer_forward_rmsnorm_swiglu_decode_quant(), 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_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), 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_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), 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_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), 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_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), 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_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), 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_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), 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_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), 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_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), 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_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), 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_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), 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_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), 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_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), 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_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), 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_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), 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_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), 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_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), 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_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), 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_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), 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_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), 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_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), 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_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), 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_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), 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_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_prefill(), and qwen2_0_5b_decode_layer_9_prefill().

◆ rope_forward_qk_bf16()

void rope_forward_qk_bf16 ( uint16_t *  q,
uint16_t *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
float *  scratch_q,
float *  scratch_k 
)

Definition at line 94 of file rope_kernels_bf16.c.

106{
107 rope_forward_qk_bf16_with_rotary_dim(q, k, cos_cache, sin_cache, num_heads, num_kv_heads,
108 num_tokens, head_dim, aligned_head_dim, pos_offset,
109 head_dim, scratch_q, scratch_k);
110}
void rope_forward_qk_bf16_with_rotary_dim(uint16_t *q, uint16_t *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float *scratch_q, float *scratch_k)

References rope_forward_qk_bf16_with_rotary_dim().

◆ rope_forward_qk_bf16_with_rotary_dim()

void rope_forward_qk_bf16_with_rotary_dim ( uint16_t *  q,
uint16_t *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float *  scratch_q,
float *  scratch_k 
)

Definition at line 112 of file rope_kernels_bf16.c.

125{
126 if (!q || !k) return;
127
128 rope_forward_bf16_with_rotary_dim(q, cos_cache, sin_cache,
129 num_heads, num_tokens, head_dim, aligned_head_dim, pos_offset,
130 rotary_dim, scratch_q);
131 rope_forward_bf16_with_rotary_dim(k, cos_cache, sin_cache,
132 num_kv_heads, num_tokens, head_dim, aligned_head_dim, pos_offset,
133 rotary_dim, scratch_k);
134}

References rope_forward_bf16_with_rotary_dim().

Referenced by rope_forward_qk_bf16().

◆ rope_forward_qk_gemma4_direct()

void rope_forward_qk_gemma4_direct ( float *  q,
float *  k,
const float *  freq_factors,
int  use_freq_factors,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float  freq_base 
)

Definition at line 1407 of file rope_kernels.c.

1419{
1420 rope_forward_qk_split_direct_f32(q, k, freq_factors, use_freq_factors,
1421 num_heads, num_kv_heads, num_tokens,
1422 head_dim, aligned_head_dim, pos_offset,
1423 rotary_dim, freq_base);
1424}
void rope_forward_qk_split_direct_f32(float *q, float *k, const float *freq_factors, int use_freq_factors, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)

References rope_forward_qk_split_direct_f32().

◆ rope_forward_qk_gemma4v_vision_xy()

void rope_forward_qk_gemma4v_vision_xy ( float *  q,
float *  k,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  grid_w,
int  rotary_dim,
float  freq_base 
)

Definition at line 1494 of file rope_kernels.c.

1504{
1505 rope_forward_gemma4v_vision_xy_one(q, num_heads, num_tokens, head_dim, aligned_head_dim, grid_w, rotary_dim, freq_base);
1506 rope_forward_gemma4v_vision_xy_one(k, num_kv_heads, num_tokens, head_dim, aligned_head_dim, grid_w, rotary_dim, freq_base);
1507}
static void rope_forward_gemma4v_vision_xy_one(float *x, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int grid_w, int rotary_dim, float freq_base)

References rope_forward_gemma4v_vision_xy_one().

◆ rope_forward_qk_pairwise_llama_cpu()

void rope_forward_qk_pairwise_llama_cpu ( float *  q,
float *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim 
)

Definition at line 1630 of file rope_kernels.c.

1641{
1642 if (!q || !k || !cos_cache || !sin_cache || num_tokens <= 0) {
1643 return;
1644 }
1645 if (rotary_dim <= 0 || rotary_dim > head_dim) {
1646 rotary_dim = head_dim;
1647 }
1648 const int cache_half = rotary_dim / 2;
1649 const size_t head_stride =
1650 (size_t)num_tokens * (size_t)aligned_head_dim;
1651 if (num_tokens == 1) {
1652 const float *cos_row =
1653 cos_cache + (size_t)pos_offset * (size_t)cache_half;
1654 const float *sin_row =
1655 sin_cache + (size_t)pos_offset * (size_t)cache_half;
1657 q, cos_row, sin_row, num_heads, aligned_head_dim, rotary_dim);
1659 k, cos_row, sin_row, num_kv_heads, aligned_head_dim, rotary_dim);
1660 return;
1661 }
1662 for (int token = 0; token < num_tokens; ++token) {
1663 const int pos = pos_offset + token;
1664 const float *cos_row =
1665 cos_cache + (size_t)pos * (size_t)cache_half;
1666 const float *sin_row =
1667 sin_cache + (size_t)pos * (size_t)cache_half;
1668 for (int head = 0; head < num_heads; ++head) {
1670 q + (size_t)head * head_stride
1671 + (size_t)token * (size_t)aligned_head_dim,
1672 cos_row,
1673 sin_row,
1674 1,
1675 aligned_head_dim,
1676 rotary_dim);
1677 }
1678 for (int head = 0; head < num_kv_heads; ++head) {
1680 k + (size_t)head * head_stride
1681 + (size_t)token * (size_t)aligned_head_dim,
1682 cos_row,
1683 sin_row,
1684 1,
1685 aligned_head_dim,
1686 rotary_dim);
1687 }
1688 }
1689}
static void rope_apply_decode_pairwise_llama_cpu(float *rows, const float *cos_row, const float *sin_row, int num_heads, int aligned_head_dim, int rotary_dim)

References rope_apply_decode_pairwise_llama_cpu(), and token.

◆ rope_forward_qk_pairwise_with_rotary_dim()

void rope_forward_qk_pairwise_with_rotary_dim ( float *  q,
float *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim 
)

Definition at line 1573 of file rope_kernels.c.

1584{
1585 size_t q_head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
1586 size_t k_head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
1587
1588 for (int h = 0; h < num_heads; ++h) {
1589 rope_apply_head_pairwise(q + (size_t) h * q_head_stride,
1590 cos_cache, sin_cache,
1591 num_tokens, head_dim, aligned_head_dim, pos_offset, rotary_dim);
1592 }
1593
1594 for (int h = 0; h < num_kv_heads; ++h) {
1595 rope_apply_head_pairwise(k + (size_t) h * k_head_stride,
1596 cos_cache, sin_cache,
1597 num_tokens, head_dim, aligned_head_dim, pos_offset, rotary_dim);
1598 }
1599}
static void rope_apply_head_pairwise(float *x, const float *cos_cache, const float *sin_cache, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)

References rope_apply_head_pairwise().

◆ rope_forward_qk_split_direct_f32()

void rope_forward_qk_split_direct_f32 ( float *  q,
float *  k,
const float *  freq_factors,
int  use_freq_factors,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float  freq_base 
)

Definition at line 1180 of file rope_kernels.c.

1192{
1193 rope_forward_split_direct_one(q, freq_factors, use_freq_factors,
1194 num_heads, num_tokens, head_dim, aligned_head_dim,
1195 pos_offset, rotary_dim, freq_base);
1196 rope_forward_split_direct_one(k, freq_factors, use_freq_factors,
1197 num_kv_heads, num_tokens, head_dim, aligned_head_dim,
1198 pos_offset, rotary_dim, freq_base);
1199}

References rope_forward_split_direct_one().

Referenced by rope_forward_qk_gemma4_direct().

◆ rope_forward_qk_split_direct_muse_pytorch_bf16_storage()

void rope_forward_qk_split_direct_muse_pytorch_bf16_storage ( float *  q,
float *  k,
const float *  freq_factors,
int  use_freq_factors,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float  freq_base 
)

Definition at line 1250 of file rope_kernels.c.

1263{
1264 (void)freq_factors;
1265 (void)use_freq_factors;
1267 q, num_heads, num_tokens, head_dim, aligned_head_dim,
1268 pos_offset, rotary_dim, freq_base);
1270 k, num_kv_heads, num_tokens, head_dim, aligned_head_dim,
1271 pos_offset, rotary_dim, freq_base);
1272}
static void rope_forward_split_direct_muse_bf16_one(float *x, int heads, int tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim, float freq_base)

References rope_forward_split_direct_muse_bf16_one().

◆ rope_forward_qk_split_direct_token_range_f32()

void rope_forward_qk_split_direct_token_range_f32 ( float *  q,
float *  k,
const float *  freq_factors,
int  use_freq_factors,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float  freq_base,
int  token_begin,
int  token_end 
)

Definition at line 1274 of file rope_kernels.c.

1289{
1290 if ((!q && !k) || num_tokens <= 0 || head_dim <= 0 ||
1291 aligned_head_dim <= 0 || token_begin < 0 ||
1292 token_begin >= token_end || token_end > num_tokens) {
1293 return;
1294 }
1295 if (rotary_dim <= 0 || rotary_dim > head_dim) {
1296 rotary_dim = head_dim;
1297 }
1298 if (freq_base <= 0.0f) {
1299 freq_base = 10000.0f;
1300 }
1301
1302 const int rotary_half = rotary_dim / 2;
1303 const size_t head_stride =
1304 (size_t)num_tokens * (size_t)aligned_head_dim;
1305 const float theta_scale = powf(freq_base, -2.0f / (float)rotary_dim);
1306
1307 for (int t = token_begin; t < token_end; ++t) {
1308 const float pos = (float)(pos_offset + t);
1309 for (int i = 0; i < rotary_half; ++i) {
1310 const int idx0 = i;
1311 const int idx1 = i + rotary_half;
1312 const float ff =
1313 (use_freq_factors && freq_factors) ? freq_factors[i] : 1.0f;
1314 const float theta = pos * powf(theta_scale, (float)i) / ff;
1315 const float c = cosf(theta);
1316 const float sv = sinf(theta);
1317
1318 for (int h = 0; q && h < num_heads; ++h) {
1319 float *row = q + (size_t)h * head_stride +
1320 (size_t)t * (size_t)aligned_head_dim;
1321 const float x0 = row[idx0];
1322 const float x1 = row[idx1];
1323 row[idx0] = x0 * c - x1 * sv;
1324 row[idx1] = x1 * c + x0 * sv;
1325 }
1326 for (int h = 0; k && h < num_kv_heads; ++h) {
1327 float *row = k + (size_t)h * head_stride +
1328 (size_t)t * (size_t)aligned_head_dim;
1329 const float x0 = row[idx0];
1330 const float x1 = row[idx1];
1331 row[idx0] = x0 * c - x1 * sv;
1332 row[idx1] = x1 * c + x0 * sv;
1333 }
1334 }
1335 }
1336}

◆ rope_forward_qk_split_llama_token_range_f32()

void rope_forward_qk_split_llama_token_range_f32 ( float *  q,
float *  k,
const float *  freq_factors,
int  use_freq_factors,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
float  freq_base,
int  token_begin,
int  token_end 
)

Definition at line 1338 of file rope_kernels.c.

1343{
1344 if ((!q && !k) || num_tokens <= 0 || head_dim <= 0 ||
1345 aligned_head_dim < head_dim || token_begin < 0 ||
1346 token_begin >= token_end || token_end > num_tokens) return;
1347 if (rotary_dim <= 0 || rotary_dim > head_dim) rotary_dim = head_dim;
1348 if (freq_base <= 0.0f) freq_base = 10000.0f;
1349 const int half = rotary_dim / 2;
1350 const size_t stride = (size_t)num_tokens * aligned_head_dim;
1351 const float scale = ck_rope_reference_powf(freq_base, -2.0f / rotary_dim);
1352 for (int t = token_begin; t < token_end; ++t) {
1353 /* The rounded recurrence is part of the ggml CPU numerical contract. */
1354 volatile float theta = (float)(pos_offset + t);
1355 for (int i = 0; i < half; ++i) {
1356 const float ff = use_freq_factors && freq_factors ? freq_factors[i] : 1.0f;
1357 const float angle = theta / ff;
1358 const float c = ck_rope_reference_cosf(angle);
1359 const float s = ck_rope_reference_sinf(angle);
1360 for (int h = 0; h < num_heads + num_kv_heads; ++h) {
1361 float *base = h < num_heads ? q : k;
1362 if (!base) continue;
1363 const int head = h < num_heads ? h : h - num_heads;
1364 float *row = base + (size_t)head * stride + (size_t)t * aligned_head_dim;
1365 const float x0 = row[i], x1 = row[i + half];
1366 row[i] = fmaf(x0, c, -(x1 * s));
1367 row[i + half] = fmaf(x0, s, x1 * c);
1368 }
1369 theta *= scale;
1370 }
1371 }
1372}
static float ck_rope_reference_sinf(float value)
static float ck_rope_reference_powf(float base, float exponent)
static float ck_rope_reference_cosf(float value)

References ck_rope_reference_cosf(), ck_rope_reference_powf(), and ck_rope_reference_sinf().

Referenced by rope_forward_q_split_llama_f32().

◆ rope_forward_qk_strided()

void rope_forward_qk_strided ( float *  q,
float *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  q_stride_tokens,
int  k_stride_tokens 
)

RoPE forward for both Q and K with custom strides (KV cache layouts)

Test:

test_rope.py::TestRoPEForward::test_rope_forward_qk_strided

test_kv_cache_attention.py::TestKVCacheAttention::test_qk_rope_strided

Combined QK RoPE with configurable strides for KV cache layouts.

After changes: make test

Definition at line 2868 of file rope_kernels.c.

2880{
2881 rope_forward_qk_strided_with_rotary_dim(q, k, cos_cache, sin_cache, num_heads, num_kv_heads,
2882 num_tokens, head_dim, aligned_head_dim, pos_offset,
2883 q_stride_tokens, k_stride_tokens, head_dim);
2884}
void rope_forward_qk_strided_with_rotary_dim(float *q, float *k, const float *cos_cache, const float *sin_cache, int num_heads, int num_kv_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int q_stride_tokens, int k_stride_tokens, int rotary_dim)

References rope_forward_qk_strided_with_rotary_dim().

Referenced by 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().

◆ rope_forward_qk_strided_with_rotary_dim()

void rope_forward_qk_strided_with_rotary_dim ( float *  q,
float *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  q_stride_tokens,
int  k_stride_tokens,
int  rotary_dim 
)

Definition at line 2886 of file rope_kernels.c.

2899{
2900 rope_forward_strided_with_rotary_dim(q, cos_cache, sin_cache, num_heads, num_tokens,
2901 head_dim, aligned_head_dim, pos_offset,
2902 q_stride_tokens, rotary_dim);
2903 rope_forward_strided_with_rotary_dim(k, cos_cache, sin_cache, num_kv_heads, num_tokens,
2904 head_dim, aligned_head_dim, pos_offset,
2905 k_stride_tokens, rotary_dim);
2906}
void rope_forward_strided_with_rotary_dim(float *x, const float *cos_cache, const float *sin_cache, int num_heads, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int head_stride_tokens, int rotary_dim)

References rope_forward_strided_with_rotary_dim().

Referenced by rope_forward_qk_strided().

◆ rope_forward_qk_with_rotary_dim()

void rope_forward_qk_with_rotary_dim ( float *  q,
float *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim 
)

Definition at line 1109 of file rope_kernels.c.

1120{
1121 rope_forward_with_rotary_dim(q, cos_cache, sin_cache, num_heads, num_tokens,
1122 head_dim, aligned_head_dim, pos_offset, rotary_dim);
1123 rope_forward_with_rotary_dim(k, cos_cache, sin_cache, num_kv_heads, num_tokens,
1124 head_dim, aligned_head_dim, pos_offset, rotary_dim);
1125}

References rope_forward_with_rotary_dim().

Referenced by rope_forward_qk().

◆ rope_forward_qk_with_rotary_dim_cache_stride()

void rope_forward_qk_with_rotary_dim_cache_stride ( float *  q,
float *  k,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_kv_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim,
int  cache_rotary_dim 
)

Definition at line 1509 of file rope_kernels.c.

1521{
1522 if (rotary_dim <= 0 || rotary_dim > head_dim) {
1523 rotary_dim = head_dim;
1524 }
1525 if (cache_rotary_dim < rotary_dim) {
1526 cache_rotary_dim = rotary_dim;
1527 }
1528 const int rotary_half = rotary_dim / 2;
1529 const int cache_half = cache_rotary_dim / 2;
1530 const size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
1531
1532 for (int h = 0; h < num_heads; ++h) {
1533 float *head = q + (size_t)h * head_stride;
1534 for (int t = 0; t < num_tokens; ++t) {
1535 const int pos = pos_offset + t;
1536 const float *cos_row = cos_cache + (size_t)pos * (size_t)cache_half;
1537 const float *sin_row = sin_cache + (size_t)pos * (size_t)cache_half;
1538 float *x_row = head + (size_t)t * (size_t)aligned_head_dim;
1539 for (int i = 0; i < rotary_half; ++i) {
1540 const int idx0 = 2 * i;
1541 const int idx1 = idx0 + 1;
1542 const float x0 = x_row[idx0];
1543 const float x1 = x_row[idx1];
1544 const float c = cos_row[i];
1545 const float sv = sin_row[i];
1546 x_row[idx0] = x0 * c - x1 * sv;
1547 x_row[idx1] = x0 * sv + x1 * c;
1548 }
1549 }
1550 }
1551
1552 for (int h = 0; h < num_kv_heads; ++h) {
1553 float *head = k + (size_t)h * head_stride;
1554 for (int t = 0; t < num_tokens; ++t) {
1555 const int pos = pos_offset + t;
1556 const float *cos_row = cos_cache + (size_t)pos * (size_t)cache_half;
1557 const float *sin_row = sin_cache + (size_t)pos * (size_t)cache_half;
1558 float *x_row = head + (size_t)t * (size_t)aligned_head_dim;
1559 for (int i = 0; i < rotary_half; ++i) {
1560 const int idx0 = 2 * i;
1561 const int idx1 = idx0 + 1;
1562 const float x0 = x_row[idx0];
1563 const float x1 = x_row[idx1];
1564 const float c = cos_row[i];
1565 const float sv = sin_row[i];
1566 x_row[idx0] = x0 * c - x1 * sv;
1567 x_row[idx1] = x0 * sv + x1 * c;
1568 }
1569 }
1570 }
1571}

◆ rope_forward_strided()

void rope_forward_strided ( float *  x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  head_stride_tokens 
)

RoPE forward with custom head stride (for KV cache layouts)

Test:

test_rope.py::TestRoPEForward::test_rope_strided

test_kv_cache_attention.py::TestKVCacheAttention::test_rope_decode

Variant with configurable head_stride_tokens for non-contiguous head layouts.

After changes: make test

Definition at line 837 of file rope_kernels.c.

846{
847 rope_forward_strided_with_rotary_dim(x, cos_cache, sin_cache, num_heads, num_tokens,
848 head_dim, aligned_head_dim, pos_offset,
849 head_stride_tokens, head_dim);
850}

References rope_forward_strided_with_rotary_dim().

◆ rope_forward_strided_with_rotary_dim()

void rope_forward_strided_with_rotary_dim ( float *  x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  head_stride_tokens,
int  rotary_dim 
)

Definition at line 852 of file rope_kernels.c.

862{
863 size_t head_stride = (size_t)head_stride_tokens * (size_t)aligned_head_dim;
864
865 for (int h = 0; h < num_heads; ++h) {
866 rope_apply_head(x + h * head_stride,
867 cos_cache, sin_cache,
868 num_tokens, head_dim, aligned_head_dim, pos_offset, rotary_dim);
869 }
870}
static void rope_apply_head(float *x, const float *cos_cache, const float *sin_cache, int num_tokens, int head_dim, int aligned_head_dim, int pos_offset, int rotary_dim)

References rope_apply_head().

Referenced by rope_forward_qk_strided_with_rotary_dim(), and rope_forward_strided().

◆ rope_forward_with_rotary_dim()

void rope_forward_with_rotary_dim ( float *  x,
const float *  cos_cache,
const float *  sin_cache,
int  num_heads,
int  num_tokens,
int  head_dim,
int  aligned_head_dim,
int  pos_offset,
int  rotary_dim 
)

Definition at line 809 of file rope_kernels.c.

818{
819 size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
820
821 for (int h = 0; h < num_heads; ++h) {
822 rope_apply_head(x + h * head_stride,
823 cos_cache, sin_cache,
824 num_tokens, head_dim, aligned_head_dim, pos_offset, rotary_dim);
825 }
826}

References rope_apply_head().

Referenced by rope_forward(), rope_forward_bf16_with_rotary_dim(), and rope_forward_qk_with_rotary_dim().

◆ rope_precompute_cache()

void rope_precompute_cache ( float *  cos_cache,
float *  sin_cache,
int  max_seq_len,
int  head_dim,
float  base,
int  rotary_dim,
const char *  scaling_type,
float  scaling_factor 
)

Precompute RoPE cos/sin cache with rotary_dim and scaling support

Test:

test_rope.py::TestRoPECache::test_cache_computation

test_rope.py::TestRoPECache::test_cache_values

Precomputes cos(m * theta_i) and sin(m * theta_i) for positions 0..max_seq_len-1. Only computes for first rotary_dim channels; remaining head_dim - rotary_dim channels are NOT rotated (pass through unchanged).

Scaling types:

  • "none": Standard RoPE
  • "linear": Scale positions by 1/scaling_factor
  • "dynamic": NTK-aware dynamic scaling
  • "yarn": YaRN scaling (beta-based)
Parameters
cos_cacheOutput: [max_seq_len, rotary_dim/2] cos values
sin_cacheOutput: [max_seq_len, rotary_dim/2] sin values
max_seq_lenMaximum sequence length for cache
head_dimFull head dimension (for frequency computation)
baseRoPE base frequency (theta)
rotary_dimNumber of dimensions to rotate (0 = use head_dim)
scaling_typeScaling type string: "none", "linear", "dynamic", "yarn"
scaling_factorScaling factor (1.0 = no scaling)

After changes: make test

Definition at line 384 of file rope_kernels.c.

392{
393 // Use rotary_dim = head_dim if not specified
394 if (rotary_dim <= 0 || rotary_dim > head_dim) {
395 rotary_dim = head_dim;
396 }
397
398 // Use no scaling if not specified
399 int is_linear_scaling = 0;
400 if (scaling_type != NULL && strcmp(scaling_type, "linear") == 0 && scaling_factor > 0.0f && scaling_factor != 1.0f) {
401 is_linear_scaling = 1;
402 }
403
404 int rotary_half = rotary_dim / 2;
405
406 for (int pos = 0; pos < max_seq_len; ++pos) {
407 // Apply linear scaling to position if needed
408 float effective_pos = (float)pos;
409 if (is_linear_scaling) {
410 effective_pos = (float)pos / scaling_factor;
411 }
412
413 for (int i = 0; i < rotary_half; ++i) {
414 // Match the FP32 reference contract directly. Computing this via
415 // long-double log/exp makes the final float depend on the host
416 // libm and long-double ABI.
417 const float exponent = ((float)(2 * i)) / (float)rotary_dim;
418 const float freq_f = 1.0f / powf(base, exponent);
419 float angle_f = effective_pos * freq_f;
420 cos_cache[pos * rotary_half + i] = cosf(angle_f);
421 sin_cache[pos * rotary_half + i] = sinf(angle_f);
422 }
423 }
424}

◆ rope_precompute_cache_llama_cpu()

void rope_precompute_cache_llama_cpu ( float *  cos_cache,
float *  sin_cache,
int  max_seq_len,
int  head_dim,
float  base,
int  rotary_dim,
const char *  scaling_type,
float  scaling_factor 
)

Definition at line 560 of file rope_kernels.c.

568{
569 if (!cos_cache || !sin_cache || max_seq_len <= 0 || head_dim <= 0) {
570 return;
571 }
572 if (rotary_dim <= 0 || rotary_dim > head_dim) {
573 rotary_dim = head_dim;
574 }
575 if (base <= 0.0f) {
576 base = 10000.0f;
577 }
578
579 const int linear_scaling =
580 scaling_type != NULL &&
581 strcmp(scaling_type, "linear") == 0 &&
582 scaling_factor > 0.0f &&
583 scaling_factor != 1.0f;
584 const int rotary_half = rotary_dim / 2;
585 const float theta_scale =
586 ck_rope_reference_powf(base, -2.0f / (float)rotary_dim);
587
588 for (int pos = 0; pos < max_seq_len; ++pos) {
589 float theta = (float)pos;
590 if (linear_scaling) {
591 theta /= scaling_factor;
592 }
593 for (int i = 0; i < rotary_half; ++i) {
594 cos_cache[(size_t)pos * (size_t)rotary_half + (size_t)i] =
596 sin_cache[(size_t)pos * (size_t)rotary_half + (size_t)i] =
598 theta *= theta_scale;
599 }
600 }
601}

References ck_rope_reference_cosf(), ck_rope_reference_powf(), and ck_rope_reference_sinf().

◆ rope_precompute_cache_split()

void rope_precompute_cache_split ( float *  cos_cache,
float *  sin_cache,
int  max_seq_len,
int  head_dim,
float  base 
)

Precompute RoPE cos/sin cache (split layout: head_dim/2) Legacy layout used before rotary_dim/scaling support.

Parameters
cos_cacheOutput: [max_seq_len, head_dim/2] cos values
sin_cacheOutput: [max_seq_len, head_dim/2] sin values
max_seq_lenMaximum sequence length for cache
head_dimFull head dimension
baseRoPE base frequency (theta)

Definition at line 340 of file rope_kernels.c.

345{
346 int half_dim = head_dim / 2;
347 for (int pos = 0; pos < max_seq_len; ++pos) {
348 for (int i = 0; i < half_dim; ++i) {
349 const float exponent = ((float)(2 * i)) / (float)head_dim;
350 const float freq_f = 1.0f / powf(base, exponent);
351 const float angle_f = (float)pos * freq_f;
352 cos_cache[pos * half_dim + i] = cosf(angle_f);
353 sin_cache[pos * half_dim + i] = sinf(angle_f);
354 }
355 }
356}

◆ rowwise_bias_add()

void rowwise_bias_add ( float *  x,
const float *  bias,
int  rows,
int  dim 
)

Definition at line 696 of file vision_kernels.c.

700{
701 if (!x || !bias || rows <= 0 || dim <= 0) {
702 return;
703 }
704
705 for (int r = 0; r < rows; ++r) {
706 float *row = x + ((size_t) r * (size_t) dim);
707 for (int c = 0; c < dim; ++c) {
708 row[c] += bias[c];
709 }
710 }
711}

◆ scal_copy_f32()

void scal_copy_f32 ( float *  y,
const float *  x,
float  alpha,
int  n 
)

Scaled copy: y = alpha * x.

Parameters
yOutput vector [n]
xInput vector [n]
alphaScalar multiplier
nVector length

Definition at line 156 of file axpy_kernels.c.

160{
161 if (!y || !x || n <= 0) {
162 return;
163 }
164
165 int i = 0;
166
167#ifdef __AVX512F__
168 __m512 valpha = _mm512_set1_ps(alpha);
169 for (; i + 16 <= n; i += 16) {
170 __m512 vx = _mm512_loadu_ps(&x[i]);
171 __m512 vy = _mm512_mul_ps(vx, valpha);
172 _mm512_storeu_ps(&y[i], vy);
173 }
174#endif
175
176#ifdef __AVX2__
177 __m256 valpha256 = _mm256_set1_ps(alpha);
178 for (; i + 8 <= n; i += 8) {
179 __m256 vx = _mm256_loadu_ps(&x[i]);
180 __m256 vy = _mm256_mul_ps(vx, valpha256);
181 _mm256_storeu_ps(&y[i], vy);
182 }
183#endif
184
185 for (; i < n; i++) {
186 y[i] = alpha * x[i];
187 }
188}

Referenced by weighted_sum_f32().

◆ sigmoid_backward()

void sigmoid_backward ( const float *  input,
const float *  d_output,
float *  d_input,
size_t  n 
)

Definition at line 138 of file sigmoid_kernels.c.

142{
143#if defined(__AVX512F__)
144 sigmoid_backward_avx512(input, d_output, d_input, n);
145#else
146 for (size_t i = 0; i < n; ++i) {
147 float x = input[i];
148 float s = sigmoid_scalar(x);
149 float s_prime = s * (1.0f - s);
150 d_input[i] = d_output[i] * s_prime;
151 }
152#endif
153}
float sigmoid_scalar(float x)

References sigmoid_scalar().

Referenced by sigmoid_backward_bf16().

◆ sigmoid_backward_bf16()

void sigmoid_backward_bf16 ( const uint16_t *  input,
const uint16_t *  d_output,
uint16_t *  d_input,
size_t  n,
float *  scratch_input,
float *  scratch_d_output,
float *  scratch_d_input 
)

Definition at line 45 of file sigmoid_kernels_bf16.c.

52{
53 if (!input || !d_output || !d_input || n == 0) return;
54 if (!scratch_input || !scratch_d_output || !scratch_d_input) return;
55
56 bf16_tensor_to_float(input, scratch_input, n);
57 bf16_tensor_to_float(d_output, scratch_d_output, n);
58 sigmoid_backward(scratch_input, scratch_d_output, scratch_d_input, n);
59 float_tensor_to_bf16(scratch_d_input, d_input, n);
60}
void sigmoid_backward(const float *input, const float *d_output, float *d_input, size_t n)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and sigmoid_backward().

◆ sigmoid_forward()

void sigmoid_forward ( const float *  input,
float *  output,
size_t  n 
)

Definition at line 122 of file sigmoid_kernels.c.

125{
126#if defined(__AVX512F__)
127 sigmoid_forward_avx512(input, output, n);
128#else
129 for (size_t i = 0; i < n; ++i) {
130 output[i] = sigmoid_scalar(input[i]);
131 }
132#endif
133}

References sigmoid_scalar().

Referenced by sigmoid_forward_bf16().

◆ sigmoid_forward_bf16()

void sigmoid_forward_bf16 ( const uint16_t *  input,
uint16_t *  output,
size_t  n,
float *  scratch_input,
float *  scratch_output 
)

Definition at line 27 of file sigmoid_kernels_bf16.c.

32{
33 if (!input || !output || n == 0) return;
34 if (!scratch_input || !scratch_output) return;
35
36 bf16_tensor_to_float(input, scratch_input, n);
37 sigmoid_forward(scratch_input, scratch_output, n);
38 float_tensor_to_bf16(scratch_output, output, n);
39}
void sigmoid_forward(const float *input, float *output, size_t n)

References bf16_tensor_to_float(), float_tensor_to_bf16(), and sigmoid_forward().

◆ sigmoid_scalar()

float sigmoid_scalar ( float  x)

Definition at line 26 of file sigmoid_kernels.c.

27{
28 return 1.0f / (1.0f + expf(-x));
29}

Referenced by sigmoid_backward(), sigmoid_forward(), swiglu_backward(), swiglu_backward_bf16(), swiglu_forward(), swiglu_forward_bf16(), and swiglu_forward_q8_k().

◆ softmax_cross_entropy_loss()

void softmax_cross_entropy_loss ( const float *  logits,
const int32_t *  targets,
int  tokens,
int  vocab_size,
float *  d_logits,
float *  loss_out 
)

Definition at line 259 of file loss_kernels.c.

265{
266 if (!logits || !targets || !d_logits || tokens <= 0 || vocab_size <= 0) {
267 if (loss_out) {
268 *loss_out = 0.0f;
269 }
270 return;
271 }
272
275 logits, targets, tokens, vocab_size, d_logits, loss_out);
276 return;
277 }
278
280 logits, targets, tokens, vocab_size, d_logits, loss_out, -1);
281}
static int ce_targets_all_valid_no_ignore(const int32_t *targets, int tokens, int vocab_size)
static int ce_legacy_mode_enabled(void)
static void softmax_cross_entropy_loss_index_mean_impl(const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out, int force_strict_math)
static void softmax_cross_entropy_loss_legacy_mean_impl(const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)

References ce_legacy_mode_enabled(), ce_targets_all_valid_no_ignore(), softmax_cross_entropy_loss_index_mean_impl(), softmax_cross_entropy_loss_legacy_mean_impl(), and vocab_size.

Referenced by softmax_cross_entropy_loss_bf16().

◆ softmax_cross_entropy_loss_bf16()

void softmax_cross_entropy_loss_bf16 ( const uint16_t *  logits,
const int32_t *  targets,
int  tokens,
int  vocab_size,
uint16_t *  d_logits,
float *  loss_out,
float *  scratch_logits,
float *  scratch_d_logits 
)

Definition at line 25 of file loss_kernels_bf16.c.

33{
34 if (!logits || !targets || !d_logits || tokens <= 0 || vocab_size <= 0) {
35 if (loss_out) *loss_out = 0.0f;
36 return;
37 }
38 if (!scratch_logits || !scratch_d_logits) {
39 if (loss_out) *loss_out = 0.0f;
40 return;
41 }
42
43 const size_t count = (size_t)tokens * (size_t)vocab_size;
44
45 bf16_tensor_to_float(logits, scratch_logits, count);
46 softmax_cross_entropy_loss(scratch_logits, targets, tokens, vocab_size, scratch_d_logits, loss_out);
47 float_tensor_to_bf16(scratch_d_logits, d_logits, count);
48}
void softmax_cross_entropy_loss(const float *logits, const int32_t *targets, int tokens, int vocab_size, float *d_logits, float *loss_out)

References bf16_tensor_to_float(), count, float_tensor_to_bf16(), softmax_cross_entropy_loss(), and vocab_size.

◆ softmax_cross_entropy_loss_ptref()

void softmax_cross_entropy_loss_ptref ( const float *  logits,
const int32_t *  targets,
int  tokens,
int  vocab_size,
float *  d_logits,
float *  loss_out 
)

Definition at line 292 of file loss_kernels.c.

298{
299 /*
300 * Keep a strict reference variant for parity experiments:
301 * - always uses strict math path,
302 * - same reduction / ignore semantics as default kernel.
303 */
305 logits, targets, tokens, vocab_size, d_logits, loss_out, 1);
306}

References softmax_cross_entropy_loss_index_mean_impl(), and vocab_size.

◆ spatial_average_pool_contiguous()

void spatial_average_pool_contiguous ( const float *  input,
float *  output,
int  grid_h,
int  grid_w,
int  embed_dim,
int  merge_size 
)

Definition at line 657 of file vision_kernels.c.

663{
664 if (input == NULL || output == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
665 return;
666 }
667
668 const int out_h = grid_h / merge_size;
669 const int out_w = grid_w / merge_size;
670 if (out_h <= 0 || out_w <= 0) {
671 return;
672 }
673
674 const float inv_area = 1.0f / (float)(merge_size * merge_size);
675 for (int oy = 0; oy < out_h; ++oy) {
676 for (int ox = 0; ox < out_w; ++ox) {
677 float *dst = output + ((size_t)oy * (size_t)out_w + (size_t)ox) * (size_t)embed_dim;
678 memset(dst, 0, (size_t)embed_dim * sizeof(float));
679 for (int dy = 0; dy < merge_size; ++dy) {
680 const int iy = oy * merge_size + dy;
681 for (int dx = 0; dx < merge_size; ++dx) {
682 const int ix = ox * merge_size + dx;
683 const float *src = input + ((size_t)iy * (size_t)grid_w + (size_t)ix) * (size_t)embed_dim;
684 for (int c = 0; c < embed_dim; ++c) {
685 dst[c] += src[c];
686 }
687 }
688 }
689 for (int c = 0; c < embed_dim; ++c) {
690 dst[c] *= inv_area;
691 }
692 }
693 }
694}

◆ spatial_merge_2x2()

void spatial_merge_2x2 ( const float *  input,
float *  output,
int  grid_h,
int  grid_w,
int  embed_dim 
)

Merge 2x2 neighboring tokens into a single wider token.

Input layout: [grid_h * grid_w, embed_dim] Output layout: [(grid_h/2) * (grid_w/2), embed_dim * 4]

Pack order within each merged token: top-left, top-right, bottom-left, bottom-right

Definition at line 577 of file vision_kernels.c.

582{
583 if (input == NULL || output == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0) {
584 return;
585 }
586
587 const int merged_h = grid_h / 2;
588 const int merged_w = grid_w / 2;
589 const size_t token_stride = (size_t)embed_dim;
590 const size_t merged_stride = (size_t)embed_dim * 4;
591
592 for (int mh = 0; mh < merged_h; ++mh) {
593 for (int mw = 0; mw < merged_w; ++mw) {
594 const int y0 = mh * 2;
595 const int x0 = mw * 2;
596 const int in_idx00 = y0 * grid_w + x0;
597 const int in_idx01 = in_idx00 + 1;
598 const int in_idx10 = in_idx00 + grid_w;
599 const int in_idx11 = in_idx10 + 1;
600 const int out_idx = mh * merged_w + mw;
601
602 const float *src00 = input + (size_t)in_idx00 * token_stride;
603 const float *src01 = input + (size_t)in_idx01 * token_stride;
604 const float *src10 = input + (size_t)in_idx10 * token_stride;
605 const float *src11 = input + (size_t)in_idx11 * token_stride;
606 float *dst = output + (size_t)out_idx * merged_stride;
607
608 memcpy(dst + 0 * embed_dim, src00, (size_t)embed_dim * sizeof(float));
609 memcpy(dst + 1 * embed_dim, src01, (size_t)embed_dim * sizeof(float));
610 memcpy(dst + 2 * embed_dim, src10, (size_t)embed_dim * sizeof(float));
611 memcpy(dst + 3 * embed_dim, src11, (size_t)embed_dim * sizeof(float));
612 }
613 }
614}

◆ spatial_merge_contiguous_tiled()

void spatial_merge_contiguous_tiled ( const float *  input,
float *  output,
int  grid_h,
int  grid_w,
int  embed_dim,
int  merge_size 
)

Definition at line 616 of file vision_kernels.c.

622{
623 if (input == NULL || output == NULL || grid_h <= 0 || grid_w <= 0 || embed_dim <= 0 || merge_size <= 0) {
624 return;
625 }
626
627 const size_t num_tokens = (size_t) grid_h * (size_t) grid_w;
628 const size_t merge_factor = (size_t) merge_size * (size_t) merge_size;
629 const size_t merged_tokens = num_tokens / merge_factor;
630 memcpy(output, input, merged_tokens * (size_t) embed_dim * merge_factor * sizeof(float));
631}

◆ speculative_commit_one_i32()

void speculative_commit_one_i32 ( int  accepted,
int  verified_token,
int *  token_buffer,
int *  token_count,
int  max_tokens,
int *  target_position,
int *  draft_position,
int *  accepted_count,
int *  rejected_count 
)

Commit one verified speculative token and update decode counters.

This is the minimal state transition for the first Gemma4 assistant bridge: greedy, one draft token, target remains authoritative. For this milestone the draft cache is kept synchronized with the target position after each token. Multi-token speculative decoding can later replace this with prefix accept and partial draft-cache rollback.

Definition at line 611 of file topk_kernels.c.

620{
621 int next_count = token_count ? *token_count : 0;
622 if (token_buffer && token_count && next_count >= 0 && next_count < max_tokens) {
623 token_buffer[next_count] = verified_token;
624 next_count += 1;
625 *token_count = next_count;
626 }
627
628 if (target_position) {
629 *target_position += 1;
630 if (draft_position) {
631 *draft_position = *target_position;
632 }
633 } else if (draft_position) {
634 *draft_position += 1;
635 }
636
637 if (accepted) {
638 if (accepted_count) {
639 *accepted_count += 1;
640 }
641 } else {
642 if (rejected_count) {
643 *rejected_count += 1;
644 }
645 }
646}

◆ speculative_verify_greedy_f32()

void speculative_verify_greedy_f32 ( const float *  target_logits,
int  vocab_size,
int  draft_token,
int *  accepted,
int *  verified_token 
)

Greedy one-token speculative verification.

The draft model proposes draft_token. The target model is authoritative: if draft_token equals argmax(target_logits), the candidate is accepted and emitted. Otherwise the target argmax is emitted and the draft path must be reset or rewound by the runtime loop.

Parameters
target_logitsTarget/backbone logits [vocab_size]
vocab_sizeNumber of logits
draft_tokenCandidate token from draft/assistant model
acceptedOutput scalar: 1 if accepted, 0 otherwise
verified_tokenOutput scalar: accepted draft token or target argmax

Definition at line 585 of file topk_kernels.c.

590{
591 const int target_token = argmax_f32(target_logits, vocab_size);
592 const int ok = (target_token >= 0 && draft_token == target_token) ? 1 : 0;
593
594 if (accepted) {
595 *accepted = ok;
596 }
597 if (verified_token) {
598 *verified_token = ok ? draft_token : target_token;
599 }
600}
int argmax_f32(const float *scores, int n)
Find index of maximum value.

References argmax_f32(), and vocab_size.

◆ split_q_gate_backward()

void split_q_gate_backward ( const float *  d_q,
const float *  d_gate,
float *  d_packed_qg,
int  rows,
int  q_dim,
int  gate_dim,
int  group_dim 
)

Definition at line 80 of file hybrid_attention_kernels.c.

86 {
87 const int packed_dim = q_dim + gate_dim;
88 if (!d_q || !d_gate || !d_packed_qg || rows <= 0 || q_dim <= 0 || gate_dim <= 0) {
89 return;
90 }
91 if (group_dim <= 0) {
92 group_dim = q_dim;
93 }
94 const int q_groups = q_dim / group_dim;
95 const int gate_group_dim = (q_groups > 0 && gate_dim % q_groups == 0) ? (gate_dim / q_groups) : gate_dim;
96 for (int row = 0; row < rows; ++row) {
97 const float *dq_src = d_q + (size_t) row * (size_t) q_dim;
98 const float *dg_src = d_gate + (size_t) row * (size_t) gate_dim;
99 float *dst = d_packed_qg + (size_t) row * (size_t) packed_dim;
100 if (q_groups > 0 && q_groups * group_dim == q_dim && q_groups * gate_group_dim == gate_dim) {
101 for (int group = 0; group < q_groups; ++group) {
102 const size_t dst_group_off = (size_t) group * (size_t) (group_dim + gate_group_dim);
103 memcpy(
104 dst + dst_group_off,
105 dq_src + (size_t) group * (size_t) group_dim,
106 (size_t) group_dim * sizeof(float));
107 memcpy(
108 dst + dst_group_off + (size_t) group_dim,
109 dg_src + (size_t) group * (size_t) gate_group_dim,
110 (size_t) gate_group_dim * sizeof(float));
111 }
112 } else {
113 memcpy(dst, dq_src, (size_t) q_dim * sizeof(float));
114 memcpy(dst + q_dim, dg_src, (size_t) gate_dim * sizeof(float));
115 }
116 }
117}

◆ split_q_gate_forward()

void split_q_gate_forward ( const float *  packed_qg,
float *  q,
float *  gate,
int  rows,
int  q_dim,
int  gate_dim,
int  group_dim 
)

Definition at line 41 of file hybrid_attention_kernels.c.

47 {
48 const int packed_dim = q_dim + gate_dim;
49 if (!packed_qg || !q || !gate || rows <= 0 || q_dim <= 0 || gate_dim <= 0) {
50 return;
51 }
52 if (group_dim <= 0) {
53 group_dim = q_dim;
54 }
55 const int q_groups = q_dim / group_dim;
56 const int gate_group_dim = (q_groups > 0 && gate_dim % q_groups == 0) ? (gate_dim / q_groups) : gate_dim;
57 for (int row = 0; row < rows; ++row) {
58 const float *src = packed_qg + (size_t) row * (size_t) packed_dim;
59 float *q_dst = q + (size_t) row * (size_t) q_dim;
60 float *gate_dst = gate + (size_t) row * (size_t) gate_dim;
61 if (q_groups > 0 && q_groups * group_dim == q_dim && q_groups * gate_group_dim == gate_dim) {
62 for (int group = 0; group < q_groups; ++group) {
63 const size_t src_group_off = (size_t) group * (size_t) (group_dim + gate_group_dim);
64 memcpy(
65 q_dst + (size_t) group * (size_t) group_dim,
66 src + src_group_off,
67 (size_t) group_dim * sizeof(float));
68 memcpy(
69 gate_dst + (size_t) group * (size_t) gate_group_dim,
70 src + src_group_off + (size_t) group_dim,
71 (size_t) gate_group_dim * sizeof(float));
72 }
73 } else {
74 memcpy(q_dst, src, (size_t) q_dim * sizeof(float));
75 memcpy(gate_dst, src + q_dim, (size_t) gate_dim * sizeof(float));
76 }
77 }
78}

◆ split_qkv_packed_head_major_forward()

void split_qkv_packed_head_major_forward ( const float *  packed_qkv,
float *  q,
float *  k,
float *  v,
int  rows,
int  q_dim,
int  k_dim,
int  v_dim,
int  num_heads,
int  num_kv_heads 
)

Definition at line 25 of file recurrent_split_kernels.c.

34 {
35 if (!packed_qkv || !q || !k || !v || rows <= 0 || q_dim <= 0 || k_dim <= 0 || v_dim <= 0 ||
36 num_heads <= 0 || num_kv_heads <= 0) {
37 return;
38 }
39
40 const int q_head_dim = q_dim / num_heads;
41 const int k_head_dim = k_dim / num_kv_heads;
42 const int v_head_dim = v_dim / num_kv_heads;
43 if (q_head_dim <= 0 || k_head_dim <= 0 || v_head_dim <= 0) {
44 return;
45 }
46 if (q_head_dim * num_heads != q_dim || k_head_dim * num_kv_heads != k_dim || v_head_dim * num_kv_heads != v_dim) {
47 return;
48 }
49
50 const int packed_dim = q_dim + k_dim + v_dim;
51 const size_t q_head_stride = (size_t) rows * (size_t) q_head_dim;
52 const size_t k_head_stride = (size_t) rows * (size_t) k_head_dim;
53 const size_t v_head_stride = (size_t) rows * (size_t) v_head_dim;
54
55 for (int row = 0; row < rows; ++row) {
56 const float *src = packed_qkv + (size_t) row * (size_t) packed_dim;
57
58 for (int head = 0; head < num_heads; ++head) {
59 const float *src_q = src + (size_t) head * (size_t) q_head_dim;
60 float *dst_q = q + (size_t) head * q_head_stride + (size_t) row * (size_t) q_head_dim;
61 memcpy(dst_q, src_q, (size_t) q_head_dim * sizeof(float));
62 }
63
64 const float *src_k_base = src + (size_t) q_dim;
65 const float *src_v_base = src + (size_t) q_dim + (size_t) k_dim;
66 for (int head = 0; head < num_kv_heads; ++head) {
67 const float *src_k = src_k_base + (size_t) head * (size_t) k_head_dim;
68 const float *src_v = src_v_base + (size_t) head * (size_t) v_head_dim;
69 float *dst_k = k + (size_t) head * k_head_stride + (size_t) row * (size_t) k_head_dim;
70 float *dst_v = v + (size_t) head * v_head_stride + (size_t) row * (size_t) v_head_dim;
71 memcpy(dst_k, src_k, (size_t) k_head_dim * sizeof(float));
72 memcpy(dst_v, src_v, (size_t) v_head_dim * sizeof(float));
73 }
74 }
75}

◆ ssm_conv1d_backward()

void ssm_conv1d_backward ( const float *  d_out,
const float *  conv_x,
const float *  kernel,
float *  d_conv_x,
float *  d_kernel,
int  kernel_size,
int  num_channels,
int  num_tokens,
int  num_seqs 
)

Definition at line 316 of file ssm_kernels.c.

325{
326 ssm_conv1d_backward_ref(d_out, conv_x, kernel, d_conv_x, d_kernel, kernel_size, num_channels, num_tokens, num_seqs);
327}
void ssm_conv1d_backward_ref(const float *d_out, const float *conv_x, const float *kernel, float *d_conv_x, float *d_kernel, int kernel_size, int num_channels, int num_tokens, int num_seqs)
Definition ssm_kernels.c:78

References ssm_conv1d_backward_ref().

◆ ssm_conv1d_forward()

void ssm_conv1d_forward ( const float *  conv_x,
const float *  kernel,
float *  out,
int  kernel_size,
int  num_channels,
int  num_tokens,
int  num_seqs 
)

Definition at line 128 of file ssm_kernels.c.

135{
136 ssm_conv1d_forward_ref(conv_x, kernel, out, kernel_size, num_channels, num_tokens, num_seqs);
137}
void ssm_conv1d_forward_ref(const float *conv_x, const float *kernel, float *out, int kernel_size, int num_channels, int num_tokens, int num_seqs)
Definition ssm_kernels.c:39

References ssm_conv1d_forward_ref().

◆ ssm_conv1d_forward_llama_fma()

void ssm_conv1d_forward_llama_fma ( const float *  conv_x,
const float *  kernel,
float *  out,
int  kernel_size,
int  num_channels,
int  num_tokens,
int  num_seqs 
)

Definition at line 272 of file ssm_kernels.c.

279{
280 if (!conv_x || !kernel || !out || kernel_size <= 0 || num_channels <= 0 ||
281 num_tokens < 0 || num_seqs <= 0) {
282 return;
283 }
284 ck_ssm_conv1d_llama_args_t args = {
285 conv_x, kernel, out, kernel_size, num_channels, num_tokens, num_seqs,
286 };
287 ck_threadpool_t *pool = ck_threadpool_global();
288 const int workers = pool ? ck_threadpool_n_threads(pool) : 1;
289 const int active = workers < num_channels ? workers : num_channels;
290 if (active > 1 && num_tokens > 1) {
292 pool, active, 0, num_channels, 32,
294 } else {
295 ck_ssm_conv1d_llama_fma_channel_range(0, num_channels, &args);
296 }
297}
static void ck_ssm_conv1d_llama_fma_channel_range(int begin, int end, void *opaque)

References ck_ssm_conv1d_llama_fma_channel_range(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_parallel_for_n().

◆ ssm_conv1d_forward_llama_production()

void ssm_conv1d_forward_llama_production ( const float *  conv_x,
const float *  kernel,
float *  out,
int  kernel_size,
int  num_channels,
int  num_tokens,
int  num_seqs 
)

Definition at line 207 of file ssm_kernels.c.

214{
215 if (!conv_x || !kernel || !out || kernel_size <= 0 || num_channels <= 0 ||
216 num_tokens < 0 || num_seqs <= 0) {
217 return;
218 }
219 ck_ssm_conv1d_llama_args_t args = {
220 conv_x, kernel, out, kernel_size, num_channels, num_tokens, num_seqs,
221 };
222 ck_threadpool_t *pool = ck_threadpool_global();
223 const int workers = pool ? ck_threadpool_n_threads(pool) : 1;
224 const int active = workers < num_channels ? workers : num_channels;
225 if (active > 1 && num_tokens > 1) {
227 pool, active, 0, num_channels, 32,
229 } else {
230 ck_ssm_conv1d_llama_channel_range(0, num_channels, &args);
231 }
232}
static void ck_ssm_conv1d_llama_channel_range(int begin, int end, void *opaque)

References ck_ssm_conv1d_llama_channel_range(), ck_threadpool_global(), ck_threadpool_n_threads(), and ck_threadpool_parallel_for_n().

◆ ssm_conv1d_forward_llama_production_serial()

void ssm_conv1d_forward_llama_production_serial ( const float *  conv_x,
const float *  kernel,
float *  out,
int  kernel_size,
int  num_channels,
int  num_tokens,
int  num_seqs 
)

Definition at line 189 of file ssm_kernels.c.

196{
197 if (!conv_x || !kernel || !out || kernel_size <= 0 || num_channels <= 0 ||
198 num_tokens < 0 || num_seqs <= 0) {
199 return;
200 }
201 ck_ssm_conv1d_llama_args_t args = {
202 conv_x, kernel, out, kernel_size, num_channels, num_tokens, num_seqs,
203 };
204 ck_ssm_conv1d_llama_channel_range(0, num_channels, &args);
205}

References ck_ssm_conv1d_llama_channel_range().

◆ ssm_conv1d_forward_pytorch_bf16_storage()

void ssm_conv1d_forward_pytorch_bf16_storage ( const float *  conv_x,
const float *  kernel,
float *  out,
int  kernel_size,
int  num_channels,
int  num_tokens,
int  num_seqs 
)

Definition at line 299 of file ssm_kernels.c.

306{
308 conv_x, kernel, out, kernel_size, num_channels, num_tokens, num_seqs);
309 const size_t count =
310 (size_t)num_seqs * (size_t)num_tokens * (size_t)num_channels;
311 for (size_t i = 0; i < count; ++i) {
312 out[i] = bf16_to_float(float_to_bf16(out[i]));
313 }
314}

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

◆ swiglu_backward()

void swiglu_backward ( const float *  input,
const float *  d_output,
float *  d_input,
int  tokens,
int  dim 
)

SwiGLU backward pass

Test:

test_swiglu.py::TestSwiGLUBackward::test_backward_tokens

test_swiglu.py::TestSwiGLUBackward::test_backward_single

test_parity.py::test_swiglu_backward_parity

Computes dGate and dUp given dY. dGate = dy * b * silu'(a), dUp = dy * silu(a)

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

Definition at line 432 of file swiglu_kernels.c.

437{
439 swiglu_backward_exact(input, d_output, d_input, tokens, dim);
440 return;
441 }
442
443 int T = tokens;
444 int D = dim;
445
446 for (int t = 0; t < T; ++t) {
447 const float *row = input + (size_t)t * (2 * D);
448 const float *dy_row = d_output + (size_t)t * D;
449 float *dx_row = d_input + (size_t)t * (2 * D);
450 int d = 0;
451
452#if defined(__AVX512F__)
453 // AVX-512: Process 16 floats at a time
454 __m512 one = _mm512_set1_ps(1.0f);
455 for (; d + 16 <= D; d += 16) {
456 __m512 a = _mm512_loadu_ps(&row[d]); // gate
457 __m512 b = _mm512_loadu_ps(&row[D + d]); // value
458 __m512 dy = _mm512_loadu_ps(&dy_row[d]);
459
460 __m512 s = sigmoid512_fast(a); // sigmoid(a)
461 __m512 silu = _mm512_mul_ps(a, s); // silu(a) = a * s
462 __m512 one_minus_s = _mm512_sub_ps(one, s);
463 __m512 inner = _mm512_fmadd_ps(a, one_minus_s, one); // 1 + a * (1 - s)
464 __m512 silu_prime = _mm512_mul_ps(s, inner); // s * (1 + a * (1 - s))
465
466 // dA = dy * b * silu_prime
467 __m512 dA = _mm512_mul_ps(dy, _mm512_mul_ps(b, silu_prime));
468 // dB = dy * silu
469 __m512 dB = _mm512_mul_ps(dy, silu);
470
471 _mm512_storeu_ps(&dx_row[d], dA);
472 _mm512_storeu_ps(&dx_row[D + d], dB);
473 }
474#elif defined(__AVX2__)
475 // AVX2: Process 8 floats at a time
476 __m256 one = _mm256_set1_ps(1.0f);
477 for (; d + 8 <= D; d += 8) {
478 __m256 a = _mm256_loadu_ps(&row[d]); // gate
479 __m256 b = _mm256_loadu_ps(&row[D + d]); // value
480 __m256 dy = _mm256_loadu_ps(&dy_row[d]);
481
482 __m256 s = sigmoid256_fast(a); // sigmoid(a)
483 __m256 silu = _mm256_mul_ps(a, s); // silu(a) = a * s
484 __m256 one_minus_s = _mm256_sub_ps(one, s);
485 __m256 inner = _mm256_fmadd_ps(a, one_minus_s, one); // 1 + a * (1 - s)
486 __m256 silu_prime = _mm256_mul_ps(s, inner); // s * (1 + a * (1 - s))
487
488 // dA = dy * b * silu_prime
489 __m256 dA = _mm256_mul_ps(dy, _mm256_mul_ps(b, silu_prime));
490 // dB = dy * silu
491 __m256 dB = _mm256_mul_ps(dy, silu);
492
493 _mm256_storeu_ps(&dx_row[d], dA);
494 _mm256_storeu_ps(&dx_row[D + d], dB);
495 }
496#elif defined(__AVX__)
497 // AVX1: Vectorize arithmetic, use scalar sigmoid
498 __m256 one = _mm256_set1_ps(1.0f);
499 float a_arr[8] __attribute__((aligned(32)));
500 float s_arr[8] __attribute__((aligned(32)));
501
502 for (; d + 8 <= D; d += 8) {
503 __m256 a = _mm256_loadu_ps(&row[d]); // gate
504 __m256 b = _mm256_loadu_ps(&row[D + d]); // value
505 __m256 dy = _mm256_loadu_ps(&dy_row[d]);
506
507 // Compute sigmoid scalarly
508 _mm256_store_ps(a_arr, a);
509 for (int j = 0; j < 8; ++j) {
510 s_arr[j] = sigmoid_scalar(a_arr[j]);
511 }
512 __m256 s = _mm256_load_ps(s_arr);
513
514 __m256 silu = _mm256_mul_ps(a, s); // silu(a) = a * s
515 __m256 one_minus_s = _mm256_sub_ps(one, s);
516 __m256 a_one_minus_s = _mm256_mul_ps(a, one_minus_s);
517 __m256 inner = _mm256_add_ps(one, a_one_minus_s); // 1 + a * (1 - s)
518 __m256 silu_prime = _mm256_mul_ps(s, inner); // s * (1 + a * (1 - s))
519
520 // dA = dy * b * silu_prime
521 __m256 dA = _mm256_mul_ps(dy, _mm256_mul_ps(b, silu_prime));
522 // dB = dy * silu
523 __m256 dB = _mm256_mul_ps(dy, silu);
524
525 _mm256_storeu_ps(&dx_row[d], dA);
526 _mm256_storeu_ps(&dx_row[D + d], dB);
527 }
528#endif
529
530 // Scalar fallback for remaining elements
531 for (; d < D; ++d) {
532 float a = row[d]; // gate
533 float b = row[D + d]; // value
534 float dy = dy_row[d];
535
536 float s = sigmoid_scalar(a); // sigmoid(a)
537 float silu = a * s; // silu(a)
538 float silu_prime = s * (1.0f + a * (1.0f - s)); // silu'(a), PyTorch form
539
540 float dA = dy * b * silu_prime;
541 float dB = dy * silu;
542
543 dx_row[d] = dA;
544 dx_row[D + d] = dB;
545 }
546 }
547}
float sigmoid_scalar(float x)
void swiglu_backward_exact(const float *input, const float *d_output, float *d_input, int tokens, int dim)

References __attribute__(), ck_strict_parity_enabled(), sigmoid_scalar(), silu(), and swiglu_backward_exact().

Referenced by ck_layer_backward_rmsnorm_swiglu().

◆ swiglu_backward_bf16()

void swiglu_backward_bf16 ( const uint16_t *  input,
const uint16_t *  d_output,
uint16_t *  d_input,
int  tokens,
int  dim 
)

Definition at line 108 of file swiglu_kernels_bf16.c.

113{
114 if (!input || !d_output || !d_input || tokens <= 0 || dim <= 0) {
115 return;
116 }
117
118 const int T = tokens;
119 const int D = dim;
120
121 for (int t = 0; t < T; ++t) {
122 const uint16_t *row = input + (size_t)t * (size_t)(2 * D);
123 const uint16_t *dy_row = d_output + (size_t)t * (size_t)D;
124 uint16_t *dx_row = d_input + (size_t)t * (size_t)(2 * D);
125 int d = 0;
126
127#if defined(__AVX512F__)
128 // AVX-512: Process 16 floats at a time
129 __m512 one = _mm512_set1_ps(1.0f);
130 for (; d + 16 <= D; d += 16) {
131 __m512 a = bf16_loadu_cvt_fp32(&row[d]); // gate
132 __m512 b = bf16_loadu_cvt_fp32(&row[D + d]); // value
133 __m512 dy = bf16_loadu_cvt_fp32(&dy_row[d]);
134
135 __m512 s = sigmoid512_fast_bf16(a); // sigmoid(a)
136 __m512 silu = _mm512_mul_ps(a, s); // silu(a) = a * s
137 __m512 s_prime = _mm512_mul_ps(s, _mm512_sub_ps(one, s)); // s * (1 - s)
138 __m512 silu_prime = _mm512_fmadd_ps(a, s_prime, s); // s + a * s_prime
139
140 // dA = dy * b * silu_prime
141 __m512 dA = _mm512_mul_ps(dy, _mm512_mul_ps(b, silu_prime));
142 // dB = dy * silu
143 __m512 dB = _mm512_mul_ps(dy, silu);
144
145 fp32_cvt_storeu_bf16(&dx_row[d], dA);
146 fp32_cvt_storeu_bf16(&dx_row[D + d], dB);
147 }
148#endif
149
150 // Scalar fallback for remaining elements
151 for (; d < D; ++d) {
152 float a = bf16_to_float(row[d]);
153 float b = bf16_to_float(row[D + d]);
154 float dy = bf16_to_float(dy_row[d]);
155
156 float s = sigmoid_scalar(a);
157 float silu = a * s;
158 float s_prime = s * (1.0f - s);
159 float silu_prime = s + a * s_prime;
160
161 float dA = dy * b * silu_prime;
162 float dB = dy * silu;
163
164 dx_row[d] = float_to_bf16(dA);
165 dx_row[D + d] = float_to_bf16(dB);
166 }
167 }
168}

References bf16_to_float(), float_to_bf16(), sigmoid_scalar(), and silu().

◆ swiglu_backward_exact()

void swiglu_backward_exact ( const float *  input,
const float *  d_output,
float *  d_input,
int  tokens,
int  dim 
)

SwiGLU backward pass (exact version using stdlib sigmoid)

Test:

test_swiglu.py::TestSwiGLUBackward::test_exact_vs_fast

test_swiglu.py::TestSwiGLUBackward::test_exact_single

Uses standard library expf for numerical accuracy reference.

After changes: make test

Definition at line 922 of file swiglu_kernels.c.

927{
928 int T = tokens;
929 int D = dim;
930
931 for (int t = 0; t < T; ++t) {
932 const float *row = input + (size_t)t * (2 * D);
933 const float *dy_row = d_output + (size_t)t * D;
934 float *dx_row = d_input + (size_t)t * (2 * D);
935
936 for (int d = 0; d < D; ++d) {
937 float a = row[d]; // gate
938 float b = row[D + d]; // value
939 float dy = dy_row[d];
940
941 float s = sigmoid_scalar_parity(a); // sigmoid(a)
942 float silu = a * s; // silu(a)
943 float silu_prime = s * (1.0f + a * (1.0f - s)); // silu'(a), PyTorch form
944
945 float dA = dy * b * silu_prime;
946 float dB = dy * silu;
947
948 dx_row[d] = dA;
949 dx_row[D + d] = dB;
950 }
951 }
952}
static float sigmoid_scalar_parity(float x)

References sigmoid_scalar_parity(), and silu().

Referenced by swiglu_backward().

◆ swiglu_forward()

void swiglu_forward ( const float *  input,
float *  output,
int  tokens,
int  dim 
)

SwiGLU forward pass

Test:

test_swiglu.py::TestSwiGLUForward::test_forward_tokens

test_swiglu.py::TestSwiGLUForward::test_forward_single

test_mlp.py::TestMLPForward::test_swiglu_mlp

test_fused_swiglu_decode.py::TestFusedSwiGLUDecode::test_fused_swiglu_decode

test_parity.py::test_swiglu_parity

SwiGLU: y = silu(gate) * up where silu(x) = x * sigmoid(x)

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

Definition at line 283 of file swiglu_kernels.c.

287{
288 const char *fast_env = getenv("CK_SWIGLU_FAST");
289 const char *exact_env = getenv("CK_SWIGLU_EXACT");
291 !(fast_env && atoi(fast_env) != 0) ||
292 (exact_env && atoi(exact_env) != 0)) {
293 swiglu_forward_exact(input, output, tokens, dim);
294 return;
295 }
296
297 int T = tokens;
298 int D = dim;
299
300 for (int t = 0; t < T; ++t) {
301 const float *row = input + (size_t)t * (2 * D);
302 float *out_row = output + (size_t)t * D;
303 int d = 0;
304
305#if defined(__AVX512F__)
306 // AVX-512: Process 16 floats at a time
307 for (; d + 16 <= D; d += 16) {
308 __m512 a = _mm512_loadu_ps(&row[d]); // gate
309 __m512 b = _mm512_loadu_ps(&row[D + d]); // value
310
311 __m512 s = sigmoid512_fast(a); // sigmoid(a)
312 __m512 silu = _mm512_mul_ps(a, s); // silu(a) = a * sigmoid(a)
313 __m512 y = _mm512_mul_ps(silu, b); // y = silu(a) * b
314
315 _mm512_storeu_ps(&out_row[d], y);
316 }
317#elif defined(__AVX2__)
318 // AVX2: Process 8 floats at a time
319 for (; d + 8 <= D; d += 8) {
320 __m256 a = _mm256_loadu_ps(&row[d]); // gate
321 __m256 b = _mm256_loadu_ps(&row[D + d]); // value
322
323 __m256 s = sigmoid256_fast(a); // sigmoid(a)
324 __m256 silu = _mm256_mul_ps(a, s); // silu(a) = a * sigmoid(a)
325 __m256 y = _mm256_mul_ps(silu, b); // y = silu(a) * b
326
327 _mm256_storeu_ps(&out_row[d], y);
328 }
329#elif defined(__AVX__)
330 // AVX1: Vectorize arithmetic, use scalar sigmoid
331 float a_arr[8] __attribute__((aligned(32)));
332 float s_arr[8] __attribute__((aligned(32)));
333
334 for (; d + 8 <= D; d += 8) {
335 __m256 a = _mm256_loadu_ps(&row[d]); // gate
336 __m256 b = _mm256_loadu_ps(&row[D + d]); // value
337
338 // Compute sigmoid scalarly
339 _mm256_store_ps(a_arr, a);
340 for (int j = 0; j < 8; ++j) {
341 s_arr[j] = sigmoid_scalar(a_arr[j]);
342 }
343 __m256 s = _mm256_load_ps(s_arr);
344
345 __m256 silu = _mm256_mul_ps(a, s); // silu(a) = a * sigmoid(a)
346 __m256 y = _mm256_mul_ps(silu, b); // y = silu(a) * b
347
348 _mm256_storeu_ps(&out_row[d], y);
349 }
350#endif
351
352 // Scalar fallback for remaining elements
353 for (; d < D; ++d) {
354 float a = row[d]; // gate
355 float b = row[D + d]; // value
356
357 float s = sigmoid_scalar(a); // sigmoid(a)
358 float silu = a * s; // silu(a) = a * sigmoid(a)
359
360 out_row[d] = silu * b;
361 }
362 }
363}
void swiglu_forward_exact(const float *input, float *output, int tokens, int dim)

References __attribute__(), ck_strict_parity_enabled(), sigmoid_scalar(), silu(), and swiglu_forward_exact().

Referenced by ck_mlp_swiglu_forward(), ck_mlp_swiglu_forward_q4_k(), ck_mlp_swiglu_forward_q4_k_q8_k(), ck_mlp_swiglu_forward_q4_k_q8_k_prefill(), ck_mlp_swiglu_forward_quant(), ck_mlp_swiglu_forward_ref(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_decode(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_0_prefill(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_decode(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_10_prefill(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_decode(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_11_prefill(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_decode(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_12_prefill(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_decode(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_13_prefill(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_decode(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_14_prefill(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_decode(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_15_prefill(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_decode(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_16_prefill(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_decode(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_17_prefill(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_decode(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_18_prefill(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_decode(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_19_prefill(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_decode(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_1_prefill(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_decode(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_20_prefill(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_decode(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_21_prefill(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_decode(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_22_prefill(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_decode(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_23_prefill(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_decode(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_2_prefill(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_decode(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_3_prefill(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_decode(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_4_prefill(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_decode(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_5_prefill(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_decode(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_6_prefill(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_decode(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_7_prefill(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_decode(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_8_prefill(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_decode(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), model_layer_9_prefill(), 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_0_decode(), qwen2_0_5b_decode_layer_0_decode(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), qwen2_0_5b_decode_layer_0_prefill(), 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_10_decode(), qwen2_0_5b_decode_layer_10_decode(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), qwen2_0_5b_decode_layer_10_prefill(), 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_11_decode(), qwen2_0_5b_decode_layer_11_decode(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), qwen2_0_5b_decode_layer_11_prefill(), 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_12_decode(), qwen2_0_5b_decode_layer_12_decode(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), qwen2_0_5b_decode_layer_12_prefill(), 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_13_decode(), qwen2_0_5b_decode_layer_13_decode(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), qwen2_0_5b_decode_layer_13_prefill(), 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_14_decode(), qwen2_0_5b_decode_layer_14_decode(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), qwen2_0_5b_decode_layer_14_prefill(), 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_15_decode(), qwen2_0_5b_decode_layer_15_decode(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), qwen2_0_5b_decode_layer_15_prefill(), 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_16_decode(), qwen2_0_5b_decode_layer_16_decode(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), qwen2_0_5b_decode_layer_16_prefill(), 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_17_decode(), qwen2_0_5b_decode_layer_17_decode(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), qwen2_0_5b_decode_layer_17_prefill(), 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_18_decode(), qwen2_0_5b_decode_layer_18_decode(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), qwen2_0_5b_decode_layer_18_prefill(), 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_19_decode(), qwen2_0_5b_decode_layer_19_decode(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), qwen2_0_5b_decode_layer_19_prefill(), 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_1_decode(), qwen2_0_5b_decode_layer_1_decode(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), qwen2_0_5b_decode_layer_1_prefill(), 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_20_decode(), qwen2_0_5b_decode_layer_20_decode(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), qwen2_0_5b_decode_layer_20_prefill(), 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_21_decode(), qwen2_0_5b_decode_layer_21_decode(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), qwen2_0_5b_decode_layer_21_prefill(), 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_22_decode(), qwen2_0_5b_decode_layer_22_decode(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), qwen2_0_5b_decode_layer_22_prefill(), 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_23_decode(), qwen2_0_5b_decode_layer_23_decode(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), qwen2_0_5b_decode_layer_23_prefill(), 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_2_decode(), qwen2_0_5b_decode_layer_2_decode(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), qwen2_0_5b_decode_layer_2_prefill(), 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_3_decode(), qwen2_0_5b_decode_layer_3_decode(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), qwen2_0_5b_decode_layer_3_prefill(), 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_4_decode(), qwen2_0_5b_decode_layer_4_decode(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), qwen2_0_5b_decode_layer_4_prefill(), 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_5_decode(), qwen2_0_5b_decode_layer_5_decode(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), qwen2_0_5b_decode_layer_5_prefill(), 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_6_decode(), qwen2_0_5b_decode_layer_6_decode(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), qwen2_0_5b_decode_layer_6_prefill(), 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_7_decode(), qwen2_0_5b_decode_layer_7_decode(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), qwen2_0_5b_decode_layer_7_prefill(), 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_8_decode(), qwen2_0_5b_decode_layer_8_decode(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_8_prefill(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_decode(), qwen2_0_5b_decode_layer_9_prefill(), qwen2_0_5b_decode_layer_9_prefill(), qwen2_0_5b_decode_layer_9_prefill(), and qwen2_0_5b_decode_layer_9_prefill().

◆ swiglu_forward_bf16()

void swiglu_forward_bf16 ( const uint16_t *  input,
uint16_t *  output,
int  tokens,
int  dim 
)

Definition at line 66 of file swiglu_kernels_bf16.c.

70{
71 if (!input || !output || tokens <= 0 || dim <= 0) {
72 return;
73 }
74
75 const int T = tokens;
76 const int D = dim;
77
78 for (int t = 0; t < T; ++t) {
79 const uint16_t *row = input + (size_t)t * (size_t)(2 * D);
80 uint16_t *out_row = output + (size_t)t * (size_t)D;
81 int d = 0;
82
83#if defined(__AVX512F__)
84 // AVX-512: Process 16 floats at a time
85 for (; d + 16 <= D; d += 16) {
86 __m512 a = bf16_loadu_cvt_fp32(&row[d]); // gate
87 __m512 b = bf16_loadu_cvt_fp32(&row[D + d]); // value
88
89 __m512 s = sigmoid512_fast_bf16(a); // sigmoid(a)
90 __m512 silu = _mm512_mul_ps(a, s); // silu(a) = a * sigmoid(a)
91 __m512 y = _mm512_mul_ps(silu, b); // y = silu(a) * b
92
93 fp32_cvt_storeu_bf16(&out_row[d], y);
94 }
95#endif
96
97 // Scalar fallback for remaining elements
98 for (; d < D; ++d) {
99 float a = bf16_to_float(row[d]);
100 float b = bf16_to_float(row[D + d]);
101 float s = sigmoid_scalar(a);
102 float silu = a * s;
103 out_row[d] = float_to_bf16(silu * b);
104 }
105 }
106}

References bf16_to_float(), float_to_bf16(), sigmoid_scalar(), and silu().

◆ swiglu_forward_exact()

void swiglu_forward_exact ( const float *  input,
float *  output,
int  tokens,
int  dim 
)

Definition at line 652 of file swiglu_kernels.c.

656{
657 if (!input || !output || tokens <= 0 || dim <= 0) {
658 return;
659 }
660
661 ck_swiglu_exact_args_t args = {input, output, dim};
662 ck_threadpool_t *pool = ck_threadpool_global();
663 int active = pool ? ck_threadpool_n_threads(pool) : 1;
664 ck_swiglu_dispatch_rows(pool, active, tokens, dim,
665 ck_swiglu_exact_rows, &args, input, output);
666}
static void ck_swiglu_dispatch_rows(ck_threadpool_t *pool, int active, int tokens, int dim, ck_range_fn_t fn, void *args, const float *input, float *output)
static void ck_swiglu_exact_rows(int begin, int end, void *opaque)

References ck_swiglu_dispatch_rows(), ck_swiglu_exact_rows(), ck_threadpool_global(), and ck_threadpool_n_threads().

Referenced by ck_mlp_swiglu_forward(), ck_mlp_swiglu_forward_ref(), and swiglu_forward().

◆ swiglu_forward_ggml()

void swiglu_forward_ggml ( const float *  input,
float *  output,
int  tokens,
int  dim 
)

◆ swiglu_forward_ggml_split()

void swiglu_forward_ggml_split ( const float *  gate,
const float *  up,
float *  output,
int  tokens,
int  dim 
)

Definition at line 743 of file swiglu_kernels.c.

748{
749 if (!gate || !up || !output || tokens <= 0 || dim <= 0) {
750 return;
751 }
752#if defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
753 const int force_ref = ck_swiglu_ggml_ref_forced();
754#endif
755 for (int t = 0; t < tokens; ++t) {
756 const float *gate_row = gate + (size_t)t * (size_t)dim;
757 const float *up_row = up + (size_t)t * (size_t)dim;
758 float *out_row = output + (size_t)t * (size_t)dim;
759 int d = 0;
760
761#if defined(__AVX512F__) && defined(__AVX512DQ__)
762 for (; d + 16 <= dim; d += 16) {
763 const __m512 gate_v = _mm512_loadu_ps(gate_row + d);
764 const __m512 up_v = _mm512_loadu_ps(up_row + d);
765 const __m512 neg_gate = _mm512_sub_ps(_mm512_setzero_ps(), gate_v);
766 const __m512 denom = _mm512_add_ps(
767 _mm512_set1_ps(1.0f), ck_ggml_expf_avx512(neg_gate));
768 const __m512 silu = _mm512_div_ps(gate_v, denom);
769 _mm512_storeu_ps(out_row + d, _mm512_mul_ps(silu, up_v));
770 }
771#elif defined(__AVX2__) && defined(__FMA__)
772 for (; d + 8 <= dim; d += 8) {
773 const __m256 gate_v = _mm256_loadu_ps(gate_row + d);
774 const __m256 up_v = _mm256_loadu_ps(up_row + d);
775 const __m256 neg_gate = _mm256_sub_ps(_mm256_setzero_ps(), gate_v);
776 const __m256 denom = _mm256_add_ps(
777 _mm256_set1_ps(1.0f), ck_ggml_expf_avx2(neg_gate));
778 const __m256 silu = _mm256_div_ps(gate_v, denom);
779 _mm256_storeu_ps(out_row + d, _mm256_mul_ps(silu, up_v));
780 }
781#elif defined(__ARM_NEON) && (defined(__aarch64__) || defined(__ARM_FEATURE_FMA))
782 if (!force_ref) {
783 for (; d + 4 <= dim; d += 4) {
784 const float32x4_t gate_v = vld1q_f32(gate_row + d);
785 const float32x4_t up_v = vld1q_f32(up_row + d);
786 const float32x4_t neg_gate = vsubq_f32(vdupq_n_f32(0.0f), gate_v);
787 const float32x4_t denom = vaddq_f32(
788 vdupq_n_f32(1.0f), ck_ggml_expf_neon(neg_gate));
789 const float32x4_t silu = vdivq_f32(gate_v, denom);
790 vst1q_f32(out_row + d, vmulq_f32(silu, up_v));
791 }
792 }
793#endif
794 for (; d < dim; ++d) {
795 const float gate_v = gate_row[d];
796 out_row[d] = (gate_v / (1.0f + expf(-gate_v))) * up_row[d];
797 }
798 }
799}

References silu().

Referenced by ck_moe_q4k_q5k_bucket_work(), and ck_moe_shared_q4k_gated_workspace().

◆ swiglu_forward_pytorch_bf16_storage()

void swiglu_forward_pytorch_bf16_storage ( const float *  input,
float *  output,
int  tokens,
int  dim 
)

Definition at line 861 of file swiglu_kernels.c.

865{
866 if (!input || !output || tokens < 0 || dim < 0) {
867 fprintf(stderr, "HARD KERNEL CONTRACT FAULT: invalid PyTorch BF16 SwiGLU arguments\n");
868 abort();
869 }
870
871#if defined(__AVX512F__)
872 pthread_once(&ck_pytorch_swiglu_once, ck_bind_pytorch_swiglu_sleef);
873 if (!ck_pytorch_swiglu_expf16) {
874 fprintf(stderr,
875 "HARD KERNEL CONTRACT FAULT: PyTorch BF16 SwiGLU requires "
876 "SLEEF Sleef_expf16_u10; set CK_SLEEF_LIBRARY\n");
877 abort();
878 }
879#endif
880
881 for (int t = 0; t < tokens; ++t) {
882 const float *row = input + (size_t)t * (size_t)(2 * dim);
883 float *out_row = output + (size_t)t * (size_t)dim;
884 int d = 0;
885
886#if defined(__AVX512F__)
887 for (; d + 16 <= dim; d += 16) {
888 const __m512 gate = _mm512_loadu_ps(row + d);
889 const __m512 denominator = _mm512_add_ps(
890 _mm512_set1_ps(1.0f),
891 ck_pytorch_swiglu_expf16(_mm512_sub_ps(_mm512_setzero_ps(), gate)));
892 const __m512 silu = _mm512_div_ps(gate, denominator);
893 float silu_lanes[16] __attribute__((aligned(64)));
894 _mm512_store_ps(silu_lanes, silu);
895 for (int lane = 0; lane < 16; ++lane) {
896 const float silu_bf16 = bf16_to_float(float_to_bf16(silu_lanes[lane]));
897 const float up_bf16 = bf16_to_float(float_to_bf16(row[dim + d + lane]));
898 out_row[d + lane] = bf16_to_float(
899 float_to_bf16(silu_bf16 * up_bf16));
900 }
901 }
902#endif
903 for (; d < dim; ++d) {
904 const float gate_bf16 = bf16_to_float(float_to_bf16(row[d]));
905 const float up_bf16 = bf16_to_float(float_to_bf16(row[dim + d]));
906 const float silu = gate_bf16 / (1.0f + expf(-gate_bf16));
907 const float silu_bf16 = bf16_to_float(float_to_bf16(silu));
908 out_row[d] = bf16_to_float(float_to_bf16(silu_bf16 * up_bf16));
909 }
910 }
911}

References __attribute__(), bf16_to_float(), float_to_bf16(), and silu().

Referenced by moe_swiglu_packed_expert_forward_bf16().

◆ swiglu_forward_q8_k()

void swiglu_forward_q8_k ( const float *  input,
void *  output_q8,
int  tokens,
int  dim 
)

Definition at line 365 of file swiglu_kernels.c.

369{
370 if (!input || !output_q8 || tokens <= 0 || dim <= 0) {
371 return;
372 }
373 if ((dim % QK_K) != 0) {
374 return;
375 }
376
377 const char *fast_env = getenv("CK_SWIGLU_FAST");
378 const char *exact_env = getenv("CK_SWIGLU_EXACT");
379 const int use_fast = !ck_strict_parity_enabled() &&
380 (fast_env && atoi(fast_env) != 0) &&
381 !(exact_env && atoi(exact_env) != 0);
382
383 const int blocks_per_row = dim / QK_K;
384 block_q8_K *q8 = (block_q8_K *)output_q8;
385 float tmp[QK_K];
386
387 for (int t = 0; t < tokens; ++t) {
388 const float *row = input + (size_t)t * (size_t)(2 * dim);
389 block_q8_K *q8_row = q8 + (size_t)t * (size_t)blocks_per_row;
390
391 for (int block = 0; block < blocks_per_row; ++block) {
392 const int base = block * QK_K;
393 int d = 0;
394
395#if defined(__AVX2__)
396 if (use_fast) {
397 for (; d + 8 <= QK_K; d += 8) {
398 const __m256 a = _mm256_loadu_ps(row + base + d);
399 const __m256 b = _mm256_loadu_ps(row + dim + base + d);
400 const __m256 s = sigmoid256_fast(a);
401 const __m256 y = _mm256_mul_ps(_mm256_mul_ps(a, s), b);
402 _mm256_storeu_ps(tmp + d, y);
403 }
404 }
405#else
406 (void)use_fast;
407#endif
408
409 for (; d < QK_K; ++d) {
410 const float a = row[base + d];
411 const float b = row[dim + base + d];
412 const float s = use_fast ? sigmoid_scalar(a) : sigmoid_scalar_parity(a);
413 tmp[d] = (a * s) * b;
414 }
415
416 quantize_row_q8_k(tmp, (void *)&q8_row[block], QK_K);
417 }
418 }
419}

References ck_strict_parity_enabled(), QK_K, quantize_row_q8_k(), sigmoid_scalar(), and sigmoid_scalar_parity().

◆ topk_batched_f32()

void topk_batched_f32 ( const float *  scores,
int  num_tokens,
int  n_experts,
int  k,
int *  indices,
float *  weights 
)

Batched top-K selection for multiple tokens.

Parameters
scoresInput scores [num_tokens, n_experts]
num_tokensNumber of tokens
n_expertsNumber of experts
kNumber of experts to select per token
indicesOutput: selected expert indices [num_tokens, k]
weightsOutput: routing weights [num_tokens, k] (can be NULL for no softmax)

Definition at line 465 of file topk_kernels.c.

471{
472 if (!scores || !indices || num_tokens <= 0 || n_experts <= 0 || k <= 0) {
473 return;
474 }
475
476 for (int t = 0; t < num_tokens; t++) {
477 const float *token_scores = scores + t * n_experts;
478 int *token_indices = indices + t * k;
479
480 if (weights) {
481 float *token_weights = weights + t * k;
482 topk_softmax_f32(token_scores, n_experts, k, token_indices, token_weights);
483 } else {
484 topk_f32(token_scores, n_experts, k, token_indices, NULL);
485 }
486 }
487}
void topk_softmax_f32(const float *scores, int n, int k, int *indices, float *weights)
Find top-K indices with softmax-normalized weights.

References topk_f32(), and topk_softmax_f32().

◆ topk_f32()

void topk_f32 ( const float *  scores,
int  n,
int  k,
int *  indices,
float *  values 
)

Find top-K indices and values from a score vector.

Parameters
scoresInput scores [n]
nNumber of scores (e.g., number of experts)
kNumber of top scores to select
indicesOutput: indices of top-K scores [k], sorted descending by value
valuesOutput: top-K score values [k], sorted descending (can be NULL)

Definition at line 51 of file topk_kernels.c.

56{
57 if (!scores || !indices || n <= 0 || k <= 0) {
58 return;
59 }
60
61 /* Clamp k to n */
62 if (k > n) {
63 k = n;
64 }
65
66 /* Initialize with first k elements */
67 float local_values[k];
68 for (int i = 0; i < k; i++) {
69 indices[i] = i;
70 local_values[i] = scores[i];
71 }
72
73 /* Find the minimum in our current top-k */
74 int min_idx = 0;
75 for (int i = 1; i < k; i++) {
76 if (local_values[i] < local_values[min_idx]) {
77 min_idx = i;
78 }
79 }
80
81 /* Scan remaining elements */
82 for (int i = k; i < n; i++) {
83 if (scores[i] > local_values[min_idx]) {
84 /* Replace the minimum */
85 indices[min_idx] = i;
86 local_values[min_idx] = scores[i];
87
88 /* Find new minimum */
89 min_idx = 0;
90 for (int j = 1; j < k; j++) {
91 if (local_values[j] < local_values[min_idx]) {
92 min_idx = j;
93 }
94 }
95 }
96 }
97
98 /* Sort results in descending order (simple insertion sort for small k) */
99 for (int i = 1; i < k; i++) {
100 float val = local_values[i];
101 int idx = indices[i];
102 int j = i - 1;
103 while (j >= 0 && local_values[j] < val) {
104 local_values[j + 1] = local_values[j];
105 indices[j + 1] = indices[j];
106 j--;
107 }
108 local_values[j + 1] = val;
109 indices[j + 1] = idx;
110 }
111
112 /* Copy values if output requested */
113 if (values) {
114 for (int i = 0; i < k; i++) {
115 values[i] = local_values[i];
116 }
117 }
118}

Referenced by moe_softmax_topk_router_llama_f32_workspace(), topk_batched_f32(), and topk_softmax_f32().

◆ topk_softmax_backward_f32()

void topk_softmax_backward_f32 ( const int *  indices,
const float *  weights,
const float *  d_weights,
float *  d_scores,
int  num_tokens,
int  n_experts_or_keys,
int  k 
)

Backward for hard top-k followed by softmax over selected values.

Matches PyTorch behavior for: values, indices = torch.topk(scores, k, dim=-1) weights = torch.softmax(values, dim=-1)

The hard selected indices are treated as fixed for this backward pass. Gradients are scattered only to selected scores; unselected scores are zero.

Definition at line 408 of file topk_kernels.c.

415{
416 if (!indices || !weights || !d_weights || !d_scores ||
417 num_tokens <= 0 || n_experts_or_keys <= 0 || k <= 0) {
418 return;
419 }
420
421 const size_t total = (size_t)num_tokens * (size_t)n_experts_or_keys;
422 for (size_t i = 0; i < total; ++i) {
423 d_scores[i] = 0.0f;
424 }
425
426 for (int t = 0; t < num_tokens; ++t) {
427 const int *row_indices = indices + (size_t)t * (size_t)k;
428 const float *row_weights = weights + (size_t)t * (size_t)k;
429 const float *row_d_weights = d_weights + (size_t)t * (size_t)k;
430 float *row_d_scores = d_scores + (size_t)t * (size_t)n_experts_or_keys;
431
432 float dot = 0.0f;
433 for (int i = 0; i < k; ++i) {
434 const int idx = row_indices[i];
435 if (idx >= 0 && idx < n_experts_or_keys) {
436 dot += row_weights[i] * row_d_weights[i];
437 }
438 }
439
440 for (int i = 0; i < k; ++i) {
441 const int idx = row_indices[i];
442 if (idx >= 0 && idx < n_experts_or_keys) {
443 row_d_scores[idx] += row_weights[i] * (row_d_weights[i] - dot);
444 }
445 }
446 }
447}

◆ topk_softmax_f32()

void topk_softmax_f32 ( const float *  scores,
int  n,
int  k,
int *  indices,
float *  weights 
)

Find top-K indices with softmax-normalized weights.

Parameters
scoresInput scores [n] (router logits)
nNumber of scores
kNumber of top scores to select
indicesOutput: indices of top-K scores [k]
weightsOutput: softmax-normalized weights for selected [k], sum to 1.0

Definition at line 136 of file topk_kernels.c.

141{
142 if (!scores || !indices || !weights || n <= 0 || k <= 0) {
143 return;
144 }
145
146 if (k > n) {
147 k = n;
148 }
149
150 /* First get top-K indices and values */
151 float values[k];
152 topk_f32(scores, n, k, indices, values);
153
154 /* Compute softmax over the selected values */
155 /* Find max for numerical stability */
156 float max_val = values[0];
157 for (int i = 1; i < k; i++) {
158 if (values[i] > max_val) {
159 max_val = values[i];
160 }
161 }
162
163 /* Compute exp and sum */
164 float sum = 0.0f;
165 for (int i = 0; i < k; i++) {
166 weights[i] = expf(values[i] - max_val);
167 sum += weights[i];
168 }
169
170 /* Normalize */
171 float inv_sum = 1.0f / sum;
172 for (int i = 0; i < k; i++) {
173 weights[i] *= inv_sum;
174 }
175}

References topk_f32().

Referenced by topk_batched_f32().

◆ unfused_rmsnorm_qkv_prefill()

void unfused_rmsnorm_qkv_prefill ( const float *  x,
const float *  gamma,
const float *  Wq,
const float *  Wk,
const float *  Wv,
float *  x_norm,
float *  Q,
float *  K,
float *  V,
int  seq_len,
int  hidden,
int  q_dim,
int  kv_dim,
float  eps 
)

Unfused version for benchmarking comparison.

Unfused version for benchmarking comparison.

Definition at line 667 of file prefill_fused_gemm.c.

682{
683 /* Step 1: Full RMSNorm → writes x_norm to memory */
684 rmsnorm_tile(x, gamma, x_norm, seq_len, hidden, hidden, eps);
685
686 /* Step 2: Separate GEMMs with N-outer tiling for weight reuse */
687 /* Q projection */
688 for (int n_start = 0; n_start < q_dim; n_start += PREFILL_TILE_N) {
689 int tile_n = (n_start + PREFILL_TILE_N <= q_dim)
690 ? PREFILL_TILE_N : (q_dim - n_start);
691 const float *W_tile = Wq + (size_t)n_start * hidden;
692
693 for (int m_start = 0; m_start < seq_len; m_start += PREFILL_TILE_M) {
694 int tile_m = (m_start + PREFILL_TILE_M <= seq_len)
695 ? PREFILL_TILE_M : (seq_len - m_start);
696 const float *x_tile = x_norm + (size_t)m_start * hidden;
697 float *out_tile = Q + (size_t)m_start * q_dim + n_start;
698 gemm_tile_nt_strided(x_tile, W_tile, out_tile,
699 tile_m, tile_n, hidden, q_dim);
700 }
701 }
702
703 /* K projection */
704 for (int n_start = 0; n_start < kv_dim; n_start += PREFILL_TILE_N) {
705 int tile_n = (n_start + PREFILL_TILE_N <= kv_dim)
706 ? PREFILL_TILE_N : (kv_dim - n_start);
707 const float *W_tile = Wk + (size_t)n_start * hidden;
708
709 for (int m_start = 0; m_start < seq_len; m_start += PREFILL_TILE_M) {
710 int tile_m = (m_start + PREFILL_TILE_M <= seq_len)
711 ? PREFILL_TILE_M : (seq_len - m_start);
712 const float *x_tile = x_norm + (size_t)m_start * hidden;
713 float *out_tile = K + (size_t)m_start * kv_dim + n_start;
714 gemm_tile_nt_strided(x_tile, W_tile, out_tile,
715 tile_m, tile_n, hidden, kv_dim);
716 }
717 }
718
719 /* V projection */
720 for (int n_start = 0; n_start < kv_dim; n_start += PREFILL_TILE_N) {
721 int tile_n = (n_start + PREFILL_TILE_N <= kv_dim)
722 ? PREFILL_TILE_N : (kv_dim - n_start);
723 const float *W_tile = Wv + (size_t)n_start * hidden;
724
725 for (int m_start = 0; m_start < seq_len; m_start += PREFILL_TILE_M) {
726 int tile_m = (m_start + PREFILL_TILE_M <= seq_len)
727 ? PREFILL_TILE_M : (seq_len - m_start);
728 const float *x_tile = x_norm + (size_t)m_start * hidden;
729 float *out_tile = V + (size_t)m_start * kv_dim + n_start;
730 gemm_tile_nt_strided(x_tile, W_tile, out_tile,
731 tile_m, tile_n, hidden, kv_dim);
732 }
733 }
734}
#define PREFILL_TILE_N

References gemm_tile_nt_strided(), PREFILL_TILE_M, PREFILL_TILE_N, and rmsnorm_tile().

◆ vec_dot_q6_k_q8_k()

void vec_dot_q6_k_q8_k ( int  n,
float *  s,
const void *  vx,
const void *  vy 
)

Q6_K x Q8_K dot product (single row)

Definition at line 1339 of file gemm_kernels_q6k_q8k.c.

1340{
1341 if (!s || !vx || !vy || n <= 0) {
1342 return;
1343 }
1344
1345 const block_q6_K *x = (const block_q6_K *)vx;
1346 const block_q8_K *y = (const block_q8_K *)vy;
1347
1348 /* This is the architecture-neutral scalar oracle. Production x86 dispatch
1349 * uses the separately parity-tested SIMD reduction tree. */
1350 *s = dot_q6_k_q8_k_ref(x, y, n);
1351}

References dot_q6_k_q8_k_ref().

◆ vision_position_ids_2d_merge()

void vision_position_ids_2d_merge ( int32_t *  positions,
int  grid_h,
int  grid_w,
int  merge_size 
)

Build merged 2D vision position IDs in the layout expected by vision M-RoPE.

Output layout: [4, grid_h * grid_w] flattened as [y_stream | x_stream | y_stream_dup | x_stream_dup]

Tokens are emitted in merged-tile traversal order so the position buffer matches the same 2x2 grouping used by Qwen-style vision encoders.

Definition at line 529 of file vision_kernels.c.

533{
534 if (!positions || grid_h <= 0 || grid_w <= 0 || merge_size <= 0) {
535 return;
536 }
537
538 const int num_tokens = grid_h * grid_w;
539 int ptr = 0;
540
541 for (int y = 0; y < grid_h; y += merge_size) {
542 for (int x = 0; x < grid_w; x += merge_size) {
543 for (int dy = 0; dy < merge_size; ++dy) {
544 for (int dx = 0; dx < merge_size; ++dx) {
545 const int yy = y + dy;
546 const int xx = x + dx;
547 if (yy >= grid_h || xx >= grid_w || ptr >= num_tokens) {
548 continue;
549 }
550 positions[ptr] = yy;
551 positions[num_tokens + ptr] = xx;
552 positions[2 * num_tokens + ptr] = yy;
553 positions[3 * num_tokens + ptr] = xx;
554 ++ptr;
555 }
556 }
557 }
558 }
559
560 for (; ptr < num_tokens; ++ptr) {
561 positions[ptr] = 0;
562 positions[num_tokens + ptr] = 0;
563 positions[2 * num_tokens + ptr] = 0;
564 positions[3 * num_tokens + ptr] = 0;
565 }
566}

◆ weighted_sum_f32()

void weighted_sum_f32 ( float *  y,
const float **  vectors,
const float *  weights,
int  k,
int  n 
)

Weighted sum of k vectors: y = sum_i(weights[i] * vectors[i])

Parameters
yOutput vector [n]
vectorsArray of k input vector pointers, each [n]
weightsArray of k scalar weights
kNumber of vectors to combine
nVector length

Definition at line 206 of file axpy_kernels.c.

211{
212 if (!y || !vectors || !weights || k <= 0 || n <= 0) {
213 return;
214 }
215
216 /* Initialize with first vector */
217 scal_copy_f32(y, vectors[0], weights[0], n);
218
219 /* Accumulate rest */
220 for (int i = 1; i < k; i++) {
221 axpy_f32(y, vectors[i], weights[i], n);
222 }
223}
void scal_copy_f32(float *y, const float *x, float alpha, int n)
Scaled copy: y = alpha * x.

References axpy_f32(), and scal_copy_f32().

◆ yarn_rope_cache_contiguous_positions_f32()

void yarn_rope_cache_contiguous_positions_f32 ( float *  cos_cache,
float *  sin_cache,
int  num_tokens,
int  rotary_dim,
float  freq_base,
float  factor,
int  original_context,
float  beta_fast,
float  beta_slow,
float  mscale,
float  mscale_all_dim 
)

Definition at line 517 of file rope_kernels.c.

528{
530 cos_cache, sin_cache, NULL, NULL, NULL, num_tokens, rotary_dim,
531 freq_base, factor, original_context, beta_fast, beta_slow, mscale,
532 mscale_all_dim);
533}
static void yarn_rope_cache_explicit_positions_impl(float *cos_f32, float *sin_f32, uint16_t *cos_bf16, uint16_t *sin_bf16, const int32_t *positions, int num_tokens, int rotary_dim, float freq_base, float factor, int original_context, float beta_fast, float beta_slow, float mscale, float mscale_all_dim)

References yarn_rope_cache_explicit_positions_impl().

◆ yarn_rope_cache_explicit_positions_bf16()

void yarn_rope_cache_explicit_positions_bf16 ( uint16_t *  cos_cache,
uint16_t *  sin_cache,
const int32_t *  positions,
int  num_tokens,
int  rotary_dim,
float  freq_base,
float  factor,
int  original_context,
float  beta_fast,
float  beta_slow,
float  mscale,
float  mscale_all_dim 
)

Definition at line 535 of file rope_kernels.c.

547{
549 NULL, NULL, cos_cache, sin_cache, positions, num_tokens, rotary_dim,
550 freq_base, factor, original_context, beta_fast, beta_slow, mscale,
551 mscale_all_dim);
552}

References yarn_rope_cache_explicit_positions_impl().

◆ yarn_rope_cache_explicit_positions_f32()

void yarn_rope_cache_explicit_positions_f32 ( float *  cos_cache,
float *  sin_cache,
const int32_t *  positions,
int  num_tokens,
int  rotary_dim,
float  freq_base,
float  factor,
int  original_context,
float  beta_fast,
float  beta_slow,
float  mscale,
float  mscale_all_dim 
)

Definition at line 498 of file rope_kernels.c.

510{
512 cos_cache, sin_cache, NULL, NULL, positions, num_tokens, rotary_dim,
513 freq_base, factor, original_context, beta_fast, beta_slow, mscale,
514 mscale_all_dim);
515}

References yarn_rope_cache_explicit_positions_impl().