| 675 | } |
| 676 | |
| 677 | Status DependencyOptimizer::Optimize(Cluster* cluster, const GrapplerItem& item, |
| 678 | GraphDef* optimized_graph) { |
| 679 | optimized_graph_ = optimized_graph; |
| 680 | *optimized_graph_ = item.graph; |
| 681 | nodes_to_preserve_ = item.NodesToPreserve(); |
| 682 | fetch_nodes_known_ = !item.fetch.empty(); |
| 683 | CleanControlInputs(); |
| 684 | |
| 685 | const int num_iterations = 2; |
| 686 | for (int iteration = 0; iteration < num_iterations; ++iteration) { |
| 687 | GRAPPLER_RETURN_IF_DEADLINE_EXCEEDED(); |
| 688 | Status topo_sort_status; |
| 689 | // Perform topological sort to prepare the graph for transitive reduction. |
| 690 | topo_sort_status = TopologicalSort(optimized_graph_); |
| 691 | // Set up index-based graph datastructures to speed up analysis steps below. |
| 692 | node_map_.reset(new NodeMap(optimized_graph_)); |
| 693 | BuildNodeToIdx(); |
| 694 | |
| 695 | if (topo_sort_status.ok()) { |
| 696 | // Remove redundant control dependencies. |
| 697 | TF_RETURN_IF_ERROR(TransitiveReduction()); |
| 698 | } else { |
| 699 | LOG(ERROR) << "Iteration = " << iteration |
| 700 | << ", topological sort failed with message: " |
| 701 | << topo_sort_status.error_message(); |
| 702 | } |
| 703 | // Turn nodes with only control outputs into NoOps, prune NoOp and Identity |
| 704 | // nodes. |
| 705 | TF_RETURN_IF_ERROR(OptimizeDependencies()); |
| 706 | |
| 707 | // Dedup control inputs. |
| 708 | CleanControlInputs(); |
| 709 | |
| 710 | GroupCrossDeviceControlEdges(); |
| 711 | } |
| 712 | |
| 713 | return Status::OK(); |
| 714 | } |
| 715 | |
| 716 | void DependencyOptimizer::Feedback(Cluster* /*cluster*/, |
| 717 | const GrapplerItem& /*item*/, |
nothing calls this directly
no test coverage detected