| 620 | } |
| 621 | |
| 622 | static void ggml_gallocr_allocate_node(ggml_gallocr_t galloc, struct ggml_tensor * node, int buffer_id) { |
| 623 | GGML_ASSERT(buffer_id >= 0); |
| 624 | struct hash_node * hn = ggml_gallocr_hash_get(galloc, node); |
| 625 | |
| 626 | if (!ggml_gallocr_is_allocated(galloc, node) && !ggml_impl_is_view(node)) { |
| 627 | hn->allocated = true; |
| 628 | assert(hn->addr.offset == 0); |
| 629 | |
| 630 | // try to reuse a parent's buffer (inplace) |
| 631 | if (ggml_op_can_inplace(node->op)) { |
| 632 | for (int i = 0; i < GGML_MAX_SRC; i++) { |
| 633 | struct ggml_tensor * parent = node->src[i]; |
| 634 | if (parent == NULL) { |
| 635 | continue; |
| 636 | } |
| 637 | |
| 638 | // if the node's data is external, then we cannot re-use it |
| 639 | if (!ggml_gallocr_is_own(galloc, parent)) { |
| 640 | AT_PRINTF("not reusing parent %s for %s as %p is external\n", parent->name, node->name, parent->data); |
| 641 | continue; |
| 642 | } |
| 643 | |
| 644 | // outputs cannot be reused |
| 645 | if (parent->flags & GGML_TENSOR_FLAG_OUTPUT || (parent->view_src != NULL && parent->view_src->flags & GGML_TENSOR_FLAG_OUTPUT)) { |
| 646 | AT_PRINTF("not reusing parent %s for %s as it is an output\n", parent->name, node->name); |
| 647 | continue; |
| 648 | } |
| 649 | |
| 650 | if (!ggml_are_same_layout(node, parent)) { |
| 651 | AT_PRINTF("not reusing parent %s for %s as layouts are different\n", parent->name, node->name); |
| 652 | continue; |
| 653 | } |
| 654 | |
| 655 | struct hash_node * p_hn = ggml_gallocr_hash_get(galloc, parent); |
| 656 | if (p_hn->n_children == 1 && p_hn->n_views == 0) { |
| 657 | if (ggml_impl_is_view(parent)) { |
| 658 | struct ggml_tensor * view_src = parent->view_src; |
| 659 | struct hash_node * view_src_hn = ggml_gallocr_hash_get(galloc, view_src); |
| 660 | if (view_src_hn->n_views == 1 && view_src_hn->n_children == 0 && view_src->data == parent->data) { |
| 661 | AT_PRINTF("reusing view parent %s (%s) for %s\n", parent->name, view_src->name, node->name); |
| 662 | assert(view_src_hn->addr.chunk == p_hn->addr.chunk && view_src_hn->addr.offset == p_hn->addr.offset); |
| 663 | hn->buffer_id = p_hn->buffer_id; |
| 664 | hn->addr = p_hn->addr; |
| 665 | p_hn->allocated = false; // avoid freeing the parent |
| 666 | view_src_hn->allocated = false; |
| 667 | ggml_gallocr_free_extra_space(galloc, node, view_src); |
| 668 | return; |
| 669 | } |
| 670 | } else { |
| 671 | AT_PRINTF("reusing parent %s for %s\n", parent->name, node->name); |
| 672 | hn->buffer_id = p_hn->buffer_id; |
| 673 | hn->addr = p_hn->addr; |
| 674 | p_hn->allocated = false; // avoid freeing the parent |
| 675 | ggml_gallocr_free_extra_space(galloc, node, parent); |
| 676 | return; |
| 677 | } |
| 678 | } |
| 679 | } |
no test coverage detected