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

RoPE (Rotary Position Embedding) kernels with SIMD. More...

#include "ckernel_engine.h"
#include "bf16_utils.h"
#include "ckernel_quant.h"
#include "ggml_runtime_compat.h"
#include <dlfcn.h>
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

Go to the source code of this file.

Macros

#define _GNU_SOURCE
 
#define CK_DEFINE_MROPE_STORAGE_WRAPPER(NAME, STORAGE_KIND)
 
#define M_PI   3.14159265358979323846
 

Typedefs

typedef void(* ck_ggml_build_forward_expand_fn) (struct ggml_cgraph *, struct ggml_tensor *)
 
typedef void(* ck_ggml_cpu_init_fn) (void)
 
typedef void(* ck_ggml_free_fn) (struct ggml_context *)
 
typedef void *(* ck_ggml_get_data_fn) (const struct ggml_tensor *)
 
typedef enum ggml_status(* ck_ggml_graph_compute_with_ctx_fn) (struct ggml_context *, struct ggml_cgraph *, int)
 
typedef struct ggml_context *(* ck_ggml_init_fn) (struct ggml_init_params)
 
typedef struct ggml_cgraph *(* ck_ggml_new_graph_fn) (struct ggml_context *)
 
typedef struct ggml_tensor *(* ck_ggml_new_tensor_1d_fn) (struct ggml_context *, enum ggml_type, int64_t)
 
typedef struct ggml_tensor *(* ck_ggml_rope_multi_inplace_fn) (struct ggml_context *, struct ggml_tensor *, struct ggml_tensor *, struct ggml_tensor *, int, int[4], int, int, float, float, float, float, float, float)
 
typedef struct ggml_tensor *(* ck_ggml_view_3d_fn) (struct ggml_context *, struct ggml_tensor *, int64_t, int64_t, int64_t, size_t, size_t, size_t)
 
typedef float(* ck_rope_math_f32_binary_fn) (float, float)
 
typedef float(* ck_rope_math_f32_fn) (float)
 

Functions

static void ck_mrope_round_storage (float *data, size_t count, int storage_kind)
 
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)
 
static ck_ggml_build_forward_expand_fn ck_resolve_ggml_build_forward_expand (void)
 
static ck_ggml_cpu_init_fn ck_resolve_ggml_cpu_init (void)
 
static ck_ggml_free_fn ck_resolve_ggml_free (void)
 
static ck_ggml_get_data_fn ck_resolve_ggml_get_data (void)
 
static ck_ggml_graph_compute_with_ctx_fn ck_resolve_ggml_graph_compute_with_ctx (void)
 
static ck_ggml_init_fn ck_resolve_ggml_init (void)
 
static ck_ggml_new_graph_fn ck_resolve_ggml_new_graph (void)
 
static ck_ggml_new_tensor_1d_fn ck_resolve_ggml_new_tensor_1d (void)
 
static ck_ggml_rope_multi_inplace_fn ck_resolve_ggml_rope_multi_inplace (void)
 
static ck_ggml_view_3d_fn ck_resolve_ggml_view_3d (void)
 
static void ck_rope_ensure_ggml_loaded (void)
 
static float ck_rope_reference_cosf (float value)
 
static float ck_rope_reference_powf (float base, float exponent)
 
static float ck_rope_reference_sinf (float value)
 
static void * ck_rope_resolve_ggml_symbol (const char *name)
 
static ck_rope_math_f32_fn ck_rope_resolve_system_math_f32 (const char *name)
 
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)
 
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_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)
 
static void mrope_rotate_pair (float x0, float x1, float cos_theta, float sin_theta, float *out0, float *out1)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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_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)
 
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)
 
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_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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
static void text_mrope_yarn (float theta_extrap, float freq_scale, const float corr_dims[2], int chan, float ext_factor, float attn_factor, float *cos_theta, float *sin_theta)
 
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)
 
static void vision_mrope_yarn (float theta_extrap, float freq_scale, const float corr_dims[2], int chan, float ext_factor, float attn_factor, float *cos_theta, float *sin_theta)
 
static float vision_mrope_yarn_corr_dim (int n_dims, int n_ctx_orig, float n_rot, float base)
 
static void vision_mrope_yarn_corr_dims (int n_dims, int n_ctx_orig, float freq_base, float beta_fast, float beta_slow, float dims[2])
 
static float vision_mrope_yarn_ramp (float low, float high, int chan)
 
static float yarn_correction_dim (float rotations, int rotary_dim, float freq_base, int original_context)
 
static float yarn_mscale (float factor, float scale)
 
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)
 
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)
 

Detailed Description

RoPE (Rotary Position Embedding) kernels with SIMD.

CK-ENGINE KERNEL RULES:

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

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

Applies rotary position embeddings to query and key vectors. Used by Llama, SmolLM, and most modern transformer architectures.

Math (Llama-style rotate-half): Split rotary_dim into two halves (0..half-1, half..rotary_dim-1). For each position m and index i in [0, half): x0 = x[i], x1 = x[i + half] x'[i] = x0 * cos(m * theta_i) - x1 * sin(m * theta_i) x'[i+half] = x0 * sin(m * theta_i) + x1 * cos(m * theta_i)

Where theta_i = 1 / (base^(2i/d)), typically base=10000.

Layout: x: [num_heads, num_tokens, head_dim] head-major cos_cache, sin_cache: [max_seq_len, rotary_dim/2] precomputed

Definition in file rope_kernels.c.

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 32 of file rope_kernels.c.

◆ CK_DEFINE_MROPE_STORAGE_WRAPPER

#define CK_DEFINE_MROPE_STORAGE_WRAPPER (   NAME,
  STORAGE_KIND 
)
Value:
void NAME(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(q, k, positions, num_heads, num_kv_heads, num_tokens, \
head_dim, aligned_head_dim, n_dims, section_0, section_1, \
section_2, section_3, n_ctx_orig, freq_base, freq_scale, \
ext_factor, attn_factor, beta_fast, beta_slow); \
const size_t q_count = (size_t) num_heads * (size_t) num_tokens * (size_t) aligned_head_dim; \
const size_t k_count = (size_t) num_kv_heads * (size_t) num_tokens * (size_t) aligned_head_dim; \
ck_mrope_round_storage(q, q_count, STORAGE_KIND); \
ck_mrope_round_storage(k, k_count, STORAGE_KIND); \
}

Definition at line 2717 of file rope_kernels.c.

2724{ \
2725 mrope_qk_vision(q, k, positions, num_heads, num_kv_heads, num_tokens, \
2726 head_dim, aligned_head_dim, n_dims, section_0, section_1, \
2727 section_2, section_3, n_ctx_orig, freq_base, freq_scale, \
2728 ext_factor, attn_factor, beta_fast, beta_slow); \
2729 const size_t q_count = (size_t) num_heads * (size_t) num_tokens * (size_t) aligned_head_dim; \
2730 const size_t k_count = (size_t) num_kv_heads * (size_t) num_tokens * (size_t) aligned_head_dim; \
2731 ck_mrope_round_storage(q, q_count, STORAGE_KIND); \
2732 ck_mrope_round_storage(k, k_count, STORAGE_KIND); \
2733}

◆ M_PI

#define M_PI   3.14159265358979323846

Definition at line 56 of file rope_kernels.c.

Typedef Documentation

◆ ck_ggml_build_forward_expand_fn

typedef void(* ck_ggml_build_forward_expand_fn) (struct ggml_cgraph *, struct ggml_tensor *)

Definition at line 79 of file rope_kernels.c.

◆ ck_ggml_cpu_init_fn

typedef void(* ck_ggml_cpu_init_fn) (void)

Definition at line 59 of file rope_kernels.c.

◆ ck_ggml_free_fn

typedef void(* ck_ggml_free_fn) (struct ggml_context *)

Definition at line 61 of file rope_kernels.c.

◆ ck_ggml_get_data_fn

typedef void *(* ck_ggml_get_data_fn) (const struct ggml_tensor *)

Definition at line 81 of file rope_kernels.c.

◆ ck_ggml_graph_compute_with_ctx_fn

typedef enum ggml_status(* ck_ggml_graph_compute_with_ctx_fn) (struct ggml_context *, struct ggml_cgraph *, int)

Definition at line 79 of file rope_kernels.c.

◆ ck_ggml_init_fn

typedef struct ggml_context *(* ck_ggml_init_fn) (struct ggml_init_params)

Definition at line 59 of file rope_kernels.c.

◆ ck_ggml_new_graph_fn

typedef struct ggml_cgraph *(* ck_ggml_new_graph_fn) (struct ggml_context *)

