42#if defined(__AVX__) || defined(__AVX2__) || defined(__AVXVNNI__)
53 int aligned_embed_dim,
62 int aligned_embed_dim,
71 int aligned_embed_dim,
80 int aligned_embed_dim,
89 int aligned_embed_dim,
97 int aligned_embed_dim,
103 const float *rstd_cache,
108 int aligned_embed_dim);
127 const char *forced = getenv(
"CK_QK_NORM_BACKWARD_ISA");
128 if (!forced || forced[0] ==
'\0' || strcmp(forced,
"auto") == 0) {
131 if (strcmp(forced,
"scalar") == 0) {
134 if (strcmp(forced,
"avx") == 0) {
137 if (strcmp(forced,
"avx2") == 0) {
140 if (strcmp(forced,
"avx_vnni") == 0) {
160#if defined(__AVXVNNI__)
176#if defined(__AVXVNNI__)
178#elif defined(__AVX2__)
180#elif defined(__AVX__)
193 for (
int r = 0; r < rows; ++r) {
194 const float *x = input + (size_t)r * (
size_t)head_dim;
196 for (
int d = 0; d < head_dim; ++d) {
197 double v = (double)x[d];
200 float mean_sq = (float)(sum_sq / (
double)head_dim);
201 rstd_cache[r] = 1.0f / sqrtf(mean_sq + eps);
206static inline float qk_norm_hsum256(__m256 v)
208 __m128 hi = _mm256_extractf128_ps(v, 1);
209 __m128 lo = _mm256_castps256_ps128(v);
210 __m128 sum = _mm_add_ps(lo, hi);
211 sum = _mm_hadd_ps(sum, sum);
212 sum = _mm_hadd_ps(sum, sum);
213 return _mm_cvtss_f32(sum);
216static void qk_norm_compute_rstd_avx(
const float *input,
222 for (
int r = 0; r < rows; ++r) {
223 const float *x = input + (size_t)r * (
size_t)head_dim;
224 __m256 sum_sq_v = _mm256_setzero_ps();
226 for (; d + 8 <= head_dim; d += 8) {
227 __m256 xv = _mm256_loadu_ps(&x[d]);
228 __m256 xv2 = _mm256_mul_ps(xv, xv);
229 sum_sq_v = _mm256_add_ps(sum_sq_v, xv2);
231 float sum_sq = qk_norm_hsum256(sum_sq_v);
232 for (; d < head_dim; ++d) {
233 sum_sq += x[d] * x[d];
235 float mean_sq = sum_sq / (float)head_dim;
236 rstd_cache[r] = 1.0f / sqrtf(mean_sq + eps);
242static void qk_norm_compute_rstd_avx2(
const float *input,
248 for (
int r = 0; r < rows; ++r) {
249 const float *x = input + (size_t)r * (
size_t)head_dim;
250 __m256 sum_sq_v = _mm256_setzero_ps();
252 for (; d + 8 <= head_dim; d += 8) {
253 __m256 xv = _mm256_loadu_ps(&x[d]);
255 sum_sq_v = _mm256_fmadd_ps(xv, xv, sum_sq_v);
257 __m256 xv2 = _mm256_mul_ps(xv, xv);
258 sum_sq_v = _mm256_add_ps(sum_sq_v, xv2);
261 float sum_sq = qk_norm_hsum256(sum_sq_v);
262 for (; d < head_dim; ++d) {
263 sum_sq += x[d] * x[d];
265 float mean_sq = sum_sq / (float)head_dim;
266 rstd_cache[r] = 1.0f / sqrtf(mean_sq + eps);
271#if defined(__AVXVNNI__)
272static void qk_norm_compute_rstd_avx_vnni(
const float *input,
279 qk_norm_compute_rstd_avx2(input, rstd_cache, rows, head_dim, eps);
280#elif defined(__AVX__)
281 qk_norm_compute_rstd_avx(input, rstd_cache, rows, head_dim, eps);
297#if defined(__AVXVNNI__)
299 qk_norm_compute_rstd_avx_vnni(input, rstd_cache, rows, head_dim, eps);
304 qk_norm_compute_rstd_avx2(input, rstd_cache, rows, head_dim, eps);
309 qk_norm_compute_rstd_avx(input, rstd_cache, rows, head_dim, eps);
336 const float *q_gamma,
const float *k_gamma,
337 int num_heads,
int num_kv_heads,
338 int num_tokens,
int head_dim,
float eps)
343 num_heads * num_tokens, head_dim, head_dim, eps);
348 num_kv_heads * num_tokens, head_dim, head_dim, eps);
352 const float *q_gamma,
const float *k_gamma,
353 int num_heads,
int num_kv_heads,
354 int num_tokens,
int head_dim,
float eps)
357 num_heads * num_tokens, head_dim, head_dim, eps);
359 num_kv_heads * num_tokens, head_dim, head_dim, eps);
363 const float *q_gamma,
const float *k_gamma,
364 int num_heads,
int num_kv_heads,
365 int num_tokens,
int head_dim,
float eps)
369 num_heads * num_tokens, head_dim, head_dim, eps);
372 num_kv_heads * num_tokens, head_dim, head_dim, eps);
376 const float *q_gamma,
377 const float *k_gamma,
378 int num_heads,
int num_kv_heads,
379 int num_tokens,
int head_dim,
384 num_heads * num_tokens, head_dim, head_dim, eps);
387 num_kv_heads * num_tokens, head_dim, head_dim, eps);
391 const float *q_gamma,
392 const float *k_gamma,
401 num_heads * num_tokens, head_dim, head_dim, eps);
404 num_kv_heads * num_tokens, head_dim, head_dim, eps);
417 const int q_elements = num_heads * num_tokens * head_dim;
419 q, q, NULL, num_heads * num_tokens, head_dim, head_dim, eps);
421 k, k, NULL, num_kv_heads * num_tokens, head_dim, head_dim, eps);
422 for (
int index = 0; index < q_elements; ++index) {
435 const float *q_gamma,
442 num_heads * num_tokens, head_dim, head_dim, eps);
457 const float *q_in,
const float *k_in,
458 const float *q_gamma,
const float *k_gamma,
459 float *d_q_in,
float *d_k_in,
460 float *d_q_gamma,
float *d_k_gamma,
461 int num_heads,
int num_kv_heads,
462 int num_tokens,
int head_dim,
float eps)
464 int q_rows = num_heads * num_tokens;
465 int k_rows = num_kv_heads * num_tokens;
468 float q_rstd_cache[q_rows];
471 d_q_in, d_q_gamma, q_rows, head_dim, head_dim);
475 float k_rstd_cache[k_rows];
478 d_k_in, d_k_gamma, k_rows, head_dim, head_dim);
static uint16_t float_to_bf16(float f)
static float bf16_to_float(uint16_t v)
static int qk_norm_isa_compiled(QKNormISA isa)
static void qk_norm_compute_rstd_scalar(const float *input, float *rstd_cache, int rows, int head_dim, float eps)
void rmsnorm_forward_fp64_sum(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
void qk_norm_forward_qwen4_pytorch_bf16_storage(float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
void rmsnorm_forward_qwen3next_pytorch_bf16_storage(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
void rmsnorm_forward_llama_production(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
static void qk_norm_compute_rstd(const float *input, float *rstd_cache, int rows, int head_dim, float eps)
void rmsnorm_forward_muse_unweighted_pytorch_bf16_storage(const float *input, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
void qk_norm_forward_muse_unweighted_scaled_pytorch_bf16_storage(float *q, float *k, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps, float q_scale)
void qk_norm_backward(const float *d_q_out, const float *d_k_out, const float *q_in, const float *k_in, const float *q_gamma, const float *k_gamma, float *d_q_in, float *d_k_in, float *d_q_gamma, float *d_k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
void qk_norm_forward_llama_production(float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
void qk_norm_forward_pytorch_bf16_storage(float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
void qk_norm_forward(float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
void qk_norm_forward_fp64_sum(float *q, float *k, const float *q_gamma, const float *k_gamma, int num_heads, int num_kv_heads, int num_tokens, int head_dim, float eps)
void rmsnorm_forward_pytorch_bf16_storage(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
void rmsnorm_forward(const float *input, const float *gamma, float *output, float *rstd_cache, int tokens, int d_model, int aligned_embed_dim, float eps)
static int g_qk_norm_last_isa
void q_norm_forward(float *q, const float *q_gamma, int num_heads, int num_tokens, int head_dim, float eps)
int qk_norm_backward_last_isa(void)
void rmsnorm_backward(const float *d_output, const float *input, const float *gamma, const float *rstd_cache, float *d_input, float *d_gamma, int tokens, int d_model, int aligned_embed_dim)
static QKNormISA qk_norm_parse_forced_isa(void)
static QKNormISA qk_norm_select_isa(void)