char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Aman Guptaggml: skip 0-sized ids tensor when offloading selected experts (#28739)43f3dda62

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