Definition at line 61 of file rope_kernels.c.

◆ ck_ggml_new_tensor_1d_fn

typedef struct ggml_tensor *(* ck_ggml_new_tensor_1d_fn) (struct ggml_context *, enum ggml_type, int64_t)

Definition at line 61 of file rope_kernels.c.

◆ ck_ggml_rope_multi_inplace_fn

typedef struct ggml_tensor *(* ck_ggml_rope_multi_inplace_fn) (struct ggml_context *, struct ggml_tensor *, struct ggml_tensor *, struct ggml_tensor *, int, int[4], int, int, float, float, float, float, float, float)

Definition at line 61 of file rope_kernels.c.

◆ ck_ggml_view_3d_fn

typedef struct ggml_tensor *(* ck_ggml_view_3d_fn) (struct ggml_context *, struct ggml_tensor *, int64_t, int64_t, int64_t, size_t, size_t, size_t)

Definition at line 61 of file rope_kernels.c.

◆ ck_rope_math_f32_binary_fn

typedef float(* ck_rope_math_f32_binary_fn) (float, float)

Definition at line 83 of file rope_kernels.c.

◆ ck_rope_math_f32_fn

typedef float(* ck_rope_math_f32_fn) (float)

Definition at line 82 of file rope_kernels.c.

Function Documentation

◆ ck_mrope_round_storage()

static void ck_mrope_round_storage ( float *  data,
size_t  count,
int  storage_kind 
)
static

Definition at line 2705 of file rope_kernels.c.

2706{
2707 if (!data) return;
2708 for (size_t i = 0; i < count; ++i) {
2709 if (storage_kind == 1) {
2710 data[i] = bf16_to_float(float_to_bf16(data[i]));
2711 } else if (storage_kind == 2) {
2712 data[i] = ck_fp16_to_fp32(ck_fp32_to_fp16(data[i]));
2713 }
2714 }
2715}
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
static ck_half ck_fp32_to_fp16(float f)
static float ck_fp16_to_fp32(ck_half h)
const uint8_t size_t count
Definition true_bpe.h:209

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

◆ 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}
const char * token
Definition tokenizer.h:307

References token.

◆ ck_resolve_ggml_build_forward_expand()

static ck_ggml_build_forward_expand_fn ck_resolve_ggml_build_forward_expand ( void  )
static

Definition at line 250 of file rope_kernels.c.

250 {
251 static ck_ggml_build_forward_expand_fn fn = NULL;
252 if (!fn) {
253 fn = (ck_ggml_build_forward_expand_fn) ck_rope_resolve_ggml_symbol("ggml_build_forward_expand");
254 }
255 return fn;
256}
void(* ck_ggml_build_forward_expand_fn)(struct ggml_cgraph *, struct ggml_tensor *)
static void * ck_rope_resolve_ggml_symbol(const char *name)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_cpu_init()

static ck_ggml_cpu_init_fn ck_resolve_ggml_cpu_init ( void  )
static

Definition at line 194 of file rope_kernels.c.

194 {
195 static ck_ggml_cpu_init_fn fn = NULL;
196 if (!fn) {
197 fn = (ck_ggml_cpu_init_fn) ck_rope_resolve_ggml_symbol("ggml_cpu_init");
198 }
199 return fn;
200}
void(* ck_ggml_cpu_init_fn)(void)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_free()

static ck_ggml_free_fn ck_resolve_ggml_free ( void  )
static

Definition at line 210 of file rope_kernels.c.

210 {
211 static ck_ggml_free_fn fn = NULL;
212 if (!fn) {
214 }
215 return fn;
216}
void(* ck_ggml_free_fn)(struct ggml_context *)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_get_data()

static ck_ggml_get_data_fn ck_resolve_ggml_get_data ( void  )
static

Definition at line 266 of file rope_kernels.c.

266 {
267 static ck_ggml_get_data_fn fn = NULL;
268 if (!fn) {
269 fn = (ck_ggml_get_data_fn) ck_rope_resolve_ggml_symbol("ggml_get_data");
270 }
271 return fn;
272}
void *(* ck_ggml_get_data_fn)(const struct ggml_tensor *)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_graph_compute_with_ctx()

static ck_ggml_graph_compute_with_ctx_fn ck_resolve_ggml_graph_compute_with_ctx ( void  )
static

Definition at line 258 of file rope_kernels.c.

258 {
259 static ck_ggml_graph_compute_with_ctx_fn fn = NULL;
260 if (!fn) {
261 fn = (ck_ggml_graph_compute_with_ctx_fn) ck_rope_resolve_ggml_symbol("ggml_graph_compute_with_ctx");
262 }
263 return fn;
264}
enum ggml_status(* ck_ggml_graph_compute_with_ctx_fn)(struct ggml_context *, struct ggml_cgraph *, int)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_init()

static ck_ggml_init_fn ck_resolve_ggml_init ( void  )
static

Definition at line 202 of file rope_kernels.c.

202 {
203 static ck_ggml_init_fn fn = NULL;
204 if (!fn) {
206 }
207 return fn;
208}
struct ggml_context *(* ck_ggml_init_fn)(struct ggml_init_params)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_new_graph()

static ck_ggml_new_graph_fn ck_resolve_ggml_new_graph ( void  )
static

Definition at line 242 of file rope_kernels.c.

242 {
243 static ck_ggml_new_graph_fn fn = NULL;
244 if (!fn) {
245 fn = (ck_ggml_new_graph_fn) ck_rope_resolve_ggml_symbol("ggml_new_graph");
246 }
247 return fn;
248}
struct ggml_cgraph *(* ck_ggml_new_graph_fn)(struct ggml_context *)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_new_tensor_1d()

static ck_ggml_new_tensor_1d_fn ck_resolve_ggml_new_tensor_1d ( void  )
static

Definition at line 218 of file rope_kernels.c.

218 {
219 static ck_ggml_new_tensor_1d_fn fn = NULL;
220 if (!fn) {
221 fn = (ck_ggml_new_tensor_1d_fn) ck_rope_resolve_ggml_symbol("ggml_new_tensor_1d");
222 }
223 return fn;
224}
struct ggml_tensor *(* ck_ggml_new_tensor_1d_fn)(struct ggml_context *, enum ggml_type, int64_t)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_rope_multi_inplace()

static ck_ggml_rope_multi_inplace_fn ck_resolve_ggml_rope_multi_inplace ( void  )
static

Definition at line 234 of file rope_kernels.c.

234 {
235 static ck_ggml_rope_multi_inplace_fn fn = NULL;
236 if (!fn) {
237 fn = (ck_ggml_rope_multi_inplace_fn) ck_rope_resolve_ggml_symbol("ggml_rope_multi_inplace");
238 }
239 return fn;
240}
struct ggml_tensor *(* ck_ggml_rope_multi_inplace_fn)(struct ggml_context *, struct ggml_tensor *, struct ggml_tensor *, struct ggml_tensor *, int, int[4], int, int, float, float, float, float, float, float)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_resolve_ggml_view_3d()

static ck_ggml_view_3d_fn ck_resolve_ggml_view_3d ( void  )
static

Definition at line 226 of file rope_kernels.c.

226 {
227 static ck_ggml_view_3d_fn fn = NULL;
228 if (!fn) {
229 fn = (ck_ggml_view_3d_fn) ck_rope_resolve_ggml_symbol("ggml_view_3d");
230 }
231 return fn;
232}
struct ggml_tensor *(* ck_ggml_view_3d_fn)(struct ggml_context *, struct ggml_tensor *, int64_t, int64_t, int64_t, size_t, size_t, size_t)

References ck_rope_resolve_ggml_symbol().

Referenced by explicit_mrope_apply_ggml_exact().

◆ ck_rope_ensure_ggml_loaded()

static void ck_rope_ensure_ggml_loaded ( void  )
static

Definition at line 143 of file rope_kernels.c.

