Creates the condition subgraph defined by `cond`.
| 89 | |
| 90 | // Creates the condition subgraph defined by `cond`. |
| 91 | Status CreateCond(const Scope& scope, const CondGraphBuilderFn& cond, |
| 92 | const std::vector<Output>& inputs, Output* output) { |
| 93 | // The control dependency is for constants in the cond graph, and other ops |
| 94 | // that do not depend on the loop variables. This ensures that these ops are |
| 95 | // in the while loop frame (since they will indirectly depend on an Enter node |
| 96 | // defining the frame) and that they are executed once per loop iteration. |
| 97 | // |
| 98 | // TODO(skyewm): the control dep will be added to all nodes in the cond graph. |
| 99 | // This is at best unnecessary, and at worst may prevent different parts of |
| 100 | // different loop iterations from executing in parallel. |
| 101 | Scope cond_scope = |
| 102 | scope.NewSubScope("cond").WithControlDependencies(inputs[0]); |
| 103 | Output raw_cond_out; |
| 104 | TF_RETURN_IF_ERROR(cond(cond_scope, inputs, &raw_cond_out)); |
| 105 | |
| 106 | TF_RETURN_IF_ERROR(scope.graph()->IsValidOutputTensor(raw_cond_out.node(), |
| 107 | raw_cond_out.index())); |
| 108 | if (raw_cond_out.type() != DT_BOOL) { |
| 109 | return errors::InvalidArgument( |
| 110 | "BuildWhileLoop: 'cond' argument must return a boolean output, got ", |
| 111 | DataTypeString(raw_cond_out.type())); |
| 112 | } |
| 113 | // TODO(skyewm): check that raw_cond_out is scalar |
| 114 | |
| 115 | *output = LoopCond(scope, raw_cond_out).output; |
| 116 | return Status::OK(); |
| 117 | } |
| 118 | |
| 119 | // Create the body subgraph defined by `body`. `outputs` must be non-null and |
| 120 | // empty. |
no test coverage detected