Builds the XLA computation. - `args` is the list of input arguments - `retvals` is the list of retvals produced by _Retval operators, in index order. - `arg_shardings` and `retval_shardings` are mapping from arg/return indices to sharding. - If `return_updated_values_for_all_resources` is true, all resources will be included in `resource_updates`, regardless of whether their value changed. - Sets
| 153 | // resource variable argument to the computation to be updated, and `type` is |
| 154 | // the type of the final output. |
| 155 | Status BuildComputation( |
| 156 | const std::vector<XlaCompiler::Argument>& args, |
| 157 | const std::vector<XlaExpression>& retvals, |
| 158 | const std::map<int, xla::OpSharding>& arg_shardings, |
| 159 | const std::map<int, xla::OpSharding>& retval_shardings, |
| 160 | const std::vector<std::unique_ptr<XlaResource>>& resources, |
| 161 | std::unique_ptr<xla::XlaOp> token_output, |
| 162 | const XlaCompiler::ShapeRepresentationFn& shape_representation_fn, |
| 163 | bool return_updated_values_for_all_resources, bool always_return_tuple, |
| 164 | xla::XlaBuilder* builder, xla::XlaComputation* computation, |
| 165 | int* num_computation_outputs, int* num_nonconst_outputs, |
| 166 | std::vector<XlaCompiler::OutputDescription>* outputs, |
| 167 | std::vector<XlaCompiler::ResourceUpdate>* resource_updates, |
| 168 | xla::Shape* output_shape) { |
| 169 | // Attach a common operator name as metadata. This has no semantic effect — it |
| 170 | // merely makes the HLO graph more readable when visualized via TensorBoard, |
| 171 | // since TensorBoard forms groups out of operators with similar names. |
| 172 | xla::OpMetadata retval_metadata; |
| 173 | retval_metadata.set_op_name("XLA_Retvals"); |
| 174 | builder->SetOpMetadata(retval_metadata); |
| 175 | VLOG(1) << "Building new computation"; |
| 176 | auto cleanup = gtl::MakeCleanup([builder]() { builder->ClearOpMetadata(); }); |
| 177 | |
| 178 | // Builds a no-op XLA computation. We need to set the sharding of outputs, but |
| 179 | // cannot change the sharding of the existing output op. To do this, we build |
| 180 | // a new identity op to which shardings can be applied. |
| 181 | auto identity_op = [builder](xla::XlaOp op) { |
| 182 | return xla::GetTupleElement(xla::Tuple(builder, {op}), 0); |
| 183 | }; |
| 184 | |
| 185 | std::vector<xla::XlaOp> elems; |
| 186 | elems.reserve(retvals.size()); |
| 187 | |
| 188 | // Keeps track of the layout of each retval. If a retval is not in this list, |
| 189 | // a descending layout is used. The first element is the output index, second |
| 190 | // element is the new layout. |
| 191 | std::vector<std::pair<int64, xla::Layout>> retval_index_and_layout; |
| 192 | for (int i = 0; i < retvals.size(); ++i) { |
| 193 | XlaCompiler::OutputDescription& output = (*outputs)[i]; |
| 194 | const XlaExpression& retval = retvals[i]; |
| 195 | output.type = retval.dtype(); |
| 196 | switch (retval.kind()) { |
| 197 | case XlaExpression::Kind::kConstant: |
| 198 | output.is_constant = true; |
| 199 | output.constant_value = retval.constant_value(); |
| 200 | output.shape = output.constant_value.shape(); |
| 201 | break; |
| 202 | |
| 203 | case XlaExpression::Kind::kTensorList: { |
| 204 | output.is_tensor_list = true; |
| 205 | xla::XlaOp value = retval.handle(); |
| 206 | elems.push_back(value); |
| 207 | break; |
| 208 | } |
| 209 | |
| 210 | case XlaExpression::Kind::kXlaOp: { |
| 211 | output.is_constant = false; |
| 212 | TF_ASSIGN_OR_RETURN(output.shape, retval.GetShape()); |
no test coverage detected