blob: 8acab71290fc09041b139719681f24b9dd61ae1d [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Sadik Armagana9c2ce12020-07-14 10:02:22 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
telsoa01c577f2c2018-08-31 09:22:23 +01005
Jan Eilers45274902020-10-15 18:34:43 +01006#include "NetworkExecutionUtils/NetworkExecutionUtils.hpp"
7#include "ExecuteNetworkProgramOptions.hpp"
Kevin Mayb4b3ac92021-05-21 16:42:21 +01008#include <armnn/IAsyncExecutionCallback.hpp>
9#include <AsyncExecutionCallback.hpp>
Jan Eilers45274902020-10-15 18:34:43 +010010
11#include <armnn/Logging.hpp>
Rob Hughes9542f902021-07-14 09:48:54 +010012#include <armnnUtils/Filesystem.hpp>
Jan Eilers45274902020-10-15 18:34:43 +010013#include <InferenceTest.hpp>
14
15#if defined(ARMNN_SERIALIZER)
16#include "armnnDeserializer/IDeserializer.hpp"
17#endif
Jan Eilers45274902020-10-15 18:34:43 +010018#if defined(ARMNN_TF_LITE_PARSER)
19#include "armnnTfLiteParser/ITfLiteParser.hpp"
20#endif
21#if defined(ARMNN_ONNX_PARSER)
22#include "armnnOnnxParser/IOnnxParser.hpp"
23#endif
Sadik Armagan5d03e312020-11-17 16:43:56 +000024#if defined(ARMNN_TFLITE_DELEGATE)
25#include <armnn_delegate.hpp>
26#include <DelegateOptions.hpp>
27
28#include <tensorflow/lite/builtin_ops.h>
29#include <tensorflow/lite/c/builtin_op_data.h>
30#include <tensorflow/lite/c/common.h>
31#include <tensorflow/lite/optional_debug_tools.h>
32#include <tensorflow/lite/kernels/builtin_op_kernels.h>
33#include <tensorflow/lite/interpreter.h>
34#include <tensorflow/lite/kernels/register.h>
35#endif
Jan Eilers45274902020-10-15 18:34:43 +010036
37#include <future>
Sadik Armagan5d03e312020-11-17 16:43:56 +000038#if defined(ARMNN_TFLITE_DELEGATE)
39int TfLiteDelegateMainImpl(const ExecuteNetworkParams& params,
40 const std::shared_ptr<armnn::IRuntime>& runtime = nullptr)
41{
42 using namespace tflite;
Jan Eilers45274902020-10-15 18:34:43 +010043
Sadik Armagan5d03e312020-11-17 16:43:56 +000044 std::unique_ptr<tflite::FlatBufferModel> model = tflite::FlatBufferModel::BuildFromFile(params.m_ModelPath.c_str());
45
46 auto tfLiteInterpreter = std::make_unique<Interpreter>();
47 tflite::ops::builtin::BuiltinOpResolver resolver;
48
49 tflite::InterpreterBuilder builder(*model, resolver);
50 builder(&tfLiteInterpreter);
51 tfLiteInterpreter->AllocateTensors();
52
Finn Williamsf806c4d2021-02-22 15:13:12 +000053 int status = 0;
54 if (params.m_TfLiteExecutor == ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteDelegate)
Sadik Armagan19a1c032021-01-20 12:17:00 +000055 {
Finn Williamsf806c4d2021-02-22 15:13:12 +000056 // Create the Armnn Delegate
57 armnnDelegate::DelegateOptions delegateOptions(params.m_ComputeDevices);
58 std::unique_ptr<TfLiteDelegate, decltype(&armnnDelegate::TfLiteArmnnDelegateDelete)>
59 theArmnnDelegate(armnnDelegate::TfLiteArmnnDelegateCreate(delegateOptions),
60 armnnDelegate::TfLiteArmnnDelegateDelete);
61 // Register armnn_delegate to TfLiteInterpreter
62 status = tfLiteInterpreter->ModifyGraphWithDelegate(std::move(theArmnnDelegate));
63 if (status == kTfLiteError)
64 {
65 ARMNN_LOG(fatal) << "Could not register ArmNN TfLite Delegate to TfLiteInterpreter!";
66 return EXIT_FAILURE;
67 }
Sadik Armagan19a1c032021-01-20 12:17:00 +000068 }
Finn Williamsf806c4d2021-02-22 15:13:12 +000069 else
70 {
71 std::cout << "Running on TfLite without ArmNN delegate\n";
72 }
73
Sadik Armagan5d03e312020-11-17 16:43:56 +000074
75 std::vector<std::string> inputBindings;
76 for (const std::string& inputName: params.m_InputNames)
77 {
78 inputBindings.push_back(inputName);
79 }
80
81 armnn::Optional<std::string> dataFile = params.m_GenerateTensorData
82 ? armnn::EmptyOptional()
83 : armnn::MakeOptional<std::string>(params.m_InputTensorDataFilePaths[0]);
84
85 const size_t numInputs = inputBindings.size();
86
87 for(unsigned int inputIndex = 0; inputIndex < numInputs; ++inputIndex)
88 {
89 int input = tfLiteInterpreter->inputs()[inputIndex];
Sadik Armagan15f7fae2020-11-18 09:37:03 +000090 TfLiteIntArray* inputDims = tfLiteInterpreter->tensor(input)->dims;
91
Mike Kelly00e9ebf2021-09-01 17:09:12 +010092 unsigned int inputSize = 1;
93 if (params.m_InputTensorShapes.size() > 0)
Sadik Armagan15f7fae2020-11-18 09:37:03 +000094 {
Mike Kelly00e9ebf2021-09-01 17:09:12 +010095 inputSize = params.m_InputTensorShapes[inputIndex]->GetNumElements();
96 }
97 else
98 {
99 for (unsigned int dim = 0; dim < static_cast<unsigned int>(inputDims->size); ++dim)
100 {
101 inputSize *= inputDims->data[dim];
102 }
Sadik Armagan15f7fae2020-11-18 09:37:03 +0000103 }
104
Sadik Armagan5d03e312020-11-17 16:43:56 +0000105 if (params.m_InputTypes[inputIndex].compare("float") == 0)
106 {
107 auto inputData = tfLiteInterpreter->typed_tensor<float>(input);
Finn Williamsbbbefec2020-11-25 14:32:42 +0000108
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000109 if(inputData == NULL)
Finn Williamsbbbefec2020-11-25 14:32:42 +0000110 {
111 ARMNN_LOG(fatal) << "Input tensor is null, input type: "
112 "\"" << params.m_InputTypes[inputIndex] << "\" may be incorrect.";
113 return EXIT_FAILURE;
114 }
115
Finn Williams56870182020-11-20 13:57:53 +0000116 std::vector<float> tensorData;
117 PopulateTensorWithDataGeneric<float>(tensorData,
Mike Kelly00e9ebf2021-09-01 17:09:12 +0100118 inputSize,
119 dataFile,
120 [](const std::string& s)
121 { return std::stof(s); });
Sadik Armagan15f7fae2020-11-18 09:37:03 +0000122
Finn Williams56870182020-11-20 13:57:53 +0000123 std::copy(tensorData.begin(), tensorData.end(), inputData);
124 }
Finn Williamsf806c4d2021-02-22 15:13:12 +0000125 else if (params.m_InputTypes[inputIndex].compare("qsymms8") == 0)
Finn Williams56870182020-11-20 13:57:53 +0000126 {
127 auto inputData = tfLiteInterpreter->typed_tensor<int8_t>(input);
Finn Williamsbbbefec2020-11-25 14:32:42 +0000128
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000129 if(inputData == NULL)
Finn Williamsbbbefec2020-11-25 14:32:42 +0000130 {
131 ARMNN_LOG(fatal) << "Input tensor is null, input type: "
132 "\"" << params.m_InputTypes[inputIndex] << "\" may be incorrect.";
133 return EXIT_FAILURE;
134 }
135
Finn Williams56870182020-11-20 13:57:53 +0000136 std::vector<int8_t> tensorData;
137 PopulateTensorWithDataGeneric<int8_t>(tensorData,
Mike Kelly00e9ebf2021-09-01 17:09:12 +0100138 inputSize,
Finn Williams56870182020-11-20 13:57:53 +0000139 dataFile,
140 [](const std::string& s)
141 { return armnn::numeric_cast<int8_t>(std::stoi(s)); });
142
143 std::copy(tensorData.begin(), tensorData.end(), inputData);
Sadik Armagan5d03e312020-11-17 16:43:56 +0000144 }
145 else if (params.m_InputTypes[inputIndex].compare("int") == 0)
146 {
147 auto inputData = tfLiteInterpreter->typed_tensor<int32_t>(input);
Finn Williamsbbbefec2020-11-25 14:32:42 +0000148
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000149 if(inputData == NULL)
Finn Williamsbbbefec2020-11-25 14:32:42 +0000150 {
151 ARMNN_LOG(fatal) << "Input tensor is null, input type: "
152 "\"" << params.m_InputTypes[inputIndex] << "\" may be incorrect.";
153 return EXIT_FAILURE;
154 }
155
Finn Williams56870182020-11-20 13:57:53 +0000156 std::vector<int32_t> tensorData;
157 PopulateTensorWithDataGeneric<int32_t>(tensorData,
Mike Kelly00e9ebf2021-09-01 17:09:12 +0100158 inputSize,
Finn Williams56870182020-11-20 13:57:53 +0000159 dataFile,
160 [](const std::string& s)
161 { return std::stoi(s); });
162
163 std::copy(tensorData.begin(), tensorData.end(), inputData);
Sadik Armagan5d03e312020-11-17 16:43:56 +0000164 }
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100165 else if (params.m_InputTypes[inputIndex].compare("qasymm8") == 0 ||
166 params.m_InputTypes[inputIndex].compare("qasymmu8") == 0)
Sadik Armagan5d03e312020-11-17 16:43:56 +0000167 {
168 auto inputData = tfLiteInterpreter->typed_tensor<uint8_t>(input);
Finn Williamsbbbefec2020-11-25 14:32:42 +0000169
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000170 if(inputData == NULL)
Finn Williamsbbbefec2020-11-25 14:32:42 +0000171 {
172 ARMNN_LOG(fatal) << "Input tensor is null, input type: "
173 "\"" << params.m_InputTypes[inputIndex] << "\" may be incorrect.";
174 return EXIT_FAILURE;
175 }
176
Finn Williams56870182020-11-20 13:57:53 +0000177 std::vector<uint8_t> tensorData;
178 PopulateTensorWithDataGeneric<uint8_t>(tensorData,
Mike Kelly00e9ebf2021-09-01 17:09:12 +0100179 inputSize,
Finn Williams56870182020-11-20 13:57:53 +0000180 dataFile,
181 [](const std::string& s)
182 { return armnn::numeric_cast<uint8_t>(std::stoi(s)); });
183
184 std::copy(tensorData.begin(), tensorData.end(), inputData);
Sadik Armagan5d03e312020-11-17 16:43:56 +0000185 }
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100186 else if (params.m_InputTypes[inputIndex].compare("qasymms8") == 0)
187 {
188 auto inputData = tfLiteInterpreter->typed_tensor<int8_t>(input);
189
190 if(inputData == NULL)
191 {
192 ARMNN_LOG(fatal) << "Input tensor is null, input type: "
193 "\"" << params.m_InputTypes[inputIndex] << "\" may be incorrect.";
194 return EXIT_FAILURE;
195 }
196
197 std::vector<int8_t> tensorData;
198 PopulateTensorWithDataGeneric<int8_t>(tensorData,
Mike Kelly00e9ebf2021-09-01 17:09:12 +0100199 inputSize,
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100200 dataFile,
201 [](const std::string& s)
202 { return armnn::numeric_cast<int8_t>(std::stoi(s)); });
203
204 std::copy(tensorData.begin(), tensorData.end(), inputData);
205 }
Sadik Armagan5d03e312020-11-17 16:43:56 +0000206 else
207 {
208 ARMNN_LOG(fatal) << "Unsupported input tensor data type \"" << params.m_InputTypes[inputIndex] << "\". ";
209 return EXIT_FAILURE;
210 }
211 }
212
213 for (size_t x = 0; x < params.m_Iterations; x++)
214 {
215 // Run the inference
Finn Williamsf806c4d2021-02-22 15:13:12 +0000216 status = tfLiteInterpreter->Invoke();
Sadik Armagan5d03e312020-11-17 16:43:56 +0000217
218 // Print out the output
219 for (unsigned int outputIndex = 0; outputIndex < params.m_OutputNames.size(); ++outputIndex)
220 {
Sadik Armagan5d03e312020-11-17 16:43:56 +0000221 auto tfLiteDelegateOutputId = tfLiteInterpreter->outputs()[outputIndex];
Sadik Armagan15f7fae2020-11-18 09:37:03 +0000222 TfLiteIntArray* outputDims = tfLiteInterpreter->tensor(tfLiteDelegateOutputId)->dims;
Sadik Armagan5d03e312020-11-17 16:43:56 +0000223
Sadik Armagan15f7fae2020-11-18 09:37:03 +0000224 long outputSize = 1;
Sadik Armagan5d03e312020-11-17 16:43:56 +0000225 for (unsigned int dim = 0; dim < static_cast<unsigned int>(outputDims->size); ++dim)
226 {
Sadik Armagan15f7fae2020-11-18 09:37:03 +0000227 outputSize *= outputDims->data[dim];
Sadik Armagan5d03e312020-11-17 16:43:56 +0000228 }
229
230 std::cout << params.m_OutputNames[outputIndex] << ": ";
231 if (params.m_OutputTypes[outputIndex].compare("float") == 0)
232 {
233 auto tfLiteDelageOutputData = tfLiteInterpreter->typed_tensor<float>(tfLiteDelegateOutputId);
Sadik Armagan5d03e312020-11-17 16:43:56 +0000234 if(tfLiteDelageOutputData == NULL)
235 {
236 ARMNN_LOG(fatal) << "Output tensor is null, output type: "
237 "\"" << params.m_OutputTypes[outputIndex] << "\" may be incorrect.";
238 return EXIT_FAILURE;
239 }
240
Jan Eilers284b5d12021-09-07 12:46:15 +0100241 if (!params.m_DontPrintOutputs)
Sadik Armagan5d03e312020-11-17 16:43:56 +0000242 {
Jan Eilers284b5d12021-09-07 12:46:15 +0100243 for (int i = 0; i < outputSize; ++i)
244 {
245 printf("%f ", tfLiteDelageOutputData[i]);
246 }
Sadik Armagan5d03e312020-11-17 16:43:56 +0000247 }
248 }
249 else if (params.m_OutputTypes[outputIndex].compare("int") == 0)
250 {
251 auto tfLiteDelageOutputData = tfLiteInterpreter->typed_tensor<int32_t>(tfLiteDelegateOutputId);
Sadik Armagan5d03e312020-11-17 16:43:56 +0000252 if(tfLiteDelageOutputData == NULL)
253 {
254 ARMNN_LOG(fatal) << "Output tensor is null, output type: "
255 "\"" << params.m_OutputTypes[outputIndex] << "\" may be incorrect.";
256 return EXIT_FAILURE;
257 }
258
Jan Eilers284b5d12021-09-07 12:46:15 +0100259 if (!params.m_DontPrintOutputs)
Sadik Armagan5d03e312020-11-17 16:43:56 +0000260 {
Jan Eilers284b5d12021-09-07 12:46:15 +0100261 for (int i = 0; i < outputSize; ++i)
262 {
263 printf("%d ", tfLiteDelageOutputData[i]);
264 }
Sadik Armagan5d03e312020-11-17 16:43:56 +0000265 }
266 }
Finn Williamsf806c4d2021-02-22 15:13:12 +0000267 else if (params.m_OutputTypes[outputIndex].compare("qsymms8") == 0)
Finn Williams56870182020-11-20 13:57:53 +0000268 {
269 auto tfLiteDelageOutputData = tfLiteInterpreter->typed_tensor<int8_t>(tfLiteDelegateOutputId);
270 if(tfLiteDelageOutputData == NULL)
271 {
272 ARMNN_LOG(fatal) << "Output tensor is null, output type: "
273 "\"" << params.m_OutputTypes[outputIndex] << "\" may be incorrect.";
274 return EXIT_FAILURE;
275 }
276
Jan Eilers284b5d12021-09-07 12:46:15 +0100277 if (!params.m_DontPrintOutputs)
Finn Williams56870182020-11-20 13:57:53 +0000278 {
Jan Eilers284b5d12021-09-07 12:46:15 +0100279 for (int i = 0; i < outputSize; ++i)
280 {
281 printf("%d ", tfLiteDelageOutputData[i]);
282 }
Finn Williams56870182020-11-20 13:57:53 +0000283 }
284 }
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100285 else if (params.m_OutputTypes[outputIndex].compare("qasymm8") == 0 ||
286 params.m_OutputTypes[outputIndex].compare("qasymmu8") == 0)
Sadik Armagan5d03e312020-11-17 16:43:56 +0000287 {
288 auto tfLiteDelageOutputData = tfLiteInterpreter->typed_tensor<uint8_t>(tfLiteDelegateOutputId);
Sadik Armagan5d03e312020-11-17 16:43:56 +0000289 if(tfLiteDelageOutputData == NULL)
290 {
291 ARMNN_LOG(fatal) << "Output tensor is null, output type: "
292 "\"" << params.m_OutputTypes[outputIndex] << "\" may be incorrect.";
293 return EXIT_FAILURE;
294 }
295
Jan Eilers284b5d12021-09-07 12:46:15 +0100296 if (!params.m_DontPrintOutputs)
Sadik Armagan5d03e312020-11-17 16:43:56 +0000297 {
Jan Eilers284b5d12021-09-07 12:46:15 +0100298 for (int i = 0; i < outputSize; ++i)
299 {
300 printf("%u ", tfLiteDelageOutputData[i]);
301 }
Sadik Armagan5d03e312020-11-17 16:43:56 +0000302 }
303 }
304 else
305 {
306 ARMNN_LOG(fatal) << "Output tensor is null, output type: "
307 "\"" << params.m_OutputTypes[outputIndex] <<
308 "\" may be incorrect. Output type can be specified with -z argument";
309 return EXIT_FAILURE;
310 }
311 std::cout << std::endl;
312 }
313 }
314
315 return status;
316}
317#endif
Jan Eilers45274902020-10-15 18:34:43 +0100318template<typename TParser, typename TDataType>
319int MainImpl(const ExecuteNetworkParams& params,
320 const std::shared_ptr<armnn::IRuntime>& runtime = nullptr)
321{
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100322 using namespace std::chrono;
Jan Eilers45274902020-10-15 18:34:43 +0100323
Sadik Armagana04a9d72021-04-27 10:02:10 +0100324 std::vector<std::vector<TContainer>> inputs;
325 std::vector<std::vector<TContainer>> outputs;
Jan Eilers45274902020-10-15 18:34:43 +0100326
327 try
328 {
329 // Creates an InferenceModel, which will parse the model and load it into an IRuntime.
330 typename InferenceModel<TParser, TDataType>::Params inferenceModelParams;
331 inferenceModelParams.m_ModelPath = params.m_ModelPath;
332 inferenceModelParams.m_IsModelBinary = params.m_IsModelBinary;
333 inferenceModelParams.m_ComputeDevices = params.m_ComputeDevices;
334 inferenceModelParams.m_DynamicBackendsPath = params.m_DynamicBackendsPath;
335 inferenceModelParams.m_PrintIntermediateLayers = params.m_PrintIntermediate;
336 inferenceModelParams.m_VisualizePostOptimizationModel = params.m_EnableLayerDetails;
337 inferenceModelParams.m_ParseUnsupported = params.m_ParseUnsupported;
338 inferenceModelParams.m_InferOutputShape = params.m_InferOutputShape;
339 inferenceModelParams.m_EnableFastMath = params.m_EnableFastMath;
Matthew Sloyan42432112021-01-08 10:30:51 +0000340 inferenceModelParams.m_SaveCachedNetwork = params.m_SaveCachedNetwork;
341 inferenceModelParams.m_CachedNetworkFilePath = params.m_CachedNetworkFilePath;
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000342 inferenceModelParams.m_NumberOfThreads = params.m_NumberOfThreads;
Finn Williams40646322021-02-11 16:16:42 +0000343 inferenceModelParams.m_MLGOTuningFilePath = params.m_MLGOTuningFilePath;
Sadik Armagana04a9d72021-04-27 10:02:10 +0100344 inferenceModelParams.m_AsyncEnabled = params.m_Concurrent;
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100345 inferenceModelParams.m_ThreadPoolSize = params.m_ThreadPoolSize;
Keith Davisf4874862021-08-09 16:49:18 +0100346 inferenceModelParams.m_OutputDetailsToStdOut = params.m_OutputDetailsToStdOut;
Keith Davis4914d0c2021-08-18 17:14:05 +0100347 inferenceModelParams.m_OutputDetailsOnlyToStdOut = params.m_OutputDetailsOnlyToStdOut;
Jan Eilers45274902020-10-15 18:34:43 +0100348
349 for(const std::string& inputName: params.m_InputNames)
350 {
351 inferenceModelParams.m_InputBindings.push_back(inputName);
352 }
353
354 for(unsigned int i = 0; i < params.m_InputTensorShapes.size(); ++i)
355 {
356 inferenceModelParams.m_InputShapes.push_back(*params.m_InputTensorShapes[i]);
357 }
358
359 for(const std::string& outputName: params.m_OutputNames)
360 {
361 inferenceModelParams.m_OutputBindings.push_back(outputName);
362 }
363
364 inferenceModelParams.m_SubgraphId = params.m_SubgraphId;
365 inferenceModelParams.m_EnableFp16TurboMode = params.m_EnableFp16TurboMode;
366 inferenceModelParams.m_EnableBf16TurboMode = params.m_EnableBf16TurboMode;
367
368 InferenceModel<TParser, TDataType> model(inferenceModelParams,
369 params.m_EnableProfiling,
370 params.m_DynamicBackendsPath,
371 runtime);
372
373 const size_t numInputs = inferenceModelParams.m_InputBindings.size();
Sadik Armagana04a9d72021-04-27 10:02:10 +0100374
375 armnn::Optional<QuantizationParams> qParams = params.m_QuantizeInput ?
376 armnn::MakeOptional<QuantizationParams>(
377 model.GetInputQuantizationParams()) :
378 armnn::EmptyOptional();
379
Jan Eilersf17fcd52021-07-26 22:20:00 +0100380 if (params.m_InputTensorDataFilePaths.size() > numInputs)
381 {
382 ARMNN_LOG(info) << "Given network has " << numInputs << " input/s. One input-tensor-data file is required "
383 << "for each input. The user provided "
384 << params.m_InputTensorDataFilePaths.size()
385 << " input-tensor-data file/s which will be used to fill the input/s.\n";
386 }
387
388 for(unsigned int j = 0; j < params.m_Iterations ; ++j)
Jan Eilers45274902020-10-15 18:34:43 +0100389 {
Sadik Armagana04a9d72021-04-27 10:02:10 +0100390 std::vector<TContainer> inputDataContainers;
391 for(unsigned int i = 0; i < numInputs; ++i)
Jan Eilers45274902020-10-15 18:34:43 +0100392 {
Jan Eilersf17fcd52021-07-26 22:20:00 +0100393 // If there are less input files given than required for the execution of
394 // params.m_Iterations we simply start with the first input file again
395 size_t inputFileIndex = j * numInputs + i;
396 if (!params.m_InputTensorDataFilePaths.empty())
397 {
398 inputFileIndex = inputFileIndex % params.m_InputTensorDataFilePaths.size();
399 }
400
Sadik Armagana04a9d72021-04-27 10:02:10 +0100401 armnn::Optional<std::string> dataFile = params.m_GenerateTensorData ?
402 armnn::EmptyOptional() :
403 armnn::MakeOptional<std::string>(
Jan Eilersf17fcd52021-07-26 22:20:00 +0100404 params.m_InputTensorDataFilePaths.at(inputFileIndex));
Sadik Armagana04a9d72021-04-27 10:02:10 +0100405
406 unsigned int numElements = model.GetInputSize(i);
407 if (params.m_InputTensorShapes.size() > i && params.m_InputTensorShapes[i])
408 {
409 // If the user has provided a tensor shape for the current input,
410 // override numElements
411 numElements = params.m_InputTensorShapes[i]->GetNumElements();
412 }
413
414 TContainer tensorData;
415 PopulateTensorWithData(tensorData,
416 numElements,
417 params.m_InputTypes[i],
418 qParams,
419 dataFile);
420
421 inputDataContainers.push_back(tensorData);
Jan Eilers45274902020-10-15 18:34:43 +0100422 }
Sadik Armagana04a9d72021-04-27 10:02:10 +0100423 inputs.push_back(inputDataContainers);
Jan Eilers45274902020-10-15 18:34:43 +0100424 }
425
426 const size_t numOutputs = inferenceModelParams.m_OutputBindings.size();
Jan Eilers45274902020-10-15 18:34:43 +0100427
Jan Eilersf17fcd52021-07-26 22:20:00 +0100428 for (unsigned int j = 0; j < params.m_Iterations; ++j)
Jan Eilers45274902020-10-15 18:34:43 +0100429 {
Sadik Armagana04a9d72021-04-27 10:02:10 +0100430 std::vector <TContainer> outputDataContainers;
431 for (unsigned int i = 0; i < numOutputs; ++i)
Jan Eilers45274902020-10-15 18:34:43 +0100432 {
Sadik Armagana04a9d72021-04-27 10:02:10 +0100433 if (params.m_OutputTypes[i].compare("float") == 0)
Jan Eilers45274902020-10-15 18:34:43 +0100434 {
Sadik Armagana04a9d72021-04-27 10:02:10 +0100435 outputDataContainers.push_back(std::vector<float>(model.GetOutputSize(i)));
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100436 }
437 else if (params.m_OutputTypes[i].compare("int") == 0)
Sadik Armagana04a9d72021-04-27 10:02:10 +0100438 {
439 outputDataContainers.push_back(std::vector<int>(model.GetOutputSize(i)));
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100440 }
441 else if (params.m_OutputTypes[i].compare("qasymm8") == 0 ||
442 params.m_OutputTypes[i].compare("qasymmu8") == 0)
Sadik Armagana04a9d72021-04-27 10:02:10 +0100443 {
444 outputDataContainers.push_back(std::vector<uint8_t>(model.GetOutputSize(i)));
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100445 }
446 else if (params.m_OutputTypes[i].compare("qasymms8") == 0)
Sadik Armagana04a9d72021-04-27 10:02:10 +0100447 {
448 outputDataContainers.push_back(std::vector<int8_t>(model.GetOutputSize(i)));
449 } else
450 {
451 ARMNN_LOG(fatal) << "Unsupported tensor data type \"" << params.m_OutputTypes[i] << "\". ";
452 return EXIT_FAILURE;
Jan Eilers45274902020-10-15 18:34:43 +0100453 }
454 }
Sadik Armagana04a9d72021-04-27 10:02:10 +0100455 outputs.push_back(outputDataContainers);
456 }
457
Jan Eilersf17fcd52021-07-26 22:20:00 +0100458 if (params.m_Iterations > 1)
459 {
460 std::stringstream msg;
461 msg << "Network will be executed " << params.m_Iterations;
462 if (params.m_Concurrent)
463 {
464 msg << " times in an asynchronous manner. ";
465 }
466 else
467 {
468 msg << " times successively. ";
469 }
470 msg << "The input-tensor-data files will be reused recursively if the user didn't provide enough to "
471 "cover each execution.";
472 ARMNN_LOG(info) << msg.str();
473 }
474
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100475 // Synchronous execution
Sadik Armagana04a9d72021-04-27 10:02:10 +0100476 if (!params.m_Concurrent)
477 {
Sadik Armagana04a9d72021-04-27 10:02:10 +0100478 for (size_t x = 0; x < params.m_Iterations; x++)
479 {
480 // model.Run returns the inference time elapsed in EnqueueWorkload (in milliseconds)
Jan Eilersf17fcd52021-07-26 22:20:00 +0100481 auto inference_duration = model.Run(inputs[x], outputs[x]);
Sadik Armagana04a9d72021-04-27 10:02:10 +0100482
483 if (params.m_GenerateTensorData)
484 {
485 ARMNN_LOG(warning) << "The input data was generated, note that the output will not be useful";
486 }
Jan Eilers284b5d12021-09-07 12:46:15 +0100487 if (params.m_DontPrintOutputs)
488 {
489 ARMNN_LOG(info) << "Printing outputs to console is disabled.";
490 }
Sadik Armagana04a9d72021-04-27 10:02:10 +0100491
492 // Print output tensors
493 const auto& infosOut = model.GetOutputBindingInfos();
494 for (size_t i = 0; i < numOutputs; i++)
495 {
496 const armnn::TensorInfo& infoOut = infosOut[i].second;
Jan Eilersf17fcd52021-07-26 22:20:00 +0100497
Jan Eilers284b5d12021-09-07 12:46:15 +0100498 // We've made sure before that the number of output files either equals numOutputs, in which
499 // case we override those files when processing the results of each iteration (only the result
500 // of the last iteration will be stored), or there are enough
Jan Eilersf17fcd52021-07-26 22:20:00 +0100501 // output files for each output of each iteration.
502 size_t outputFileIndex = x * numOutputs + i;
503 if (!params.m_OutputTensorFiles.empty())
504 {
505 outputFileIndex = outputFileIndex % params.m_OutputTensorFiles.size();
506 ARMNN_LOG(info) << "Writing output " << i << " named: '"
507 << inferenceModelParams.m_OutputBindings[i]
508 << "' of iteration: " << x+1 << " to file: '"
509 << params.m_OutputTensorFiles[outputFileIndex] << "'";
510 }
511 auto outputTensorFile = params.m_OutputTensorFiles.empty()
512 ? ""
513 : params.m_OutputTensorFiles[outputFileIndex];
Sadik Armagana04a9d72021-04-27 10:02:10 +0100514
515 TensorPrinter printer(inferenceModelParams.m_OutputBindings[i],
516 infoOut,
517 outputTensorFile,
Jan Eilers284b5d12021-09-07 12:46:15 +0100518 params.m_DequantizeOutput,
519 !params.m_DontPrintOutputs);
Jan Eilersf17fcd52021-07-26 22:20:00 +0100520 mapbox::util::apply_visitor(printer, outputs[x][i]);
Sadik Armagana04a9d72021-04-27 10:02:10 +0100521 }
522
523 ARMNN_LOG(info) << "\nInference time: " << std::setprecision(2)
524 << std::fixed << inference_duration.count() << " ms\n";
525
526 // If thresholdTime == 0.0 (default), then it hasn't been supplied at command line
527 if (params.m_ThresholdTime != 0.0)
528 {
529 ARMNN_LOG(info) << "Threshold time: " << std::setprecision(2)
530 << std::fixed << params.m_ThresholdTime << " ms";
531 auto thresholdMinusInference = params.m_ThresholdTime - inference_duration.count();
532 ARMNN_LOG(info) << "Threshold time - Inference time: " << std::setprecision(2)
533 << std::fixed << thresholdMinusInference << " ms" << "\n";
534
535 if (thresholdMinusInference < 0)
536 {
537 std::string errorMessage = "Elapsed inference time is greater than provided threshold time.";
538 ARMNN_LOG(fatal) << errorMessage;
539 }
540 }
541 }
542 }
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100543 // Asynchronous execution using the Arm NN thread pool
Kevin May94dd4db2021-05-26 16:01:08 +0100544 else if (params.m_ThreadPoolSize >= 1)
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100545 {
546 try
547 {
548 ARMNN_LOG(info) << "Asynchronous execution with Arm NN thread pool... \n";
Finn Williamsf364d532021-06-09 17:07:33 +0100549 armnn::AsyncCallbackManager callbackManager;
550 std::unordered_map<armnn::InferenceId, std::vector<TContainer>&> inferenceOutputMap;
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100551
552 // Declare the latest and earliest inference times here to be used when calculating overall time
553 std::chrono::high_resolution_clock::time_point earliestStartTime;
554 std::chrono::high_resolution_clock::time_point latestEndTime =
555 std::chrono::high_resolution_clock::now();
556
557 // For the asynchronous execution, we are adding a pool of working memory handles (1 per thread) in the
558 // LoadedNetwork with each scheduled inference having a specific priority
Jan Eilersf17fcd52021-07-26 22:20:00 +0100559 for (size_t i = 0; i < params.m_Iterations; ++i)
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100560 {
Finn Williamsf364d532021-06-09 17:07:33 +0100561 std::shared_ptr<armnn::AsyncExecutionCallback> cb = callbackManager.GetNewCallback();
562 inferenceOutputMap.insert({cb->GetInferenceId(), outputs[i]});
563 model.RunAsync(inputs[i], outputs[i], cb);
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100564 }
565
566 // Check the results
567 unsigned int j = 0;
Jan Eilersf17fcd52021-07-26 22:20:00 +0100568 for (size_t iteration = 0; iteration < params.m_Iterations; ++iteration)
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100569 {
Finn Williamsf364d532021-06-09 17:07:33 +0100570 auto cb = callbackManager.GetNotifiedCallback();
571
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100572 // Get the results
573 auto endTime = time_point_cast<std::chrono::milliseconds>(cb->GetEndTime());
574 auto startTime = time_point_cast<std::chrono::milliseconds>(cb->GetStartTime());
575 auto inferenceDuration = endTime - startTime;
576
577 if (latestEndTime < cb->GetEndTime())
578 {
579 latestEndTime = cb->GetEndTime();
580 }
581
582 if (earliestStartTime.time_since_epoch().count() == 0)
583 {
584 earliestStartTime = cb->GetStartTime();
585 }
586 else if (earliestStartTime > cb->GetStartTime())
587 {
588 earliestStartTime = cb->GetStartTime();
589 }
590
591 if (params.m_GenerateTensorData)
592 {
593 ARMNN_LOG(warning) << "The input data was generated, note that the output will not be useful";
594 }
Jan Eilers284b5d12021-09-07 12:46:15 +0100595 if (params.m_DontPrintOutputs)
596 {
597 ARMNN_LOG(info) << "Printing outputs to console is disabled.";
598 }
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100599
600 // Print output tensors
601 const auto& infosOut = model.GetOutputBindingInfos();
602 for (size_t i = 0; i < numOutputs; i++)
603 {
Jan Eilersf17fcd52021-07-26 22:20:00 +0100604 // We've made sure before that the number of output files either equals numOutputs, in which
Jan Eilers284b5d12021-09-07 12:46:15 +0100605 // case we override those files when processing the results of each iteration (only the
606 // result of the last iteration will be stored), or there are enough
Jan Eilersf17fcd52021-07-26 22:20:00 +0100607 // output files for each output of each iteration.
608 size_t outputFileIndex = iteration * numOutputs + i;
609 if (!params.m_OutputTensorFiles.empty())
610 {
611 outputFileIndex = outputFileIndex % params.m_OutputTensorFiles.size();
612 ARMNN_LOG(info) << "Writing output " << i << " named: '"
613 << inferenceModelParams.m_OutputBindings[i]
614 << "' of iteration: " << iteration+1 << " to file: '"
615 << params.m_OutputTensorFiles[outputFileIndex] << "'";
616 }
617
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100618 const armnn::TensorInfo& infoOut = infosOut[i].second;
619 auto outputTensorFile = params.m_OutputTensorFiles.empty()
620 ? ""
Jan Eilersf17fcd52021-07-26 22:20:00 +0100621 : params.m_OutputTensorFiles[outputFileIndex];
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100622
623 TensorPrinter printer(inferenceModelParams.m_OutputBindings[i],
624 infoOut,
625 outputTensorFile,
Jan Eilers284b5d12021-09-07 12:46:15 +0100626 params.m_DequantizeOutput,
627 !params.m_DontPrintOutputs);
Finn Williamsf364d532021-06-09 17:07:33 +0100628 mapbox::util::apply_visitor(printer, inferenceOutputMap.at(cb->GetInferenceId())[i]);
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100629 }
630
631 ARMNN_LOG(info) << "\nInference time: " << std::setprecision(2)
632 << std::fixed << inferenceDuration.count() << " ms\n";
633
634 // If thresholdTime == 0.0 (default), then it hasn't been supplied at command line
635 if (params.m_ThresholdTime != 0.0)
636 {
637 ARMNN_LOG(info) << "Threshold time: " << std::setprecision(2)
638 << std::fixed << params.m_ThresholdTime << " ms";
639 auto thresholdMinusInference =
640 params.m_ThresholdTime - duration<double, std::milli>(inferenceDuration).count();
641 ARMNN_LOG(info) << "Threshold time - Inference time: " << std::setprecision(2)
642 << std::fixed << thresholdMinusInference << " ms" << "\n";
643
644 if (thresholdMinusInference < 0)
645 {
646 ARMNN_LOG(fatal) << "Elapsed inference time is greater than provided threshold time. \n";
647 }
648 }
649 ++j;
650 }
651 //print duration difference between overallStartTime and overallEndTime
652 auto overallEndTime = time_point_cast<std::chrono::milliseconds>(latestEndTime);
653 auto overallStartTime = time_point_cast<std::chrono::milliseconds>(earliestStartTime);
654 auto totalInferenceDuration = overallEndTime - overallStartTime;
655 ARMNN_LOG(info) << "\nOverall Inference time: " << std::setprecision(2)
656 << std::fixed << totalInferenceDuration.count() << " ms\n";
657 }
658 catch (const armnn::Exception& e)
659 {
660 ARMNN_LOG(fatal) << "Armnn Error: " << e.what();
661 return EXIT_FAILURE;
662 }
663 }
664 // Asynchronous execution using std::launch::async
Sadik Armagana04a9d72021-04-27 10:02:10 +0100665 else
666 {
667 try
668 {
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100669 ARMNN_LOG(info) << "Asynchronous Execution with std::launch:async... \n";
Finn Williamsf364d532021-06-09 17:07:33 +0100670 std::vector<std::future<std::tuple<unsigned int,
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100671 std::chrono::duration<double, std::milli>>>> inferenceResults;
Jan Eilersf17fcd52021-07-26 22:20:00 +0100672 inferenceResults.reserve(params.m_Iterations);
Sadik Armagana04a9d72021-04-27 10:02:10 +0100673
674 // Create WorkingMemHandles for each inference
675 std::vector<std::unique_ptr<armnn::experimental::IWorkingMemHandle>> workingMemHandles;
Jan Eilersf17fcd52021-07-26 22:20:00 +0100676 workingMemHandles.reserve(params.m_Iterations);
677 for (unsigned int i = 0; i < params.m_Iterations; ++i)
Sadik Armagana04a9d72021-04-27 10:02:10 +0100678 {
679 workingMemHandles.push_back(model.CreateWorkingMemHandle());
680 }
681
682 // Run each inference in its own thread
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100683 // start a timer
684 const auto start_time = armnn::GetTimeNow();
Jan Eilersf17fcd52021-07-26 22:20:00 +0100685 for (unsigned int i = 0; i < params.m_Iterations; ++i)
Sadik Armagana04a9d72021-04-27 10:02:10 +0100686 {
687 armnn::experimental::IWorkingMemHandle& workingMemHandleRef = *workingMemHandles[i].get();
Finn Williamsf364d532021-06-09 17:07:33 +0100688
Sadik Armagana04a9d72021-04-27 10:02:10 +0100689 inferenceResults.push_back(std::async(
690 std::launch::async, [&model, &workingMemHandleRef, &inputs, &outputs, i]() {
Finn Williamsf364d532021-06-09 17:07:33 +0100691 return model.RunAsync(workingMemHandleRef, inputs[i], outputs[i], i);
Sadik Armagana04a9d72021-04-27 10:02:10 +0100692 }
693 ));
694 }
695
696 // Check the results
697 for (unsigned int j = 0; j < inferenceResults.size(); ++j)
698 {
699 // Get the results
700 auto inferenceResult = inferenceResults[j].get();
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100701 auto inferenceDuration = std::get<1>(inferenceResult);
Sadik Armagana04a9d72021-04-27 10:02:10 +0100702 auto inferenceID = std::get<0>(inferenceResult);
703
704 if (params.m_GenerateTensorData)
705 {
706 ARMNN_LOG(warning) << "The input data was generated, note that the output will not be useful";
707 }
Jan Eilers284b5d12021-09-07 12:46:15 +0100708 if (params.m_DontPrintOutputs)
709 {
710 ARMNN_LOG(info) << "Printing outputs to console is disabled.";
711 }
Sadik Armagana04a9d72021-04-27 10:02:10 +0100712
713 // Print output tensors
714 const auto& infosOut = model.GetOutputBindingInfos();
715 for (size_t i = 0; i < numOutputs; i++)
716 {
Jan Eilersf17fcd52021-07-26 22:20:00 +0100717 // We've made sure before that the number of output files either equals numOutputs, in which
Jan Eilers284b5d12021-09-07 12:46:15 +0100718 // case we override those files when processing the results of each iteration (only the
719 // result of the last iteration will be stored), or there are enough
Jan Eilersf17fcd52021-07-26 22:20:00 +0100720 // output files for each output of each iteration.
721 size_t outputFileIndex = j * numOutputs + i;
722 if (!params.m_OutputTensorFiles.empty())
723 {
724 outputFileIndex = outputFileIndex % params.m_OutputTensorFiles.size();
725 ARMNN_LOG(info) << "Writing output " << i << " named: '"
726 << inferenceModelParams.m_OutputBindings[i]
727 << "' of iteration: " << j+1 << " to file: '"
728 << params.m_OutputTensorFiles[outputFileIndex] << "'";
729 }
Sadik Armagana04a9d72021-04-27 10:02:10 +0100730 const armnn::TensorInfo& infoOut = infosOut[i].second;
731 auto outputTensorFile = params.m_OutputTensorFiles.empty()
732 ? ""
Jan Eilersf17fcd52021-07-26 22:20:00 +0100733 : params.m_OutputTensorFiles[outputFileIndex];
Sadik Armagana04a9d72021-04-27 10:02:10 +0100734
735 TensorPrinter printer(inferenceModelParams.m_OutputBindings[i],
736 infoOut,
737 outputTensorFile,
Jan Eilers284b5d12021-09-07 12:46:15 +0100738 params.m_DequantizeOutput,
739 !params.m_DontPrintOutputs);
Sadik Armagana04a9d72021-04-27 10:02:10 +0100740 mapbox::util::apply_visitor(printer, outputs[j][i]);
741 }
742
743 ARMNN_LOG(info) << "\nInference time: " << std::setprecision(2)
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100744 << std::fixed << inferenceDuration.count() << " ms\n";
Sadik Armagana04a9d72021-04-27 10:02:10 +0100745
746 // If thresholdTime == 0.0 (default), then it hasn't been supplied at command line
747 if (params.m_ThresholdTime != 0.0)
748 {
749 ARMNN_LOG(info) << "Threshold time: " << std::setprecision(2)
750 << std::fixed << params.m_ThresholdTime << " ms";
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100751 auto thresholdMinusInference = params.m_ThresholdTime - inferenceDuration.count();
Sadik Armagana04a9d72021-04-27 10:02:10 +0100752 ARMNN_LOG(info) << "Threshold time - Inference time: " << std::setprecision(2)
753 << std::fixed << thresholdMinusInference << " ms" << "\n";
754
755 if (thresholdMinusInference < 0)
756 {
757 ARMNN_LOG(fatal) << "Elapsed inference time is greater than provided threshold time. \n";
758 }
759 }
760 ARMNN_LOG(info) << "Asynchronous Execution is finished for Inference ID: " << inferenceID << " \n";
761
762 }
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100763 // finish timer
764 const auto duration = armnn::GetTimeDuration(start_time);
765 ARMNN_LOG(info) << "\nOverall Inference time: " << std::setprecision(2)
766 << std::fixed << duration.count() << " ms\n";
Sadik Armagana04a9d72021-04-27 10:02:10 +0100767 }
768 catch (const armnn::Exception& e)
769 {
770 ARMNN_LOG(fatal) << "Armnn Error: " << e.what();
771 return EXIT_FAILURE;
772 }
Jan Eilers45274902020-10-15 18:34:43 +0100773 }
774 }
775 catch (const armnn::Exception& e)
776 {
777 ARMNN_LOG(fatal) << "Armnn Error: " << e.what();
778 return EXIT_FAILURE;
779 }
780
781 return EXIT_SUCCESS;
782}
783
telsoa01c577f2c2018-08-31 09:22:23 +0100784
James Conroy7b4886f2019-04-11 10:23:58 +0100785// MAIN
telsoa01c577f2c2018-08-31 09:22:23 +0100786int main(int argc, const char* argv[])
787{
788 // Configures logging for both the ARMNN library and this test program.
Jan Eilers45274902020-10-15 18:34:43 +0100789 #ifdef NDEBUG
telsoa01c577f2c2018-08-31 09:22:23 +0100790 armnn::LogSeverity level = armnn::LogSeverity::Info;
Jan Eilers45274902020-10-15 18:34:43 +0100791 #else
telsoa01c577f2c2018-08-31 09:22:23 +0100792 armnn::LogSeverity level = armnn::LogSeverity::Debug;
Jan Eilers45274902020-10-15 18:34:43 +0100793 #endif
telsoa01c577f2c2018-08-31 09:22:23 +0100794 armnn::ConfigureLogging(true, true, level);
telsoa01c577f2c2018-08-31 09:22:23 +0100795
telsoa01c577f2c2018-08-31 09:22:23 +0100796
Jan Eilers45274902020-10-15 18:34:43 +0100797 // Get ExecuteNetwork parameters and runtime options from command line
Jan Eilersf17fcd52021-07-26 22:20:00 +0100798 // This might throw an InvalidArgumentException if the user provided invalid inputs
799 ProgramOptions ProgramOptions;
800 try {
801 ProgramOptions.ParseOptions(argc, argv);
802 } catch (const std::exception &e){
803 ARMNN_LOG(fatal) << e.what();
804 return EXIT_FAILURE;
805 }
Narumol Prangnawaratd8cc8112020-03-24 13:54:05 +0000806
Keith Davis4914d0c2021-08-18 17:14:05 +0100807 if ((ProgramOptions.m_ExNetParams.m_OutputDetailsToStdOut ||
808 ProgramOptions.m_ExNetParams.m_OutputDetailsOnlyToStdOut)
809 && !ProgramOptions.m_ExNetParams.m_EnableProfiling)
Keith Davisf4874862021-08-09 16:49:18 +0100810 {
811 ARMNN_LOG(fatal) << "You must enable profiling if you would like to output layer details";
812 return EXIT_FAILURE;
813 }
814
Finn Williamsd7fcafa2020-04-23 17:55:18 +0100815 // Create runtime
Jan Eilers45274902020-10-15 18:34:43 +0100816 std::shared_ptr<armnn::IRuntime> runtime(armnn::IRuntime::Create(ProgramOptions.m_RuntimeOptions));
Finn Williamsd7fcafa2020-04-23 17:55:18 +0100817
Jan Eilers45274902020-10-15 18:34:43 +0100818 std::string modelFormat = ProgramOptions.m_ExNetParams.m_ModelFormat;
819
820 // Forward to implementation based on the parser type
821 if (modelFormat.find("armnn") != std::string::npos)
Finn Williamsd7fcafa2020-04-23 17:55:18 +0100822 {
Jan Eilers45274902020-10-15 18:34:43 +0100823 #if defined(ARMNN_SERIALIZER)
824 return MainImpl<armnnDeserializer::IDeserializer, float>(ProgramOptions.m_ExNetParams, runtime);
825 #else
826 ARMNN_LOG(fatal) << "Not built with serialization support.";
Finn Williamsd7fcafa2020-04-23 17:55:18 +0100827 return EXIT_FAILURE;
Jan Eilers45274902020-10-15 18:34:43 +0100828 #endif
Finn Williamsd7fcafa2020-04-23 17:55:18 +0100829 }
Jan Eilers45274902020-10-15 18:34:43 +0100830 else if (modelFormat.find("onnx") != std::string::npos)
telsoa01c577f2c2018-08-31 09:22:23 +0100831 {
Jan Eilers45274902020-10-15 18:34:43 +0100832 #if defined(ARMNN_ONNX_PARSER)
833 return MainImpl<armnnOnnxParser::IOnnxParser, float>(ProgramOptions.m_ExNetParams, runtime);
834 #else
835 ARMNN_LOG(fatal) << "Not built with Onnx parser support.";
836 return EXIT_FAILURE;
837 #endif
838 }
Jan Eilers45274902020-10-15 18:34:43 +0100839 else if(modelFormat.find("tflite") != std::string::npos)
840 {
Finn Williamsf806c4d2021-02-22 15:13:12 +0000841 if (ProgramOptions.m_ExNetParams.m_TfLiteExecutor == ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteParser)
842 {
843 #if defined(ARMNN_TF_LITE_PARSER)
844 return MainImpl<armnnTfLiteParser::ITfLiteParser, float>(ProgramOptions.m_ExNetParams, runtime);
845 #else
846 ARMNN_LOG(fatal) << "Not built with Tensorflow-Lite parser support.";
847 return EXIT_FAILURE;
848 #endif
849 }
850 else if (ProgramOptions.m_ExNetParams.m_TfLiteExecutor ==
851 ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteDelegate ||
852 ProgramOptions.m_ExNetParams.m_TfLiteExecutor ==
853 ExecuteNetworkParams::TfLiteExecutor::TfliteInterpreter)
Sadik Armagan5d03e312020-11-17 16:43:56 +0000854 {
855 #if defined(ARMNN_TF_LITE_DELEGATE)
856 return TfLiteDelegateMainImpl(ProgramOptions.m_ExNetParams, runtime);
857 #else
Finn Williamsbbbefec2020-11-25 14:32:42 +0000858 ARMNN_LOG(fatal) << "Not built with Arm NN Tensorflow-Lite delegate support.";
Sadik Armagan5d03e312020-11-17 16:43:56 +0000859 return EXIT_FAILURE;
860 #endif
861 }
Jan Eilers45274902020-10-15 18:34:43 +0100862 }
863 else
864 {
865 ARMNN_LOG(fatal) << "Unknown model format: '" << modelFormat
Nikhil Raj5d955cf2021-04-19 16:59:48 +0100866 << "'. Please include 'tflite' or 'onnx'";
Jan Eilers45274902020-10-15 18:34:43 +0100867 return EXIT_FAILURE;
telsoa014fcda012018-03-09 14:13:49 +0000868 }
869}