blob: d84d420977393c34be17823b64f59a43b3957a93 [file] [log] [blame]
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +00001//
Teresa Charlinad1b3d72023-03-14 12:10:28 +00002// Copyright © 2021, 2023 Arm Ltd and Contributors. All rights reserved.
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +00003// SPDX-License-Identifier: MIT
4//
5
6#include "DelegateOptionsTestHelper.hpp"
Nikhil Raj7dcc6972021-04-30 15:44:24 +01007#include <common/include/ProfilingGuid.hpp>
Colm Donelan3e32a872021-10-04 22:55:37 +01008#include <armnnUtils/Filesystem.hpp>
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +00009
10namespace armnnDelegate
11{
12
13TEST_SUITE("DelegateOptions")
14{
15
16TEST_CASE ("ArmnnDelegateOptimizerOptionsReduceFp32ToFp16")
17{
18 std::stringstream ss;
19 {
20 StreamRedirector redirect(std::cout, ss.rdbuf());
21
22 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
23 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
24 std::vector<float> inputData = { 1, 2, 3, 4 };
25 std::vector<float> divData = { 2, 2, 3, 4 };
26 std::vector<float> expectedResult = { 1, 2, 2, 2 };
27
28 // Enable ReduceFp32ToFp16
29 armnn::OptimizerOptions optimizerOptions(true, true, false, false);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +000030 armnnDelegate::DelegateOptions delegateOptions(backends, optimizerOptions);
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000031
32 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000033 tensorShape,
34 inputData,
35 inputData,
36 divData,
37 expectedResult,
38 delegateOptions);
39 }
40 // ReduceFp32ToFp16 option is enabled
41 CHECK(ss.str().find("convert_fp32_to_fp16") != std::string::npos);
42 CHECK(ss.str().find("convert_fp16_to_fp32") != std::string::npos);
43}
44
45TEST_CASE ("ArmnnDelegateOptimizerOptionsDebug")
46{
47 std::stringstream ss;
48 {
49 StreamRedirector redirect(std::cout, ss.rdbuf());
50
51 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
52 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
53 std::vector<float> inputData = { 1, 2, 3, 4 };
54 std::vector<float> divData = { 2, 2, 3, 4 };
55 std::vector<float> expectedResult = { 1, 2, 2, 2 };
56
57 // Enable Debug
58 armnn::OptimizerOptions optimizerOptions(false, true, false, false);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +000059 armnnDelegate::DelegateOptions delegateOptions(backends, optimizerOptions);
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000060
61 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000062 tensorShape,
63 inputData,
64 inputData,
65 divData,
66 expectedResult,
67 delegateOptions);
68 }
69 // Debug option triggered.
70 CHECK(ss.str().find("layerGuid") != std::string::npos);
71 CHECK(ss.str().find("layerName") != std::string::npos);
72 CHECK(ss.str().find("outputSlot") != std::string::npos);
73 CHECK(ss.str().find("shape") != std::string::npos);
74 CHECK(ss.str().find("data") != std::string::npos);
75}
76
77TEST_CASE ("ArmnnDelegateOptimizerOptionsDebugFunction")
78{
79 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
80 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
81 std::vector<float> inputData = { 1, 2, 3, 4 };
82 std::vector<float> divData = { 2, 2, 3, 4 };
83 std::vector<float> expectedResult = { 1, 2, 2, 2 };
84
85 // Enable debug with debug callback function
86 armnn::OptimizerOptions optimizerOptions(false, true, false, false);
87 bool callback = false;
Cathal Corbett5aa9fd72022-02-25 15:33:28 +000088 auto mockCallback = [&](LayerGuid guid, unsigned int slotIndex, armnn::ITensorHandle* tensor)
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000089 {
90 armnn::IgnoreUnused(guid);
91 armnn::IgnoreUnused(slotIndex);
92 armnn::IgnoreUnused(tensor);
93 callback = true;
94 };
95
Francis Murtagh73d3e2e2021-04-29 14:23:04 +010096 armnn::INetworkProperties networkProperties(false, armnn::MemorySource::Undefined, armnn::MemorySource::Undefined);
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000097 armnnDelegate::DelegateOptions delegateOptions(backends,
98 optimizerOptions,
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000099 armnn::EmptyOptional(),
100 armnn::Optional<armnn::DebugCallbackFunction>(mockCallback));
101
102 CHECK(!callback);
103
104 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000105 tensorShape,
106 inputData,
107 inputData,
108 divData,
109 expectedResult,
110 delegateOptions);
111
112 // Check that the debug callback function was called.
113 CHECK(callback);
114}
115
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000116TEST_CASE ("ArmnnDelegateOptimizerOptionsImport")
117{
Matthew Sloyanebe392d2023-03-30 10:12:08 +0100118 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000119 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
120 std::vector<uint8_t> inputData = { 1, 2, 3, 4 };
121 std::vector<uint8_t> divData = { 2, 2, 3, 4 };
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000122 std::vector<uint8_t> expectedResult = { 1, 2, 2, 2 };
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000123
124 armnn::OptimizerOptions optimizerOptions(false, false, false, true);
Narumol Prangnawarat74a3cf52021-01-29 15:38:54 +0000125 armnnDelegate::DelegateOptions delegateOptions(backends, optimizerOptions);
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000126
127 DelegateOptionTest<uint8_t>(::tflite::TensorType_UINT8,
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000128 tensorShape,
129 inputData,
130 inputData,
131 divData,
132 expectedResult,
133 delegateOptions);
134}
135
Sadik Armaganca565c12022-08-16 12:17:24 +0100136TEST_CASE ("ArmnnDelegateStringParsingOptionDisableTfLiteRuntimeFallback")
137{
138 std::stringstream stringStream;
139 std::vector<std::string> keys { "backends", "debug-data", "disable-tflite-runtime-fallback"};
140 std::vector<std::string> values { "CpuRef", "1", "1"};
141
142 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
143 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
144 std::vector<float> inputData = { 0.1f, -2.1f, 3.0f, -4.6f };
145 std::vector<float> expectedResult = { 1.0f, -2.0f, 3.0f, -4.0f };
146
147 // Create options_keys and options_values char array
148 size_t num_options = keys.size();
149 std::unique_ptr<const char*> options_keys =
150 std::unique_ptr<const char*>(new const char*[num_options + 1]);
151 std::unique_ptr<const char*> options_values =
152 std::unique_ptr<const char*>(new const char*[num_options + 1]);
153 for (size_t i=0; i<num_options; ++i)
154 {
155 options_keys.get()[i] = keys[i].c_str();
156 options_values.get()[i] = values[i].c_str();
157 }
158
159 StreamRedirector redirect(std::cout, stringStream.rdbuf());
160
161 armnnDelegate::DelegateOptions delegateOptions(options_keys.get(), options_values.get(), num_options, nullptr);
162 DelegateOptionNoFallbackTest<float>(::tflite::TensorType_FLOAT32,
Sadik Armaganca565c12022-08-16 12:17:24 +0100163 tensorShape,
164 inputData,
165 expectedResult,
166 delegateOptions);
167 CHECK(stringStream.str().find("TfLiteArmnnDelegate: There are unsupported operators in the model")
168 != std::string::npos);
169}
170
171TEST_CASE ("ArmnnDelegateStringParsingOptionEnableTfLiteRuntimeFallback")
172{
173 std::stringstream stringStream;
174 std::vector<std::string> keys { "backends", "debug-data", "disable-tflite-runtime-fallback"};
175 std::vector<std::string> values { "CpuRef", "1", "0"};
176
177 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
178 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
179 std::vector<float> inputData = { 0.1f, -2.1f, 3.0f, -4.6f };
180 std::vector<float> expectedResult = { 1.0f, -2.0f, 3.0f, -4.0f };
181
182 // Create options_keys and options_values char array
183 size_t num_options = keys.size();
184 std::unique_ptr<const char*> options_keys =
185 std::unique_ptr<const char*>(new const char*[num_options + 1]);
186 std::unique_ptr<const char*> options_values =
187 std::unique_ptr<const char*>(new const char*[num_options + 1]);
188 for (size_t i=0; i<num_options; ++i)
189 {
190 options_keys.get()[i] = keys[i].c_str();
191 options_values.get()[i] = values[i].c_str();
192 }
193
194 StreamRedirector redirect(std::cout, stringStream.rdbuf());
195
196 armnnDelegate::DelegateOptions delegateOptions(options_keys.get(), options_values.get(), num_options, nullptr);
197 DelegateOptionNoFallbackTest<float>(::tflite::TensorType_FLOAT32,
Sadik Armaganca565c12022-08-16 12:17:24 +0100198 tensorShape,
199 inputData,
200 expectedResult,
201 delegateOptions);
202
203 CHECK(stringStream.str().find("TfLiteArmnnDelegate: There are unsupported operators in the model")
204 == std::string::npos);
205}
206
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000207}
208
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000209TEST_SUITE("DelegateOptions_CpuAccTests")
210{
211
212TEST_CASE ("ArmnnDelegateModelOptions_CpuAcc_Test")
213{
214 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuAcc };
215 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
216 std::vector<float> inputData = { 1, 2, 3, 4 };
217 std::vector<float> divData = { 2, 2, 3, 4 };
218 std::vector<float> expectedResult = { 1, 2, 2, 2 };
219
220 unsigned int numberOfThreads = 2;
221
222 armnn::ModelOptions modelOptions;
223 armnn::BackendOptions cpuAcc("CpuAcc",
224 {
225 { "FastMathEnabled", true },
226 { "NumberOfThreads", numberOfThreads }
227 });
228 modelOptions.push_back(cpuAcc);
229
Francis Murtagh626bd902022-06-21 13:16:23 +0000230 armnn::OptimizerOptions optimizerOptions(false, false, false, false, modelOptions, false);
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000231 armnnDelegate::DelegateOptions delegateOptions(backends, optimizerOptions);
232
233 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000234 tensorShape,
235 inputData,
236 inputData,
237 divData,
238 expectedResult,
239 delegateOptions);
240}
241
Colm Donelan3e32a872021-10-04 22:55:37 +0100242TEST_CASE ("ArmnnDelegateSerializeToDot")
243{
244 const fs::path filename(fs::temp_directory_path() / "ArmnnDelegateSerializeToDot.dot");
245 if ( fs::exists(filename) )
246 {
247 fs::remove(filename);
248 }
249 std::stringstream ss;
250 {
251 StreamRedirector redirect(std::cout, ss.rdbuf());
252
253 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
254 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
255 std::vector<float> inputData = { 1, 2, 3, 4 };
256 std::vector<float> divData = { 2, 2, 3, 4 };
257 std::vector<float> expectedResult = { 1, 2, 2, 2 };
258
259 armnn::OptimizerOptions optimizerOptions(false, false, false, false);
260 armnnDelegate::DelegateOptions delegateOptions(backends, optimizerOptions);
261 // Enable serialize to dot by specifying the target file name.
262 delegateOptions.SetSerializeToDot(filename);
263 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Colm Donelan3e32a872021-10-04 22:55:37 +0100264 tensorShape,
265 inputData,
266 inputData,
267 divData,
268 expectedResult,
269 delegateOptions);
270 }
271 CHECK(fs::exists(filename));
272 // The file should have a size greater than 0 bytes.
273 CHECK(fs::file_size(filename) > 0);
274 // Clean up.
275 fs::remove(filename);
276}
277
Jan Eilersf39f8d82021-10-26 16:57:34 +0100278void CreateFp16StringParsingTestRun(std::vector<std::string>& keys,
279 std::vector<std::string>& values,
280 std::stringstream& ss)
281{
282 StreamRedirector redirect(std::cout, ss.rdbuf());
283
284 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
285 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
286 std::vector<float> inputData = { 1, 2, 3, 4 };
287 std::vector<float> divData = { 2, 2, 3, 4 };
288 std::vector<float> expectedResult = { 1, 2, 2, 2 };
289
290 // Create options_keys and options_values char array
291 size_t num_options = keys.size();
292 std::unique_ptr<const char*> options_keys =
293 std::unique_ptr<const char*>(new const char*[num_options + 1]);
294 std::unique_ptr<const char*> options_values =
295 std::unique_ptr<const char*>(new const char*[num_options + 1]);
296 for (size_t i=0; i<num_options; ++i)
297 {
298 options_keys.get()[i] = keys[i].c_str();
299 options_values.get()[i] = values[i].c_str();
300 }
301
302 armnnDelegate::DelegateOptions delegateOptions(options_keys.get(), options_values.get(), num_options, nullptr);
303 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Jan Eilersf39f8d82021-10-26 16:57:34 +0100304 tensorShape,
305 inputData,
306 inputData,
307 divData,
308 expectedResult,
309 delegateOptions);
310}
311
312TEST_CASE ("ArmnnDelegateStringParsingOptionReduceFp32ToFp16")
313{
314 SUBCASE("Fp16=1")
315 {
316 std::stringstream ss;
317 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16", "logging-severity"};
318 std::vector<std::string> values { "CpuRef", "1", "1", "info"};
319 CreateFp16StringParsingTestRun(keys, values, ss);
320 CHECK(ss.str().find("convert_fp32_to_fp16") != std::string::npos);
321 CHECK(ss.str().find("convert_fp16_to_fp32") != std::string::npos);
322 }
323 SUBCASE("Fp16=true")
324 {
325 std::stringstream ss;
326 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
327 std::vector<std::string> values { "CpuRef", "TRUE", "true"};
328 CreateFp16StringParsingTestRun(keys, values, ss);
329 CHECK(ss.str().find("convert_fp32_to_fp16") != std::string::npos);
330 CHECK(ss.str().find("convert_fp16_to_fp32") != std::string::npos);
331 }
332 SUBCASE("Fp16=True")
333 {
334 std::stringstream ss;
335 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
336 std::vector<std::string> values { "CpuRef", "true", "True"};
337 CreateFp16StringParsingTestRun(keys, values, ss);
338 CHECK(ss.str().find("convert_fp32_to_fp16") != std::string::npos);
339 CHECK(ss.str().find("convert_fp16_to_fp32") != std::string::npos);
340 }
341 SUBCASE("Fp16=0")
342 {
343 std::stringstream ss;
344 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
345 std::vector<std::string> values { "CpuRef", "true", "0"};
346 CreateFp16StringParsingTestRun(keys, values, ss);
347 CHECK(ss.str().find("convert_fp32_to_fp16") == std::string::npos);
348 CHECK(ss.str().find("convert_fp16_to_fp32") == std::string::npos);
349 }
350 SUBCASE("Fp16=false")
351 {
352 std::stringstream ss;
353 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
354 std::vector<std::string> values { "CpuRef", "1", "false"};
355 CreateFp16StringParsingTestRun(keys, values, ss);
356 CHECK(ss.str().find("convert_fp32_to_fp16") == std::string::npos);
357 CHECK(ss.str().find("convert_fp16_to_fp32") == std::string::npos);
358 }
359}
360
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000361}
362
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000363} // namespace armnnDelegate