| 1661 | } |
| 1662 | |
| 1663 | void AggregateForApply(Graph* dest, Node* n, |
| 1664 | map_node_list& duplicated_nodes, int grad_input) { |
| 1665 | const Edge* e = nullptr; |
| 1666 | TF_CHECK_OK(n->input_edge(grad_input, &e)); |
| 1667 | auto grad = e->src(); |
| 1668 | auto duplicate_grads = duplicated_nodes[grad]; |
| 1669 | std::vector<NodeDefBuilder::NodeOut> src_list; |
| 1670 | src_list.emplace_back(grad->name(), e->src_output(), |
| 1671 | grad->output_type(0)); |
| 1672 | for (auto it : duplicate_grads) { |
| 1673 | src_list.emplace_back(it->name(), e->src_output(), |
| 1674 | it->output_type(0)); |
| 1675 | } |
| 1676 | |
| 1677 | NodeDef node_def; |
| 1678 | TF_CHECK_OK(NodeDefBuilder(n->name() + "/aggr_addn", "AddN") |
| 1679 | .Device(n->assigned_device_name()) |
| 1680 | .Input(src_list) |
| 1681 | .Attr("T", grad->output_type(0)) |
| 1682 | .Finalize(&node_def)); |
| 1683 | |
| 1684 | Status s; |
| 1685 | Node* aggregate_node = dest->AddNode(node_def, &s); |
| 1686 | TF_CHECK_OK(s); |
| 1687 | aggregate_node->set_assigned_device_name(n->assigned_device_name()); |
| 1688 | |
| 1689 | dest->RemoveEdge(e); |
| 1690 | dest->AddEdge(aggregate_node, 0, n, grad_input); |
| 1691 | dest->AddEdge(grad, 0, aggregate_node, 0); |
| 1692 | for (size_t i = 0; i < duplicate_grads.size(); ++i) { |
| 1693 | dest->AddEdge(duplicate_grads[i], 0, aggregate_node, i+1); |
| 1694 | } |
| 1695 | } |
| 1696 | |
| 1697 | |
| 1698 | void AggregateForSparseApply(Graph* dest, Node* n, |
no test coverage detected