Bug Summary

File:root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp
Warning:line 1114, column 5
Access to field 'buffer' results in a dereference of a null pointer (loaded from variable 'tensor')

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-meta.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-meta.cpp
1#include "ggml.h"
2#include "ggml-impl.h"
3#include "ggml-backend.h"
4#include "ggml-backend-impl.h"
5#include "ggml-alloc.h"
6#include "ggml-cpp.h"
7
8#include <algorithm>
9#include <cassert>
10#include <cmath>
11#include <cstddef>
12#include <cstdint>
13#include <cstring>
14#include <map>
15#include <memory>
16#include <set>
17#include <string>
18#include <tuple>
19#include <utility>
20#include <vector>
21
22struct ggml_backend_meta_device;
23struct ggml_backend_meta_buffer_type;
24struct ggml_backend_meta_buffer;
25struct ggml_backend_meta;
26
27const char * ggml_backend_meta_split_axis_name(enum ggml_backend_meta_split_axis split_axis) {
28 switch (split_axis) {
29 case GGML_BACKEND_SPLIT_AXIS_0:
30 return "0";
31 case GGML_BACKEND_SPLIT_AXIS_1:
32 return "1";
33 case GGML_BACKEND_SPLIT_AXIS_2:
34 return "2";
35 case GGML_BACKEND_SPLIT_AXIS_3:
36 return "3";
37 case GGML_BACKEND_SPLIT_AXIS_MIRRORED:
38 return "MIRRORED";
39 case GGML_BACKEND_SPLIT_AXIS_PARTIAL:
40 return "PARTIAL";
41 case GGML_BACKEND_SPLIT_AXIS_NONE:
42 return "NONE";
43 case GGML_BACKEND_SPLIT_AXIS_UNKNOWN:
44 return "UNKNOWN";
45 default:
46 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 46, "fatal error")
;
47 }
48}
49
50//
51// meta backend device
52//
53
54struct ggml_backend_meta_device_context {
55 std::vector<ggml_backend_dev_t> simple_devs;
56 ggml_backend_meta_get_split_state_t get_split_state;
57 void * get_split_state_ud;
58
59 std::string name;
60 std::string description;
61
62 ggml_backend_meta_device_context(
63 std::vector<ggml_backend_dev_t> simple_devs, ggml_backend_meta_get_split_state_t get_split_state, void * get_split_state_ud) :
64 simple_devs(std::move(simple_devs)), get_split_state(get_split_state), get_split_state_ud(get_split_state_ud) {
65 name = std::string("Meta(");
66 description = std::string("Meta(");
67 for (size_t i = 0; i < simple_devs.size(); i++) {
68 if (i > 0) {
69 name += ",";
70 description += ",";
71 }
72 name += ggml_backend_dev_name (simple_devs[i]);
73 description += ggml_backend_dev_description(simple_devs[i]);
74 }
75 name += ")";
76 description += ")";
77 }
78
79 bool operator<(const ggml_backend_meta_device_context & other) const {
80 return std::tie(simple_devs, get_split_state, get_split_state_ud)
81 < std::tie(other.simple_devs, other.get_split_state, other.get_split_state_ud);
82 }
83};
84
85static bool ggml_backend_dev_is_meta(ggml_backend_dev_t dev);
86
87static const char * ggml_backend_meta_device_get_name(ggml_backend_dev_t dev) {
88 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 88, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
89 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
90 return meta_dev_ctx->name.c_str();
91}
92
93static const char * ggml_backend_meta_device_get_description(ggml_backend_dev_t dev) {
94 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 94, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
95 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
96 return meta_dev_ctx->description.c_str();
97}
98
99static void ggml_backend_meta_device_get_memory(ggml_backend_dev_t dev, size_t * free, size_t * total) {
100 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 100, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
101 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
102 *free = 0;
103 *total = 0;
104 for (ggml_backend_dev_t dev : meta_dev_ctx->simple_devs) {
105 size_t tmp_free, tmp_total;
106 ggml_backend_dev_memory(dev, &tmp_free, &tmp_total);
107 *free += tmp_free;
108 *total += tmp_total;
109 }
110}
111
112static enum ggml_backend_dev_type ggml_backend_meta_device_get_type(ggml_backend_dev_t dev) {
113 return GGML_BACKEND_DEVICE_TYPE_META;
114
115 GGML_UNUSED(dev)(void)(dev);
116}
117
118static void ggml_backend_meta_device_get_props(ggml_backend_dev_t dev, ggml_backend_dev_props * props) {
119 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 119, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
120 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
121
122 // TODO replace placeholders
123 props->name = ggml_backend_meta_device_get_name(dev);
124 props->description = ggml_backend_meta_device_get_description(dev);
125 props->type = ggml_backend_meta_device_get_type(dev);
126 props->device_id = 0;
127
128 ggml_backend_meta_device_get_memory(dev, &props->memory_free, &props->memory_total);
129
130 props->caps = {
131 /* .async = */ true,
132 /* .host_buffer = */ false, // Not implemented.
133 /* .buffer_from_host_ptr = */ false, // Not implemented.
134 /* .events = */ false, // Not implemented.
135 };
136 for (ggml_backend_dev_t simple_dev : meta_dev_ctx->simple_devs) {
137 ggml_backend_dev_props tmp_props;
138 ggml_backend_dev_get_props(simple_dev, &tmp_props);
139 props->caps.async = props->caps.async && tmp_props.caps.async;
140 props->caps.host_buffer = props->caps.host_buffer && tmp_props.caps.host_buffer;
141 props->caps.buffer_from_host_ptr = props->caps.buffer_from_host_ptr && tmp_props.caps.buffer_from_host_ptr;
142 props->caps.events = props->caps.events && tmp_props.caps.events;
143 }
144}
145
146static ggml_backend_t ggml_backend_meta_device_init_backend(ggml_backend_dev_t dev, const char * params);
147
148static ggml_backend_buffer_type_t ggml_backend_meta_device_get_buffer_type(ggml_backend_dev_t dev);
149
150static ggml_backend_buffer_type_t ggml_backend_meta_device_get_host_buffer_type(ggml_backend_dev_t dev);
151
152static bool ggml_backend_meta_device_supports_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
153 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 153, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
154 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
155 return std::all_of(meta_dev_ctx->simple_devs.begin(), meta_dev_ctx->simple_devs.end(),
156 [op](ggml_backend_dev_t simple_dev) { return ggml_backend_dev_supports_op(simple_dev, op); });
157}
158
159static bool ggml_backend_meta_device_supports_buft(ggml_backend_dev_t dev, ggml_backend_buffer_type_t buft) {
160 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 160, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
161 ggml_backend_dev_t dev_buft = ggml_backend_buft_get_device(buft);
162 if (!ggml_backend_dev_is_meta(dev_buft)) {
163 return false;
164 }
165 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
166 const ggml_backend_meta_device_context * meta_buft_dev_ctx = (const ggml_backend_meta_device_context *) dev_buft->context;
167 if (meta_dev_ctx->simple_devs.size() != meta_buft_dev_ctx->simple_devs.size()) {
168 return false;
169 }
170 for (size_t i = 0; i < meta_dev_ctx->simple_devs.size(); i++) {
171 if (meta_dev_ctx->simple_devs[i] != meta_buft_dev_ctx->simple_devs[i]) {
172 return false;
173 }
174 }
175 return true;
176}
177
178static const ggml_backend_device_i ggml_backend_meta_device_iface = {
179 /* .get_name = */ ggml_backend_meta_device_get_name,
180 /* .get_description = */ ggml_backend_meta_device_get_description,
181 /* .get_memory = */ ggml_backend_meta_device_get_memory,
182 /* .get_type = */ ggml_backend_meta_device_get_type,
183 /* .get_props = */ ggml_backend_meta_device_get_props,
184 /* .init_backend = */ ggml_backend_meta_device_init_backend,
185 /* .get_buffer_type = */ ggml_backend_meta_device_get_buffer_type,
186 /* .get_host_buffer_type = */ ggml_backend_meta_device_get_host_buffer_type,
187 /* .buffer_from_host_ptr = */ nullptr,
188 /* .supports_op = */ ggml_backend_meta_device_supports_op,
189 /* .supports_buft = */ ggml_backend_meta_device_supports_buft,
190 /* .offload_op = */ nullptr,
191 /* .event_new = */ nullptr,
192 /* .event_free = */ nullptr,
193 /* .event_synchronize = */ nullptr,
194};
195
196static bool ggml_backend_dev_is_meta(ggml_backend_dev_t dev) {
197 return dev != nullptr && dev->iface.get_name == ggml_backend_meta_device_iface.get_name;
198}
199
200static size_t ggml_backend_meta_dev_n_devs(ggml_backend_dev_t meta_dev) {
201 GGML_ASSERT(ggml_backend_dev_is_meta(meta_dev))if (!(ggml_backend_dev_is_meta(meta_dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 201, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(meta_dev)"
)
;
202 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) meta_dev->context;
203 return meta_dev_ctx->simple_devs.size();
204}
205
206static ggml_backend_dev_t ggml_backend_meta_dev_simple_dev(ggml_backend_dev_t meta_dev, size_t index) {
207 GGML_ASSERT(ggml_backend_dev_is_meta(meta_dev))if (!(ggml_backend_dev_is_meta(meta_dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 207, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(meta_dev)"
)
;
208 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) meta_dev->context;
209 GGML_ASSERT(index < meta_dev_ctx->simple_devs.size())if (!(index < meta_dev_ctx->simple_devs.size())) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 209, "GGML_ASSERT(%s) failed", "index < meta_dev_ctx->simple_devs.size()"
)
;
210 return meta_dev_ctx->simple_devs[index];
211}
212
213ggml_backend_dev_t ggml_backend_meta_device(
214 ggml_backend_dev_t * devs, size_t n_devs, ggml_backend_meta_get_split_state_t get_split_state, void * get_split_state_ud) {
215 GGML_ASSERT(n_devs <= GGML_BACKEND_META_MAX_DEVICES)if (!(n_devs <= 16)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 215, "GGML_ASSERT(%s) failed", "n_devs <= GGML_BACKEND_META_MAX_DEVICES"
)
;
216 // TODO: this is not thread-safe - needs to be fixed
217 static std::vector<std::unique_ptr<ggml_backend_meta_device_context>> ctxs;
218 static std::map<ggml_backend_meta_device_context, struct ggml_backend_device> meta_devs;
219
220 std::vector<ggml_backend_dev_t> simple_devs;
221 simple_devs.reserve(n_devs);
222 for (size_t i = 0; i < n_devs; i++) {
223 simple_devs.push_back(devs[i]);
224 }
225 ggml_backend_meta_device_context ctx(simple_devs, get_split_state, get_split_state_ud);
226
227 {
228 auto it = meta_devs.find(ctx);
229 if (it != meta_devs.end()) {
230 return &it->second;
231 }
232 }
233 ctxs.push_back(std::make_unique<ggml_backend_meta_device_context>(ctx));
234
235 struct ggml_backend_device meta_dev = {
236 /*iface =*/ ggml_backend_meta_device_iface,
237 /*reg =*/ nullptr,
238 /*ctx =*/ ctxs.back().get(),
239 };
240
241 auto result = meta_devs.emplace(*ctxs.back(), meta_dev);
242 return &result.first->second;
243}
244
245//
246// meta backend buffer type
247//
248
249struct ggml_backend_meta_buffer_type_context {
250 std::vector<ggml_backend_buffer_type_t> simple_bufts;
251
252 std::string name;
253
254 ggml_backend_meta_buffer_type_context(std::vector<ggml_backend_buffer_type_t> simple_bufts) : simple_bufts(std::move(simple_bufts)) {
255 name = "Meta(";
256 for (size_t i = 0; i < simple_bufts.size(); i++) {
257 if (i > 0) {
258 name += ",";
259 }
260 name += ggml_backend_buft_name(simple_bufts[i]);
261 }
262 name += ")";
263 }
264
265 bool operator<(const ggml_backend_meta_buffer_type_context & other) const {
266 return simple_bufts < other.simple_bufts;
267 }
268};
269
270static size_t ggml_backend_meta_buft_n_bufts(ggml_backend_buffer_type_t meta_buft) {
271 GGML_ASSERT(ggml_backend_buft_is_meta(meta_buft))if (!(ggml_backend_buft_is_meta(meta_buft))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 271, "GGML_ASSERT(%s) failed", "ggml_backend_buft_is_meta(meta_buft)"
)
;
272 const ggml_backend_meta_buffer_type_context * meta_buft_ctx = (const ggml_backend_meta_buffer_type_context *) meta_buft->context;
273 return meta_buft_ctx->simple_bufts.size();
274}
275
276static const char * ggml_backend_meta_buffer_type_get_name(ggml_backend_buffer_type_t buft) {
277 GGML_ASSERT(ggml_backend_buft_is_meta(buft))if (!(ggml_backend_buft_is_meta(buft))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 277, "GGML_ASSERT(%s) failed", "ggml_backend_buft_is_meta(buft)"
)
;
278 const ggml_backend_meta_buffer_type_context * meta_buft_ctx = (const ggml_backend_meta_buffer_type_context *) buft->context;
279 return meta_buft_ctx->name.c_str();
280}
281
282static ggml_backend_buffer_type_t ggml_backend_meta_buft_simple_buft(ggml_backend_buffer_type_t meta_buft, size_t index) {
283 GGML_ASSERT(ggml_backend_buft_is_meta(meta_buft))if (!(ggml_backend_buft_is_meta(meta_buft))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 283, "GGML_ASSERT(%s) failed", "ggml_backend_buft_is_meta(meta_buft)"
)
;
284 const ggml_backend_meta_buffer_type_context * meta_buft_ctx = (const ggml_backend_meta_buffer_type_context *) meta_buft->context;
285 GGML_ASSERT(index < meta_buft_ctx->simple_bufts.size())if (!(index < meta_buft_ctx->simple_bufts.size())) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 285, "GGML_ASSERT(%s) failed", "index < meta_buft_ctx->simple_bufts.size()"
)
;
286 return meta_buft_ctx->simple_bufts[index];
287}
288
289static ggml_backend_buffer_t ggml_backend_meta_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size);
290
291static size_t ggml_backend_meta_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) {
292 const size_t n_simple_bufts = ggml_backend_meta_buft_n_bufts(buft);
293 size_t max_alignment = 1;
294 for (size_t i = 0; i < n_simple_bufts; i++) {
295 const size_t alignment = ggml_backend_buft_get_alignment(ggml_backend_meta_buft_simple_buft(buft, i));
296 max_alignment = std::max(max_alignment, alignment);
297 GGML_ASSERT(max_alignment % alignment == 0)if (!(max_alignment % alignment == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 297, "GGML_ASSERT(%s) failed", "max_alignment % alignment == 0"
)
;
298 }
299 return max_alignment;
300}
301
302static size_t ggml_backend_meta_buffer_type_get_max_size(ggml_backend_buffer_type_t buft) {
303 const size_t n_simple_bufts = ggml_backend_meta_buft_n_bufts(buft);
304 size_t max_size = SIZE_MAX(18446744073709551615UL);
305 for (size_t i = 0; i < n_simple_bufts; i++) {
306 max_size = std::min(max_size, ggml_backend_buft_get_max_size(ggml_backend_meta_buft_simple_buft(buft, i)));
307 }
308 return max_size;
309}
310
311static size_t ggml_backend_meta_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor) {
312 const size_t n_simple_bufts = ggml_backend_meta_buft_n_bufts(buft);
313 size_t max_alloc_size = 0;
314 for (size_t i = 0; i < n_simple_bufts; i++) {
315 const size_t alloc_size = ggml_backend_buft_get_alloc_size(ggml_backend_meta_buft_simple_buft(buft, i), tensor);
316 max_alloc_size = std::max(max_alloc_size, alloc_size);
317 }
318 return max_alloc_size;
319}
320
321static bool ggml_backend_meta_buffer_type_is_host(ggml_backend_buffer_type_t buft) {
322 const size_t n_simple_bufts = ggml_backend_meta_buft_n_bufts(buft);
323 for (size_t i = 0; i < n_simple_bufts; i++) {
324 if (!ggml_backend_buft_is_host(ggml_backend_meta_buft_simple_buft(buft, i))) {
325 return false;
326 }
327 }
328 return true;
329}
330
331static const struct ggml_backend_buffer_type_i ggml_backend_meta_buffer_type_iface = {
332 /* .get_name = */ ggml_backend_meta_buffer_type_get_name,
333 /* .alloc_buffer = */ ggml_backend_meta_buffer_type_alloc_buffer,
334 /* .get_alignment = */ ggml_backend_meta_buffer_type_get_alignment,
335 /* .get_max_size = */ ggml_backend_meta_buffer_type_get_max_size,
336 /* .get_alloc_size = */ ggml_backend_meta_buffer_type_get_alloc_size,
337 /* .is_host = */ ggml_backend_meta_buffer_type_is_host,
338};
339
340bool ggml_backend_buft_is_meta(ggml_backend_buffer_type_t buft) {
341 return buft != nullptr && buft->iface.get_name == ggml_backend_meta_buffer_type_iface.get_name;
342}
343
344static ggml_backend_buffer_type_t ggml_backend_meta_device_get_buffer_type(ggml_backend_dev_t dev) {
345 static std::map<ggml_backend_dev_t, struct ggml_backend_buffer_type> meta_bufts;
346 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 346, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
347 {
348 auto it = meta_bufts.find(dev);
349 if (it != meta_bufts.end()) {
350 return &it->second;
351 }
352 }
353
354 const size_t n_devs = ggml_backend_meta_dev_n_devs(dev);
355 std::vector<ggml_backend_buffer_type_t> simple_bufts;
356 simple_bufts.reserve(n_devs);
357 for (size_t i = 0; i < n_devs; i++) {
358 simple_bufts.push_back(ggml_backend_dev_buffer_type(ggml_backend_meta_dev_simple_dev(dev, i)));
359 }
360 ggml_backend_meta_buffer_type_context * buft_ctx = new ggml_backend_meta_buffer_type_context(simple_bufts);
361
362 struct ggml_backend_buffer_type meta_buft = {
363 /*iface =*/ ggml_backend_meta_buffer_type_iface,
364 /*device =*/ dev,
365 /*ctx =*/ buft_ctx,
366 };
367 auto result = meta_bufts.emplace(dev, meta_buft);
368 return &result.first->second;
369}
370
371static ggml_backend_buffer_type_t ggml_backend_meta_device_get_host_buffer_type(ggml_backend_dev_t dev) {
372 GGML_ASSERT(ggml_backend_dev_is_meta(dev))if (!(ggml_backend_dev_is_meta(dev))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 372, "GGML_ASSERT(%s) failed", "ggml_backend_dev_is_meta(dev)"
)
;
373 const ggml_backend_meta_device_context * meta_dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
374
375 ggml_backend_buffer_type_t host_buft = nullptr;
376 for (ggml_backend_dev_t simple_dev : meta_dev_ctx->simple_devs) {
377 ggml_backend_buffer_type_t simple_host_buft = ggml_backend_dev_host_buffer_type(simple_dev);
378 if (simple_host_buft == nullptr) {
379 return nullptr;
380 }
381 if (host_buft == nullptr) {
382 host_buft = simple_host_buft;
383 } else if (host_buft != simple_host_buft) {
384 // if different simple devices have different host buffer types,
385 // we cannot provide a single host buffer type for the meta device
386 return nullptr;
387 }
388 }
389 return host_buft;
390}
391
392//
393// meta backend buffer
394//
395
396// Container to hold the tensor slices per simple ggml backend buffer.
397struct ggml_backend_meta_simple_tensor_container {
398 std::vector<ggml_context_ptr> ctxs;
399 std::map<const ggml_tensor *, std::vector<ggml_tensor *>> simple_tensors;
400
401 ggml_backend_meta_simple_tensor_container(const ggml_init_params & params, const int n_simple) {
402 ctxs.reserve(n_simple);
403 for (int i = 0; i < n_simple; i++) {
404 ctxs.emplace_back(ggml_init(params));
405 }
406 }
407 ggml_backend_meta_simple_tensor_container() {}
408};
409
410struct ggml_backend_meta_buffer_context {
411 // FIXME
412 // Most tensors can simply be stored statically in their own buffer.
413 // Externally created views however also need a mapping to simple tensors but they use the buffer of the view source.
414 // If external views are simply using that buffer they will slowly deplete its memory.
415 // Current solution: rotating set of 2 "compute" containers to hold external views, works correctly for llama.cpp.
416 // Long-term: tie the lifetime of external views to the meta backend executing the graph instead,
417 // currently not possible due to graph-external operations in the backend scheduler.
418 ggml_backend_meta_simple_tensor_container stc_static;
419 ggml_backend_meta_simple_tensor_container stc_compute[2];
420 int stc_compute_index = 0;
421 int stc_compute_index_next = 0;
422 std::vector<ggml_backend_buffer_ptr> bufs;
423
424 // FIXME
425 // The size of the split state cache is unbounded and can theoretically grow infinitely large.
426 // However, it is also expensive to build and clearing it on every rebuild in ggml_backend_meta_graph_compute is too expensive.
427 static constexpr size_t nbtc = GGML_TENSOR_SIZE - sizeof(ggml_tensor::padding);
428 std::map<std::pair<const ggml_tensor *, bool>, std::pair<ggml_backend_meta_split_state, char[nbtc]>> split_state_cache;
429
430 int debug;
431
432 ggml_backend_meta_buffer_context(
433 ggml_backend_meta_simple_tensor_container & stc_static,
434 ggml_backend_meta_simple_tensor_container & stc_compute_0,
435 ggml_backend_meta_simple_tensor_container & stc_compute_1,
436 const std::vector<ggml_backend_buffer_t> & bufs)
437 : stc_static(std::move(stc_static)), stc_compute{std::move(stc_compute_0), std::move(stc_compute_1)} {
438 this->bufs.reserve(bufs.size());
439 for (ggml_backend_buffer_t buf : bufs) {
440 this->bufs.emplace_back(buf);
441 }
442 const char * GGML_META_DEBUG = getenv("GGML_META_DEBUG");
443 debug = GGML_META_DEBUG ? atoi(GGML_META_DEBUG) : 0;
444 }
445
446 ggml_backend_meta_simple_tensor_container & get_simple_tensor_container(const ggml_tensor * tensor) {
447 if (stc_static.simple_tensors.find(tensor) != stc_static.simple_tensors.end()) {
448 return stc_static;
449 }
450 return stc_compute[stc_compute_index];
451 }
452};
453
454static void ggml_backend_meta_buffer_free_buffer(ggml_backend_buffer_t buffer) {
455 GGML_ASSERT(ggml_backend_buffer_is_meta(buffer))if (!(ggml_backend_buffer_is_meta(buffer))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 455, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(buffer)"
)
;
456 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) buffer->context;
457 delete buf_ctx;
458}
459
460static size_t ggml_backend_meta_buffer_n_bufs(ggml_backend_buffer_t meta_buf) {
461 GGML_ASSERT(ggml_backend_buffer_is_meta(meta_buf))if (!(ggml_backend_buffer_is_meta(meta_buf))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 461, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(meta_buf)"
)
;
462 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) meta_buf->context;
463 return buf_ctx->bufs.size();
464}
465
466static ggml_backend_buffer_t ggml_backend_meta_buffer_simple_buffer(ggml_backend_buffer_t meta_buf, size_t index) {
467 GGML_ASSERT(ggml_backend_buffer_is_meta(meta_buf))if (!(ggml_backend_buffer_is_meta(meta_buf))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 467, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(meta_buf)"
)
;
468 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) meta_buf->context;
469 GGML_ASSERT(index < buf_ctx->bufs.size())if (!(index < buf_ctx->bufs.size())) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 469, "GGML_ASSERT(%s) failed", "index < buf_ctx->bufs.size()"
)
;
470 return buf_ctx->bufs[index].get();
471}
472
473static struct ggml_tensor * ggml_backend_meta_buffer_simple_tensor(const struct ggml_tensor * tensor, size_t index) {
474 GGML_ASSERT(ggml_backend_buffer_is_meta(tensor->buffer))if (!(ggml_backend_buffer_is_meta(tensor->buffer))) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 474, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(tensor->buffer)"
)
;
475 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) tensor->buffer->context;
476 GGML_ASSERT(index < buf_ctx->bufs.size())if (!(index < buf_ctx->bufs.size())) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 476, "GGML_ASSERT(%s) failed", "index < buf_ctx->bufs.size()"
)
;
477
478 ggml_backend_meta_simple_tensor_container & stc = buf_ctx->get_simple_tensor_container(tensor);
479 auto it = stc.simple_tensors.find(tensor);
480 if (it == stc.simple_tensors.end()) {
481 return nullptr;
482 }
483 return it->second[index];
484}
485
486static struct ggml_backend_meta_split_state ggml_backend_meta_get_split_state(const struct ggml_tensor * tensor, bool assume_sync);
487
488static struct ggml_backend_meta_split_state ggml_backend_meta_get_split_state(
489 ggml_backend_meta_simple_tensor_container & stc, const struct ggml_tensor * tensor, bool assume_sync) {
490 // FIXME Currently this function preserves/erases the information in n_segments and nr in an inconsistent way.
491 // Since the operations in question are developed specifically for llama.cpp this currently does not manifest as a bug there.
492 // However, in a broader ggml context with arbitrary ggml graphs this can lead to unexpected results.
493 const size_t n_bufs = ggml_backend_meta_buffer_n_bufs(tensor->buffer);
494 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) tensor->buffer->context;
495
496 auto split_states_equal = [&](const ggml_backend_meta_split_state & a, const ggml_backend_meta_split_state & b) -> bool {
497 if (a.axis != b.axis) {
498 return false;
499 }
500 for (size_t j = 0; j < n_bufs; j++) {
501 int64_t sum_a = 0;
502 for (size_t s = 0; s < a.n_segments; s++) {
503 sum_a += a.ne[s*n_bufs + j] * a.nr[s];
504 }
505 int64_t sum_b = 0;
506 for (size_t s = 0; s < b.n_segments; s++) {
507 sum_b += b.ne[s*n_bufs + j] * b.nr[s];
508 }
509 if (sum_a != sum_b) {
510 return false;
511 }
512 }
513 return true;
514 };
515
516 auto handle_generic = [&](const std::vector<ggml_backend_meta_split_state> & src_ss, bool scalar_only) -> ggml_backend_meta_split_state {
517 ggml_backend_meta_split_state ret = {GGML_BACKEND_SPLIT_AXIS_NONE, {0}, {1}, 1};
518 for (size_t i = 0; i < GGML_MAX_SRC10; i++) {
519 if (tensor->src[i] == nullptr || tensor->src[i] == tensor) {
520 continue;
521 }
522 if (ret.axis == GGML_BACKEND_SPLIT_AXIS_NONE) {
523 ret = src_ss[i];
524 } else if (!split_states_equal(src_ss[i], ret)) {
525 ret = {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
526 break;
527 }
528 }
529 if (ret.axis == GGML_BACKEND_SPLIT_AXIS_NONE) {
530 ret = {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
531 }
532 if (scalar_only && ret.axis >= 0 && ret.axis < GGML_MAX_DIMS4) {
533 ret = {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
534 }
535 GGML_ASSERT(ret.axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN)if (!(ret.axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 535, "GGML_ASSERT(%s) failed", "ret.axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN"
)
;
536 return ret;
537 };
538
539 // Some ops process data on a per-row bases:
540 auto handle_per_row = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
541 GGML_ASSERT(src_ss[0].axis != GGML_BACKEND_SPLIT_AXIS_0)if (!(src_ss[0].axis != GGML_BACKEND_SPLIT_AXIS_0)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 541, "GGML_ASSERT(%s) failed", "src_ss[0].axis != GGML_BACKEND_SPLIT_AXIS_0"
)
;
542 return src_ss[0];
543 };
544
545 // Some ops broadcast the src1 data across src0:
546 auto handle_bin_bcast = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
547 if (src_ss[0].axis >= 0 && src_ss[0].axis < GGML_MAX_DIMS4 &&
548 tensor->src[1]->ne[src_ss[0].axis] == 1 && src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
549 return src_ss[0];
550 }
551 if (src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && (src_ss[0].axis == src_ss[1].axis ||
552 (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && (src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_PARTIAL)))) {
553 return src_ss[0]; // GGML_OP_ADD_ID
554 }
555 GGML_ASSERT(tensor->src[2] == nullptr || src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED)if (!(tensor->src[2] == nullptr || src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 555, "GGML_ASSERT(%s) failed", "tensor->src[2] == nullptr || src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED"
)
;
556 return handle_generic(src_ss, /*scalar_only =*/ false);
557 };
558
559 auto handle_concat = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
560 const ggml_backend_meta_split_axis concat_axis = ggml_backend_meta_split_axis(ggml_get_op_params_i32(tensor, 0));
561 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && src_ss[1].axis >= 0 && src_ss[1].axis < GGML_MAX_DIMS4) {
562 GGML_ASSERT(concat_axis != src_ss[1].axis)if (!(concat_axis != src_ss[1].axis)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 562, "GGML_ASSERT(%s) failed", "concat_axis != src_ss[1].axis"
)
;
563 return src_ss[1];
564 }
565 if (src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && src_ss[0].axis >= 0 && src_ss[0].axis < GGML_MAX_DIMS4) {
566 GGML_ASSERT(concat_axis != src_ss[0].axis)if (!(concat_axis != src_ss[0].axis)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 566, "GGML_ASSERT(%s) failed", "concat_axis != src_ss[0].axis"
)
;
567 return src_ss[0];
568 }
569 if (src_ss[0].axis == src_ss[1].axis && src_ss[0].axis != concat_axis) {
570 return src_ss[0];
571 }
572 return handle_generic(src_ss, /*scalar_only =*/ true);
573 };
574
575 auto handle_mul_mat = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
576 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
577 return {GGML_BACKEND_SPLIT_AXIS_MIRRORED, {0}, {1}, 1};
578 }
579 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_1 && src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
580 ggml_backend_meta_split_state ret = src_ss[0];
581 ret.axis = GGML_BACKEND_SPLIT_AXIS_0;
582 ret.nr[0] = 1;
583 ret.n_segments = 1;
584 return ret;
585 }
586 if (src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_1 && src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
587 return src_ss[1];
588 }
589 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_0 && src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_0) {
590 GGML_ASSERT(split_states_equal(src_ss[0], src_ss[1]))if (!(split_states_equal(src_ss[0], src_ss[1]))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 590, "GGML_ASSERT(%s) failed", "split_states_equal(src_ss[0], src_ss[1])"
)
;
591 return {assume_sync ? GGML_BACKEND_SPLIT_AXIS_MIRRORED : GGML_BACKEND_SPLIT_AXIS_PARTIAL, {0}, {1}, 1};
592 }
593 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 593, "fatal error")
;
594 //return {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
595 };
596
597 auto handle_reshape = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
598 switch (src_ss[0].axis) {
599 case GGML_BACKEND_SPLIT_AXIS_0:
600 case GGML_BACKEND_SPLIT_AXIS_1:
601 case GGML_BACKEND_SPLIT_AXIS_2:
602 case GGML_BACKEND_SPLIT_AXIS_3: {
603 GGML_ASSERT(src_ss[0].n_segments == 1)if (!(src_ss[0].n_segments == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 603, "GGML_ASSERT(%s) failed", "src_ss[0].n_segments == 1")
;
604 if (src_ss[0].axis == ggml_n_dims(tensor->src[0]) - 1 && src_ss[0].nr[0] == 1) {
605 return {ggml_backend_meta_split_axis(ggml_n_dims(tensor) - 1), {0}, {1}, 1};
606 }
607 int64_t base_ne_in = tensor->src[0]->ne[0];
608 for (int dim = 1; dim <= src_ss[0].axis; dim++) {
609 base_ne_in *= tensor->src[0]->ne[dim];
610 }
611 base_ne_in /= src_ss[0].nr[0];
612 int64_t base_ne_out = 1;
613 for (int dim = 0; dim < GGML_MAX_DIMS4; dim++) {
614 const int64_t base_ne_out_next = base_ne_out *= tensor->ne[dim];
615 if (base_ne_out_next % base_ne_in == 0) {
616 return {ggml_backend_meta_split_axis(dim), {0}, {uint32_t(base_ne_out_next/base_ne_in)}, 1};
617 }
618 if (base_ne_out_next > base_ne_in) {
619 GGML_ASSERT(src_ss[0].n_segments == 1)if (!(src_ss[0].n_segments == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 619, "GGML_ASSERT(%s) failed", "src_ss[0].n_segments == 1")
;
620 GGML_ASSERT(src_ss[0].nr[0] == 1)if (!(src_ss[0].nr[0] == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 620, "GGML_ASSERT(%s) failed", "src_ss[0].nr[0] == 1")
;
621 return {ggml_backend_meta_split_axis(dim), {0}, {1}, 1};
622 }
623 base_ne_out = base_ne_out_next;
624 }
625 GGML_ABORT("shape mismatch for %s", ggml_op_name(tensor->op))ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 625, "shape mismatch for %s", ggml_op_name(tensor->op))
;
626 }
627 case GGML_BACKEND_SPLIT_AXIS_MIRRORED:
628 case GGML_BACKEND_SPLIT_AXIS_PARTIAL: {
629 return src_ss[0];
630 }
631 default: {
632 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 632, "fatal error")
;
633 //return {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
634 }
635 }
636 };
637
638 auto handle_cpy = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
639 if (src_ss[0].axis >= 0 && src_ss[0].axis < GGML_MAX_DIMS4) {
640 return handle_reshape(src_ss);
641 }
642 return handle_generic(src_ss, /*scalar_only =*/ false);
643 };
644
645 auto handle_view = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
646 if (ggml_is_contiguous(tensor) && ggml_is_contiguous(tensor->src[0])) {
647 return handle_reshape(src_ss);
648 }
649 const int axis = src_ss[0].axis;
650 {
651 bool all_strides_the_same = true;
652 for (int dim = 0; dim < GGML_MAX_DIMS4; dim++) {
653 if (tensor->ne[dim] == 1 && tensor->src[0]->ne[dim] == 1) {
654 continue;
655 }
656 if (tensor->nb[dim] != tensor->src[0]->nb[dim]) {
657 all_strides_the_same = false;
658 break;
659 }
660 }
661 if (all_strides_the_same) {
662 return src_ss[0];
663 }
664 }
665 if (!ggml_is_permuted(tensor) && !ggml_is_permuted(tensor->src[0]) && axis >= 0 && axis < GGML_MAX_DIMS4-1) {
666 for (int dim = 0; dim < GGML_MAX_DIMS4-1; dim++) {
667 if (tensor->nb[dim+1] == tensor->src[0]->nb[axis+1]) {
668 return {ggml_backend_meta_split_axis(dim), {0}, {1}, 1};
669 }
670 }
671 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 671, "fatal error")
;
672 }
673 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED || src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_PARTIAL) {
674 return src_ss[0];
675 }
676 GGML_ABORT("view of permuted tensor not implemented")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 676, "view of permuted tensor not implemented")
;
677 //return {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
678 };
679
680 auto handle_permute = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
681 switch (src_ss[0].axis) {
682 case GGML_BACKEND_SPLIT_AXIS_0:
683 case GGML_BACKEND_SPLIT_AXIS_1:
684 case GGML_BACKEND_SPLIT_AXIS_2:
685 case GGML_BACKEND_SPLIT_AXIS_3: {
686 GGML_ASSERT(src_ss[0].n_segments == 1 || src_ss[0].nr[0] == 1)if (!(src_ss[0].n_segments == 1 || src_ss[0].nr[0] == 1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 686, "GGML_ASSERT(%s) failed", "src_ss[0].n_segments == 1 || src_ss[0].nr[0] == 1"
)
;
687 return {ggml_backend_meta_split_axis(tensor->op_params[src_ss[0].axis]), {0}, {src_ss[0].nr[0]}, 1};
688 }
689 case GGML_BACKEND_SPLIT_AXIS_MIRRORED:
690 case GGML_BACKEND_SPLIT_AXIS_PARTIAL: {
691 return src_ss[0];
692 }
693 default: {
694 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 694, "fatal error")
;
695 //return {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
696 }
697 }
698 };
699
700 auto handle_transpose = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
701 switch (src_ss[0].axis) {
702 case GGML_BACKEND_SPLIT_AXIS_0:
703 case GGML_BACKEND_SPLIT_AXIS_1: {
704 GGML_ASSERT(src_ss[0].n_segments == 1 || src_ss[0].nr[0] == 1)if (!(src_ss[0].n_segments == 1 || src_ss[0].nr[0] == 1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 704, "GGML_ASSERT(%s) failed", "src_ss[0].n_segments == 1 || src_ss[0].nr[0] == 1"
)
;
705 return {ggml_backend_meta_split_axis(int(src_ss[0].axis) ^ 1), {0}, {src_ss[0].nr[0]}, 1};
706 }
707 case GGML_BACKEND_SPLIT_AXIS_2:
708 case GGML_BACKEND_SPLIT_AXIS_3:
709 case GGML_BACKEND_SPLIT_AXIS_MIRRORED:
710 case GGML_BACKEND_SPLIT_AXIS_PARTIAL: {
711 return src_ss[0];
712 }
713 default: {
714 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 714, "fatal error")
;
715 //return {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
716 }
717 }
718 };
719
720 auto handle_get_rows = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
721 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_0 && src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
722 return src_ss[0];
723 }
724 return handle_generic(src_ss, /*scalar_only =*/ true);
725 };
726
727 auto handle_set_rows = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
728 GGML_ASSERT(src_ss[0].axis != GGML_BACKEND_SPLIT_AXIS_1)if (!(src_ss[0].axis != GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 728, "GGML_ASSERT(%s) failed", "src_ss[0].axis != GGML_BACKEND_SPLIT_AXIS_1"
)
;
729 GGML_ASSERT(src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED)if (!(src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 729, "GGML_ASSERT(%s) failed", "src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED"
)
;
730 GGML_ASSERT(split_states_equal(src_ss[0], src_ss[2]))if (!(split_states_equal(src_ss[0], src_ss[2]))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 730, "GGML_ASSERT(%s) failed", "split_states_equal(src_ss[0], src_ss[2])"
)
;
731 return src_ss[0];
732 };
733
734 auto handle_rope = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
735 GGML_ASSERT(src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED)if (!(src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 735, "GGML_ASSERT(%s) failed", "src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED"
)
;
736 return src_ss[0];
737 };
738
739 auto handle_pad = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
740 if (src_ss[0].axis >= 0 && src_ss[0].axis < GGML_MAX_DIMS4) {
741 GGML_ASSERT(tensor->op_params[2*src_ss[0].axis + 0] == 0)if (!(tensor->op_params[2*src_ss[0].axis + 0] == 0)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 741, "GGML_ASSERT(%s) failed", "tensor->op_params[2*src_ss[0].axis + 0] == 0"
)
;
742 GGML_ASSERT(tensor->op_params[2*src_ss[0].axis + 1] == 0)if (!(tensor->op_params[2*src_ss[0].axis + 1] == 0)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 742, "GGML_ASSERT(%s) failed", "tensor->op_params[2*src_ss[0].axis + 1] == 0"
)
;
743 }
744 return src_ss[0];
745 };
746
747 auto handle_flash_attn_ext = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
748 GGML_ASSERT( src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_2)if (!(src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_2)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 748, "GGML_ASSERT(%s) failed", "src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_2"
)
;
749 GGML_ASSERT( src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_2)if (!(src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_2)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 749, "GGML_ASSERT(%s) failed", "src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_2"
)
;
750 GGML_ASSERT( src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_2)if (!(src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_2)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 750, "GGML_ASSERT(%s) failed", "src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_2"
)
;
751 GGML_ASSERT(tensor->src[4] == nullptr || src_ss[3].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED)if (!(tensor->src[4] == nullptr || src_ss[3].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 751, "GGML_ASSERT(%s) failed", "tensor->src[4] == nullptr || src_ss[3].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED"
)
;
752 GGML_ASSERT(tensor->src[4] == nullptr || src_ss[4].axis == GGML_BACKEND_SPLIT_AXIS_0)if (!(tensor->src[4] == nullptr || src_ss[4].axis == GGML_BACKEND_SPLIT_AXIS_0
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 752, "GGML_ASSERT(%s) failed", "tensor->src[4] == nullptr || src_ss[4].axis == GGML_BACKEND_SPLIT_AXIS_0"
)
;
753 return {GGML_BACKEND_SPLIT_AXIS_1, {0}, {1}, 1};
754 };
755
756 auto handle_ssm_conv = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
757 if (src_ss[0].axis == src_ss[1].axis) {
758 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_0) {
759 return {GGML_BACKEND_SPLIT_AXIS_1, {0}, {1}, 1};
760 }
761 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_1) {
762 return {GGML_BACKEND_SPLIT_AXIS_0, {0}, {1}, 1};
763 }
764 }
765 return handle_generic(src_ss, /*scalar_only =*/ false);
766 };
767
768 auto handle_gated_delta_net = [&](const std::vector<ggml_backend_meta_split_state> & src_ss) -> ggml_backend_meta_split_state {
769 if (src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED &&
770 src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && src_ss[3].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED &&
771 src_ss[4].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED && src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
772 return src_ss[0];
773 }
774 GGML_ASSERT(src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_1)if (!(src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 774, "GGML_ASSERT(%s) failed", "src_ss[0].axis == GGML_BACKEND_SPLIT_AXIS_1"
)
;
775 GGML_ASSERT(src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_1)if (!(src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 775, "GGML_ASSERT(%s) failed", "src_ss[1].axis == GGML_BACKEND_SPLIT_AXIS_1"
)
;
776 GGML_ASSERT(src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_1)if (!(src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 776, "GGML_ASSERT(%s) failed", "src_ss[2].axis == GGML_BACKEND_SPLIT_AXIS_1"
)
;
777 GGML_ASSERT(src_ss[3].axis == GGML_BACKEND_SPLIT_AXIS_1)if (!(src_ss[3].axis == GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 777, "GGML_ASSERT(%s) failed", "src_ss[3].axis == GGML_BACKEND_SPLIT_AXIS_1"
)
;
778 GGML_ASSERT(src_ss[4].axis == GGML_BACKEND_SPLIT_AXIS_1)if (!(src_ss[4].axis == GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 778, "GGML_ASSERT(%s) failed", "src_ss[4].axis == GGML_BACKEND_SPLIT_AXIS_1"
)
;
779 // state shape is [S_v, S_v, H_v, n_seqs] (s0 only); the heads dim is its own axis 2,
780 // so a head-aligned split on the input cache lands on axis 2 here.
781 GGML_ASSERT(src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_2 || src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_1 || src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_0)if (!(src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_2 || src_ss[5
].axis == GGML_BACKEND_SPLIT_AXIS_1 || src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_0
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 781, "GGML_ASSERT(%s) failed", "src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_2 || src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_1 || src_ss[5].axis == GGML_BACKEND_SPLIT_AXIS_0"
)
;
782 return {GGML_BACKEND_SPLIT_AXIS_0, {0}, {1}, 1};
783 };
784
785 auto calculate_split_state = [&]() -> ggml_backend_meta_split_state {
786 if (ggml_nelements(tensor) == 0) {
787 return {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
788 }
789 if (ggml_backend_buffer_get_usage(tensor->buffer) != GGML_BACKEND_BUFFER_USAGE_COMPUTE && tensor->view_src == nullptr) {
790 ggml_backend_dev_t dev = ggml_backend_buft_get_device(ggml_backend_buffer_get_type(tensor->buffer));
791 const ggml_backend_meta_device_context * dev_ctx = (const ggml_backend_meta_device_context *) dev->context;
792 ggml_backend_meta_split_state ret = dev_ctx->get_split_state(tensor, dev_ctx->get_split_state_ud);
793 if (ret.axis >= 0 && ret.axis <= GGML_MAX_DIMS4) {
794 const int64_t granularity = ret.axis == GGML_BACKEND_SPLIT_AXIS_0 ? ggml_blck_size(tensor->type) : 1;
795 int64_t ne_sum = 0;
796 for (size_t s = 0; s < ret.n_segments; s++) {
797 for (size_t j = 0; j < n_bufs; j++) {
798 GGML_ASSERT(ret.ne[s*n_bufs + j] % granularity == 0)if (!(ret.ne[s*n_bufs + j] % granularity == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 798, "GGML_ASSERT(%s) failed", "ret.ne[s*n_bufs + j] % granularity == 0"
)
;
799 ne_sum += ret.ne[s*n_bufs + j] * ret.nr[s];
800 }
801 }
802 GGML_ASSERT(ne_sum == tensor->ne[ret.axis])if (!(ne_sum == tensor->ne[ret.axis])) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 802, "GGML_ASSERT(%s) failed", "ne_sum == tensor->ne[ret.axis]"
)
;
803 }
804 return ret;
805 }
806
807 std::vector<ggml_backend_meta_split_state> src_ss(GGML_MAX_SRC10, {GGML_BACKEND_SPLIT_AXIS_NONE, {0}, {1}, 1});
808 for (size_t i = 0; i < GGML_MAX_SRC10; i++) {
809 if (tensor->src[i] == nullptr || tensor->src[i] == tensor) {
810 src_ss[i] = {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
811 continue;
812 }
813 src_ss[i] = ggml_backend_meta_get_split_state(stc, tensor->src[i], /*assume_sync =*/ true);
814 GGML_ASSERT(src_ss[i].axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN)if (!(src_ss[i].axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 814, "GGML_ASSERT(%s) failed", "src_ss[i].axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN"
)
;
815 }
816
817 ggml_backend_meta_split_state split_state;
818 switch (tensor->op) {
819 case GGML_OP_NONE: {
820 split_state = {GGML_BACKEND_SPLIT_AXIS_MIRRORED, {0}, {1}, 1};
821 } break;
822 case GGML_OP_DUP: {
823 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
824 } break;
825 case GGML_OP_ADD:
826 case GGML_OP_ADD_ID: {
827 split_state = handle_bin_bcast(src_ss);
828 } break;
829 case GGML_OP_ADD1:
830 case GGML_OP_ACC: {
831 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
832 } break;
833 case GGML_OP_SUB:
834 case GGML_OP_MUL:
835 case GGML_OP_DIV: {
836 split_state = handle_bin_bcast(src_ss);
837 } break;
838 case GGML_OP_SQR:
839 case GGML_OP_SQRT:
840 case GGML_OP_LOG:
841 case GGML_OP_SIN:
842 case GGML_OP_COS: {
843 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
844 } break;
845 case GGML_OP_SUM: {
846 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
847 } break;
848 case GGML_OP_SUM_ROWS:
849 case GGML_OP_CUMSUM:
850 case GGML_OP_MEAN:
851 case GGML_OP_ARGMAX:
852 case GGML_OP_COUNT_EQUAL: {
853 split_state = handle_per_row(src_ss);
854 } break;
855 case GGML_OP_REPEAT:
856 case GGML_OP_REPEAT_BACK: {
857 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
858 } break;
859 case GGML_OP_CONCAT: {
860 split_state = handle_concat(src_ss);
861 } break;
862 case GGML_OP_SILU_BACK: {
863 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
864 } break;
865 case GGML_OP_NORM:
866 case GGML_OP_RMS_NORM:
867 case GGML_OP_RMS_NORM_BACK:
868 case GGML_OP_GROUP_NORM:
869 case GGML_OP_L2_NORM: {
870 split_state = handle_per_row(src_ss);
871 } break;
872 case GGML_OP_MUL_MAT:
873 case GGML_OP_MUL_MAT_ID: {
874 split_state = handle_mul_mat(src_ss);
875 } break;
876 case GGML_OP_OUT_PROD: {
877 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
878 } break;
879 case GGML_OP_SCALE: {
880 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
881 } break;
882 case GGML_OP_SET: {
883 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
884 } break;
885 case GGML_OP_CPY: {
886 split_state = handle_cpy(src_ss);
887 } break;
888 case GGML_OP_CONT:
889 case GGML_OP_RESHAPE: {
890 split_state = handle_reshape(src_ss);
891 } break;
892 case GGML_OP_VIEW: {
893 split_state = handle_view(src_ss);
894 } break;
895 case GGML_OP_PERMUTE: {
896 split_state = handle_permute(src_ss);
897 } break;
898 case GGML_OP_TRANSPOSE: {
899 split_state = handle_transpose(src_ss);
900 } break;
901 case GGML_OP_GET_ROWS: {
902 split_state = handle_get_rows(src_ss);
903 } break;
904 case GGML_OP_GET_ROWS_BACK: {
905 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
906 } break;
907 case GGML_OP_SET_ROWS: {
908 split_state = handle_set_rows(src_ss);
909 } break;
910 case GGML_OP_DIAG:
911 case GGML_OP_DIAG_MASK_INF:
912 case GGML_OP_DIAG_MASK_ZERO: {
913 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
914 } break;
915 case GGML_OP_SOFT_MAX:
916 case GGML_OP_SOFT_MAX_BACK: {
917 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
918 } break;
919 case GGML_OP_ROPE: {
920 split_state = handle_rope(src_ss);
921 } break;
922 case GGML_OP_ROPE_BACK: {
923 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
924 } break;
925 case GGML_OP_CLAMP: {
926 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
927 } break;
928 case GGML_OP_CONV_TRANSPOSE_1D:
929 case GGML_OP_IM2COL:
930 case GGML_OP_IM2COL_BACK:
931 case GGML_OP_IM2COL_3D:
932 case GGML_OP_CONV_2D:
933 case GGML_OP_CONV_3D:
934 case GGML_OP_CONV_2D_DW:
935 case GGML_OP_CONV_TRANSPOSE_2D:
936 case GGML_OP_POOL_1D:
937 case GGML_OP_POOL_2D:
938 case GGML_OP_POOL_2D_BACK:
939 case GGML_OP_UPSCALE: {
940 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
941 } break;
942 case GGML_OP_PAD: {
943 split_state = handle_pad(src_ss);
944 } break;
945 case GGML_OP_PAD_REFLECT_1D:
946 case GGML_OP_ROLL:
947 case GGML_OP_ARANGE:
948 case GGML_OP_TIMESTEP_EMBEDDING: {
949 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
950 } break;
951 case GGML_OP_ARGSORT:
952 case GGML_OP_TOP_K: {
953 split_state = handle_per_row(src_ss);
954 } break;
955 case GGML_OP_LEAKY_RELU: {
956 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
957 } break;
958 case GGML_OP_TRI: {
959 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
960 } break;
961 case GGML_OP_FILL: {
962 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
963 } break;
964 case GGML_OP_FLASH_ATTN_EXT: {
965 split_state = handle_flash_attn_ext(src_ss);
966 } break;
967 case GGML_OP_FLASH_ATTN_BACK: {
968 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
969 } break;
970 case GGML_OP_SSM_CONV: {
971 split_state = handle_ssm_conv(src_ss);
972 } break;
973 case GGML_OP_SSM_SCAN:
974 case GGML_OP_WIN_PART:
975 case GGML_OP_WIN_UNPART:
976 case GGML_OP_GET_REL_POS:
977 case GGML_OP_ADD_REL_POS:
978 case GGML_OP_RWKV_WKV6:
979 case GGML_OP_GATED_LINEAR_ATTN:
980 case GGML_OP_RWKV_WKV7:
981 case GGML_OP_SOLVE_TRI: {
982 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
983 } break;
984 case GGML_OP_GATED_DELTA_NET: {
985 split_state = handle_gated_delta_net(src_ss);
986 } break;
987 case GGML_OP_UNARY: {
988 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
989 } break;
990 case GGML_OP_MAP_CUSTOM1:
991 case GGML_OP_MAP_CUSTOM2:
992 case GGML_OP_MAP_CUSTOM3:
993 case GGML_OP_CUSTOM: {
994 split_state = handle_generic(src_ss, /*scalar_only =*/ true);
995 } break;
996 case GGML_OP_CROSS_ENTROPY_LOSS:
997 case GGML_OP_CROSS_ENTROPY_LOSS_BACK: {
998 split_state = handle_per_row(src_ss);
999 } break;
1000 case GGML_OP_OPT_STEP_ADAMW:
1001 case GGML_OP_OPT_STEP_SGD:
1002 case GGML_OP_GLU: {
1003 split_state = handle_generic(src_ss, /*scalar_only =*/ false);
1004 } break;
1005 default: {
1006 GGML_ABORT("ggml op not implemented: %s", ggml_op_name(tensor->op))ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1006, "ggml op not implemented: %s", ggml_op_name(tensor->
op))
;
1007 split_state = {GGML_BACKEND_SPLIT_AXIS_UNKNOWN, {0}, {1}, 1};
1008 } break;
1009 }
1010 if (split_state.axis >= 0 && split_state.axis < GGML_MAX_DIMS4) {
1011 bool first_src_split_by_axis = true;
1012 const size_t n_bufs = ggml_backend_meta_buffer_n_bufs(tensor->buffer);
1013
1014 for (size_t i = 0; i < GGML_MAX_SRC10; i++) {
1015 if (tensor->src[i] == nullptr || src_ss[i].axis < 0 || src_ss[i].axis >= GGML_MAX_DIMS4) {
1016 continue;
1017 }
1018 if (first_src_split_by_axis) {
1019 for (size_t j = 0; j < n_bufs; j++) {
1020 // Take over ratio from src:
1021 for (size_t s = 0; s < src_ss[i].n_segments; s++) {
1022 split_state.ne[s*n_bufs + j] = 0;
1023 }
1024 for (size_t s = 0; s < src_ss[i].n_segments; s++) {
1025 split_state.ne[j] += src_ss[i].ne[s*n_bufs + j] * src_ss[i].nr[s];
1026 }
1027 split_state.ne[j] *= tensor->ne[split_state.axis];
1028 if (split_state.ne[j] != 0 || tensor->src[i]->ne[src_ss[i].axis] != 0) {
1029 const int64_t div = tensor->src[i]->ne[src_ss[i].axis] * split_state.nr[0];
1030 GGML_ASSERT(split_state.ne[j] % div == 0)if (!(split_state.ne[j] % div == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1030, "GGML_ASSERT(%s) failed", "split_state.ne[j] % div == 0"
)
;
1031 split_state.ne[j] /= div;
1032 }
1033 }
1034 } else {
1035 GGML_ASSERT(split_state.n_segments == 1)if (!(split_state.n_segments == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1035, "GGML_ASSERT(%s) failed", "split_state.n_segments == 1"
)
;
1036 for (size_t j = 0; j < n_bufs; j++) {
1037 // Assert that ratio is consistent:
1038 int64_t sum = 0;
1039 for (size_t s = 0; s < src_ss[i].n_segments; s++) {
1040 sum += src_ss[i].ne[s*n_bufs + j] * src_ss[i].nr[s];
1041 }
1042 GGML_ASSERT(split_state.ne[j]*split_state.nr[0] * tensor->src[i]->ne[src_ss[i].axis]if (!(split_state.ne[j]*split_state.nr[0] * tensor->src[i]
->ne[src_ss[i].axis] == sum * tensor->ne[split_state.axis
])) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1043, "GGML_ASSERT(%s) failed", "split_state.ne[j]*split_state.nr[0] * tensor->src[i]->ne[src_ss[i].axis] == sum * tensor->ne[split_state.axis]"
)
1043 == sum * tensor->ne[split_state.axis])if (!(split_state.ne[j]*split_state.nr[0] * tensor->src[i]
->ne[src_ss[i].axis] == sum * tensor->ne[split_state.axis
])) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1043, "GGML_ASSERT(%s) failed", "split_state.ne[j]*split_state.nr[0] * tensor->src[i]->ne[src_ss[i].axis] == sum * tensor->ne[split_state.axis]"
)
;
1044 }
1045 }
1046 first_src_split_by_axis = false;
1047 }
1048 GGML_ASSERT(!first_src_split_by_axis)if (!(!first_src_split_by_axis)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1048, "GGML_ASSERT(%s) failed", "!first_src_split_by_axis")
;
1049 }
1050 return split_state;
1051 };
1052
1053 const std::pair key = std::make_pair(tensor, assume_sync);
1054 auto it = buf_ctx->split_state_cache.find(key);
1055 if (it != buf_ctx->split_state_cache.end() && memcmp(it->second.second, (const char *) tensor, sizeof(it->second.second)) != 0) {
22
Assuming the condition is false
23
Taking false branch
1056 buf_ctx->split_state_cache.clear();
1057 it = buf_ctx->split_state_cache.end();
1058 }
1059
1060 if (it == buf_ctx->split_state_cache.end()) {
24
Taking true branch
1061 buf_ctx->split_state_cache[key].first = calculate_split_state();
25
Assigning value
1062 memcpy(buf_ctx->split_state_cache[key].second, tensor, sizeof(buf_ctx->split_state_cache[key].second));
1063 if (buf_ctx->debug > 0) {
26
Assuming field 'debug' is > 0
27
Taking true branch
1064 std::string srcs_info;
1065 for (size_t i = 0; i < GGML_MAX_SRC10; i++) {
28
Loop condition is true. Entering loop body
32
Loop condition is true. Entering loop body
1066 if (tensor->src[i] == nullptr) {
29
Assuming pointer value is null
30
Taking true branch
33
Assuming the condition is false
34
Taking false branch
1067 continue;
31
Execution continues on line 1065
1068 }
1069 if (!srcs_info.empty()) {
35
Assuming the condition is false
36
Taking false branch
1070 srcs_info += ", ";
1071 }
1072 const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(tensor->src[0], true);
37
Passing null pointer value via 1st parameter 'tensor'
38
Calling 'ggml_backend_meta_get_split_state'
1073 GGML_ASSERT(split_state.n_segments == 1)if (!(split_state.n_segments == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1073, "GGML_ASSERT(%s) failed", "split_state.n_segments == 1"
)
;
1074 const char * axis_name = ggml_backend_meta_split_axis_name(split_state.axis);
1075 std::string ne_info;
1076 for (size_t j = 0; j < n_bufs; j++) {
1077 if (!ne_info.empty()) {
1078 ne_info += ", ";
1079 }
1080 ne_info += std::to_string(split_state.ne[j]) + "x" + std::to_string(split_state.nr[0]);
1081 }
1082 srcs_info += std::string(tensor->src[i]->name) + "[" + ggml_op_name(tensor->src[i]->op) + ", " + axis_name + ", {" + ne_info + "}]";
1083 }
1084 std::string ne_info;
1085 for (size_t j = 0; j < n_bufs; j++) {
1086 if (!ne_info.empty()) {
1087 ne_info += ", ";
1088 }
1089 const ggml_backend_meta_split_state & ss = buf_ctx->split_state_cache[key].first;
1090 ne_info += std::to_string(ss.ne[j]) + "x" + std::to_string(ss.nr[0]);
1091 }
1092 GGML_LOG_DEBUG("SPLIT_STATE: {%s} -> %s[%s, %s, {%s}]\n", srcs_info.c_str(), tensor->name, ggml_op_name(tensor->op),ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "SPLIT_STATE: {%s} -> %s[%s, %s, {%s}]\n"
, srcs_info.c_str(), tensor->name, ggml_op_name(tensor->
op), ggml_backend_meta_split_axis_name(buf_ctx->split_state_cache
[key].first.axis), ne_info.c_str())
1093 ggml_backend_meta_split_axis_name(buf_ctx->split_state_cache[key].first.axis), ne_info.c_str())ggml_log_internal(GGML_LOG_LEVEL_DEBUG, "SPLIT_STATE: {%s} -> %s[%s, %s, {%s}]\n"
, srcs_info.c_str(), tensor->name, ggml_op_name(tensor->
op), ggml_backend_meta_split_axis_name(buf_ctx->split_state_cache
[key].first.axis), ne_info.c_str())
;
1094 }
1095 }
1096
1097 ggml_backend_meta_split_state ret = buf_ctx->split_state_cache[key].first;
1098 GGML_ASSERT(ret.axis != GGML_BACKEND_SPLIT_AXIS_NONE)if (!(ret.axis != GGML_BACKEND_SPLIT_AXIS_NONE)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1098, "GGML_ASSERT(%s) failed", "ret.axis != GGML_BACKEND_SPLIT_AXIS_NONE"
)
;
1099#ifndef NDEBUG
1100 if (ret.axis >= 0 && ret.axis < GGML_MAX_DIMS4) {
1101 int64_t ne_ret = 0;
1102 for (size_t s = 0; s < ret.n_segments; s++) {
1103 for (size_t j = 0; j < n_bufs; j++) {
1104 ne_ret += ret.ne[s*n_bufs + j] * ret.nr[s];
1105 }
1106 }
1107 assert(ne_ret == tensor->ne[int(ret.axis)])(static_cast <bool> (ne_ret == tensor->ne[int(ret.axis
)]) ? void (0) : __assert_fail ("ne_ret == tensor->ne[int(ret.axis)]"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
1108 }
1109#endif // NDEBUG
1110 return ret;
1111}
1112
1113static struct ggml_backend_meta_split_state ggml_backend_meta_get_split_state(const struct ggml_tensor * tensor, bool assume_sync) {
1114 GGML_ASSERT(ggml_backend_buffer_is_meta(tensor->buffer))if (!(ggml_backend_buffer_is_meta(tensor->buffer))) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1114, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(tensor->buffer)"
)
;
20
Taking false branch
39
Access to field 'buffer' results in a dereference of a null pointer (loaded from variable 'tensor')
1115 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) tensor->buffer->context;
1116 return ggml_backend_meta_get_split_state(buf_ctx->get_simple_tensor_container(tensor), tensor, assume_sync);
21
Calling 'ggml_backend_meta_get_split_state'
1117}
1118
1119static void * ggml_backend_meta_buffer_get_base(ggml_backend_buffer_t buffer) {
1120 GGML_UNUSED(buffer)(void)(buffer);
1121 return (void *) 0x1000000000000000; // FIXME
1122}
1123
1124static enum ggml_status ggml_backend_meta_buffer_init_tensor_impl(ggml_backend_meta_simple_tensor_container & stc, ggml_tensor * tensor) {
1125 GGML_ASSERT(ggml_backend_buffer_is_meta(tensor->buffer))if (!(ggml_backend_buffer_is_meta(tensor->buffer))) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1125, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(tensor->buffer)"
)
;
1126 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) tensor->buffer->context;
1127 const size_t n_simple_bufs = ggml_backend_meta_buffer_n_bufs(tensor->buffer);
1128
1129 const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(stc, tensor, /*assume_sync =*/ true);
1130 GGML_ASSERT(ggml_nelements(tensor) == 0 || split_state.axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN)if (!(ggml_nelements(tensor) == 0 || split_state.axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN
)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1130, "GGML_ASSERT(%s) failed", "ggml_nelements(tensor) == 0 || split_state.axis != GGML_BACKEND_SPLIT_AXIS_UNKNOWN"
)
;
1131 GGML_ASSERT(split_state.n_segments <= 16)if (!(split_state.n_segments <= 16)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1131, "GGML_ASSERT(%s) failed", "split_state.n_segments <= 16"
)
;
1132
1133 int split_dim = split_state.axis;
1134 int64_t ne[GGML_MAX_DIMS4];
1135 size_t nb[GGML_MAX_DIMS4];
1136 for (size_t k = 0; k < GGML_MAX_DIMS4; k++) {
1137 ne[k] = tensor->ne[k];
1138 nb[k] = tensor->nb[k];
1139 }
1140
1141 std::vector<ggml_tensor *> simple_tensors;
1142 simple_tensors.reserve(n_simple_bufs);
1143 for (size_t j = 0; j < n_simple_bufs; j++) {
1144 ggml_context * simple_ctx = stc.ctxs[j].get();
1145 ggml_backend_buffer_t simple_buf = buf_ctx->bufs[j].get();
1146
1147 if (split_dim >= 0 && split_dim < GGML_MAX_DIMS4) {
1148 // TODO: the following assert fails for llama-parallel even though the results are correct:
1149 // GGML_ASSERT(ggml_is_contiguously_allocated(tensor));
1150 ne[split_dim] = 0;
1151 for (size_t s = 0; s < split_state.n_segments; s++) {
1152 ne[split_dim] += split_state.ne[s*n_simple_bufs + j] * split_state.nr[s];
1153 }
1154 for (int i = 0; i < GGML_MAX_DIMS4; i++) {
1155 if (tensor->nb[i] > tensor->nb[split_dim]) {
1156 nb[i] = tensor->nb[i] * ne[split_dim]/tensor->ne[split_dim];
1157 }
1158 }
1159 }
1160
1161 ggml_tensor * t_ij = ggml_new_tensor(simple_ctx, tensor->type, GGML_MAX_DIMS4, ne);
1162 t_ij->op = tensor->op;
1163 for (int i = 0; i < GGML_MAX_DIMS4; i++) {
1164 t_ij->nb[i] = nb[i];
1165 }
1166 t_ij->flags = tensor->flags;
1167 memcpy(t_ij->op_params, tensor->op_params, sizeof(tensor->op_params));
1168 ggml_set_name(t_ij, tensor->name);
1169 t_ij->buffer = simple_buf;
1170 t_ij->view_src = tensor->view_src;
1171 t_ij->view_offs = tensor->view_offs;
1172 if (t_ij->view_src != nullptr && ggml_backend_buffer_is_meta(t_ij->view_src->buffer)) {
1173 t_ij->view_src = ggml_backend_meta_buffer_simple_tensor(tensor->view_src, j);
1174 if (t_ij->view_offs > 0 && split_dim >= 0 && split_dim < GGML_MAX_DIMS4) {
1175 GGML_ASSERT(tensor->ne[split_dim] != 0)if (!(tensor->ne[split_dim] != 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1175, "GGML_ASSERT(%s) failed", "tensor->ne[split_dim] != 0"
)
;
1176 const int split_dim_view_src = ggml_backend_meta_get_split_state(tensor->view_src, /*assume_sync =*/ true).axis;
1177 GGML_ASSERT(split_dim_view_src >= 0 && split_dim_view_src < GGML_MAX_DIMS)if (!(split_dim_view_src >= 0 && split_dim_view_src
< 4)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1177, "GGML_ASSERT(%s) failed", "split_dim_view_src >= 0 && split_dim_view_src < GGML_MAX_DIMS"
)
;
1178
1179 // The offset can be internal to the data split, in those cases the view offset should not be scaled.
1180 // If however, the offset is larger than the data split then it needs to be scaled proportionally.
1181 bool split_internal_offset = t_ij->view_offs <= tensor->view_src->nb[split_dim_view_src];
1182 for (int i = 0; i < GGML_MAX_DIMS4; i++) {
1183 const size_t dim_size = tensor->ne[i] * tensor->nb[i];
1184 if (tensor->view_offs <= dim_size && dim_size < tensor->nb[split_dim]) {
1185 split_internal_offset = true;
1186 break;
1187 }
1188 }
1189 if (!split_internal_offset) {
1190 t_ij->view_offs = t_ij->view_offs * ne[split_dim]/tensor->ne[split_dim];
1191 }
1192 }
1193 }
1194 if (t_ij->view_src != nullptr) {
1195 t_ij->data = (char *) t_ij->view_src->data + t_ij->view_offs;
1196 } else if (simple_buf != nullptr) {
1197 t_ij->data = (char *) ggml_backend_buffer_get_base(simple_buf)
1198 + size_t(tensor->data) - size_t(ggml_backend_buffer_get_base(tensor->buffer));
1199 }
1200 t_ij->extra = tensor->extra;
1201 for (int i = 0; i < GGML_MAX_SRC10; i++) {
1202 t_ij->src[i] = tensor->src[i];
1203 if (tensor->src[i] == tensor) {
1204 t_ij->src[i] = t_ij;
1205 } else if (t_ij->src[i] != nullptr && ggml_backend_buffer_is_meta(t_ij->src[i]->buffer)) {
1206 t_ij->src[i] = ggml_backend_meta_buffer_simple_tensor(tensor->src[i], j);
1207 }
1208 }
1209
1210 simple_tensors.push_back(t_ij);
1211 }
1212
1213 // If one of the sources has a zero-sized slice, disable the computation:
1214 for (int i = 0; i < GGML_MAX_SRC10; i++) {
1215 if (tensor->src[i] == nullptr || !ggml_backend_buffer_is_meta(tensor->src[i]->buffer)) {
1216 continue;
1217 }
1218
1219 const ggml_backend_meta_split_state split_state_src = ggml_backend_meta_get_split_state(tensor->src[i], /*assume_sync =*/ true);
1220 if (split_state_src.axis < 0 || split_state_src.axis >= GGML_MAX_DIMS4) {
1221 continue;
1222 }
1223 for (size_t j = 0; j < n_simple_bufs; j++) {
1224 int64_t ne_sum = 0;
1225 for (size_t s = 0; s < split_state_src.n_segments; s++) {
1226 ne_sum += split_state_src.ne[s*n_simple_bufs + j] * split_state_src.nr[s];
1227 }
1228 if (ne_sum == 0) {
1229 simple_tensors[j]->flags &= ~GGML_TENSOR_FLAG_COMPUTE;
1230 }
1231 }
1232 }
1233
1234 stc.simple_tensors[tensor] = simple_tensors;
1235
1236 return GGML_STATUS_SUCCESS;
1237}
1238
1239static enum ggml_status ggml_backend_meta_buffer_init_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor) {
1240 GGML_ASSERT(ggml_backend_buffer_is_meta(buffer))if (!(ggml_backend_buffer_is_meta(buffer))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1240, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(buffer)"
)
;
1241 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) buffer->context;
1242 buf_ctx->stc_compute_index = buf_ctx->stc_compute_index_next;
1243 return ggml_backend_meta_buffer_init_tensor_impl(buf_ctx->get_simple_tensor_container(tensor), tensor);
1244}
1245
1246static void ggml_backend_meta_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, const void * data, size_t offset, size_t size) {
1247 const size_t n_bufs = ggml_backend_meta_buffer_n_bufs(buffer);
1248 GGML_ASSERT(ggml_is_contiguous(tensor))if (!(ggml_is_contiguous(tensor))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1248, "GGML_ASSERT(%s) failed", "ggml_is_contiguous(tensor)"
)
;
1249
1250 const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(tensor, /*assume_sync =*/ false);
1251
1252 if (split_state.n_segments != 1 || split_state.nr[0] != 1) {
1253 GGML_ASSERT(split_state.axis >= 0 && split_state.axis < GGML_MAX_DIMS)if (!(split_state.axis >= 0 && split_state.axis <
4)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1253, "GGML_ASSERT(%s) failed", "split_state.axis >= 0 && split_state.axis < GGML_MAX_DIMS"
)
;
1254 GGML_ASSERT(split_state.nr[0] != 0)if (!(split_state.nr[0] != 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1254, "GGML_ASSERT(%s) failed", "split_state.nr[0] != 0")
;
1255 GGML_ASSERT(tensor->ne[3] == 1)if (!(tensor->ne[3] == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1255, "GGML_ASSERT(%s) failed", "tensor->ne[3] == 1")
;
1256
1257 size_t offset_data = 0;
1258 std::vector<size_t> simple_offsets(n_bufs, 0);
1259 if (split_state.axis == GGML_BACKEND_SPLIT_AXIS_0) {
1260 GGML_ASSERT(tensor->ne[2] == 1)if (!(tensor->ne[2] == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1260, "GGML_ASSERT(%s) failed", "tensor->ne[2] == 1")
;
1261
1262 const size_t row_stride = tensor->nb[1];
1263 GGML_ASSERT(offset % row_stride == 0)if (!(offset % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1263, "GGML_ASSERT(%s) failed", "offset % row_stride == 0")
;
1264 GGML_ASSERT(size % row_stride == 0)if (!(size % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1264, "GGML_ASSERT(%s) failed", "size % row_stride == 0")
;
1265 const int64_t row_start = offset / row_stride;
1266 const int64_t row_count = size / row_stride;
1267 GGML_ASSERT(row_start + row_count <= tensor->ne[1])if (!(row_start + row_count <= tensor->ne[1])) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1267, "GGML_ASSERT(%s) failed", "row_start + row_count <= tensor->ne[1]"
)
;
1268
1269 const int64_t blck_size = ggml_blck_size(tensor->type);
1270 for (size_t s = 0; s < split_state.n_segments; s++) {
1271 for (size_t r = 0; r < split_state.nr[s]; r++) {
1272 for (size_t j = 0; j < n_bufs; j++) {
1273 ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1274 GGML_ASSERT(split_state.ne[s*n_bufs + j] % blck_size == 0)if (!(split_state.ne[s*n_bufs + j] % blck_size == 0)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1274, "GGML_ASSERT(%s) failed", "split_state.ne[s*n_bufs + j] % blck_size == 0"
)
;
1275 const size_t nbytes = split_state.ne[s*n_bufs + j]/blck_size * tensor->nb[0];
1276 ggml_backend_tensor_set_2d(simple_tensor, (const char *) data + offset_data,
1277 simple_offsets[j] + row_start * simple_tensor->nb[1], nbytes,
1278 row_count, simple_tensor->nb[1], tensor->nb[1]);
1279 offset_data += nbytes;
1280 simple_offsets[j] += nbytes;
1281 }
1282 }
1283 }
1284 GGML_ASSERT(offset_data*row_count == size)if (!(offset_data*row_count == size)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1284, "GGML_ASSERT(%s) failed", "offset_data*row_count == size"
)
;
1285 return;
1286 }
1287 GGML_ASSERT(split_state.axis == GGML_BACKEND_SPLIT_AXIS_1)if (!(split_state.axis == GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1287, "GGML_ASSERT(%s) failed", "split_state.axis == GGML_BACKEND_SPLIT_AXIS_1"
)
;
1288
1289 const size_t row_stride = tensor->nb[2];
1290 GGML_ASSERT(offset % row_stride == 0)if (!(offset % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1290, "GGML_ASSERT(%s) failed", "offset % row_stride == 0")
;
1291 GGML_ASSERT(size % row_stride == 0)if (!(size % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1291, "GGML_ASSERT(%s) failed", "size % row_stride == 0")
;
1292 const int64_t row_start = offset / row_stride;
1293 const int64_t row_count = size / row_stride;
1294 GGML_ASSERT(row_start + row_count <= tensor->ne[2])if (!(row_start + row_count <= tensor->ne[2])) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1294, "GGML_ASSERT(%s) failed", "row_start + row_count <= tensor->ne[2]"
)
;
1295
1296 for (size_t s = 0; s < split_state.n_segments; s++) {
1297 for (size_t r = 0; r < split_state.nr[s]; r++) {
1298 for (size_t j = 0; j < n_bufs; j++) {
1299 ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1300 const size_t nbytes = split_state.ne[s*n_bufs + j] * tensor->nb[1];
1301 ggml_backend_tensor_set_2d(simple_tensor, (const char *) data + offset_data,
1302 simple_offsets[j] + row_start * simple_tensor->nb[2], nbytes,
1303 row_count, simple_tensor->nb[2], tensor->nb[2]);
1304 offset_data += nbytes;
1305 simple_offsets[j] += nbytes;
1306 }
1307 }
1308 }
1309 GGML_ASSERT(offset_data*row_count == size)if (!(offset_data*row_count == size)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1309, "GGML_ASSERT(%s) failed", "offset_data*row_count == size"
)
;
1310 return;
1311 }
1312
1313 switch (split_state.axis) {
1314 case GGML_BACKEND_SPLIT_AXIS_0:
1315 case GGML_BACKEND_SPLIT_AXIS_1:
1316 case GGML_BACKEND_SPLIT_AXIS_2: {
1317 // Exploit that tensors are contiguous to splice it with simple tensors as "chunks".
1318 const size_t chunk_size_full = tensor->nb[split_state.axis + 1];
1319 GGML_ASSERT(offset % chunk_size_full == 0)if (!(offset % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1319, "GGML_ASSERT(%s) failed", "offset % chunk_size_full == 0"
)
;
1320 GGML_ASSERT(size % chunk_size_full == 0)if (!(size % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1320, "GGML_ASSERT(%s) failed", "size % chunk_size_full == 0"
)
;
1321 const int64_t i_start = offset /chunk_size_full;
1322 const int64_t i_stop = (offset + size)/chunk_size_full;
1323 size_t offset_j = 0;
1324 for (size_t j = 0; j < n_bufs; j++) {
1325 ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1326 const size_t chunk_size_j = simple_tensor->nb[split_state.axis + 1];
1327 if (chunk_size_j == 0) {
1328 continue;
1329 }
1330 const size_t simple_offset = i_start * chunk_size_j;
1331 ggml_backend_tensor_set_2d(simple_tensor, (const char *) data + offset_j, simple_offset, chunk_size_j, i_stop - i_start, chunk_size_j, chunk_size_full);
1332 offset_j += chunk_size_j;
1333 }
1334 GGML_ASSERT(offset_j == chunk_size_full)if (!(offset_j == chunk_size_full)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1334, "GGML_ASSERT(%s) failed", "offset_j == chunk_size_full"
)
;
1335 } break;
1336 case GGML_BACKEND_SPLIT_AXIS_MIRRORED: {
1337 for (size_t j = 0; j < n_bufs; j++) {
1338 ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1339 ggml_backend_tensor_set(simple_tensor, data, offset, size);
1340 }
1341 } break;
1342 case GGML_BACKEND_SPLIT_AXIS_PARTIAL: {
1343 GGML_ASSERT(tensor->type == GGML_TYPE_F32)if (!(tensor->type == GGML_TYPE_F32)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1343, "GGML_ASSERT(%s) failed", "tensor->type == GGML_TYPE_F32"
)
;
1344 const int64_t ne = ggml_nelements(tensor);
1345 std::vector<float> tmp;
1346 tmp.reserve(ne);
1347 for (int64_t i = 0; i < ne; i++) {
1348 tmp.push_back(((const float *) data)[i] / n_bufs);
1349 }
1350 for (size_t j = 0; j < n_bufs; j++) {
1351 ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1352 ggml_backend_tensor_set(simple_tensor, tmp.data(), offset, size);
1353 }
1354 } break;
1355 default: {
1356 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1356, "fatal error")
;
1357 }
1358 }
1359}
1360
1361static void ggml_backend_meta_buffer_get_tensor(ggml_backend_buffer_t buffer, const ggml_tensor * tensor, void * data, size_t offset, size_t size) {
1362 const size_t n_bufs = ggml_backend_meta_buffer_n_bufs(buffer);
1363 GGML_ASSERT(ggml_is_contiguous(tensor))if (!(ggml_is_contiguous(tensor))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1363, "GGML_ASSERT(%s) failed", "ggml_is_contiguous(tensor)"
)
;
1364
1365 const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(tensor, /*assume_sync =*/ false);
1366
1367 if (split_state.n_segments != 1 || split_state.nr[0] != 1) {
1368 GGML_ASSERT(split_state.axis >= 0 && split_state.axis < GGML_MAX_DIMS)if (!(split_state.axis >= 0 && split_state.axis <
4)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1368, "GGML_ASSERT(%s) failed", "split_state.axis >= 0 && split_state.axis < GGML_MAX_DIMS"
)
;
1369 GGML_ASSERT(split_state.nr[0] != 0)if (!(split_state.nr[0] != 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1369, "GGML_ASSERT(%s) failed", "split_state.nr[0] != 0")
;
1370 GGML_ASSERT(tensor->ne[3] == 1)if (!(tensor->ne[3] == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1370, "GGML_ASSERT(%s) failed", "tensor->ne[3] == 1")
;
1371
1372 size_t offset_data = 0;
1373 std::vector<size_t> simple_offsets(n_bufs, 0);
1374 if (split_state.axis == GGML_BACKEND_SPLIT_AXIS_0) {
1375 GGML_ASSERT(tensor->ne[2] == 1)if (!(tensor->ne[2] == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1375, "GGML_ASSERT(%s) failed", "tensor->ne[2] == 1")
;
1376
1377 const size_t row_stride = tensor->nb[1];
1378 GGML_ASSERT(offset % row_stride == 0)if (!(offset % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1378, "GGML_ASSERT(%s) failed", "offset % row_stride == 0")
;
1379 GGML_ASSERT(size % row_stride == 0)if (!(size % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1379, "GGML_ASSERT(%s) failed", "size % row_stride == 0")
;
1380 const int64_t row_start = offset / row_stride;
1381 const int64_t row_count = size / row_stride;
1382 GGML_ASSERT(row_start + row_count <= tensor->ne[1])if (!(row_start + row_count <= tensor->ne[1])) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1382, "GGML_ASSERT(%s) failed", "row_start + row_count <= tensor->ne[1]"
)
;
1383
1384 const int64_t blck_size = ggml_blck_size(tensor->type);
1385 for (size_t s = 0; s < split_state.n_segments; s++) {
1386 for (size_t r = 0; r < split_state.nr[s]; r++) {
1387 for (size_t j = 0; j < n_bufs; j++) {
1388 const ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1389 GGML_ASSERT(split_state.ne[s*n_bufs + j] % blck_size == 0)if (!(split_state.ne[s*n_bufs + j] % blck_size == 0)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1389, "GGML_ASSERT(%s) failed", "split_state.ne[s*n_bufs + j] % blck_size == 0"
)
;
1390 const size_t nbytes = split_state.ne[s*n_bufs + j]/blck_size * tensor->nb[0];
1391 ggml_backend_tensor_get_2d(simple_tensor, (char *) data + offset_data,
1392 simple_offsets[j] + row_start * simple_tensor->nb[1], nbytes,
1393 row_count, simple_tensor->nb[1], tensor->nb[1]);
1394 offset_data += nbytes;
1395 simple_offsets[j] += nbytes;
1396 }
1397 }
1398 }
1399 GGML_ASSERT(offset_data*row_count == size)if (!(offset_data*row_count == size)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1399, "GGML_ASSERT(%s) failed", "offset_data*row_count == size"
)
;
1400 return;
1401 }
1402 GGML_ASSERT(split_state.axis == GGML_BACKEND_SPLIT_AXIS_1)if (!(split_state.axis == GGML_BACKEND_SPLIT_AXIS_1)) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1402, "GGML_ASSERT(%s) failed", "split_state.axis == GGML_BACKEND_SPLIT_AXIS_1"
)
;
1403
1404 const size_t row_stride = tensor->nb[2];
1405 GGML_ASSERT(offset % row_stride == 0)if (!(offset % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1405, "GGML_ASSERT(%s) failed", "offset % row_stride == 0")
;
1406 GGML_ASSERT(size % row_stride == 0)if (!(size % row_stride == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1406, "GGML_ASSERT(%s) failed", "size % row_stride == 0")
;
1407 const int64_t row_start = offset / row_stride;
1408 const int64_t row_count = size / row_stride;
1409 GGML_ASSERT(row_start + row_count <= tensor->ne[2])if (!(row_start + row_count <= tensor->ne[2])) ggml_abort
("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1409, "GGML_ASSERT(%s) failed", "row_start + row_count <= tensor->ne[2]"
)
;
1410
1411 for (size_t s = 0; s < split_state.n_segments; s++) {
1412 for (size_t r = 0; r < split_state.nr[s]; r++) {
1413 for (size_t j = 0; j < n_bufs; j++) {
1414 const ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1415 const size_t nbytes = split_state.ne[s*n_bufs + j] * tensor->nb[1];
1416 ggml_backend_tensor_get_2d(simple_tensor, (char *) data + offset_data,
1417 simple_offsets[j] + row_start * simple_tensor->nb[2], nbytes,
1418 row_count, simple_tensor->nb[2], tensor->nb[2]);
1419 offset_data += nbytes;
1420 simple_offsets[j] += nbytes;
1421 }
1422 }
1423 }
1424 GGML_ASSERT(offset_data*row_count == size)if (!(offset_data*row_count == size)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1424, "GGML_ASSERT(%s) failed", "offset_data*row_count == size"
)
;
1425 return;
1426 }
1427
1428 switch (split_state.axis) {
1429 case GGML_BACKEND_SPLIT_AXIS_0:
1430 case GGML_BACKEND_SPLIT_AXIS_1:
1431 case GGML_BACKEND_SPLIT_AXIS_2: {
1432 // Exploit that tensors are contiguous to splice it with simple tensors as "chunks".
1433 const size_t chunk_size_full = tensor->nb[split_state.axis + 1];
1434 GGML_ASSERT(offset % chunk_size_full == 0)if (!(offset % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1434, "GGML_ASSERT(%s) failed", "offset % chunk_size_full == 0"
)
;
1435 GGML_ASSERT(size % chunk_size_full == 0)if (!(size % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1435, "GGML_ASSERT(%s) failed", "size % chunk_size_full == 0"
)
;
1436 const int64_t i_start = offset /chunk_size_full;
1437 const int64_t i_stop = (offset + size)/chunk_size_full;
1438 size_t offset_j = 0;
1439 for (size_t j = 0; j < n_bufs; j++){
1440 const ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1441 const size_t chunk_size_j = simple_tensor->nb[split_state.axis + 1];
1442 if (chunk_size_j == 0) {
1443 continue;
1444 }
1445 const size_t simple_offset = i_start * chunk_size_j;
1446 ggml_backend_tensor_get_2d(simple_tensor, (char *) data + offset_j, simple_offset, chunk_size_j, i_stop - i_start, chunk_size_j, chunk_size_full);
1447 offset_j += chunk_size_j;
1448 }
1449 GGML_ASSERT(offset_j == chunk_size_full)if (!(offset_j == chunk_size_full)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1449, "GGML_ASSERT(%s) failed", "offset_j == chunk_size_full"
)
;
1450 } break;
1451 case GGML_BACKEND_SPLIT_AXIS_MIRRORED: {
1452 // TODO other simple backend may be better
1453 const ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, 0);
1454 ggml_backend_tensor_get(simple_tensor, data, offset, size);
1455 } break;
1456 default: {
1457 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1457, "fatal error")
;
1458 }
1459 }
1460}
1461
1462static void ggml_backend_meta_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
1463 const size_t n_buffers = ggml_backend_meta_buffer_n_bufs(buffer);
1464 for (size_t i = 0; i < n_buffers; i++) {
1465 ggml_backend_buffer_clear(ggml_backend_meta_buffer_simple_buffer(buffer, i), value);
1466 }
1467}
1468
1469static void ggml_backend_meta_buffer_reset(ggml_backend_buffer_t buffer) {
1470 GGML_ASSERT(ggml_backend_buffer_is_meta(buffer))if (!(ggml_backend_buffer_is_meta(buffer))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1470, "GGML_ASSERT(%s) failed", "ggml_backend_buffer_is_meta(buffer)"
)
;
1471 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) buffer->context;
1472 for (size_t i = 0; i < buf_ctx->bufs.size(); i++) {
1473 ggml_backend_buffer_reset(ggml_backend_meta_buffer_simple_buffer(buffer, i));
1474 }
1475}
1476
1477static const ggml_backend_buffer_i ggml_backend_meta_buffer_iface = {
1478 /* .free_buffer = */ ggml_backend_meta_buffer_free_buffer,
1479 /* .get_base = */ ggml_backend_meta_buffer_get_base,
1480 /* .init_tensor = */ ggml_backend_meta_buffer_init_tensor,
1481 /* .memset_tensor = */ nullptr, // TODO implement
1482 /* .set_tensor = */ ggml_backend_meta_buffer_set_tensor,
1483 /* .get_tensor = */ ggml_backend_meta_buffer_get_tensor,
1484 /* .set_tensor_2d = */ nullptr,
1485 /* .get_tensor_2d = */ nullptr,
1486 /* .cpy_tensor = */ nullptr,
1487 /* .clear = */ ggml_backend_meta_buffer_clear,
1488 /* .reset = */ ggml_backend_meta_buffer_reset,
1489};
1490
1491bool ggml_backend_buffer_is_meta(ggml_backend_buffer_t buf) {
1492 return buf != nullptr && buf->iface.free_buffer == ggml_backend_meta_buffer_iface.free_buffer;
1493}
1494
1495static ggml_backend_buffer_t ggml_backend_meta_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) {
1496 const size_t n_simple_bufts = ggml_backend_meta_buft_n_bufts(buft);
1497
1498 const ggml_init_params params = {
1499 /*.mem_size =*/ 1024*1024*ggml_tensor_overhead(), // FIXME
1500 /*.mem_buffer =*/ nullptr,
1501 /*.no_alloc =*/ true,
1502 };
1503 ggml_backend_meta_simple_tensor_container stc_static;
1504 ggml_backend_meta_simple_tensor_container stc_compute_0(params, n_simple_bufts);
1505 ggml_backend_meta_simple_tensor_container stc_compute_1(params, n_simple_bufts);
1506
1507 size_t max_size = 0;
1508 std::vector<ggml_backend_buffer_t> bufs;
1509 bufs.reserve(n_simple_bufts);
1510 for (size_t i = 0; i < n_simple_bufts; i++) {
1511 bufs.push_back(ggml_backend_buft_alloc_buffer(ggml_backend_meta_buft_simple_buft(buft, i), size));
1512 GGML_ASSERT(bufs.back() != nullptr)if (!(bufs.back() != nullptr)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1512, "GGML_ASSERT(%s) failed", "bufs.back() != nullptr")
;
1513 max_size = std::max(max_size, ggml_backend_buffer_get_size(bufs.back()));
1514 }
1515 ggml_backend_meta_buffer_context * buf_ctx = new ggml_backend_meta_buffer_context(stc_static, stc_compute_0, stc_compute_1, bufs);
1516
1517 return ggml_backend_buffer_init(buft, ggml_backend_meta_buffer_iface, buf_ctx, max_size);
1518}
1519
1520struct ggml_backend_buffer * ggml_backend_meta_alloc_ctx_tensors_from_buft(struct ggml_context * ctx, ggml_backend_buffer_type_t buft) {
1521 const size_t n_simple_bufts = ggml_backend_meta_buft_n_bufts(buft);
1522
1523 constexpr size_t compute_headroom = 16; // Maximum number of views per statically allocated tensor that can be created between evals.
1524 const ggml_init_params params_static = {
1525 /*.mem_size =*/ ggml_get_mem_size(ctx),
1526 /*.mem_buffer =*/ nullptr,
1527 /*.no_alloc =*/ true,
1528 };
1529 const ggml_init_params params_compute = {
1530 /*.mem_size =*/ compute_headroom*ggml_get_mem_size(ctx),
1531 /*.mem_buffer =*/ nullptr,
1532 /*.no_alloc =*/ true,
1533 };
1534 ggml_backend_meta_simple_tensor_container stc_static (params_static, n_simple_bufts);
1535 ggml_backend_meta_simple_tensor_container stc_compute_0(params_compute, n_simple_bufts);
1536 ggml_backend_meta_simple_tensor_container stc_compute_1(params_compute, n_simple_bufts);
1537
1538 std::vector<ggml_backend_buffer_t> bufs(n_simple_bufts, nullptr);
1539 ggml_backend_meta_buffer_context * meta_buf_ctx = new ggml_backend_meta_buffer_context(stc_static, stc_compute_0, stc_compute_1, bufs);
1540
1541 ggml_backend_buffer_t meta_buf = ggml_backend_buffer_init(buft, ggml_backend_meta_buffer_iface, meta_buf_ctx, 0);
1542 for (ggml_tensor * t = ggml_get_first_tensor(ctx); t != nullptr; t = ggml_get_next_tensor(ctx, t)) {
1543 t->buffer = meta_buf;
1544 ggml_backend_meta_buffer_init_tensor_impl(meta_buf_ctx->stc_static, t);
1545 t->data = (void *) 0x2000000000000000; // FIXME
1546 }
1547 for (size_t i = 0; i < n_simple_bufts; i++) {
1548 ggml_context * ctx = meta_buf_ctx->stc_static.ctxs[i].get();
1549 ggml_backend_buffer_type_t simple_buft = ggml_backend_meta_buft_simple_buft(buft, i);
1550
1551 // If a ggml_context only has zero-sized tensors, ggml_backend_alloc_ctx_tensors_from_buft returns NULL.
1552 // For those edge cases, allocate a dummy buffer instead.
1553 bool any_nonzero_slice = false;
1554 for (ggml_tensor * t = ggml_get_first_tensor(ctx); t != nullptr; t = ggml_get_next_tensor(ctx, t)) {
1555 if (ggml_nelements(t) != 0) {
1556 any_nonzero_slice = true;
1557 break;
1558 }
1559 }
1560 if (any_nonzero_slice) {
1561 meta_buf_ctx->bufs[i].reset(ggml_backend_alloc_ctx_tensors_from_buft(ctx, simple_buft));
1562 } else {
1563 meta_buf_ctx->bufs[i].reset(ggml_backend_buft_alloc_buffer(simple_buft, 0));
1564 for (ggml_tensor * t = ggml_get_first_tensor(ctx); t != nullptr; t = ggml_get_next_tensor(ctx, t)) {
1565 t->buffer = meta_buf_ctx->bufs[i].get();
1566 }
1567 }
1568 GGML_ASSERT(meta_buf_ctx->bufs[i])if (!(meta_buf_ctx->bufs[i])) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1568, "GGML_ASSERT(%s) failed", "meta_buf_ctx->bufs[i]")
;
1569 meta_buf->size = std::max(meta_buf->size, ggml_backend_buffer_get_size(meta_buf_ctx->bufs[i].get()));
1570 }
1571 return meta_buf;
1572}
1573
1574//
1575// meta backend
1576//
1577
1578static ggml_guid_t ggml_backend_meta_guid() {
1579 static ggml_guid guid = {0xf1, 0x0e, 0x34, 0xcf, 0x9c, 0x6f, 0x43, 0xcb, 0x96, 0x92, 0xbe, 0x8e, 0xbb, 0x71, 0x3f, 0xda};
1580 return &guid;
1581}
1582
1583struct ggml_backend_meta_context {
1584 struct cgraph_config {
1585 ggml_cgraph * cgraph_main = nullptr;
1586 int offset = 0; // Node offset vs. original graph
1587
1588 std::vector<ggml_cgraph *> cgraphs_aux;
1589 };
1590 struct backend_config {
1591 ggml_backend_t backend;
1592
1593 std::vector<cgraph_config> cgraphs;
1594 std::vector<ggml_tensor *> nodes;
1595 std::vector<ggml_backend_buffer_ptr> bufs;
1596
1597 backend_config(ggml_backend_t backend, const size_t n_reduce_steps) : backend(backend) {
1598 bufs.resize(n_reduce_steps);
1599 }
1600 };
1601 std::string name;
1602 std::vector<backend_config> backend_configs;
1603 ggml_context_ptr ctx;
1604 std::vector<ggml_cgraph *> cgraphs_aux;
1605 std::vector<ggml_tensor *> nodes_aux;
1606 size_t n_reduce_steps;
1607 int max_nnodes = 0;
1608 size_t max_tmp_size = 0;
1609 size_t max_subgraphs = 0;
1610 size_t n_subgraphs = 0;
1611 uint64_t uid = 0;
1612
1613 void * comm_ctx = nullptr;
1614 ggml_backend_comm_allreduce_tensor_t comm_allreduce = nullptr;
1615
1616 ggml_backend_meta_context(ggml_backend_dev_t meta_dev, const char * params) {
1617 const size_t n_devs = ggml_backend_meta_dev_n_devs(meta_dev);
1618 n_reduce_steps = std::ceil(std::log2(n_devs));
1619 name = "Meta(";
1620 std::vector<ggml_backend_t> simple_backends;
1621 backend_configs.reserve(n_devs);
1622 simple_backends.reserve(n_devs);
1623 for (size_t i = 0; i < n_devs; i++) {
1624 ggml_backend_dev_t simple_dev = ggml_backend_meta_dev_simple_dev(meta_dev, i);
1625 if (i > 0) {
1626 name += ",";
1627 }
1628 name += ggml_backend_dev_name(simple_dev);
1629 simple_backends.push_back(ggml_backend_dev_init(simple_dev, params));
1630 backend_configs.emplace_back(simple_backends.back(), n_reduce_steps);
1631 }
1632 name += ")";
1633
1634 if (n_devs > 1) {
1635 ggml_backend_comm_init_t comm_init = (ggml_backend_comm_init_t) ggml_backend_reg_get_proc_address(
1636 ggml_backend_dev_backend_reg(ggml_backend_get_device(simple_backends[0])), "ggml_backend_comm_init");
1637 if (comm_init != nullptr) {
1638 comm_ctx = comm_init(simple_backends.data(), simple_backends.size());
1639 }
1640 }
1641 if (comm_ctx != nullptr) {
1642 comm_allreduce = (ggml_backend_comm_allreduce_tensor_t)
1643 ggml_backend_reg_get_proc_address(ggml_backend_dev_backend_reg(
1644 ggml_backend_get_device(simple_backends[0])), "ggml_backend_comm_allreduce_tensor");
1645 GGML_ASSERT(comm_allreduce != nullptr)if (!(comm_allreduce != nullptr)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1645, "GGML_ASSERT(%s) failed", "comm_allreduce != nullptr"
)
;
1646 }
1647 }
1648
1649 ~ggml_backend_meta_context() {
1650 if (comm_ctx != nullptr) {
1651 ggml_backend_comm_free_t comm_free = (ggml_backend_comm_free_t) ggml_backend_reg_get_proc_address(
1652 ggml_backend_dev_backend_reg(ggml_backend_get_device(backend_configs[0].backend)), "ggml_backend_comm_free");
1653 GGML_ASSERT(comm_free != nullptr)if (!(comm_free != nullptr)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1653, "GGML_ASSERT(%s) failed", "comm_free != nullptr")
;
1654 comm_free(comm_ctx);
1655 }
1656 for (auto & bc : backend_configs) {
1657 ggml_backend_free(bc.backend);
1658 }
1659 }
1660};
1661
1662static const char * ggml_backend_meta_get_name(ggml_backend_t backend) {
1663 GGML_ASSERT(ggml_backend_is_meta(backend))if (!(ggml_backend_is_meta(backend))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1663, "GGML_ASSERT(%s) failed", "ggml_backend_is_meta(backend)"
)
;
1664 const ggml_backend_meta_context * backend_ctx = (const ggml_backend_meta_context *) backend->context;
1665 return backend_ctx->name.c_str();
1666}
1667
1668static void ggml_backend_meta_free(ggml_backend_t backend) {
1669 GGML_ASSERT(ggml_backend_is_meta(backend))if (!(ggml_backend_is_meta(backend))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1669, "GGML_ASSERT(%s) failed", "ggml_backend_is_meta(backend)"
)
;
1670 ggml_backend_meta_context * backend_ctx = (ggml_backend_meta_context *) backend->context;
1671 delete backend_ctx;
1672 delete backend;
1673}
1674
1675static void ggml_backend_meta_set_tensor_async(ggml_backend_t backend, ggml_tensor * tensor, const void * data, size_t offset, size_t size) {
1676 const size_t n_backends = ggml_backend_meta_n_backends(backend);
1677 GGML_ASSERT(offset == 0)if (!(offset == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1677, "GGML_ASSERT(%s) failed", "offset == 0")
;
1678 GGML_ASSERT(ggml_is_contiguous(tensor))if (!(ggml_is_contiguous(tensor))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1678, "GGML_ASSERT(%s) failed", "ggml_is_contiguous(tensor)"
)
;
1679
1680 const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(tensor, /*assume_sync =*/ false);
1681 GGML_ASSERT(split_state.n_segments == 1)if (!(split_state.n_segments == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1681, "GGML_ASSERT(%s) failed", "split_state.n_segments == 1"
)
;
1682 GGML_ASSERT(split_state.nr[0] == 1)if (!(split_state.nr[0] == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1682, "GGML_ASSERT(%s) failed", "split_state.nr[0] == 1")
;
1683
1684 switch (split_state.axis) {
1685 case GGML_BACKEND_SPLIT_AXIS_0:
1686 case GGML_BACKEND_SPLIT_AXIS_1:
1687 case GGML_BACKEND_SPLIT_AXIS_2: {
1688 // Exploit that tensors are contiguous to splice it with simple tensors as "chunks".
1689 const size_t chunk_size_full = tensor->nb[split_state.axis + 1];
1690 GGML_ASSERT(offset % chunk_size_full == 0)if (!(offset % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1690, "GGML_ASSERT(%s) failed", "offset % chunk_size_full == 0"
)
;
1691 GGML_ASSERT(size % chunk_size_full == 0)if (!(size % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1691, "GGML_ASSERT(%s) failed", "size % chunk_size_full == 0"
)
;
1692 const int64_t i_start = offset /chunk_size_full;
1693 const int64_t i_stop = (offset + size)/chunk_size_full;
1694 size_t offset_j = 0;
1695 for (size_t j = 0; j < n_backends; j++){
1696 ggml_backend_t simple_backend = ggml_backend_meta_simple_backend(backend, j);
1697 ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1698 const size_t chunk_size_j = simple_tensor->nb[split_state.axis + 1];
1699 if (chunk_size_j == 0) {
1700 continue;
1701 }
1702 ggml_backend_tensor_set_2d_async(simple_backend, simple_tensor, (const char *) data + offset_j, offset, chunk_size_j,
1703 i_stop - i_start, chunk_size_j, chunk_size_full);
1704 offset_j += chunk_size_j;
1705 }
1706 GGML_ASSERT(offset_j == chunk_size_full)if (!(offset_j == chunk_size_full)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1706, "GGML_ASSERT(%s) failed", "offset_j == chunk_size_full"
)
;
1707 } break;
1708 case GGML_BACKEND_SPLIT_AXIS_MIRRORED: {
1709 for (size_t j = 0; j < n_backends; j++) {
1710 ggml_backend_tensor_set_async(
1711 ggml_backend_meta_simple_backend(backend, j), ggml_backend_meta_buffer_simple_tensor(tensor, j), data, offset, size);
1712 }
1713 } break;
1714 default: {
1715 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1715, "fatal error")
;
1716 }
1717 }
1718}
1719
1720static void ggml_backend_meta_get_tensor_async(ggml_backend_t backend, const ggml_tensor * tensor, void * data, size_t offset, size_t size) {
1721 const size_t n_backends = ggml_backend_meta_n_backends(backend);
1722 GGML_ASSERT(offset == 0)if (!(offset == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1722, "GGML_ASSERT(%s) failed", "offset == 0")
;
1723 GGML_ASSERT(ggml_is_contiguous(tensor))if (!(ggml_is_contiguous(tensor))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1723, "GGML_ASSERT(%s) failed", "ggml_is_contiguous(tensor)"
)
;
1724
1725 const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(tensor, /*assume_sync =*/ false);
1726 GGML_ASSERT(split_state.n_segments == 1)if (!(split_state.n_segments == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1726, "GGML_ASSERT(%s) failed", "split_state.n_segments == 1"
)
;
1727 GGML_ASSERT(split_state.nr[0] == 1)if (!(split_state.nr[0] == 1)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1727, "GGML_ASSERT(%s) failed", "split_state.nr[0] == 1")
;
1728
1729 switch (split_state.axis) {
1730 case GGML_BACKEND_SPLIT_AXIS_0:
1731 case GGML_BACKEND_SPLIT_AXIS_1:
1732 case GGML_BACKEND_SPLIT_AXIS_2: {
1733 // Exploit that tensors are contiguous to splice it with simple tensors as "chunks".
1734 const size_t chunk_size_full = tensor->nb[split_state.axis + 1];
1735 GGML_ASSERT(offset % chunk_size_full == 0)if (!(offset % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1735, "GGML_ASSERT(%s) failed", "offset % chunk_size_full == 0"
)
;
1736 GGML_ASSERT(size % chunk_size_full == 0)if (!(size % chunk_size_full == 0)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1736, "GGML_ASSERT(%s) failed", "size % chunk_size_full == 0"
)
;
1737 const int64_t i_start = offset /chunk_size_full;
1738 const int64_t i_stop = (offset + size)/chunk_size_full;
1739 size_t offset_j = 0;
1740 for (size_t j = 0; j < n_backends; j++){
1741 ggml_backend_t simple_backend = ggml_backend_meta_simple_backend(backend, j);
1742 const ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, j);
1743 const size_t chunk_size_j = simple_tensor->nb[split_state.axis + 1];
1744 if (chunk_size_j == 0) {
1745 continue;
1746 }
1747 ggml_backend_tensor_get_2d_async(simple_backend, simple_tensor, (char *) data + offset_j, offset, chunk_size_j,
1748 i_stop - i_start, chunk_size_j, chunk_size_full);
1749 offset_j += chunk_size_j;
1750 }
1751 GGML_ASSERT(offset_j == chunk_size_full)if (!(offset_j == chunk_size_full)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1751, "GGML_ASSERT(%s) failed", "offset_j == chunk_size_full"
)
;
1752 } break;
1753 case GGML_BACKEND_SPLIT_AXIS_MIRRORED: {
1754 // TODO other simple backend may be better
1755 ggml_backend_t simple_backend = ggml_backend_meta_simple_backend(backend, 0);
1756 const ggml_tensor * simple_tensor = ggml_backend_meta_buffer_simple_tensor(tensor, 0);
1757 ggml_backend_tensor_get_async(simple_backend, simple_tensor, data, offset, size);
1758 } break;
1759 default: {
1760 GGML_ABORT("fatal error")ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1760, "fatal error")
;
1761 }
1762 }
1763}
1764
1765static void ggml_backend_meta_synchronize(ggml_backend_t backend) {
1766 const size_t n_backends = ggml_backend_meta_n_backends(backend);
1767 for (size_t i = 0; i < n_backends; i++) {
1768 ggml_backend_synchronize(ggml_backend_meta_simple_backend(backend, i));
1769 }
1770}
1771
1772static enum ggml_status ggml_backend_meta_graph_compute(ggml_backend_t backend, struct ggml_cgraph * cgraph) {
1773 GGML_ASSERT(cgraph->grads == nullptr)if (!(cgraph->grads == nullptr)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1773, "GGML_ASSERT(%s) failed", "cgraph->grads == nullptr"
)
;
1
Assuming the condition is true
2
Taking false branch
1774 const size_t n_backends = ggml_backend_meta_n_backends(backend);
1775 ggml_backend_meta_context * backend_ctx = (ggml_backend_meta_context *) backend->context;
1776
1777 // If the previous cgraph had a defined UID it can be used to skip rebuilding the subgraphs per simple backend.
1778 const bool needs_rebuild = (cgraph->uid == 0) || (cgraph->uid != backend_ctx->uid);
3
Assuming field 'uid' is not equal to 0
4
Assuming 'cgraph->uid' is not equal to 'backend_ctx->uid'
1779
1780 bool max_nnodes_raised = false;
1781 if (cgraph->n_nodes > backend_ctx->max_nnodes) {
5
Assuming field 'n_nodes' is <= field 'max_nnodes'
6
Taking false branch
1782 for (size_t j = 0; j < n_backends; j++) {
1783 auto & bcj = backend_ctx->backend_configs[j];
1784 bcj.nodes.resize(cgraph->n_nodes);
1785 bcj.cgraphs.resize(cgraph->n_nodes);
1786 }
1787 backend_ctx->max_nnodes = cgraph->n_nodes;
1788 max_nnodes_raised = true;
1789 assert(needs_rebuild)(static_cast <bool> (needs_rebuild) ? void (0) : __assert_fail
("needs_rebuild", __builtin_FILE (), __builtin_LINE (), __extension__
__PRETTY_FUNCTION__))
;
1790 }
1791
1792 if (needs_rebuild
6.1
'needs_rebuild' is true
) {
7
Taking true branch
1793 std::set<ggml_backend_buffer_t> used_buffers;
1794 for (int i = 0; i < cgraph->n_leafs; i++) {
8
Assuming 'i' is >= field 'n_leafs'
9
Loop condition is false. Execution continues on line 1799
1795 if (ggml_backend_buffer_is_meta(cgraph->leafs[i]->buffer)) {
1796 used_buffers.emplace(cgraph->leafs[i]->buffer);
1797 }
1798 }
1799 for (int i = 0; i < cgraph->n_nodes; i++) {
10
Assuming 'i' is < field 'n_nodes'
11
Loop condition is true. Entering loop body
13
Assuming 'i' is >= field 'n_nodes'
14
Loop condition is false. Execution continues on line 1804
1800 if (ggml_backend_buffer_is_meta(cgraph->nodes[i]->buffer)) {
12
Taking true branch
1801 used_buffers.emplace(cgraph->nodes[i]->buffer);
1802 }
1803 }
1804 for (ggml_backend_buffer_t buf : used_buffers) {
1805 ggml_backend_meta_buffer_context * buf_ctx = (ggml_backend_meta_buffer_context *) buf->context;
1806 buf_ctx->stc_compute_index_next = buf_ctx->stc_compute_index ^ 1;
1807 ggml_backend_meta_simple_tensor_container & stc = buf_ctx->stc_compute[buf_ctx->stc_compute_index_next];
1808 for (ggml_context_ptr & ctx : stc.ctxs) {
1809 ggml_reset(ctx.get());
1810 }
1811 stc.simple_tensors.clear();
1812 }
1813 size_t n_subgraphs = 0;
1814 size_t max_tmp_size = 0;
1815
1816 for (size_t j = 0; j < n_backends; j++) {
15
Assuming 'j' is >= 'n_backends'
16
Loop condition is false. Execution continues on line 1834
1817 auto & bcj = backend_ctx->backend_configs[j];
1818
1819 for (int i = 0; i < cgraph->n_nodes; i++) {
1820 ggml_tensor * node = cgraph->nodes[i];
1821 if (node->view_src != nullptr && node->view_src->op == GGML_OP_NONE && ggml_backend_buffer_is_host(node->view_src->buffer)) {
1822 // FIXME s_copy_main is on the CPU and its view seems to be incorrectly added to the graph nodes.
1823 // For regular usage this doesn't matter since it's a noop but trying to call ggml_backend_meta_buffer_simple_tensor results in a crash.
1824 bcj.nodes[i] = node;
1825 continue;
1826 }
1827 bcj.nodes[i] = ggml_backend_meta_buffer_simple_tensor(node, j);
1828 GGML_ASSERT(bcj.nodes[i])if (!(bcj.nodes[i])) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1828, "GGML_ASSERT(%s) failed", "bcj.nodes[i]")
;
1829 }
1830 }
1831
1832 {
1833 // For MoE models it may make sense to delay the AllReduce in order to reduce I/O:
1834 auto get_i_delayed = [&](const int i) -> int {
1835 int id = i; // i_delayed
1836 int idr = i; // i_delayed return, last safe return value
1837
1838 ggml_tensor * node = cgraph->nodes[id];
1839 int32_t n_used = ggml_node_get_use_count(cgraph, id);
1840
1841 // Skip MIRRORED nodes that don't consume node
1842 auto skip_unrelated = [&]() {
1843 while (id + 1 < cgraph->n_nodes) {
1844 ggml_tensor * next = cgraph->nodes[id+1];
1845 if (ggml_backend_meta_get_split_state(next, false).axis != GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
1846 break;
1847 }
1848 bool safe = true;
1849 for (int s = 0; s < GGML_MAX_SRC10; s++) {
1850 if (next->src[s] == nullptr) {
1851 continue;
1852 }
1853 if (next->src[s] == node) {
1854 safe = false;
1855 break;
1856 }
1857 if (ggml_backend_meta_get_split_state(next->src[s], false).axis != GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
1858 safe = false;
1859 break;
1860 }
1861 }
1862 if (!safe) {
1863 break;
1864 }
1865 id++;
1866 }
1867 };
1868
1869 skip_unrelated();
1870 if (id + 1 >= cgraph->n_nodes) {
1871 return idr;
1872 }
1873 {
1874 ggml_tensor * next = cgraph->nodes[id+1];
1875 if (next->op == GGML_OP_ADD_ID && next->src[0] == node &&
1876 ggml_backend_meta_get_split_state(next->src[1], false).axis == GGML_BACKEND_SPLIT_AXIS_PARTIAL &&
1877 ggml_backend_meta_get_split_state(next->src[2], false).axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
1878 node = next;
1879 id++;
1880 idr = id;
1881 n_used = ggml_node_get_use_count(cgraph, id);
1882 }
1883 }
1884 // Chain of MULs with MIRRORED src[1]
1885 while (true) {
1886 skip_unrelated();
1887 if (id + 1 >= cgraph->n_nodes) {
1888 return idr;
1889 }
1890 ggml_tensor * next = cgraph->nodes[id+1];
1891 if (next->op == GGML_OP_MUL && next->src[0] == node &&
1892 ggml_backend_meta_get_split_state(next->src[1], false).axis == GGML_BACKEND_SPLIT_AXIS_MIRRORED) {
1893 node = next;
1894 id++;
1895 idr = id;
1896 n_used = ggml_node_get_use_count(cgraph, id);
1897 } else {
1898 break;
1899 }
1900 }
1901
1902 if (n_used != node->ne[1] || id + 2*n_used-1 >= cgraph->n_nodes) {
1903 return idr;
1904 }
1905 for (int32_t k = 0; k < n_used; k++) {
1906 ggml_tensor * next = cgraph->nodes[id+1];
1907 if (next->op != GGML_OP_VIEW || next->view_src != node || next->view_offs != k*node->nb[1] ||
1908 next->ne[0] != node->ne[0] || next->ne[1] != node->ne[2] || next->nb[1] != node->nb[2] ||
1909 ggml_node_get_use_count(cgraph, id+1) != 1) {
1910 return idr;
1911 }
1912 id++;
1913 }
1914 {
1915 ggml_tensor * next = cgraph->nodes[id+1];
1916 if (next->op != GGML_OP_ADD || next->src[0] != cgraph->nodes[id - (n_used-1)] ||
1917 next->src[1] != cgraph->nodes[id - (n_used-2)] || ggml_node_get_use_count(cgraph, id+1) != 1) {
1918 return idr;
1919 }
1920 id++;
1921 }
1922 for (int32_t k = 0; k < n_used - 2; k++) {
1923 ggml_tensor * next = cgraph->nodes[id+1];
1924 if (next->op != GGML_OP_ADD || next->src[0] != cgraph->nodes[id] ||
1925 next->src[1] != cgraph->nodes[id - (n_used-2)] || ggml_node_get_use_count(cgraph, id+1) != 1) {
1926 return idr;
1927 }
1928 id++;
1929 }
1930 idr = id;
1931 return idr;
1932 };
1933
1934 int i_start = 0;
1935 for (int i = 0; i < cgraph->n_nodes; i++) {
17
Loop condition is true. Entering loop body
1936 ggml_tensor * node = cgraph->nodes[i];
1937 if (node->view_src != nullptr && node->view_src->op == GGML_OP_NONE && ggml_backend_buffer_is_host(node->view_src->buffer)) {
18
Assuming the condition is false
1938 continue;
1939 }
1940 const ggml_backend_meta_split_state split_state = ggml_backend_meta_get_split_state(node, /*assume_sync =*/ false);
19
Calling 'ggml_backend_meta_get_split_state'
1941 if (split_state.axis == GGML_BACKEND_SPLIT_AXIS_PARTIAL) {
1942 max_tmp_size = std::max(max_tmp_size, ggml_nbytes(node));
1943 }
1944 const bool new_subgraph = i + 1 == cgraph->n_nodes || split_state.axis == GGML_BACKEND_SPLIT_AXIS_PARTIAL;
1945 if (!new_subgraph) {
1946 continue;
1947 }
1948
1949 const int i_delayed = get_i_delayed(i);
1950
1951 // If we can delay the AllReduce we need to consider the interaction with zero-sized tensor slices.
1952 // A backend with such a slice would normally have valid data after participating in the AllReduce with a node that has
1953 // its compute flag disabled and thus gets its data zeroed out.
1954 // If the AllReduce is delayed then the nodes until that point also need to have their compute flag disabled.
1955 if (i_delayed > i) {
1956 for (size_t j = 0; j < n_backends; j++) {
1957 auto & bcj = backend_ctx->backend_configs[j];
1958 if ((bcj.nodes[i]->flags & GGML_TENSOR_FLAG_COMPUTE) == 0) {
1959 for (int ii = i + 1; ii <= i_delayed; ii++) {
1960 bcj.nodes[ii]->flags &= ~GGML_TENSOR_FLAG_COMPUTE;
1961 }
1962 }
1963 }
1964 }
1965
1966 i = i_delayed;
1967
1968 for (size_t j = 0; j < n_backends; j++) {
1969 auto & bcj = backend_ctx->backend_configs[j];
1970 bcj.cgraphs[n_subgraphs].offset = i_start;
1971 }
1972 n_subgraphs++;
1973 i_start = i + 1;
1974 }
1975 GGML_ASSERT(i_start == cgraph->n_nodes)if (!(i_start == cgraph->n_nodes)) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 1975, "GGML_ASSERT(%s) failed", "i_start == cgraph->n_nodes"
)
;
1976 }
1977
1978 backend_ctx->uid = cgraph->uid;
1979 backend_ctx->n_subgraphs = n_subgraphs;
1980
1981 if (max_tmp_size > backend_ctx->max_tmp_size) {
1982 for (size_t j = 0; j < n_backends; j++) {
1983 auto & bcj = backend_ctx->backend_configs[j];
1984 for (size_t i = 0; i < backend_ctx->n_reduce_steps; i++) {
1985 bcj.bufs[i].reset(ggml_backend_alloc_buffer(bcj.backend, max_tmp_size));
1986 }
1987 }
1988 backend_ctx->max_tmp_size = max_tmp_size;
1989 }
1990
1991 if (max_nnodes_raised || n_subgraphs > backend_ctx->max_subgraphs) {
1992 backend_ctx->max_subgraphs = std::max(backend_ctx->max_subgraphs, n_subgraphs);
1993 const size_t n_nodes_per_device = 3 * backend_ctx->n_reduce_steps; // tmp + ADD (+zeroing) graph per step and device
1994 const size_t n_cgraphs_per_device = 2 * backend_ctx->n_reduce_steps; // ADD ( + zeroing) graph per step and device
1995 const size_t mem_per_device_graphs_main = backend_ctx->max_subgraphs*ggml_graph_overhead_custom(backend_ctx->max_nnodes, cgraph->grads);
1996 const size_t mem_per_device_graphs_aux = n_cgraphs_per_device*backend_ctx->max_subgraphs*ggml_graph_overhead_custom(1, cgraph->grads);
1997 const size_t mem_per_device_nodes_aux = n_nodes_per_device*backend_ctx->max_subgraphs*ggml_tensor_overhead();
1998 const ggml_init_params params = {
1999 /*.mem_size =*/ n_backends * (mem_per_device_graphs_main + mem_per_device_graphs_aux + mem_per_device_nodes_aux),
2000 /*.mem_buffer =*/ nullptr,
2001 /*.no_alloc =*/ true,
2002 };
2003 backend_ctx->ctx.reset(ggml_init(params));
2004 for (size_t j = 0; j < n_backends; j++) {
2005 auto & bcj = backend_ctx->backend_configs[j];
2006 for (size_t i = 0; i < n_subgraphs; i++) {
2007 bcj.cgraphs[i].cgraph_main = ggml_new_graph_custom(backend_ctx->ctx.get(), cgraph->n_nodes, /*grads =*/ false);
2008 }
2009 }
2010 backend_ctx->cgraphs_aux.resize(n_backends*n_cgraphs_per_device*backend_ctx->max_subgraphs);
2011 for (size_t k = 0; k < backend_ctx->cgraphs_aux.size(); k++) {
2012 backend_ctx->cgraphs_aux[k] = ggml_new_graph_custom(backend_ctx->ctx.get(), 1, cgraph->grads);
2013 }
2014 backend_ctx->nodes_aux.resize(n_backends*n_nodes_per_device*backend_ctx->max_subgraphs);
2015 for (size_t k = 0; k < backend_ctx->nodes_aux.size(); k++) {
2016 backend_ctx->nodes_aux[k] = ggml_new_tensor_1d(backend_ctx->ctx.get(), GGML_TYPE_F32, 1);
2017 }
2018 }
2019
2020 for (size_t j = 0; j < n_backends; j++) {
2021 auto & bcj = backend_ctx->backend_configs[j];
2022 for (size_t i_graph = 0; i_graph < n_subgraphs; i_graph++) {
2023 ggml_cgraph * cgraph_ij = bcj.cgraphs[i_graph].cgraph_main;
2024 const size_t i_node_start = bcj.cgraphs[i_graph].offset;
2025 const size_t i_node_stop = i_graph + 1 < n_subgraphs ? bcj.cgraphs[i_graph + 1].offset : cgraph->n_nodes;
2026 cgraph_ij->n_nodes = i_node_stop - i_node_start;
2027 ggml_hash_set_reset(&cgraph_ij->visited_hash_set);
2028 for (size_t i_node = i_node_start; i_node < i_node_stop; i_node++) {
2029 ggml_tensor * node_ij = bcj.nodes[i_node];
2030 cgraph_ij->nodes[i_node - i_node_start] = node_ij;
2031 const size_t hash_pos_orig = ggml_hash_find(&cgraph->visited_hash_set, cgraph->nodes[i_node]);
2032 const size_t hash_pos_ij = ggml_hash_insert(&cgraph_ij->visited_hash_set, node_ij);
2033 cgraph_ij->use_counts[hash_pos_ij] = cgraph->use_counts[hash_pos_orig];
2034 }
2035 cgraph_ij->uid = ggml_graph_next_uid();
2036 }
2037 }
2038 }
2039
2040 size_t iga = 0; // i graph aux
2041 size_t ina = 0; // i node aux
2042
2043 auto get_node_aux = [&](ggml_tensor * t) -> ggml_tensor * {
2044 ggml_tensor * ret = backend_ctx->nodes_aux[ina++];
2045 memset(ret, 0, sizeof(ggml_tensor));
2046 ret->op = GGML_OP_NONE;
2047 ret->type = t->type;
2048 for (size_t k = 0; k < GGML_MAX_DIMS4; k++) {
2049 ret->ne[k] = t->ne[k];
2050 ret->nb[k] = t->nb[k];
2051 }
2052 return ret;
2053 };
2054 auto set_tmp_data = [&](ggml_tensor * tensor, const size_t j, const size_t i_buf) {
2055 auto & bcj = backend_ctx->backend_configs[j];
2056 ggml_backend_buffer_ptr & buf_ptr = bcj.bufs[i_buf];
2057 if (!buf_ptr || ggml_backend_buffer_get_size(buf_ptr.get()) < backend_ctx->max_tmp_size) {
2058 buf_ptr.reset(ggml_backend_alloc_buffer(bcj.backend, backend_ctx->max_tmp_size));
2059 }
2060 tensor->buffer = buf_ptr.get();
2061 tensor->data = ggml_backend_buffer_get_base(buf_ptr.get());
2062 };
2063 // FIXME usage_counts
2064 auto get_cgraph_aux = [&]() -> ggml_cgraph * {
2065 ggml_cgraph * ret = backend_ctx->cgraphs_aux[iga++];
2066 return ret;
2067 };
2068
2069 // Preferentially use backend-specific allreduce_tensor_async (e.g. NCCL for CUDA), use a generic fallback if unavailable:
2070 auto allreduce_fallback = [&](size_t i) -> ggml_status {
2071 std::vector<ggml_cgraph *> step_cgraphs(n_backends, nullptr);
2072
2073 // Zero out nodes that were disabled due to having a zero-sized slice:
2074 for (size_t j = 0; j < n_backends; j++) {
2075 auto & bcj = backend_ctx->backend_configs[j];
2076 ggml_tensor * node = bcj.cgraphs[i].cgraph_main->nodes[bcj.cgraphs[i].cgraph_main->n_nodes - 1];
2077 if (node->flags & GGML_TENSOR_FLAG_COMPUTE) {
2078 continue;
2079 }
2080 ggml_tensor * node_zero = get_node_aux(node);
2081 node_zero->op = GGML_OP_SCALE; // FIXME 0.0f * NaN == NaN
2082 node_zero->src[0] = node;
2083 ggml_set_op_params_f32(node_zero, 0, 0.0f);
2084 node_zero->data = node->data;
2085 node_zero->buffer = node->buffer;
2086 node_zero->flags |= GGML_TENSOR_FLAG_COMPUTE;
2087
2088 step_cgraphs[j] = get_cgraph_aux();
2089 step_cgraphs[j]->nodes[0] = node_zero;
2090 step_cgraphs[j]->n_nodes = 1;
2091 const ggml_status status = ggml_backend_graph_compute_async(bcj.backend, step_cgraphs[j]);
2092 if (status != GGML_STATUS_SUCCESS) {
2093 return status;
2094 }
2095 }
2096 std::fill(step_cgraphs.begin(), step_cgraphs.end(), nullptr);
2097
2098 auto push_data = [&](const size_t j_src, const size_t j_dst, const size_t i_buf) {
2099 assert(step_cgraphs[j_dst] == nullptr)(static_cast <bool> (step_cgraphs[j_dst] == nullptr) ? void
(0) : __assert_fail ("step_cgraphs[j_dst] == nullptr", __builtin_FILE
(), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__))
;
2100 auto & bcj_src = backend_ctx->backend_configs[j_src];
2101 auto & bcj_dst = backend_ctx->backend_configs[j_dst];
2102
2103 ggml_tensor * node_src = bcj_src.cgraphs[i].cgraph_main->nodes[bcj_src.cgraphs[i].cgraph_main->n_nodes - 1];
2104 ggml_tensor * node_dst = bcj_dst.cgraphs[i].cgraph_main->nodes[bcj_dst.cgraphs[i].cgraph_main->n_nodes - 1];
2105 GGML_ASSERT(ggml_is_contiguous(node_src))if (!(ggml_is_contiguous(node_src))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 2105, "GGML_ASSERT(%s) failed", "ggml_is_contiguous(node_src)"
)
;
2106 GGML_ASSERT(ggml_is_contiguous(node_dst))if (!(ggml_is_contiguous(node_dst))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 2106, "GGML_ASSERT(%s) failed", "ggml_is_contiguous(node_dst)"
)
;
2107
2108 ggml_tensor * node_tmp = get_node_aux(node_dst);
2109 set_tmp_data(node_tmp, j_dst, i_buf);
2110
2111 ggml_backend_tensor_copy_async(bcj_src.backend, bcj_dst.backend, node_src, node_tmp);
2112
2113 ggml_tensor * node_red = get_node_aux(node_dst);
2114 node_red->view_src = node_dst->view_src == nullptr ? node_dst : node_dst->view_src;
2115 node_red->view_offs = node_dst->view_offs;
2116 node_red->op = GGML_OP_ADD;
2117 node_red->src[0] = node_dst;
2118 node_red->src[1] = node_tmp;
2119 node_red->flags |= GGML_TENSOR_FLAG_COMPUTE;
2120 ggml_backend_view_init(node_red);
2121
2122 ggml_cgraph * cgraph_aux = get_cgraph_aux();
2123 cgraph_aux->nodes[0] = node_red;
2124 cgraph_aux->n_nodes = 1;
2125 step_cgraphs[j_dst] = cgraph_aux;
2126 };
2127
2128 size_t offset_j = n_backends/2;
2129 while ((offset_j & (offset_j - 1)) != 0) {
2130 offset_j--;
2131 }
2132 const size_t offset_j_max = offset_j;
2133 size_t i_buf = 0;
2134
2135 // If n_backends is not a power of 2, fold in the excess prior to butterfly reduction:
2136 for (size_t j_src = 2*offset_j_max; j_src < n_backends; j_src++) {
2137 const size_t j_dst = j_src - 2*offset_j_max;
2138 push_data(j_src, j_dst, i_buf);
2139 const ggml_status status = ggml_backend_graph_compute_async(backend_ctx->backend_configs[j_dst].backend, step_cgraphs[j_dst]);
2140 if (status != GGML_STATUS_SUCCESS) {
2141 return status;
2142 }
2143 i_buf = 1;
2144 }
2145
2146 // Butterfly reduction:
2147 for (; offset_j >= 1; offset_j /= 2) {
2148 std::fill(step_cgraphs.begin(), step_cgraphs.end(), nullptr);
2149
2150 for (size_t j = 0; j < 2*offset_j_max; j++) {
2151 const size_t j_other = j ^ offset_j;
2152 if (j_other >= n_backends) {
2153 continue;
2154 }
2155 push_data(j, j_other, i_buf);
2156 }
2157
2158 for (size_t j = 0; j < 2*offset_j_max; j++) {
2159 if (step_cgraphs[j] == nullptr) {
2160 continue;
2161 }
2162 auto & bcj = backend_ctx->backend_configs[j];
2163 const ggml_status status = ggml_backend_graph_compute_async(bcj.backend, step_cgraphs[j]);
2164 if (status != GGML_STATUS_SUCCESS) {
2165 return status;
2166 }
2167 }
2168 i_buf++;
2169 }
2170 assert(i_buf == backend_ctx->n_reduce_steps)(static_cast <bool> (i_buf == backend_ctx->n_reduce_steps
) ? void (0) : __assert_fail ("i_buf == backend_ctx->n_reduce_steps"
, __builtin_FILE (), __builtin_LINE (), __extension__ __PRETTY_FUNCTION__
))
;
2171
2172 // If n_backends is not a power of 2, copy back the reduced tensors to the excess:
2173 for (size_t j = 2*offset_j_max; j < n_backends; j++) {
2174 auto & bcj_src = backend_ctx->backend_configs[j - 2*offset_j_max];
2175 auto & bcj_dst = backend_ctx->backend_configs[j];
2176
2177 ggml_tensor * node_src = bcj_src.cgraphs[i].cgraph_main->nodes[bcj_src.cgraphs[i].cgraph_main->n_nodes - 1];
2178 ggml_tensor * node_dst = bcj_dst.cgraphs[i].cgraph_main->nodes[bcj_dst.cgraphs[i].cgraph_main->n_nodes - 1];
2179 ggml_backend_tensor_copy_async(bcj_src.backend, bcj_dst.backend, node_src, node_dst);
2180 }
2181
2182 return GGML_STATUS_SUCCESS;
2183 };
2184
2185
2186 for (size_t i = 0; i < backend_ctx->n_subgraphs; i++) {
2187 for (size_t j = 0; j < n_backends; j++) {
2188 auto & bcj = backend_ctx->backend_configs[j];
2189 const ggml_status status = ggml_backend_graph_compute_async(bcj.backend, bcj.cgraphs[i].cgraph_main);
2190 if (status != GGML_STATUS_SUCCESS) {
2191 return status;
2192 }
2193 }
2194
2195 if (n_backends > 1 && i < backend_ctx->n_subgraphs - 1) {
2196 bool backend_allreduce_success = false;
2197 if (backend_ctx->comm_ctx) {
2198 std::vector<ggml_tensor *> nodes;
2199 nodes.reserve(n_backends);
2200 for (size_t j = 0; j < n_backends; j++) {
2201 auto & bcj = backend_ctx->backend_configs[j];
2202 ggml_cgraph * cgraph_ij = bcj.cgraphs[i].cgraph_main;
2203 nodes.push_back(cgraph_ij->nodes[cgraph_ij->n_nodes-1]);
2204 }
2205 backend_allreduce_success = backend_ctx->comm_allreduce(backend_ctx->comm_ctx, nodes.data());
2206 }
2207
2208 if (!backend_allreduce_success) {
2209 const ggml_status status = allreduce_fallback(i);
2210 if (status != GGML_STATUS_SUCCESS) {
2211 return status;
2212 }
2213 }
2214 }
2215 }
2216 return GGML_STATUS_SUCCESS;
2217}
2218
2219static const ggml_backend_i ggml_backend_meta_i = {
2220 /* .get_name = */ ggml_backend_meta_get_name,
2221 /* .free = */ ggml_backend_meta_free,
2222 /* .set_tensor_async = */ ggml_backend_meta_set_tensor_async,
2223 /* .get_tensor_async = */ ggml_backend_meta_get_tensor_async,
2224 /* .set_tensor_2d_async = */ nullptr,
2225 /* .get_tensor_2d_async = */ nullptr,
2226 /* .cpy_tensor_async = */ nullptr,
2227 /* .synchronize = */ ggml_backend_meta_synchronize,
2228 /* .graph_plan_create = */ nullptr,
2229 /* .graph_plan_free = */ nullptr,
2230 /* .graph_plan_update = */ nullptr,
2231 /* .graph_plan_compute = */ nullptr,
2232 /* .graph_compute = */ ggml_backend_meta_graph_compute,
2233 /* .event_record = */ nullptr,
2234 /* .event_wait = */ nullptr,
2235 /* .graph_optimize = */ nullptr,
2236};
2237
2238bool ggml_backend_is_meta(ggml_backend_t backend) {
2239 return backend != nullptr && backend->iface.get_name == ggml_backend_meta_i.get_name;
2240}
2241
2242static ggml_backend_t ggml_backend_meta_device_init_backend(ggml_backend_dev_t dev, const char * params) {
2243 ggml_backend_meta_context * backend_ctx = new ggml_backend_meta_context(dev, params);
2244
2245 ggml_backend_t backend = new struct ggml_backend;
2246 backend->guid = ggml_backend_meta_guid();
2247 backend->iface = ggml_backend_meta_i;
2248 backend->device = dev;
2249 backend->context = backend_ctx;
2250 return backend;
2251}
2252
2253size_t ggml_backend_meta_n_backends(ggml_backend_t meta_backend) {
2254 GGML_ASSERT(ggml_backend_is_meta(meta_backend))if (!(ggml_backend_is_meta(meta_backend))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 2254, "GGML_ASSERT(%s) failed", "ggml_backend_is_meta(meta_backend)"
)
;
2255 const ggml_backend_meta_context * backend_ctx = (const ggml_backend_meta_context *) meta_backend->context;
2256 return backend_ctx->backend_configs.size();
2257}
2258
2259ggml_backend_t ggml_backend_meta_simple_backend(ggml_backend_t meta_backend, size_t index) {
2260 GGML_ASSERT(ggml_backend_is_meta(meta_backend))if (!(ggml_backend_is_meta(meta_backend))) ggml_abort("/root/firefox-clang/third_party/llama.cpp/ggml/src/ggml-backend-meta.cpp"
, 2260, "GGML_ASSERT(%s) failed", "ggml_backend_is_meta(meta_backend)"
)
;
2261 const ggml_backend_meta_context * backend_ctx = (const ggml_backend_meta_context *) meta_backend->context;
2262 return backend_ctx->backend_configs[index].backend;
2263}