144{
145 static int tried = 0;
146 if (tried) {
147 return;
148 }
149 tried = 1;
150
151 const char *env_dir = getenv("CK_GGML_LIB_DIR");
152 const char *dirs[] = {
153 "/opt/app-root/src/Software/llama.cpp/build/bin",
154 "./llama.cpp/build/bin",
155 "llama.cpp/build/bin",
156 NULL,
157 };
158 char path_buf[512];
159 if (env_dir && env_dir[0]) {
160 snprintf(path_buf, sizeof(path_buf), "%s/libggml-base.so", env_dir);
161 dlopen(path_buf, RTLD_NOW | RTLD_GLOBAL);
162 snprintf(path_buf, sizeof(path_buf), "%s/libggml.so", env_dir);
163 dlopen(path_buf, RTLD_NOW | RTLD_GLOBAL);
164 snprintf(path_buf, sizeof(path_buf), "%s/libggml-cpu.so", env_dir);
165 void *cpu = dlopen(path_buf, RTLD_NOW | RTLD_GLOBAL);
166 if (cpu) {
167 return;
168 }
169 }
170 for (int i = 0; dirs[i] != NULL; ++i) {
171 snprintf(path_buf, sizeof(path_buf), "%s/libggml-base.so", dirs[i]);
172 dlopen(path_buf, RTLD_NOW | RTLD_GLOBAL);
173 snprintf(path_buf, sizeof(path_buf), "%s/libggml.so", dirs[i]);
174 dlopen(path_buf, RTLD_NOW | RTLD_GLOBAL);
175 snprintf(path_buf, sizeof(path_buf), "%s/libggml-cpu.so", dirs[i]);
176 void *cpu = dlopen(path_buf, RTLD_NOW | RTLD_GLOBAL);
177 if (cpu) {
178 return;
179 }
180 }
181}

Referenced by ck_rope_resolve_ggml_symbol().

◆ ck_rope_reference_cosf()

static float ck_rope_reference_cosf ( float  value)
static

Definition at line 108 of file rope_kernels.c.

109{
110 static ck_rope_math_f32_fn fn = NULL;
111 if (!fn) {
113 }
114 return fn ? fn(value) : cosf(value);
115}
float(* ck_rope_math_f32_fn)(float)
static ck_rope_math_f32_fn ck_rope_resolve_system_math_f32(const char *name)

References ck_rope_resolve_system_math_f32().

Referenced by rope_forward_qk_split_llama_token_range_f32(), rope_precompute_cache_llama_cpu(), text_mrope_apply_positions_pytorch_bf16_storage(), text_mrope_apply_pytorch_bf16_storage(), text_mrope_yarn(), vision_mrope_yarn(), and yarn_rope_cache_explicit_positions_impl().

◆ ck_rope_reference_powf()

static float ck_rope_reference_powf ( float  base,
float  exponent 
)
static

Definition at line 126 of file rope_kernels.c.

127{
128 static ck_rope_math_f32_binary_fn fn = NULL;
129 if (!fn) {
130#if defined(__linux__)
131 static void *libm_handle = NULL;
132 if (!libm_handle) {
133 libm_handle = dlopen("libm.so.6", RTLD_NOW | RTLD_LOCAL);
134 }
135 if (libm_handle) {
136 fn = (ck_rope_math_f32_binary_fn)dlsym(libm_handle, "powf");
137 }
138#endif
139 }
140 return fn ? fn(base, exponent) : powf(base, exponent);
141}
float(* ck_rope_math_f32_binary_fn)(float, float)

Referenced by explicit_mrope_apply_head(), rope_forward_qk_split_llama_token_range_f32(), rope_precompute_cache_llama_cpu(), text_mrope_apply_positions_pytorch_bf16_storage(), text_mrope_apply_pytorch_bf16_storage(), vision_mrope_apply_head(), and yarn_rope_cache_explicit_positions_impl().

◆ ck_rope_reference_sinf()

static float ck_rope_reference_sinf ( float  value)
static

◆ ck_rope_resolve_ggml_symbol()

static void * ck_rope_resolve_ggml_symbol ( const char *  name)
static

◆ ck_rope_resolve_system_math_f32()

static ck_rope_math_f32_fn ck_rope_resolve_system_math_f32 ( const char *  name)
static

Definition at line 85 of file rope_kernels.c.

86{
87#if defined(__linux__)
88 static void *libm_handle = NULL;
89 if (!libm_handle) {
90 libm_handle = dlopen("libm.so.6", RTLD_NOW | RTLD_LOCAL);
91 }
92 if (libm_handle) {
93 ck_rope_math_f32_fn fn = (ck_rope_math_f32_fn)dlsym(libm_handle, name);
94 if (fn) {
95 return fn;
96 }
97 }
98#else
99 (void)name;
100#endif
101 return NULL;
102}

Referenced by ck_rope_reference_cosf(), and ck_rope_reference_sinf().

◆ explicit_mrope_apply_ggml_exact()

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

Definition at line 1947 of file rope_kernels.c.

1964 {
1965 ck_ggml_cpu_init_fn ggml_cpu_init_fn = ck_resolve_ggml_cpu_init();
1966 ck_ggml_init_fn ggml_init_fn = ck_resolve_ggml_init();
1967 ck_ggml_free_fn ggml_free_fn = ck_resolve_ggml_free();
1969 ck_ggml_view_3d_fn ggml_view_3d_fn = ck_resolve_ggml_view_3d();
1971 ck_ggml_new_graph_fn ggml_new_graph_fn = ck_resolve_ggml_new_graph();
1974 ck_ggml_get_data_fn ggml_get_data_fn = ck_resolve_ggml_get_data();
1975
1976 if (!x || !positions || num_heads <= 0 || num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim) {
1977 return 0;
1978 }
1979 if (!ggml_cpu_init_fn || !ggml_init_fn || !ggml_free_fn || !ggml_new_tensor_1d_fn ||
1980 !ggml_view_3d_fn || !ggml_rope_multi_inplace_fn || !ggml_new_graph_fn ||
1981 !ggml_build_forward_expand_fn || !ggml_graph_compute_with_ctx_fn || !ggml_get_data_fn) {
1982 return 0;
1983 }
1984
1985 ggml_cpu_init_fn();
1986
1987 const size_t row_bytes = (size_t) aligned_head_dim * sizeof(float);
1988 const size_t head_bytes = (size_t) num_tokens * row_bytes;
1989 const int64_t total_elems = (int64_t) num_heads * (int64_t) num_tokens * (int64_t) aligned_head_dim;
1990 const size_t mem_size =
1991 (size_t) 16 * 1024 * 1024 +
1992 (size_t) total_elems * sizeof(float) +
1993 (size_t) 4 * (size_t) num_tokens * sizeof(int32_t);
1994
1995 struct ggml_init_params params = {
1996 .mem_size = mem_size,
1997 .mem_buffer = NULL,
1998 .no_alloc = false,
1999 };
2000 struct ggml_context *ctx = ggml_init_fn(params);
2001 if (!ctx) {
2002 return 0;
2003 }
2004
2005 int ok = 0;
2006 struct ggml_tensor *x_base = ggml_new_tensor_1d_fn(ctx, GGML_TYPE_F32, total_elems);
2007 struct ggml_tensor *pos_base = ggml_new_tensor_1d_fn(ctx, GGML_TYPE_I32, (int64_t) 4 * (int64_t) num_tokens);
2008 if (!x_base || !pos_base) {
2009 ggml_free_fn(ctx);
2010 return 0;
2011 }
2012
2013 void *x_base_data = ggml_get_data_fn(x_base);
2014 void *pos_base_data = ggml_get_data_fn(pos_base);
2015 if (!x_base_data || !pos_base_data) {
2016 ggml_free_fn(ctx);
2017 return 0;
2018 }
2019
2020 memcpy(x_base_data, x, (size_t) total_elems * sizeof(float));
2021 memcpy(pos_base_data, positions, (size_t) 4 * (size_t) num_tokens * sizeof(int32_t));
2022
2023 struct ggml_tensor *x_view = ggml_view_3d_fn(ctx,
2024 x_base,
2025 head_dim,
2026 num_heads,
2027 num_tokens,
2028 head_bytes,
2029 row_bytes,
2030 0);
2031 if (!x_view) {
2032 ggml_free_fn(ctx);
2033 return 0;
2034 }
2035
2036 int ggml_sections[GGML_MROPE_SECTIONS] = {
2037 sections[0], sections[1], sections[2], sections[3]
2038 };
2039 /* CK's vision contract names the full rotary width. ggml's VISION mode
2040 * names the split-half stride (the number of frequency pairs). Keep this
2041 * unit conversion inside the oracle adapter so production kernels and IR
2042 * continue to carry the canonical full-width value. */
2043 const int ggml_n_dims = rope_type == GGML_ROPE_TYPE_VISION ? n_dims / 2 : n_dims;
2044 if (ggml_n_dims <= 0 || (rope_type == GGML_ROPE_TYPE_VISION && (n_dims & 1) != 0)) {
2045 ggml_free_fn(ctx);
2046 return 0;
2047 }
2048 struct ggml_tensor *rope = ggml_rope_multi_inplace_fn(ctx,
2049 x_view,
2050 pos_base,
2051 NULL,
2052 ggml_n_dims,
2053 ggml_sections,
2054 rope_type,
2055 n_ctx_orig,
2056 freq_base,
2057 freq_scale,
2058 ext_factor,
2059 attn_factor,
2060 beta_fast,
2061 beta_slow);
2062 if (!rope) {
2063 ggml_free_fn(ctx);
2064 return 0;
2065 }
2066
2067 struct ggml_cgraph *gf = ggml_new_graph_fn(ctx);
2068 if (!gf) {
2069 ggml_free_fn(ctx);
2070 return 0;
2071 }
2072 ggml_build_forward_expand_fn(gf, rope);
2073 if (ggml_graph_compute_with_ctx_fn(ctx, gf, 1) != GGML_STATUS_SUCCESS) {
2074 ggml_free_fn(ctx);
2075 return 0;
2076 }
2077
2078 memcpy(x, x_base_data, (size_t) total_elems * sizeof(float));
2079 ok = 1;
2080 ggml_free_fn(ctx);
2081 return ok;
2082}
@ GGML_STATUS_SUCCESS
#define GGML_MROPE_SECTIONS
@ GGML_TYPE_F32
@ GGML_TYPE_I32
#define GGML_ROPE_TYPE_VISION
static ck_ggml_rope_multi_inplace_fn ck_resolve_ggml_rope_multi_inplace(void)
static ck_ggml_view_3d_fn ck_resolve_ggml_view_3d(void)
static ck_ggml_new_tensor_1d_fn ck_resolve_ggml_new_tensor_1d(void)
static ck_ggml_build_forward_expand_fn ck_resolve_ggml_build_forward_expand(void)
static ck_ggml_get_data_fn ck_resolve_ggml_get_data(void)
static ck_ggml_graph_compute_with_ctx_fn ck_resolve_ggml_graph_compute_with_ctx(void)
static ck_ggml_new_graph_fn ck_resolve_ggml_new_graph(void)
static ck_ggml_free_fn ck_resolve_ggml_free(void)
static ck_ggml_init_fn ck_resolve_ggml_init(void)
static ck_ggml_cpu_init_fn ck_resolve_ggml_cpu_init(void)

