IVGCVSW-7526 Upgrade ArmNN to Tensorflow 2.12
When creating a flatbuffers model, we need to provide an empty buffer 0 that is
reserved by tensorflow. When creating empty buffers for inputs and outputs we
can not pass in an empty vector, or tflite will assume that we know how many bytes to
allocate in advance. Instead we need to only pass in the builder.
* Update libraries in FindTfLite.cmake
* Add nullptr to delegate struct for OpaqueDelegateBuilder
* Fix issue in unit tests where Flatbuffers model was not being parsed by tflite
* Tensorflow 2.12 now includes C++ 17 features. Update our cmake build
to require a compiler to support these features.
* Change minimum cmake in Arm NN to 3.7 as that's the minimum for the
delegate build.
Signed-off-by: Ryan OShea <ryan.oshea3@arm.com>
Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Signed-off-by: Colm Donelan <colm.donelan@arm.com>
Change-Id: I7d15b196b8c59b1914f8fc1c4c2f8960630c069c
diff --git a/delegate/src/test/SplitTestHelper.hpp b/delegate/src/test/SplitTestHelper.hpp
index 31fc7d5..3c5f50f 100644
--- a/delegate/src/test/SplitTestHelper.hpp
+++ b/delegate/src/test/SplitTestHelper.hpp
@@ -1,5 +1,5 @@
//
-// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2020, 2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
@@ -35,11 +35,12 @@
using namespace tflite;
flatbuffers::FlatBufferBuilder flatBufferBuilder;
- std::array<flatbuffers::Offset<tflite::Buffer>, 2> buffers;
- buffers[0] = CreateBuffer(flatBufferBuilder, flatBufferBuilder.CreateVector({}));
- buffers[1] = CreateBuffer(flatBufferBuilder,
- flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(axisData.data()),
- sizeof(int32_t) * axisData.size()));
+ std::vector<flatbuffers::Offset<tflite::Buffer>> buffers;
+ buffers.push_back(CreateBuffer(flatBufferBuilder));
+ buffers.push_back(CreateBuffer(flatBufferBuilder));
+ buffers.push_back(CreateBuffer(flatBufferBuilder,
+ flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(axisData.data()),
+ sizeof(int32_t) * axisData.size())));
auto quantizationParameters =
CreateQuantizationParameters(flatBufferBuilder,
@@ -53,27 +54,28 @@
flatBufferBuilder.CreateVector<int32_t>(axisTensorShape.data(),
axisTensorShape.size()),
::tflite::TensorType_INT32,
- 1,
+ 2,
flatBufferBuilder.CreateString("axis"),
quantizationParameters);
tensors[1] = CreateTensor(flatBufferBuilder,
flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
inputTensorShape.size()),
tensorType,
- 0,
+ 1,
flatBufferBuilder.CreateString("input"),
quantizationParameters);
// Create output tensor
for (unsigned int i = 0; i < outputTensorShapes.size(); ++i)
{
+ buffers.push_back(CreateBuffer(flatBufferBuilder));
tensors[i + 2] = CreateTensor(flatBufferBuilder,
- flatBufferBuilder.CreateVector<int32_t>(outputTensorShapes[i].data(),
- outputTensorShapes[i].size()),
- tensorType,
- 0,
- flatBufferBuilder.CreateString("output"),
- quantizationParameters);
+ flatBufferBuilder.CreateVector<int32_t>(outputTensorShapes[i].data(),
+ outputTensorShapes[i].size()),
+ tensorType,
+ (i+3),
+ flatBufferBuilder.CreateString("output"),
+ quantizationParameters);
}
// create operator. Mean uses ReducerOptions.
@@ -109,7 +111,7 @@
flatBufferBuilder.CreateVector(&operatorCode, 1),
flatBufferBuilder.CreateVector(&subgraph, 1),
modelDescription,
- flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
+ flatBufferBuilder.CreateVector(buffers));
flatBufferBuilder.Finish(flatbufferModel);
@@ -144,21 +146,21 @@
// Create TfLite Interpreters
std::unique_ptr<Interpreter> armnnDelegate;
CHECK(InterpreterBuilder(tfLiteModel, ::tflite::ops::builtin::BuiltinOpResolver())
- (&armnnDelegate) == kTfLiteOk);
+ (&armnnDelegate) == kTfLiteOk);
CHECK(armnnDelegate != nullptr);
CHECK(armnnDelegate->AllocateTensors() == kTfLiteOk);
std::unique_ptr<Interpreter> tfLiteDelegate;
CHECK(InterpreterBuilder(tfLiteModel, ::tflite::ops::builtin::BuiltinOpResolver())
- (&tfLiteDelegate) == kTfLiteOk);
+ (&tfLiteDelegate) == kTfLiteOk);
CHECK(tfLiteDelegate != nullptr);
CHECK(tfLiteDelegate->AllocateTensors() == kTfLiteOk);
// Create the ArmNN Delegate
armnnDelegate::DelegateOptions delegateOptions(backends);
std::unique_ptr<TfLiteDelegate, decltype(&armnnDelegate::TfLiteArmnnDelegateDelete)>
- theArmnnDelegate(armnnDelegate::TfLiteArmnnDelegateCreate(delegateOptions),
- armnnDelegate::TfLiteArmnnDelegateDelete);
+ theArmnnDelegate(armnnDelegate::TfLiteArmnnDelegateCreate(delegateOptions),
+ armnnDelegate::TfLiteArmnnDelegateDelete);
CHECK(theArmnnDelegate != nullptr);
// Modify armnnDelegateInterpreter to use armnnDelegate
@@ -210,11 +212,11 @@
sizeof(int32_t) * axisData.size()));
auto quantizationParameters =
- CreateQuantizationParameters(flatBufferBuilder,
- 0,
- 0,
- flatBufferBuilder.CreateVector<float>({ quantScale }),
- flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
+ CreateQuantizationParameters(flatBufferBuilder,
+ 0,
+ 0,
+ flatBufferBuilder.CreateVector<float>({ quantScale }),
+ flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
std::array<flatbuffers::Offset<Tensor>, 5> tensors;
tensors[0] = CreateTensor(flatBufferBuilder,
@@ -258,33 +260,33 @@
const std::vector<int> operatorInputs{ {0, 1, 2} };
const std::vector<int> operatorOutputs{ {3, 4} };
flatbuffers::Offset <Operator> controlOperator =
- CreateOperator(flatBufferBuilder,
- 0,
- flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
- flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
- operatorBuiltinOptionsType,
- operatorBuiltinOptions);
+ CreateOperator(flatBufferBuilder,
+ 0,
+ flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
+ flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
+ operatorBuiltinOptionsType,
+ operatorBuiltinOptions);
const std::vector<int> subgraphInputs{ {0, 1, 2} };
const std::vector<int> subgraphOutputs{ {3, 4} };
flatbuffers::Offset <SubGraph> subgraph =
- CreateSubGraph(flatBufferBuilder,
- flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
- flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
- flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
- flatBufferBuilder.CreateVector(&controlOperator, 1));
+ CreateSubGraph(flatBufferBuilder,
+ flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
+ flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
+ flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
+ flatBufferBuilder.CreateVector(&controlOperator, 1));
flatbuffers::Offset <flatbuffers::String> modelDescription =
- flatBufferBuilder.CreateString("ArmnnDelegate: SPLIT_V Operator Model");
+ flatBufferBuilder.CreateString("ArmnnDelegate: SPLIT_V Operator Model");
flatbuffers::Offset <OperatorCode> operatorCode = CreateOperatorCode(flatBufferBuilder, BuiltinOperator_SPLIT_V);
flatbuffers::Offset <Model> flatbufferModel =
- CreateModel(flatBufferBuilder,
- TFLITE_SCHEMA_VERSION,
- flatBufferBuilder.CreateVector(&operatorCode, 1),
- flatBufferBuilder.CreateVector(&subgraph, 1),
- modelDescription,
- flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
+ CreateModel(flatBufferBuilder,
+ TFLITE_SCHEMA_VERSION,
+ flatBufferBuilder.CreateVector(&operatorCode, 1),
+ flatBufferBuilder.CreateVector(&subgraph, 1),
+ modelDescription,
+ flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
flatBufferBuilder.Finish(flatbufferModel);