Skip to content

Commit 744c0c7

Browse files
authored
llama : rotate activations for better quantization (ggml-org#21038)
* llama : rotate activations for better quantization * cont : rotate V more + refactor * cont : rotate caches separately + support non-power-of-2 head sizes * cont : simplify * cont : add reference for V rotation * cont : refactor * cont : support context shift * cont : consolidate * cont : dedup + allow different types for the rotation matrix * cont : add env variable to disable rotation * cont : simplify attn rot kv cache logic + rename env * cont : pre-compute the Hadamard matrices
1 parent 0356e33 commit 744c0c7

4 files changed

Lines changed: 337 additions & 26 deletions

File tree

src/llama-graph.cpp

Lines changed: 94 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
// dedup helpers
2121

22-
static ggml_tensor * build_kq_mask(
22+
static ggml_tensor * build_attn_inp_kq_mask(
2323
ggml_context * ctx,
2424
const llama_kv_cache_context * mctx,
2525
const llama_ubatch & ubatch,
@@ -28,7 +28,11 @@ static ggml_tensor * build_kq_mask(
2828
const auto n_tokens = ubatch.n_tokens;
2929
const auto n_stream = cparams.kv_unified ? 1 : ubatch.n_seqs_unq;
3030

31-
return ggml_new_tensor_4d(ctx, GGML_TYPE_F32, n_kv, n_tokens/n_stream, 1, n_stream);
31+
ggml_tensor * res = ggml_new_tensor_4d(ctx, GGML_TYPE_F32, n_kv, n_tokens/n_stream, 1, n_stream);
32+
ggml_set_input(res);
33+
ggml_set_name(res, "attn_inp_kq_mask");
34+
35+
return res;
3236
}
3337

3438
static bool can_reuse_kq_mask(
@@ -52,6 +56,21 @@ static bool can_reuse_kq_mask(
5256

5357
// impl
5458

59+
static ggml_tensor * ggml_mul_mat_aux(
60+
ggml_context * ctx,
61+
ggml_tensor * cur,
62+
ggml_tensor * rot) {
63+
const auto n = rot->ne[0];
64+
65+
ggml_tensor * res;
66+
67+
res = ggml_reshape_2d(ctx, cur, n, ggml_nelements(cur)/n);
68+
res = ggml_mul_mat (ctx, rot, res);
69+
res = ggml_reshape_4d(ctx, res, cur->ne[0], cur->ne[1], cur->ne[2], cur->ne[3]);
70+
71+
return res;
72+
}
73+
5574
void llm_graph_input_embd::set_input(const llama_ubatch * ubatch) {
5675
if (ubatch->token) {
5776
const int64_t n_tokens = ubatch->n_tokens;
@@ -429,6 +448,14 @@ void llm_graph_input_attn_kv::set_input(const llama_ubatch * ubatch) {
429448
mctx->set_input_v_idxs(self_v_idxs, ubatch);
430449

431450
mctx->set_input_kq_mask(self_kq_mask, ubatch, cparams.causal_attn);
451+
452+
if (self_k_rot) {
453+
mctx->set_input_k_rot(self_k_rot);
454+
}
455+
456+
if (self_v_rot) {
457+
mctx->set_input_v_rot(self_v_rot);
458+
}
432459
}
433460

434461
bool llm_graph_input_attn_kv::can_reuse(const llm_graph_params & params) {
@@ -476,6 +503,14 @@ void llm_graph_input_attn_kv_iswa::set_input(const llama_ubatch * ubatch) {
476503
mctx->get_swa()->set_input_v_idxs(self_v_idxs_swa, ubatch);
477504

478505
mctx->get_swa()->set_input_kq_mask(self_kq_mask_swa, ubatch, cparams.causal_attn);
506+
507+
if (self_k_rot) {
508+
mctx->get_base()->set_input_k_rot(self_k_rot);
509+
}
510+
511+
if (self_v_rot) {
512+
mctx->get_base()->set_input_v_rot(self_v_rot);
513+
}
479514
}
480515

481516
bool llm_graph_input_attn_kv_iswa::can_reuse(const llm_graph_params & params) {
@@ -532,6 +567,14 @@ void llm_graph_input_mem_hybrid::set_input(const llama_ubatch * ubatch) {
532567

533568
mctx->get_attn()->set_input_kq_mask(inp_attn->self_kq_mask, ubatch, cparams.causal_attn);
534569

570+
if (inp_attn->self_k_rot) {
571+
mctx->get_attn()->set_input_k_rot(inp_attn->self_k_rot);
572+
}
573+
574+
if (inp_attn->self_v_rot) {
575+
mctx->get_attn()->set_input_v_rot(inp_attn->self_v_rot);
576+
}
577+
535578
const int64_t n_rs = mctx->get_recr()->get_n_rs();
536579

537580
if (inp_rs->s_copy) {
@@ -630,6 +673,14 @@ void llm_graph_input_mem_hybrid_iswa::set_input(const llama_ubatch * ubatch) {
630673
attn_ctx->get_swa()->set_input_kq_mask(inp_attn->self_kq_mask_swa, ubatch, cparams.causal_attn);
631674
}
632675

676+
if (inp_attn->self_k_rot) {
677+
attn_ctx->get_base()->set_input_k_rot(inp_attn->self_k_rot);
678+
}
679+
680+
if (inp_attn->self_v_rot) {
681+
attn_ctx->get_base()->set_input_v_rot(inp_attn->self_v_rot);
682+
}
683+
633684
const int64_t n_rs = mctx->get_recr()->get_n_rs();
634685

635686
if (inp_rs->s_copy) {
@@ -2002,13 +2053,13 @@ static std::unique_ptr<llm_graph_input_attn_kv> build_attn_inp_kv_impl(
20022053
inp->self_k_idxs = mctx_cur->build_input_k_idxs(ctx0, ubatch);
20032054
inp->self_v_idxs = mctx_cur->build_input_v_idxs(ctx0, ubatch);
20042055

2005-
inp->self_kq_mask = build_kq_mask(ctx0, mctx_cur, ubatch, cparams);
2006-
2007-
ggml_set_input(inp->self_kq_mask);
2008-
2056+
inp->self_kq_mask = build_attn_inp_kq_mask(ctx0, mctx_cur, ubatch, cparams);
20092057
inp->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask, GGML_TYPE_F16) : inp->self_kq_mask;
20102058
}
20112059

2060+
inp->self_k_rot = mctx_cur->build_input_k_rot(ctx0);
2061+
inp->self_v_rot = mctx_cur->build_input_v_rot(ctx0);
2062+
20122063
return inp;
20132064
}
20142065

@@ -2034,6 +2085,15 @@ ggml_tensor * llm_graph_context::build_attn(
20342085
int il) const {
20352086
GGML_ASSERT(v_mla == nullptr);
20362087

2088+
if (inp->self_k_rot) {
2089+
q_cur = ggml_mul_mat_aux(ctx0, q_cur, inp->self_k_rot);
2090+
k_cur = ggml_mul_mat_aux(ctx0, k_cur, inp->self_k_rot);
2091+
}
2092+
2093+
if (inp->self_v_rot) {
2094+
v_cur = ggml_mul_mat_aux(ctx0, v_cur, inp->self_v_rot);
2095+
}
2096+
20372097
// these nodes are added to the graph together so that they are not reordered
20382098
// by doing so, the number of splits in the graph is reduced
20392099
// expand k later to enable rope fusion which directly writes into k-v cache
@@ -2061,6 +2121,10 @@ ggml_tensor * llm_graph_context::build_attn(
20612121
ggml_tensor * cur = build_attn_mha(q, k, v, kq_b, kq_mask, sinks, v_mla, kq_scale, il);
20622122
cb(cur, "kqv_out", il);
20632123

2124+
if (inp->self_v_rot) {
2125+
cur = ggml_mul_mat_aux(ctx0, cur, inp->self_v_rot);
2126+
}
2127+
20642128
if (wo) {
20652129
cur = build_lora_mm(wo, cur);
20662130
if (arch == LLM_ARCH_GLM4 || arch == LLM_ARCH_GLM4_MOE || arch == LLM_ARCH_JAIS2) {
@@ -2090,9 +2154,7 @@ static std::unique_ptr<llm_graph_input_attn_k> build_attn_inp_k_impl(
20902154

20912155
inp->self_k_idxs = mctx_cur->build_input_k_idxs(ctx0, ubatch);
20922156

2093-
inp->self_kq_mask = build_kq_mask(ctx0, mctx_cur, ubatch, cparams);
2094-
ggml_set_input(inp->self_kq_mask);
2095-
2157+
inp->self_kq_mask = build_attn_inp_kq_mask(ctx0, mctx_cur, ubatch, cparams);
20962158
inp->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask, GGML_TYPE_F16) : inp->self_kq_mask;
20972159
}
20982160

@@ -2171,6 +2233,18 @@ ggml_tensor * llm_graph_context::build_attn(
21712233
ggml_tensor * v_mla,
21722234
float kq_scale,
21732235
int il) const {
2236+
if (inp->self_k_rot) {
2237+
q_cur = ggml_mul_mat_aux(ctx0, q_cur, inp->self_k_rot);
2238+
if (k_cur) {
2239+
k_cur = ggml_mul_mat_aux(ctx0, k_cur, inp->self_k_rot);
2240+
}
2241+
}
2242+
if (inp->self_v_rot) {
2243+
if (v_cur) {
2244+
v_cur = ggml_mul_mat_aux(ctx0, v_cur, inp->self_v_rot);
2245+
}
2246+
}
2247+
21742248
// these nodes are added to the graph together so that they are not reordered
21752249
// by doing so, the number of splits in the graph is reduced
21762250
ggml_build_forward_expand(gf, q_cur);
@@ -2211,6 +2285,10 @@ ggml_tensor * llm_graph_context::build_attn(
22112285
ggml_tensor * cur = build_attn_mha(q, k, v, kq_b, kq_mask, sinks, v_mla, kq_scale, il);
22122286
cb(cur, "kqv_out", il);
22132287

2288+
if (inp->self_v_rot) {
2289+
cur = ggml_mul_mat_aux(ctx0, cur, inp->self_v_rot);
2290+
}
2291+
22142292
if (wo) {
22152293
cur = build_lora_mm(wo, cur);
22162294
}
@@ -2293,12 +2371,8 @@ llm_graph_input_attn_kv_iswa * llm_graph_context::build_attn_inp_kv_iswa() const
22932371
inp->self_k_idxs = mctx_cur->get_base()->build_input_k_idxs(ctx0, ubatch);
22942372
inp->self_v_idxs = mctx_cur->get_base()->build_input_v_idxs(ctx0, ubatch);
22952373

2296-
inp->self_kq_mask = build_kq_mask(ctx0, mctx_cur->get_base(), ubatch, cparams);
2297-
ggml_set_input(inp->self_kq_mask);
2298-
ggml_set_name(inp->self_kq_mask, "self_kq_mask");
2299-
2374+
inp->self_kq_mask = build_attn_inp_kq_mask(ctx0, mctx_cur->get_base(), ubatch, cparams);
23002375
inp->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask, GGML_TYPE_F16) : inp->self_kq_mask;
2301-
ggml_set_name(inp->self_kq_mask_cnv, "self_kq_mask_cnv");
23022376
}
23032377

23042378
{
@@ -2307,14 +2381,13 @@ llm_graph_input_attn_kv_iswa * llm_graph_context::build_attn_inp_kv_iswa() const
23072381
inp->self_k_idxs_swa = mctx_cur->get_swa()->build_input_k_idxs(ctx0, ubatch);
23082382
inp->self_v_idxs_swa = mctx_cur->get_swa()->build_input_v_idxs(ctx0, ubatch);
23092383

2310-
inp->self_kq_mask_swa = build_kq_mask(ctx0, mctx_cur->get_swa(), ubatch, cparams);
2311-
ggml_set_input(inp->self_kq_mask_swa);
2312-
ggml_set_name(inp->self_kq_mask_swa, "self_kq_mask_swa");
2313-
2384+
inp->self_kq_mask_swa = build_attn_inp_kq_mask(ctx0, mctx_cur->get_swa(), ubatch, cparams);
23142385
inp->self_kq_mask_swa_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp->self_kq_mask_swa, GGML_TYPE_F16) : inp->self_kq_mask_swa;
2315-
ggml_set_name(inp->self_kq_mask_swa_cnv, "self_kq_mask_swa_cnv");
23162386
}
23172387

2388+
inp->self_k_rot = mctx_cur->get_base()->build_input_k_rot(ctx0);
2389+
inp->self_v_rot = mctx_cur->get_base()->build_input_v_rot(ctx0);
2390+
23182391
return (llm_graph_input_attn_kv_iswa *) res->add_input(std::move(inp));
23192392
}
23202393

@@ -2473,19 +2546,15 @@ llm_graph_input_mem_hybrid_iswa * llm_graph_context::build_inp_mem_hybrid_iswa()
24732546
inp_attn->self_k_idxs = attn_ctx->get_base()->build_input_k_idxs(ctx0, ubatch);
24742547
inp_attn->self_v_idxs = attn_ctx->get_base()->build_input_v_idxs(ctx0, ubatch);
24752548

2476-
inp_attn->self_kq_mask = build_kq_mask(ctx0, attn_ctx->get_base(), ubatch, cparams);
2477-
ggml_set_input(inp_attn->self_kq_mask);
2478-
2549+
inp_attn->self_kq_mask = build_attn_inp_kq_mask(ctx0, attn_ctx->get_base(), ubatch, cparams);
24792550
inp_attn->self_kq_mask_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp_attn->self_kq_mask, GGML_TYPE_F16) : inp_attn->self_kq_mask;
24802551
}
24812552

24822553
{
24832554
inp_attn->self_k_idxs_swa = attn_ctx->get_swa()->build_input_k_idxs(ctx0, ubatch);
24842555
inp_attn->self_v_idxs_swa = attn_ctx->get_swa()->build_input_v_idxs(ctx0, ubatch);
24852556

2486-
inp_attn->self_kq_mask_swa = build_kq_mask(ctx0, attn_ctx->get_swa(), ubatch, cparams);
2487-
ggml_set_input(inp_attn->self_kq_mask_swa);
2488-
2557+
inp_attn->self_kq_mask_swa = build_attn_inp_kq_mask(ctx0, attn_ctx->get_swa(), ubatch, cparams);
24892558
inp_attn->self_kq_mask_swa_cnv = cparams.flash_attn ? ggml_cast(ctx0, inp_attn->self_kq_mask_swa, GGML_TYPE_F16) : inp_attn->self_kq_mask_swa;
24902559
}
24912560

src/llama-graph.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ class llm_graph_input_attn_kv : public llm_graph_input_i {
308308
ggml_tensor * self_kq_mask = nullptr; // F32 [n_kv, n_batch/n_stream, 1, n_stream]
309309
ggml_tensor * self_kq_mask_cnv = nullptr; // [n_kv, n_batch/n_stream, 1, n_stream]
310310

311+
// note: assumes v_rot^ == I
312+
ggml_tensor * self_k_rot = nullptr;
313+
ggml_tensor * self_v_rot = nullptr;
314+
311315
// note: these have to be copies because in order to be able to reuse a graph, its inputs
312316
// need to carry these parameters with them. otherwise, they can point to freed
313317
// llm_graph_params from a previous batch, causing stack-use-after-return
@@ -384,6 +388,10 @@ class llm_graph_input_attn_kv_iswa : public llm_graph_input_i {
384388
ggml_tensor * self_kq_mask_swa = nullptr; // F32 [n_kv, n_batch/n_stream, 1, n_stream]
385389
ggml_tensor * self_kq_mask_swa_cnv = nullptr; // [n_kv, n_batch/n_stream, 1, n_stream]
386390

391+
// note: using same rotation matrices for both base and swa cache
392+
ggml_tensor * self_k_rot = nullptr;
393+
ggml_tensor * self_v_rot = nullptr;
394+
387395
const llama_hparams hparams;
388396
const llama_cparams cparams;
389397

0 commit comments

Comments
 (0)