References ck_resolve_ggml_build_forward_expand(), ck_resolve_ggml_cpu_init(), ck_resolve_ggml_free(), ck_resolve_ggml_get_data(), ck_resolve_ggml_graph_compute_with_ctx(), ck_resolve_ggml_init(), ck_resolve_ggml_new_graph(), ck_resolve_ggml_new_tensor_1d(), ck_resolve_ggml_rope_multi_inplace(), ck_resolve_ggml_view_3d(), GGML_MROPE_SECTIONS, GGML_ROPE_TYPE_VISION, GGML_STATUS_SUCCESS, GGML_TYPE_F32, GGML_TYPE_I32, and ggml_init_params::mem_size.

Referenced by mrope_qk_imrope_positions(), and mrope_qk_vision().

◆ explicit_mrope_apply_head()

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

Definition at line 2084 of file rope_kernels.c.

2100 {
2101 if (!x || !positions || num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim || n_dims <= 0) {
2102 return;
2103 }
2104
2105 int rope_dims = n_dims;
2106 if (rope_dims > head_dim) {
2107 rope_dims = head_dim;
2108 }
2109 rope_dims &= ~1;
2110 if (rope_dims <= 0) {
2111 return;
2112 }
2113 const int rope_pairs = rope_dims / 2;
2114
2115 const int num_pos = num_tokens;
2116 const int sec_w = sections[0] + sections[1];
2117 const int sec_e = sec_w + sections[2];
2118 const int sect_dims = sections[0] + sections[1] + sections[2] + sections[3];
2119 const float theta_scale =
2120 ck_rope_reference_powf(freq_base, -2.0f / (float) rope_dims);
2121 float corr_dims[2] = {0.0f, (float) (rope_dims - 1)};
2122 vision_mrope_yarn_corr_dims(rope_dims, n_ctx_orig, freq_base, beta_fast, beta_slow, corr_dims);
2123
2124 for (int tok = 0; tok < num_tokens; ++tok) {
2125 float theta_t = (float) positions[tok];
2126 float theta_h = (float) positions[tok + num_pos];
2127 float theta_w = (float) positions[tok + 2 * num_pos];
2128 float theta_e = (float) positions[tok + 3 * num_pos];
2129 float *row = x + (size_t) tok * (size_t) aligned_head_dim;
2130
2131 for (int pair = 0; pair < rope_pairs; ++pair) {
2132 const int sector = sect_dims > 0 ? (pair % sect_dims) : pair;
2133 if (!is_imrope) {
2134 if (sector == 0) {
2135 theta_t = (float) positions[tok];
2136 } else if (sector == sections[0]) {
2137 theta_h = (float) positions[tok + num_pos];
2138 } else if (sector == sec_w) {
2139 theta_w = (float) positions[tok + 2 * num_pos];
2140 } else if (sector == sec_e) {
2141 theta_e = (float) positions[tok + 3 * num_pos];
2142 }
2143 }
2144
2145 float theta = theta_t;
2146 if (is_imrope) {
2147 if (sector % 3 == 1 && sector < 3 * sections[1]) {
2148 theta = theta_h;
2149 } else if (sector % 3 == 2 && sector < 3 * sections[2]) {
2150 theta = theta_w;
2151 } else if (sector % 3 == 0 && sector < 3 * sections[0]) {
2152 theta = theta_t;
2153 } else {
2154 theta = theta_e;
2155 }
2156 } else if (sector >= sections[0] && sector < sec_w) {
2157 theta = theta_h;
2158 } else if (sector >= sec_w && sector < sec_e) {
2159 theta = theta_w;
2160 } else if (sector >= sec_e) {
2161 theta = theta_e;
2162 }
2163
2164 float cos_theta = 0.0f;
2165 float sin_theta = 0.0f;
2167 theta,
2168 freq_scale,
2169 corr_dims,
2170 pair * 2,
2171 ext_factor,
2172 attn_factor,
2173 &cos_theta,
2174 &sin_theta
2175 );
2176
2177 const float x0 = row[pair];
2178 const float x1 = row[pair + rope_pairs];
2180 x0,
2181 x1,
2182 cos_theta,
2183 sin_theta,
2184 &row[pair],
2185 &row[pair + rope_pairs]
2186 );
2187
2188 theta_t *= theta_scale;
2189 theta_h *= theta_scale;
2190 theta_w *= theta_scale;
2191 theta_e *= theta_scale;
2192 }
2193 }
2194}
static float ck_rope_reference_powf(float base, float exponent)
static void vision_mrope_yarn(float theta_extrap, float freq_scale, const float corr_dims[2], int chan, float ext_factor, float attn_factor, float *cos_theta, float *sin_theta)
static void vision_mrope_yarn_corr_dims(int n_dims, int n_ctx_orig, float freq_base, float beta_fast, float beta_slow, float dims[2])
static void mrope_rotate_pair(float x0, float x1, float cos_theta, float sin_theta, float *out0, float *out1)

References ck_rope_reference_powf(), mrope_rotate_pair(), vision_mrope_yarn(), and vision_mrope_yarn_corr_dims().

Referenced by mrope_qk_imrope_positions().

◆ 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}
int ck_strict_parity_enabled(void)
#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}
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_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.

◆ mrope_rotate_pair()

static void mrope_rotate_pair ( float  x0,
float  x1,
float  cos_theta,
float  sin_theta,
float *  out0,
float *  out1 
)
inlinestatic

Definition at line 1763 of file rope_kernels.c.

1770 {
1771 const float x1_sin = x1 * sin_theta;
1772 const float x1_cos = x1 * cos_theta;
1773 *out0 = fmaf(x0, cos_theta, -x1_sin);
1774 *out1 = fmaf(x0, sin_theta, x1_cos);
1775}

Referenced by explicit_mrope_apply_head(), text_mrope_apply_head(), and vision_mrope_apply_head().

◆ rope_apply_decode_pairwise_llama_cpu()

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

Definition at line 1609 of file rope_kernels.c.

1615{
1616 for (int head = 0; head < num_heads; ++head) {
1617 float *row = rows + (size_t)head * (size_t)aligned_head_dim;
1618 for (int i = 0; i < rotary_dim; i += 2) {
1619 const int pair = i / 2;
1620 const float x0 = row[i];
1621 const float x1 = row[i + 1];
1622 const float cosine = cos_row[pair];
1623 const float sine = sin_row[pair];
1624 row[i] = fmaf(x0, cosine, -x1 * sine);
1625 row[i + 1] = fmaf(x0, sine, x1 * cosine);
1626 }
1627 }
1628}

Referenced by rope_forward_qk_pairwise_llama_cpu().

