20static inline size_t ds_mhc_idx(
int t,
int s,
int d,
int n_streams,
int dim)
22 return ((
size_t)t * (
size_t)n_streams + (
size_t)s) * (size_t)dim + (
size_t)d;
25static inline size_t ds_mix_idx(
int t,
int out_s,
int in_s,
int n_streams)
27 return ((
size_t)t * (
size_t)n_streams + (
size_t)out_s) * (size_t)n_streams + (
size_t)in_s;
37 if (!streams || !mix || !out || tokens <= 0 || n_streams <= 0 || dim <= 0)
return;
39 for (
int t = 0; t < tokens; ++t) {
40 for (
int os = 0; os < n_streams; ++os) {
41 for (
int d = 0; d < dim; ++d) {
43 for (
int is = 0; is < n_streams; ++is) {
47 out[
ds_mhc_idx(t, os, d, n_streams, dim)] = acc;
62 if (!d_out || !streams || !mix || !d_streams || !d_mix ||
63 tokens <= 0 || n_streams <= 0 || dim <= 0)
return;
65 const size_t stream_count = (size_t)tokens * (
size_t)n_streams * (size_t)dim;
66 const size_t mix_count = (size_t)tokens * (
size_t)n_streams * (size_t)n_streams;
67 for (
size_t i = 0; i < stream_count; ++i) d_streams[i] = 0.0f;
68 for (
size_t i = 0; i < mix_count; ++i) d_mix[i] = 0.0f;
70 for (
int t = 0; t < tokens; ++t) {
71 for (
int os = 0; os < n_streams; ++os) {
72 for (
int is = 0; is < n_streams; ++is) {
73 float d_mix_acc = 0.0f;
74 const float m = mix[
ds_mix_idx(t, os, is, n_streams)];
75 for (
int d = 0; d < dim; ++d) {
76 const float go = d_out[
ds_mhc_idx(t, os, d, n_streams, dim)];
77 d_streams[
ds_mhc_idx(t, is, d, n_streams, dim)] += m * go;
78 d_mix_acc += go * streams[
ds_mhc_idx(t, is, d, n_streams, dim)];
80 d_mix[
ds_mix_idx(t, os, is, n_streams)] = d_mix_acc;
94 if (!scores || !indices || !weights || tokens <= 0 || heads <= 0 ||
95 key_count <= 0 || top_k <= 0)
return;
97 if (top_k > key_count) top_k = key_count;
99 for (
int t = 0; t < tokens; ++t) {
100 for (
int h = 0; h < heads; ++h) {
101 const float *row = scores + ((size_t)t * (
size_t)heads + (size_t)h) * (size_t)key_count;
102 int *idx = indices + ((size_t)t * (
size_t)heads + (size_t)h) * (size_t)top_k;
103 float *w = weights + ((size_t)t * (
size_t)heads + (size_t)h) * (size_t)top_k;
105 for (
int k = 0; k < top_k; ++k) {
110 for (
int j = 0; j < key_count; ++j) {
111 const float v = row[j];
113 for (
int k = 0; k < top_k; ++k) {
114 if (idx[k] < 0 || v > w[k] || (v == w[k] && j < idx[k])) {
120 for (
int k = top_k - 1; k > pos; --k) {
130 for (
int k = 1; k < top_k; ++k)
if (w[k] > max_v) max_v = w[k];
132 for (
int k = 0; k < top_k; ++k) {
133 w[k] = expf(w[k] - max_v);
137 const float inv = 1.0f / sum;
138 for (
int k = 0; k < top_k; ++k) w[k] *= inv;
146 const float *weights,
147 const float *d_weights,
150 int n_experts_or_keys,
154 const float *weights,
155 const float *d_weights,
162 if (!indices || !weights || !d_weights || !d_scores ||
163 tokens <= 0 || heads <= 0 || key_count <= 0 || top_k <= 0)
return;
177 return (
size_t)t * (size_t)dim + (
size_t)d;
182 return ((
size_t)t * (
size_t)heads + (
size_t)h) * (size_t)dim + (
size_t)d;
186 const float *kv_b_proj,
195 if (!compressed_kv || !kv_b_proj || !k_nope || !value ||
196 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 || v_dim <= 0) {
200 const int out_per_head = qk_nope_dim + v_dim;
201 for (
int t = 0; t < tokens; ++t) {
202 for (
int h = 0; h < heads; ++h) {
203 for (
int d = 0; d < qk_nope_dim; ++d) {
204 const int out_col = h * out_per_head + d;
206 for (
int r = 0; r < kv_lora_rank; ++r) {
207 acc += kv_b_proj[(size_t)out_col * (
size_t)kv_lora_rank + (size_t)r] *
212 for (
int d = 0; d < v_dim; ++d) {
213 const int out_col = h * out_per_head + qk_nope_dim + d;
215 for (
int r = 0; r < kv_lora_rank; ++r) {
216 acc += kv_b_proj[(size_t)out_col * (
size_t)kv_lora_rank + (size_t)r] *
226 const uint16_t *kv_b_proj,
237 if (!compressed_kv || !kv_b_proj || !k_nope || !value ||
238 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 || v_dim <= 0 ||
239 token_begin < 0 || token_begin >= token_end || token_end > tokens) {
243 const int out_per_head = qk_nope_dim + v_dim;
244 for (
int t = token_begin; t < token_end; ++t) {
245 for (
int h = 0; h < heads; ++h) {
246 for (
int d = 0; d < qk_nope_dim; ++d) {
247 const int out_col = h * out_per_head + d;
249 for (
int r = 0; r < kv_lora_rank; ++r) {
250 acc +=
bf16_to_float(kv_b_proj[(
size_t)out_col * (
size_t)kv_lora_rank + (
size_t)r]) *
256 for (
int d = 0; d < v_dim; ++d) {
257 const int out_col = h * out_per_head + qk_nope_dim + d;
259 for (
int r = 0; r < kv_lora_rank; ++r) {
260 acc +=
bf16_to_float(kv_b_proj[(
size_t)out_col * (
size_t)kv_lora_rank + (
size_t)r]) *
271 const uint16_t *kv_b_proj,
280 if (tokens <= 0)
return;
282 compressed_kv, kv_b_proj, k_nope, value, tokens, heads,
283 kv_lora_rank, qk_nope_dim, v_dim, 0, tokens);
287 const float *compressed_kv;
288 const uint16_t *kv_b_proj;
296} ds_mla_kv_decompress_bf16_args_t;
300 const ds_mla_kv_decompress_bf16_args_t *args =
301 (
const ds_mla_kv_decompress_bf16_args_t *)opaque;
303 args->compressed_kv, args->kv_b_proj, args->k_nope, args->value,
304 args->tokens, args->heads, args->kv_lora_rank, args->qk_nope_dim,
305 args->v_dim, begin,
end);
309 const float *compressed_kv,
310 const uint16_t *kv_b_proj,
320 const char *disabled = getenv(
"CK_DISABLE_MLA_PARALLEL_PREFILL");
321 if ((disabled && disabled[0] && strcmp(disabled,
"0") != 0) ||
324 compressed_kv, kv_b_proj, k_nope, value, tokens, heads,
325 kv_lora_rank, qk_nope_dim, v_dim);
328 ds_mla_kv_decompress_bf16_args_t args = {
329 .compressed_kv = compressed_kv,
330 .kv_b_proj = kv_b_proj,
335 .kv_lora_rank = kv_lora_rank,
336 .qk_nope_dim = qk_nope_dim,
340 if (active > tokens) active = tokens;
341 int grain = tokens / (active * 4);
342 if (grain < 1) grain = 1;
352 const float *cos_row,
353 const float *sin_row,
356 const int half = dim / 2;
357 for (
int i = 0; i < half; ++i) {
358 const float x_first = src[2 * i];
359 const float x_second = src[2 * i + 1];
360 const float c = cos_row[i];
361 const float s = sin_row[i];
362 dst[i] = x_first * c - x_second * s;
363 dst[half + i] = x_second * c + x_first * s;
380 if (!q_nope || !q_pe || !k_nope || !k_pe || !cos || !sin || !query || !key ||
381 tokens <= 0 || heads <= 0 || qk_nope_dim <= 0 || qk_rope_dim <= 0 || (qk_rope_dim % 2) != 0) {
385 const int q_head_dim = qk_nope_dim + qk_rope_dim;
386 for (
int t = 0; t < tokens; ++t) {
387 const float *cos_row = cos + (size_t)t * (
size_t)(qk_rope_dim / 2);
388 const float *sin_row = sin + (size_t)t * (
size_t)(qk_rope_dim / 2);
389 for (
int h = 0; h < heads; ++h) {
390 float *q_out = query +
ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
392 const float *qn = q_nope +
ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
393 const float *qp = q_pe +
ds_mla_thd_idx(t, h, 0, heads, qk_rope_dim);
394 const float *kn = k_nope +
ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
396 for (
int d = 0; d < qk_nope_dim; ++d) {
408 const float *kv_a_packed,
419 if (!q_packed || !k_nope || !kv_a_packed || !cos || !sin || !query || !key ||
420 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 ||
421 qk_rope_dim <= 0 || qk_rope_dim > 256 || (qk_rope_dim % 2) != 0) {
425 const int q_head_dim = qk_nope_dim + qk_rope_dim;
426 const int kv_a_dim = kv_lora_rank + qk_rope_dim;
427 const int half = qk_rope_dim / 2;
428 if (qk_rope_dim > 256) {
431 for (
int t = 0; t < tokens; ++t) {
432 const float *cos_row = cos + (size_t)t * (
size_t)half;
433 const float *sin_row = sin + (size_t)t * (
size_t)half;
434 const float *kp = kv_a_packed + (size_t)t * (
size_t)kv_a_dim + (size_t)kv_lora_rank;
435 for (
int h = 0; h < heads; ++h) {
436 const float *q_in = q_packed +
ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
437 const float *kn = k_nope +
ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
438 float *q_out = query +
ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
441 for (
int d = 0; d < qk_nope_dim; ++d) {
446 const float *qp = q_in + qk_nope_dim;
448 if (qk_rope_dim > (
int)(
sizeof(q_pe_tmp) /
sizeof(q_pe_tmp[0]))) {
451 for (
int i = 0; i < qk_rope_dim; ++i) q_pe_tmp[i] = qp[i];
452 for (
int i = 0; i < half; ++i) {
453 const float q_first = q_pe_tmp[2 * i];
454 const float q_second = q_pe_tmp[2 * i + 1];
455 const float k_first = kp[2 * i];
456 const float k_second = kp[2 * i + 1];
457 const float c = cos_row[i];
458 const float ss = sin_row[i];
459 q_out[qk_nope_dim + i] = q_first * c - q_second * ss;
460 q_out[qk_nope_dim + half + i] = q_second * c + q_first * ss;
461 k_out[qk_nope_dim + i] = k_first * c - k_second * ss;
462 k_out[qk_nope_dim + half + i] = k_second * c + k_first * ss;
474 const float *q_packed,
476 const float *kv_a_packed,
487 if (!q_packed || !k_nope || !kv_a_packed || !cos || !sin || !query || !key ||
488 tokens <= 0 || heads <= 0 || kv_lora_rank <= 0 || qk_nope_dim <= 0 ||
489 qk_rope_dim <= 0 || (qk_rope_dim % 2) != 0) {
493 const int q_head_dim = qk_nope_dim + qk_rope_dim;
494 const int kv_a_dim = kv_lora_rank + qk_rope_dim;
495 const int half = qk_rope_dim / 2;
496 for (
int t = 0; t < tokens; ++t) {
497 const float *cos_row = cos + (size_t)t * (
size_t)half;
498 const float *sin_row = sin + (size_t)t * (
size_t)half;
499 const float *kp = kv_a_packed + (size_t)t * (
size_t)kv_a_dim + (size_t)kv_lora_rank;
500 for (
int h = 0; h < heads; ++h) {
501 const float *q_in = q_packed +
ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
502 const float *kn = k_nope +
ds_mla_thd_idx(t, h, 0, heads, qk_nope_dim);
503 float *q_out = query +
ds_mla_thd_idx(t, h, 0, heads, q_head_dim);
506 for (
int d = 0; d < qk_nope_dim; ++d) {
512 for (
int i = 0; i < qk_rope_dim; ++i) {
515 for (
int i = 0; i < half; ++i) {
516 const float q_first = q_pe_tmp[2 * i];
517 const float q_second = q_pe_tmp[2 * i + 1];
543 return ((
size_t)
token * (
size_t)heads + (
size_t)head) * (size_t)dim + (
size_t)d;
550 for (
int i = 1; i < n; ++i)
if (x[i] > max_v) max_v = x[i];
552 for (
int i = 0; i < n; ++i) {
553 x[i] = expf(x[i] - max_v);
557 const float inv = 1.0f / sum;
558 for (
int i = 0; i < n; ++i) x[i] *= inv;
575 if (!q || !k || !v || !indices || !out || query_tokens <= 0 || key_tokens <= 0 ||
576 heads <= 0 || dim <= 0 || top_k <= 0)
return;
578 for (
int tq = 0; tq < query_tokens; ++tq) {
579 for (
int h = 0; h < heads; ++h) {
580 float local_scores[top_k];
582 for (
int j = 0; j < top_k; ++j) {
583 const int tk = indices[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j];
584 if (tk < 0 || tk >= key_tokens) {
585 local_scores[j] = -FLT_MAX;
589 for (
int d = 0; d < dim; ++d) {
592 local_scores[j] = dot * scale;
596 float *out_row = out +
ds_qkv_idx(tq, h, 0, heads, dim);
597 for (
int d = 0; d < dim; ++d) out_row[d] = 0.0f;
600 for (
int j = 0; j < top_k; ++j) {
601 attn[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j] = 0.0f;
608 for (
int j = 0; j < top_k; ++j) {
609 const int tk = indices[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j];
610 const float a = (tk >= 0 && tk < key_tokens) ? local_scores[j] : 0.0f;
611 if (attn) attn[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j] = a;
612 if (a == 0.0f)
continue;
613 for (
int d = 0; d < dim; ++d) {
614 out_row[d] += a * v[
ds_qkv_idx(tk, h, d, heads, dim)];
637 if (!d_out || !q || !k || !v || !indices || !attn || !d_q || !d_k || !d_v ||
638 query_tokens <= 0 || key_tokens <= 0 || heads <= 0 || dim <= 0 || top_k <= 0)
return;
640 const size_t q_count = (size_t)query_tokens * (
size_t)heads * (size_t)dim;
641 const size_t kv_count = (size_t)key_tokens * (
size_t)heads * (size_t)dim;
642 for (
size_t i = 0; i < q_count; ++i) d_q[i] = 0.0f;
643 for (
size_t i = 0; i < kv_count; ++i) {
648 for (
int tq = 0; tq < query_tokens; ++tq) {
649 for (
int h = 0; h < heads; ++h) {
651 float attn_dot = 0.0f;
652 for (
int j = 0; j < top_k; ++j) {
653 const int tk = indices[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j];
655 if (tk >= 0 && tk < key_tokens) {
656 const float a = attn[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j];
657 for (
int d = 0; d < dim; ++d) {
658 const float go = d_out[
ds_qkv_idx(tq, h, d, heads, dim)];
659 da += go * v[
ds_qkv_idx(tk, h, d, heads, dim)];
660 d_v[
ds_qkv_idx(tk, h, d, heads, dim)] += a * go;
667 for (
int j = 0; j < top_k; ++j) {
668 const int tk = indices[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j];
669 if (tk < 0 || tk >= key_tokens)
continue;
670 const float a = attn[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)top_k + (
size_t)j];
671 const float d_score = a * (d_attn[j] - attn_dot);
672 for (
int d = 0; d < dim; ++d) {
673 const float qv = q[
ds_qkv_idx(tq, h, d, heads, dim)];
674 const float kv = k[
ds_qkv_idx(tk, h, d, heads, dim)];
675 d_q[
ds_qkv_idx(tq, h, d, heads, dim)] += scale * d_score * kv;
676 d_k[
ds_qkv_idx(tk, h, d, heads, dim)] += scale * d_score * qv;
699 query_tokens, key_tokens, heads, dim, top_k, scale);
703 int dense_indices[query_tokens * heads * key_tokens];
704 for (
int tq = 0; tq < query_tokens; ++tq) {
705 for (
int h = 0; h < heads; ++h) {
706 for (
int tk = 0; tk < key_tokens; ++tk) {
707 dense_indices[((size_t)tq * (
size_t)heads + (size_t)h) * (size_t)key_tokens + (
size_t)tk] = tk;
712 query_tokens, key_tokens, heads, dim, key_tokens, scale);
731 for (
int query = query_begin; query < query_end; query += query_step) {
732 const int t = query / num_heads;
733 const int h = query - t * num_heads;
734 const int kv_h = (int)((
long long)h * (
long long)num_kv_heads / (
long long)num_heads);
735 const float *q_vec = q +
ds_mla_thd_idx(t, h, 0, num_heads, qk_head_dim);
737 float max_score = -FLT_MAX;
738 for (
int j = 0; j <= t; ++j) {
739 const float *k_vec = k +
ds_mla_thd_idx(j, kv_h, 0, num_kv_heads, qk_head_dim);
741 for (
int d = 0; d < qk_head_dim; ++d) {
742 dot += q_vec[d] * k_vec[d];
744 const float score = dot * scale;
750 for (
int j = 0; j <= t; ++j) {
751 const float e = expf(scores[j] - max_score);
755 const float inv_sum = sum > 0.0f ? (1.0f / sum) : 0.0f;
756 float *out = output + ((size_t)t * (
size_t)num_heads + (size_t)h) * (size_t)v_head_dim;
757 for (
int d = 0; d < v_head_dim; ++d) out[d] = 0.0f;
758 for (
int j = 0; j <= t; ++j) {
759 const float weight = scores[j] * inv_sum;
760 const float *v_vec = v +
ds_mla_thd_idx(j, kv_h, 0, num_kv_heads, v_head_dim);
761 for (
int d = 0; d < v_head_dim; ++d) {
762 out[d] += weight * v_vec[d];
781 if (!q || !k || !v || !output || num_heads <= 0 || num_kv_heads <= 0 ||
782 num_tokens <= 0 || qk_head_dim <= 0 || v_head_dim <= 0 ||
783 num_tokens > INT_MAX / num_heads ||
784 !isfinite(scale) || scale <= 0.0f) {
787 if ((
size_t)num_tokens > SIZE_MAX /
sizeof(
float) || !scores ||
788 scores_bytes < (
size_t)num_tokens *
sizeof(
float)) {
793 q, k, v, output, num_heads, num_kv_heads, num_tokens,
794 qk_head_dim, v_head_dim, scale, scores,
795 0, num_tokens * num_heads, 1);
811} ds_mla_attention_f32_args_t;
815 ds_mla_attention_f32_args_t *args =
816 (ds_mla_attention_f32_args_t *)opaque;
817 float *thread_scores = args->scores + (size_t)ith * (
size_t)args->num_tokens;
823 const int token = atomic_fetch_add_explicit(
826 memory_order_relaxed);
827 if (
token >= args->num_tokens)
break;
829 args->q, args->k, args->v, args->output,
830 args->num_heads, args->num_kv_heads, args->num_tokens,
831 args->qk_head_dim, args->v_head_dim, args->scale,
833 token * args->num_heads,
834 (
token + 1) * args->num_heads,
854 const char *disabled = getenv(
"CK_DISABLE_MLA_PARALLEL_PREFILL");
856 if (active > num_heads) active = num_heads;
857 const size_t score_row_bytes =
858 num_tokens > 0 ? (size_t)num_tokens *
sizeof(
float) : 0;
859 if ((disabled && disabled[0] && strcmp(disabled,
"0") != 0) ||
860 !pool || active <= 1 || num_tokens <= 0 || num_heads <= 0 ||
861 num_tokens > INT_MAX / num_heads ||
862 score_row_bytes == 0 || (
size_t)active > SIZE_MAX / score_row_bytes ||
863 scores_bytes < (
size_t)active * score_row_bytes) {
865 q, k, v, output, num_heads, num_kv_heads, num_tokens,
866 qk_head_dim, v_head_dim, scale, scores, scores_bytes);
869 ds_mla_attention_f32_args_t args = {
870 .q = q, .k = k, .v = v, .output = output,
871 .num_heads = num_heads, .num_kv_heads = num_kv_heads,
872 .num_tokens = num_tokens, .qk_head_dim = qk_head_dim,
873 .v_head_dim = v_head_dim, .scale = scale, .scores = scores,
875 atomic_init(&args.next_token, 0);
889 if (num_tokens <= 0 || (
size_t)num_tokens > SIZE_MAX /
sizeof(
float))
return;
890 const size_t scores_bytes = (size_t)num_tokens *
sizeof(
float);
891 float *scores = (
float *)malloc(scores_bytes);
894 q, k, v, output, num_heads, num_kv_heads, num_tokens,
895 qk_head_dim, v_head_dim, 1.0f / sqrtf((
float)qk_head_dim),
896 scores, scores_bytes);
911 if (!k_cache || !v_cache || !k || !v || num_tokens <= 0 ||
912 num_kv_heads <= 0 || qk_head_dim <= 0 || v_head_dim <= 0 ||
913 max_seq_len <= 0 || cache_stride <= 0) {
916 if (qk_head_dim > cache_stride || v_head_dim > cache_stride) {
919 if (num_tokens > max_seq_len) {
920 num_tokens = max_seq_len;
923 for (
int t = 0; t < num_tokens; ++t) {
924 for (
int h = 0; h < num_kv_heads; ++h) {
925 const float *k_src = k + ((size_t)t * (
size_t)num_kv_heads + (size_t)h) * (size_t)qk_head_dim;
926 const float *v_src = v + ((size_t)t * (
size_t)num_kv_heads + (size_t)h) * (size_t)v_head_dim;
927 float *k_dst = k_cache + ((size_t)h * (
size_t)max_seq_len + (size_t)t) * (size_t)cache_stride;
928 float *v_dst = v_cache + ((size_t)h * (
size_t)max_seq_len + (size_t)t) * (size_t)cache_stride;
929 for (
int d = 0; d < qk_head_dim; ++d) k_dst[d] = k_src[d];
930 for (
int d = qk_head_dim; d < cache_stride; ++d) k_dst[d] = 0.0f;
931 for (
int d = 0; d < v_head_dim; ++d) v_dst[d] = v_src[d];
932 for (
int d = v_head_dim; d < cache_stride; ++d) v_dst[d] = 0.0f;
948 if (!k_cache || !v_cache || !k || !v || pos < 0 ||
949 num_kv_heads <= 0 || qk_head_dim <= 0 || v_head_dim <= 0 ||
950 max_seq_len <= 0 || cache_stride <= 0) {
953 if (pos >= max_seq_len || qk_head_dim > cache_stride || v_head_dim > cache_stride) {
957 for (
int h = 0; h < num_kv_heads; ++h) {
958 const float *k_src = k + ((size_t)h * (
size_t)qk_head_dim);
959 const float *v_src = v + ((size_t)h * (
size_t)v_head_dim);
960 float *k_dst = k_cache + ((size_t)h * (
size_t)max_seq_len + (size_t)pos) * (size_t)cache_stride;
961 float *v_dst = v_cache + ((size_t)h * (
size_t)max_seq_len + (size_t)pos) * (size_t)cache_stride;
963 for (
int d = 0; d < qk_head_dim; ++d) {
966 for (
int d = qk_head_dim; d < cache_stride; ++d) {
969 for (
int d = 0; d < v_head_dim; ++d) {
972 for (
int d = v_head_dim; d < cache_stride; ++d) {
979 const float *k_cache,
980 const float *v_cache,
993 if (!q || !k_cache || !v_cache || !output || num_heads <= 0 ||
994 num_kv_heads <= 0 || cache_len <= 0 || qk_head_dim <= 0 ||
995 v_head_dim <= 0 || max_seq_len <= 0 || cache_stride <= 0 ||
996 !isfinite(scale) || scale <= 0.0f) {
999 if (qk_head_dim > cache_stride || v_head_dim > cache_stride) {
1002 if ((
size_t)cache_len > SIZE_MAX /
sizeof(
float) || !scores ||
1003 scores_bytes < (
size_t)cache_len *
sizeof(
float)) {
1007 for (
int h = 0; h < num_heads; ++h) {
1008 const int kv_h = (int)((
long long)h * (
long long)num_kv_heads / (
long long)num_heads);
1009 const float *q_vec = q + (size_t)h * (
size_t)qk_head_dim;
1011 float max_score = -FLT_MAX;
1012 for (
int j = 0; j < cache_len; ++j) {
1013 const float *k_vec = k_cache + ((size_t)kv_h * (
size_t)max_seq_len + (size_t)j) * (size_t)cache_stride;
1015 for (
int d = 0; d < qk_head_dim; ++d) {
1016 dot += q_vec[d] * k_vec[d];
1018 const float score = dot * scale;
1024 for (
int j = 0; j < cache_len; ++j) {
1025 const float e = expf(scores[j] - max_score);
1030 const float inv_sum = sum > 0.0f ? (1.0f / sum) : 0.0f;
1031 float *out = output + (size_t)h * (
size_t)v_head_dim;
1032 for (
int d = 0; d < v_head_dim; ++d) out[d] = 0.0f;
1033 for (
int j = 0; j < cache_len; ++j) {
1034 const float w = scores[j] * inv_sum;
1035 const float *v_vec = v_cache + ((size_t)kv_h * (
size_t)max_seq_len + (size_t)j) * (size_t)cache_stride;
1036 for (
int d = 0; d < v_head_dim; ++d) {
1037 out[d] += w * v_vec[d];
1045 const float *k_cache,
1046 const float *v_cache,
1056 if (cache_len <= 0 || (
size_t)cache_len > SIZE_MAX /
sizeof(
float))
return;
1057 const size_t scores_bytes = (size_t)cache_len *
sizeof(
float);
1058 float *scores = (
float *)malloc(scores_bytes);
1059 if (!scores)
return;
1061 q, k_cache, v_cache, output, num_heads, num_kv_heads, cache_len,
1062 qk_head_dim, v_head_dim, max_seq_len, cache_stride,
1063 1.0f / sqrtf((
float)qk_head_dim), scores, scores_bytes);
static uint16_t float_to_bf16(float f)
static float bf16_to_float(uint16_t v)
Persistent pthread thread pool for CK-Engine inference.
void ck_threadpool_parallel_for_n(ck_threadpool_t *pool, int active_threads, int begin, int end, int grain_size, ck_range_fn_t fn, void *args)
void ck_threadpool_dispatch_n(ck_threadpool_t *pool, int active_threads, ck_work_fn_t fn, void *args)
ck_threadpool_t * ck_threadpool_global(void)
int ck_threadpool_n_threads(const ck_threadpool_t *pool)
static size_t ds_mix_idx(int t, int out_s, int in_s, int n_streams)
void deepseek_mla_partial_rope_concat_f32(const float *q_nope, const float *q_pe, const float *k_nope, const float *k_pe, const float *cos, const float *sin, float *query, float *key, int tokens, int heads, int qk_nope_dim, int qk_rope_dim)
static void ds_mla_attention_f32_work(int ith, int nth, void *opaque)
void deepseek_mla_attention_f32_workspace(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)
static size_t ds_mhc_idx(int t, int s, int d, int n_streams, int dim)
void deepseek_csa_attention_f32(const float *q, const float *k, const float *v, const int *indices, float *out, float *attn, int query_tokens, int key_tokens, int heads, int dim, int top_k, float scale)
void topk_softmax_backward_f32(const int *indices, const float *weights, const float *d_weights, float *d_scores, int num_tokens, int n_experts_or_keys, int k)
Backward for hard top-k followed by softmax over selected values.
void deepseek_mla_attention_decode_f32_workspace(const float *q, const float *k_cache, const float *v_cache, float *output, int num_heads, int num_kv_heads, int cache_len, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride, float scale, float *scores, size_t scores_bytes)
void deepseek_mhc_mix_f32(const float *streams, const float *mix, float *out, int tokens, int n_streams, int dim)
void deepseek_mla_kv_decompress_bf16(const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim)
void deepseek_mla_kv_decompress_f32(const float *compressed_kv, const float *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim)
static float ds_mla_bf16_round(float value)
void deepseek_mla_kv_decompress_bf16_token_range(const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim, int token_begin, int token_end)
static size_t ds_qkv_idx(int token, int head, int d, int heads, int dim)
static size_t ds_mla_thd_idx(int t, int h, int d, int heads, int dim)
static void ds_mla_attention_f32_query_range(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, int query_begin, int query_end, int query_step)
void deepseek_mla_attention_f32_parallel_dispatch(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim, float scale, float *scores, size_t scores_bytes)
static void ds_mla_kv_decompress_bf16_rows(int begin, int end, void *opaque)
void deepseek_csa_attention_backward_f32(const float *d_out, const float *q, const float *k, const float *v, const int *indices, const float *attn, float *d_q, float *d_k, float *d_v, int query_tokens, int key_tokens, int heads, int dim, int top_k, float scale)
void deepseek_mla_kv_cache_batch_store_f32(float *k_cache, float *v_cache, const float *k, const float *v, int num_tokens, int num_kv_heads, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride)
static void ds_softmax(float *x, int n)
static size_t ds_mla_tok_idx(int t, int d, int dim)
void deepseek_mla_attention_f32(const float *q, const float *k, const float *v, float *output, int num_heads, int num_kv_heads, int num_tokens, int qk_head_dim, int v_head_dim)
void deepseek_mhc_mix_backward_f32(const float *d_out, const float *streams, const float *mix, float *d_streams, float *d_mix, int tokens, int n_streams, int dim)
void deepseek_dsa_topk_softmax_f32(const float *scores, int *indices, float *weights, int tokens, int heads, int key_count, int top_k)
void deepseek_dsa_topk_softmax_backward_f32(const int *indices, const float *weights, const float *d_weights, float *d_scores, int tokens, int heads, int key_count, int top_k)
void deepseek_mla_kv_decompress_bf16_parallel_dispatch(const float *compressed_kv, const uint16_t *kv_b_proj, float *k_nope, float *value, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int v_dim)
void deepseek_mla_partial_rope_concat_packed_f32(const float *q_packed, const float *k_nope, const float *kv_a_packed, const float *cos, const float *sin, float *query, float *key, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int qk_rope_dim)
void deepseek_mla_attention_decode_f32(const float *q, const float *k_cache, const float *v_cache, float *output, int num_heads, int num_kv_heads, int cache_len, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride)
void deepseek_hybrid_attention_f32(const float *q, const float *k, const float *v, const int *indices, float *out, float *attn, int query_tokens, int key_tokens, int heads, int dim, int top_k, float scale, int mode)
void deepseek_mla_kv_cache_store_f32(float *k_cache, float *v_cache, const float *k, const float *v, int pos, int num_kv_heads, int qk_head_dim, int v_head_dim, int max_seq_len, int cache_stride)
void deepseek_mla_partial_rope_concat_packed_bf16_storage(const float *q_packed, const float *k_nope, const float *kv_a_packed, const float *cos, const float *sin, float *query, float *key, int tokens, int heads, int kv_lora_rank, int qk_nope_dim, int qk_rope_dim)
static void ds_mla_apply_kimi_rope(const float *src, float *dst, const float *cos_row, const float *sin_row, int dim)