1/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#include <stddef.h>
17#include <stdlib.h>
18
19#include <cstdint>
20#include <functional>
21#include <memory>
22#include <utility>
23#include <vector>
24
25#include "ruy/denormal.h" // from @ruy
26#include "tensorflow/lite/allocation.h"
27#include "tensorflow/lite/c/c_api_types.h"
28#include "tensorflow/lite/c/common.h"
29#include "tensorflow/lite/c/common_internal.h"
30#include "tensorflow/lite/core/api/error_reporter.h"
31#include "tensorflow/lite/core/api/profiler.h"
32#include "tensorflow/lite/core/subgraph.h"
33#include "tensorflow/lite/external_cpu_backend_context.h"
34#include "tensorflow/lite/interpreter.h"
35#include "tensorflow/lite/minimal_logging.h"
36#include "tensorflow/lite/stderr_reporter.h"
37#include "tensorflow/lite/util.h"
38
39namespace tflite {
40
41TfLiteStatus Interpreter::SetCustomAllocationForTensor(
42 int tensor_index, const TfLiteCustomAllocation& allocation, int64_t flags) {
43 return primary_subgraph().SetCustomAllocationForTensor(tensor_index,
44 allocation, flags);
45}
46
47TfLiteStatus Interpreter::ReleaseNonPersistentMemory() {
48 // TODO(b/138790287): We could do this for all subgraphs whose tensors have
49 // been allocated. However, AllocateTensors() relies on Control Flow ops to
50 // allocate tensors on 'children' subgraphs. Revisit this if required.
51 return primary_subgraph().ReleaseNonPersistentMemory();
52}
53
54TfLiteStatus Interpreter::ResetVariableTensors() {
55 for (auto& subgraph : subgraphs_) {
56 TF_LITE_ENSURE_STATUS(subgraph->ResetVariableTensors());
57 }
58 return kTfLiteOk;
59}
60
61void Interpreter::SetAllowFp16PrecisionForFp32(bool allow) {
62 for (auto& subgraph : subgraphs_) {
63 subgraph->context()->allow_fp32_relax_to_fp16 = allow;
64 }
65}
66
67// TODO(b/121264966): Subgraphs added after cancellation is set will not get the
68// cancellation function added to their context.
69void Interpreter::SetCancellationFunction(void* data,
70 bool (*check_cancelled_func)(void*)) {
71 for (auto& subgraph : subgraphs_) {
72 subgraph->SetCancellationFunction(data, check_cancelled_func);
73 }
74}
75
76bool Interpreter::IsCancelled() { return primary_subgraph().IsCancelled(); }
77
78TfLiteStatus Interpreter::ModifyGraphWithDelegate(TfLiteDelegate* delegate) {
79 return ModifyGraphWithDelegateImpl(delegate);
80}
81
82bool Interpreter::HasDelegates() { return primary_subgraph().HasDelegates(); }
83
84TfLiteStatus Interpreter::SetBufferHandle(int tensor_index,
85 TfLiteBufferHandle buffer_handle,
86 TfLiteDelegate* delegate) {
87 TF_LITE_ENSURE(context_, tensor_index < tensors_size());
88 TfLiteTensor* tensor = primary_subgraph().tensor(tensor_index);
89
90 TF_LITE_ENSURE(context_,
91 tensor->delegate == nullptr || tensor->delegate == delegate);
92 tensor->delegate = delegate;
93 if (tensor->buffer_handle != kTfLiteNullBufferHandle) {
94 TF_LITE_ENSURE_STATUS(TfLiteDelegateFreeBufferHandleInternal(
95 context_, tensor->delegate, &(tensor->buffer_handle)));
96 }
97 tensor->buffer_handle = buffer_handle;
98
99 return kTfLiteOk;
100}
101
102TfLiteStatus Interpreter::GetBufferHandle(int tensor_index,
103 TfLiteBufferHandle* buffer_handle,
104 TfLiteDelegate** delegate) {
105 TF_LITE_ENSURE(context_, tensor_index < tensors_size());
106 TfLiteTensor* tensor = primary_subgraph().tensor(tensor_index);
107
108 *delegate = tensor->delegate;
109 *buffer_handle = tensor->buffer_handle;
110
111 return kTfLiteOk;
112}
113
114void Interpreter::SetProfiler(Profiler* profiler) {
115 if (profiler == nullptr) {
116 root_profiler_ = nullptr;
117 return;
118 }
119 if (root_profiler_ != nullptr) root_profiler_->RemoveChildProfilers();
120 AddProfiler(profiler);
121}
122
123void Interpreter::SetProfiler(std::unique_ptr<Profiler> profiler) {
124 SetProfilerImpl(std::move(profiler));
125}
126
127void Interpreter::AddProfiler(Profiler* profiler) {
128 if (profiler == nullptr) return;
129 if (root_profiler_ == nullptr) {
130 root_profiler_ = std::make_unique<profiling::RootProfiler>();
131 }
132 root_profiler_->AddProfiler(profiler);
133 SetSubgraphProfiler();
134}
135
136Profiler* Interpreter::GetProfiler() {
137 return primary_subgraph().GetProfiler();
138}
139
140TfLiteStatus Interpreter::ApplyOptions(InterpreterOptions* options) {
141 return ApplyOptionsImpl(options);
142}
143
144SignatureRunner* Interpreter::GetSignatureRunner(const char* signature_key) {
145 auto iter = signature_runner_map_.find(signature_key);
146 if (iter != signature_runner_map_.end()) {
147 return &(iter->second);
148 }
149
150 // Default delegates are applied once for all subgraphs. Only returns error
151 // when the status is kTfLiteError. For other statuses, it will fall back to
152 // the default implementation.
153 if (ApplyLazyDelegateProviders() == kTfLiteError) {
154 return nullptr;
155 }
156
157 for (const auto& signature : signature_defs_) {
158 if (signature.signature_key == signature_key) {
159 auto status = signature_runner_map_.insert(
160 {signature_key,
161 SignatureRunner(&signature, subgraph(signature.subgraph_index))});
162 return &(status.first->second);
163 }
164 }
165 return nullptr;
166}
167
168} // namespace tflite
169