◆ rope_apply_head()

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

Definition at line 608 of file rope_kernels.c.

616{
617 // Use head_dim if rotary_dim not specified or invalid
618 if (rotary_dim <= 0 || rotary_dim > head_dim) {
619 rotary_dim = head_dim;
620 }
621
622 int rotary_half = rotary_dim / 2;
623
624 for (int t = 0; t < num_tokens; ++t) {
625 int pos = pos_offset + t;
626 const float *cos_row = cos_cache + pos * rotary_half;
627 const float *sin_row = sin_cache + pos * rotary_half;
628 float *x_row = x + (size_t)t * (size_t)aligned_head_dim;
629
630#if defined(__AVX512F__)
631 // Process 16 pairs at a time (within rotary_half)
632 int i = 0;
633 for (; i + 16 <= rotary_half; i += 16) {
634 __m512 x0 = _mm512_loadu_ps(&x_row[i]);
635 __m512 x1 = _mm512_loadu_ps(&x_row[i + rotary_half]);
636 __m512 c = _mm512_loadu_ps(&cos_row[i]);
637 __m512 s = _mm512_loadu_ps(&sin_row[i]);
638
639 // x'[i] = x0 * c - x1 * s
640 __m512 r0 = _mm512_fmsub_ps(x0, c, _mm512_mul_ps(x1, s));
641 // x'[i+half] = x0 * s + x1 * c
642 __m512 r1 = _mm512_fmadd_ps(x0, s, _mm512_mul_ps(x1, c));
643
644 _mm512_storeu_ps(&x_row[i], r0);
645 _mm512_storeu_ps(&x_row[i + rotary_half], r1);
646 }
647 // Handle remaining elements in rotary portion
648 for (; i < rotary_half; ++i) {
649 float x0 = x_row[i];
650 float x1 = x_row[i + rotary_half];
651 float c = cos_row[i];
652 float s = sin_row[i];
653 x_row[i] = x0 * c - x1 * s;
654 x_row[i + rotary_half] = x0 * s + x1 * c;
655 }
656
657#elif defined(__AVX__)
658 // Process 8 pairs at a time (within rotary_half)
659 int i = 0;
660 for (; i + 8 <= rotary_half; i += 8) {
661 __m256 x0 = _mm256_loadu_ps(&x_row[i]);
662 __m256 x1 = _mm256_loadu_ps(&x_row[i + rotary_half]);
663 __m256 c = _mm256_loadu_ps(&cos_row[i]);
664 __m256 s = _mm256_loadu_ps(&sin_row[i]);
665
666 // x'[i] = x0 * c - x1 * s (no FMA in AVX1)
667 __m256 x0c = _mm256_mul_ps(x0, c);
668 __m256 x1s = _mm256_mul_ps(x1, s);
669 __m256 r0 = _mm256_sub_ps(x0c, x1s);
670
671 // x'[i+half] = x0 * s + x1 * c
672 __m256 x0s = _mm256_mul_ps(x0, s);
673 __m256 x1c = _mm256_mul_ps(x1, c);
674 __m256 r1 = _mm256_add_ps(x0s, x1c);
675
676 _mm256_storeu_ps(&x_row[i], r0);
677 _mm256_storeu_ps(&x_row[i + rotary_half], r1);
678 }
679 // Handle remaining elements in rotary portion
680 for (; i < rotary_half; ++i) {
681 float x0 = x_row[i];
682 float x1 = x_row[i + rotary_half];
683 float c = cos_row[i];
684 float s = sin_row[i];
685 x_row[i] = x0 * c - x1 * s;
686 x_row[i + rotary_half] = x0 * s + x1 * c;
687 }
688
689#else
690 // Scalar fallback
691 for (int i = 0; i < rotary_half; ++i) {
692 float x0 = x_row[i];
693 float x1 = x_row[i + rotary_half];
694 float c = cos_row[i];
695 float s = sin_row[i];
696
697 x_row[i] = x0 * c - x1 * s;
698 x_row[i + rotary_half] = x0 * s + x1 * c;
699 }
700#endif
701
702 // Channels [rotary_dim, head_dim) pass through unchanged - nothing to do
703 // They're already in place and don't need rotation
704 }
705}

Referenced by rope_forward_strided_with_rotary_dim(), and rope_forward_with_rotary_dim().

◆ rope_apply_head_pairwise()

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

Definition at line 707 of file rope_kernels.c.

715{
716 if (rotary_dim <= 0 || rotary_dim > head_dim) {
717 rotary_dim = head_dim;
718 }
719
720 int rotary_half = rotary_dim / 2;
721
722 for (int t = 0; t < num_tokens; ++t) {
723 int pos = pos_offset + t;
724 const float *cos_row = cos_cache + pos * rotary_half;
725 const float *sin_row = sin_cache + pos * rotary_half;
726 float *x_row = x + (size_t)t * (size_t)aligned_head_dim;
727
728 for (int i = 0; i < rotary_half; ++i) {
729 const int idx0 = 2 * i;
730 const int idx1 = idx0 + 1;
731 float x0 = x_row[idx0];
732 float x1 = x_row[idx1];
733 float c = cos_row[i];
734 float s = sin_row[i];
735 x_row[idx0] = x0 * c - x1 * s;
736 x_row[idx1] = x0 * s + x1 * c;
737 }
738 }
739}

Referenced by rope_forward_qk_pairwise_with_rotary_dim().

◆ 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_apply_head_pairwise()

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

Definition at line 741 of file rope_kernels.c.

750{
751 if (rotary_dim <= 0 || rotary_dim > head_dim) {
752 rotary_dim = head_dim;
753 }
754
755 int rotary_even = rotary_dim - (rotary_dim % 2);
756 int rotary_half = rotary_even / 2;
757
758 for (int t = 0; t < num_tokens; ++t) {
759 int pos = pos_offset + t;
760 const float *cos_row = cos_cache + pos * rotary_half;
761 const float *sin_row = sin_cache + pos * rotary_half;
762 const float *d_out_row = d_out + (size_t)t * (size_t)aligned_head_dim;
763 float *d_x_row = d_x + (size_t)t * (size_t)aligned_head_dim;
764
765 for (int i = 0; i < rotary_half; ++i) {
766 const int idx0 = 2 * i;
767 const int idx1 = idx0 + 1;
768 float d0 = d_out_row[idx0];
769 float d1 = d_out_row[idx1];
770 float c = cos_row[i];
771 float s = sin_row[i];
772 d_x_row[idx0] = d0 * c + d1 * s;
773 d_x_row[idx1] = -d0 * s + d1 * c;
774 }
775
776 for (int i = rotary_even; i < head_dim; ++i) {
777 d_x_row[i] = d_out_row[i];
778 }
779 for (int i = head_dim; i < aligned_head_dim; ++i) {
780 d_x_row[i] = 0.0f;
781 }
782 }
783}

Referenced by rope_backward_qk_pairwise_with_rotary_dim().

◆ 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_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_gemma4v_vision_xy_one()

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

Definition at line 1427 of file rope_kernels.c.

1435{
1436 if (!x || num_heads <= 0 || num_tokens <= 0 || head_dim <= 0 || aligned_head_dim <= 0) {
1437 return;
1438 }
1439 if (grid_w <= 0) {
1440 grid_w = num_tokens;
1441 }
1442 if (rotary_dim <= 0 || rotary_dim > head_dim) {
1443 rotary_dim = head_dim;
1444 }
1445 if (freq_base <= 0.0f) {
1446 freq_base = 100.0f;
1447 }
1448
1449 /* Gemma4V vision uses llama.cpp's 2D NEOX RoPE contract:
1450 * rotate the first half of the rotary span by patch x, and the second
1451 * half by patch y. Each half is itself split-half/NEOX rotated.
1452 */
1453 const int half_span = rotary_dim / 2;
1454 const int segment_half = half_span / 2;
1455 if (segment_half <= 0) {
1456 return;
1457 }
1458 const size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
1459 const float theta_scale = powf(freq_base, -2.0f / (float)half_span);
1460
1461 for (int h = 0; h < num_heads; ++h) {
1462 float *head = x + (size_t)h * head_stride;
1463 for (int t = 0; t < num_tokens; ++t) {
1464 const int pos_x = t % grid_w;
1465 const int pos_y = t / grid_w;
1466 float *row = head + (size_t)t * (size_t)aligned_head_dim;
1467 for (int i = 0; i < segment_half; ++i) {
1468 const float inv_freq = powf(theta_scale, (float)i);
1469
1470 const float theta_x = (float)pos_x * inv_freq;
1471 const float cx = cosf(theta_x);
1472 const float sx = sinf(theta_x);
1473 const int x0i = i;
1474 const int x1i = i + segment_half;
1475 const float x0 = row[x0i];
1476 const float x1 = row[x1i];
1477 row[x0i] = x0 * cx - x1 * sx;
1478 row[x1i] = x1 * cx + x0 * sx;
1479
1480 const float theta_y = (float)pos_y * inv_freq;
1481 const float cy = cosf(theta_y);
1482 const float sy = sinf(theta_y);
1483 const int y0i = half_span + i;
1484 const int y1i = half_span + i + segment_half;
1485 const float y0 = row[y0i];
1486 const float y1 = row[y1i];
1487 row[y0i] = y0 * cy - y1 * sy;
1488 row[y1i] = y1 * cy + y0 * sy;
1489 }
1490 }
1491 }
1492}

