blob: cde69c2f90829a1d7a87a0d54c64c909ebf55453 [file] [log] [blame]
Matthew Sloyan91c41712020-11-13 09:47:35 +00001//
Colm Donelan7bcae3c2024-01-22 10:07:14 +00002// Copyright © 2020, 2023-2024 Arm Ltd and Contributors. All rights reserved.
Matthew Sloyan91c41712020-11-13 09:47:35 +00003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
8#include "TestUtils.hpp"
9
10#include <armnn_delegate.hpp>
Matthew Sloyanebe392d2023-03-30 10:12:08 +010011#include <DelegateTestInterpreter.hpp>
Matthew Sloyan91c41712020-11-13 09:47:35 +000012
Matthew Sloyan91c41712020-11-13 09:47:35 +000013#include <tensorflow/lite/version.h>
14
Matthew Sloyan91c41712020-11-13 09:47:35 +000015namespace
16{
17
18std::vector<char> CreateConcatTfLiteModel(tflite::BuiltinOperator controlOperatorCode,
19 tflite::TensorType tensorType,
20 std::vector<int32_t>& inputTensorShape,
21 const std::vector <int32_t>& outputTensorShape,
22 const int32_t inputTensorNum,
23 int32_t axis = 0,
24 float quantScale = 1.0f,
25 int quantOffset = 0)
26{
27 using namespace tflite;
28 flatbuffers::FlatBufferBuilder flatBufferBuilder;
29
30 std::vector<flatbuffers::Offset<tflite::Buffer>> buffers;
Ryan OShea238ecd92023-03-07 11:44:23 +000031 buffers.push_back(CreateBuffer(flatBufferBuilder));
32 buffers.push_back(CreateBuffer(flatBufferBuilder));
33 buffers.push_back(CreateBuffer(flatBufferBuilder));
Matthew Sloyan91c41712020-11-13 09:47:35 +000034
35 auto quantizationParameters =
36 CreateQuantizationParameters(flatBufferBuilder,
37 0,
38 0,
39 flatBufferBuilder.CreateVector<float>({ quantScale }),
40 flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
41
42 std::vector<int32_t> operatorInputs{};
43 const std::vector<int32_t> operatorOutputs{inputTensorNum};
44 std::vector<int> subgraphInputs{};
45 const std::vector<int> subgraphOutputs{inputTensorNum};
46
47 std::vector<flatbuffers::Offset<Tensor>> tensors(inputTensorNum + 1);
48 for (int i = 0; i < inputTensorNum; ++i)
49 {
50 tensors[i] = CreateTensor(flatBufferBuilder,
51 flatBufferBuilder.CreateVector<int32_t>(inputTensorShape.data(),
52 inputTensorShape.size()),
53 tensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +000054 1,
Matthew Sloyan91c41712020-11-13 09:47:35 +000055 flatBufferBuilder.CreateString("input" + std::to_string(i)),
56 quantizationParameters);
57
58 // Add number of inputs to vector.
59 operatorInputs.push_back(i);
60 subgraphInputs.push_back(i);
61 }
62
63 // Create output tensor
64 tensors[inputTensorNum] = CreateTensor(flatBufferBuilder,
65 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
66 outputTensorShape.size()),
67 tensorType,
Ryan OShea238ecd92023-03-07 11:44:23 +000068 2,
Matthew Sloyan91c41712020-11-13 09:47:35 +000069 flatBufferBuilder.CreateString("output"),
70 quantizationParameters);
71
72 // create operator
73 tflite::BuiltinOptions operatorBuiltinOptionsType = tflite::BuiltinOptions_ConcatenationOptions;
74 flatbuffers::Offset<void> operatorBuiltinOptions = CreateConcatenationOptions(flatBufferBuilder, axis).Union();
75
76 flatbuffers::Offset <Operator> controlOperator =
77 CreateOperator(flatBufferBuilder,
78 0,
79 flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
80 flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
81 operatorBuiltinOptionsType,
82 operatorBuiltinOptions);
83
84 flatbuffers::Offset <SubGraph> subgraph =
85 CreateSubGraph(flatBufferBuilder,
86 flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
87 flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
88 flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
89 flatBufferBuilder.CreateVector(&controlOperator, 1));
90
91 flatbuffers::Offset <flatbuffers::String> modelDescription =
92 flatBufferBuilder.CreateString("ArmnnDelegate: Concatenation Operator Model");
93 flatbuffers::Offset <OperatorCode> operatorCode = CreateOperatorCode(flatBufferBuilder, controlOperatorCode);
94
95 flatbuffers::Offset <Model> flatbufferModel =
96 CreateModel(flatBufferBuilder,
97 TFLITE_SCHEMA_VERSION,
98 flatBufferBuilder.CreateVector(&operatorCode, 1),
99 flatBufferBuilder.CreateVector(&subgraph, 1),
100 modelDescription,
101 flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
102
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100103 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000104
105 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
106 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
107}
108
109std::vector<char> CreateMeanTfLiteModel(tflite::BuiltinOperator controlOperatorCode,
110 tflite::TensorType tensorType,
111 std::vector<int32_t>& input0TensorShape,
112 std::vector<int32_t>& input1TensorShape,
113 const std::vector <int32_t>& outputTensorShape,
114 std::vector<int32_t>& axisData,
115 const bool keepDims,
116 float quantScale = 1.0f,
117 int quantOffset = 0)
118{
119 using namespace tflite;
120 flatbuffers::FlatBufferBuilder flatBufferBuilder;
121
122 std::array<flatbuffers::Offset<tflite::Buffer>, 2> buffers;
Ryan OShea238ecd92023-03-07 11:44:23 +0000123 buffers[0] = CreateBuffer(flatBufferBuilder);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000124 buffers[1] = CreateBuffer(flatBufferBuilder,
125 flatBufferBuilder.CreateVector(reinterpret_cast<const uint8_t*>(axisData.data()),
126 sizeof(int32_t) * axisData.size()));
127
128 auto quantizationParameters =
129 CreateQuantizationParameters(flatBufferBuilder,
130 0,
131 0,
132 flatBufferBuilder.CreateVector<float>({ quantScale }),
133 flatBufferBuilder.CreateVector<int64_t>({ quantOffset }));
134
135 std::array<flatbuffers::Offset<Tensor>, 3> tensors;
136 tensors[0] = CreateTensor(flatBufferBuilder,
137 flatBufferBuilder.CreateVector<int32_t>(input0TensorShape.data(),
138 input0TensorShape.size()),
139 tensorType,
140 0,
141 flatBufferBuilder.CreateString("input"),
142 quantizationParameters);
143
144 tensors[1] = CreateTensor(flatBufferBuilder,
145 flatBufferBuilder.CreateVector<int32_t>(input1TensorShape.data(),
146 input1TensorShape.size()),
147 ::tflite::TensorType_INT32,
148 1,
149 flatBufferBuilder.CreateString("axis"),
150 quantizationParameters);
151
152 // Create output tensor
153 tensors[2] = CreateTensor(flatBufferBuilder,
154 flatBufferBuilder.CreateVector<int32_t>(outputTensorShape.data(),
155 outputTensorShape.size()),
156 tensorType,
157 0,
158 flatBufferBuilder.CreateString("output"),
159 quantizationParameters);
160
161 // create operator. Mean uses ReducerOptions.
162 tflite::BuiltinOptions operatorBuiltinOptionsType = tflite::BuiltinOptions_ReducerOptions;
163 flatbuffers::Offset<void> operatorBuiltinOptions = CreateReducerOptions(flatBufferBuilder, keepDims).Union();
164
165 const std::vector<int> operatorInputs{ {0, 1} };
166 const std::vector<int> operatorOutputs{ 2 };
167 flatbuffers::Offset <Operator> controlOperator =
168 CreateOperator(flatBufferBuilder,
169 0,
170 flatBufferBuilder.CreateVector<int32_t>(operatorInputs.data(), operatorInputs.size()),
171 flatBufferBuilder.CreateVector<int32_t>(operatorOutputs.data(), operatorOutputs.size()),
172 operatorBuiltinOptionsType,
173 operatorBuiltinOptions);
174
175 const std::vector<int> subgraphInputs{ {0, 1} };
176 const std::vector<int> subgraphOutputs{ 2 };
177 flatbuffers::Offset <SubGraph> subgraph =
178 CreateSubGraph(flatBufferBuilder,
179 flatBufferBuilder.CreateVector(tensors.data(), tensors.size()),
180 flatBufferBuilder.CreateVector<int32_t>(subgraphInputs.data(), subgraphInputs.size()),
181 flatBufferBuilder.CreateVector<int32_t>(subgraphOutputs.data(), subgraphOutputs.size()),
182 flatBufferBuilder.CreateVector(&controlOperator, 1));
183
184 flatbuffers::Offset <flatbuffers::String> modelDescription =
185 flatBufferBuilder.CreateString("ArmnnDelegate: Mean Operator Model");
186 flatbuffers::Offset <OperatorCode> operatorCode = CreateOperatorCode(flatBufferBuilder, controlOperatorCode);
187
188 flatbuffers::Offset <Model> flatbufferModel =
189 CreateModel(flatBufferBuilder,
190 TFLITE_SCHEMA_VERSION,
191 flatBufferBuilder.CreateVector(&operatorCode, 1),
192 flatBufferBuilder.CreateVector(&subgraph, 1),
193 modelDescription,
194 flatBufferBuilder.CreateVector(buffers.data(), buffers.size()));
195
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100196 flatBufferBuilder.Finish(flatbufferModel, armnnDelegate::FILE_IDENTIFIER);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000197
198 return std::vector<char>(flatBufferBuilder.GetBufferPointer(),
199 flatBufferBuilder.GetBufferPointer() + flatBufferBuilder.GetSize());
200}
201
202template <typename T>
203void ConcatenationTest(tflite::BuiltinOperator controlOperatorCode,
204 tflite::TensorType tensorType,
Matthew Sloyan91c41712020-11-13 09:47:35 +0000205 std::vector<int32_t>& inputShapes,
206 std::vector<int32_t>& expectedOutputShape,
207 std::vector<std::vector<T>>& inputValues,
208 std::vector<T>& expectedOutputValues,
209 int32_t axis = 0,
210 float quantScale = 1.0f,
Colm Donelaneff204a2023-11-28 15:46:09 +0000211 int quantOffset = 0,
212 const std::vector<armnn::BackendId>& backends = {})
Matthew Sloyan91c41712020-11-13 09:47:35 +0000213{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100214 using namespace delegateTestInterpreter;
Matthew Sloyan91c41712020-11-13 09:47:35 +0000215 std::vector<char> modelBuffer = CreateConcatTfLiteModel(controlOperatorCode,
216 tensorType,
217 inputShapes,
218 expectedOutputShape,
219 inputValues.size(),
220 axis,
221 quantScale,
222 quantOffset);
223
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100224 // Setup interpreter with just TFLite Runtime.
225 auto tfLiteInterpreter = DelegateTestInterpreter(modelBuffer);
226 CHECK(tfLiteInterpreter.AllocateTensors() == kTfLiteOk);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000227
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100228 // Setup interpreter with Arm NN Delegate applied.
Colm Donelaneff204a2023-11-28 15:46:09 +0000229 auto armnnInterpreter = DelegateTestInterpreter(modelBuffer, CaptureAvailableBackends(backends));
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100230 CHECK(armnnInterpreter.AllocateTensors() == kTfLiteOk);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000231
Matthew Sloyan91c41712020-11-13 09:47:35 +0000232 for (unsigned int i = 0; i < inputValues.size(); ++i)
233 {
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100234 CHECK(tfLiteInterpreter.FillInputTensor<T>(inputValues[i], i) == kTfLiteOk);
235 CHECK(armnnInterpreter.FillInputTensor<T>(inputValues[i], i) == kTfLiteOk);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000236 }
237
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100238 CHECK(tfLiteInterpreter.Invoke() == kTfLiteOk);
239 std::vector<T> tfLiteOutputValues = tfLiteInterpreter.GetOutputResult<T>(0);
240 std::vector<int32_t> tfLiteOutputShape = tfLiteInterpreter.GetOutputShape(0);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000241
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100242 CHECK(armnnInterpreter.Invoke() == kTfLiteOk);
243 std::vector<T> armnnOutputValues = armnnInterpreter.GetOutputResult<T>(0);
244 std::vector<int32_t> armnnOutputShape = armnnInterpreter.GetOutputShape(0);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000245
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100246 armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
247 armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, expectedOutputShape);
248
249 tfLiteInterpreter.Cleanup();
250 armnnInterpreter.Cleanup();
Matthew Sloyan91c41712020-11-13 09:47:35 +0000251}
252
253template <typename T>
254void MeanTest(tflite::BuiltinOperator controlOperatorCode,
255 tflite::TensorType tensorType,
Matthew Sloyan91c41712020-11-13 09:47:35 +0000256 std::vector<int32_t>& input0Shape,
257 std::vector<int32_t>& input1Shape,
258 std::vector<int32_t>& expectedOutputShape,
259 std::vector<T>& input0Values,
260 std::vector<int32_t>& input1Values,
261 std::vector<T>& expectedOutputValues,
262 const bool keepDims,
263 float quantScale = 1.0f,
Colm Donelaneff204a2023-11-28 15:46:09 +0000264 int quantOffset = 0,
265 const std::vector<armnn::BackendId>& backends = {})
Matthew Sloyan91c41712020-11-13 09:47:35 +0000266{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100267 using namespace delegateTestInterpreter;
Matthew Sloyan91c41712020-11-13 09:47:35 +0000268 std::vector<char> modelBuffer = CreateMeanTfLiteModel(controlOperatorCode,
269 tensorType,
270 input0Shape,
271 input1Shape,
272 expectedOutputShape,
273 input1Values,
274 keepDims,
275 quantScale,
276 quantOffset);
277
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100278 // Setup interpreter with just TFLite Runtime.
279 auto tfLiteInterpreter = DelegateTestInterpreter(modelBuffer);
280 CHECK(tfLiteInterpreter.AllocateTensors() == kTfLiteOk);
281 CHECK(tfLiteInterpreter.FillInputTensor<T>(input0Values, 0) == kTfLiteOk);
282 CHECK(tfLiteInterpreter.Invoke() == kTfLiteOk);
283 std::vector<T> tfLiteOutputValues = tfLiteInterpreter.GetOutputResult<T>(0);
284 std::vector<int32_t> tfLiteOutputShape = tfLiteInterpreter.GetOutputShape(0);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000285
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100286 // Setup interpreter with Arm NN Delegate applied.
Colm Donelaneff204a2023-11-28 15:46:09 +0000287 auto armnnInterpreter = DelegateTestInterpreter(modelBuffer, CaptureAvailableBackends(backends));
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100288 CHECK(armnnInterpreter.AllocateTensors() == kTfLiteOk);
289 CHECK(armnnInterpreter.FillInputTensor<T>(input0Values, 0) == kTfLiteOk);
290 CHECK(armnnInterpreter.Invoke() == kTfLiteOk);
291 std::vector<T> armnnOutputValues = armnnInterpreter.GetOutputResult<T>(0);
292 std::vector<int32_t> armnnOutputShape = armnnInterpreter.GetOutputShape(0);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000293
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100294 armnnDelegate::CompareOutputData<T>(tfLiteOutputValues, armnnOutputValues, expectedOutputValues);
295 armnnDelegate::CompareOutputShape(tfLiteOutputShape, armnnOutputShape, expectedOutputShape);
Matthew Sloyan91c41712020-11-13 09:47:35 +0000296
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100297 tfLiteInterpreter.Cleanup();
298 armnnInterpreter.Cleanup();
Matthew Sloyan91c41712020-11-13 09:47:35 +0000299}
300
301} // anonymous namespace