| 1725 | } |
| 1726 | |
| 1727 | ggml_backend_sched_t ggml_backend_sched_new( |
| 1728 | ggml_backend_t * backends, |
| 1729 | ggml_backend_buffer_type_t * bufts, |
| 1730 | int n_backends, |
| 1731 | size_t graph_size, |
| 1732 | bool parallel, |
| 1733 | bool op_offload) { |
| 1734 | GGML_ASSERT(n_backends > 0); |
| 1735 | GGML_ASSERT(n_backends <= GGML_SCHED_MAX_BACKENDS); |
| 1736 | GGML_ASSERT(ggml_backend_dev_type(ggml_backend_get_device(backends[n_backends - 1])) == GGML_BACKEND_DEVICE_TYPE_CPU); |
| 1737 | |
| 1738 | struct ggml_backend_sched * sched = (ggml_backend_sched *) calloc(1, sizeof(struct ggml_backend_sched)); |
| 1739 | |
| 1740 | const char * GGML_SCHED_DEBUG = getenv("GGML_SCHED_DEBUG"); |
| 1741 | sched->debug = GGML_SCHED_DEBUG ? atoi(GGML_SCHED_DEBUG) : 0; |
| 1742 | |
| 1743 | sched->debug_realloc = 0; |
| 1744 | #ifdef GGML_SCHED_NO_REALLOC |
| 1745 | sched->debug_realloc = 1; |
| 1746 | #endif |
| 1747 | const char * GGML_SCHED_DEBUG_REALLOC = getenv("GGML_SCHED_DEBUG_REALLOC"); |
| 1748 | sched->debug_realloc = GGML_SCHED_DEBUG_REALLOC ? atoi(GGML_SCHED_DEBUG_REALLOC) : sched->debug_realloc; |
| 1749 | |
| 1750 | sched->n_backends = n_backends; |
| 1751 | sched->n_copies = parallel ? GGML_SCHED_MAX_COPIES : 1; |
| 1752 | |
| 1753 | // initialize hash table |
| 1754 | // FIXME: needs to be size*2 to account for leafs (do it in graph_split instead) |
| 1755 | sched->hash_set = ggml_hash_set_new(graph_size); |
| 1756 | sched->hv_tensor_backend_ids = (int *) malloc(sched->hash_set.size * sizeof(sched->hv_tensor_backend_ids[0])); |
| 1757 | sched->hv_tensor_copies = (ggml_tensor **) malloc(sched->hash_set.size * sched->n_backends * sched->n_copies * sizeof(struct ggml_tensor *)); |
| 1758 | |
| 1759 | const size_t ggml_sched_max_splits = graph_size; // at most there is one split for each node in the graph |
| 1760 | const size_t nodes_size = graph_size + ggml_sched_max_splits*GGML_SCHED_MAX_SPLIT_INPUTS*2; |
| 1761 | sched->node_backend_ids = (int *) calloc(nodes_size, sizeof(sched->node_backend_ids[0])); |
| 1762 | sched->leaf_backend_ids = (int *) calloc(nodes_size, sizeof(sched->leaf_backend_ids[0])); |
| 1763 | sched->prev_node_backend_ids = (int *) calloc(nodes_size, sizeof(sched->prev_node_backend_ids[0])); |
| 1764 | sched->prev_leaf_backend_ids = (int *) calloc(nodes_size, sizeof(sched->prev_leaf_backend_ids[0])); |
| 1765 | |
| 1766 | sched->debug_graph_size = 0; |
| 1767 | sched->debug_prev_graph_size = 0; |
| 1768 | |
| 1769 | sched->context_buffer_size = ggml_sched_max_splits*GGML_SCHED_MAX_SPLIT_INPUTS*2*sizeof(struct ggml_tensor) + ggml_graph_overhead_custom(graph_size, false); |
| 1770 | sched->context_buffer = (char *) malloc(sched->context_buffer_size); |
| 1771 | |
| 1772 | const int initial_splits_capacity = 16; |
| 1773 | sched->splits = (ggml_backend_sched_split *) calloc(initial_splits_capacity, sizeof(sched->splits[0])); |
| 1774 | sched->splits_capacity = initial_splits_capacity; |
| 1775 | |
| 1776 | for (int b = 0; b < n_backends; b++) { |
| 1777 | sched->backends[b] = backends[b]; |
| 1778 | sched->bufts[b] = bufts ? bufts[b] : ggml_backend_get_default_buffer_type(backends[b]); |
| 1779 | GGML_ASSERT(ggml_backend_supports_buft(backends[b], sched->bufts[b])); |
| 1780 | |
| 1781 | if (sched->n_copies > 1) { |
| 1782 | for (int c = 0; c < sched->n_copies; c++) { |
| 1783 | sched->events[b][c] = ggml_backend_event_new(backends[b]->device); |
| 1784 | } |