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

Function BuildWhileLoop

tensorflow/cc/ops/while_loop.cc:172–247  ·  view source on GitHub ↗

A while loop with a single loop variable looks like this: (output) ^ +---------------+ | | body subgraph +-------------+ Exit +---------------+ | ^ ^ | | | | Switch<--------+ v ^ | NextIteration | +------+--------+ | +---->| cond subgraph | | | +----------

Source from the content-addressed store, hash-verified

170// duplicated for each loop variable.
171// TODO(skyewm): link to public version of design doc
172Status BuildWhileLoop(const Scope& scope, const std::vector<Output>& inputs,
173 const CondGraphBuilderFn& cond,
174 const BodyGraphBuilderFn& body, const string& frame_name,
175 OutputList* outputs, bool create_while_ctx,
176 Output* cond_output) {
177 DCHECK(!inputs.empty());
178 DCHECK(outputs != nullptr);
179 DCHECK(outputs->empty());
180
181 TF_RETURN_IF_ERROR(scope.status());
182 const size_t num_loop_vars = inputs.size();
183
184 std::vector<Output> enter_outputs(num_loop_vars);
185 for (int i = 0; i < num_loop_vars; ++i) {
186 enter_outputs[i] = internal::Enter(scope, inputs[i], frame_name);
187 }
188 TF_RETURN_IF_ERROR(scope.status());
189
190 std::vector<Output> merge_outputs(num_loop_vars);
191 for (int i = 0; i < num_loop_vars; ++i) {
192 TF_RETURN_IF_ERROR(
193 CreateMerge(scope, i, enter_outputs[i], &merge_outputs[i]));
194 }
195
196 Output cond_out;
197 TF_RETURN_IF_ERROR(CreateCond(scope, cond, merge_outputs, &cond_out));
198 if (cond_output != nullptr) *cond_output = cond_out;
199
200 std::vector<Output> switch_trues(num_loop_vars);
201 std::vector<Output> switch_falses(num_loop_vars);
202 for (int i = 0; i < num_loop_vars; ++i) {
203 auto switch_i = Switch(scope, merge_outputs[i], cond_out);
204 switch_trues[i] = switch_i.output_true;
205 switch_falses[i] = switch_i.output_false;
206 }
207 TF_RETURN_IF_ERROR(scope.status());
208
209 std::vector<Output> body_outputs;
210 TF_RETURN_IF_ERROR(CreateBody(scope, body, switch_trues, &body_outputs));
211
212 std::vector<Output> next_outputs(num_loop_vars);
213 for (int i = 0; i < num_loop_vars; ++i) {
214 next_outputs[i] = NextIteration(scope, body_outputs[i]);
215 DCHECK_EQ(next_outputs[i].node()->name(), NextIterationName(scope, i));
216 }
217 TF_RETURN_IF_ERROR(scope.status());
218
219 // Create the backedges from the NextIteration nodes to the Merge nodes.
220 for (int i = 0; i < num_loop_vars; ++i) {
221 const int merge_backedge_output_index = 1;
222 scope.graph()->AddEdge(next_outputs[i].node(), next_outputs[i].index(),
223 merge_outputs[i].node(),
224 merge_backedge_output_index);
225 }
226
227 outputs->resize(num_loop_vars);
228 for (int i = 0; i < num_loop_vars; ++i) {
229 (*outputs)[i] = internal::Exit(scope, switch_falses[i]);

Callers 9

NestedLoopBodyFunction · 0.85
TESTFunction · 0.85
TEST_FFunction · 0.85
TF_FinishWhileHelperFunction · 0.85
CreateLoopMethod · 0.85
AddForwardLoopCounterFunction · 0.85
AddBackPropLoopCounterFunction · 0.85
AddWhileGradientLoopFunction · 0.85
CreateLoopMethod · 0.85

Calls 15

CreateMergeFunction · 0.85
CreateCondFunction · 0.85
CreateBodyFunction · 0.85
NextIterationFunction · 0.85
NextIterationNameFunction · 0.85
ToNodesFunction · 0.85
ToOutputTensorFunction · 0.85
ToOutputTensorsFunction · 0.85
set_while_ctxMethod · 0.80
nameMethod · 0.65
EnterFunction · 0.50
SwitchFunction · 0.50

Tested by 5

NestedLoopBodyFunction · 0.68
TESTFunction · 0.68
TEST_FFunction · 0.68
CreateLoopMethod · 0.68
CreateLoopMethod · 0.68