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