diff options
author | Teresa Charlin <teresa.charlinreyes@arm.com> | 2022-07-07 14:24:59 +0100 |
---|---|---|
committer | Nikhil Raj <nikhil.raj@arm.com> | 2022-07-28 15:08:22 +0100 |
commit | 83b429107a4bb1fe84e756c29d8ad3771d4beeee (patch) | |
tree | c383d2692365a8166b949f90267e152f0624704f /tests/ExecuteNetwork/TfliteExecutor.cpp | |
parent | 46f298657c14c1b0a4b0690ecce49f64dc0a7010 (diff) | |
download | armnn-83b429107a4bb1fe84e756c29d8ad3771d4beeee.tar.gz |
Revert "Revert "IVGCVSW-6650 Refactor ExecuteNetwork""
This reverts commit 1a7f033768acb27da11503bd29abb468d2e77f9e.
List of fixes to be able to add this code again:
* "emplacing_back" the vector inputTensors into the vector m_InputTensorsVec outside the for loop
* GetIOInfo() uses IOptimizedNetwork instead of INetwork, where the infered shapes are not saved
* Add missing data type Signed32 to SetupInputsAndOutputs()
* PrintOutputTensors() prints the actual output without dequantizing
* Add profilingDetailsMethod as input in networkProperties in ArmNNExecutor constructor
* Fix typos
Change-Id: I91de166f87228282db3efa27431fe91458834442
Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com>
Change-Id: Ic6634d48892d11e5f146cdf285e1e333e93e9937
Signed-off-by: Francis Murtagh <francis.murtagh@arm.com>
Diffstat (limited to 'tests/ExecuteNetwork/TfliteExecutor.cpp')
-rw-r--r-- | tests/ExecuteNetwork/TfliteExecutor.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/tests/ExecuteNetwork/TfliteExecutor.cpp b/tests/ExecuteNetwork/TfliteExecutor.cpp new file mode 100644 index 0000000000..dc495be5c3 --- /dev/null +++ b/tests/ExecuteNetwork/TfliteExecutor.cpp @@ -0,0 +1,251 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "TfliteExecutor.hpp" + +TfLiteExecutor::TfLiteExecutor(const ExecuteNetworkParams& params) : m_Params(params) +{ + std::unique_ptr<tflite::FlatBufferModel> model = + tflite::FlatBufferModel::BuildFromFile(m_Params.m_ModelPath.c_str()); + + m_TfLiteInterpreter = std::make_unique<Interpreter>(); + tflite::ops::builtin::BuiltinOpResolver resolver; + + tflite::InterpreterBuilder builder(*model, resolver); + builder(&m_TfLiteInterpreter); + m_TfLiteInterpreter->AllocateTensors(); + + int status = kTfLiteError; + if (m_Params.m_TfLiteExecutor == ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteDelegate) + { + // Create the Armnn Delegate + // Populate a DelegateOptions from the ExecuteNetworkParams. + armnnDelegate::DelegateOptions delegateOptions = m_Params.ToDelegateOptions(); + delegateOptions.SetExternalProfilingParams(delegateOptions.GetExternalProfilingParams()); + + std::unique_ptr<TfLiteDelegate, decltype(&armnnDelegate::TfLiteArmnnDelegateDelete)> + theArmnnDelegate(armnnDelegate::TfLiteArmnnDelegateCreate(delegateOptions), + armnnDelegate::TfLiteArmnnDelegateDelete); + // Register armnn_delegate to TfLiteInterpreter + status = m_TfLiteInterpreter->ModifyGraphWithDelegate(std::move(theArmnnDelegate)); + if (status == kTfLiteError) + { + LogAndThrow("Could not register ArmNN TfLite Delegate to TfLiteInterpreter"); + } + } + else + { + std::cout << "Running on TfLite without ArmNN delegate\n"; + } + + armnn::Optional<std::string> dataFile = m_Params.m_GenerateTensorData + ? armnn::EmptyOptional() + : armnn::MakeOptional<std::string>(m_Params.m_InputTensorDataFilePaths[0]); + + const size_t numInputs = m_Params.m_InputNames.size(); + + for(unsigned int inputIndex = 0; inputIndex < numInputs; ++inputIndex) + { + int input = m_TfLiteInterpreter->inputs()[inputIndex]; + + TfLiteIntArray* inputDims = m_TfLiteInterpreter->tensor(input)->dims; + + unsigned int inputSize = 1; + for (unsigned int dim = 0; dim < static_cast<unsigned int>(inputDims->size); ++dim) + { + inputSize *= inputDims->data[dim]; + } + + const auto& inputName = m_TfLiteInterpreter->input_tensor(input)->name; + const auto& dataType = m_TfLiteInterpreter->input_tensor(input)->type; + + switch (dataType) + { + case kTfLiteFloat32: + { + auto inputData = m_TfLiteInterpreter->typed_tensor<float>(input); + PopulateTensorWithData(inputData, inputSize, dataFile, inputName); + break; + } + case kTfLiteInt32: + { + auto inputData = m_TfLiteInterpreter->typed_tensor<int>(input); + PopulateTensorWithData(inputData, inputSize, dataFile, inputName); + break; + } + case kTfLiteUInt8: + { + auto inputData = m_TfLiteInterpreter->typed_tensor<uint8_t>(input); + PopulateTensorWithData(inputData, inputSize, dataFile, inputName); + break; + } + case kTfLiteInt16: + { + auto inputData = m_TfLiteInterpreter->typed_tensor<int16_t>(input); + PopulateTensorWithData(inputData, inputSize, dataFile, inputName); + break; + } + case kTfLiteInt8: + { + auto inputData = m_TfLiteInterpreter->typed_tensor<int8_t>(input); + PopulateTensorWithData(inputData, inputSize, dataFile, inputName); + break; + } + default: + { + LogAndThrow("Unsupported input tensor data type"); + } + } + } +} + +std::vector<const void *> TfLiteExecutor::Execute() +{ + int status = 0; + std::vector<const void*> results; + for (size_t x = 0; x < m_Params.m_Iterations; x++) + { + // Start timer to record inference time in milliseconds. + const auto start_time = armnn::GetTimeNow(); + // Run the inference + status = m_TfLiteInterpreter->Invoke(); + const auto duration = armnn::GetTimeDuration(start_time); + + if (m_Params.m_DontPrintOutputs || m_Params.m_ReuseBuffers) + { + break; + } + // Print out the output + for (unsigned int outputIndex = 0; outputIndex < m_TfLiteInterpreter->outputs().size(); ++outputIndex) + { + auto tfLiteDelegateOutputId = m_TfLiteInterpreter->outputs()[outputIndex]; + TfLiteIntArray* outputDims = m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->dims; + // If we've been asked to write to a file then set a file output stream. Otherwise use stdout. + FILE* outputTensorFile = stdout; + if (!m_Params.m_OutputTensorFiles.empty()) + { + outputTensorFile = fopen(m_Params.m_OutputTensorFiles[outputIndex].c_str(), "w"); + if (outputTensorFile == NULL) + { + LogAndThrow("Specified output tensor file, \"" + m_Params.m_OutputTensorFiles[outputIndex] + + "\", cannot be created. Defaulting to stdout. Error was: " + std::strerror(errno)); + } + else + { + ARMNN_LOG(info) << "Writing output " << outputIndex << "' of iteration: " << x+1 << " to file: '" + << m_Params.m_OutputTensorFiles[outputIndex] << "'"; + } + } + long outputSize = 1; + for (unsigned int dim = 0; dim < static_cast<unsigned int>(outputDims->size); ++dim) + { + outputSize *= outputDims->data[dim]; + } + + std::cout << m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->name << ": "; + results.push_back(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation); + + switch (m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->type) + { + + case kTfLiteFloat32: + { + auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<float>(tfLiteDelegateOutputId); + + for (int i = 0; i < outputSize; ++i) + { + fprintf(outputTensorFile, "%f ", tfLiteDelageOutputData[i]); + } + break; + } + case kTfLiteInt32: + { + auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<int32_t>(tfLiteDelegateOutputId); + for (int i = 0; i < outputSize; ++i) + { + fprintf(outputTensorFile, "%d ", tfLiteDelageOutputData[i]); + } + break; + } + case kTfLiteUInt8: + { + auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<uint8_t>(tfLiteDelegateOutputId); + for (int i = 0; i < outputSize; ++i) + { + fprintf(outputTensorFile, "%u ", tfLiteDelageOutputData[i]); + } + break; + } + case kTfLiteInt8: + { + auto tfLiteDelageOutputData = m_TfLiteInterpreter->typed_tensor<int8_t>(tfLiteDelegateOutputId); + for (int i = 0; i < outputSize; ++i) + { + fprintf(outputTensorFile, "%d ", tfLiteDelageOutputData[i]); + } + break; + } + default: + { + LogAndThrow("Unsupported output type"); + } + } + + std::cout << std::endl; + } + CheckInferenceTimeThreshold(duration, m_Params.m_ThresholdTime); + } + + std::cout << status; + return results; +} + +void TfLiteExecutor::CompareAndPrintResult(std::vector<const void*> otherOutput) +{ + for (unsigned int outputIndex = 0; outputIndex < m_TfLiteInterpreter->outputs().size(); ++outputIndex) + { + auto tfLiteDelegateOutputId = m_TfLiteInterpreter->outputs()[outputIndex]; + float result = 0; + switch (m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->type) + { + case kTfLiteFloat32: + { + result = ComputeRMSE<float>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation, + otherOutput[outputIndex], + m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes); + + break; + } + case kTfLiteInt32: + { + result = ComputeRMSE<int32_t>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation, + otherOutput[outputIndex], + m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes); + break; + } + case kTfLiteUInt8: + { + result = ComputeRMSE<uint8_t>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation, + otherOutput[outputIndex], + m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes); + break; + } + case kTfLiteInt8: + { + result = ComputeRMSE<int8_t>(m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->allocation, + otherOutput[outputIndex], + m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->bytes); + break; + } + default: + { + } + } + + std::cout << "RMSE of " + << m_TfLiteInterpreter->tensor(tfLiteDelegateOutputId)->name + << ": " << result << std::endl; + } +}; |