|
7 | 7 |
|
8 | 8 | #include "llama-kv-cache.h" |
9 | 9 | #include "llama-kv-cache-iswa.h" |
| 10 | +#include "llama-kv-cache-dsa.h" |
10 | 11 | #include "llama-memory-hybrid.h" |
11 | 12 | #include "llama-memory-hybrid-iswa.h" |
12 | 13 | #include "llama-memory-recurrent.h" |
@@ -531,6 +532,34 @@ bool llm_graph_input_attn_k::can_reuse(const llm_graph_params & params) { |
531 | 532 | return res; |
532 | 533 | } |
533 | 534 |
|
| 535 | +void llm_graph_input_attn_k_dsa::set_input(const llama_ubatch * ubatch) { |
| 536 | + mctx->get_mla()->set_input_k_idxs(self_k_idxs_mla, ubatch); |
| 537 | + |
| 538 | + mctx->get_mla()->set_input_kq_mask(self_kq_mask_mla, ubatch, cparams.causal_attn); |
| 539 | + |
| 540 | + mctx->get_lid()->set_input_k_idxs(self_k_idxs_lid, ubatch); |
| 541 | + |
| 542 | + mctx->get_lid()->set_input_kq_mask(self_kq_mask_lid, ubatch, cparams.causal_attn); |
| 543 | + |
| 544 | + mctx->get_lid()->set_input_k_rot(self_k_rot_lid); |
| 545 | +} |
| 546 | + |
| 547 | +bool llm_graph_input_attn_k_dsa::can_reuse(const llm_graph_params & params) { |
| 548 | + const auto * mctx = static_cast<const llama_kv_cache_dsa_context *>(params.mctx); |
| 549 | + |
| 550 | + this->mctx = mctx; |
| 551 | + |
| 552 | + bool res = true; |
| 553 | + |
| 554 | + res &= self_k_idxs_mla->ne[0] == params.ubatch.n_tokens; |
| 555 | + res &= self_k_idxs_lid->ne[0] == params.ubatch.n_tokens; |
| 556 | + |
| 557 | + res &= can_reuse_kq_mask(self_kq_mask_mla, mctx->get_mla(), params.ubatch, params.cparams); |
| 558 | + res &= can_reuse_kq_mask(self_kq_mask_lid, mctx->get_lid(), params.ubatch, params.cparams); |
| 559 | + |
| 560 | + return res; |
| 561 | +} |
| 562 | + |
534 | 563 | void llm_graph_input_attn_kv_iswa::set_input(const llama_ubatch * ubatch) { |
535 | 564 | // base tensors may not be allocated if there are no non-SWA attention layers |
536 | 565 | if (self_k_idxs && self_k_idxs->buffer) { |
@@ -2396,6 +2425,82 @@ ggml_tensor * llm_graph_context::build_attn( |
2396 | 2425 | return cur; |
2397 | 2426 | } |
2398 | 2427 |
|
| 2428 | +ggml_tensor * llm_graph_context::build_attn( |
| 2429 | + llm_graph_input_attn_k_dsa * inp, |
| 2430 | + ggml_tensor * wo, |
| 2431 | + ggml_tensor * wo_b, |
| 2432 | + ggml_tensor * wo_s, |
| 2433 | + ggml_tensor * q_cur, |
| 2434 | + ggml_tensor * k_cur, |
| 2435 | + ggml_tensor * v_cur, |
| 2436 | + ggml_tensor * kq_b, |
| 2437 | + ggml_tensor * sinks, |
| 2438 | + ggml_tensor * v_mla, |
| 2439 | + ggml_tensor * top_k, |
| 2440 | + float kq_scale, |
| 2441 | + int il) const { |
| 2442 | + // these nodes are added to the graph together so that they are not reordered |
| 2443 | + // by doing so, the number of splits in the graph is reduced |
| 2444 | + // expand k later to enable rope fusion which directly writes into k-v cache |
| 2445 | + ggml_build_forward_expand(gf, q_cur); |
| 2446 | + ggml_build_forward_expand(gf, v_cur); |
| 2447 | + ggml_build_forward_expand(gf, k_cur); |
| 2448 | + |
| 2449 | + const auto * mctx_cur = inp->mctx->get_mla(); |
| 2450 | + |
| 2451 | + // store to KV cache |
| 2452 | + { |
| 2453 | + const auto & k_idxs = inp->get_k_idxs_mla(); |
| 2454 | + |
| 2455 | + ggml_build_forward_expand(gf, mctx_cur->cpy_k(ctx0, k_cur, k_idxs, il)); |
| 2456 | + } |
| 2457 | + |
| 2458 | + const auto & kq_mask = inp->get_kq_mask_mla(); |
| 2459 | + |
| 2460 | + // prepare new kq mask - starts filled with -INFINITY |
| 2461 | + ggml_tensor * kq_mask_all = ggml_fill(ctx0, kq_mask, -INFINITY); |
| 2462 | + |
| 2463 | + // reshape KQ mask into tensor with rows of size 1: |
| 2464 | + // [n_kv, n_batch, 1, n_stream] -> [1, n_kv, n_batch, n_stream] |
| 2465 | + kq_mask_all = ggml_view_4d(ctx0, kq_mask_all, 1, kq_mask_all->ne[0], kq_mask_all->ne[1], kq_mask_all->ne[3], kq_mask_all->nb[0], kq_mask_all->nb[1], kq_mask_all->nb[2], 0); |
| 2466 | + |
| 2467 | + // reshape top_k indices: [n_top_k, n_batch, 1, n_stream] -> [n_top_k, n_batch, n_stream, 1] |
| 2468 | + ggml_tensor * top_k_3d = ggml_view_4d(ctx0, top_k, top_k->ne[0], top_k->ne[1], top_k->ne[3], 1, top_k->nb[1], top_k->nb[2], top_k->ne[3]*top_k->nb[3], 0); |
| 2469 | + |
| 2470 | + // prepare zero-filled tensor with rows of size 1: [1, n_top_k, n_batch, n_stream] |
| 2471 | + // this will be our source of zero values for unmasking top k mask elements |
| 2472 | + ggml_tensor * zeros = ggml_new_tensor_4d(ctx0, GGML_TYPE_F32, 1, top_k_3d->ne[0], top_k_3d->ne[1], top_k_3d->ne[2]); |
| 2473 | + zeros = ggml_fill(ctx0, zeros, 0.0f); |
| 2474 | + |
| 2475 | + // modify KQ mask by unmasking elements that are in top_k indices |
| 2476 | + // ggml_set_rows([1, n_kv, n_batch, n_stream], [1, n_top_k, n_batch, n_stream], [n_top_k, n_batch, n_stream, 1]) |
| 2477 | + ggml_tensor * kq_mask_top_k = ggml_set_rows(ctx0, kq_mask_all, zeros, top_k_3d); |
| 2478 | + |
| 2479 | + // reshape to restore the original shape of KQ mask: |
| 2480 | + // [1, n_kv, n_batch, n_stream] -> [n_kv, n_batch, 1, n_stream] |
| 2481 | + kq_mask_top_k = ggml_view_4d(ctx0, kq_mask_top_k, kq_mask_top_k->ne[1], kq_mask_top_k->ne[2], 1, kq_mask_top_k->ne[3], kq_mask_top_k->nb[2], kq_mask_top_k->nb[3], kq_mask_top_k->nb[3], 0); |
| 2482 | + |
| 2483 | + // combine with the original kq mask |
| 2484 | + kq_mask_top_k = ggml_add(ctx0, kq_mask_top_k, kq_mask); |
| 2485 | + |
| 2486 | + ggml_tensor * q = q_cur; |
| 2487 | + ggml_tensor * k = mctx_cur->get_k(ctx0, il); |
| 2488 | + ggml_tensor * v = ggml_view_4d(ctx0, k, v_cur->ne[0], k->ne[1], k->ne[2], k->ne[3], k->nb[1], k->nb[2], k->nb[3], 0); |
| 2489 | + |
| 2490 | + ggml_tensor * cur = build_attn_mha(q, k, v, kq_b, kq_mask_top_k, sinks, v_mla, kq_scale, il); |
| 2491 | + cb(cur, "kqv_out", il); |
| 2492 | + |
| 2493 | + if (wo) { |
| 2494 | + cur = build_lora_mm(wo, cur, wo_s); |
| 2495 | + } |
| 2496 | + |
| 2497 | + if (wo_b) { |
| 2498 | + cur = ggml_add(ctx0, cur, wo_b); |
| 2499 | + } |
| 2500 | + |
| 2501 | + return cur; |
| 2502 | +} |
| 2503 | + |
2399 | 2504 | ggml_tensor * llm_graph_context::build_attn( |
2400 | 2505 | llm_graph_input_attn_kv_iswa * inp, |
2401 | 2506 | ggml_tensor * wo, |
@@ -2542,6 +2647,30 @@ ggml_tensor * llm_graph_context::build_attn( |
2542 | 2647 | return cur; |
2543 | 2648 | } |
2544 | 2649 |
|
| 2650 | +llm_graph_input_attn_k_dsa * llm_graph_context::build_attn_inp_k_dsa() const { |
| 2651 | + const auto * mctx_cur = static_cast<const llama_kv_cache_dsa_context *>(mctx); |
| 2652 | + |
| 2653 | + auto inp = std::make_unique<llm_graph_input_attn_k_dsa>(hparams, cparams, mctx_cur); |
| 2654 | + |
| 2655 | + { |
| 2656 | + inp->self_k_idxs_mla = mctx_cur->get_mla()->build_input_k_idxs(ctx0, ubatch); |
| 2657 | + |
| 2658 | + inp->self_kq_mask_mla = build_attn_inp_kq_mask(ctx0, mctx_cur->get_mla(), ubatch, cparams); |
| 2659 | + inp->self_kq_mask_mla_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask_mla, GGML_TYPE_F16) : inp->self_kq_mask_mla; |
| 2660 | + } |
| 2661 | + |
| 2662 | + { |
| 2663 | + inp->self_k_idxs_lid = mctx_cur->get_lid()->build_input_k_idxs(ctx0, ubatch); |
| 2664 | + |
| 2665 | + inp->self_kq_mask_lid = build_attn_inp_kq_mask(ctx0, mctx_cur->get_lid(), ubatch, cparams); |
| 2666 | + inp->self_kq_mask_lid_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask_lid, GGML_TYPE_F16) : inp->self_kq_mask_lid; |
| 2667 | + |
| 2668 | + inp->self_k_rot_lid = mctx_cur->get_lid()->build_input_k_rot(ctx0); |
| 2669 | + } |
| 2670 | + |
| 2671 | + return (llm_graph_input_attn_k_dsa *) res->add_input(std::move(inp)); |
| 2672 | +} |
| 2673 | + |
2545 | 2674 | // TODO: maybe separate the inner implementation into a separate function |
2546 | 2675 | // like with the non-sliding window equivalent |
2547 | 2676 | // once sliding-window hybrid caches are a thing. |
|
0 commit comments