| 29 | |
| 30 | template <typename GraphViewT> |
| 31 | inline Status FrameView::InferFromGraphViewT(const GraphViewT& graph_view) { |
| 32 | if (is_inferred_) { |
| 33 | return errors::Internal("FrameView was already inferred from the graph"); |
| 34 | } |
| 35 | is_inferred_ = true; |
| 36 | |
| 37 | std::deque<int> ready_node_indices; |
| 38 | |
| 39 | // All nodes without inputs are automatically added to the ready queue. |
| 40 | for (const auto& node : graph_view.GetNodes()) { |
| 41 | if (node.NumRegularFanins() + node.NumControllingFanins() == 0) { |
| 42 | ready_node_indices.push_back(node.node_index()); |
| 43 | node_to_frames_[node.node()] = node_has_no_frames_; |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | const auto* graph = graph_view.graph(); |
| 48 | |
| 49 | // We assign unique int id to each frame, and use this map to track what |
| 50 | // frames we've already seen in the graph. |
| 51 | absl::flat_hash_map<string, int> frame_name_to_id; |
| 52 | |
| 53 | auto process_fanout = [this, graph]( |
| 54 | absl::flat_hash_map<string, int>* frame_name_to_id, |
| 55 | std::deque<int>* ready_node_indices, |
| 56 | const NodeDef* ready_node, int fanout_node_index) { |
| 57 | const NodeDef* fanout_node = &graph->node(fanout_node_index); |
| 58 | if (!node_to_frames_.contains(fanout_node)) { |
| 59 | // If we have never seen this node before, we add all frames from the |
| 60 | // incoming node (and pop/push frames if coming from Exit/Enter nodes). |
| 61 | std::vector<int> frame_ids = node_to_frames_[ready_node]; |
| 62 | |
| 63 | if (IsExit(*ready_node)) { |
| 64 | frame_ids.pop_back(); |
| 65 | } |
| 66 | |
| 67 | if (IsEnter(*fanout_node)) { |
| 68 | const AttrValue* frame_name_attr = |
| 69 | AttrSlice(*fanout_node).Find("frame_name"); |
| 70 | |
| 71 | if (!frame_name_attr) { |
| 72 | return errors::InvalidArgument( |
| 73 | "Missing frame name for the Enter node: ", |
| 74 | SummarizeNodeDef(*fanout_node)); |
| 75 | } |
| 76 | |
| 77 | const string& frame_name = frame_name_attr->s(); |
| 78 | int frame_id; |
| 79 | |
| 80 | if (frame_name_to_id->contains(frame_name)) { |
| 81 | frame_id = (*frame_name_to_id)[frame_name]; |
| 82 | } else { |
| 83 | frame_id = static_cast<int>(frame_name_to_id->size()); |
| 84 | (*frame_name_to_id)[frame_name] = frame_id; |
| 85 | } |
| 86 | |
| 87 | frame_ids.push_back(frame_id); |
| 88 | } |
nothing calls this directly
no test coverage detected