| 556 | } |
| 557 | |
| 558 | GenericFunction GradTransformation::make_backward_closure(Span<ValueRef> ys) { |
| 559 | // reset GradKey |
| 560 | auto grad_key = m_key; |
| 561 | std::vector<GradSlotPtr> y_slots; |
| 562 | for (auto&& y : ys) { |
| 563 | if (auto&& grad_value = as_grad_value(y)) { |
| 564 | y_slots.push_back(grad_value->slot()); |
| 565 | } else { |
| 566 | y_slots.emplace_back(); |
| 567 | } |
| 568 | } |
| 569 | GenericFunction closure = [grad_key, y_slots](Span<ValueRef> dys) -> ValueRefList { |
| 570 | size_t nr_grads = y_slots.size(); |
| 571 | mgb_assert(dys.size() == nr_grads); |
| 572 | for (size_t i = 0; i < nr_grads; ++i) { |
| 573 | if (y_slots[i]) { |
| 574 | y_slots[i]->m_grad = dys[i]; |
| 575 | } |
| 576 | } |
| 577 | grad_key->backward(); |
| 578 | return {}; |
| 579 | }; |
| 580 | grad_key->freeze(); |
| 581 | cleanup(); |
| 582 | return closure; |
| 583 | } |
| 584 | |
| 585 | void GradTransformation::on_unregister() noexcept { |
| 586 | cleanup(); |
nothing calls this directly
no test coverage detected