tensorflow/c/eager/unified_api_testutil.cc
// Runs `model` maybe wrapped in a function.
Runs `model` maybe wrapped in a function.
Runs ` model ` maybe wrapped in a function .
Status RunModel(Model model, AbstractContext* ctx,
                absl::Span<AbstractTensorHandle* const> inputs,
                absl::Span<AbstractTensorHandle*> outputs, bool use_function) {
  if (use_function) {
    const char* fn_name = "test_fn";
    core::RefCountPtr<AbstractFunction> scoped_func;
    absl::flat_hash_set<int> null_indices;
    {
      AbstractContextPtr func_ctx(BuildFunction(fn_name));
      std::vector<AbstractTensorHandle*> func_inputs;
      func_inputs.reserve(inputs.size());
      TF_RETURN_IF_ERROR(
          CreateParamsForInputs(func_ctx.get(), inputs, &func_inputs));
      std::vector<AbstractTensorHandle*> model_outputs;
      model_outputs.resize(outputs.size());
      TF_RETURN_IF_ERROR(model(func_ctx.get(), absl::MakeSpan(func_inputs),
                               absl::MakeSpan(model_outputs)));
      for (auto func_input : func_inputs) {
        func_input->Unref();
      }
      AbstractFunction* func = nullptr;
      OutputList output_list;
      output_list.expected_num_outputs = 0;
      output_list.outputs.reserve(outputs.size());
      for (int i = 0; i < model_outputs.size(); i++) {
        if (model_outputs[i]) {
          output_list.outputs.emplace_back(model_outputs[i]);
          output_list.expected_num_outputs += 1;
        } else {
          null_indices.insert(i);
        }
      }
      TF_RETURN_IF_ERROR(dyn_cast<tracing::TracingContext>(func_ctx.get())
                             ->Finalize(&output_list, &func));
      scoped_func.reset(func);
      for (auto output : output_list.outputs) {
        output->Unref();
      }
      TF_RETURN_IF_ERROR(ctx->RegisterFunction(func));
    }
    AbstractOperationPtr fn_op(ctx->CreateOperation());
    TF_RETURN_IF_ERROR(fn_op->Reset(fn_name, nullptr));
    for (auto input : inputs) {
      TF_RETURN_IF_ERROR(fn_op->AddInput(input));
    }
    int retvals = outputs.size() - null_indices.size();
    std::vector<AbstractTensorHandle*> fn_outputs(retvals);
    TF_RETURN_IF_ERROR(fn_op->Execute(
        absl::Span<AbstractTensorHandle*>(fn_outputs.data(), fn_outputs.size()),
        &retvals));
    int skipped_indices = 0;
    for (int i = 0; i < outputs.size(); i++) {
      if (!null_indices.contains(i)) {
        outputs[i] = fn_outputs[i - skipped_indices];
      } else {
        skipped_indices += 1;
      }
    }
    TF_RETURN_IF_ERROR(ctx->RemoveFunction(fn_name));
    return Status::OK();
  } else {
    return model(ctx, inputs, outputs);
  }
}
Status RunModel ( Model model , AbstractContext * ctx , absl :: Span < AbstractTensorHandle * const > inputs , absl :: Span < AbstractTensorHandle * > outputs , bool use_function ) { if ( use_function ) { const char * fn_name = " " ; core :: RefCountPtr < AbstractFunction > scoped_func ; absl :: flat_hash_set < int > null_indices ; { AbstractContextPtr func_ctx ( BuildFunction ( fn_name ) ) ; std :: vector < AbstractTensorHandle * > func_inputs ; func_inputs . reserve ( inputs . size ( ) ) ; TF_RETURN_IF_ERROR ( CreateParamsForInputs ( func_ctx . get ( ) , inputs , & func_inputs ) ) ; std :: vector < AbstractTensorHandle * > model_outputs ; model_outputs . resize ( outputs . size ( ) ) ; TF_RETURN_IF_ERROR ( model ( func_ctx . get ( ) , absl :: MakeSpan ( func_inputs ) , absl :: MakeSpan ( model_outputs ) ) ) ; for ( auto func_input : func_inputs ) { func_input -> Unref ( ) ; } AbstractFunction * func = nullptr ; OutputList output_list ; output_list . expected_num_outputs = 0 ; output_list . outputs . reserve ( outputs . size ( ) ) ; for ( int i = 0 ; i < model_outputs . size ( ) ; i ++ ) { if ( model_outputs [ i ] ) { output_list . outputs . emplace_back ( model_outputs [ i ] ) ; output_list . expected_num_outputs += 1 ; } else { null_indices . insert ( i ) ; } } TF_RETURN_IF_ERROR ( dyn_cast < tracing :: TracingContext > ( func_ctx . get ( ) ) -> Finalize ( & output_list , & func ) ) ; scoped_func . reset ( func ) ; for ( auto output : output_list . outputs ) { output -> Unref ( ) ; } TF_RETURN_IF_ERROR ( ctx -> RegisterFunction ( func ) ) ; } AbstractOperationPtr fn_op ( ctx -> CreateOperation ( ) ) ; TF_RETURN_IF_ERROR ( fn_op -> Reset ( fn_name , nullptr ) ) ; for ( auto input : inputs ) { TF_RETURN_IF_ERROR ( fn_op -> AddInput ( input ) ) ; } int retvals = outputs . size ( ) - null_indices . size ( ) ; std :: vector < AbstractTensorHandle * > fn_outputs ( retvals ) ; TF_RETURN_IF_ERROR ( fn_op -> Execute ( absl :: Span < AbstractTensorHandle * > ( fn_outputs . data ( ) , fn_outputs . size ( ) ) , & retvals ) ) ; int skipped_indices = 0 ; for ( int i = 0 ; i < outputs . size ( ) ; i ++ ) { if ( ! null_indices . contains ( i ) ) { outputs [ i ] = fn_outputs [ i - skipped_indices ] ; } else { skipped_indices += 1 ; } } TF_RETURN_IF_ERROR ( ctx -> RemoveFunction ( fn_name ) ) ; return Status :: OK ( ) ; } else { return model ( ctx , inputs , outputs ) ; } }
Runs `model` maybe wrapped in a function.
Runs ` model ` maybe wrapped in a function .
// Returning null tensors from a tf.function is not supported, so we keep // track of indices in the model's outputs are nullptr in this set. // The FunctionDef only outputs the non-null tensors. We later pad the // function op outputs to have nullptrs at the `null_indices`. /*raw_device_name=*/