static */
| 940 | } |
| 941 | |
| 942 | /* static */ Status RemoteFusedGraphExecuteUtils::FuseCluster( |
| 943 | const GraphDef& input_graph_def, const std::vector<string>& inputs, |
| 944 | const std::vector<string>& outputs, |
| 945 | const string& remote_fused_graph_node_name, const ClusterInfo& cluster, |
| 946 | const string& remote_graph_executor_name, const bool require_shape_type, |
| 947 | GraphDef* output_graph_def) { |
| 948 | LOG(INFO) << "Transforming quantized stripped model to a remote fused " |
| 949 | "graph execute op by fusing a specified subgraph..."; |
| 950 | |
| 951 | CHECK(!remote_graph_executor_name.empty()); |
| 952 | |
| 953 | const std::vector<string>& border_inputs = std::get<1>(cluster); |
| 954 | const std::vector<string>& border_outputs = std::get<2>(cluster); |
| 955 | |
| 956 | GraphDef subgraph_def; |
| 957 | TF_RETURN_IF_ERROR( |
| 958 | BuildClusterSubgraphDef(cluster, input_graph_def, &subgraph_def)); |
| 959 | |
| 960 | Graph graph(OpRegistry::Global()); |
| 961 | ShapeRefiner shape_refiner(graph.versions(), graph.op_registry()); |
| 962 | TF_RETURN_IF_ERROR( |
| 963 | ImportGraphDef({}, input_graph_def, &graph, &shape_refiner)); |
| 964 | |
| 965 | Node* fused_node; |
| 966 | TF_RETURN_IF_ERROR(BuildRemoteFusedGraphExecuteOpNode( |
| 967 | remote_fused_graph_node_name, remote_graph_executor_name, subgraph_def, |
| 968 | border_inputs, border_outputs, require_shape_type, &graph, &fused_node)); |
| 969 | |
| 970 | for (const Node* node : graph.nodes()) { |
| 971 | for (int i = 0; i < node->num_inputs(); ++i) { |
| 972 | const Edge* edge = nullptr; |
| 973 | TF_RETURN_IF_ERROR(node->input_edge(i, &edge)); |
| 974 | for (int j = 0; j < border_outputs.size(); ++j) { |
| 975 | const string& output = border_outputs.at(j); |
| 976 | const TensorId tid = ParseTensorName(output); |
| 977 | const string output_name(tid.first); |
| 978 | Node* src_node = edge->src(); |
| 979 | if (src_node != nullptr && src_node->name() == output_name && |
| 980 | edge->src_output() == tid.second) { |
| 981 | // Source node is replaced by new fused node. |
| 982 | Node* dst_node = edge->dst(); |
| 983 | const int dst_input = edge->dst_input(); |
| 984 | LOG(INFO) << "Removing existing edge to " << edge->dst()->name() |
| 985 | << " from " << edge->src()->name(); |
| 986 | graph.RemoveEdge(edge); |
| 987 | graph.AddEdge(fused_node, j, dst_node, dst_input); |
| 988 | } |
| 989 | } |
| 990 | } |
| 991 | } |
| 992 | |
| 993 | // Replace output nodes by identity nodes which forward outputs from |
| 994 | // RemoteFusedGraphExecuteOpNode |
| 995 | for (const string& output : outputs) { |
| 996 | const TensorId output_tid = ParseTensorName(output); |
| 997 | const string output_name(output_tid.first); |
| 998 | for (size_t i = 0; i < border_outputs.size(); ++i) { |
| 999 | const TensorId subgraph_output_tid = |
nothing calls this directly
no test coverage detected