| 467 | } |
| 468 | |
| 469 | static void allocate_node(ggml_gallocr_t galloc, struct ggml_tensor * node) { |
| 470 | ggml_tallocr_t alloc = node_tallocr(galloc, node); |
| 471 | |
| 472 | if (node->data == NULL) { |
| 473 | if (ggml_is_view(node)) { |
| 474 | init_view(galloc, node, true); |
| 475 | } else { |
| 476 | // see if we can reuse a parent's buffer (inplace) |
| 477 | if (ggml_op_can_inplace(node->op)) { |
| 478 | for (int i = 0; i < GGML_MAX_SRC; i++) { |
| 479 | struct ggml_tensor * parent = node->src[i]; |
| 480 | if (parent == NULL) { |
| 481 | break; |
| 482 | } |
| 483 | |
| 484 | // if the node's data is external, then we cannot re-use it |
| 485 | if (ggml_tallocr_is_own(alloc, parent) == false) { |
| 486 | AT_PRINTF("not reusing parent %s for %s as %p is external\n", parent->name, node->name, parent->data); |
| 487 | continue; |
| 488 | } |
| 489 | |
| 490 | struct hash_node * p_hn = hash_get(galloc, parent); |
| 491 | if (parent->data != NULL && p_hn->n_children == 1 && p_hn->n_views == 0 && ggml_are_same_layout(node, parent)) { |
| 492 | if (ggml_is_view(parent)) { |
| 493 | struct ggml_tensor * view_src = parent->view_src; |
| 494 | struct hash_node * view_src_hn = hash_get(galloc, view_src); |
| 495 | if (view_src_hn->n_views == 1 && view_src_hn->n_children == 0 && view_src->data == parent->data) { |
| 496 | // TODO: the offset of the view parent must be kept to ensure that the op doesn't overwrite |
| 497 | // the parent's data that it will need later (same layout requirement). the problem is that then |
| 498 | // we cannot free the tensor because the original address of the allocation is lost. |
| 499 | // adding a view_src pointer to the tensor would solve this and simplify the code dealing with views |
| 500 | // for now, we only reuse the parent's data if the offset is zero (view_src->data == parent->data) |
| 501 | AT_PRINTF("reusing view parent %s (%s) for %s\n", parent->name, view_src->name, node->name); |
| 502 | node->view_src = view_src; |
| 503 | view_src_hn->n_views += 1; |
| 504 | init_view(galloc, node, false); |
| 505 | return; |
| 506 | } |
| 507 | } else { |
| 508 | AT_PRINTF("reusing parent %s for %s\n", parent->name, node->name); |
| 509 | node->view_src = parent; |
| 510 | p_hn->n_views += 1; |
| 511 | init_view(galloc, node, false); |
| 512 | return; |
| 513 | } |
| 514 | } |
| 515 | } |
| 516 | } |
| 517 | ggml_tallocr_alloc(alloc, node); |
| 518 | } |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | static void free_node(ggml_gallocr_t galloc, struct ggml_tensor * node) { |
| 523 | ggml_tallocr_t alloc = node_tallocr(galloc, node); |
no test coverage detected