| 2366 | }; |
| 2367 | |
| 2368 | void SymbolicGradientHelper::Copy(FunctionBody* gbody) { |
| 2369 | const Graph& src = *(fbody_->graph); |
| 2370 | gbody->graph = new Graph(src.op_registry()); |
| 2371 | Graph* dst = gbody->graph; |
| 2372 | |
| 2373 | std::vector<Node*> node_map(src.num_node_ids()); |
| 2374 | |
| 2375 | // Copy just the fdef attributes (copy '_noinline' and other similar flags to |
| 2376 | // the gradient function body). |
| 2377 | *(gbody->fdef.mutable_attr()) = fbody_->fdef.attr(); |
| 2378 | |
| 2379 | // Copy the nodes. |
| 2380 | node_map[src.source_node()->id()] = dst->source_node(); |
| 2381 | node_map[src.sink_node()->id()] = dst->sink_node(); |
| 2382 | for (Node* n : src.op_nodes()) { |
| 2383 | node_map[n->id()] = dst->CopyNode(n); |
| 2384 | } |
| 2385 | |
| 2386 | // Copy the edges. |
| 2387 | for (const Edge* e : src.edges()) { |
| 2388 | Node* src_copy = node_map[e->src()->id()]; |
| 2389 | Node* dst_copy = node_map[e->dst()->id()]; |
| 2390 | dst->AddEdge(src_copy, e->src_output(), dst_copy, e->dst_input()); |
| 2391 | } |
| 2392 | |
| 2393 | // Save inputs in copied graph. |
| 2394 | CHECK_EQ(fbody_->arg_types.size(), fbody_->arg_nodes.size()); |
| 2395 | gbody->arg_types = fbody_->arg_types; |
| 2396 | for (std::size_t i = 0; i < fbody_->arg_nodes.size(); ++i) { |
| 2397 | gbody->arg_nodes.push_back(node_map[fbody_->arg_nodes[i]->id()]); |
| 2398 | } |
| 2399 | |
| 2400 | // Save outputs in copied graph. |
| 2401 | CHECK_EQ(fbody_->ret_types.size(), fbody_->ret_nodes.size()); |
| 2402 | gbody->ret_types = fbody_->ret_types; |
| 2403 | for (std::size_t i = 0; i < fbody_->ret_nodes.size(); ++i) { |
| 2404 | gbody->ret_nodes.push_back(node_map[fbody_->ret_nodes[i]->id()]); |
| 2405 | } |
| 2406 | } |
| 2407 | |
| 2408 | std::unique_ptr<FunctionBody> SymbolicGradientHelper::Compute() { |
| 2409 | FunctionBody* gbody = new FunctionBody; |