TODO(suharshs): Merge with CheckFetches in DirectSession. TODO(suharsh,mrry): Build a map from fetch target to set of feeds it depends on once at setup time to prevent us from computing the dependencies everytime.
| 1010 | // on once at setup time to prevent us from computing the dependencies |
| 1011 | // everytime. |
| 1012 | Status MasterSession::ReffedClientGraph::CheckFetches( |
| 1013 | const RunStepRequestWrapper& req, const RunState* run_state, |
| 1014 | GraphExecutionState* execution_state) { |
| 1015 | // Build the set of pending feeds that we haven't seen. |
| 1016 | std::unordered_set<TensorId, TensorId::Hasher> pending_feeds; |
| 1017 | for (const auto& input : run_state->pending_inputs) { |
| 1018 | // Skip if already fed. |
| 1019 | if (input.second) continue; |
| 1020 | TensorId id(ParseTensorName(input.first)); |
| 1021 | const Node* n = execution_state->get_node_by_name(string(id.first)); |
| 1022 | if (n == nullptr) { |
| 1023 | return errors::NotFound("Feed ", input.first, ": not found"); |
| 1024 | } |
| 1025 | pending_feeds.insert(id); |
| 1026 | } |
| 1027 | for (size_t i = 0; i < req.num_feeds(); ++i) { |
| 1028 | const TensorId id(ParseTensorName(req.feed_name(i))); |
| 1029 | pending_feeds.erase(id); |
| 1030 | } |
| 1031 | |
| 1032 | // Initialize the stack with the fetch nodes. |
| 1033 | std::vector<const Node*> stack; |
| 1034 | for (size_t i = 0; i < req.num_fetches(); ++i) { |
| 1035 | const string& fetch = req.fetch_name(i); |
| 1036 | const TensorId id(ParseTensorName(fetch)); |
| 1037 | const Node* n = execution_state->get_node_by_name(string(id.first)); |
| 1038 | if (n == nullptr) { |
| 1039 | return errors::NotFound("Fetch ", fetch, ": not found"); |
| 1040 | } |
| 1041 | stack.push_back(n); |
| 1042 | } |
| 1043 | |
| 1044 | // Any tensor needed for fetches can't be in pending_feeds. |
| 1045 | // We need to use the original full graph from execution state. |
| 1046 | const Graph* graph = execution_state->full_graph(); |
| 1047 | std::vector<bool> visited(graph->num_node_ids(), false); |
| 1048 | while (!stack.empty()) { |
| 1049 | const Node* n = stack.back(); |
| 1050 | stack.pop_back(); |
| 1051 | |
| 1052 | for (const Edge* in_edge : n->in_edges()) { |
| 1053 | const Node* in_node = in_edge->src(); |
| 1054 | if (pending_feeds.count({in_node->name(), in_edge->src_output()}) > 0) { |
| 1055 | return errors::InvalidArgument("Fetch ", in_node->name(), ":", |
| 1056 | in_edge->src_output(), |
| 1057 | " can't be computed from the feeds" |
| 1058 | " that have been fed so far."); |
| 1059 | } |
| 1060 | if (!visited[in_node->id()]) { |
| 1061 | visited[in_node->id()] = true; |
| 1062 | stack.push_back(in_node); |
| 1063 | } |
| 1064 | } |
| 1065 | } |
| 1066 | return Status::OK(); |
| 1067 | } |
| 1068 | |
| 1069 | // Asynchronously deregisters subgraphs on the workers, without waiting for the |
no test coverage detected