Referenced by rope_forward_qk_gemma4v_vision_xy().

◆ 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(), ck_test_rope(), 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_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_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_split_direct_muse_bf16_one()

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

Definition at line 1201 of file rope_kernels.c.

1210{
1211 if (!x || heads <= 0 || tokens <= 0 || head_dim <= 0 ||
1212 aligned_head_dim < head_dim) {
1213 return;
1214 }
1215 if (rotary_dim <= 0 || rotary_dim > head_dim) rotary_dim = head_dim;
1216 if (freq_base <= 0.0f) freq_base = 10000.0f;
1217
1218 const int half = rotary_dim / 2;
1219 const size_t head_stride = (size_t)tokens * (size_t)aligned_head_dim;
1220 for (int token = 0; token < tokens; ++token) {
1221 const float position = (float)(pos_offset + token);
1222 for (int index = 0; index < half; ++index) {
1223 const float exponent = (float)(2 * index) / (float)rotary_dim;
1224 const float inv_freq = 1.0f / powf(freq_base, exponent);
1225 const float angle = position * inv_freq;
1226 const float cosine = bf16_to_float(float_to_bf16(cosf(angle)));
1227 const float sine = bf16_to_float(float_to_bf16(sinf(angle)));
1228 for (int head = 0; head < heads; ++head) {
1229 float *row = x + (size_t)head * head_stride +
1230 (size_t)token * (size_t)aligned_head_dim;
1231 const float first = bf16_to_float(float_to_bf16(row[index]));
1232 const float second = bf16_to_float(float_to_bf16(row[index + half]));
1233 const float first_cos =
1234 bf16_to_float(float_to_bf16(first * cosine));
1235 const float second_sin =
1236 bf16_to_float(float_to_bf16(second * sine));
1237 const float second_cos =
1238 bf16_to_float(float_to_bf16(second * cosine));
1239 const float first_sin =
1240 bf16_to_float(float_to_bf16(first * sine));
1241 row[index] =
1242 bf16_to_float(float_to_bf16(first_cos - second_sin));
1243 row[index + half] =
1244 bf16_to_float(float_to_bf16(second_cos + first_sin));
1245 }
1246 }
1247 }
1248}

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

Referenced by rope_forward_qk_split_direct_muse_pytorch_bf16_storage().

◆ rope_forward_split_direct_one()

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

Definition at line 1128 of file rope_kernels.c.

1138{
1139 if (!x || num_heads <= 0 || num_tokens <= 0 || head_dim <= 0 || aligned_head_dim <= 0) {
1140 return;
1141 }
1142 if (rotary_dim <= 0 || rotary_dim > head_dim) {
1143 rotary_dim = head_dim;
1144 }
1145 if (freq_base <= 0.0f) {
1146 freq_base = 10000.0f;
1147 }
1148
1149 /* Split-half rotate_half layout, matching HF/Llama-style RoPE:
1150 * [x0...xH, y0...yH] -> [-y0...-yH, x0...xH]
1151 * Gemma4 is currently the first v8 model that needs direct per-layer
1152 * theta/rotary_dim control; keep this model-neutral and select it from
1153 * the IR via rope_layout=split_half + rope_param_mode=per_layer/direct.
1154 */
1155 const int rotary_half = rotary_dim / 2;
1156 const size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
1157 const float theta_scale = powf(freq_base, -2.0f / (float)rotary_dim);
1158
1159 for (int h = 0; h < num_heads; ++h) {
1160 float *head = x + (size_t)h * head_stride;
1161 for (int t = 0; t < num_tokens; ++t) {
1162 const float pos = (float)(pos_offset + t);
1163 float *x_row = head + (size_t)t * (size_t)aligned_head_dim;
1164 for (int i = 0; i < rotary_half; ++i) {
1165 const int idx0 = i;
1166 const int idx1 = i + rotary_half;
1167 const float ff = (use_freq_factors && freq_factors) ? freq_factors[i] : 1.0f;
1168 const float theta = pos * powf(theta_scale, (float)i) / ff;
1169 const float c = cosf(theta);
1170 const float sv = sinf(theta);
1171 const float x0 = x_row[idx0];
1172 const float x1 = x_row[idx1];
1173 x_row[idx0] = x0 * c - x1 * sv;
1174 x_row[idx1] = x1 * c + x0 * sv;
1175 }
1176 }
1177 }
1178}

Referenced by rope_forward_q_split_direct_f32(), and rope_forward_qk_split_direct_f32().

◆ 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}

Referenced by ck_test_rope().

◆ 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}

◆ text_mrope_apply_head()

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

Definition at line 2196 of file rope_kernels.c.

2212 {
2213 if (!x || num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim || n_dims <= 0) {
2214 return;
2215 }
2216
2217 int rope_dims = n_dims;
2218 if (rope_dims > head_dim) {
2219 rope_dims = head_dim;
2220 }
2221 rope_dims &= ~1;
2222 if (rope_dims <= 0) {
2223 return;
2224 }
2225 const int rope_pairs = rope_dims / 2;
2226
2227 const int sec_w = sections[0] + sections[1];
2228 const int sec_e = sec_w + sections[2];
2229 const int sect_dims = sections[0] + sections[1] + sections[2] + sections[3];
2230 const float theta_scale = powf(freq_base, -2.0f / (float) rope_dims);
2231 float corr_dims[2] = {0.0f, (float) (rope_dims - 1)};
2232 vision_mrope_yarn_corr_dims(rope_dims, n_ctx_orig, freq_base, beta_fast, beta_slow, corr_dims);
2233
2234 for (int tok = 0; tok < num_tokens; ++tok) {
2235 const float base_pos = (float) (pos_offset + tok);
2236 float theta_t = base_pos;
2237 float theta_h = base_pos;
2238 float theta_w = base_pos;
2239 float theta_e = 0.0f;
2240 float *row = x + (size_t) tok * (size_t) aligned_head_dim;
2241
2242 for (int pair = 0; pair < rope_pairs; ++pair) {
2243 const int sector = sect_dims > 0 ? (pair % sect_dims) : pair;
2244 float theta = theta_t;
2245 if (is_imrope && sector % 3 == 1 && sector < 3 * sections[1]) {
2246 theta = theta_h;
2247 } else if (is_imrope && sector % 3 == 2 && sector < 3 * sections[2]) {
2248 theta = theta_w;
2249 } else if (is_imrope && sector % 3 == 0 && sector < 3 * sections[0]) {
2250 theta = theta_t;
2251 } else if (is_imrope) {
2252 theta = theta_e;
2253 } else if (sector >= sections[0] && sector < sec_w) {
2254 theta = theta_h;
2255 } else if (sector >= sec_w && sector < sec_e) {
2256 theta = theta_w;
2257 } else if (sector >= sec_e) {
2258 theta = theta_e;
2259 }
2260
2261 float cos_theta = 0.0f;
2262 float sin_theta = 0.0f;
2264 theta,
2265 freq_scale,
2266 corr_dims,
2267 pair * 2,
2268 ext_factor,
2269 attn_factor,
2270 &cos_theta,
2271 &sin_theta
2272 );
2273
2274 const float x0 = row[pair];
2275 const float x1 = row[pair + rope_pairs];
2277 x0,
2278 x1,
2279 cos_theta,
2280 sin_theta,
2281 &row[pair],
2282 &row[pair + rope_pairs]
2283 );
2284
2285 theta_t *= theta_scale;
2286 theta_h *= theta_scale;
2287 theta_w *= theta_scale;
2288 theta_e *= theta_scale;
2289 }
2290 }
2291}
static void text_mrope_yarn(float theta_extrap, float freq_scale, const float corr_dims[2], int chan, float ext_factor, float attn_factor, float *cos_theta, float *sin_theta)

References mrope_rotate_pair(), text_mrope_yarn(), and vision_mrope_yarn_corr_dims().

