Bug Summary

File:root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp
Warning:line 243, column 9
Value stored to 'p0' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name llama-memory-recurrent.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +avx -target-feature +avx2 -target-feature +bmi2 -target-feature +f16c -target-feature +fma -target-feature +sse4.2 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/llama.cpp -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/llama.cpp -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D _GNU_SOURCE=1 -D GGML_USE_CPU=1 -D GGML_VERSION="GGML_VERSION" -D GGML_COMMIT="GGML_COMMIT" -D GGML_SHARED=1 -D LLAMA_SHARED=1 -D GGML_BUILD=1 -D LLAMA_BUILD=1 -D GGML_BACKEND_SHARED=1 -D GGML_BACKEND_BUILD=1 -D MOZ_HAS_MOZGLUE -I /root/firefox-clang/third_party/llama.cpp -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/llama.cpp -I /root/firefox-clang/third_party/llama.cpp/ggml -I /root/firefox-clang/third_party/llama.cpp/ggml/include -I /root/firefox-clang/third_party/llama.cpp/ggml/src -I /root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-cpu -I /root/firefox-clang/third_party/llama.cpp/include -I /root/firefox-clang/third_party/llama.cpp/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -Wno-sign-compare -Wno-unused-function -Wno-tautological-unsigned-enum-zero-compare -Wno-implicit-fallthrough -Wno-unreachable-code -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ /root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp
1#include "llama-memory-recurrent.h"
2
3#include "ggml-backend.h"
4#include "llama-impl.h"
5#include "llama-io.h"
6#include "llama-batch.h"
7#include "llama-model.h"
8
9#include <algorithm>
10#include <cassert>
11#include <cstring>
12#include <limits>
13#include <map>
14#include <stdexcept>
15
16#include "moz-overrides.h"
17
18//
19// llama_memory_recurrent
20//
21
22llama_memory_recurrent::llama_memory_recurrent(
23 const llama_model & model,
24 ggml_type type_r,
25 ggml_type type_s,
26 bool offload,
27 uint32_t mem_size,
28 uint32_t n_seq_max,
29 uint32_t n_rs_seq,
30 const layer_filter_cb & filter) : hparams(model.hparams), n_seq_max(n_seq_max) {
31 const int32_t n_layer = hparams.n_layer();
32
33 head = 0;
34 size = mem_size;
35 used = 0;
36
37 this->n_rs_seq = n_rs_seq;
38 rs_idx.assign(n_seq_max, 0);
39
40 cells.clear();
41 cells.resize(mem_size);
42
43 // define a comparator for the buft -> ctx map to ensure that the order is well-defined:
44 struct ggml_backend_buft_comparator {
45 bool operator()(const ggml_backend_buffer_type_t & lhs, const ggml_backend_buffer_type_t & rhs) const {
46 return strcmp(ggml_backend_buft_name(lhs), ggml_backend_buft_name(rhs)) < 0;
47 }
48 };
49 std::map<ggml_backend_buffer_type_t, ggml_context_ptr, ggml_backend_buft_comparator> ctx_map;
50
51 // create a context for each buffer type
52 auto ctx_for_buft = [&](ggml_backend_buffer_type_t buft) -> ggml_context * {
53 auto it = ctx_map.find(buft);
54 if (it == ctx_map.end()) {
55 ggml_init_params params = {
56 /*.mem_size =*/ size_t(2u*n_layer*ggml_tensor_overhead()),
57 /*.mem_buffer =*/ NULL__null,
58 /*.no_alloc =*/ true,
59 };
60
61 ggml_context * ctx = ggml_init(params);
62 if (!ctx) {
63 return nullptr;
64 }
65
66 ctx_map.emplace(buft, ctx);
67
68 return ctx;
69 }
70
71 return it->second.get();
72 };
73
74 r_l.resize(n_layer);
75 s_l.resize(n_layer);
76
77 for (int i = 0; i < n_layer; i++) {
78 if (filter && !filter(i)) {
79 LLAMA_LOG_DEBUG("%s: layer %3d: skipped\n", __func__, i)llama_log_internal(GGML_LOG_LEVEL_DEBUG, "%s: layer %3d: skipped\n"
, __func__, i)
;
80 continue;
81 }
82
83 const char * dev_name = "CPU";
84
85 ggml_backend_buffer_type_t buft = ggml_backend_cpu_buffer_type();
86
87 if (offload) {
88 auto * dev = model.dev_layer(i);
89 buft = ggml_backend_dev_buffer_type(dev);
90
91 dev_name = ggml_backend_dev_name(dev);
92 }
93
94 LLAMA_LOG_DEBUG("%s, layer %3d: dev = %s\n", __func__, i, dev_name)llama_log_internal(GGML_LOG_LEVEL_DEBUG, "%s, layer %3d: dev = %s\n"
, __func__, i, dev_name)
;
95
96 ggml_context * ctx = ctx_for_buft(buft);
97 if (!ctx) {
98 throwabort_with_suppression(); if (false) std::runtime_error("failed to create ggml context for rs cache");
99 }
100
101 const uint32_t n_rows = mem_size * (1 + n_rs_seq);
102 ggml_tensor * r = ggml_new_tensor_2d(ctx, type_r, hparams.n_embd_r(), n_rows);
103 ggml_tensor * s = ggml_new_tensor_2d(ctx, type_s, hparams.n_embd_s(), n_rows);
104 ggml_format_name(r, "cache_r_l%d", i);
105 ggml_format_name(s, "cache_s_l%d", i);
106 r_l[i] = r;
107 s_l[i] = s;
108 }
109
110 // allocate tensors and initialize the buffers to avoid NaNs in the padding
111 for (auto & [buft, ctx] : ctx_map) {
112 ggml_backend_buffer_t buf = ggml_backend_alloc_ctx_tensors_from_buft(ctx.get(), buft);
113 if (!buf) {
114 throwabort_with_suppression(); if (false) std::runtime_error("failed to allocate buffer for rs cache");
115 }
116 ggml_backend_buffer_clear(buf, 0);
117 LLAMA_LOG_INFO("%s: %10s RS buffer size = %8.2f MiB\n", __func__, ggml_backend_buffer_name(buf), ggml_backend_buffer_get_size(buf)/1024.0/1024.0)llama_log_internal(GGML_LOG_LEVEL_INFO , "%s: %10s RS buffer size = %8.2f MiB\n"
, __func__, ggml_backend_buffer_name(buf), ggml_backend_buffer_get_size
(buf)/1024.0/1024.0)
;
118 ctxs_bufs.emplace_back(std::move(ctx), buf);
119 }
120
121 {
122 const size_t memory_size_r = size_r_bytes();
123 const size_t memory_size_s = size_s_bytes();
124
125 LLAMA_LOG_INFO("%s: size = %7.2f MiB (%6u cells, %3d layers, %2u seqs %2u rs_seq), R (%s): %7.2f MiB, S (%s): %7.2f MiB\n", __func__,llama_log_internal(GGML_LOG_LEVEL_INFO , "%s: size = %7.2f MiB (%6u cells, %3d layers, %2u seqs %2u rs_seq), R (%s): %7.2f MiB, S (%s): %7.2f MiB\n"
, __func__, (float)(memory_size_r + memory_size_s) / (1024.0f
* 1024.0f), mem_size, n_layer, n_seq_max, n_rs_seq, ggml_type_name
(type_r), (float)memory_size_r / (1024.0f * 1024.0f), ggml_type_name
(type_s), (float)memory_size_s / (1024.0f * 1024.0f))
126 (float)(memory_size_r + memory_size_s) / (1024.0f * 1024.0f), mem_size, n_layer, n_seq_max, n_rs_seq,llama_log_internal(GGML_LOG_LEVEL_INFO , "%s: size = %7.2f MiB (%6u cells, %3d layers, %2u seqs %2u rs_seq), R (%s): %7.2f MiB, S (%s): %7.2f MiB\n"
, __func__, (float)(memory_size_r + memory_size_s) / (1024.0f
* 1024.0f), mem_size, n_layer, n_seq_max, n_rs_seq, ggml_type_name
(type_r), (float)memory_size_r / (1024.0f * 1024.0f), ggml_type_name
(type_s), (float)memory_size_s / (1024.0f * 1024.0f))
127 ggml_type_name(type_r), (float)memory_size_r / (1024.0f * 1024.0f),llama_log_internal(GGML_LOG_LEVEL_INFO , "%s: size = %7.2f MiB (%6u cells, %3d layers, %2u seqs %2u rs_seq), R (%s): %7.2f MiB, S (%s): %7.2f MiB\n"
, __func__, (float)(memory_size_r + memory_size_s) / (1024.0f
* 1024.0f), mem_size, n_layer, n_seq_max, n_rs_seq, ggml_type_name
(type_r), (float)memory_size_r / (1024.0f * 1024.0f), ggml_type_name
(type_s), (float)memory_size_s / (1024.0f * 1024.0f))
128 ggml_type_name(type_s), (float)memory_size_s / (1024.0f * 1024.0f))llama_log_internal(GGML_LOG_LEVEL_INFO , "%s: size = %7.2f MiB (%6u cells, %3d layers, %2u seqs %2u rs_seq), R (%s): %7.2f MiB, S (%s): %7.2f MiB\n"
, __func__, (float)(memory_size_r + memory_size_s) / (1024.0f
* 1024.0f), mem_size, n_layer, n_seq_max, n_rs_seq, ggml_type_name
(type_r), (float)memory_size_r / (1024.0f * 1024.0f), ggml_type_name
(type_s), (float)memory_size_s / (1024.0f * 1024.0f))
;
129 }
130}
131
132void llama_memory_recurrent::clear(bool data) {
133 for (int32_t i = 0; i < (int32_t) size; ++i) {
134 cells[i].pos = -1;
135 cells[i].seq_id.clear();
136 cells[i].src = -1;
137 cells[i].tail = -1;
138 }
139
140 head = 0;
141 used = 0;
142
143 if (data) {
144 for (auto & [_, buf] : ctxs_bufs) {
145 ggml_backend_buffer_clear(buf.get(), 0);
146 }
147 }
148
149 std::fill(rs_idx.begin(), rs_idx.end(), 0);
150}
151
152bool llama_memory_recurrent::seq_rm(llama_seq_id seq_id, llama_pos p0, llama_pos p1) {
153 uint32_t new_head = size;
154
155 if (p0 < 0) {
156 p0 = 0;
157 }
158
159 if (p1 < 0) {
160 p1 = std::numeric_limits<llama_pos>::max();
161 }
162
163 const bool rm_all = p0 == 0 && p1 == std::numeric_limits<llama_pos>::max();
164 if (rm_all) {
165 if (seq_id >= 0) {
166 set_rs_idx(seq_id, 0);
167 } else {
168 std::fill(rs_idx.begin(), rs_idx.end(), 0);
169 }
170 }
171
172 // models like Mamba or RWKV can't have a state partially erased at the end
173 // of the sequence because their state isn't preserved for previous tokens
174 if (seq_id >= (int64_t) size) {
175 // could be fatal
176 return false;
177 }
178 if (0 <= seq_id) {
179 int32_t & tail_id = cells[seq_id].tail;
180 if (tail_id >= 0) {
181 auto & cell = cells[tail_id];
182
183 // partial rollback via per-token snapshot index (bounded by n_rs_seq)
184 if (0 < p0 && p0 <= cell.pos && p1 > cell.pos) {
185 const llama_pos rollback = cell.pos - (p0 - 1);
186 if (rollback >= 1 && rollback <= (llama_pos) n_rs_seq) {
187 set_rs_idx(seq_id, (uint32_t) rollback);
188 cell.pos = p0 - 1;
189 return true;
190 }
191 return false;
192 }
193 // invalidate tails which will be cleared
194 if (p0 <= cell.pos && cell.pos < p1) {
195 tail_id = -1;
196 }
197 }
198 } else {
199 // seq_id is negative, then the range should include everything or nothing
200 if (p0 != p1 && (p0 != 0 || p1 != std::numeric_limits<llama_pos>::max())) {
201 //printf("[DEBUG] inside `llama_memory_recurrent::seq_rm`: `seq_id` is negative, so returning false\n");
202 return false;
203 }
204 }
205
206 for (uint32_t i = 0; i < size; ++i) {
207 if (cells[i].pos >= p0 && cells[i].pos < p1) {
208 if (seq_id < 0) {
209 cells[i].seq_id.clear();
210 } else if (cells[i].has_seq_id(seq_id)) {
211 cells[i].seq_id.erase(seq_id);
212 } else {
213 continue;
214 }
215 if (cells[i].is_empty()) {
216 // keep count of the number of used cells
217 if (cells[i].pos >= 0) {
218 used--;
219 }
220 cells[i].pos = -1;
221 cells[i].src = -1;
222 if (new_head == size) {
223 new_head = i;
224 }
225 }
226 }
227 }
228
229 // If we freed up a slot, set head to it so searching can start there.
230 if (new_head != size && new_head < head) {
231 head = new_head;
232 }
233
234 return true;
235}
236
237void llama_memory_recurrent::seq_cp(llama_seq_id seq_id_src, llama_seq_id seq_id_dst, llama_pos p0, llama_pos p1) {
238 if (seq_id_src == seq_id_dst) {
239 return;
240 }
241
242 if (p0 < 0) {
243 p0 = 0;
Value stored to 'p0' is never read
244 }
245
246 if (p1 < 0) {
247 p1 = std::numeric_limits<llama_pos>::max();
248 }
249
250 if ((uint32_t) seq_id_dst < size && (uint32_t) seq_id_src < size) {
251 auto & tail_src = cells[seq_id_src];
252 auto & tail_dst = cells[seq_id_dst];
253 if (tail_dst.tail >= 0) {
254 // clear destination seq_id if it wasn't empty
255 auto & cell_dst = cells[tail_dst.tail];
256
257 cell_dst.seq_id.erase(seq_id_dst);
258 tail_dst.tail = -1;
259 if (cell_dst.seq_id.empty()) {
260 cell_dst.pos = -1;
261 cell_dst.src = -1;
262 used -= 1;
263 }
264 }
265 if (tail_src.tail >= 0) {
266 auto & cell_src = cells[tail_src.tail];
267
268 cell_src.seq_id.insert(seq_id_dst);
269 tail_dst.tail = tail_src.tail;
270 }
271 }
272}
273
274void llama_memory_recurrent::seq_keep(llama_seq_id seq_id) {
275 uint32_t new_head = size;
276
277 for (uint32_t i = 0; i < size; ++i) {
278 if ((llama_seq_id) i != seq_id) {
279 cells[i].tail = -1;
280 }
281
282 if (!cells[i].has_seq_id(seq_id)) {
283 if (cells[i].pos >= 0) {
284 used--;
285 }
286
287 cells[i].pos = -1;
288 cells[i].src = -1;
289 cells[i].seq_id.clear();
290
291 if (new_head == size){
292 new_head = i;
293 }
294 } else {
295 cells[i].seq_id.clear();
296 cells[i].seq_id.insert(seq_id);
297 }
298 }
299
300 // If we freed up a slot, set head to it so searching can start there.
301 if (new_head != size && new_head < head) {
302 head = new_head;
303 }
304}
305
306void llama_memory_recurrent::seq_add(llama_seq_id seq_id, llama_pos p0, llama_pos p1, llama_pos shift) {
307 if (shift == 0) {
308 return;
309 }
310
311 if (p0 < 0) {
312 p0 = 0;
313 }
314
315 if (p1 < 0) {
316 p1 = std::numeric_limits<llama_pos>::max();
317 }
318
319 // If there is no range then return early to avoid looping over the
320 if (p0 == p1) {
321 return;
322 }
323
324 // for Mamba-like or RWKV models, only the pos needs to be shifted
325 if (0 <= seq_id && seq_id < (int64_t) size) {
326 const int32_t tail_id = cells[seq_id].tail;
327 if (tail_id >= 0) {
328 auto & cell = cells[tail_id];
329 if (cell.has_seq_id(seq_id) && p0 <= cell.pos && cell.pos < p1) {
330 cell.pos += shift;
331 }
332 }
333 }
334}
335
336void llama_memory_recurrent::seq_div(llama_seq_id seq_id, llama_pos p0, llama_pos p1, int d) {
337 if (d == 1) {
338 return;
339 }
340
341 if (p0 < 0) {
342 p0 = 0;
343 }
344
345 if (p1 < 0) {
346 p1 = std::numeric_limits<llama_pos>::max();
347 }
348
349 // If there is no range then return early to avoid looping over the cache.
350 if (p0 == p1) {
351 return;
352 }
353
354 // for Mamba-like or RWKV models, only the pos needs to be changed
355 if (0 <= seq_id && seq_id < (int64_t) size) {
356 const int32_t tail_id = cells[seq_id].tail;
357 if (tail_id >= 0) {
358 auto & cell = cells[tail_id];
359 if (cell.has_seq_id(seq_id) && p0 <= cell.pos && cell.pos < p1) {
360 cell.pos /= d;
361 }
362 }
363 }
364}
365
366llama_pos llama_memory_recurrent::seq_pos_min(llama_seq_id seq_id) const {
367 llama_pos result = std::numeric_limits<llama_pos>::max();
368
369 for (uint32_t i = 0; i < size; ++i) {
370 if (cells[i].has_seq_id(seq_id)) {
371 result = std::min(result, cells[i].pos);
372 }
373 }
374
375 if (result == std::numeric_limits<llama_pos>::max()) {
376 result = -1;
377 }
378
379 return result;
380}
381
382llama_pos llama_memory_recurrent::seq_pos_max(llama_seq_id seq_id) const {
383 llama_pos result = -1;
384
385 for (uint32_t i = 0; i < size; ++i) {
386 if (cells[i].has_seq_id(seq_id)) {
387 result = std::max(result, cells[i].pos);
388 }
389 }
390
391 return result;
392}
393
394void llama_memory_recurrent::set_rs_idx(llama_seq_id seq_id, uint32_t idx) {
395 if (seq_id < 0 || (size_t) seq_id >= rs_idx.size()) {
396 return;
397 }
398 rs_idx[seq_id] = (idx > n_rs_seq) ? n_rs_seq : idx;
399}
400
401std::map<ggml_backend_buffer_type_t, size_t> llama_memory_recurrent::memory_breakdown() const {
402 std::map<ggml_backend_buffer_type_t, size_t> ret;
403 for (const auto & [_, buf] : ctxs_bufs) {
404 ret[ggml_backend_buffer_get_type(buf.get())] += ggml_backend_buffer_get_size(buf.get());
405 }
406 return ret;
407}
408
409llama_memory_context_ptr llama_memory_recurrent::init_batch(llama_batch_allocr & balloc, uint32_t n_ubatch, bool embd_all) {
410 do {
411 balloc.split_reset();
412
413 std::vector<llama_ubatch> ubatches;
414 while (true) {
415 llama_ubatch ubatch;
416
417 if (embd_all) {
418 // if all tokens are output, split by sequence
419 ubatch = balloc.split_seq(n_ubatch);
420 } else {
421 if (n_rs_seq > 0) {
422 // [TAG_RECURRENT_ROLLBACK_SPLITS]
423 // TODO: recurrent state rollback does not support equal splits
424 ubatch = balloc.split_seq(n_ubatch);
425 } else {
426 // TODO: non-sequential equal split can be done if using unified KV cache
427 // for simplicity, we always use sequential equal split for now
428 ubatch = balloc.split_equal(n_ubatch, true);
429 }
430 }
431
432 if (ubatch.n_tokens == 0) {
433 break;
434 }
435
436 ubatches.push_back(std::move(ubatch)); // NOLINT
437 }
438
439 if (balloc.get_n_used() < balloc.get_n_tokens()) {
440 // failed to find a suitable split
441 break;
442 }
443
444 if (!prepare(ubatches)) {
445 break;
446 }
447
448 return std::make_unique<llama_memory_recurrent_context>(this, std::move(ubatches));
449 } while (false);
450
451 return std::make_unique<llama_memory_recurrent_context>(LLAMA_MEMORY_STATUS_FAILED_PREPARE);
452}
453
454llama_memory_context_ptr llama_memory_recurrent::init_full() {
455 return std::make_unique<llama_memory_recurrent_context>(this);
456}
457
458llama_memory_context_ptr llama_memory_recurrent::init_update(llama_context * lctx, bool optimize) {
459 GGML_UNUSED(lctx)(void)(lctx);
460 GGML_UNUSED(optimize)(void)(optimize);
461
462 return std::make_unique<llama_memory_recurrent_context>(LLAMA_MEMORY_STATUS_NO_UPDATE);
463}
464
465bool llama_memory_recurrent::prepare(const std::vector<llama_ubatch> & ubatches) {
466 // simply remember the full state because it is very small for this type of cache
467 // TODO: optimize
468 auto org_cells = cells;
469 auto org_used = used;
470 auto org_head = head;
471
472 bool success = true;
473
474 for (const auto & ubatch : ubatches) {
475 if (!find_slot(ubatch)) {
476 success = false;
477 break;
478 }
479 }
480
481 // restore the original state
482 cells = std::move(org_cells);
483 used = org_used;
484 head = org_head;
485
486 return success;
487}
488
489bool llama_memory_recurrent::find_slot(const llama_ubatch & ubatch) {
490 const uint32_t n_seq_tokens = ubatch.n_seq_tokens;
491 const uint32_t n_seqs = ubatch.n_seqs;
492
493 // if we have enough unused cells before the current head ->
494 // better to start searching from the beginning of the cache, hoping to fill it
495 if (head > used + 2*n_seqs) {
496 head = 0;
497 }
498
499 // For recurrent state architectures (like Mamba or RWKV),
500 // each cache cell can store the state for a whole sequence.
501 // A slot should be always be contiguous.
502
503 // can only process batches with an equal number of new tokens in each sequence
504 GGML_ASSERT(ubatch.equal_seqs())if (!(ubatch.equal_seqs())) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 504, "GGML_ASSERT(%s) failed", "ubatch.equal_seqs()")
;
505
506 int32_t min = size - 1;
507 int32_t max = 0;
508
509 // everything should fit if all seq_ids are smaller than the max
510 for (uint32_t s = 0; s < n_seqs; ++s) {
511 const uint32_t i = s*n_seq_tokens; // first token of sequence set s
512 const uint32_t n_seq_id = ubatch.n_seq_id[i];
513
514 for (uint32_t j = 0; j < n_seq_id; ++j) {
515 const llama_seq_id seq_id = ubatch.seq_id[i][j];
516
517 if (seq_id < 0 || (uint32_t) seq_id >= size) {
518 // too big seq_id
519 // TODO: would it be possible to resize the cache instead?
520 LLAMA_LOG_ERROR("%s: seq_id=%d >= n_seq_max=%u Try using a bigger --parallel value\n", __func__, seq_id, n_seq_max)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: seq_id=%d >= n_seq_max=%u Try using a bigger --parallel value\n"
, __func__, seq_id, n_seq_max)
;
521 return false;
522 }
523 if (j > 0) {
524 auto & seq = cells[seq_id];
525 if (seq.tail >= 0) {
526 auto & cell = cells[seq.tail];
527 // clear cells from seq_ids that become shared
528 // (should not normally happen, but let's handle it anyway)
529 cell.seq_id.erase(seq_id);
530 seq.tail = -1;
531 if (cell.seq_id.empty()) {
532 cell.pos = -1;
533 cell.src = -1;
534 used -= 1;
535 }
536 }
537 }
538 }
539 }
540
541#ifndef NDEBUG
542 {
543 std::vector<int32_t> tails_verif;
544 tails_verif.assign(size, -1);
545 for (uint32_t i = 0; i < size; ++i) {
546 auto & cell = cells[i];
547 for (llama_seq_id seq_id : cell.seq_id) {
548 if (tails_verif[seq_id] != -1) {
549 LLAMA_LOG_ERROR("%s: duplicate tail for seq_id %d in cell %d and %d\n", __func__, seq_id, i, tails_verif[seq_id])llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: duplicate tail for seq_id %d in cell %d and %d\n"
, __func__, seq_id, i, tails_verif[seq_id])
;
550 }
551 tails_verif[seq_id] = i;
552 }
553 }
554 for (uint32_t i = 0; i < size; ++i) {
555 if (tails_verif[i] != cells[i].tail) {
556 LLAMA_LOG_ERROR("%s: wrong tail for seq_id %d, (%d instead of %d)\n", __func__, i, cells[i].tail, tails_verif[i])llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: wrong tail for seq_id %d, (%d instead of %d)\n"
, __func__, i, cells[i].tail, tails_verif[i])
;
557 }
558 }
559 }
560#endif
561
562 // find next empty cell
563 uint32_t next_empty_cell = head;
564
565 for (uint32_t i = 0; i < size; ++i) {
566 if (next_empty_cell >= size) { next_empty_cell -= size; }
567 auto & cell = cells[next_empty_cell];
568 if (cell.is_empty()) { break; }
569 next_empty_cell += 1;
570 }
571
572 // find usable cell range
573 for (uint32_t s = 0; s < n_seqs; ++s) {
574 const uint32_t i = s*n_seq_tokens;
575 const llama_seq_id seq_id = ubatch.seq_id[i][0];
576 auto & seq_meta = cells[seq_id];
577 bool has_cell = false;
578 if (seq_meta.tail >= 0) {
579 auto & cell = cells[seq_meta.tail];
580 GGML_ASSERT(cell.has_seq_id(seq_id))if (!(cell.has_seq_id(seq_id))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 580, "GGML_ASSERT(%s) failed", "cell.has_seq_id(seq_id)")
;
581 // does this seq_id "own" the cell?
582 if (cell.seq_id.size() == 1) { has_cell = true; }
583 }
584 if (!has_cell) {
585 auto & empty_cell = cells[next_empty_cell];
586 GGML_ASSERT(empty_cell.is_empty())if (!(empty_cell.is_empty())) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 586, "GGML_ASSERT(%s) failed", "empty_cell.is_empty()")
;
587 // copy old tail into the empty cell
588 if (seq_meta.tail >= 0) {
589 auto & orig_cell = cells[seq_meta.tail];
590 empty_cell.pos = orig_cell.pos;
591 empty_cell.src = orig_cell.src;
592 orig_cell.seq_id.erase(seq_id);
593 empty_cell.seq_id.insert(seq_id); // will be overwritten
594 GGML_ASSERT(!orig_cell.is_empty())if (!(!orig_cell.is_empty())) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 594, "GGML_ASSERT(%s) failed", "!orig_cell.is_empty()")
; // has at least one remaining seq_id
595 }
596 seq_meta.tail = next_empty_cell;
597 // find next empty cell
598 if (s + 1 < n_seqs) {
599 for (uint32_t j = 0; j < size; ++j) {
600 next_empty_cell += 1;
601 if (next_empty_cell >= size) { next_empty_cell -= size; }
602 auto & cell = cells[next_empty_cell];
603 if (cell.is_empty()) { break; }
604 }
605 }
606 }
607 if (min > seq_meta.tail) { min = seq_meta.tail; }
608 if (max < seq_meta.tail) { max = seq_meta.tail; }
609 }
610
611 // gather and re-order
612 for (uint32_t s = 0; s < n_seqs; ++s) {
613 const uint32_t i = s*n_seq_tokens;
614 const int32_t dst_id = s + min;
615 const int32_t src_id = cells[ubatch.seq_id[i][0]].tail;
616 if (dst_id != src_id) {
617 auto & dst_cell = cells[dst_id];
618 auto & src_cell = cells[src_id];
619
620 std::swap(dst_cell.pos, src_cell.pos);
621 std::swap(dst_cell.src, src_cell.src);
622 std::swap(dst_cell.seq_id, src_cell.seq_id);
623
624 // swap tails
625 for (uint32_t j = 0; j < size; ++j) {
626 int32_t & tail = cells[j].tail;
627 if (tail == src_id) {
628 tail = dst_id;
629 } else if (tail == dst_id) {
630 tail = src_id;
631 }
632 }
633 }
634 }
635
636 // update the pos of the used seqs
637 for (uint32_t s = 0; s < n_seqs; ++s) {
638 const uint32_t i = s*n_seq_tokens;
639 const llama_pos last_pos = ubatch.pos[i + n_seq_tokens - 1];
640 const int32_t cell_id = s + min;
641 auto & cell = cells[cell_id];
642
643 if (cell.pos >= 0 && last_pos != cell.pos + (llama_pos) n_seq_tokens) {
644 // What should happen when the pos backtracks or skips a value?
645 // Clearing the state mid-batch would require special-casing which isn't done.
646 LLAMA_LOG_WARN("%s: non-consecutive token position %d after %d for sequence %d with %u new tokens\n",llama_log_internal(GGML_LOG_LEVEL_WARN , "%s: non-consecutive token position %d after %d for sequence %d with %u new tokens\n"
, __func__, last_pos, cell.pos, ubatch.seq_id[i][0], n_seq_tokens
)
647 __func__, last_pos, cell.pos, ubatch.seq_id[i][0], n_seq_tokens)llama_log_internal(GGML_LOG_LEVEL_WARN , "%s: non-consecutive token position %d after %d for sequence %d with %u new tokens\n"
, __func__, last_pos, cell.pos, ubatch.seq_id[i][0], n_seq_tokens
)
;
648 }
649 cell.pos = last_pos;
650 cell.seq_id.clear();
651 for (int32_t j = 0; j < ubatch.n_seq_id[i]; ++j) {
652 const llama_seq_id seq_id = ubatch.seq_id[i][j];
653 cell.seq_id.insert(seq_id);
654 cells[seq_id].tail = cell_id;
655 }
656 }
657
658 // Find first cell without src refs, to use as the zero-ed state
659 {
660 // TODO: bake-in src refcounts in the cell metadata
661 std::vector<int32_t> refcounts(size, 0);
662 for (size_t i = 0; i < size; ++i) {
663 const int32_t src = cells[i].src;
664 if (src >= 0) {
665 refcounts[src] += 1;
666 }
667 }
668
669 rs_z = -1;
670 for (int i = min; i <= max; ++i) {
671 if (refcounts[i] == 0) {
672 rs_z = i;
673 break;
674 }
675 }
676
677 for (int i = min; i <= max; ++i) {
678 if (cells[i].src < 0) {
679 GGML_ASSERT(rs_z >= 0)if (!(rs_z >= 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 679, "GGML_ASSERT(%s) failed", "rs_z >= 0")
;
680 cells[i].src0 = rs_z;
681 } else {
682 // Stage the source ids for all used cells to allow correct seq_* behavior
683 // and still make these values available when setting the inputs
684 cells[i].src0 = cells[i].src;
685 }
686 cells[i].src = i; // avoid moving or clearing twice
687 }
688 }
689
690 // allow getting the range of used cells, from head to head + n
691 head = min;
692 n = max - min + 1;
693 used = std::count_if(cells.begin(), cells.end(),
694 [](const mem_cell & cell){ return !cell.is_empty(); });
695
696 // sanity check
697 return n >= n_seqs;
698}
699
700bool llama_memory_recurrent::get_can_shift() const {
701 // shifting the pos is trivial for recurrent models
702 return true;
703}
704
705size_t llama_memory_recurrent::total_size() const {
706 size_t size = 0;
707 for (const auto & [_, buf] : ctxs_bufs) {
708 size += ggml_backend_buffer_get_size(buf.get());
709 }
710
711 return size;
712}
713
714size_t llama_memory_recurrent::size_r_bytes() const {
715 size_t size_r_bytes = 0;
716
717 for (const auto & r : r_l) {
718 if (r != nullptr) {
719 size_r_bytes += ggml_nbytes(r);
720 }
721 }
722
723 return size_r_bytes;
724}
725
726size_t llama_memory_recurrent::size_s_bytes() const {
727 size_t size_s_bytes = 0;
728
729 for (const auto & s : s_l) {
730 if (s != nullptr) {
731 size_s_bytes += ggml_nbytes(s);
732 }
733 }
734
735 return size_s_bytes;
736}
737
738void llama_memory_recurrent::state_write(llama_io_write_i & io, llama_seq_id seq_id, llama_state_seq_flags flags) const {
739 GGML_UNUSED(flags)(void)(flags);
740
741 std::vector<std::pair<uint32_t, uint32_t>> cell_ranges; // ranges, from inclusive, to exclusive
742 std::vector<std::pair<uint32_t, uint32_t>> cell_ranges_data; // logical source row ranges
743 uint32_t cell_count = 0;
744
745 // Count the number of cells with the specified seq_id
746 // Find all the ranges of cells with this seq id (or all, when -1)
747 uint32_t cell_range_begin = size;
748 for (uint32_t i = 0; i < size; ++i) {
749 const auto & cell = cells[i];
750 if ((seq_id == -1 && !cell.is_empty()) || cell.has_seq_id(seq_id)) {
751 ++cell_count;
752 uint32_t rs_idx_cur = 0;
753
754 if (n_rs_seq != 0) {
755 if (seq_id != -1) {
756 GGML_ASSERT(seq_id >= 0 && (size_t) seq_id < rs_idx.size())if (!(seq_id >= 0 && (size_t) seq_id < rs_idx.size
())) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 756, "GGML_ASSERT(%s) failed", "seq_id >= 0 && (size_t) seq_id < rs_idx.size()"
)
;
757 rs_idx_cur = rs_idx[seq_id];
758 } else {
759 bool has_rs_idx = false;
760 for (const llama_seq_id cell_seq_id : cell.seq_id) {
761 GGML_ASSERT(cell_seq_id >= 0 && (size_t) cell_seq_id < rs_idx.size())if (!(cell_seq_id >= 0 && (size_t) cell_seq_id <
rs_idx.size())) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 761, "GGML_ASSERT(%s) failed", "cell_seq_id >= 0 && (size_t) cell_seq_id < rs_idx.size()"
)
;
762
763 const uint32_t seq_rs_idx = rs_idx[cell_seq_id];
764 if (!has_rs_idx) {
765 rs_idx_cur = seq_rs_idx;
766 has_rs_idx = true;
767 } else if (rs_idx_cur != seq_rs_idx) {
768 GGML_ABORT("cannot write shared recurrent state with different rollback indices")ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 768, "cannot write shared recurrent state with different rollback indices"
)
;
769 }
770 }
771 }
772 }
773
774 const uint32_t cell_id = rs_idx_cur * size + (cell.src >= 0 ? cell.src : (int32_t) i);
775 if (cell_ranges_data.empty() || cell_ranges_data.back().second != cell_id) {
776 cell_ranges_data.emplace_back(cell_id, cell_id + 1);
777 } else {
778 cell_ranges_data.back().second++;
779 }
780
781 if (cell_range_begin == size) {
782 cell_range_begin = i;
783 }
784 } else {
785 if (cell_range_begin != size) {
786 cell_ranges.emplace_back(cell_range_begin, i);
787 cell_range_begin = size;
788 }
789 }
790 }
791 if (cell_range_begin != size) {
792 cell_ranges.emplace_back(cell_range_begin, size);
793 }
794
795 if ((flags & LLAMA_STATE_SEQ_FLAGS_ON_DEVICE2) && cell_ranges.size() > 1) {
796 GGML_ABORT("cannot save/load multiple ranges of cells to/from device memory\n")ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 796, "cannot save/load multiple ranges of cells to/from device memory\n"
)
;
797 }
798
799 // DEBUG CHECK: Sum of cell counts in ranges should equal the total cell count
800 uint32_t cell_count_check = 0;
801 for (const auto & range : cell_ranges) {
802 cell_count_check += range.second - range.first;
803 }
804 GGML_ASSERT(cell_count == cell_count_check)if (!(cell_count == cell_count_check)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 804, "GGML_ASSERT(%s) failed", "cell_count == cell_count_check"
)
;
805
806 cell_count_check = 0;
807 for (const auto & range : cell_ranges_data) {
808 cell_count_check += range.second - range.first;
809 }
810 GGML_ASSERT(cell_count == cell_count_check)if (!(cell_count == cell_count_check)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 810, "GGML_ASSERT(%s) failed", "cell_count == cell_count_check"
)
;
811
812 io.write(&cell_count, sizeof(cell_count));
813
814 state_write_meta(io, cell_ranges, seq_id);
815 state_write_data(io, cell_ranges_data);
816}
817
818void llama_memory_recurrent::state_read(llama_io_read_i & io, llama_seq_id seq_id, llama_state_seq_flags flags) {
819 GGML_UNUSED(flags)(void)(flags);
820
821 uint32_t cell_count;
822 io.read(&cell_count, sizeof(cell_count));
823
824 bool res = true;
825
826 res = res && state_read_meta(io, cell_count, seq_id);
827 res = res && state_read_data(io, cell_count);
828
829 if (!res) {
830 if (seq_id == -1) {
831 clear(true);
832 } else {
833 seq_rm(seq_id, -1, -1);
834 }
835 throwabort_with_suppression(); if (false) std::runtime_error("failed to restore kv cache");
836 }
837
838 if (n_rs_seq != 0) {
839 if (seq_id == -1) {
840 std::fill(rs_idx.begin(), rs_idx.end(), 0);
841 } else {
842 set_rs_idx(seq_id, 0);
843 }
844 }
845}
846
847void llama_memory_recurrent::state_write_meta(llama_io_write_i & io, const std::vector<std::pair<uint32_t, uint32_t>> & cell_ranges, llama_seq_id seq_id) const {
848 for (const auto & range : cell_ranges) {
849 for (uint32_t i = range.first; i < range.second; ++i) {
850 const auto & cell = cells[i];
851 const llama_pos pos = cell.pos;
852 const uint32_t n_seq_id = seq_id == -1 ? cell.seq_id.size() : 0;
853
854 io.write(&pos, sizeof(pos));
855 io.write(&n_seq_id, sizeof(n_seq_id));
856
857 if (n_seq_id) {
858 for (auto seq_id : cell.seq_id) {
859 io.write(&seq_id, sizeof(seq_id));
860 }
861 }
862 }
863 }
864}
865
866void llama_memory_recurrent::state_write_data(llama_io_write_i & io, const std::vector<std::pair<uint32_t, uint32_t>> & cell_ranges) const {
867 const uint32_t s_trans = 0;
868 const uint32_t n_layer = hparams.n_layer();
869
870 io.write(&s_trans, sizeof(s_trans));
871 io.write(&n_layer, sizeof(n_layer));
872
873 // Iterate and write all the R tensors first, each row is a cell
874 // Get whole range at a time
875 for (uint32_t il = 0; il < n_layer; ++il) {
876 // skip null layers (read_data will handle this by checking "r_l" and "s_l" for null)
877 if (r_l[il] == nullptr) continue;
878
879 // Write R tensor type
880 const int32_t r_type_i = (int32_t)r_l[il]->type;
881 io.write(&r_type_i, sizeof(r_type_i));
882
883 // Write row size of R tensor
884 const uint64_t r_size_row = ggml_row_size(r_l[il]->type, hparams.n_embd_r());
885 io.write(&r_size_row, sizeof(r_size_row));
886
887 // Write each logical cell row range. With pending recurrent rollback,
888 // the logical current state may live in a rollback snapshot plane.
889 for (const auto & range : cell_ranges) {
890 const size_t range_size = range.second - range.first;
891 const size_t buf_size = range_size * r_size_row;
892 io.write_tensor(r_l[il], range.first * r_size_row, buf_size);
893 }
894 }
895
896 if (!s_trans) {
897 for (uint32_t il = 0; il < n_layer; ++il) {
898 // skip null layers (read_data will handle this by checking "r_l" and "s_l" for null)
899 if (s_l[il] == nullptr) continue;
900
901 // Write S tensor type
902 const int32_t s_type_i = (int32_t)s_l[il]->type;
903 io.write(&s_type_i, sizeof(s_type_i));
904
905 // Write row size of S tensor
906 const uint64_t s_size_row = ggml_row_size(s_l[il]->type, hparams.n_embd_s());
907 io.write(&s_size_row, sizeof(s_size_row));
908
909 // Write each logical cell row range. With pending recurrent rollback,
910 // the logical current state may live in a rollback snapshot plane.
911 for (const auto & range : cell_ranges) {
912 const size_t range_size = range.second - range.first;
913 const size_t buf_size = range_size * s_size_row;
914 io.write_tensor(s_l[il], range.first * s_size_row, buf_size);
915 }
916 }
917 } else {
918 // When S tensor is transposed, we also need the element size and get the element ranges from each row
919 const uint32_t mem_size = size;
920 for (uint32_t il = 0; il < n_layer; ++il) {
921 // skip null layers (read_data will handle this by checking "r_l" and "s_l" for null)
922 if (s_l[il] == nullptr) continue;
923
924 const uint32_t n_embd_s = hparams.n_embd_s();
925
926 // Write S tensor type
927 const int32_t s_type_i = (int32_t)s_l[il]->type;
928 io.write(&s_type_i, sizeof(s_type_i));
929
930 // Write element size
931 const uint32_t s_size_el = ggml_type_size(s_l[il]->type);
932 io.write(&s_size_el, sizeof(s_size_el));
933
934 // Write GQA embedding size
935 io.write(&n_embd_s, sizeof(n_embd_s));
936
937 // For each row, we get the element values of each logical cell
938 for (uint32_t j = 0; j < n_embd_s; ++j) {
939 for (const auto & range : cell_ranges) {
940 const size_t range_size = range.second - range.first;
941 const size_t src_offset = (range.first + j * mem_size) * s_size_el;
942 const size_t buf_size = range_size * s_size_el;
943 io.write_tensor(s_l[il], src_offset, buf_size);
944 }
945 }
946 }
947 }
948}
949
950bool llama_memory_recurrent::state_read_meta(llama_io_read_i & io, uint32_t cell_count, llama_seq_id dest_seq_id) {
951 if (dest_seq_id != -1) {
952 // single sequence
953 seq_rm(dest_seq_id, -1, -1);
954
955 if (cell_count == 0) {
956 return true;
957 }
958
959 llama_batch_allocr balloc(hparams.n_pos_per_embd());
960
961 llama_ubatch ubatch = balloc.ubatch_reserve(cell_count, 1);
962
963 for (uint32_t i = 0; i < cell_count; ++i) {
964 llama_pos pos;
965 uint32_t n_seq_id;
966
967 io.read(&pos, sizeof(pos));
968 io.read(&n_seq_id, sizeof(n_seq_id));
969
970 if (n_seq_id != 0) {
971 LLAMA_LOG_ERROR("%s: invalid seq_id-agnostic kv cell\n", __func__)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: invalid seq_id-agnostic kv cell\n"
, __func__)
;
972 return false;
973 }
974
975 ubatch.pos[i] = pos;
976 }
977 ubatch.n_seq_id[0] = 1;
978 ubatch.seq_id[0] = &dest_seq_id;
979
980 if (!find_slot(ubatch)) {
981 LLAMA_LOG_ERROR("%s: failed to find available cells in kv cache\n", __func__)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: failed to find available cells in kv cache\n"
, __func__)
;
982 return false;
983 }
984
985 // DEBUG CHECK: kv.head should be our first cell, kv.head + cell_count - 1 should be our last cell (verify seq_id and pos values)
986 // Assume that this is one contiguous block of cells
987 GGML_ASSERT(head + cell_count <= size)if (!(head + cell_count <= size)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 987, "GGML_ASSERT(%s) failed", "head + cell_count <= size"
)
;
988 GGML_ASSERT(cells[head].pos == ubatch.pos[0])if (!(cells[head].pos == ubatch.pos[0])) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 988, "GGML_ASSERT(%s) failed", "cells[head].pos == ubatch.pos[0]"
)
;
989 GGML_ASSERT(cells[head + cell_count - 1].pos == ubatch.pos[cell_count - 1])if (!(cells[head + cell_count - 1].pos == ubatch.pos[cell_count
- 1])) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 989, "GGML_ASSERT(%s) failed", "cells[head + cell_count - 1].pos == ubatch.pos[cell_count - 1]"
)
;
990 GGML_ASSERT(cells[head].has_seq_id(dest_seq_id))if (!(cells[head].has_seq_id(dest_seq_id))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 990, "GGML_ASSERT(%s) failed", "cells[head].has_seq_id(dest_seq_id)"
)
;
991 GGML_ASSERT(cells[head + cell_count - 1].has_seq_id(dest_seq_id))if (!(cells[head + cell_count - 1].has_seq_id(dest_seq_id))) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/src/llama-memory-recurrent.cpp"
, 991, "GGML_ASSERT(%s) failed", "cells[head + cell_count - 1].has_seq_id(dest_seq_id)"
)
;
992 } else {
993 // whole KV cache restore
994
995 if (cell_count > size) {
996 LLAMA_LOG_ERROR("%s: not enough cells in kv cache\n", __func__)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: not enough cells in kv cache\n"
, __func__)
;
997 return false;
998 }
999
1000 clear(true);
1001
1002 for (uint32_t i = 0; i < cell_count; ++i) {
1003 auto & cell = cells[i];
1004
1005 llama_pos pos;
1006 uint32_t n_seq_id;
1007
1008 io.read(&pos, sizeof(pos));
1009 io.read(&n_seq_id, sizeof(n_seq_id));
1010
1011 cell.pos = pos;
1012
1013 for (uint32_t j = 0; j < n_seq_id; ++j) {
1014 llama_seq_id seq_id;
1015 io.read(&seq_id, sizeof(seq_id));
1016
1017 if (seq_id < 0 || (uint32_t) seq_id >= this->n_seq_max) {
1018 LLAMA_LOG_ERROR("%s: invalid seq_id, %d is out of range [0, %u)\n", __func__, seq_id, this->n_seq_max)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: invalid seq_id, %d is out of range [0, %u)\n"
, __func__, seq_id, this->n_seq_max)
;
1019 return false;
1020 }
1021
1022 cell.seq_id.insert(seq_id);
1023
1024 int32_t & tail = cells[seq_id].tail;
1025 if (tail != -1) {
1026 LLAMA_LOG_ERROR("%s: duplicate tail for seq_id %d in cell %d and %d\n", __func__, seq_id, i, tail)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: duplicate tail for seq_id %d in cell %d and %d\n"
, __func__, seq_id, i, tail)
;
1027 return false;
1028 }
1029 tail = i;
1030 }
1031 }
1032
1033 head = 0;
1034 used = cell_count;
1035 }
1036
1037 for (uint32_t i = 0; i < cell_count; ++i) {
1038 uint32_t cell_id = head + i;
1039 // make sure the recurrent states will keep their restored state
1040 cells[cell_id].src = cell_id;
1041 }
1042
1043 return true;
1044}
1045
1046bool llama_memory_recurrent::state_read_data(llama_io_read_i & io, uint32_t cell_count) {
1047 uint32_t s_trans;
1048 uint32_t n_layer;
1049 io.read(&s_trans, sizeof(s_trans));
1050 io.read(&n_layer, sizeof(n_layer));
1051
1052 if (n_layer != hparams.n_layer()) {
1053 LLAMA_LOG_ERROR("%s: mismatched layer count (%u instead of %u)\n", __func__, n_layer, hparams.n_layer())llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched layer count (%u instead of %u)\n"
, __func__, n_layer, hparams.n_layer())
;
1054 return false;
1055 }
1056 if (cell_count > size) {
1057 LLAMA_LOG_ERROR("%s: not enough cells in kv cache to restore state (%u > %u)\n", __func__, cell_count, size)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: not enough cells in kv cache to restore state (%u > %u)\n"
, __func__, cell_count, size)
;
1058 return false;
1059 }
1060 if (false != (bool) s_trans) {
1061 LLAMA_LOG_ERROR("%s: incompatible s transposition\n", __func__)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: incompatible s transposition\n"
, __func__)
;
1062 return false;
1063 }
1064
1065 // For each layer, read the keys for each cell, one row is one cell, read as one contiguous block
1066 for (uint32_t il = 0; il < n_layer; ++il) {
1067 // skip null layers
1068 if (r_l[il] == nullptr) continue;
1069
1070 // Read type of key
1071 int32_t r_type_i_ref;
1072 io.read(&r_type_i_ref, sizeof(r_type_i_ref));
1073 const int32_t r_type_i = (int32_t) r_l[il]->type;
1074 if (r_type_i != r_type_i_ref) {
1075 LLAMA_LOG_ERROR("%s: mismatched r type (%d != %d, layer %d)\n", __func__, r_type_i, r_type_i_ref, il)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched r type (%d != %d, layer %d)\n"
, __func__, r_type_i, r_type_i_ref, il)
;
1076 return false;
1077 }
1078
1079 // Read row size of key
1080 uint64_t r_size_row_ref;
1081 io.read(&r_size_row_ref, sizeof(r_size_row_ref));
1082 const size_t r_size_row = ggml_row_size(r_l[il]->type, hparams.n_embd_r());
1083 if (r_size_row != r_size_row_ref) {
1084 LLAMA_LOG_ERROR("%s: mismatched r row size (%zu != %zu, layer %d)\n", __func__, r_size_row, (size_t) r_size_row_ref, il)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched r row size (%zu != %zu, layer %d)\n"
, __func__, r_size_row, (size_t) r_size_row_ref, il)
;
1085 return false;
1086 }
1087
1088 if (cell_count) {
1089 // Read and set the keys for the whole cell range
1090 io.read_tensor(r_l[il], head * r_size_row, cell_count * r_size_row);
1091 }
1092 }
1093
1094 if (!s_trans) {
1095 for (uint32_t il = 0; il < n_layer; ++il) {
1096 // skip null layers
1097 if (s_l[il] == nullptr) continue;
1098
1099 // Read type of value
1100 int32_t s_type_i_ref;
1101 io.read(&s_type_i_ref, sizeof(s_type_i_ref));
1102 const int32_t s_type_i = (int32_t)s_l[il]->type;
1103
1104 if (s_type_i != s_type_i_ref) {
1105 LLAMA_LOG_ERROR("%s: mismatched s type (%d != %d, layer %d)\n", __func__, s_type_i, s_type_i_ref, il)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched s type (%d != %d, layer %d)\n"
, __func__, s_type_i, s_type_i_ref, il)
;
1106 return false;
1107 }
1108
1109 // Read row size of value
1110 uint64_t s_size_row_ref;
1111 io.read(&s_size_row_ref, sizeof(s_size_row_ref));
1112 const size_t s_size_row = ggml_row_size(s_l[il]->type, hparams.n_embd_s());
1113 if (s_size_row != s_size_row_ref) {
1114 LLAMA_LOG_ERROR("%s: mismatched s row size (%zu != %zu, layer %d)\n", __func__, s_size_row, (size_t) s_size_row_ref, il)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched s row size (%zu != %zu, layer %d)\n"
, __func__, s_size_row, (size_t) s_size_row_ref, il)
;
1115 return false;
1116 }
1117
1118 if (cell_count) {
1119 // Read and set the values for the whole cell range
1120 io.read_tensor(s_l[il], head * s_size_row, cell_count * s_size_row);
1121 }
1122 }
1123 } else {
1124 // For each layer, read the values for each cell (transposed)
1125 for (uint32_t il = 0; il < n_layer; ++il) {
1126 // skip null layers
1127 if (s_l[il] == nullptr) continue;
1128
1129 const uint32_t n_embd_s = hparams.n_embd_s();
1130
1131 // Read type of value
1132 int32_t s_type_i_ref;
1133 io.read(&s_type_i_ref, sizeof(s_type_i_ref));
1134 const int32_t s_type_i = (int32_t)s_l[il]->type;
1135 if (s_type_i != s_type_i_ref) {
1136 LLAMA_LOG_ERROR("%s: mismatched s type (%d != %d, layer %d)\n", __func__, s_type_i, s_type_i_ref, il)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched s type (%d != %d, layer %d)\n"
, __func__, s_type_i, s_type_i_ref, il)
;
1137 return false;
1138 }
1139
1140 // Read element size of value
1141 uint32_t s_size_el_ref;
1142 io.read(&s_size_el_ref, sizeof(s_size_el_ref));
1143 const size_t s_size_el = ggml_type_size(s_l[il]->type);
1144 if (s_size_el != s_size_el_ref) {
1145 LLAMA_LOG_ERROR("%s: mismatched s element size (%zu != %zu, layer %d)\n", __func__, s_size_el, (size_t) s_size_el_ref, il)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched s element size (%zu != %zu, layer %d)\n"
, __func__, s_size_el, (size_t) s_size_el_ref, il)
;
1146 return false;
1147 }
1148
1149 // Read state embedding size
1150 uint32_t n_embd_s_ref;
1151 io.read(&n_embd_s_ref, sizeof(n_embd_s_ref));
1152 if (n_embd_s != n_embd_s_ref) {
1153 LLAMA_LOG_ERROR("%s: mismatched s embedding size (%u != %u, layer %d)\n", __func__, n_embd_s, n_embd_s_ref, il)llama_log_internal(GGML_LOG_LEVEL_ERROR, "%s: mismatched s embedding size (%u != %u, layer %d)\n"
, __func__, n_embd_s, n_embd_s_ref, il)
;
1154 return false;
1155 }
1156
1157 if (cell_count) {
1158 // For each row in the transposed matrix, read the values for the whole cell range
1159 for (uint32_t j = 0; j < n_embd_s; ++j) {
1160 const size_t dst_offset = (head + j * size) * s_size_el;
1161 io.read_tensor(s_l[il], dst_offset, cell_count * s_size_el);
1162 }
1163 }
1164 }
1165 }
1166
1167 return true;
1168}
1169
1170//
1171// llama_memory_recurrent_context
1172//
1173
1174llama_memory_recurrent_context::llama_memory_recurrent_context(llama_memory_status status) : status(status) {}
1175
1176llama_memory_recurrent_context::llama_memory_recurrent_context(
1177 llama_memory_recurrent * mem) : status(LLAMA_MEMORY_STATUS_SUCCESS), mem(mem), is_full(true) {
1178}
1179
1180llama_memory_recurrent_context::llama_memory_recurrent_context(
1181 llama_memory_recurrent * mem,
1182 std::vector<llama_ubatch> ubatches) : status(LLAMA_MEMORY_STATUS_SUCCESS), mem(mem), ubatches(std::move(ubatches)) {}
1183
1184llama_memory_recurrent_context::~llama_memory_recurrent_context() = default;
1185
1186bool llama_memory_recurrent_context::next() {
1187 assert(status == LLAMA_MEMORY_STATUS_SUCCESS)(static_cast <bool> (status == LLAMA_MEMORY_STATUS_SUCCESS
) ? void (0) : __assert_fail ("status == LLAMA_MEMORY_STATUS_SUCCESS"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1188
1189 if (++i_next >= ubatches.size()) {
1190 return false;
1191 }
1192
1193 return true;
1194}
1195
1196bool llama_memory_recurrent_context::apply() {
1197 assert(!llama_memory_status_is_fail(status))(static_cast <bool> (!llama_memory_status_is_fail(status
)) ? void (0) : __assert_fail ("!llama_memory_status_is_fail(status)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1198
1199 // no ubatches -> this is an update
1200 if (ubatches.empty()) {
1201 // recurrent cache never performs updates
1202 assert(status == LLAMA_MEMORY_STATUS_NO_UPDATE)(static_cast <bool> (status == LLAMA_MEMORY_STATUS_NO_UPDATE
) ? void (0) : __assert_fail ("status == LLAMA_MEMORY_STATUS_NO_UPDATE"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1203
1204 return true;
1205 }
1206
1207 mem->find_slot(ubatches[i_next]);
1208
1209 return true;
1210}
1211
1212llama_memory_status llama_memory_recurrent_context::get_status() const {
1213 return status;
1214}
1215
1216const llama_ubatch & llama_memory_recurrent_context::get_ubatch() const {
1217 assert(status == LLAMA_MEMORY_STATUS_SUCCESS)(static_cast <bool> (status == LLAMA_MEMORY_STATUS_SUCCESS
) ? void (0) : __assert_fail ("status == LLAMA_MEMORY_STATUS_SUCCESS"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1218
1219 return ubatches[i_next];
1220}
1221
1222uint32_t llama_memory_recurrent_context::get_n_rs() const {
1223 return is_full ? mem->size : mem->n;
1224}
1225
1226uint32_t llama_memory_recurrent_context::get_head() const {
1227 return is_full ? 0 : mem->head;
1228}
1229
1230int32_t llama_memory_recurrent_context::get_rs_z() const {
1231 return is_full ? 0 : mem->rs_z;
1232}
1233
1234uint32_t llama_memory_recurrent_context::get_size() const {
1235 return mem->size;
1236}
1237
1238ggml_tensor * llama_memory_recurrent_context::get_r_l(int32_t il) const {
1239 return mem->r_l[il];
1240}
1241
1242ggml_tensor * llama_memory_recurrent_context::get_s_l(int32_t il) const {
1243 return mem->s_l[il];
1244}
1245
1246int32_t llama_memory_recurrent_context::s_copy(int i) const {
1247 const uint32_t cell_idx = i + mem->head;
1248 const int32_t src0 = mem->cells[cell_idx].src0;
1249
1250 if (mem->n_rs_seq == 0) {
1251 return src0;
1252 }
1253
1254 uint32_t idx = 0;
1255 if (!mem->cells[cell_idx].seq_id.empty()) {
1256 const llama_seq_id seq = *mem->cells[cell_idx].seq_id.begin();
1257 if (seq >= 0 && (size_t) seq < mem->rs_idx.size()) {
1258 idx = mem->rs_idx[seq];
1259 // reset rollback idx
1260 mem->rs_idx[seq] = 0;
1261 }
1262 }
1263 return (int32_t)(idx * mem->size) + src0;
1264}