blob: dc495be5c31d3238901b34bfc2f6457eb68033be [file] [log] [blame]
Teresa Charlin83b42912022-07-07 14:24:59 +01001//
2// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "TfliteExecutor.hpp"
7
8TfLiteExecutor::TfLiteExecutor(const ExecuteNetworkParams& params) : m_Params(params)
9{
10 std::unique_ptr<tflite::FlatBufferModel> model =
11 tflite::FlatBufferModel::BuildFromFile(m_Params.m_ModelPath.c_str());
12
13 m_TfLiteInterpreter = std::make_unique<Interpreter>();
14 tflite::ops::builtin::BuiltinOpResolver resolver;
15
16 tflite::InterpreterBuilder builder(*model, resolver);
17 builder(&m_TfLiteInterpreter);
18 m_TfLiteInterpreter->AllocateTensors();
19
20 int status = kTfLiteError;
21 if (m_Params.m_TfLiteExecutor == ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteDelegate)
22 {
23 // Create the Armnn Delegate
24 // Populate a DelegateOptions from the ExecuteNetworkParams.
25 armnnDelegate::DelegateOptions delegateOptions = m_Params.ToDelegateOptions();
26 delegateOptions.SetExternalProfilingParams(delegateOptions.GetExternalProfilingParams());
27
28 std::unique_ptr<TfLiteDelegate, decltype(&armnnDelegate::TfLiteArmnnDelegateDelete)>
29 theArmnnDelegate(armnnDelegate::TfLiteArmnnDelegateCreate(delegateOptions),
30 armnnDelegate::TfLiteArmnnDelegateDelete);
31 // Register armnn_delegate to TfLiteInterpreter
32 status = m_TfLiteInterpreter->ModifyGraphWithDelegate(std::move(theArmnnDelegate));
33 if (status == kTfLiteError)
34 {
35 LogAndThrow("Could not register ArmNN TfLite Delegate to TfLiteInterpreter");
36 }
37 }
38 else
39 {
40 std::cout << "Running on TfLite without ArmNN delegate\n";
41 }
42
43 armnn::Optional<std::string> dataFile = m_Params.m_GenerateTensorData
44 ? armnn::EmptyOptional()
45 : armnn::MakeOptional<std::string>(m_Params.m_InputTensorDataFilePaths[0]);
46
47 const size_t numInputs = m_Params.m_InputNames.size();
48
49 for(unsigned int inputIndex = 0; inputIndex < numInputs; ++inputIndex)
50 {
51 int input = m_TfLiteInterpreter->inputs()[inputIndex];
52
53 TfLiteIntArray* inputDims = m_TfLiteInterpreter->tensor(input)->dims;
54
55 unsigned int inputSize = 1;
56 for (unsigned int dim = 0; dim < static_cast<unsigned int>(inputDims->size); ++dim)
57 {
58 inputSize *= inputDims->data[dim];
59 }
60
61 const auto& inputName = m_TfLiteInterpreter->input_tensor(input)->name;
62 const auto& dataType = m_TfLiteInterpreter->input_tensor(input)->type;
63
64 switch (dataType)
65 {
66 case kTfLiteFloat32:
67 {
68 auto inputData = m_TfLiteInterpreter->typed_tensor<float>(input);
69 PopulateTensorWithData(inputData, inputSize, dataFile, inputName);
70 break;
71 }
72 case kTfLiteInt32:
73 {
74 auto inputData = m_TfLiteInterpreter->typed_tensor<int>(input);
75 PopulateTensorWithData(inputData, inputSize, dataFile, inputName);
76 break;
77 }
78 case kTfLiteUInt8:
79 {
80 auto inputData = m_TfLiteInterpreter->typed_tensor<uint8_t>(input);
81 PopulateTensorWithData(inputData, inputSize, dataFile, inputName);
82 break;
83 }
84 case kTfLiteInt16:
85 {
86 auto inputData = m_TfLiteInterpreter->typed_tensor<int16_t>(input);
87 PopulateTensorWithData(inputData, inputSize, dataFile, inputName);
88 break;
89 }
90 case kTfLiteInt8:
91 {
92 auto inputData = m_TfLiteInterpreter->typed_tensor<int8_t>(input);
93 PopulateTensorWithData(inputData, inputSize, dataFile, inputName);
94 break;
95 }
96 default:
97 {
98 LogAndThrow("Unsupported input tensor data type");
99 }
100 }
101 }
102}
103
104std::vector<const void *> TfLiteExecutor::Execute()
105{
106 int status = 0;
107 std::vector<const void*> results;
108 for (size_t x = 0; x < m_Params.m_Iterations; x++)
109 {
110 // Start timer to record inference time in milliseconds.
111 const auto start_time = armnn::GetTimeNow();
112 // Run the inference
113 status = m_TfLiteInterpreter->Invoke();
114 const auto duration = armnn::GetTimeDuration(start_time);
115
116 if (m_Params.m_DontPrintOutputs || m_Params.m_ReuseBuffers)
117 {
118 break;
119 }
120 // Print out the output
121 for (unsigned int outputIndex = 0; outputIndex < m_TfLiteInterpreter->outputs().size(); ++outputIndex)
122 {
123 auto tfLiteDelegateOutputId = m_TfLiteInterpreter->outputs()[outputIndex];
124 TfLiteIntArray* outputDims = m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->dims;
125 // If we've been asked to write to a file then set a file output stream. Otherwise use stdout.
126 FILE* outputTensorFile = stdout;
127 if (!m_Params.m_OutputTensorFiles.empty())
128 {
129 outputTensorFile = fopen(m_Params.m_OutputTensorFiles[outputIndex].c_str(), "w");
130 if (outputTensorFile == NULL)
131 {
132 LogAndThrow("Specified output tensor file, \"" + m_Params.m_OutputTensorFiles[outputIndex] +
133 "\", cannot be created. Defaulting to stdout. Error was: " + std::strerror(errno));
134 }
135 else
136 {
137 ARMNN_LOG(info) << "Writing output " << outputIndex << "' of iteration: " << x+1 << " to file: '"
138 << m_Params.m_OutputTensorFiles[outputIndex] << "'";
139 }
140 }
141 long outputSize = 1;
142 for (unsigned int dim = 0; dim < static_cast<unsigned int>(outputDims->size); ++dim)
143 {
144 outputSize *= outputDims->data[dim];
145 }
146
147 std::cout << m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->name << ": ";
148 results.push_back(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation);
149
150 switch (m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->type)
151 {
152
153 case kTfLiteFloat32:
154 {
155 auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<float>(tfLiteDelegateOutputId);
156
157 for (int i = 0; i < outputSize; ++i)
158 {
159 fprintf(outputTensorFile, "%f ", tfLiteDelageOutputData[i]);
160 }
161 break;
162 }
163 case kTfLiteInt32:
164 {
165 auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<int32_t>(tfLiteDelegateOutputId);
166 for (int i = 0; i < outputSize; ++i)
167 {
168 fprintf(outputTensorFile, "%d ", tfLiteDelageOutputData[i]);
169 }
170 break;
171 }
172 case kTfLiteUInt8:
173 {
174 auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<uint8_t>(tfLiteDelegateOutputId);
175 for (int i = 0; i < outputSize; ++i)
176 {
177 fprintf(outputTensorFile, "%u ", tfLiteDelageOutputData[i]);
178 }
179 break;
180 }
181 case kTfLiteInt8:
182 {
183 auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<int8_t>(tfLiteDelegateOutputId);
184 for (int i = 0; i < outputSize; ++i)
185 {
186 fprintf(outputTensorFile, "%d ", tfLiteDelageOutputData[i]);
187 }
188 break;
189 }
190 default:
191 {
192 LogAndThrow("Unsupported output type");
193 }
194 }
195
196 std::cout << std::endl;
197 }
198 CheckInferenceTimeThreshold(duration, m_Params.m_ThresholdTime);
199 }
200
201 std::cout << status;
202 return results;
203}
204
205void TfLiteExecutor::CompareAndPrintResult(std::vector<const void*> otherOutput)
206{
207 for (unsigned int outputIndex = 0; outputIndex < m_TfLiteInterpreter->outputs().size(); ++outputIndex)
208 {
209 auto tfLiteDelegateOutputId = m_TfLiteInterpreter->outputs()[outputIndex];
210 float result = 0;
211 switch (m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->type)
212 {
213 case kTfLiteFloat32:
214 {
215 result = ComputeRMSE<float>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation,
216 otherOutput[outputIndex],
217 m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes);
218
219 break;
220 }
221 case kTfLiteInt32:
222 {
223 result = ComputeRMSE<int32_t>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation,
224 otherOutput[outputIndex],
225 m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes);
226 break;
227 }
228 case kTfLiteUInt8:
229 {
230 result = ComputeRMSE<uint8_t>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation,
231 otherOutput[outputIndex],
232 m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes);
233 break;
234 }
235 case kTfLiteInt8:
236 {
237 result = ComputeRMSE<int8_t>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation,
238 otherOutput[outputIndex],
239 m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes);
240 break;
241 }
242 default:
243 {
244 }
245 }
246
247 std::cout << "RMSE of "
248 << m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->name
249 << ": " << result << std::endl;
250 }
251};