Referenced by mrope_qk_text(), and mrope_qk_text_imrope().

◆ text_mrope_apply_positions_pytorch_bf16_storage()

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

Definition at line 2487 of file rope_kernels.c.

2498{
2499 if (!x || !positions || num_heads <= 0 || num_tokens <= 0 || head_dim <= 0 ||
2500 aligned_head_dim < head_dim || n_dims <= 0) {
2501 return;
2502 }
2503 int rope_dims = n_dims < head_dim ? n_dims : head_dim;
2504 rope_dims &= ~1;
2505 if (rope_dims <= 0) return;
2506 const int pairs = rope_dims / 2;
2507 if (sections[0] <= 0 || sections[1] < 0 || sections[2] < 0 ||
2508 sections[3] != 0 || sections[0] + sections[1] + sections[2] != pairs) {
2509 return;
2510 }
2511 const size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
2512
2513 for (int h = 0; h < num_heads; ++h) {
2514 float *head = x + (size_t)h * head_stride;
2515 for (int tok = 0; tok < num_tokens; ++tok) {
2516 float *row = head + (size_t)tok * (size_t)aligned_head_dim;
2517 for (int pair = 0; pair < pairs; ++pair) {
2518 int axis = 0;
2519 if (pair < sections[1] * 3 && pair % 3 == 1) axis = 1;
2520 if (pair < sections[2] * 3 && pair % 3 == 2) axis = 2;
2521 const float position = (float)positions[(size_t)axis * (size_t)num_tokens + (size_t)tok];
2522 const float exponent = (2.0f * (float)pair) / (float)rope_dims;
2523 const float inv_freq = 1.0f / ck_rope_reference_powf(freq_base, exponent);
2524 const float angle = (position * inv_freq) * freq_scale;
2525 const float cosine = bf16_to_float(float_to_bf16(ck_rope_reference_cosf(angle)));
2526 const float sine = bf16_to_float(float_to_bf16(ck_rope_reference_sinf(angle)));
2527 const float x0 = row[pair];
2528 const float x1 = row[pair + pairs];
2529
2530 volatile uint16_t x0_cos_bits = float_to_bf16(x0 * cosine);
2531 volatile uint16_t x1_sin_bits = float_to_bf16((-x1) * sine);
2532 volatile uint16_t x1_cos_bits = float_to_bf16(x1 * cosine);
2533 volatile uint16_t x0_sin_bits = float_to_bf16(x0 * sine);
2534 const float x0_cos = bf16_to_float(x0_cos_bits);
2535 const float x1_sin = bf16_to_float(x1_sin_bits);
2536 const float x1_cos = bf16_to_float(x1_cos_bits);
2537 const float x0_sin = bf16_to_float(x0_sin_bits);
2538 volatile uint16_t out0_bits = float_to_bf16(x0_cos + x1_sin);
2539 volatile uint16_t out1_bits = float_to_bf16(x1_cos + x0_sin);
2540 row[pair] = bf16_to_float(out0_bits);
2541 row[pair + pairs] = bf16_to_float(out1_bits);
2542 }
2543 }
2544 }
2545}

References bf16_to_float(), ck_rope_reference_cosf(), ck_rope_reference_powf(), ck_rope_reference_sinf(), and float_to_bf16().

Referenced by mrope_qk_text_imrope_positions_bf16_pytorch_storage().

◆ text_mrope_apply_pytorch_bf16_storage()

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

Definition at line 2433 of file rope_kernels.c.

2442{
2443 if (!x || num_heads <= 0 || num_tokens <= 0 || head_dim <= 0 ||
2444 aligned_head_dim < head_dim || n_dims <= 0) {
2445 return;
2446 }
2447 int rope_dims = n_dims < head_dim ? n_dims : head_dim;
2448 rope_dims &= ~1;
2449 if (rope_dims <= 0) return;
2450 const int pairs = rope_dims / 2;
2451 const size_t head_stride = (size_t)num_tokens * (size_t)aligned_head_dim;
2452
2453 for (int h = 0; h < num_heads; ++h) {
2454 float *head = x + (size_t)h * head_stride;
2455 for (int tok = 0; tok < num_tokens; ++tok) {
2456 float *row = head + (size_t)tok * (size_t)aligned_head_dim;
2457 const float position = (float)(pos_offset + tok);
2458 for (int pair = 0; pair < pairs; ++pair) {
2459 const float exponent = (2.0f * (float)pair) / (float)rope_dims;
2460 const float inv_freq = 1.0f / ck_rope_reference_powf(freq_base, exponent);
2461 const float angle = (position * inv_freq) * freq_scale;
2462 const float cosine = bf16_to_float(float_to_bf16(ck_rope_reference_cosf(angle)));
2463 const float sine = bf16_to_float(float_to_bf16(ck_rope_reference_sinf(angle)));
2464 const float x0 = row[pair];
2465 const float x1 = row[pair + pairs];
2466
2467 volatile uint16_t x0_cos_bits = float_to_bf16(x0 * cosine);
2468 volatile uint16_t x1_sin_bits = float_to_bf16((-x1) * sine);
2469 volatile uint16_t x1_cos_bits = float_to_bf16(x1 * cosine);
2470 volatile uint16_t x0_sin_bits = float_to_bf16(x0 * sine);
2471 const float x0_cos = bf16_to_float(x0_cos_bits);
2472 const float x1_sin = bf16_to_float(x1_sin_bits);
2473 const float x1_cos = bf16_to_float(x1_cos_bits);
2474 const float x0_sin = bf16_to_float(x0_sin_bits);
2475 volatile uint16_t out0_bits = float_to_bf16(x0_cos + x1_sin);
2476 volatile uint16_t out1_bits = float_to_bf16(x1_cos + x0_sin);
2477 row[pair] = bf16_to_float(out0_bits);
2478 row[pair + pairs] = bf16_to_float(out1_bits);
2479 }
2480 }
2481 }
2482}

References bf16_to_float(), ck_rope_reference_cosf(), ck_rope_reference_powf(), ck_rope_reference_sinf(), and float_to_bf16().

Referenced by mrope_qk_text_imrope_bf16_pytorch_storage().

◆ text_mrope_yarn()

static void text_mrope_yarn ( float  theta_extrap,
float  freq_scale,
const float  corr_dims[2],
int  chan,
float  ext_factor,
float  attn_factor,
float *  cos_theta,
float *  sin_theta 
)
static

Definition at line 1738 of file rope_kernels.c.

1747 {
1748 float theta_interp = freq_scale * theta_extrap;
1749 float theta = theta_interp;
1750 float mscale = attn_factor;
1751
1752 if (ext_factor != 0.0f) {
1753 const float ramp_mix =
1754 vision_mrope_yarn_ramp(corr_dims[0], corr_dims[1], chan) * ext_factor;
1755 theta = theta_interp * (1.0f - ramp_mix) + theta_extrap * ramp_mix;
1756 mscale *= 1.0f + 0.1f * logf(1.0f / fmaxf(freq_scale, 1e-6f));
1757 }
1758
1759 *cos_theta = ck_rope_reference_cosf(theta) * mscale;
1760 *sin_theta = ck_rope_reference_sinf(theta) * mscale;
1761}
static float vision_mrope_yarn_ramp(float low, float high, int chan)

References ck_rope_reference_cosf(), ck_rope_reference_sinf(), and vision_mrope_yarn_ramp().

Referenced by text_mrope_apply_head().

◆ vision_mrope_apply_head()

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

Definition at line 1777 of file rope_kernels.c.

