MCPcopy Create free account
hub / github.com/DeepRec-AI/DeepRec / AddControlFlow

Function AddControlFlow

tensorflow/core/graph/graph_partition.cc:1041–1188  ·  view source on GitHub ↗

Each participating device needs to decide a) if there is a next iteration, and b) if the loop terminates. We take the approach to encode this control flow logic in the dataflow graph. There are at least two possible encodings. In a completely decentralized encoding, the participants communicate peer to peer. The other encoding uses a frame leader (the participant who owns the pivot termination pre

Source from the content-addressed store, hash-verified

1039// TODO(yuanbyu): The correctness of this construction is rather subtle. I got
1040// it wrong many times so it would be nice to write a proof to be sure.
1041Status AddControlFlow(const PartitionOptions& opts, Graph* g,
1042 GraphInfo* g_info) {
1043 Status status;
1044 GraphDefBuilder::Options bopts(g, &status);
1045 std::vector<ControlFlowInfo>& cf_info = g_info->cf_info;
1046
1047 // Build the control flow info for every node.
1048 status = BuildControlFlowInfo(g, &cf_info);
1049 if (!status.ok()) return status;
1050
1051 OptimizeControlFlowColocation(g);
1052
1053 // The map from frames to their LoopCond nodes.
1054 std::unordered_map<string, Node*> frame_cond_map;
1055 int num_node_ids = g->num_node_ids();
1056 for (int i = 0; i < num_node_ids; ++i) {
1057 Node* node = g->FindNodeId(i);
1058 if (node == nullptr) continue;
1059
1060 if (IsLoopCond(node)) {
1061 const string& frame_name = cf_info[node->id()].frame_name;
1062 DCHECK(!frame_name.empty());
1063 frame_cond_map[frame_name] = node;
1064 }
1065 }
1066
1067 // Add all control loops for cross-device frames.
1068 // A control loop is added only when there is a cross-device edge in a
1069 // non-root frame. Nothing is added if there is no loops. We also don't
1070 // add anything for a frame that is completely local to a device. For
1071 // nested loops, we stack the control loops together by connecting
1072 // the merge of the outer loop to the enter of the inner loop.
1073 //
1074 // A map from <frame_name, device_name> to ControlLoop.
1075 std::unordered_map<string, ControlLoop> control_loops;
1076 int num_edge_ids = g->num_edge_ids();
1077 for (int i = 0; i < num_edge_ids; ++i) {
1078 const Edge* edge = g->FindEdgeId(i);
1079 if (edge == nullptr) continue;
1080
1081 const Node* src = edge->src();
1082 const Node* dst = edge->dst();
1083 // Skip Sink/Source nodes.
1084 if (!src->IsOp() || !dst->IsOp()) continue;
1085
1086 const string& src_device = src->assigned_device_name();
1087 const string& dst_device = dst->assigned_device_name();
1088 // Skip local edges.
1089 if (src_device == dst_device) continue;
1090
1091 const Node* src_frame = OutputFrame(src, cf_info);
1092 const Node* dst_frame = InputFrame(dst, cf_info);
1093 const string& src_frame_name = cf_info[src_frame->id()].frame_name;
1094 const string& dst_frame_name = cf_info[dst_frame->id()].frame_name;
1095 // Skip if src and dst are not in the same frame.
1096 if (src_frame_name.empty() || src_frame_name != dst_frame_name) {
1097 continue;
1098 }

Callers 4

PartitionFunction · 0.85
PartitionWithTensorFuseFunction · 0.85
SplitGraphInternalV2Method · 0.85
SplitGraphInternalMethod · 0.85

Calls 15

BuildControlFlowInfoFunction · 0.85
OutputFrameFunction · 0.85
InputFrameFunction · 0.85
AddControlConstFunction · 0.85
AddControlFlowInfoFunction · 0.85
InvalidArgumentFunction · 0.85
AddControlLoopFunction · 0.85
num_edge_idsMethod · 0.80
FindEdgeIdMethod · 0.80
IsOpMethod · 0.80
IsLoopCondFunction · 0.70

Tested by

no test coverage detected