Bug Summary

File:root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp
Warning:line 2049, column 9
Access to field 'view_src' results in a dereference of a null pointer (loaded from variable 'dst')

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 ggml-backend.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/ggml/src/ggml-backend.cpp

/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp

1// Note: porting this file to C++ is a work in progress
2
3#ifdef _WIN32
4#define WIN32_LEAN_AND_MEAN
5#ifndef NOMINMAX
6# define NOMINMAX
7#endif
8#include <windows.h>
9#endif
10
11#include "ggml-backend.h"
12#include "ggml-backend-impl.h"
13#include "ggml-alloc.h"
14#include "ggml-impl.h"
15
16#include <assert.h>
17#include <limits.h>
18#include <stdarg.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <algorithm>
23#include <vector>
24
25#ifdef __APPLE__
26#include <sys/types.h>
27#include <sys/sysctl.h>
28#endif
29
30
31// backend buffer type
32
33const char * ggml_backend_buft_name(ggml_backend_buffer_type_t buft) {
34 GGML_ASSERT(buft)if (!(buft)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 34, "GGML_ASSERT(%s) failed", "buft")
;
35 return buft->iface.get_name(buft);
36}
37
38ggml_backend_buffer_t ggml_backend_buft_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) {
39 GGML_ASSERT(buft)if (!(buft)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 39, "GGML_ASSERT(%s) failed", "buft")
;
40 if (size == 0) {
41 // return a dummy buffer for zero-sized allocations
42 return ggml_backend_buffer_init(buft, {}, NULL__null, 0);
43 }
44 return buft->iface.alloc_buffer(buft, size);
45}
46
47size_t ggml_backend_buft_get_alignment(ggml_backend_buffer_type_t buft) {
48 GGML_ASSERT(buft)if (!(buft)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 48, "GGML_ASSERT(%s) failed", "buft")
;
49 return buft->iface.get_alignment(buft);
50}
51
52size_t ggml_backend_buft_get_max_size(ggml_backend_buffer_type_t buft) {
53 GGML_ASSERT(buft)if (!(buft)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 53, "GGML_ASSERT(%s) failed", "buft")
;
54 // get_max_size is optional, defaults to SIZE_MAX
55 if (buft->iface.get_max_size) {
56 return buft->iface.get_max_size(buft);
57 }
58 return SIZE_MAX(18446744073709551615UL);
59}
60
61size_t ggml_backend_buft_get_alloc_size(ggml_backend_buffer_type_t buft, const struct ggml_tensor * tensor) {
62 GGML_ASSERT(buft)if (!(buft)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 62, "GGML_ASSERT(%s) failed", "buft")
;
63 // get_alloc_size is optional, defaults to ggml_nbytes
64 if (buft->iface.get_alloc_size) {
65 size_t size = buft->iface.get_alloc_size(buft, tensor);
66 assert(size >= ggml_nbytes(tensor))(static_cast <bool> (size >= ggml_nbytes(tensor)) ? void
(0) : __assert_fail ("size >= ggml_nbytes(tensor)", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
67 return size;
68 }
69 return ggml_nbytes(tensor);
70}
71
72bool ggml_backend_buft_is_host(ggml_backend_buffer_type_t buft) {
73 GGML_ASSERT(buft)if (!(buft)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 73, "GGML_ASSERT(%s) failed", "buft")
;
74 if (buft->iface.is_host) {
75 return buft->iface.is_host(buft);
76 }
77 return false;
78}
79
80ggml_backend_dev_t ggml_backend_buft_get_device(ggml_backend_buffer_type_t buft) {
81 GGML_ASSERT(buft)if (!(buft)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 81, "GGML_ASSERT(%s) failed", "buft")
;
82 return buft->device;
83}
84
85// backend buffer
86
87ggml_backend_buffer_t ggml_backend_buffer_init(
88 ggml_backend_buffer_type_t buft,
89 struct ggml_backend_buffer_i iface,
90 void * context,
91 size_t size) {
92 ggml_backend_buffer_t buffer = new ggml_backend_buffer {
93 /* .interface = */ iface,
94 /* .buft = */ buft,
95 /* .context = */ context,
96 /* .size = */ size,
97 /* .usage = */ GGML_BACKEND_BUFFER_USAGE_ANY
98 };
99
100 return buffer;
101}
102
103const char * ggml_backend_buffer_name(ggml_backend_buffer_t buffer) {
104 return ggml_backend_buft_name(ggml_backend_buffer_get_type(buffer));
105}
106
107void ggml_backend_buffer_free(ggml_backend_buffer_t buffer) {
108 if (buffer == NULL__null) {
109 return;
110 }
111
112 if (buffer->iface.free_buffer != NULL__null) {
113 buffer->iface.free_buffer(buffer);
114 }
115 delete buffer;
116}
117
118size_t ggml_backend_buffer_get_size(ggml_backend_buffer_t buffer) {
119 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 119, "GGML_ASSERT(%s) failed", "buffer")
;
120 return buffer->size;
121}
122
123void * ggml_backend_buffer_get_base(ggml_backend_buffer_t buffer) {
124 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 124, "GGML_ASSERT(%s) failed", "buffer")
;
125 // get_base is optional if the buffer is zero-sized
126 if (!ggml_backend_buffer_is_meta(buffer) && buffer->size == 0) {
127 return NULL__null;
128 }
129
130 // FIXME JG: a multi_buffer has a non-zero size, according to the above comment get_base is not optional,
131 // I don't know whether the above comment is correct
132 if (!buffer->iface.get_base) {
133 return NULL__null;
134 }
135
136 void * base = buffer->iface.get_base(buffer);
137
138 GGML_ASSERT(base != NULL && "backend buffer base cannot be NULL")if (!(base != __null && "backend buffer base cannot be NULL"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 138, "GGML_ASSERT(%s) failed", "base != NULL && \"backend buffer base cannot be NULL\""
)
;
139
140 return base;
141}
142
143enum ggml_status ggml_backend_buffer_init_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor) {
144 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 144, "GGML_ASSERT(%s) failed", "buffer")
;
145 // init_tensor is optional
146 if (buffer->iface.init_tensor) {
147 return buffer->iface.init_tensor(buffer, tensor);
148 }
149 return GGML_STATUS_SUCCESS;
150}
151
152void ggml_backend_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
153 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 153, "GGML_ASSERT(%s) failed", "buffer")
;
154 // clear is optional if the buffer is zero-sized
155 if (buffer->size == 0) {
156 return;
157 }
158
159 buffer->iface.clear(buffer, value);
160}
161
162size_t ggml_backend_buffer_get_alignment(ggml_backend_buffer_t buffer) {
163 return ggml_backend_buft_get_alignment(ggml_backend_buffer_get_type(buffer));
164}
165
166size_t ggml_backend_buffer_get_max_size(ggml_backend_buffer_t buffer) {
167 return ggml_backend_buft_get_max_size(ggml_backend_buffer_get_type(buffer));
168}
169
170size_t ggml_backend_buffer_get_alloc_size(ggml_backend_buffer_t buffer, const struct ggml_tensor * tensor) {
171 return ggml_backend_buft_get_alloc_size(ggml_backend_buffer_get_type(buffer), tensor);
172}
173
174bool ggml_backend_buffer_is_host(ggml_backend_buffer_t buffer) {
175 return ggml_backend_buft_is_host(ggml_backend_buffer_get_type(buffer));
176}
177
178void ggml_backend_buffer_set_usage(ggml_backend_buffer_t buffer, enum ggml_backend_buffer_usage usage) {
179 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 179, "GGML_ASSERT(%s) failed", "buffer")
;
180 buffer->usage = usage;
181
182 // FIXME: add a generic callback to the buffer interface
183 if (ggml_backend_buffer_is_multi_buffer(buffer)) {
184 ggml_backend_multi_buffer_set_usage(buffer, usage);
185 }
186}
187
188enum ggml_backend_buffer_usage ggml_backend_buffer_get_usage(ggml_backend_buffer_t buffer) {
189 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 189, "GGML_ASSERT(%s) failed", "buffer")
;
190 return buffer->usage;
191}
192
193ggml_backend_buffer_type_t ggml_backend_buffer_get_type(ggml_backend_buffer_t buffer) {
194 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 194, "GGML_ASSERT(%s) failed", "buffer")
;
195 return buffer->buft;
196}
197
198void ggml_backend_buffer_reset(ggml_backend_buffer_t buffer) {
199 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 199, "GGML_ASSERT(%s) failed", "buffer")
;
200 if (buffer->iface.reset) {
201 buffer->iface.reset(buffer);
202 }
203}
204
205bool ggml_backend_buffer_copy_tensor(const struct ggml_tensor * src, struct ggml_tensor * dst) {
206 ggml_backend_buffer_t dst_buf = dst->view_src ? dst->view_src->buffer : dst->buffer;
207 if (dst_buf->iface.cpy_tensor) {
208 return dst_buf->iface.cpy_tensor(dst_buf, src, dst);
209 }
210 return false;
211}
212
213// backend
214
215ggml_guid_t ggml_backend_guid(ggml_backend_t backend) {
216 if (backend == NULL__null) {
217 return NULL__null;
218 }
219 return backend->guid;
220}
221
222const char * ggml_backend_name(ggml_backend_t backend) {
223 if (backend == NULL__null) {
224 return "NULL";
225 }
226 return backend->iface.get_name(backend);
227}
228
229void ggml_backend_free(ggml_backend_t backend) {
230 if (backend == NULL__null) {
231 return;
232 }
233
234 backend->iface.free(backend);
235}
236
237ggml_backend_buffer_type_t ggml_backend_get_default_buffer_type(ggml_backend_t backend) {
238 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 238, "GGML_ASSERT(%s) failed", "backend")
;
239 return ggml_backend_dev_buffer_type(backend->device);
240}
241
242ggml_backend_buffer_t ggml_backend_alloc_buffer(ggml_backend_t backend, size_t size) {
243 return ggml_backend_buft_alloc_buffer(ggml_backend_get_default_buffer_type(backend), size);
244}
245
246size_t ggml_backend_get_alignment(ggml_backend_t backend) {
247 return ggml_backend_buft_get_alignment(ggml_backend_get_default_buffer_type(backend));
248}
249
250size_t ggml_backend_get_max_size(ggml_backend_t backend) {
251 return ggml_backend_buft_get_max_size(ggml_backend_get_default_buffer_type(backend));
252}
253
254void ggml_backend_tensor_set_async(ggml_backend_t backend, struct ggml_tensor * tensor, const void * data, size_t offset, size_t size) {
255 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 255, "GGML_ASSERT(%s) failed", "backend")
;
256 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 256, "GGML_ASSERT(%s) failed", "tensor")
;
257 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 257, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
258 GGML_ASSERT(offset + size <= ggml_nbytes(tensor) && "tensor write out of bounds")if (!(offset + size <= ggml_nbytes(tensor) && "tensor write out of bounds"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 258, "GGML_ASSERT(%s) failed", "offset + size <= ggml_nbytes(tensor) && \"tensor write out of bounds\""
)
;
259
260 if (backend->iface.set_tensor_async == NULL__null) {
261 ggml_backend_synchronize(backend);
262 ggml_backend_tensor_set(tensor, data, offset, size);
263 } else {
264 backend->iface.set_tensor_async(backend, tensor, data, offset, size);
265 }
266}
267
268void ggml_backend_tensor_get_async(ggml_backend_t backend, const struct ggml_tensor * tensor, void * data, size_t offset, size_t size) {
269 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 269, "GGML_ASSERT(%s) failed", "backend")
;
270 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 270, "GGML_ASSERT(%s) failed", "tensor")
;
271 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 271, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
272 GGML_ASSERT(offset + size <= ggml_nbytes(tensor) && "tensor read out of bounds")if (!(offset + size <= ggml_nbytes(tensor) && "tensor read out of bounds"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 272, "GGML_ASSERT(%s) failed", "offset + size <= ggml_nbytes(tensor) && \"tensor read out of bounds\""
)
;
273
274 if (backend->iface.get_tensor_async == NULL__null) {
275 ggml_backend_synchronize(backend);
276 ggml_backend_tensor_get(tensor, data, offset, size);
277 } else {
278 backend->iface.get_tensor_async(backend, tensor, data, offset, size);
279 }
280}
281
282void ggml_backend_tensor_set_2d_async(ggml_backend_t backend, struct ggml_tensor * tensor, const void * data, size_t offset, size_t size,
283 size_t n_copies, size_t stride_tensor, size_t stride_data) {
284 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 284, "GGML_ASSERT(%s) failed", "backend")
;
285 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 285, "GGML_ASSERT(%s) failed", "tensor")
;
286 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 286, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
287
288 if (n_copies <= 1 || backend->iface.set_tensor_2d_async == NULL__null) {
289 for (size_t i = 0; i < n_copies; i++) {
290 ggml_backend_tensor_set_async(backend, tensor, (const char *) data + i*stride_data, offset + i*stride_tensor, size);
291 }
292 return;
293 }
294 if (size == 0) {
295 return;
296 }
297
298 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 298, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
299 GGML_ASSERT(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && "tensor write out of bounds")if (!(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes
(tensor) && "tensor write out of bounds")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 299, "GGML_ASSERT(%s) failed", "offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && \"tensor write out of bounds\""
)
;
300 backend->iface.set_tensor_2d_async(backend, tensor, data, offset, size, n_copies, stride_tensor, stride_data);
301}
302
303void ggml_backend_tensor_get_2d_async(ggml_backend_t backend, const struct ggml_tensor * tensor, void * data, size_t offset, size_t size,
304 size_t n_copies, size_t stride_tensor, size_t stride_data) {
305 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 305, "GGML_ASSERT(%s) failed", "backend")
;
306 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 306, "GGML_ASSERT(%s) failed", "tensor")
;
307 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 307, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
308
309 if (n_copies <= 1 || backend->iface.get_tensor_2d_async == NULL__null) {
310 for (size_t i = 0; i < n_copies; i++) {
311 ggml_backend_tensor_get_async(backend, tensor, (char *) data + i*stride_data, offset + i*stride_tensor, size);
312 }
313 return;
314 }
315 if (size == 0) {
316 return;
317 }
318
319 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 319, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
320 GGML_ASSERT(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && "tensor read out of bounds")if (!(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes
(tensor) && "tensor read out of bounds")) ggml_abort(
"/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 320, "GGML_ASSERT(%s) failed", "offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && \"tensor read out of bounds\""
)
;
321 backend->iface.get_tensor_2d_async(backend, tensor, data, offset, size, n_copies, stride_tensor, stride_data);
322}
323
324void ggml_backend_tensor_set(struct ggml_tensor * tensor, const void * data, size_t offset, size_t size) {
325 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 325, "GGML_ASSERT(%s) failed", "tensor")
;
326 ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
327 GGML_ASSERT(buf != NULL && "tensor buffer not set")if (!(buf != __null && "tensor buffer not set")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 327, "GGML_ASSERT(%s) failed", "buf != NULL && \"tensor buffer not set\""
)
;
328
329 if (size == 0) {
330 return;
331 }
332
333 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 333, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
334 GGML_ASSERT(offset + size <= ggml_nbytes(tensor) && "tensor write out of bounds")if (!(offset + size <= ggml_nbytes(tensor) && "tensor write out of bounds"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 334, "GGML_ASSERT(%s) failed", "offset + size <= ggml_nbytes(tensor) && \"tensor write out of bounds\""
)
;
335
336 buf->iface.set_tensor(buf, tensor, data, offset, size);
337}
338
339void ggml_backend_tensor_get(const struct ggml_tensor * tensor, void * data, size_t offset, size_t size) {
340 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 340, "GGML_ASSERT(%s) failed", "tensor")
;
341 ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
342 GGML_ASSERT(buf != NULL && "tensor buffer not set")if (!(buf != __null && "tensor buffer not set")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 342, "GGML_ASSERT(%s) failed", "buf != NULL && \"tensor buffer not set\""
)
;
343
344 if (size == 0) {
345 return;
346 }
347
348 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 348, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
349 GGML_ASSERT(offset + size <= ggml_nbytes(tensor) && "tensor read out of bounds")if (!(offset + size <= ggml_nbytes(tensor) && "tensor read out of bounds"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 349, "GGML_ASSERT(%s) failed", "offset + size <= ggml_nbytes(tensor) && \"tensor read out of bounds\""
)
;
350
351 buf->iface.get_tensor(buf, tensor, data, offset, size);
352}
353
354void ggml_backend_tensor_set_2d(struct ggml_tensor * tensor, const void * data, size_t offset, size_t size,
355 size_t n_copies, size_t stride_tensor, size_t stride_data) {
356 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 356, "GGML_ASSERT(%s) failed", "tensor")
;
357 ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
358 GGML_ASSERT(buf != NULL && "tensor buffer not set")if (!(buf != __null && "tensor buffer not set")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 358, "GGML_ASSERT(%s) failed", "buf != NULL && \"tensor buffer not set\""
)
;
359
360 if (n_copies <= 1 || buf->iface.set_tensor_2d == NULL__null) {
361 for (size_t i = 0; i < n_copies; i++) {
362 ggml_backend_tensor_set(tensor, (const char *) data + i*stride_data, offset + i*stride_tensor, size);
363 }
364 return;
365 }
366 if (size == 0) {
367 return;
368 }
369
370 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 370, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
371 GGML_ASSERT(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && "tensor write out of bounds")if (!(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes
(tensor) && "tensor write out of bounds")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 371, "GGML_ASSERT(%s) failed", "offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && \"tensor write out of bounds\""
)
;
372
373 buf->iface.set_tensor_2d(buf, tensor, data, offset, size, n_copies, stride_tensor, stride_data);
374}
375
376void ggml_backend_tensor_get_2d(const struct ggml_tensor * tensor, void * data, size_t offset, size_t size,
377 size_t n_copies, size_t stride_tensor, size_t stride_data) {
378 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 378, "GGML_ASSERT(%s) failed", "tensor")
;
379 ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
380 GGML_ASSERT(buf != NULL && "tensor buffer not set")if (!(buf != __null && "tensor buffer not set")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 380, "GGML_ASSERT(%s) failed", "buf != NULL && \"tensor buffer not set\""
)
;
381
382 if (n_copies <= 1 || buf->iface.get_tensor_2d == NULL__null) {
383 for (size_t i = 0; i < n_copies; i++) {
384 ggml_backend_tensor_get(tensor, (char *) data + i*stride_data, offset + i*stride_tensor, size);
385 }
386 return;
387 }
388 if (size == 0) {
389 return;
390 }
391
392 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 392, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
393 GGML_ASSERT(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && "tensor read out of bounds")if (!(offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes
(tensor) && "tensor read out of bounds")) ggml_abort(
"/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 393, "GGML_ASSERT(%s) failed", "offset + (n_copies-1)*stride_tensor + size <= ggml_nbytes(tensor) && \"tensor read out of bounds\""
)
;
394
395 buf->iface.get_tensor_2d(buf, tensor, data, offset, size, n_copies, stride_tensor, stride_data);
396}
397
398void ggml_backend_tensor_memset(struct ggml_tensor * tensor, uint8_t value, size_t offset, size_t size) {
399 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 399, "GGML_ASSERT(%s) failed", "tensor")
;
400 ggml_backend_buffer_t buf = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
401
402 if (size == 0) {
403 return;
404 }
405
406 GGML_ASSERT(buf != NULL && "tensor buffer not set")if (!(buf != __null && "tensor buffer not set")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 406, "GGML_ASSERT(%s) failed", "buf != NULL && \"tensor buffer not set\""
)
;
407 GGML_ASSERT(tensor->data != NULL && "tensor not allocated")if (!(tensor->data != __null && "tensor not allocated"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 407, "GGML_ASSERT(%s) failed", "tensor->data != NULL && \"tensor not allocated\""
)
;
408 GGML_ASSERT(offset + size <= ggml_nbytes(tensor) && "tensor write out of bounds")if (!(offset + size <= ggml_nbytes(tensor) && "tensor write out of bounds"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 408, "GGML_ASSERT(%s) failed", "offset + size <= ggml_nbytes(tensor) && \"tensor write out of bounds\""
)
;
409 GGML_ASSERT(buf->iface.memset_tensor != NULL && "memset not implemented by backend buffer")if (!(buf->iface.memset_tensor != __null && "memset not implemented by backend buffer"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 409, "GGML_ASSERT(%s) failed", "buf->iface.memset_tensor != NULL && \"memset not implemented by backend buffer\""
)
;
410
411 buf->iface.memset_tensor(buf, tensor, value, offset, size);
412}
413
414void ggml_backend_synchronize(ggml_backend_t backend) {
415 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 415, "GGML_ASSERT(%s) failed", "backend")
;
416 if (backend->iface.synchronize == NULL__null) {
417 return;
418 }
419
420 backend->iface.synchronize(backend);
421}
422
423ggml_backend_graph_plan_t ggml_backend_graph_plan_create(ggml_backend_t backend, struct ggml_cgraph * cgraph) {
424 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 424, "GGML_ASSERT(%s) failed", "backend")
;
425 GGML_ASSERT(backend->iface.graph_plan_create != NULL)if (!(backend->iface.graph_plan_create != __null)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 425, "GGML_ASSERT(%s) failed", "backend->iface.graph_plan_create != NULL"
)
;
426
427 return backend->iface.graph_plan_create(backend, cgraph);
428}
429
430void ggml_backend_graph_plan_free(ggml_backend_t backend, ggml_backend_graph_plan_t plan) {
431 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 431, "GGML_ASSERT(%s) failed", "backend")
;
432 GGML_ASSERT(backend->iface.graph_plan_free != NULL)if (!(backend->iface.graph_plan_free != __null)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 432, "GGML_ASSERT(%s) failed", "backend->iface.graph_plan_free != NULL"
)
;
433
434 backend->iface.graph_plan_free(backend, plan);
435}
436
437enum ggml_status ggml_backend_graph_plan_compute(ggml_backend_t backend, ggml_backend_graph_plan_t plan) {
438 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 438, "GGML_ASSERT(%s) failed", "backend")
;
439 GGML_ASSERT(backend->iface.graph_plan_compute != NULL)if (!(backend->iface.graph_plan_compute != __null)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 439, "GGML_ASSERT(%s) failed", "backend->iface.graph_plan_compute != NULL"
)
;
440
441 return backend->iface.graph_plan_compute(backend, plan);
442}
443
444enum ggml_status ggml_backend_graph_compute(ggml_backend_t backend, struct ggml_cgraph * cgraph) {
445 enum ggml_status err = ggml_backend_graph_compute_async(backend, cgraph);
446 ggml_backend_synchronize(backend);
447 return err;
448}
449
450enum ggml_status ggml_backend_graph_compute_async(ggml_backend_t backend, struct ggml_cgraph * cgraph) {
451 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 451, "GGML_ASSERT(%s) failed", "backend")
;
452 return backend->iface.graph_compute(backend, cgraph);
453}
454
455bool ggml_backend_supports_op(ggml_backend_t backend, const struct ggml_tensor * op) {
456 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 456, "GGML_ASSERT(%s) failed", "backend")
;
457 return ggml_backend_dev_supports_op(backend->device, op);
458}
459
460bool ggml_backend_supports_buft(ggml_backend_t backend, ggml_backend_buffer_type_t buft) {
461 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 461, "GGML_ASSERT(%s) failed", "backend")
;
462 return ggml_backend_dev_supports_buft(backend->device, buft);
463}
464
465bool ggml_backend_offload_op(ggml_backend_t backend, const struct ggml_tensor * op) {
466 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 466, "GGML_ASSERT(%s) failed", "backend")
;
467 return ggml_backend_dev_offload_op(backend->device, op);
468}
469
470ggml_backend_dev_t ggml_backend_get_device(ggml_backend_t backend) {
471 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 471, "GGML_ASSERT(%s) failed", "backend")
;
472 return backend->device;
473}
474
475// backend copy
476
477void ggml_backend_tensor_copy(const struct ggml_tensor * src, struct ggml_tensor * dst) {
478 GGML_ASSERT(ggml_are_same_layout(src, dst) && "cannot copy tensors with different layouts")if (!(ggml_are_same_layout(src, dst) && "cannot copy tensors with different layouts"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 478, "GGML_ASSERT(%s) failed", "ggml_are_same_layout(src, dst) && \"cannot copy tensors with different layouts\""
)
;
479
480 if (src == dst) {
481 return;
482 }
483
484 if (ggml_backend_buffer_is_host(src->buffer)) {
485 ggml_backend_tensor_set(dst, src->data, 0, ggml_nbytes(src));
486 } else if (ggml_backend_buffer_is_host(dst->buffer)) {
487 ggml_backend_tensor_get(src, dst->data, 0, ggml_nbytes(src));
488 } else if (!ggml_backend_buffer_copy_tensor(src, dst)) {
489#ifndef NDEBUG
490 GGML_LOG_DEBUG("%s: warning: slow copy from %s to %s\n", __func__, ggml_backend_buffer_name(src->buffer), ggml_backend_buffer_name(dst->buffer))ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "%s: warning: slow copy from %s to %s\n"
, __func__, ggml_backend_buffer_name(src->buffer), ggml_backend_buffer_name
(dst->buffer))
;
491#endif // NDEBUG
492 size_t nbytes = ggml_nbytes(src);
493 void * data = malloc(nbytes);
494 ggml_backend_tensor_get(src, data, 0, nbytes);
495 ggml_backend_tensor_set(dst, data, 0, nbytes);
496 free(data);
497 }
498}
499
500void ggml_backend_tensor_copy_async(ggml_backend_t backend_src, ggml_backend_t backend_dst, const struct ggml_tensor * src, struct ggml_tensor * dst) {
501 GGML_ASSERT(ggml_are_same_layout(src, dst) && "cannot copy tensors with different layouts")if (!(ggml_are_same_layout(src, dst) && "cannot copy tensors with different layouts"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 501, "GGML_ASSERT(%s) failed", "ggml_are_same_layout(src, dst) && \"cannot copy tensors with different layouts\""
)
;
502
503 if (src == dst) {
504 return;
505 }
506
507 GGML_ASSERT(backend_dst)if (!(backend_dst)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 507, "GGML_ASSERT(%s) failed", "backend_dst")
;
508 if (backend_dst->iface.cpy_tensor_async != NULL__null) {
509 if (backend_dst->iface.cpy_tensor_async(backend_src, backend_dst, src, dst)) {
510 return;
511 }
512 }
513
514 // an async copy would normally happen after all the queued operations on both backends are completed
515 // to simulate the same behavior, we need to synchronize both backends first, and do a blocking copy
516 ggml_backend_synchronize(backend_src);
517 ggml_backend_synchronize(backend_dst);
518 ggml_backend_tensor_copy(src, dst);
519}
520
521// events
522
523ggml_backend_event_t ggml_backend_event_new(ggml_backend_dev_t device) {
524 // null device is allowed for the transition period to the device interface
525 if (device == NULL__null || device->iface.event_new == NULL__null) {
526 return NULL__null;
527 }
528 return device->iface.event_new(device);
529}
530
531void ggml_backend_event_free(ggml_backend_event_t event) {
532 if (event == NULL__null) {
533 return;
534 }
535 event->device->iface.event_free(event->device, event);
536}
537
538void ggml_backend_event_record(ggml_backend_event_t event, ggml_backend_t backend) {
539 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 539, "GGML_ASSERT(%s) failed", "backend")
;
540 GGML_ASSERT(backend->iface.event_record != NULL)if (!(backend->iface.event_record != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 540, "GGML_ASSERT(%s) failed", "backend->iface.event_record != NULL"
)
;
541
542 backend->iface.event_record(backend, event);
543}
544
545void ggml_backend_event_synchronize(ggml_backend_event_t event) {
546 GGML_ASSERT(event)if (!(event)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 546, "GGML_ASSERT(%s) failed", "event")
;
547 GGML_ASSERT(event->device->iface.event_synchronize)if (!(event->device->iface.event_synchronize)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 547, "GGML_ASSERT(%s) failed", "event->device->iface.event_synchronize"
)
;
548
549 event->device->iface.event_synchronize(event->device, event);
550}
551
552void ggml_backend_event_wait(ggml_backend_t backend, ggml_backend_event_t event) {
553 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 553, "GGML_ASSERT(%s) failed", "backend")
;
554 GGML_ASSERT(backend->iface.event_wait != NULL)if (!(backend->iface.event_wait != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 554, "GGML_ASSERT(%s) failed", "backend->iface.event_wait != NULL"
)
;
555
556 backend->iface.event_wait(backend, event);
557}
558
559static void ggml_backend_graph_optimize(ggml_backend_t backend, struct ggml_cgraph * cgraph) {
560 GGML_ASSERT(backend)if (!(backend)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 560, "GGML_ASSERT(%s) failed", "backend")
;
561 if (backend->iface.graph_optimize != NULL__null) {
562 backend->iface.graph_optimize(backend, cgraph);
563 }
564}
565
566// Backend device
567
568const char * ggml_backend_dev_name(ggml_backend_dev_t device) {
569 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 569, "GGML_ASSERT(%s) failed", "device")
;
570 return device->iface.get_name(device);
571}
572
573const char * ggml_backend_dev_description(ggml_backend_dev_t device) {
574 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 574, "GGML_ASSERT(%s) failed", "device")
;
575 return device->iface.get_description(device);
576}
577
578void ggml_backend_dev_memory(ggml_backend_dev_t device, size_t * free, size_t * total) {
579 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 579, "GGML_ASSERT(%s) failed", "device")
;
580 device->iface.get_memory(device, free, total);
581}
582
583enum ggml_backend_dev_type ggml_backend_dev_type(ggml_backend_dev_t device) {
584 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 584, "GGML_ASSERT(%s) failed", "device")
;
585 return device->iface.get_type(device);
586}
587
588void ggml_backend_dev_get_props(ggml_backend_dev_t device, struct ggml_backend_dev_props * props) {
589 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 589, "GGML_ASSERT(%s) failed", "device")
;
590 memset(props, 0, sizeof(*props));
591 device->iface.get_props(device, props);
592}
593
594ggml_backend_reg_t ggml_backend_dev_backend_reg(ggml_backend_dev_t device) {
595 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 595, "GGML_ASSERT(%s) failed", "device")
;
596 return device->reg;
597}
598
599ggml_backend_t ggml_backend_dev_init(ggml_backend_dev_t device, const char * params) {
600 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 600, "GGML_ASSERT(%s) failed", "device")
;
601 return device->iface.init_backend(device, params);
602}
603
604ggml_backend_buffer_type_t ggml_backend_dev_buffer_type(ggml_backend_dev_t device) {
605 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 605, "GGML_ASSERT(%s) failed", "device")
;
606 return device->iface.get_buffer_type(device);
607}
608
609ggml_backend_buffer_type_t ggml_backend_dev_host_buffer_type(ggml_backend_dev_t device) {
610 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 610, "GGML_ASSERT(%s) failed", "device")
;
611 if (device->iface.get_host_buffer_type == NULL__null) {
612 return NULL__null;
613 }
614
615 return device->iface.get_host_buffer_type(device);
616}
617
618ggml_backend_buffer_t ggml_backend_dev_buffer_from_host_ptr(ggml_backend_dev_t device, void * ptr, size_t size, size_t max_tensor_size) {
619 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 619, "GGML_ASSERT(%s) failed", "device")
;
620 return device->iface.buffer_from_host_ptr(device, ptr, size, max_tensor_size);
621}
622
623bool ggml_backend_dev_supports_op(ggml_backend_dev_t device, const struct ggml_tensor * op) {
624 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 624, "GGML_ASSERT(%s) failed", "device")
;
625 return device->iface.supports_op(device, op);
626}
627
628bool ggml_backend_dev_supports_buft(ggml_backend_dev_t device, ggml_backend_buffer_type_t buft) {
629 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 629, "GGML_ASSERT(%s) failed", "device")
;
630 return device->iface.supports_buft(device, buft);
631}
632
633bool ggml_backend_dev_offload_op(ggml_backend_dev_t device, const struct ggml_tensor * op) {
634 GGML_ASSERT(device)if (!(device)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 634, "GGML_ASSERT(%s) failed", "device")
;
635 if (device->iface.offload_op != NULL__null) {
636 return device->iface.offload_op(device, op);
637 }
638
639 return false;
640}
641
642// Backend (reg)
643
644const char * ggml_backend_reg_name(ggml_backend_reg_t reg) {
645 GGML_ASSERT(reg)if (!(reg)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 645, "GGML_ASSERT(%s) failed", "reg")
;
646 return reg->iface.get_name(reg);
647}
648
649size_t ggml_backend_reg_dev_count(ggml_backend_reg_t reg) {
650 GGML_ASSERT(reg)if (!(reg)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 650, "GGML_ASSERT(%s) failed", "reg")
;
651 return reg->iface.get_device_count(reg);
652}
653
654ggml_backend_dev_t ggml_backend_reg_dev_get(ggml_backend_reg_t reg, size_t index) {
655 GGML_ASSERT(reg)if (!(reg)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 655, "GGML_ASSERT(%s) failed", "reg")
;
656 return reg->iface.get_device(reg, index);
657}
658
659void * ggml_backend_reg_get_proc_address(ggml_backend_reg_t reg, const char * name) {
660 GGML_ASSERT(reg)if (!(reg)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 660, "GGML_ASSERT(%s) failed", "reg")
;
661 if (!reg->iface.get_proc_address) {
662 return NULL__null;
663 }
664 return reg->iface.get_proc_address(reg, name);
665}
666
667// multi-buffer buffer
668
669struct ggml_backend_multi_buffer_context {
670 ggml_backend_buffer_t * buffers;
671 size_t n_buffers;
672};
673
674static void ggml_backend_multi_buffer_free_buffer(ggml_backend_buffer_t buffer) {
675 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 675, "GGML_ASSERT(%s) failed", "buffer")
;
676 ggml_backend_multi_buffer_context * ctx = (ggml_backend_multi_buffer_context *) buffer->context;
677 for (size_t i = 0; i < ctx->n_buffers; i++) {
678 ggml_backend_buffer_free(ctx->buffers[i]);
679 }
680
681 free(ctx->buffers);
682 free(ctx);
683}
684
685static void ggml_backend_multi_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
686 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 686, "GGML_ASSERT(%s) failed", "buffer")
;
687 ggml_backend_multi_buffer_context * ctx = (ggml_backend_multi_buffer_context *) buffer->context;
688 for (size_t i = 0; i < ctx->n_buffers; i++) {
689 ggml_backend_buffer_clear(ctx->buffers[i], value);
690 }
691}
692
693static const struct ggml_backend_buffer_i ggml_backend_multi_buffer_i = {
694 /* .free_buffer = */ ggml_backend_multi_buffer_free_buffer,
695 /* .get_base = */ NULL__null,
696 /* .init_tensor = */ NULL__null,
697 /* .memset_tensor = */ NULL__null,
698 /* .set_tensor = */ NULL__null,
699 /* .get_tensor = */ NULL__null,
700 /* .set_tensor_2d = */ NULL__null,
701 /* .get_tensor_2d = */ NULL__null,
702 /* .cpy_tensor = */ NULL__null,
703 /* .clear = */ ggml_backend_multi_buffer_clear,
704 /* .reset = */ NULL__null,
705};
706
707ggml_backend_buffer_t ggml_backend_multi_buffer_alloc_buffer(ggml_backend_buffer_t * buffers, size_t n_buffers) {
708 ggml_backend_multi_buffer_context * ctx = (ggml_backend_multi_buffer_context *) malloc(sizeof(struct ggml_backend_multi_buffer_context));
709 ctx->n_buffers = n_buffers;
710 ctx->buffers = (ggml_backend_buffer_t *) malloc(n_buffers * sizeof(ggml_backend_buffer_t));
711
712 GGML_ASSERT(ctx->buffers != NULL)if (!(ctx->buffers != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 712, "GGML_ASSERT(%s) failed", "ctx->buffers != NULL")
;
713
714 size_t total_size = 0;
715 for (size_t i = 0; i < n_buffers; i++) {
716 ctx->buffers[i] = buffers[i];
717 total_size += ggml_backend_buffer_get_size(buffers[i]);
718 }
719
720 return ggml_backend_buffer_init(buffers[0]->buft, ggml_backend_multi_buffer_i, ctx, total_size);
721}
722
723bool ggml_backend_buffer_is_multi_buffer(ggml_backend_buffer_t buffer) {
724 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 724, "GGML_ASSERT(%s) failed", "buffer")
;
725 return buffer->iface.free_buffer == ggml_backend_multi_buffer_free_buffer;
726}
727
728void ggml_backend_multi_buffer_set_usage(ggml_backend_buffer_t buffer, enum ggml_backend_buffer_usage usage) {
729 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 729, "GGML_ASSERT(%s) failed", "buffer")
;
730 GGML_ASSERT(ggml_backend_buffer_is_multi_buffer(buffer))if (!(ggml_backend_buffer_is_multi_buffer(buffer))) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 730, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_multi_buffer(buffer)"
)
;
731 ggml_backend_multi_buffer_context * ctx = (ggml_backend_multi_buffer_context *) buffer->context;
732 for (size_t i = 0; i < ctx->n_buffers; i++) {
733 ggml_backend_buffer_set_usage(ctx->buffers[i], usage);
734 }
735}
736
737// creates a copy of the tensor with the same memory layout
738static struct ggml_tensor * ggml_dup_tensor_layout(struct ggml_context * ctx, const struct ggml_tensor * tensor) {
739 struct ggml_tensor * dup = ggml_dup_tensor(ctx, tensor);
740 for (int i = 0; i < GGML_MAX_DIMS4; i++) {
741 dup->nb[i] = tensor->nb[i];
742 }
743 return dup;
744}
745
746static bool ggml_is_view_op(enum ggml_op op) {
747 return op == GGML_OP_VIEW || op == GGML_OP_RESHAPE || op == GGML_OP_PERMUTE || op == GGML_OP_TRANSPOSE;
748}
749
750// scheduler
751
752#ifndef GGML_SCHED_MAX_BACKENDS16
753#define GGML_SCHED_MAX_BACKENDS16 16
754#endif
755
756#ifndef GGML_SCHED_MAX_SPLIT_INPUTS30
757#define GGML_SCHED_MAX_SPLIT_INPUTS30 30
758#endif
759
760#ifndef GGML_SCHED_MAX_COPIES4
761#define GGML_SCHED_MAX_COPIES4 4
762#endif
763
764struct ggml_backend_sched_split {
765 int backend_id;
766 int i_start;
767 int i_end;
768 struct ggml_tensor * inputs[GGML_SCHED_MAX_SPLIT_INPUTS30];
769 int n_inputs;
770 // graph view of this split
771 struct ggml_cgraph graph;
772};
773
774struct ggml_backend_sched {
775 bool is_reset; // true if the scheduler has been reset since the last graph split
776 bool is_alloc;
777
778 int n_backends;
779
780 ggml_backend_t backends[GGML_SCHED_MAX_BACKENDS16];
781 ggml_backend_buffer_type_t bufts[GGML_SCHED_MAX_BACKENDS16];
782 ggml_gallocr_t galloc;
783
784 // hash map of the nodes in the graph
785 struct ggml_hash_set hash_set;
786 int * hv_tensor_backend_ids; // [hash_set.size]
787 struct ggml_tensor ** hv_tensor_copies; // [hash_set.size][n_backends][n_copies]
788
789 int * node_backend_ids; // [graph_size]
790 int * leaf_backend_ids; // [graph_size]
791
792 int * prev_node_backend_ids; // [graph_size]
793 int * prev_leaf_backend_ids; // [graph_size]
794
795 // copy of the graph with modified inputs
796 struct ggml_cgraph graph;
797
798 // graph splits
799 struct ggml_backend_sched_split * splits;
800 int n_splits;
801 int splits_capacity;
802
803 // pipeline parallelism support
804 int n_copies;
805 int cur_copy;
806 int next_copy;
807 ggml_backend_event_t events[GGML_SCHED_MAX_BACKENDS16][GGML_SCHED_MAX_COPIES4];
808 struct ggml_tensor * graph_inputs[GGML_SCHED_MAX_SPLIT_INPUTS30];
809 int n_graph_inputs;
810
811 struct ggml_context * ctx;
812
813 ggml_backend_sched_eval_callback callback_eval;
814 void * callback_eval_user_data;
815
816 char * context_buffer;
817 size_t context_buffer_size;
818
819 bool op_offload;
820
821 int debug;
822
823 // used for debugging graph reallocations [GGML_SCHED_DEBUG_REALLOC]
824 // ref: https://github.com/ggml-org/llama.cpp/pull/17617
825 int debug_realloc;
826 int debug_graph_size;
827 int debug_prev_graph_size;
828};
829
830#define hash_id(tensor)ggml_hash_find_or_insert(&sched->hash_set, tensor) ggml_hash_find_or_insert(&sched->hash_set, tensor)
831#define tensor_backend_id(tensor)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, tensor)]
sched->hv_tensor_backend_ids[hash_id(tensor)ggml_hash_find_or_insert(&sched->hash_set, tensor)]
832#define tensor_id_copy(id, backend_id, copy_id)sched->hv_tensor_copies[(id) * sched->n_backends * sched
->n_copies + (backend_id) * sched->n_copies + (copy_id)
]
sched->hv_tensor_copies[(id) * sched->n_backends * sched->n_copies + (backend_id) * sched->n_copies + (copy_id)]
833#define tensor_copy(tensor, backend_id, copy_id)sched->hv_tensor_copies[(ggml_hash_find_or_insert(&sched
->hash_set, tensor)) * sched->n_backends * sched->n_copies
+ (backend_id) * sched->n_copies + (copy_id)]
tensor_id_copy(hash_id(tensor), backend_id, copy_id)sched->hv_tensor_copies[(ggml_hash_find_or_insert(&sched
->hash_set, tensor)) * sched->n_backends * sched->n_copies
+ (backend_id) * sched->n_copies + (copy_id)]
834
835// returns the priority of the backend, lower id is higher priority
836static int ggml_backend_sched_backend_id(ggml_backend_sched_t sched, ggml_backend_t backend) {
837 for (int i = 0; i < sched->n_backends; i++) {
838 if (sched->backends[i] == backend) {
839 return i;
840 }
841 }
842 return -1;
843}
844
845static int ggml_backend_sched_backend_from_buffer(ggml_backend_sched_t sched, const struct ggml_tensor * tensor, const struct ggml_tensor * op) {
846 ggml_backend_buffer_t buffer = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
847 if (buffer == NULL__null) {
848 return -1;
849 }
850
851 // find highest prio backend that supports the buffer type and the op
852 for (int i = 0; i < sched->n_backends; i++) {
853 if (ggml_backend_supports_buft(sched->backends[i], buffer->buft) &&
854 ggml_backend_supports_op(sched->backends[i], op)) {
855 return i;
856 }
857 }
858
859#ifndef NDEBUG
860 GGML_LOG_DEBUG("%s: warning: no backend supports op %s with a weight with buffer type %s used in tensor %s, the weight will need to be copied\n",ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "%s: warning: no backend supports op %s with a weight with buffer type %s used in tensor %s, the weight will need to be copied\n"
, __func__, ggml_op_desc(tensor), ggml_backend_buffer_name(buffer
), tensor->name)
861 __func__, ggml_op_desc(tensor), ggml_backend_buffer_name(buffer), tensor->name)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "%s: warning: no backend supports op %s with a weight with buffer type %s used in tensor %s, the weight will need to be copied\n"
, __func__, ggml_op_desc(tensor), ggml_backend_buffer_name(buffer
), tensor->name)
;
862#endif
863
864 return -1;
865}
866
867#if 0
868#define GGML_SCHED_MAX_SPLITS_DEBUG 4096
869static char causes[GGML_DEFAULT_GRAPH_SIZE2048*16 + GGML_SCHED_MAX_SPLITS_DEBUG*GGML_SCHED_MAX_SPLIT_INPUTS30][128]; // debug only
870#define SET_CAUSE(node, ...) sprintf(causes[hash_id(node)ggml_hash_find_or_insert(&sched->hash_set, node)], __VA_ARGS__)
871#define GET_CAUSE(node)"" causes[hash_id(node)ggml_hash_find_or_insert(&sched->hash_set, node)]
872#else
873#define SET_CAUSE(node, ...)
874#define GET_CAUSE(node)"" ""
875#endif
876
877// returns the backend that should be used for the node based on the current locations
878static int ggml_backend_sched_backend_id_from_cur(ggml_backend_sched_t sched, struct ggml_tensor * tensor) {
879 // assign pre-allocated nodes to their backend
880 int cur_backend_id = ggml_backend_sched_backend_from_buffer(sched, tensor, tensor);
881 if (cur_backend_id != -1) {
882 SET_CAUSE(tensor, "1.dst");
883 return cur_backend_id;
884 }
885
886 // view_src
887 if (tensor->view_src != NULL__null) {
888 cur_backend_id = ggml_backend_sched_backend_from_buffer(sched, tensor->view_src, tensor);
889 if (cur_backend_id != -1) {
890 SET_CAUSE(tensor, "1.vsrc");
891 return cur_backend_id;
892 }
893 }
894
895 if (tensor->buffer || (tensor->view_src && tensor->view_src->buffer)) {
896 // since the tensor is pre-allocated, it cannot be moved to another backend
897 ggml_backend_buffer_t buffer = tensor->view_src ? tensor->view_src->buffer : tensor->buffer;
898 GGML_ABORT("pre-allocated tensor (%s) in a buffer (%s) that cannot run the operation (%s)", tensor->name, ggml_backend_buffer_name(buffer), ggml_op_name(tensor->op))ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 898, "pre-allocated tensor (%s) in a buffer (%s) that cannot run the operation (%s)"
, tensor->name, ggml_backend_buffer_name(buffer), ggml_op_name
(tensor->op))
;
899 }
900
901 // graph input
902 if (tensor->flags & GGML_TENSOR_FLAG_INPUT) {
903 cur_backend_id = sched->n_backends - 1; // last backend (assumed CPU)
904 SET_CAUSE(tensor, "1.inp");
905 return cur_backend_id;
906 }
907
908 // operations with weights are preferably run on the same backend as the weights
909 for (int i = 0; i < GGML_MAX_SRC10; i++) {
910 const struct ggml_tensor * src = tensor->src[i];
911 if (src == NULL__null) {
912 continue;
913 }
914 // skip ROPE since the rope freqs tensor is too small to choose a backend based on it
915 // not an ideal solution
916 if (tensor->op != GGML_OP_ROPE && src->buffer != NULL__null && src->buffer->usage == GGML_BACKEND_BUFFER_USAGE_WEIGHTS) {
917 int src_backend_id = ggml_backend_sched_backend_from_buffer(sched, src, tensor);
918 // check if a backend with higher prio wants to offload the op
919 if (sched->op_offload && src_backend_id == sched->n_backends - 1 && ggml_backend_buffer_is_host(src->buffer)) {
920 for (int b = 0; b < src_backend_id; b++) {
921 if (ggml_backend_supports_op(sched->backends[b], tensor) && ggml_backend_offload_op(sched->backends[b], tensor)) {
922 SET_CAUSE(tensor, "1.off");
923 return b;
924 }
925 }
926 }
927 SET_CAUSE(tensor, "1.wgt%d", i);
928 return src_backend_id;
929 }
930 }
931
932 return -1;
933}
934
935static char * fmt_size(size_t size) {
936 static char buffer[128];
937 if (size >= 1024*1024) {
938 snprintf(buffer, sizeof(buffer), "%zuM", size/1024/1024);
939 } else {
940 snprintf(buffer, sizeof(buffer), "%zuK", size/1024);
941 }
942 return buffer;
943}
944
945static void ggml_backend_sched_print_assignments(ggml_backend_sched_t sched, struct ggml_cgraph * graph) {
946 int cur_split = 0;
947 for (int i = 0; i < graph->n_nodes; i++) {
948 if (cur_split < sched->n_splits && i == sched->splits[cur_split].i_start) {
949 ggml_backend_t split_backend = sched->backends[sched->splits[cur_split].backend_id];
950 GGML_LOG_DEBUG("\n## SPLIT #%d: %s # %d inputs", cur_split, ggml_backend_name(split_backend),ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "\n## SPLIT #%d: %s # %d inputs"
, cur_split, ggml_backend_name(split_backend), sched->splits
[cur_split].n_inputs)
951 sched->splits[cur_split].n_inputs)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "\n## SPLIT #%d: %s # %d inputs"
, cur_split, ggml_backend_name(split_backend), sched->splits
[cur_split].n_inputs)
;
952 for (int j = 0; j < sched->splits[cur_split].n_inputs; j++) {
953 if (j == 0) {
954 GGML_LOG_DEBUG(": ")ggml_log_internal(GGML_LOG_LEVEL_DEBUG, ": ");
955 }
956 GGML_LOG_DEBUG("[%s (%5.5s)] ", sched->splits[cur_split].inputs[j]->name,ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "[%s (%5.5s)] ", sched
->splits[cur_split].inputs[j]->name, fmt_size(ggml_nbytes
(sched->splits[cur_split].inputs[j])))
957 fmt_size(ggml_nbytes(sched->splits[cur_split].inputs[j])))ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "[%s (%5.5s)] ", sched
->splits[cur_split].inputs[j]->name, fmt_size(ggml_nbytes
(sched->splits[cur_split].inputs[j])))
;
958 }
959 GGML_LOG_DEBUG("\n")ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "\n");
960 cur_split++;
961 }
962 struct ggml_tensor * node = graph->nodes[i];
963 if (ggml_is_view_op(node->op)) {
964 continue;
965 }
966 if (sched->debug > 1) {
967 ggml_backend_t tensor_backend = ggml_backend_sched_get_tensor_backend(sched, node);
968 GGML_LOG_DEBUG("node #%3d (%10.10s): %20.20s (%5.5s) [%5.5s %8.8s] use=%d,c=%d:", i, ggml_op_desc(node), node->name,ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "node #%3d (%10.10s): %20.20s (%5.5s) [%5.5s %8.8s] use=%d,c=%d:"
, i, ggml_op_desc(node), node->name, fmt_size(ggml_nbytes(
node)), tensor_backend ? ggml_backend_name(tensor_backend) : "NULL"
, "", graph->use_counts[ggml_hash_find(&graph->visited_hash_set
, node)], node->flags & GGML_TENSOR_FLAG_COMPUTE ? 1 :
0)
969 fmt_size(ggml_nbytes(node)), tensor_backend ? ggml_backend_name(tensor_backend) : "NULL", GET_CAUSE(node),ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "node #%3d (%10.10s): %20.20s (%5.5s) [%5.5s %8.8s] use=%d,c=%d:"
, i, ggml_op_desc(node), node->name, fmt_size(ggml_nbytes(
node)), tensor_backend ? ggml_backend_name(tensor_backend) : "NULL"
, "", graph->use_counts[ggml_hash_find(&graph->visited_hash_set
, node)], node->flags & GGML_TENSOR_FLAG_COMPUTE ? 1 :
0)
970 graph->use_counts[ggml_hash_find(&graph->visited_hash_set, node)], node->flags & GGML_TENSOR_FLAG_COMPUTE ? 1 : 0)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "node #%3d (%10.10s): %20.20s (%5.5s) [%5.5s %8.8s] use=%d,c=%d:"
, i, ggml_op_desc(node), node->name, fmt_size(ggml_nbytes(
node)), tensor_backend ? ggml_backend_name(tensor_backend) : "NULL"
, "", graph->use_counts[ggml_hash_find(&graph->visited_hash_set
, node)], node->flags & GGML_TENSOR_FLAG_COMPUTE ? 1 :
0)
;
971 for (int j = 0; j < GGML_MAX_SRC10; j++) {
972 struct ggml_tensor * src = node->src[j];
973 if (src == NULL__null) {
974 continue;
975 }
976 ggml_backend_t src_backend = ggml_backend_sched_get_tensor_backend(sched, src);
977 GGML_LOG_DEBUG(" %20.20s (%5.5s) [%5.5s %8.8s]", src->name,ggml_log_internal(GGML_LOG_LEVEL_DEBUG, " %20.20s (%5.5s) [%5.5s %8.8s]"
, src->name, fmt_size(ggml_nbytes(src)), src_backend ? ggml_backend_name
(src_backend) : "NULL", "")
978 fmt_size(ggml_nbytes(src)), src_backend ? ggml_backend_name(src_backend) : "NULL", GET_CAUSE(src))ggml_log_internal(GGML_LOG_LEVEL_DEBUG, " %20.20s (%5.5s) [%5.5s %8.8s]"
, src->name, fmt_size(ggml_nbytes(src)), src_backend ? ggml_backend_name
(src_backend) : "NULL", "")
;
979 }
980 GGML_LOG_DEBUG("\n")ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "\n");
981 }
982 }
983}
984
985static bool ggml_backend_sched_buffer_supported(ggml_backend_sched_t sched, struct ggml_tensor * t, int backend_id) {
986 ggml_backend_buffer_t buf = t->view_src ? t->view_src->buffer : t->buffer;
987 ggml_backend_buffer_type_t buft = NULL__null;
988
989 if (buf) {
990 // the tensor is already allocated
991 buft = buf->buft;
992 } else {
993 // see if the tensor already has a backend assigned, and use the buffer type of that backend
994 int tensor_backend_id = tensor_backend_id(t)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, t)]
;
995 if (tensor_backend_id == -1 && t->view_src) {
996 tensor_backend_id = tensor_backend_id(t->view_src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, t->view_src)]
;
997 }
998 if (tensor_backend_id != -1) {
999 buft = sched->bufts[tensor_backend_id];
1000 }
1001 }
1002
1003 return buft != NULL__null && ggml_backend_supports_buft(sched->backends[backend_id], buft);
1004}
1005
1006static void ggml_backend_sched_set_if_supported(ggml_backend_sched_t sched, struct ggml_tensor * node, int cur_backend_id, int * node_backend_id) {
1007 if (ggml_backend_supports_op(sched->backends[cur_backend_id], node)) {
1008 *node_backend_id = cur_backend_id;
1009 SET_CAUSE(node, "2.sup");
1010 }
1011}
1012
1013// assigns backends to ops and splits the graph into subgraphs that can be computed on the same backend
1014void ggml_backend_sched_split_graph(ggml_backend_sched_t sched, struct ggml_cgraph * graph) {
1015 // reset splits
1016 sched->n_splits = 0;
1017 sched->n_graph_inputs = 0;
1018 sched->is_reset = false;
1019
1020 struct ggml_init_params params = {
1021 /* .mem_size = */ sched->context_buffer_size,
1022 /* .mem_buffer = */ sched->context_buffer,
1023 /* .no_alloc = */ true
1024 };
1025
1026 ggml_free(sched->ctx);
1027
1028 sched->ctx = ggml_init(params);
1029 if (sched->ctx == NULL__null) {
1030 GGML_ABORT("%s: failed to initialize context\n", __func__)ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1030, "%s: failed to initialize context\n", __func__)
;
1031 }
1032
1033 graph->uid = ggml_graph_next_uid();
1034
1035 // pass 1: assign backends to ops with pre-allocated inputs
1036 for (int i = 0; i < graph->n_leafs; i++) {
1037 struct ggml_tensor * leaf = graph->leafs[i];
1038 int * leaf_backend_id = &tensor_backend_id(leaf)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, leaf)]
;
1039 // do not overwrite user assignments
1040 if (*leaf_backend_id == -1) {
1041 *leaf_backend_id = ggml_backend_sched_backend_id_from_cur(sched, leaf);
1042 }
1043 }
1044
1045 for (int i = 0; i < graph->n_nodes; i++) {
1046 struct ggml_tensor * node = graph->nodes[i];
1047 int * node_backend_id = &tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1048 // do not overwrite user assignments
1049 if (*node_backend_id == -1) {
1050 *node_backend_id = ggml_backend_sched_backend_id_from_cur(sched, node);
1051
1052#if 0
1053 // src
1054 if (node->op == GGML_OP_NONE) {
1055 continue;
1056 }
1057
1058 for (int j = 0; j < GGML_MAX_SRC10; j++) {
1059 struct ggml_tensor * src = node->src[j];
1060 if (src == NULL__null) {
1061 continue;
1062 }
1063 int * src_backend_id = &tensor_backend_id(src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, src)]
;
1064 if (*src_backend_id == -1) {
1065 *src_backend_id = ggml_backend_sched_backend_id_from_cur(sched, src);
1066 }
1067 }
1068#endif
1069 }
1070 }
1071
1072 // pass 2: expand current backend assignments
1073 // assign the same backend to adjacent nodes
1074 // expand gpu backends (i.e. non last prio) up and down, ignoring cpu (the lowest priority backend)
1075 // thus, cpu will never be used unless weights are on cpu, or there are no gpu ops between cpu ops
1076 // ops unsupported by the backend being expanded will be left unassigned so that they can be assigned later when the locations of its inputs are known
1077 // expand gpu down
1078 {
1079 int cur_backend_id = -1;
1080 for (int i = 0; i < graph->n_nodes; i++) {
1081 struct ggml_tensor * node = graph->nodes[i];
1082 if (ggml_is_view_op(node->op)) {
1083 continue;
1084 }
1085 int * node_backend_id = &tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1086 if (*node_backend_id != -1) {
1087 if (*node_backend_id == sched->n_backends - 1) {
1088 // skip cpu (lowest prio backend)
1089 cur_backend_id = -1;
1090 } else {
1091 cur_backend_id = *node_backend_id;
1092 }
1093 } else if (cur_backend_id != -1) {
1094 ggml_backend_sched_set_if_supported(sched, node, cur_backend_id, node_backend_id);
1095 }
1096 }
1097 }
1098 // expand gpu up
1099 {
1100 int cur_backend_id = -1;
1101 for (int i = graph->n_nodes - 1; i >= 0; i--) {
1102 struct ggml_tensor * node = graph->nodes[i];
1103 if (ggml_is_view_op(node->op)) {
1104 continue;
1105 }
1106 int * node_backend_id = &tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1107 if (*node_backend_id != -1) {
1108 if (*node_backend_id == sched->n_backends - 1) {
1109 // skip cpu (lowest prio backend)
1110 cur_backend_id = -1;
1111 } else {
1112 cur_backend_id = *node_backend_id;
1113 }
1114 } else if (cur_backend_id != -1) {
1115 ggml_backend_sched_set_if_supported(sched, node, cur_backend_id, node_backend_id);
1116 }
1117 }
1118 }
1119 // expand rest down
1120 {
1121 int cur_backend_id = -1;
1122 for (int i = 0; i < graph->n_nodes; i++) {
1123 struct ggml_tensor * node = graph->nodes[i];
1124 if (ggml_is_view_op(node->op)) {
1125 continue;
1126 }
1127 int * node_backend_id = &tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1128 if (*node_backend_id != -1) {
1129 cur_backend_id = *node_backend_id;
1130 } else if (cur_backend_id != -1) {
1131 ggml_backend_sched_set_if_supported(sched, node, cur_backend_id, node_backend_id);
1132 }
1133 }
1134 }
1135 // expand rest up
1136 {
1137 int cur_backend_id = -1;
1138 for (int i = graph->n_nodes - 1; i >= 0; i--) {
1139 struct ggml_tensor * node = graph->nodes[i];
1140 if (ggml_is_view_op(node->op)) {
1141 continue;
1142 }
1143 int * node_backend_id = &tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1144 if (*node_backend_id != -1) {
1145 cur_backend_id = *node_backend_id;
1146 } else if (cur_backend_id != -1) {
1147 ggml_backend_sched_set_if_supported(sched, node, cur_backend_id, node_backend_id);
1148 }
1149 }
1150 }
1151
1152 // pass 3: upgrade nodes to higher prio backends with compatible buffer types
1153 // if the tensor is already in the same buffer type (*) as another higher priority backend, we should move it there
1154 // however, we also need to verify that the sources are in compatible buffer types
1155 // (*) the actual requirement is more relaxed, the buffer type of the backend should be supported by all the users of this tensor further down the graph
1156 // however, this is slow to verify, so we have a more strict requirement that the buffer type is the same
1157 // this is not uncommon since multiple backends can use host memory, with the same buffer type (eg. BLAS and CPU)
1158 // additionally, set remaining unassigned nodes to the backend with the most supported inputs
1159 // only nodes that could not be assigned during expansion due to the backend not supporting the op should be unassigned at this point
1160 for (int i = 0; i < graph->n_nodes; i++) {
1161 struct ggml_tensor * node = graph->nodes[i];
1162 if (ggml_is_view_op(node->op)) {
1163 continue;
1164 }
1165 int * node_backend_id = &tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1166 if (*node_backend_id == -1) {
1167 // unassigned node: find the backend with the most supported inputs
1168 int n_supported_best = -1;
1169 for (int b = 0; b < sched->n_backends; b++) {
1170 if (ggml_backend_supports_op(sched->backends[b], node)) {
1171 int n_supported = 0;
1172 for (int j = 0; j < GGML_MAX_SRC10; j++) {
1173 struct ggml_tensor * src = node->src[j];
1174 if (src == NULL__null) {
1175 continue;
1176 }
1177 if ((tensor_backend_id(src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, src)]
!= -1 || tensor_backend_id(src->view_src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, src->view_src)]
!= -1) && ggml_backend_sched_buffer_supported(sched, src, b)) {
1178 n_supported++;
1179 }
1180 }
1181 if (n_supported > n_supported_best) {
1182 n_supported_best = n_supported;
1183 *node_backend_id = b;
1184 SET_CAUSE(node, "3.best");
1185 }
1186 }
1187 }
1188 } else {
1189 // assigned node: upgrade to higher prio backend if possible
1190 for (int b = 0; b < *node_backend_id; b++) {
1191 if (sched->bufts[b] == sched->bufts[*node_backend_id] && ggml_backend_supports_op(sched->backends[b], node)) {
1192 bool supported = true;
1193 for (int j = 0; j < GGML_MAX_SRC10; j++) {
1194 struct ggml_tensor * src = node->src[j];
1195 if (src == NULL__null) {
1196 continue;
1197 }
1198 if (!ggml_backend_sched_buffer_supported(sched, src, b)) {
1199 supported = false;
1200 break;
1201 }
1202 }
1203 if (supported) {
1204 *node_backend_id = b;
1205 SET_CAUSE(node, "3.upg");
1206 break;
1207 }
1208 }
1209 }
1210 }
1211 }
1212
1213 // pass 4: assign backends to remaining src from dst and view_src
1214 for (int i = 0; i < graph->n_nodes; i++) {
1215 struct ggml_tensor * node = graph->nodes[i];
1216 int * cur_backend_id = &tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1217 if (node->view_src != NULL__null && *cur_backend_id == -1) {
1218 *cur_backend_id = tensor_backend_id(node->view_src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node->view_src)]
;
1219 SET_CAUSE(node, "4.vsrc");
1220 }
1221 for (int j = 0; j < GGML_MAX_SRC10; j++) {
1222 struct ggml_tensor * src = node->src[j];
1223 if (src == NULL__null) {
1224 continue;
1225 }
1226 int * src_backend_id = &tensor_backend_id(src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, src)]
;
1227 if (*src_backend_id == -1) {
1228 if (src->view_src != NULL__null) {
1229 // views are always on the same backend as the source
1230 *src_backend_id = tensor_backend_id(src->view_src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, src->view_src)]
;
1231 SET_CAUSE(src, "4.vsrc");
1232 } else {
1233 *src_backend_id = *cur_backend_id;
1234 SET_CAUSE(src, "4.cur");
1235 }
1236 }
1237 }
1238 // if the node is still unassigned, assign it to the first backend that supports it
1239 for (int b = 0; b < sched->n_backends && *cur_backend_id == -1; b++) {
1240 ggml_backend_sched_set_if_supported(sched, node, b, cur_backend_id);
1241 }
1242 GGML_ASSERT(*cur_backend_id != -1)if (!(*cur_backend_id != -1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1242, "GGML_ASSERT(%s) failed", "*cur_backend_id != -1")
;
1243 }
1244
1245 // pass 5: split graph, find tensors that need to be copied
1246 {
1247 int i_split = 0;
1248 struct ggml_backend_sched_split * split = &sched->splits[0];
1249 // find the backend of the first split, skipping view ops
1250 int i = 0;
1251 for (; i < graph->n_nodes; i++) {
1252 struct ggml_tensor * node = graph->nodes[i];
1253 if (!ggml_is_view_op(node->op)) {
1254 split->backend_id = tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1255 break;
1256 }
1257 }
1258 split->i_start = 0;
1259 split->n_inputs = 0;
1260 int cur_backend_id = split->backend_id;
1261 for (; i < graph->n_nodes; i++) {
1262 struct ggml_tensor * node = graph->nodes[i];
1263
1264 if (ggml_is_view_op(node->op)) {
1265 continue;
1266 }
1267
1268 const int node_backend_id = tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1269
1270 GGML_ASSERT(node_backend_id != -1)if (!(node_backend_id != -1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1270, "GGML_ASSERT(%s) failed", "node_backend_id != -1")
; // all nodes should be assigned by now, this can happen if there is no CPU fallback
1271
1272 // check if we should start a new split based on the sources of the current node
1273 bool need_new_split = false;
1274 if (node_backend_id == cur_backend_id && split->n_inputs > 0) {
1275 for (int j = 0; j < GGML_MAX_SRC10; j++) {
1276 struct ggml_tensor * src = node->src[j];
1277 if (src == NULL__null) {
1278 continue;
1279 }
1280 // check if a weight is on a different and incompatible backend
1281 // by starting a new split, the memory of the previously offloaded weights can be reused
1282 if (src->buffer != NULL__null && src->buffer->usage == GGML_BACKEND_BUFFER_USAGE_WEIGHTS) {
1283 int src_backend_id = tensor_backend_id(src)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, src)]
;
1284 if (src_backend_id != cur_backend_id && !ggml_backend_sched_buffer_supported(sched, src, cur_backend_id)) {
1285 need_new_split = true;
1286 break;
1287 }
1288 }
1289 // check if the split has too many inputs
1290 // FIXME: count the number of inputs instead of only checking when full
1291 if (split->n_inputs == GGML_SCHED_MAX_SPLIT_INPUTS30) {
1292 const size_t id = hash_id(src)ggml_hash_find_or_insert(&sched->hash_set, src);
1293 int src_backend_id = sched->hv_tensor_backend_ids[id];
1294 bool supported = ggml_backend_sched_buffer_supported(sched, src, cur_backend_id);
1295 if (src_backend_id != cur_backend_id && tensor_id_copy(id, cur_backend_id, 0)sched->hv_tensor_copies[(id) * sched->n_backends * sched
->n_copies + (cur_backend_id) * sched->n_copies + (0)]
== NULL__null && !supported) {
1296 need_new_split = true;
1297 break;
1298 }
1299 }
1300 }
1301 }
1302
1303 if (node_backend_id != cur_backend_id || need_new_split) {
1304 split->i_end = i;
1305 i_split++;
1306 if (i_split >= sched->splits_capacity) {
1307 sched->splits_capacity *= 2;
1308 sched->splits = (ggml_backend_sched_split *)
1309 realloc(sched->splits, sched->splits_capacity * sizeof(struct ggml_backend_sched_split));
1310 GGML_ASSERT(sched->splits != NULL)if (!(sched->splits != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1310, "GGML_ASSERT(%s) failed", "sched->splits != NULL")
;
1311 }
1312 split = &sched->splits[i_split];
1313 split->backend_id = node_backend_id;
1314 split->i_start = i;
1315 split->n_inputs = 0;
1316 cur_backend_id = node_backend_id;
1317 }
1318
1319 // find inputs that are not on the same backend
1320 for (int j = 0; j < GGML_MAX_SRC10; j++) {
1321 struct ggml_tensor * src = node->src[j];
1322 if (src == NULL__null) {
1323 continue;
1324 }
1325
1326 size_t src_id = hash_id(src)ggml_hash_find_or_insert(&sched->hash_set, src);
1327 const int src_backend_id = sched->hv_tensor_backend_ids[src_id];
1328 GGML_ASSERT(src_backend_id != -1)if (!(src_backend_id != -1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1328, "GGML_ASSERT(%s) failed", "src_backend_id != -1")
; // all inputs should be assigned by now
1329
1330 if (src->flags & GGML_TENSOR_FLAG_INPUT && sched->n_copies > 1) {
1331 if (tensor_id_copy(src_id, src_backend_id, 0)sched->hv_tensor_copies[(src_id) * sched->n_backends * sched
->n_copies + (src_backend_id) * sched->n_copies + (0)]
== NULL__null) {
1332 ggml_backend_t backend = sched->backends[src_backend_id];
1333 for (int c = 0; c < sched->n_copies; c++) {
1334 struct ggml_tensor * tensor_copy;
1335 if (c == sched->cur_copy) {
1336 tensor_copy = src; // use the original tensor as the current copy
1337 } else {
1338 tensor_copy = ggml_dup_tensor_layout(sched->ctx, src);
1339 ggml_format_name(tensor_copy, "%s#%s#%d", ggml_backend_name(backend), src->name, c);
1340 }
1341 ggml_set_input(tensor_copy);
1342 ggml_set_output(tensor_copy); // prevent ggml-alloc from overwriting the tensor
1343 tensor_id_copy(src_id, src_backend_id, c)sched->hv_tensor_copies[(src_id) * sched->n_backends * sched
->n_copies + (src_backend_id) * sched->n_copies + (c)]
= tensor_copy;
1344 SET_CAUSE(tensor_copy, "4.cpy");
1345 }
1346 int n_graph_inputs = sched->n_graph_inputs++;
1347 GGML_ASSERT(n_graph_inputs < GGML_SCHED_MAX_SPLIT_INPUTS)if (!(n_graph_inputs < 30)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1347, "GGML_ASSERT(%s) failed", "n_graph_inputs < GGML_SCHED_MAX_SPLIT_INPUTS"
)
;
1348 sched->graph_inputs[n_graph_inputs] = src;
1349 }
1350 }
1351
1352 if (src_backend_id != cur_backend_id && !ggml_backend_sched_buffer_supported(sched, src, cur_backend_id)) {
1353 // create a copy of the input in the split's backend
1354 if (tensor_id_copy(src_id, cur_backend_id, 0)sched->hv_tensor_copies[(src_id) * sched->n_backends * sched
->n_copies + (cur_backend_id) * sched->n_copies + (0)]
== NULL__null) {
1355 ggml_backend_t backend = sched->backends[cur_backend_id];
1356 for (int c = 0; c < sched->n_copies; c++) {
1357 struct ggml_tensor * tensor_copy = ggml_dup_tensor_layout(sched->ctx, src);
1358 ggml_format_name(tensor_copy, "%s#%s#%d", ggml_backend_name(backend), src->name, c);
1359 if (sched->n_copies > 1) {
1360 ggml_set_input(tensor_copy);
1361 ggml_set_output(tensor_copy); // prevent ggml-alloc from overwriting the tensor
1362 }
1363 tensor_id_copy(src_id, cur_backend_id, c)sched->hv_tensor_copies[(src_id) * sched->n_backends * sched
->n_copies + (cur_backend_id) * sched->n_copies + (c)]
= tensor_copy;
1364 SET_CAUSE(tensor_copy, "4.cpy");
1365 }
1366 int n_inputs = split->n_inputs++;
1367 GGML_ASSERT(n_inputs < GGML_SCHED_MAX_SPLIT_INPUTS)if (!(n_inputs < 30)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1367, "GGML_ASSERT(%s) failed", "n_inputs < GGML_SCHED_MAX_SPLIT_INPUTS"
)
;
1368 split->inputs[n_inputs] = src;
1369 }
1370 node->src[j] = tensor_id_copy(src_id, cur_backend_id, sched->cur_copy)sched->hv_tensor_copies[(src_id) * sched->n_backends * sched
->n_copies + (cur_backend_id) * sched->n_copies + (sched
->cur_copy)]
;
1371 }
1372 }
1373 }
1374 split->i_end = graph->n_nodes;
1375 sched->n_splits = i_split + 1;
1376 }
1377
1378 if (sched->debug) {
1379 ggml_backend_sched_print_assignments(sched, graph);
1380 }
1381
1382 // swap node_backend_ids and leaf _backend_ids with prevs
1383 {
1384 int * tmp = sched->node_backend_ids;
1385 sched->node_backend_ids = sched->prev_node_backend_ids;
1386 sched->prev_node_backend_ids = tmp;
1387
1388 tmp = sched->leaf_backend_ids;
1389 sched->leaf_backend_ids = sched->prev_leaf_backend_ids;
1390 sched->prev_leaf_backend_ids = tmp;
1391 }
1392
1393 int graph_size = std::max(graph->n_nodes, graph->n_leafs) + sched->n_splits*GGML_SCHED_MAX_SPLIT_INPUTS30*2*sched->n_copies;
1394
1395 // remember the actual graph_size for performing reallocation checks later [GGML_SCHED_DEBUG_REALLOC]
1396 sched->debug_prev_graph_size = sched->debug_graph_size;
1397 sched->debug_graph_size = graph_size;
1398
1399 if (sched->graph.size < graph_size) {
1400 sched->graph.size = graph_size;
1401 sched->graph.nodes = (ggml_tensor **) realloc(sched->graph.nodes, graph_size * sizeof(struct ggml_tensor *));
1402 sched->graph.leafs = (ggml_tensor **) realloc(sched->graph.leafs, graph_size * sizeof(struct ggml_tensor *));
1403 GGML_ASSERT(sched->graph.nodes != NULL)if (!(sched->graph.nodes != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1403, "GGML_ASSERT(%s) failed", "sched->graph.nodes != NULL"
)
;
1404 GGML_ASSERT(sched->graph.leafs != NULL)if (!(sched->graph.leafs != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1404, "GGML_ASSERT(%s) failed", "sched->graph.leafs != NULL"
)
;
1405 }
1406 sched->graph.n_nodes = 0;
1407 sched->graph.n_leafs = 0;
1408
1409 struct ggml_cgraph * graph_copy = &sched->graph;
1410
1411 for (int i = 0; i < sched->n_splits; i++) {
1412 struct ggml_backend_sched_split * split = &sched->splits[i];
1413 split->graph = ggml_graph_view(graph, split->i_start, split->i_end);
1414
1415 // Optimize this split of the graph. This needs to happen before we make graph_copy,
1416 // so they are in sync.
1417 ggml_backend_graph_optimize(sched->backends[split->backend_id], &split->graph);
1418
1419 // add inputs to the graph copy so that they are allocated by ggml-alloc at the start of the split
1420 for (int j = 0; j < split->n_inputs; j++) {
1421 assert(graph_copy->size > (graph_copy->n_nodes + 1))(static_cast <bool> (graph_copy->size > (graph_copy
->n_nodes + 1)) ? void (0) : __assert_fail ("graph_copy->size > (graph_copy->n_nodes + 1)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1422
1423 struct ggml_tensor * input = split->inputs[j];
1424 const size_t input_id = hash_id(input)ggml_hash_find_or_insert(&sched->hash_set, input);
1425 struct ggml_tensor * input_cpy = tensor_id_copy(input_id, split->backend_id, sched->cur_copy)sched->hv_tensor_copies[(input_id) * sched->n_backends *
sched->n_copies + (split->backend_id) * sched->n_copies
+ (sched->cur_copy)]
;
1426
1427 // add a dependency to the input source so that it is not freed before the copy is done
1428 struct ggml_tensor * input_dep = ggml_view_tensor(sched->ctx, input);
1429 input_dep->src[0] = input;
1430 sched->node_backend_ids[graph_copy->n_nodes] = sched->hv_tensor_backend_ids[input_id];
1431 graph_copy->nodes[graph_copy->n_nodes++] = input_dep;
1432
1433 // add a dependency to the input copy so that it is allocated at the start of the split
1434 sched->node_backend_ids[graph_copy->n_nodes] = split->backend_id;
1435 graph_copy->nodes[graph_copy->n_nodes++] = input_cpy;
1436 }
1437
1438 for (int j = split->i_start; j < split->i_end; j++) {
1439 assert(graph_copy->size > graph_copy->n_nodes)(static_cast <bool> (graph_copy->size > graph_copy
->n_nodes) ? void (0) : __assert_fail ("graph_copy->size > graph_copy->n_nodes"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1440 sched->node_backend_ids[graph_copy->n_nodes] = tensor_backend_id(graph->nodes[j])sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, graph->nodes[j])]
;
1441 graph_copy->nodes[graph_copy->n_nodes++] = graph->nodes[j];
1442 }
1443 }
1444
1445 if (sched->n_copies > 1) {
1446 // add input copies as leafs so that they are allocated first
1447 for (int i = 0; i < sched->n_graph_inputs; i++) {
1448 struct ggml_tensor * input = sched->graph_inputs[i];
1449 size_t id = hash_id(input)ggml_hash_find_or_insert(&sched->hash_set, input);
1450 int backend_id = tensor_backend_id(input)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, input)]
;
1451 for (int c = 0; c < sched->n_copies; c++) {
1452 struct ggml_tensor * input_cpy = tensor_id_copy(id, backend_id, c)sched->hv_tensor_copies[(id) * sched->n_backends * sched
->n_copies + (backend_id) * sched->n_copies + (c)]
;
1453 sched->leaf_backend_ids[graph_copy->n_leafs] = backend_id;
1454 assert(graph_copy->size > graph_copy->n_leafs)(static_cast <bool> (graph_copy->size > graph_copy
->n_leafs) ? void (0) : __assert_fail ("graph_copy->size > graph_copy->n_leafs"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1455 graph_copy->leafs[graph_copy->n_leafs++] = input_cpy;
1456 }
1457 }
1458
1459 for (int i = 0; i < sched->n_splits; i++) {
1460 struct ggml_backend_sched_split * split = &sched->splits[i];
1461 int backend_id = split->backend_id;
1462 for (int j = 0; j < split->n_inputs; j++) {
1463 struct ggml_tensor * input = split->inputs[j];
1464 size_t id = hash_id(input)ggml_hash_find_or_insert(&sched->hash_set, input);
1465 for (int c = 0; c < sched->n_copies; c++) {
1466 struct ggml_tensor * input_cpy = tensor_id_copy(id, backend_id, c)sched->hv_tensor_copies[(id) * sched->n_backends * sched
->n_copies + (backend_id) * sched->n_copies + (c)]
;
1467 sched->leaf_backend_ids[graph_copy->n_leafs] = backend_id;
1468 assert(graph_copy->size > graph_copy->n_leafs)(static_cast <bool> (graph_copy->size > graph_copy
->n_leafs) ? void (0) : __assert_fail ("graph_copy->size > graph_copy->n_leafs"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1469 graph_copy->leafs[graph_copy->n_leafs++] = input_cpy;
1470 }
1471 }
1472 }
1473 }
1474
1475 // add leafs from the original graph
1476 for (int i = 0; i < graph->n_leafs; i++) {
1477 struct ggml_tensor * leaf = graph->leafs[i];
1478 sched->leaf_backend_ids[graph_copy->n_leafs] = tensor_backend_id(leaf)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, leaf)]
;
1479 assert(graph_copy->size > graph_copy->n_leafs)(static_cast <bool> (graph_copy->size > graph_copy
->n_leafs) ? void (0) : __assert_fail ("graph_copy->size > graph_copy->n_leafs"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1480 graph_copy->leafs[graph_copy->n_leafs++] = leaf;
1481 }
1482
1483 // set ids for all splits
1484 for (int i = 0; i < sched->n_splits; ++i) {
1485 sched->splits[i].graph.uid = ggml_graph_next_uid();
1486 }
1487}
1488
1489static bool ggml_backend_sched_alloc_splits(ggml_backend_sched_t sched) {
1490 bool backend_ids_changed = false;
1491 for (int i = 0; i < sched->graph.n_nodes; i++) {
1492 if (sched->node_backend_ids[i] != sched->prev_node_backend_ids[i] &&
1493 sched->bufts[sched->node_backend_ids[i]] != sched->bufts[sched->prev_node_backend_ids[i]]) {
1494 backend_ids_changed = true;
1495 break;
1496 }
1497 }
1498 if (!backend_ids_changed) {
1499 for (int i = 0; i < sched->graph.n_leafs; i++) {
1500 if (sched->leaf_backend_ids[i] != sched->prev_leaf_backend_ids[i] &&
1501 sched->bufts[sched->leaf_backend_ids[i]] != sched->bufts[sched->prev_leaf_backend_ids[i]]) {
1502 backend_ids_changed = true;
1503 break;
1504 }
1505 }
1506 }
1507
1508 // allocate graph
1509 if (backend_ids_changed || !ggml_gallocr_alloc_graph(sched->galloc, &sched->graph)) {
1510#ifndef NDEBUG
1511 GGML_LOG_DEBUG("%s: failed to allocate graph, reserving (backend_ids_changed = %d)\n", __func__, backend_ids_changed)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "%s: failed to allocate graph, reserving (backend_ids_changed = %d)\n"
, __func__, backend_ids_changed)
;
1512#endif
1513
1514 if (sched->debug_realloc > 0) {
1515 // we are interested only in situations where the graph was reallocated even though its size remained the same [GGML_SCHED_DEBUG_REALLOC]
1516 // example: https://github.com/ggml-org/llama.cpp/pull/17143
1517 const bool unexpected = !backend_ids_changed && sched->debug_prev_graph_size == sched->debug_graph_size;
1518
1519 if (unexpected || sched->debug_realloc > 1) {
1520 GGML_ABORT("%s: unexpected graph reallocation (graph size = %d, nodes = %d, leafs = %d), debug_realloc = %d\n", __func__,ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1521, "%s: unexpected graph reallocation (graph size = %d, nodes = %d, leafs = %d), debug_realloc = %d\n"
, __func__, sched->debug_graph_size, sched->graph.n_nodes
, sched->graph.n_leafs, sched->debug_realloc)
1521 sched->debug_graph_size, sched->graph.n_nodes, sched->graph.n_leafs, sched->debug_realloc)ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1521, "%s: unexpected graph reallocation (graph size = %d, nodes = %d, leafs = %d), debug_realloc = %d\n"
, __func__, sched->debug_graph_size, sched->graph.n_nodes
, sched->graph.n_leafs, sched->debug_realloc)
;
1522 }
1523 }
1524
1525 // the re-allocation may cause the split inputs to be moved to a different address
1526 // synchronize without ggml_backend_sched_synchronize to avoid changing cur_copy
1527 for (int i = 0; i < sched->n_backends; i++) {
1528 ggml_backend_synchronize(sched->backends[i]);
1529 }
1530
1531 ggml_gallocr_reserve_n(sched->galloc, &sched->graph, sched->node_backend_ids, sched->leaf_backend_ids);
1532 if (!ggml_gallocr_alloc_graph(sched->galloc, &sched->graph)) {
1533 GGML_LOG_ERROR("%s: failed to allocate graph\n", __func__)ggml_log_internal(GGML_LOG_LEVEL_ERROR, "%s: failed to allocate graph\n"
, __func__)
;
1534 return false;
1535 }
1536 }
1537
1538 return true;
1539}
1540
1541static enum ggml_status ggml_backend_sched_compute_splits(ggml_backend_sched_t sched) {
1542 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1542, "GGML_ASSERT(%s) failed", "sched")
;
1543 struct ggml_backend_sched_split * splits = sched->splits;
1544
1545 ggml_tensor * prev_ids_tensor = nullptr;
1546 std::vector<int32_t> ids;
1547 std::vector<ggml_bitset_t> used_ids;
1548
1549 for (int split_id = 0; split_id < sched->n_splits; split_id++) {
1550 struct ggml_backend_sched_split * split = &splits[split_id];
1551 int split_backend_id = split->backend_id;
1552 ggml_backend_t split_backend = sched->backends[split_backend_id];
1553
1554 // copy the input tensors to the split backend
1555 for (int input_id = 0; input_id < split->n_inputs; input_id++) {
1556 ggml_backend_t input_backend = ggml_backend_sched_get_tensor_backend(sched, split->inputs[input_id]);
1557 struct ggml_tensor * input = split->inputs[input_id];
1558 struct ggml_tensor * input_cpy = tensor_copy(input, split_backend_id, sched->cur_copy)sched->hv_tensor_copies[(ggml_hash_find_or_insert(&sched
->hash_set, input)) * sched->n_backends * sched->n_copies
+ (split_backend_id) * sched->n_copies + (sched->cur_copy
)]
;
1559
1560 if (input->flags & GGML_TENSOR_FLAG_INPUT) {
1561 // inputs from the user must be copied immediately to prevent the user overwriting the data before the copy is done
1562 if (sched->events[split_backend_id][sched->cur_copy] != NULL__null) {
1563 ggml_backend_event_synchronize(sched->events[split_backend_id][sched->cur_copy]);
1564 } else {
1565 ggml_backend_synchronize(split_backend);
1566 }
1567 ggml_backend_tensor_copy(input, input_cpy);
1568 } else {
1569 // wait for the split backend to finish using the input before overwriting it
1570 if (sched->events[split_backend_id][sched->cur_copy] != NULL__null) {
1571 ggml_backend_event_wait(split_backend, sched->events[split_backend_id][sched->cur_copy]);
1572 } else {
1573 ggml_backend_synchronize(split_backend);
1574 }
1575
1576 // when offloading MoE weights, we can reduce the amount of data copied by copying only the experts that are used
1577 ggml_tensor * node = split->graph.nodes[0];
1578 if (split->graph.n_nodes > 0 &&
1579 ggml_backend_buffer_get_usage(input->buffer) == GGML_BACKEND_BUFFER_USAGE_WEIGHTS &&
1580 ggml_backend_buffer_is_host(input->buffer) && (
1581 (node->src[0] == input_cpy && node->op == GGML_OP_MUL_MAT_ID)
1582 //|| (node->src[1] == input_cpy && node->op == GGML_OP_ADD_ID) /* GGML_OP_ADD_ID weights are small and not worth splitting */
1583 )) {
1584
1585 const int64_t n_expert = node->op == GGML_OP_MUL_MAT_ID ? input->ne[2] : input->ne[1];
1586 const size_t expert_size = node->op == GGML_OP_MUL_MAT_ID ? input->nb[2] : input->nb[1];
1587
1588 ggml_backend_synchronize(input_backend);
1589
1590 // get the ids
1591 ggml_tensor * ids_tensor = node->src[2];
1592 ggml_backend_t ids_backend = split_backend;
1593
1594 // if the ids tensor is also an input of the split, it may not have been copied yet to the split backend
1595 // in that case, we use the original ids tensor
1596 for (int i = input_id + 1; i < split->n_inputs; i++) {
1597 if (ids_tensor == tensor_copy(split->inputs[i], split_backend_id, sched->cur_copy)sched->hv_tensor_copies[(ggml_hash_find_or_insert(&sched
->hash_set, split->inputs[i])) * sched->n_backends *
sched->n_copies + (split_backend_id) * sched->n_copies
+ (sched->cur_copy)]
) {
1598 ids_tensor = split->inputs[i];
1599 ids_backend = ggml_backend_sched_get_tensor_backend(sched, split->inputs[i]);
1600 break;
1601 }
1602 }
1603
1604 if (ids_tensor != prev_ids_tensor) {
1605 ids.resize(ggml_nbytes(ids_tensor) / sizeof(int32_t));
1606 ggml_backend_tensor_get_async(ids_backend, ids_tensor, ids.data(), 0, ggml_nbytes(ids_tensor));
1607 ggml_backend_synchronize(ids_backend);
1608
1609 // find the used experts
1610 used_ids.clear();
1611 used_ids.resize(ggml_bitset_size(n_expert));
1612 for (int64_t i1 = 0; i1 < ids_tensor->ne[1]; i1++) {
1613 for (int64_t i0 = 0; i0 < ids_tensor->ne[0]; i0++) {
1614 int32_t id = ids[i1 * ids_tensor->nb[1]/sizeof(int32_t) + i0 * ids_tensor->nb[0]/sizeof(int32_t)];
1615 GGML_ASSERT(id >= 0 && id < n_expert)if (!(id >= 0 && id < n_expert)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1615, "GGML_ASSERT(%s) failed", "id >= 0 && id < n_expert"
)
;
1616 ggml_bitset_set(used_ids.data(), id);
1617 }
1618 }
1619
1620 prev_ids_tensor = ids_tensor;
1621 }
1622
1623 // group consecutive experts and copy them together
1624 auto copy_experts = [&](int32_t first_id, int32_t last_id) {
1625 const size_t expert_offset = first_id * expert_size;
1626 const size_t expert_size_copy = (last_id - first_id + 1) * expert_size;
1627 const size_t padding = std::min<size_t>(expert_size, 512);
1628 const size_t padding_end = last_id < n_expert - 1 ? padding : 0;
1629
1630 ggml_backend_tensor_set_async(split_backend,
1631 input_cpy,
1632 (const uint8_t *)input->data + expert_offset, expert_offset,
1633 // copy a bit extra at the to ensure there are no NaNs in the padding of the last expert
1634 // this is necessary for MMQ in the CUDA backend
1635 expert_size_copy + padding_end);
1636 };
1637
1638 int id = 0;
1639 while (!ggml_bitset_get(used_ids.data(), id)) {
1640 id++;
1641 }
1642 int32_t first_id = id;
1643 int32_t last_id = first_id;
1644
1645 for (++id; id < n_expert; ++id) {
1646 if (!ggml_bitset_get(used_ids.data(), id)) {
1647 continue;
1648 }
1649
1650 if (id == last_id + 1) {
1651 last_id = id;
1652 continue;
1653 }
1654
1655 copy_experts(first_id, last_id);
1656
1657 first_id = id;
1658 last_id = id;
1659 }
1660 copy_experts(first_id, last_id);
1661 } else {
1662 // try async copy, but if not possible, we can still use a sync copy without synchronizing the dst backend, since we handle the synchronization here with multiple copies and events
1663 // TODO: add public function to facilitate this, since applications do not have direct access to the backend interface
1664 if (!split_backend->iface.cpy_tensor_async || !split_backend->iface.cpy_tensor_async(input_backend, split_backend, input, input_cpy)) {
1665 ggml_backend_synchronize(input_backend);
1666 if (sched->events[split_backend_id][sched->cur_copy] != NULL__null) {
1667 ggml_backend_event_synchronize(sched->events[split_backend_id][sched->cur_copy]);
1668 } else {
1669 ggml_backend_synchronize(split_backend);
1670 }
1671 ggml_backend_tensor_copy(input, input_cpy);
1672 }
1673 }
1674 }
1675 }
1676
1677 if (!sched->callback_eval) {
1678 enum ggml_status ec = ggml_backend_graph_compute_async(split_backend, &split->graph);
1679 if (ec != GGML_STATUS_SUCCESS) {
1680 return ec;
1681 }
1682 } else {
1683 // similar to ggml_backend_compare_graph_backend
1684 for (int j0 = 0; j0 < split->graph.n_nodes; j0++) {
1685 struct ggml_tensor * t = split->graph.nodes[j0];
1686
1687 // check if the user needs data from this node
1688 bool need = sched->callback_eval(t, true, sched->callback_eval_user_data);
1689
1690 int j1 = j0;
1691
1692 // determine the range [j0, j1] of nodes that can be computed together
1693 while (!need && j1 < split->graph.n_nodes - 1) {
1694 t = split->graph.nodes[++j1];
1695 need = sched->callback_eval(t, true, sched->callback_eval_user_data);
1696 }
1697
1698 struct ggml_cgraph gv = ggml_graph_view(&split->graph, j0, j1 + 1);
1699
1700 enum ggml_status ec = ggml_backend_graph_compute_async(split_backend, &gv);
1701 if (ec != GGML_STATUS_SUCCESS) {
1702 return ec;
1703 }
1704
1705 // TODO: pass backend to the callback, then the user can decide if they want to synchronize
1706 ggml_backend_synchronize(split_backend);
1707
1708 if (need && !sched->callback_eval(t, false, sched->callback_eval_user_data)) {
1709 break;
1710 }
1711
1712 j0 = j1;
1713 }
1714 }
1715
1716 // record the event of this copy
1717 if (split->n_inputs > 0) {
1718 if (sched->events[split_backend_id][sched->cur_copy] != NULL__null) {
1719 ggml_backend_event_record(sched->events[split_backend_id][sched->cur_copy], split_backend);
1720 }
1721 }
1722 }
1723
1724 return GGML_STATUS_SUCCESS;
1725}
1726
1727ggml_backend_sched_t ggml_backend_sched_new(
1728 ggml_backend_t * backends,
1729 ggml_backend_buffer_type_t * bufts,
1730 int n_backends,
1731 size_t graph_size,
1732 bool parallel,
1733 bool op_offload) {
1734 GGML_ASSERT(n_backends > 0)if (!(n_backends > 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1734, "GGML_ASSERT(%s) failed", "n_backends > 0")
;
1735 GGML_ASSERT(n_backends <= GGML_SCHED_MAX_BACKENDS)if (!(n_backends <= 16)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1735, "GGML_ASSERT(%s) failed", "n_backends <= GGML_SCHED_MAX_BACKENDS"
)
;
1736 GGML_ASSERT(ggml_backend_dev_type(ggml_backend_get_device(backends[n_backends - 1])) == GGML_BACKEND_DEVICE_TYPE_CPU)if (!(ggml_backend_dev_type(ggml_backend_get_device(backends[
n_backends - 1])) == GGML_BACKEND_DEVICE_TYPE_CPU)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1736, "GGML_ASSERT(%s) failed", "ggml_backend_dev_type(ggml_backend_get_device(backends[n_backends - 1])) == GGML_BACKEND_DEVICE_TYPE_CPU"
)
;
1737
1738 struct ggml_backend_sched * sched = (ggml_backend_sched *) calloc(1, sizeof(struct ggml_backend_sched));
1739
1740 const char * GGML_SCHED_DEBUG = getenv("GGML_SCHED_DEBUG");
1741 sched->debug = GGML_SCHED_DEBUG ? atoi(GGML_SCHED_DEBUG) : 0;
1742
1743 sched->debug_realloc = 0;
1744#ifdef GGML_SCHED_NO_REALLOC
1745 sched->debug_realloc = 1;
1746#endif
1747 const char * GGML_SCHED_DEBUG_REALLOC = getenv("GGML_SCHED_DEBUG_REALLOC");
1748 sched->debug_realloc = GGML_SCHED_DEBUG_REALLOC ? atoi(GGML_SCHED_DEBUG_REALLOC) : sched->debug_realloc;
1749
1750 sched->n_backends = n_backends;
1751 sched->n_copies = parallel ? GGML_SCHED_MAX_COPIES4 : 1;
1752
1753 // initialize hash table
1754 // FIXME: needs to be size*2 to account for leafs (do it in graph_split instead)
1755 sched->hash_set = ggml_hash_set_new(graph_size);
1756 sched->hv_tensor_backend_ids = (int *) malloc(sched->hash_set.size * sizeof(sched->hv_tensor_backend_ids[0]));
1757 sched->hv_tensor_copies = (ggml_tensor **) malloc(sched->hash_set.size * sched->n_backends * sched->n_copies * sizeof(struct ggml_tensor *));
1758
1759 const size_t ggml_sched_max_splits = graph_size; // at most there is one split for each node in the graph
1760 const size_t nodes_size = graph_size + ggml_sched_max_splits*GGML_SCHED_MAX_SPLIT_INPUTS30*2;
1761 sched->node_backend_ids = (int *) calloc(nodes_size, sizeof(sched->node_backend_ids[0]));
1762 sched->leaf_backend_ids = (int *) calloc(nodes_size, sizeof(sched->leaf_backend_ids[0]));
1763 sched->prev_node_backend_ids = (int *) calloc(nodes_size, sizeof(sched->prev_node_backend_ids[0]));
1764 sched->prev_leaf_backend_ids = (int *) calloc(nodes_size, sizeof(sched->prev_leaf_backend_ids[0]));
1765
1766 sched->debug_graph_size = 0;
1767 sched->debug_prev_graph_size = 0;
1768
1769 sched->context_buffer_size = ggml_sched_max_splits*GGML_SCHED_MAX_SPLIT_INPUTS30*2*sizeof(struct ggml_tensor) + ggml_graph_overhead_custom(graph_size, false);
1770 sched->context_buffer = (char *) malloc(sched->context_buffer_size);
1771
1772 const int initial_splits_capacity = 16;
1773 sched->splits = (ggml_backend_sched_split *) calloc(initial_splits_capacity, sizeof(sched->splits[0]));
1774 sched->splits_capacity = initial_splits_capacity;
1775
1776 for (int b = 0; b < n_backends; b++) {
1777 sched->backends[b] = backends[b];
1778 sched->bufts[b] = bufts ? bufts[b] : ggml_backend_get_default_buffer_type(backends[b]);
1779 GGML_ASSERT(ggml_backend_supports_buft(backends[b], sched->bufts[b]))if (!(ggml_backend_supports_buft(backends[b], sched->bufts
[b]))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1779, "GGML_ASSERT(%s) failed", "ggml_backend_supports_buft(backends[b], sched->bufts[b])"
)
;
1780
1781 if (sched->n_copies > 1) {
1782 for (int c = 0; c < sched->n_copies; c++) {
1783 sched->events[b][c] = ggml_backend_event_new(backends[b]->device);
1784 }
1785 }
1786 }
1787
1788 sched->galloc = ggml_gallocr_new_n(sched->bufts, n_backends);
1789 sched->op_offload = op_offload;
1790
1791 ggml_backend_sched_reset(sched);
1792
1793 return sched;
1794}
1795
1796void ggml_backend_sched_free(ggml_backend_sched_t sched) {
1797 if (sched == NULL__null) {
1798 return;
1799 }
1800 for (int b = 0; b < sched->n_backends; b++) {
1801 for (int c = 0; c < sched->n_copies; c++) {
1802 ggml_backend_event_free(sched->events[b][c]);
1803 }
1804 }
1805 ggml_gallocr_free(sched->galloc);
1806 ggml_free(sched->ctx);
1807 ggml_hash_set_free(&sched->hash_set);
1808 free(sched->splits);
1809 free(sched->hv_tensor_backend_ids);
1810 free(sched->hv_tensor_copies);
1811 free(sched->node_backend_ids);
1812 free(sched->leaf_backend_ids);
1813 free(sched->prev_node_backend_ids);
1814 free(sched->prev_leaf_backend_ids);
1815 free(sched->context_buffer);
1816 free(sched->graph.nodes);
1817 free(sched->graph.leafs);
1818 free(sched);
1819}
1820
1821void ggml_backend_sched_reset(ggml_backend_sched_t sched) {
1822 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1822, "GGML_ASSERT(%s) failed", "sched")
;
1823 // reset state for the next run
1824 if (!sched->is_reset) {
1825 ggml_hash_set_reset(&sched->hash_set);
1826 memset(sched->hv_tensor_backend_ids, -1, sched->hash_set.size * sizeof(sched->hv_tensor_backend_ids[0]));
1827 memset(sched->hv_tensor_copies, 0, sched->hash_set.size * sched->n_backends * sched->n_copies * sizeof(struct ggml_tensor *));
1828 sched->is_reset = true;
1829 }
1830 sched->is_alloc = false;
1831}
1832
1833void ggml_backend_sched_reserve_size(ggml_backend_sched_t sched, struct ggml_cgraph * measure_graph, size_t * sizes) {
1834 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1834, "GGML_ASSERT(%s) failed", "sched")
;
1835 GGML_ASSERT((int)sched->hash_set.size >= measure_graph->n_nodes + measure_graph->n_leafs)if (!((int)sched->hash_set.size >= measure_graph->n_nodes
+ measure_graph->n_leafs)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1835, "GGML_ASSERT(%s) failed", "(int)sched->hash_set.size >= measure_graph->n_nodes + measure_graph->n_leafs"
)
;
1836 GGML_ASSERT(sizes)if (!(sizes)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1836, "GGML_ASSERT(%s) failed", "sizes")
;
1837
1838 ggml_backend_sched_reset(sched);
1839
1840 ggml_backend_sched_synchronize(sched);
1841
1842 ggml_backend_sched_split_graph(sched, measure_graph);
1843
1844 ggml_gallocr_reserve_n_size(sched->galloc, &sched->graph, sched->node_backend_ids, sched->leaf_backend_ids, sizes);
1845}
1846
1847bool ggml_backend_sched_reserve(ggml_backend_sched_t sched, struct ggml_cgraph * measure_graph) {
1848 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1848, "GGML_ASSERT(%s) failed", "sched")
;
1849 GGML_ASSERT((int)sched->hash_set.size >= measure_graph->n_nodes + measure_graph->n_leafs)if (!((int)sched->hash_set.size >= measure_graph->n_nodes
+ measure_graph->n_leafs)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1849, "GGML_ASSERT(%s) failed", "(int)sched->hash_set.size >= measure_graph->n_nodes + measure_graph->n_leafs"
)
;
1850
1851 ggml_backend_sched_synchronize(sched);
1852
1853 ggml_backend_sched_split_graph(sched, measure_graph);
1854
1855 if (!ggml_gallocr_reserve_n(sched->galloc, &sched->graph, sched->node_backend_ids, sched->leaf_backend_ids)) {
1856 return false;
1857 }
1858
1859 ggml_backend_sched_reset(sched);
1860
1861 return true;
1862}
1863
1864bool ggml_backend_sched_alloc_graph(ggml_backend_sched_t sched, struct ggml_cgraph * graph) {
1865 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1865, "GGML_ASSERT(%s) failed", "sched")
;
1866 GGML_ASSERT((int)sched->hash_set.size >= graph->n_nodes + graph->n_leafs)if (!((int)sched->hash_set.size >= graph->n_nodes + graph
->n_leafs)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1866, "GGML_ASSERT(%s) failed", "(int)sched->hash_set.size >= graph->n_nodes + graph->n_leafs"
)
;
1867 GGML_ASSERT(!sched->is_alloc)if (!(!sched->is_alloc)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1867, "GGML_ASSERT(%s) failed", "!sched->is_alloc")
;
1868
1869 sched->cur_copy = sched->next_copy;
1870 sched->next_copy = (sched->next_copy + 1) % sched->n_copies;
1871
1872 ggml_backend_sched_split_graph(sched, graph);
1873
1874 if (!ggml_backend_sched_alloc_splits(sched)) {
1875 return false;
1876 }
1877
1878 sched->is_alloc = true;
1879
1880 return true;
1881}
1882
1883enum ggml_status ggml_backend_sched_graph_compute(ggml_backend_sched_t sched, struct ggml_cgraph * graph) {
1884 enum ggml_status err = ggml_backend_sched_graph_compute_async(sched, graph);
1885 ggml_backend_sched_synchronize(sched);
1886 return err;
1887}
1888
1889enum ggml_status ggml_backend_sched_graph_compute_async(ggml_backend_sched_t sched, struct ggml_cgraph * graph) {
1890 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1890, "GGML_ASSERT(%s) failed", "sched")
;
1891 if (!sched->is_reset && !sched->is_alloc) {
1892 ggml_backend_sched_reset(sched);
1893 }
1894
1895 if (!sched->is_alloc) {
1896 if (!ggml_backend_sched_alloc_graph(sched, graph)) {
1897 return GGML_STATUS_ALLOC_FAILED;
1898 }
1899 }
1900
1901 return ggml_backend_sched_compute_splits(sched);
1902}
1903
1904void ggml_backend_sched_synchronize(ggml_backend_sched_t sched) {
1905 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1905, "GGML_ASSERT(%s) failed", "sched")
;
1906 for (int i = 0; i < sched->n_backends; i++) {
1907 ggml_backend_synchronize(sched->backends[i]);
1908 }
1909 if (!sched->is_alloc) {
1910 // if the graph is not already allocated, always use copy 0 after a synchronization
1911 // this ensures that during generation the same copy is used every time,
1912 // which avoids changes in the graph that could cause CUDA or other graphs to be disabled
1913 sched->next_copy = 0;
1914 }
1915}
1916
1917void ggml_backend_sched_set_eval_callback(ggml_backend_sched_t sched, ggml_backend_sched_eval_callback callback, void * user_data) {
1918 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1918, "GGML_ASSERT(%s) failed", "sched")
;
1919 sched->callback_eval = callback;
1920 sched->callback_eval_user_data = user_data;
1921}
1922
1923int ggml_backend_sched_get_n_splits(ggml_backend_sched_t sched) {
1924 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1924, "GGML_ASSERT(%s) failed", "sched")
;
1925 return sched->n_splits;
1926}
1927
1928int ggml_backend_sched_get_n_copies(ggml_backend_sched_t sched) {
1929 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1929, "GGML_ASSERT(%s) failed", "sched")
;
1930 return sched->n_copies;
1931}
1932
1933int ggml_backend_sched_get_n_backends(ggml_backend_sched_t sched) {
1934 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1934, "GGML_ASSERT(%s) failed", "sched")
;
1935 return sched->n_backends;
1936}
1937
1938ggml_backend_t ggml_backend_sched_get_backend(ggml_backend_sched_t sched, int i) {
1939 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1939, "GGML_ASSERT(%s) failed", "sched")
;
1940 GGML_ASSERT(i >= 0 && i < sched->n_backends)if (!(i >= 0 && i < sched->n_backends)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1940, "GGML_ASSERT(%s) failed", "i >= 0 && i < sched->n_backends"
)
;
1941 return sched->backends[i];
1942}
1943
1944ggml_backend_buffer_type_t ggml_backend_sched_get_buffer_type(ggml_backend_sched_t sched, ggml_backend_t backend) {
1945 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1945, "GGML_ASSERT(%s) failed", "sched")
;
1946 int backend_index = ggml_backend_sched_backend_id(sched, backend);
1947 GGML_ASSERT(backend_index >= 0 && backend_index < sched->n_backends)if (!(backend_index >= 0 && backend_index < sched
->n_backends)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1947, "GGML_ASSERT(%s) failed", "backend_index >= 0 && backend_index < sched->n_backends"
)
;
1948
1949 return sched->bufts[backend_index];
1950}
1951
1952size_t ggml_backend_sched_get_buffer_size(ggml_backend_sched_t sched, ggml_backend_t backend) {
1953 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1953, "GGML_ASSERT(%s) failed", "sched")
;
1954 int backend_index = ggml_backend_sched_backend_id(sched, backend);
1955 GGML_ASSERT(backend_index >= 0 && backend_index < sched->n_backends)if (!(backend_index >= 0 && backend_index < sched
->n_backends)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1955, "GGML_ASSERT(%s) failed", "backend_index >= 0 && backend_index < sched->n_backends"
)
;
1956
1957 return ggml_gallocr_get_buffer_size(sched->galloc, backend_index);
1958}
1959
1960void ggml_backend_sched_set_tensor_backend(ggml_backend_sched_t sched, struct ggml_tensor * node, ggml_backend_t backend) {
1961 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1961, "GGML_ASSERT(%s) failed", "sched")
;
1962 int backend_index = ggml_backend_sched_backend_id(sched, backend);
1963 GGML_ASSERT(backend_index >= 0 && backend_index < sched->n_backends)if (!(backend_index >= 0 && backend_index < sched
->n_backends)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1963, "GGML_ASSERT(%s) failed", "backend_index >= 0 && backend_index < sched->n_backends"
)
;
1964 tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
= backend_index;
1965 SET_CAUSE(node, "usr");
1966 sched->is_reset = false;
1967}
1968
1969ggml_backend_t ggml_backend_sched_get_tensor_backend(ggml_backend_sched_t sched, struct ggml_tensor * node) {
1970 GGML_ASSERT(sched)if (!(sched)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1970, "GGML_ASSERT(%s) failed", "sched")
;
1971 int backend_index = tensor_backend_id(node)sched->hv_tensor_backend_ids[ggml_hash_find_or_insert(&
sched->hash_set, node)]
;
1972 if (backend_index == -1) {
1973 return NULL__null;
1974 }
1975 return sched->backends[backend_index];
1976}
1977
1978// utils
1979
1980enum ggml_status ggml_backend_view_init(struct ggml_tensor * tensor) {
1981 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1981, "GGML_ASSERT(%s) failed", "tensor")
;
1982 GGML_ASSERT(tensor->buffer == NULL)if (!(tensor->buffer == __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1982, "GGML_ASSERT(%s) failed", "tensor->buffer == NULL"
)
;
1983 GGML_ASSERT(tensor->view_src != NULL)if (!(tensor->view_src != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1983, "GGML_ASSERT(%s) failed", "tensor->view_src != NULL"
)
;
1984 GGML_ASSERT(tensor->view_src->buffer != NULL)if (!(tensor->view_src->buffer != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1984, "GGML_ASSERT(%s) failed", "tensor->view_src->buffer != NULL"
)
;
1985 GGML_ASSERT(tensor->view_src->data != NULL)if (!(tensor->view_src->data != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1985, "GGML_ASSERT(%s) failed", "tensor->view_src->data != NULL"
)
;
1986
1987 tensor->buffer = tensor->view_src->buffer;
1988 tensor->data = (char *)tensor->view_src->data + tensor->view_offs;
1989 return ggml_backend_buffer_init_tensor(tensor->buffer, tensor);
1990}
1991
1992enum ggml_status ggml_backend_tensor_alloc(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, void * addr) {
1993 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1993, "GGML_ASSERT(%s) failed", "tensor")
;
1994 GGML_ASSERT(tensor->buffer == NULL)if (!(tensor->buffer == __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1994, "GGML_ASSERT(%s) failed", "tensor->buffer == NULL"
)
;
1995 GGML_ASSERT(tensor->data == NULL)if (!(tensor->data == __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1995, "GGML_ASSERT(%s) failed", "tensor->data == NULL")
;
1996 GGML_ASSERT(tensor->view_src == NULL)if (!(tensor->view_src == __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1996, "GGML_ASSERT(%s) failed", "tensor->view_src == NULL"
)
;
1997 GGML_ASSERT(addr >= ggml_backend_buffer_get_base(buffer))if (!(addr >= ggml_backend_buffer_get_base(buffer))) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 1997, "GGML_ASSERT(%s) failed", "addr >= ggml_backend_buffer_get_base(buffer)"
)
;
1998 GGML_ASSERT(ggml_backend_buffer_is_meta(buffer) ||if (!(ggml_backend_buffer_is_meta(buffer) || (char *) addr + ggml_backend_buffer_get_alloc_size
(buffer, tensor) <= (char *) ggml_backend_buffer_get_base(
buffer) + ggml_backend_buffer_get_size(buffer))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2000, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(buffer) || (char *) addr + ggml_backend_buffer_get_alloc_size(buffer, tensor) <= (char *) ggml_backend_buffer_get_base(buffer) + ggml_backend_buffer_get_size(buffer)"
)
1999 (char *) addr + ggml_backend_buffer_get_alloc_size(buffer, tensor) <=if (!(ggml_backend_buffer_is_meta(buffer) || (char *) addr + ggml_backend_buffer_get_alloc_size
(buffer, tensor) <= (char *) ggml_backend_buffer_get_base(
buffer) + ggml_backend_buffer_get_size(buffer))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2000, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(buffer) || (char *) addr + ggml_backend_buffer_get_alloc_size(buffer, tensor) <= (char *) ggml_backend_buffer_get_base(buffer) + ggml_backend_buffer_get_size(buffer)"
)
2000 (char *) ggml_backend_buffer_get_base(buffer) + ggml_backend_buffer_get_size(buffer))if (!(ggml_backend_buffer_is_meta(buffer) || (char *) addr + ggml_backend_buffer_get_alloc_size
(buffer, tensor) <= (char *) ggml_backend_buffer_get_base(
buffer) + ggml_backend_buffer_get_size(buffer))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2000, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(buffer) || (char *) addr + ggml_backend_buffer_get_alloc_size(buffer, tensor) <= (char *) ggml_backend_buffer_get_base(buffer) + ggml_backend_buffer_get_size(buffer)"
)
;
2001
2002 tensor->buffer = buffer;
2003 tensor->data = addr;
2004 return ggml_backend_buffer_init_tensor(buffer, tensor);
2005}
2006
2007static struct ggml_tensor * graph_copy_dup_tensor(struct ggml_hash_set hash_set, struct ggml_tensor ** node_copies,
2008 struct ggml_context * ctx_allocated, struct ggml_context * ctx_unallocated, struct ggml_tensor * src) {
2009
2010 GGML_ASSERT(src != NULL)if (!(src != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2010, "GGML_ASSERT(%s) failed", "src != NULL")
;
11
Assuming the condition is true
2011 GGML_ASSERT(src->data && "graph must be allocated")if (!(src->data && "graph must be allocated")) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2011, "GGML_ASSERT(%s) failed", "src->data && \"graph must be allocated\""
)
;
12
Taking false branch
13
Assuming field 'data' is non-null
14
Taking false branch
2012
2013 size_t id = ggml_hash_insert(&hash_set, src);
2014 if (id == GGML_HASHSET_ALREADY_EXISTS((size_t)-2)) {
15
Taking true branch
2015 return node_copies[ggml_hash_find(&hash_set, src)];
2016 }
2017
2018 struct ggml_tensor * dst = ggml_dup_tensor_layout(src->data && !src->view_src ? ctx_allocated : ctx_unallocated, src);
2019 if (src->view_src != NULL__null) {
2020 dst->view_src = graph_copy_dup_tensor(hash_set, node_copies, ctx_allocated, ctx_unallocated, src->view_src);
2021 dst->view_offs = src->view_offs;
2022 }
2023 dst->op = src->op;
2024 dst->flags = src->flags;
2025 memcpy(dst->op_params, src->op_params, sizeof(dst->op_params));
2026 ggml_set_name(dst, src->name);
2027
2028 // copy src
2029 for (int i = 0; i < GGML_MAX_SRC10; i++) {
2030 struct ggml_tensor * s = src->src[i];
2031 if (s == NULL__null) {
2032 continue;
2033 }
2034 dst->src[i] = graph_copy_dup_tensor(hash_set, node_copies, ctx_allocated, ctx_unallocated, s);
2035 }
2036
2037 node_copies[id] = dst;
2038 return dst;
2039}
2040
2041static void graph_copy_init_tensor(struct ggml_hash_set * hash_set, struct ggml_tensor ** node_copies, bool * node_init, struct ggml_tensor * src) {
2042 size_t id = ggml_hash_find(hash_set, src);
23
Calling 'ggml_hash_find'
30
Returning from 'ggml_hash_find'
31
'id' initialized to 18446744073709551615
2043 if (node_init[id]) {
32
Taking false branch
2044 return;
2045 }
2046 node_init[id] = true;
2047
2048 struct ggml_tensor * dst = node_copies[id];
33
'dst' initialized to a null pointer value
2049 if (dst->view_src != NULL__null) {
34
Access to field 'view_src' results in a dereference of a null pointer (loaded from variable 'dst')
2050 graph_copy_init_tensor(hash_set, node_copies, node_init, src->view_src);
2051 enum ggml_status status = ggml_backend_view_init(dst);
2052 GGML_ASSERT(status == GGML_STATUS_SUCCESS)if (!(status == GGML_STATUS_SUCCESS)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2052, "GGML_ASSERT(%s) failed", "status == GGML_STATUS_SUCCESS"
)
;
2053 }
2054 else {
2055 ggml_backend_tensor_copy(src, dst);
2056 }
2057
2058 // init src
2059 for (int i = 0; i < GGML_MAX_SRC10; i++) {
2060 struct ggml_tensor * s = src->src[i];
2061 if (s == NULL__null) {
2062 continue;
2063 }
2064 graph_copy_init_tensor(hash_set, node_copies, node_init, s);
2065 }
2066}
2067
2068struct ggml_backend_graph_copy ggml_backend_graph_copy(ggml_backend_t backend, struct ggml_cgraph * graph) {
2069 GGML_ASSERT(graph)if (!(graph)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2069, "GGML_ASSERT(%s) failed", "graph")
;
2
Assuming 'graph' is non-null
3
Taking false branch
2070 struct ggml_hash_set hash_set = ggml_hash_set_new(graph->visited_hash_set.size);
2071 struct ggml_tensor ** node_copies = (ggml_tensor **) calloc(hash_set.size, sizeof(node_copies[0])); // NOLINT
4
Storing null pointer value
2072 bool * node_init = (bool *) calloc(hash_set.size, sizeof(node_init[0]));
2073
2074 struct ggml_init_params params = {
2075 /* .mem_size = */ ggml_tensor_overhead()*hash_set.size + ggml_graph_overhead_custom(graph->size, false),
2076 /* .mem_buffer = */ NULL__null,
2077 /* .no_alloc = */ true
2078 };
2079
2080 struct ggml_context * ctx_allocated = ggml_init(params);
2081 struct ggml_context * ctx_unallocated = ggml_init(params);
2082
2083 if (ctx_allocated == NULL__null || ctx_unallocated == NULL__null) {
5
Assuming 'ctx_allocated' is not equal to NULL
6
Assuming 'ctx_unallocated' is not equal to NULL
7
Taking false branch
2084 GGML_LOG_ERROR("%s: failed to allocate context for graph copy\n", __func__)ggml_log_internal(GGML_LOG_LEVEL_ERROR, "%s: failed to allocate context for graph copy\n"
, __func__)
;
2085 ggml_hash_set_free(&hash_set);
2086 free(node_copies);
2087 free(node_init);
2088 ggml_free(ctx_allocated);
2089 ggml_free(ctx_unallocated);
2090 return {
2091 /* .buffer = */ NULL__null,
2092 /* .ctx_allocated = */ NULL__null,
2093 /* .ctx_unallocated = */ NULL__null,
2094 /* .graph = */ NULL__null,
2095 };
2096 }
2097
2098 // dup nodes
2099 for (int i = 0; i < graph->n_nodes; i++) {
8
Assuming 'i' is < field 'n_nodes'
9
Loop condition is true. Entering loop body
17
Assuming 'i' is >= field 'n_nodes'
18
Loop condition is false. Execution continues on line 2105
2100 struct ggml_tensor * node = graph->nodes[i];
2101 graph_copy_dup_tensor(hash_set, node_copies, ctx_allocated, ctx_unallocated, node);
10
Calling 'graph_copy_dup_tensor'
16
Returning from 'graph_copy_dup_tensor'
2102 }
2103
2104 // allocate nodes
2105 ggml_backend_buffer_t buffer = ggml_backend_alloc_ctx_tensors(ctx_allocated, backend);
2106 if (buffer == NULL__null) {
19
Assuming 'buffer' is not equal to NULL
20
Taking false branch
2107 GGML_LOG_ERROR("%s: failed to allocate buffer for graph copy\n", __func__)ggml_log_internal(GGML_LOG_LEVEL_ERROR, "%s: failed to allocate buffer for graph copy\n"
, __func__)
;
2108 ggml_hash_set_free(&hash_set);
2109 free(node_copies);
2110 free(node_init);
2111 ggml_free(ctx_allocated);
2112 ggml_free(ctx_unallocated);
2113 return {
2114 /* .buffer = */ NULL__null,
2115 /* .ctx_allocated = */ NULL__null,
2116 /* .ctx_unallocated = */ NULL__null,
2117 /* .graph = */ NULL__null,
2118 };
2119 }
2120
2121 //printf("copy buffer size: %zu MB\n", ggml_backend_buffer_get_size(buffer) / 1024 / 1024);
2122
2123 // copy data and init views
2124 for (int i = 0; i < graph->n_nodes; i++) {
21
Loop condition is true. Entering loop body
2125 struct ggml_tensor * node = graph->nodes[i];
2126 graph_copy_init_tensor(&hash_set, node_copies, node_init, node);
22
Calling 'graph_copy_init_tensor'
2127 }
2128
2129 // build graph copy
2130 struct ggml_cgraph * graph_copy = ggml_new_graph_custom(ctx_allocated, graph->size, false);
2131 for (int i = 0; i < graph->n_nodes; i++) {
2132 struct ggml_tensor * node = graph->nodes[i];
2133 struct ggml_tensor * node_copy = node_copies[ggml_hash_find(&hash_set, node)];
2134 graph_copy->nodes[i] = node_copy;
2135 }
2136 graph_copy->n_nodes = graph->n_nodes;
2137
2138 ggml_hash_set_free(&hash_set);
2139 free(node_copies);
2140 free(node_init);
2141
2142 return {
2143 /* .buffer = */ buffer,
2144 /* .ctx_allocated = */ ctx_allocated,
2145 /* .ctx_unallocated = */ ctx_unallocated,
2146 /* .graph = */ graph_copy,
2147 };
2148}
2149
2150void ggml_backend_graph_copy_free(struct ggml_backend_graph_copy copy) {
2151 ggml_backend_buffer_free(copy.buffer);
2152 ggml_free(copy.ctx_allocated);
2153 ggml_free(copy.ctx_unallocated);
2154}
2155
2156bool ggml_backend_compare_graph_backend(ggml_backend_t backend1, ggml_backend_t backend2, struct ggml_cgraph * graph, ggml_backend_eval_callback callback, void * user_data, struct ggml_tensor const * const * test_nodes, size_t num_test_nodes) {
2157 struct ggml_backend_graph_copy copy = ggml_backend_graph_copy(backend2, graph);
1
Calling 'ggml_backend_graph_copy'
2158 if (copy.buffer == NULL__null) {
2159 return false;
2160 }
2161
2162 struct ggml_cgraph * g1 = graph;
2163 struct ggml_cgraph * g2 = copy.graph;
2164
2165 assert(g1->n_nodes == g2->n_nodes)(static_cast <bool> (g1->n_nodes == g2->n_nodes) ?
void (0) : __assert_fail ("g1->n_nodes == g2->n_nodes"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
2166
2167 if (num_test_nodes != 0) {
2168 GGML_ASSERT(test_nodes)if (!(test_nodes)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2168, "GGML_ASSERT(%s) failed", "test_nodes")
;
2169 // Compute the whole graph and only test the output for specific tensors
2170 ggml_backend_graph_compute(backend1, g1);
2171 ggml_backend_graph_compute(backend2, g2);
2172
2173 bool verified = false;
2174 for (int i = 0; i < g1->n_nodes; i++) {
2175 for (size_t j = 0; j < num_test_nodes; ++j) {
2176 if (g1->nodes[i] == test_nodes[j]) {
2177 callback(i, g1->nodes[i], g2->nodes[i], user_data);
2178 verified = true;
2179 }
2180 }
2181 }
2182 GGML_ASSERT(verified)if (!(verified)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2182, "GGML_ASSERT(%s) failed", "verified")
;
2183 } else {
2184 for (int i = 0; i < g1->n_nodes; i++) {
2185 struct ggml_tensor * t1 = g1->nodes[i];
2186 struct ggml_tensor * t2 = g2->nodes[i];
2187
2188 assert(t1->op == t2->op && ggml_are_same_layout(t1, t2))(static_cast <bool> (t1->op == t2->op && ggml_are_same_layout
(t1, t2)) ? void (0) : __assert_fail ("t1->op == t2->op && ggml_are_same_layout(t1, t2)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
2189
2190 struct ggml_cgraph g1v = ggml_graph_view(g1, i, i + 1);
2191 struct ggml_cgraph g2v = ggml_graph_view(g2, i, i + 1);
2192
2193 ggml_backend_graph_compute(backend1, &g1v);
2194 ggml_backend_graph_compute(backend2, &g2v);
2195
2196 if (ggml_is_view_op(t1->op)) {
2197 continue;
2198 }
2199
2200 // compare results, calculate rms etc
2201 if (!callback(i, t1, t2, user_data)) {
2202 break;
2203 }
2204 }
2205 }
2206 ggml_backend_graph_copy_free(copy);
2207
2208 return true;
2209}
2210
2211// CPU backend - buffer
2212
2213static void * ggml_backend_cpu_buffer_get_base(ggml_backend_buffer_t buffer) {
2214 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2214, "GGML_ASSERT(%s) failed", "buffer")
;
2215 uintptr_t data = (uintptr_t)buffer->context;
2216
2217 // align the buffer
2218 if (data % TENSOR_ALIGNMENT32 != 0) {
2219 data = GGML_PAD(data, TENSOR_ALIGNMENT)(((data) + (32) - 1) & ~((32) - 1));
2220 }
2221
2222 return (void *)data;
2223}
2224
2225static void ggml_backend_cpu_buffer_free_buffer(ggml_backend_buffer_t buffer) {
2226 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2226, "GGML_ASSERT(%s) failed", "buffer")
;
2227 ggml_aligned_free(buffer->context, buffer->size);
2228}
2229
2230static void ggml_backend_cpu_buffer_memset_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, uint8_t value, size_t offset, size_t size) {
2231 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2231, "GGML_ASSERT(%s) failed", "tensor")
;
2232 memset((char *)tensor->data + offset, value, size);
2233
2234 GGML_UNUSED(buffer)(void)(buffer);
2235}
2236
2237static void ggml_backend_cpu_buffer_set_tensor(ggml_backend_buffer_t buffer, struct ggml_tensor * tensor, const void * data, size_t offset, size_t size) {
2238 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2238, "GGML_ASSERT(%s) failed", "tensor")
;
2239 memcpy((char *)tensor->data + offset, data, size);
2240
2241 GGML_UNUSED(buffer)(void)(buffer);
2242}
2243
2244static void ggml_backend_cpu_buffer_get_tensor(ggml_backend_buffer_t buffer, const struct ggml_tensor * tensor, void * data, size_t offset, size_t size) {
2245 GGML_ASSERT(tensor)if (!(tensor)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2245, "GGML_ASSERT(%s) failed", "tensor")
;
2246 memcpy(data, (const char *)tensor->data + offset, size);
2247
2248 GGML_UNUSED(buffer)(void)(buffer);
2249}
2250
2251static bool ggml_backend_cpu_buffer_cpy_tensor(ggml_backend_buffer_t buffer, const struct ggml_tensor * src, struct ggml_tensor * dst) {
2252 GGML_ASSERT(src)if (!(src)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2252, "GGML_ASSERT(%s) failed", "src")
;
2253 if (ggml_backend_buffer_is_host(src->buffer)) {
2254 memcpy(dst->data, src->data, ggml_nbytes(src));
2255 return true;
2256 }
2257 return false;
2258
2259 GGML_UNUSED(buffer)(void)(buffer);
2260}
2261
2262static void ggml_backend_cpu_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
2263 GGML_ASSERT(buffer)if (!(buffer)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2263, "GGML_ASSERT(%s) failed", "buffer")
;
2264 memset(buffer->context, value, buffer->size);
2265}
2266
2267static const struct ggml_backend_buffer_i ggml_backend_cpu_buffer_i = {
2268 /* .free_buffer = */ ggml_backend_cpu_buffer_free_buffer,
2269 /* .get_base = */ ggml_backend_cpu_buffer_get_base,
2270 /* .init_tensor = */ NULL__null, // no initialization required
2271 /* .memset_tensor = */ ggml_backend_cpu_buffer_memset_tensor,
2272 /* .set_tensor = */ ggml_backend_cpu_buffer_set_tensor,
2273 /* .get_tensor = */ ggml_backend_cpu_buffer_get_tensor,
2274 /* .set_tensor_2d = */ NULL__null,
2275 /* .get_tensor_2d = */ NULL__null,
2276 /* .cpy_tensor = */ ggml_backend_cpu_buffer_cpy_tensor,
2277 /* .clear = */ ggml_backend_cpu_buffer_clear,
2278 /* .reset = */ NULL__null,
2279};
2280
2281static const struct ggml_backend_buffer_i ggml_backend_cpu_buffer_from_ptr_i = {
2282 /* .free_buffer = */ NULL__null, // ptr is not owned by the buffer, so it does not need to be freed
2283 /* .get_base = */ ggml_backend_cpu_buffer_get_base,
2284 /* .init_tensor = */ NULL__null, // no initialization required
2285 /* .memset_tensor = */ ggml_backend_cpu_buffer_memset_tensor,
2286 /* .set_tensor = */ ggml_backend_cpu_buffer_set_tensor,
2287 /* .get_tensor = */ ggml_backend_cpu_buffer_get_tensor,
2288 /* .set_tensor_2d = */ NULL__null,
2289 /* .get_tensor_2d = */ NULL__null,
2290 /* .cpy_tensor = */ ggml_backend_cpu_buffer_cpy_tensor,
2291 /* .clear = */ ggml_backend_cpu_buffer_clear,
2292 /* .reset = */ NULL__null,
2293};
2294
2295// CPU backend buffer type
2296
2297// this buffer type is defined here to make it available to all backends
2298
2299static const char * ggml_backend_cpu_buffer_type_get_name(ggml_backend_buffer_type_t buft) {
2300 return "CPU";
2301
2302 GGML_UNUSED(buft)(void)(buft);
2303}
2304
2305static ggml_backend_buffer_t ggml_backend_cpu_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) {
2306 void * data = ggml_aligned_malloc(size);
2307
2308 if (data == NULL__null) {
2309 GGML_LOG_ERROR("%s: failed to allocate buffer of size %zu\n", __func__, size)ggml_log_internal(GGML_LOG_LEVEL_ERROR, "%s: failed to allocate buffer of size %zu\n"
, __func__, size)
;
2310 return NULL__null;
2311 }
2312
2313 return ggml_backend_buffer_init(buft, ggml_backend_cpu_buffer_i, data, size);
2314}
2315
2316static size_t ggml_backend_cpu_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) {
2317 return TENSOR_ALIGNMENT32;
2318
2319 GGML_UNUSED(buft)(void)(buft);
2320}
2321
2322static bool ggml_backend_cpu_buffer_type_is_host(ggml_backend_buffer_type_t buft) {
2323 return true;
2324
2325 GGML_UNUSED(buft)(void)(buft);
2326}
2327
2328ggml_backend_buffer_type_t ggml_backend_cpu_buffer_type(void) {
2329 static struct ggml_backend_buffer_type ggml_backend_cpu_buffer_type = {
2330 /* .iface = */ {
2331 /* .get_name = */ ggml_backend_cpu_buffer_type_get_name,
2332 /* .alloc_buffer = */ ggml_backend_cpu_buffer_type_alloc_buffer,
2333 /* .get_alignment = */ ggml_backend_cpu_buffer_type_get_alignment,
2334 /* .get_max_size = */ NULL__null, // defaults to SIZE_MAX
2335 /* .get_alloc_size = */ NULL__null, // defaults to ggml_nbytes
2336 /* .is_host = */ ggml_backend_cpu_buffer_type_is_host,
2337 },
2338 /* .device = */ NULL__null, // FIXME ggml_backend_reg_dev_get(ggml_backend_cpu_reg(), 0),
2339 /* .context = */ NULL__null,
2340 };
2341
2342 return &ggml_backend_cpu_buffer_type;
2343}
2344
2345static const char * ggml_backend_cpu_buffer_from_ptr_type_get_name(ggml_backend_buffer_type_t buft) {
2346 return "CPU_Mapped";
2347
2348 GGML_UNUSED(buft)(void)(buft);
2349}
2350
2351static ggml_backend_buffer_type_t ggml_backend_cpu_buffer_from_ptr_type(void) {
2352 static struct ggml_backend_buffer_type ggml_backend_cpu_buffer_type = {
2353 /* .iface = */ {
2354 /* .get_name = */ ggml_backend_cpu_buffer_from_ptr_type_get_name,
2355 /* .alloc_buffer = */ ggml_backend_cpu_buffer_type_alloc_buffer,
2356 /* .get_alignment = */ ggml_backend_cpu_buffer_type_get_alignment,
2357 /* .get_max_size = */ NULL__null, // defaults to SIZE_MAX
2358 /* .get_alloc_size = */ NULL__null, // defaults to ggml_nbytes
2359 /* .is_host = */ ggml_backend_cpu_buffer_type_is_host,
2360 },
2361 /* .device = */ NULL__null, // FIXME ggml_backend_reg_dev_get(ggml_backend_cpu_reg(), 0),
2362 /* .context = */ NULL__null,
2363 };
2364
2365 return &ggml_backend_cpu_buffer_type;
2366}
2367
2368ggml_backend_buffer_t ggml_backend_cpu_buffer_from_ptr(void * ptr, size_t size) {
2369 GGML_ASSERT((uintptr_t)ptr % TENSOR_ALIGNMENT == 0 && "buffer pointer must be aligned")if (!((uintptr_t)ptr % 32 == 0 && "buffer pointer must be aligned"
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend.cpp"
, 2369, "GGML_ASSERT(%s) failed", "(uintptr_t)ptr % TENSOR_ALIGNMENT == 0 && \"buffer pointer must be aligned\""
)
;
2370 return ggml_backend_buffer_init(ggml_backend_cpu_buffer_from_ptr_type(), ggml_backend_cpu_buffer_from_ptr_i, ptr, size);
2371}

/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-impl.h

1#pragma once
2
3// GGML internal header
4
5#include "ggml.h"
6#include "gguf.h"
7
8#include <assert.h>
9#include <math.h>
10#include <stdlib.h> // load `stdlib.h` before other headers to work around MinGW bug: https://sourceforge.net/p/mingw-w64/bugs/192/
11#include <stdbool.h>
12#include <stdint.h>
13#include <string.h>
14
15#ifdef __ARM_FEATURE_SVE
16#include <arm_sve.h>
17#endif // __ARM_FEATURE_SVE
18
19#if defined(__ARM_NEON) && !defined(__CUDACC__) && !defined(__MUSACC__)
20// if YCM cannot find <arm_neon.h>, make a symbolic link to it, for example:
21//
22// $ ln -sfn /Library/Developer/CommandLineTools/usr/lib/clang/13.1.6/include/arm_neon.h ./src/
23//
24#include <arm_neon.h>
25#endif
26
27#ifdef __cplusplus202002L
28extern "C" {
29#endif
30
31void ggml_print_backtrace(void);
32
33uint64_t ggml_graph_next_uid(void);
34
35#ifndef MIN
36# define MIN(a, b)((a) < (b) ? (a) : (b)) ((a) < (b) ? (a) : (b))
37#endif
38
39#ifndef MAX
40# define MAX(a, b)((a) > (b) ? (a) : (b)) ((a) > (b) ? (a) : (b))
41#endif
42
43// required for mmap as gguf only guarantees 32-byte alignment
44#define TENSOR_ALIGNMENT32 32
45
46// static_assert should be a #define, but if it's not,
47// fall back to the _Static_assert C11 keyword.
48// if C99 - static_assert is noop
49// ref: https://stackoverflow.com/a/53923785/4039976
50#ifndef __cplusplus202002L
51 #ifndef static_assert
52 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201100L)
53 #define static_assert(cond, msg) _Static_assert(cond, msg)
54 #else
55 #define static_assert(cond, msg) struct global_scope_noop_trick
56 #endif
57 #endif
58#endif
59
60static inline int ggml_up32(int n) {
61 return (n + 31) & ~31;
62}
63
64//static inline int ggml_up64(int n) {
65// return (n + 63) & ~63;
66//}
67
68static inline int ggml_up(int n, int m) {
69 // assert m is a power of 2
70 GGML_ASSERT((m & (m - 1)) == 0)if (!((m & (m - 1)) == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-impl.h"
, 70, "GGML_ASSERT(%s) failed", "(m & (m - 1)) == 0")
;
71 return (n + m - 1) & ~(m - 1);
72}
73
74// TODO: move to ggml.h? (won't be able to inline)
75static bool ggml_are_same_layout(const struct ggml_tensor * a, const struct ggml_tensor * b) {
76 if (a->type != b->type) {
77 return false;
78 }
79 for (int i = 0; i < GGML_MAX_DIMS4; i++) {
80 if (a->ne[i] != b->ne[i]) {
81 return false;
82 }
83 if (a->nb[i] != b->nb[i]) {
84 return false;
85 }
86 }
87 return true;
88}
89
90static bool ggml_op_is_empty(enum ggml_op op) {
91 switch (op) {
92 case GGML_OP_NONE:
93 case GGML_OP_RESHAPE:
94 case GGML_OP_TRANSPOSE:
95 case GGML_OP_VIEW:
96 case GGML_OP_PERMUTE:
97 return true;
98 default:
99 return false;
100 }
101}
102
103static inline bool ggml_impl_is_view(const struct ggml_tensor * t) {
104 return t->view_src != NULL__null;
105}
106
107static inline float ggml_compute_softplus_f32(float input) {
108 return (input > 20.0f) ? input : logf(1 + expf(input));
109}
110//
111// logging
112//
113
114GGML_ATTRIBUTE_FORMAT(2, 3)__attribute__((format(printf, 2, 3)))
115GGML_API__attribute__ ((visibility ("default"))) extern void ggml_log_internal (enum ggml_log_level level, const char * format, ...);
116GGML_API__attribute__ ((visibility ("default"))) extern void ggml_log_callback_default(enum ggml_log_level level, const char * text, void * user_data);
117
118#define GGML_LOG(...)ggml_log_internal(GGML_LOG_LEVEL_NONE , ...) ggml_log_internal(GGML_LOG_LEVEL_NONE , __VA_ARGS__)
119#define GGML_LOG_INFO(...)ggml_log_internal(GGML_LOG_LEVEL_INFO , ...) ggml_log_internal(GGML_LOG_LEVEL_INFO , __VA_ARGS__)
120#define GGML_LOG_WARN(...)ggml_log_internal(GGML_LOG_LEVEL_WARN , ...) ggml_log_internal(GGML_LOG_LEVEL_WARN , __VA_ARGS__)
121#define GGML_LOG_ERROR(...)ggml_log_internal(GGML_LOG_LEVEL_ERROR, ...) ggml_log_internal(GGML_LOG_LEVEL_ERROR, __VA_ARGS__)
122#define GGML_LOG_DEBUG(...)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, ...) ggml_log_internal(GGML_LOG_LEVEL_DEBUG, __VA_ARGS__)
123#define GGML_LOG_CONT(...)ggml_log_internal(GGML_LOG_LEVEL_CONT , ...) ggml_log_internal(GGML_LOG_LEVEL_CONT , __VA_ARGS__)
124
125#define GGML_DEBUG0 0
126
127#if (GGML_DEBUG0 >= 1)
128#define GGML_PRINT_DEBUG(...) GGML_LOG_DEBUG(__VA_ARGS__)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, __VA_ARGS__)
129#else
130#define GGML_PRINT_DEBUG(...)
131#endif
132
133#if (GGML_DEBUG0 >= 5)
134#define GGML_PRINT_DEBUG_5(...) GGML_LOG_DEBUG(__VA_ARGS__)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, __VA_ARGS__)
135#else
136#define GGML_PRINT_DEBUG_5(...)
137#endif
138
139#if (GGML_DEBUG0 >= 10)
140#define GGML_PRINT_DEBUG_10(...) GGML_LOG_DEBUG(__VA_ARGS__)ggml_log_internal(GGML_LOG_LEVEL_DEBUG, __VA_ARGS__)
141#else
142#define GGML_PRINT_DEBUG_10(...)
143#endif
144
145// tensor params
146
147static void ggml_set_op_params(struct ggml_tensor * tensor, const void * params, size_t params_size) {
148 GGML_ASSERT(tensor != NULL)if (!(tensor != __null)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-impl.h"
, 148, "GGML_ASSERT(%s) failed", "tensor != NULL")
; // silence -Warray-bounds warnings
149 assert(params_size <= GGML_MAX_OP_PARAMS)(static_cast <bool> (params_size <= 64) ? void (0) :
__assert_fail ("params_size <= GGML_MAX_OP_PARAMS", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
150 memcpy(tensor->op_params, params, params_size);
151}
152
153static int32_t ggml_get_op_params_i32(const struct ggml_tensor * tensor, uint32_t i) {
154 assert(i < GGML_MAX_OP_PARAMS / sizeof(int32_t))(static_cast <bool> (i < 64 / sizeof(int32_t)) ? void
(0) : __assert_fail ("i < GGML_MAX_OP_PARAMS / sizeof(int32_t)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
155 return ((const int32_t *)(tensor->op_params))[i];
156}
157
158static float ggml_get_op_params_f32(const struct ggml_tensor * tensor, uint32_t i) {
159 assert(i < GGML_MAX_OP_PARAMS / sizeof(float))(static_cast <bool> (i < 64 / sizeof(float)) ? void (
0) : __assert_fail ("i < GGML_MAX_OP_PARAMS / sizeof(float)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
160 return ((const float *)(tensor->op_params))[i];
161}
162
163static void ggml_set_op_params_i32(struct ggml_tensor * tensor, uint32_t i, int32_t value) {
164 assert(i < GGML_MAX_OP_PARAMS / sizeof(int32_t))(static_cast <bool> (i < 64 / sizeof(int32_t)) ? void
(0) : __assert_fail ("i < GGML_MAX_OP_PARAMS / sizeof(int32_t)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
165 ((int32_t *)(tensor->op_params))[i] = value;
166}
167
168static void ggml_set_op_params_f32(struct ggml_tensor * tensor, uint32_t i, float value) {
169 assert(i < GGML_MAX_OP_PARAMS / sizeof(float))(static_cast <bool> (i < 64 / sizeof(float)) ? void (
0) : __assert_fail ("i < GGML_MAX_OP_PARAMS / sizeof(float)"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
170 ((float *)(tensor->op_params))[i] = value;
171}
172
173struct ggml_map_custom1_op_params {
174 ggml_custom1_op_t fun;
175 int n_tasks;
176 void * userdata;
177};
178
179struct ggml_map_custom2_op_params {
180 ggml_custom2_op_t fun;
181 int n_tasks;
182 void * userdata;
183};
184
185struct ggml_map_custom3_op_params {
186 ggml_custom3_op_t fun;
187 int n_tasks;
188 void * userdata;
189};
190
191struct ggml_custom_op_params {
192 ggml_custom_op_t fun;
193 int n_tasks;
194 void * userdata;
195};
196
197// bitset
198
199typedef uint32_t ggml_bitset_t;
200
201static_assert(sizeof(ggml_bitset_t) == 4, "bitset_t constants must be updated");
202#define BITSET_SHR5 5 // log2(sizeof(ggml_bitset_t)*8)
203#define BITSET_MASK(sizeof(ggml_bitset_t)*8 - 1) (sizeof(ggml_bitset_t)*8 - 1)
204
205static size_t ggml_bitset_size(size_t n) {
206 return (n + BITSET_MASK(sizeof(ggml_bitset_t)*8 - 1)) >> BITSET_SHR5;
207}
208
209static inline bool ggml_bitset_get(const ggml_bitset_t * bitset, size_t i) {
210 return !!(bitset[i >> BITSET_SHR5] & (1u << (i & BITSET_MASK(sizeof(ggml_bitset_t)*8 - 1))));
211}
212
213static inline void ggml_bitset_set(ggml_bitset_t * bitset, size_t i) {
214 bitset[i >> BITSET_SHR5] |= (1u << (i & BITSET_MASK(sizeof(ggml_bitset_t)*8 - 1)));
215}
216
217static inline void ggml_bitset_clear(ggml_bitset_t * bitset, size_t i) {
218 bitset[i >> BITSET_SHR5] &= ~(1u << (i & BITSET_MASK(sizeof(ggml_bitset_t)*8 - 1)));
219}
220
221// hash set
222
223#define GGML_HASHSET_FULL((size_t)-1) ((size_t)-1)
224#define GGML_HASHSET_ALREADY_EXISTS((size_t)-2) ((size_t)-2)
225
226struct ggml_hash_set {
227 size_t size;
228 ggml_bitset_t * used; // whether or not the keys are in use i.e. set
229 struct ggml_tensor ** keys; // actual tensors in the set, keys[i] is only defined if ggml_bitset_get(used, i)
230};
231
232struct ggml_hash_set ggml_hash_set_new(size_t size);
233void ggml_hash_set_free(struct ggml_hash_set * hash_set);
234
235// returns the minimum size for a hash set that can hold min_sz elements
236size_t ggml_hash_size(size_t min_sz);
237
238// remove all elements from the hash set
239void ggml_hash_set_reset(struct ggml_hash_set * hash_set);
240
241// returns true if key is in the hash set
242static bool ggml_hash_contains(const struct ggml_hash_set * hash_set, struct ggml_tensor * key);
243
244// returns GGML_HASHSET_FULL if table is full, otherwise the current index of the key or where it should be inserted
245static size_t ggml_hash_find(const struct ggml_hash_set * hash_set, const struct ggml_tensor * key);
246
247// returns GGML_HASHSET_ALREADY_EXISTS if key already exists, index otherwise, asserts if table is full
248static size_t ggml_hash_insert(struct ggml_hash_set * hash_set, struct ggml_tensor * key);
249
250// return index, asserts if table is full
251static size_t ggml_hash_find_or_insert(struct ggml_hash_set * hash_set, struct ggml_tensor * key);
252
253// hash function for ggml_tensor
254static inline size_t ggml_hash(const struct ggml_tensor * p) {
255 // the last 4 bits are always zero due to alignment
256 return (size_t)(uintptr_t)p >> 4;
257}
258
259static size_t ggml_hash_find(const struct ggml_hash_set * hash_set, const struct ggml_tensor * key) {
260 size_t h = ggml_hash(key) % hash_set->size;
261
262 // linear probing
263 size_t i = h;
264 while (ggml_bitset_get(hash_set->used, i) && hash_set->keys[i] != key) {
24
Assuming the condition is true
25
Loop condition is true. Entering loop body
265 i = (i + 1) % hash_set->size;
266 if (i == h) {
26
Assuming 'i' is equal to 'h'
27
Taking true branch
267 // visited all hash table entries -> not found
268 return GGML_HASHSET_FULL((size_t)-1);
28
Returning the value 18446744073709551615, which participates in a condition later
29
Returning the value 18446744073709551615
269 }
270 }
271 return i;
272}
273
274static bool ggml_hash_contains(const struct ggml_hash_set * hash_set, struct ggml_tensor * key) {
275 size_t i = ggml_hash_find(hash_set, key);
276 return i != GGML_HASHSET_FULL((size_t)-1) && ggml_bitset_get(hash_set->used, i);
277}
278
279static size_t ggml_hash_insert(struct ggml_hash_set * hash_set, struct ggml_tensor * key) {
280 size_t h = ggml_hash(key) % hash_set->size;
281
282 // linear probing
283 size_t i = h;
284 do {
285 if (!ggml_bitset_get(hash_set->used, i)) {
286 ggml_bitset_set(hash_set->used, i);
287 hash_set->keys[i] = key;
288 return i;
289 }
290 if (hash_set->keys[i] == key) {
291 return GGML_HASHSET_ALREADY_EXISTS((size_t)-2);
292 }
293 i = (i + 1) % hash_set->size;
294 } while (i != h);
295
296 // visited all hash table entries -> not found
297 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-impl.h"
, 297, "fatal error")
;
298}
299
300static size_t ggml_hash_find_or_insert(struct ggml_hash_set * hash_set, struct ggml_tensor * key) {
301 size_t h = ggml_hash(key) % hash_set->size;
302
303 // linear probing
304 size_t i = h;
305 do {
306 if (!ggml_bitset_get(hash_set->used, i)) {
307 ggml_bitset_set(hash_set->used, i);
308 hash_set->keys[i] = key;
309 return i;
310 }
311 if (hash_set->keys[i] == key) {
312 return i;
313 }
314 i = (i + 1) % hash_set->size;
315 } while (i != h);
316
317 // visited all hash table entries -> not found
318 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-impl.h"
, 318, "fatal error")
;
319}
320
321// computation graph
322
323enum ggml_cgraph_eval_order {
324 GGML_CGRAPH_EVAL_ORDER_LEFT_TO_RIGHT = 0,
325 GGML_CGRAPH_EVAL_ORDER_RIGHT_TO_LEFT,
326 GGML_CGRAPH_EVAL_ORDER_COUNT
327};
328
329struct ggml_cgraph {
330 int size; // maximum number of nodes/leafs/grads/grad_accs
331 int n_nodes; // number of nodes currently in use
332 int n_leafs; // number of leafs currently in use
333
334 struct ggml_tensor ** nodes; // tensors with data that can change if the graph is evaluated
335 struct ggml_tensor ** grads; // the outputs of these tensors are the gradients of the nodes
336 struct ggml_tensor ** grad_accs; // accumulators for node gradients
337 struct ggml_tensor ** leafs; // tensors with constant data
338 int32_t * use_counts;// number of uses of each tensor, indexed by hash table slot
339
340 struct ggml_hash_set visited_hash_set;
341
342 enum ggml_cgraph_eval_order order;
343
344 // an optional identifier that can be utilized to recognize same graphs if two non-zero values match
345 // a value of 0 means it is not set and should be ignored
346 uint64_t uid;
347};
348
349// returns a slice of cgraph with nodes [i0, i1)
350// the slice does not have leafs or gradients
351// if you need the gradients, get them from the original graph
352struct ggml_cgraph ggml_graph_view(struct ggml_cgraph * cgraph, int i0, int i1);
353
354// ggml-alloc.c: true if the operation can reuse memory from its sources
355GGML_API__attribute__ ((visibility ("default"))) extern bool ggml_op_can_inplace(enum ggml_op op);
356
357
358// Memory allocation
359
360GGML_API__attribute__ ((visibility ("default"))) extern void * ggml_aligned_malloc(size_t size);
361GGML_API__attribute__ ((visibility ("default"))) extern void ggml_aligned_free(void * ptr, size_t size);
362
363// FP16 <-> FP32
364// ref: https://github.com/Maratyszcza/FP16
365
366static inline float fp32_from_bits(uint32_t w) {
367 union {
368 uint32_t as_bits;
369 float as_value;
370 } fp32;
371 fp32.as_bits = w;
372 return fp32.as_value;
373}
374
375static inline uint32_t fp32_to_bits(float f) {
376 union {
377 float as_value;
378 uint32_t as_bits;
379 } fp32;
380 fp32.as_value = f;
381 return fp32.as_bits;
382}
383
384static inline float ggml_compute_fp16_to_fp32(ggml_fp16_t h) {
385 const uint32_t w = (uint32_t) h << 16;
386 const uint32_t sign = w & UINT32_C(0x80000000)0x80000000U;
387 const uint32_t two_w = w + w;
388
389 const uint32_t exp_offset = UINT32_C(0xE0)0xE0U << 23;
390#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__4) && !defined(__STRICT_ANSI__)) && (!defined(__cplusplus202002L) || __cplusplus202002L >= 201703L)
391 const float exp_scale = 0x1.0p-112f;
392#else
393 const float exp_scale = fp32_from_bits(UINT32_C(0x7800000)0x7800000U);
394#endif
395 const float normalized_value = fp32_from_bits((two_w >> 4) + exp_offset) * exp_scale;
396
397 const uint32_t magic_mask = UINT32_C(126)126U << 23;
398 const float magic_bias = 0.5f;
399 const float denormalized_value = fp32_from_bits((two_w >> 17) | magic_mask) - magic_bias;
400
401 const uint32_t denormalized_cutoff = UINT32_C(1)1U << 27;
402 const uint32_t result = sign |
403 (two_w < denormalized_cutoff ? fp32_to_bits(denormalized_value) : fp32_to_bits(normalized_value));
404 return fp32_from_bits(result);
405}
406
407static inline ggml_fp16_t ggml_compute_fp32_to_fp16(float f) {
408#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || defined(__GNUC__4) && !defined(__STRICT_ANSI__)) && (!defined(__cplusplus202002L) || __cplusplus202002L >= 201703L)
409 const float scale_to_inf = 0x1.0p+112f;
410 const float scale_to_zero = 0x1.0p-110f;
411#else
412 const float scale_to_inf = fp32_from_bits(UINT32_C(0x77800000)0x77800000U);
413 const float scale_to_zero = fp32_from_bits(UINT32_C(0x08800000)0x08800000U);
414#endif
415 float base = (fabsf(f) * scale_to_inf) * scale_to_zero;
416
417 const uint32_t w = fp32_to_bits(f);
418 const uint32_t shl1_w = w + w;
419 const uint32_t sign = w & UINT32_C(0x80000000)0x80000000U;
420 uint32_t bias = shl1_w & UINT32_C(0xFF000000)0xFF000000U;
421 if (bias < UINT32_C(0x71000000)0x71000000U) {
422 bias = UINT32_C(0x71000000)0x71000000U;
423 }
424
425 base = fp32_from_bits((bias >> 1) + UINT32_C(0x07800000)0x07800000U) + base;
426 const uint32_t bits = fp32_to_bits(base);
427 const uint32_t exp_bits = (bits >> 13) & UINT32_C(0x00007C00)0x00007C00U;
428 const uint32_t mantissa_bits = bits & UINT32_C(0x00000FFF)0x00000FFFU;
429 const uint32_t nonsign = exp_bits + mantissa_bits;
430 return (sign >> 16) | (shl1_w > UINT32_C(0xFF000000)0xFF000000U ? UINT16_C(0x7E00)0x7E00 : nonsign);
431}
432
433#define GGML_COMPUTE_FP16_TO_FP32(x)ggml_compute_fp16_to_fp32(x) ggml_compute_fp16_to_fp32(x)
434#define GGML_COMPUTE_FP32_TO_FP16(x)ggml_compute_fp32_to_fp16(x) ggml_compute_fp32_to_fp16(x)
435
436#define GGML_FP16_TO_FP32(x)ggml_compute_fp16_to_fp32(x) GGML_COMPUTE_FP16_TO_FP32(x)ggml_compute_fp16_to_fp32(x)
437#define GGML_FP32_TO_FP16(x)ggml_compute_fp32_to_fp16(x) GGML_COMPUTE_FP32_TO_FP16(x)ggml_compute_fp32_to_fp16(x)
438
439static inline float ggml_e8m0_to_fp32(uint8_t x) {
440 uint32_t bits; // Stores the raw bit representation of the float
441
442 // Handle special case for minimum exponent (denormalized float)
443 if (x == 0) {
444 // Bit pattern for 2^(-127):
445 // - Sign bit: 0 (positive)
446 // - Exponent: 0 (denormalized number)
447 // - Mantissa: 0x400000 (0.5 in fractional form)
448 // Value = 0.5 * 2^(-126) = 2^(-127)
449 bits = 0x00400000;
450 }
451 // note: disabled as we don't need to handle NaNs
452 //// Handle special case for NaN (all bits set)
453 //else if (x == 0xFF) {
454 // // Standard quiet NaN pattern:
455 // // - Sign bit: 0
456 // // - Exponent: all 1s (0xFF)
457 // // - Mantissa: 0x400000 (quiet NaN flag)
458 // bits = 0x7FC00000;
459 //}
460 // Normalized values (most common case)
461 else {
462 // Construct normalized float by shifting exponent into position:
463 // - Exponent field: 8 bits (positions 30-23)
464 // - Mantissa: 0 (implicit leading 1)
465 // Value = 2^(x - 127)
466 bits = (uint32_t) x << 23;
467 }
468
469 float result; // Final float value
470 // Safely reinterpret bit pattern as float without type-punning issues
471 memcpy(&result, &bits, sizeof(float));
472 return result;
473}
474
475// Equal to ggml_e8m0_to_fp32/2
476// Useful with MXFP4 quantization since the E0M2 values are doubled
477static inline float ggml_e8m0_to_fp32_half(uint8_t x) {
478 uint32_t bits;
479
480 // For x < 2: use precomputed denormal patterns
481 if (x < 2) {
482 // 0x00200000 = 2^(-128), 0x00400000 = 2^(-127)
483 bits = 0x00200000 << x;
484 }
485 // For x >= 2: normalized exponent adjustment
486 else {
487 // 0.5 * 2^(x-127) = 2^(x-128) = normalized with exponent (x-1)
488 bits = (uint32_t)(x - 1) << 23;
489 }
490 // Note: NaNs are not handled here
491
492 float result;
493 memcpy(&result, &bits, sizeof(float));
494 return result;
495}
496
497#define GGML_E8M0_TO_FP32(x)ggml_e8m0_to_fp32(x) ggml_e8m0_to_fp32(x)
498#define GGML_E8M0_TO_FP32_HALF(x)ggml_e8m0_to_fp32_half(x) ggml_e8m0_to_fp32_half(x)
499
500// UE4M3: unsigned, 4 exp bits (bias=7), 3 mantissa bits
501// Returns value * 0.5 to match kvalues_mxfp4 convention (kvalues = 2 * E2M1_float)
502static inline float ggml_ue4m3_to_fp32(uint8_t x) {
503 if (x == 0 || x == 0x7F) {
504 return 0.0f;
505 }
506 int exp = (x >> 3) & 0xF;
507 int man = x & 0x7;
508 float raw;
509 if (exp == 0) {
510 raw = ldexpf((float) man, -9);
511 } else {
512 raw = ldexpf(1.0f + (float) man / 8.0f, exp - 7);
513 }
514 return raw * 0.5f;
515}
516
517static inline uint8_t ggml_fp32_to_ue4m3(float x) {
518 if (!(x > 0.0f)) {
519 return 0;
520 }
521 if (x > 448.0f) {
522 x = 448.0f;
523 }
524 uint32_t bits;
525 memcpy(&bits, &x, 4);
526 int fp32_exp = ((bits >> 23) & 0xFF) - 127;
527 int fp32_man = (bits >> 20) & 0x7;
528 int ue4m3_exp = fp32_exp + 7;
529 if (ue4m3_exp <= 0) {
530 // subnormal: value = man * 2^-9, man = round(x * 2^9)
531 int man = (int) (x * 512.0f + 0.5f);
532 if (man > 7) {
533 man = 7;
534 }
535 if (man < 1) {
536 return 0;
537 }
538 return (uint8_t) man;
539 }
540 if (ue4m3_exp >= 15) {
541 return 0x7E;
542 }
543 int round_bit = (bits >> 19) & 1;
544 int ue4m3_man = fp32_man + round_bit;
545 if (ue4m3_man > 7) {
546 ue4m3_man = 0;
547 ue4m3_exp++;
548 if (ue4m3_exp >= 15) {
549 return 0x7E;
550 }
551 }
552 return (uint8_t) ((ue4m3_exp << 3) | ue4m3_man);
553}
554
555/**
556 * Converts brain16 to float32.
557 *
558 * The bfloat16 floating point format has the following structure:
559 *
560 * ┌sign
561 * │
562 * │ ┌exponent
563 * │ │
564 * │ │ ┌mantissa
565 * │ │ │
566 * │┌──┴───┐┌─┴───┐
567 * 0b0000000000000000 brain16
568 *
569 * Since bf16 has the same number of exponent bits as a 32bit float,
570 * encoding and decoding numbers becomes relatively straightforward.
571 *
572 * ┌sign
573 * │
574 * │ ┌exponent
575 * │ │
576 * │ │ ┌mantissa
577 * │ │ │
578 * │┌──┴───┐┌─┴───────────────────┐
579 * 0b00000000000000000000000000000000 IEEE binary32
580 *
581 * For comparison, the standard fp16 format has fewer exponent bits.
582 *
583 * ┌sign
584 * │
585 * │ ┌exponent
586 * │ │
587 * │ │ ┌mantissa
588 * │ │ │
589 * │┌─┴─┐┌─┴──────┐
590 * 0b0000000000000000 IEEE binary16
591 *
592 * @see IEEE 754-2008
593 */
594static inline float ggml_compute_bf16_to_fp32(ggml_bf16_t h) {
595 union {
596 float f;
597 uint32_t i;
598 } u;
599 u.i = (uint32_t)h.bits << 16;
600 return u.f;
601}
602
603/**
604 * Converts float32 to brain16.
605 *
606 * This is binary identical with Google Brain float conversion.
607 * Floats shall round to nearest even, and NANs shall be quiet.
608 * Subnormals aren't flushed to zero, except perhaps when used.
609 * This code should vectorize nicely if using modern compilers.
610 */
611static inline ggml_bf16_t ggml_compute_fp32_to_bf16(float s) {
612 ggml_bf16_t h;
613 union {
614 float f;
615 uint32_t i;
616 } u;
617 u.f = s;
618 if ((u.i & 0x7fffffff) > 0x7f800000) { /* nan */
619 h.bits = (u.i >> 16) | 64; /* force to quiet */
620 return h;
621 }
622 h.bits = (u.i + (0x7fff + ((u.i >> 16) & 1))) >> 16;
623 return h;
624}
625
626#define GGML_FP32_TO_BF16(x)ggml_compute_fp32_to_bf16(x) ggml_compute_fp32_to_bf16(x)
627#define GGML_BF16_TO_FP32(x)ggml_compute_bf16_to_fp32(x) ggml_compute_bf16_to_fp32(x)
628
629static inline int32_t ggml_node_get_use_count(const struct ggml_cgraph * cgraph, int node_idx) {
630 const struct ggml_tensor * node = cgraph->nodes[node_idx];
631
632 size_t hash_pos = ggml_hash_find(&cgraph->visited_hash_set, node);
633 if (!ggml_bitset_get(cgraph->visited_hash_set.used, hash_pos)) {
634 return 0;
635 }
636 return cgraph->use_counts[hash_pos];
637}
638
639// return true if the node's results are only used by N other nodes
640// and can be fused into their calculations.
641static inline bool ggml_node_has_n_uses(const struct ggml_cgraph * cgraph, int node_idx, int32_t n_uses) {
642 const struct ggml_tensor * node = cgraph->nodes[node_idx];
643
644 // check the use count against how many we're replacing
645 if (ggml_node_get_use_count(cgraph, node_idx) != n_uses) {
646 return false;
647 }
648
649 // if node is a view, some other node might be using the intermediate result
650 // via the view source.
651 if (node->view_src) {
652 return false;
653 }
654
655 // If the user requested output for the node, can't fuse
656 if (node->flags & GGML_TENSOR_FLAG_OUTPUT) {
657 return false;
658 }
659
660 return true;
661}
662
663// Returns true if nodes with indices { node_idxs } are the sequence of ggml_ops in ops[]
664// and are fusable. Nodes are considered fusable according to this function if:
665// - all nodes except the last have only one use and are not views/outputs (see ggml_node_has_N_uses).
666// - all nodes except the last are a src of the following node.
667// - all nodes are the same shape.
668// TODO: Consider allowing GGML_OP_NONE nodes in between
669static inline bool ggml_can_fuse_ext(const struct ggml_cgraph * cgraph, const int * node_idxs, const enum ggml_op * ops, int num_ops) {
670 for (int i = 0; i < num_ops; ++i) {
671 if (node_idxs[i] >= cgraph->n_nodes) {
672 return false;
673 }
674
675 struct ggml_tensor * node = cgraph->nodes[node_idxs[i]];
676 if (node->op != ops[i]) {
677 return false;
678 }
679 if ((node->flags & GGML_TENSOR_FLAG_COMPUTE) == 0) {
680 return false;
681 }
682 if (i < num_ops - 1 && !ggml_node_has_n_uses(cgraph, node_idxs[i], 1)) {
683 return false;
684 }
685 if (i > 0) {
686 struct ggml_tensor * prev = cgraph->nodes[node_idxs[i - 1]];
687 if (node->src[0] != prev && node->src[1] != prev) {
688 return false;
689 }
690 if (!ggml_are_same_shape(node, prev)) {
691 return false;
692 }
693 }
694 }
695 return true;
696}
697
698// same as above, for sequential indices starting at node_idx
699static inline bool ggml_can_fuse(const struct ggml_cgraph * cgraph, int node_idx, const enum ggml_op * ops, int num_ops) {
700 assert(num_ops < 32)(static_cast <bool> (num_ops < 32) ? void (0) : __assert_fail
("num_ops < 32", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
701
702 if (node_idx + num_ops > cgraph->n_nodes) {
703 return false;
704 }
705
706 int idxs[32];
707 for (int i = 0; i < num_ops; ++i) {
708 idxs[i] = node_idx + i;
709 }
710
711 return ggml_can_fuse_ext(cgraph, idxs, ops, num_ops);
712}
713
714GGML_API__attribute__ ((visibility ("default"))) extern bool ggml_can_fuse_subgraph_ext(const struct ggml_cgraph * cgraph,
715 const int * node_idxs,
716 int count,
717 const enum ggml_op * ops,
718 const int * outputs,
719 int num_outputs);
720
721// Returns true if the subgraph formed by {node_idxs} can be fused
722// checks whethers all nodes which are not part of outputs can be elided
723// by checking if their num_uses are confined to the subgraph
724static inline bool ggml_can_fuse_subgraph(const struct ggml_cgraph * cgraph,
725 int node_idx,
726 int count,
727 const enum ggml_op * ops,
728 const int * outputs,
729 int num_outputs) {
730 GGML_ASSERT(count < 32)if (!(count < 32)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-impl.h"
, 730, "GGML_ASSERT(%s) failed", "count < 32")
;
731 if (node_idx + count > cgraph->n_nodes) {
732 return false;
733 }
734
735 int idxs[32];
736
737 for (int i = 0; i < count; ++i) {
738 idxs[i] = node_idx + i;
739 }
740
741 return ggml_can_fuse_subgraph_ext(cgraph, idxs, count, ops, outputs, num_outputs);
742}
743
744#ifdef __cplusplus202002L
745}
746#endif
747
748#ifdef __cplusplus202002L
749#include <array>
750#include <initializer_list>
751#include <vector>
752
753// nicer C++ syntax for ggml_can_fuse
754inline bool ggml_can_fuse(const struct ggml_cgraph * cgraph, int node_idx, std::initializer_list<enum ggml_op> ops) {
755 return ggml_can_fuse(cgraph, node_idx, ops.begin(), (int)ops.size());
756}
757
758inline bool ggml_can_fuse_subgraph(const struct ggml_cgraph * cgraph,
759 int start_idx,
760 std::initializer_list<enum ggml_op> ops,
761 std::initializer_list<int> outputs = {}) {
762 return ggml_can_fuse_subgraph(cgraph, start_idx, ops.size(), ops.begin(), outputs.begin(), outputs.size());
763}
764
765// Return true if the edges in the graph match expectations.
766inline bool ggml_check_edges(const struct ggml_cgraph * cgraph,
767 int start_idx,
768 std::initializer_list<std::array<int, 3>> edges) {
769 for (const auto & edge : edges) {
770 int dst_node = edge[0];
771 int src_idx = edge[1];
772 int src_node = edge[2];
773 if (cgraph->nodes[start_idx + dst_node]->src[src_idx] != cgraph->nodes[start_idx + src_node]) {
774 return false;
775 }
776 }
777 return true;
778}
779
780// expose GGUF internals for test code
781GGML_API__attribute__ ((visibility ("default"))) extern size_t gguf_type_size(enum gguf_type type);
782GGML_API__attribute__ ((visibility ("default"))) extern void gguf_write_to_buf(const struct gguf_context * ctx, std::vector<int8_t> & buf, bool only_meta);
783#endif // __cplusplus