1792 {
1793 if (!x || !positions || num_tokens <= 0 || head_dim <= 0 || aligned_head_dim < head_dim || n_dims <= 0) {
1794 return;
1795 }
1796
1797 int rotary_width = n_dims;
1798 if (rotary_width > head_dim) {
1799 rotary_width = head_dim;
1800 }
1801 if (rotary_width <= 0 || (rotary_width & 1) != 0 || rotary_width > aligned_head_dim) {
1802 return;
1803 }
1804 const int rope_pairs = rotary_width / 2;
1805
1806 const int axis_y_pairs = sections[0];
1807 const int axis_x_pairs = sections[1];
1808 if (axis_y_pairs <= 0 || axis_x_pairs <= 0 || axis_y_pairs + axis_x_pairs > rope_pairs) {
1809 return;
1810 }
1811
1812 const int num_pos = num_tokens;
1813 const float theta_scale = ck_rope_reference_powf(freq_base, -2.0f / (float) rope_pairs);
1814 float corr_dims[2] = {0.0f, (float) (rope_pairs - 1)};
1815 vision_mrope_yarn_corr_dims(rope_pairs, n_ctx_orig, freq_base, beta_fast, beta_slow, corr_dims);
1816
1817 for (int tok = 0; tok < num_tokens; ++tok) {
1818 float theta_y = (float) positions[tok];
1819 float theta_x = (float) positions[tok + num_pos];
1820 float *row = x + (size_t) tok * (size_t) aligned_head_dim;
1821
1822 for (int pair = 0; pair < rope_pairs; ++pair) {
1823 const int is_x_axis = pair >= axis_y_pairs && pair < axis_y_pairs + axis_x_pairs;
1824 if (pair == axis_y_pairs) {
1825 theta_x = (float) positions[tok + num_pos];
1826 }
1827 const float theta = is_x_axis ? theta_x : theta_y;
1828
1829 float cos_theta = 0.0f;
1830 float sin_theta = 0.0f;
1832 theta,
1833 freq_scale,
1834 corr_dims,
1835 pair * 2,
1836 ext_factor,
1837 attn_factor,
1838 &cos_theta,
1839 &sin_theta
1840 );
1841
1842 const float x0 = row[pair];
1843 const float x1 = row[pair + rope_pairs];
1845 x0,
1846 x1,
1847 cos_theta,
1848 sin_theta,
1849 &row[pair],
1850 &row[pair + rope_pairs]
1851 );
1852
1853 theta_y *= theta_scale;
1854 theta_x *= theta_scale;
1855 }
1856 }
1857}

References ck_rope_reference_powf(), mrope_rotate_pair(), vision_mrope_yarn(), and vision_mrope_yarn_corr_dims().

Referenced by mrope_qk_vision().

◆ vision_mrope_yarn()

static void vision_mrope_yarn ( float  theta_extrap,
float  freq_scale,
const float  corr_dims[2],
int  chan,
float  ext_factor,
float  attn_factor,
float *  cos_theta,
float *  sin_theta 
)
static

Definition at line 1714 of file rope_kernels.c.

1723 {
1724 float theta_interp = freq_scale * theta_extrap;
1725 float theta = theta_interp;
1726 float mscale = attn_factor;
1727
1728 if (ext_factor != 0.0f) {
1729 const float ramp_mix = vision_mrope_yarn_ramp(corr_dims[0], corr_dims[1], chan) * ext_factor;
1730 theta = theta_interp * (1.0f - ramp_mix) + theta_extrap * ramp_mix;
1731 mscale *= 1.0f + 0.1f * logf(1.0f / fmaxf(freq_scale, 1e-6f));
1732 }
1733
1734 *cos_theta = ck_rope_reference_cosf(theta) * mscale;
1735 *sin_theta = ck_rope_reference_sinf(theta) * mscale;
1736}

References ck_rope_reference_cosf(), ck_rope_reference_sinf(), and vision_mrope_yarn_ramp().

Referenced by explicit_mrope_apply_head(), and vision_mrope_apply_head().

◆ vision_mrope_yarn_corr_dim()

static float vision_mrope_yarn_corr_dim ( int  n_dims,
int  n_ctx_orig,
float  n_rot,
float  base 
)
static

Definition at line 1691 of file rope_kernels.c.

1691 {
1692 return n_dims * logf((float) n_ctx_orig / (n_rot * 2.0f * (float) M_PI)) / (2.0f * logf(base));
1693}
#define M_PI

References M_PI.

Referenced by vision_mrope_yarn_corr_dims().

◆ vision_mrope_yarn_corr_dims()

static void vision_mrope_yarn_corr_dims ( int  n_dims,
int  n_ctx_orig,
float  freq_base,
float  beta_fast,
float  beta_slow,
float  dims[2] 
)
static

Definition at line 1695 of file rope_kernels.c.

1702 {
1703 float start = floorf(vision_mrope_yarn_corr_dim(n_dims, n_ctx_orig, beta_fast, freq_base));
1704 float end = ceilf(vision_mrope_yarn_corr_dim(n_dims, n_ctx_orig, beta_slow, freq_base));
1705 dims[0] = start < 0.0f ? 0.0f : start;
1706 dims[1] = end > (float) (n_dims - 1) ? (float) (n_dims - 1) : end;
1707}
static float vision_mrope_yarn_corr_dim(int n_dims, int n_ctx_orig, float n_rot, float base)
uint32_t end
Definition utf8.c:215
uint32_t start
Definition utf8.c:214

References end, start, and vision_mrope_yarn_corr_dim().

Referenced by explicit_mrope_apply_head(), text_mrope_apply_head(), and vision_mrope_apply_head().

◆ vision_mrope_yarn_ramp()

static float vision_mrope_yarn_ramp ( float  low,
float  high,
int  chan 
)
static

Definition at line 1709 of file rope_kernels.c.

1709 {
1710 const float y = ((float) chan - low) / fmaxf(0.001f, high - low);
1711 return 1.0f - fminf(1.0f, fmaxf(0.0f, y));
1712}

Referenced by text_mrope_yarn(), and vision_mrope_yarn().

◆ yarn_correction_dim()

static float yarn_correction_dim ( float  rotations,
int  rotary_dim,
float  freq_base,
int  original_context 
)
static

Definition at line 426 of file rope_kernels.c.

430{
431 return ((float)rotary_dim *
432 logf((float)original_context / (rotations * 2.0f * (float)M_PI))) /
433 (2.0f * logf(freq_base));
434}

References M_PI.

Referenced by yarn_rope_cache_explicit_positions_impl().

◆ yarn_mscale()

static float yarn_mscale ( float  factor,
float  scale 
)
static

Definition at line 436 of file rope_kernels.c.

437{
438 return factor <= 1.0f ? 1.0f : 0.1f * scale * logf(factor) + 1.0f;
439}

Referenced by yarn_rope_cache_explicit_positions_impl().

◆ 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().

◆ yarn_rope_cache_explicit_positions_impl()

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

Definition at line 441 of file rope_kernels.c.

455{
456 if ((!cos_f32 && !cos_bf16) || (!sin_f32 && !sin_bf16) ||
457 num_tokens <= 0 || rotary_dim <= 0 || (rotary_dim & 1) != 0 ||
458 freq_base <= 0.0f || factor <= 0.0f || original_context <= 0 ||
459 beta_fast <= 0.0f || beta_slow <= 0.0f) {
460 return;
461 }
462
463 const int pairs = rotary_dim / 2;
464 float low = floorf(yarn_correction_dim(
465 beta_fast, rotary_dim, freq_base, original_context));
466 float high = ceilf(yarn_correction_dim(
467 beta_slow, rotary_dim, freq_base, original_context));
468 low = fmaxf(low, 0.0f);
469 high = fminf(high, (float)(rotary_dim - 1));
470 if (low == high) high += 0.001f;
471
472 const float attention_factor =
473 yarn_mscale(factor, mscale) /
474 yarn_mscale(factor, mscale_all_dim);
475
476 for (int token = 0; token < num_tokens; ++token) {
477 const float position = (float)(positions ? positions[token] : token);
478 for (int pair = 0; pair < pairs; ++pair) {
479 const float exponent = (2.0f * (float)pair) / (float)rotary_dim;
480 const float pos_freq = ck_rope_reference_powf(freq_base, exponent);
481 const float inv_extrap = 1.0f / pos_freq;
482 const float inv_interp = 1.0f / (factor * pos_freq);
483 float ramp = ((float)pair - low) / (high - low);
484 ramp = fminf(1.0f, fmaxf(0.0f, ramp));
485 const float inv_freq = inv_interp * ramp + inv_extrap * (1.0f - ramp);
486 const float angle = position * inv_freq;
487 const float cosine = ck_rope_reference_cosf(angle) * attention_factor;
488 const float sine = ck_rope_reference_sinf(angle) * attention_factor;
489 const size_t index = (size_t)token * (size_t)pairs + (size_t)pair;
490 if (cos_f32) cos_f32[index] = cosine;
491 if (sin_f32) sin_f32[index] = sine;
492 if (cos_bf16) cos_bf16[index] = float_to_bf16(cosine);
493 if (sin_bf16) sin_bf16[index] = float_to_bf16(sine);
494 }
495 }
496}
static float yarn_mscale(float factor, float scale)
static float yarn_correction_dim(float rotations, int rotary_dim, float freq_base, int original_context)

References ck_rope_reference_cosf(), ck_rope_reference_powf(), ck_rope_reference_sinf(), float_to_bf16(), token, yarn_correction_dim(), and yarn_mscale().

Referenced by yarn_rope_cache_contiguous_positions_f32(), yarn_rope_cache_explicit_positions_bf16(), and yarn_rope_cache_explicit_positions_f32().