| 715 | } |
| 716 | |
| 717 | static void ggml_gallocr_alloc_graph_impl(ggml_gallocr_t galloc, struct ggml_cgraph * graph, const int * node_buffer_ids, const int * leaf_buffer_ids) { |
| 718 | // clear hash tables |
| 719 | ggml_hash_set_reset(&galloc->hash_set); |
| 720 | memset(galloc->hash_values, 0, sizeof(struct hash_node) * galloc->hash_set.size); |
| 721 | |
| 722 | // allocate leafs |
| 723 | // these may be tensors that the application is not using in the graph, but may still want to allocate for other purposes |
| 724 | for (int i = 0; i < graph->n_leafs; i++) { |
| 725 | struct ggml_tensor * leaf = graph->leafs[i]; |
| 726 | ggml_gallocr_allocate_node(galloc, leaf, get_node_buffer_id(leaf_buffer_ids, i)); |
| 727 | } |
| 728 | |
| 729 | // count number of children and views |
| 730 | // allocate other graph inputs and leafs first to avoid overwriting them |
| 731 | for (int i = 0; i < graph->n_nodes; i++) { |
| 732 | struct ggml_tensor * node = graph->nodes[i]; |
| 733 | |
| 734 | // TODO: better way to add external dependencies |
| 735 | // GGML_OP_NONE does not appear normally in the graph nodes, but is used by ggml-backend to add dependencies to |
| 736 | // control when some tensors are allocated and freed. in this case, the dependencies are in `src`, but the node |
| 737 | // itself is never used and should not be considered a dependency |
| 738 | if (ggml_impl_is_view(node) && node->op != GGML_OP_NONE) { |
| 739 | struct ggml_tensor * view_src = node->view_src; |
| 740 | ggml_gallocr_hash_get(galloc, view_src)->n_views += 1; |
| 741 | } |
| 742 | |
| 743 | if (node->flags & GGML_TENSOR_FLAG_INPUT) { |
| 744 | ggml_gallocr_allocate_node(galloc, graph->nodes[i], get_node_buffer_id(node_buffer_ids, i)); |
| 745 | } |
| 746 | |
| 747 | for (int j = 0; j < GGML_MAX_SRC; j++) { |
| 748 | struct ggml_tensor * src = node->src[j]; |
| 749 | if (src == NULL) { |
| 750 | continue; |
| 751 | } |
| 752 | |
| 753 | ggml_gallocr_hash_get(galloc, src)->n_children += 1; |
| 754 | |
| 755 | // allocate explicit inputs |
| 756 | if (src->flags & GGML_TENSOR_FLAG_INPUT) { |
| 757 | ggml_gallocr_allocate_node(galloc, src, get_node_buffer_id(node_buffer_ids, i)); |
| 758 | } |
| 759 | } |
| 760 | } |
| 761 | |
| 762 | // allocate tensors |
| 763 | for (int i = 0; i < graph->n_nodes; i++) { |
| 764 | struct ggml_tensor * node = graph->nodes[i]; |
| 765 | int buffer_id = get_node_buffer_id(node_buffer_ids, i); |
| 766 | |
| 767 | // allocate parents (only leafs need to be allocated at this point) |
| 768 | for (int j = 0; j < GGML_MAX_SRC; j++) { |
| 769 | struct ggml_tensor * parent = node->src[j]; |
| 770 | if (parent == NULL) { |
| 771 | continue; |
| 772 | } |
| 773 | ggml_gallocr_allocate_node(galloc, parent, buffer_id); |
| 774 | } |
no test coverage detected