blob: fd1ef886453986db07ee524b5e6d98fb93a5fff0 [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
John Mcloughlinc5ee0d72023-03-24 12:07:25 +000029 armnn::OptimizerOptionsOpaque 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
John Mcloughlinc5ee0d72023-03-24 12:07:25 +000058 armnn::OptimizerOptionsOpaque 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
John Mcloughlinc5ee0d72023-03-24 12:07:25 +000086 armnn::OptimizerOptionsOpaque optimizerOptions(false, true, false, false);
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +000087 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
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000124 armnn::OptimizerOptionsOpaque 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
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000230 armnn::OptimizerOptionsOpaque optimizerOptions(false, false, false,
231 false, modelOptions, false);
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000232 armnnDelegate::DelegateOptions delegateOptions(backends, optimizerOptions);
233
234 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000235 tensorShape,
236 inputData,
237 inputData,
238 divData,
239 expectedResult,
240 delegateOptions);
241}
242
Colm Donelan3e32a872021-10-04 22:55:37 +0100243TEST_CASE ("ArmnnDelegateSerializeToDot")
244{
245 const fs::path filename(fs::temp_directory_path() / "ArmnnDelegateSerializeToDot.dot");
246 if ( fs::exists(filename) )
247 {
248 fs::remove(filename);
249 }
250 std::stringstream ss;
251 {
252 StreamRedirector redirect(std::cout, ss.rdbuf());
253
254 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
255 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
256 std::vector<float> inputData = { 1, 2, 3, 4 };
257 std::vector<float> divData = { 2, 2, 3, 4 };
258 std::vector<float> expectedResult = { 1, 2, 2, 2 };
259
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000260 armnn::OptimizerOptionsOpaque optimizerOptions(false, false,
261 false, false);
Colm Donelan3e32a872021-10-04 22:55:37 +0100262 armnnDelegate::DelegateOptions delegateOptions(backends, optimizerOptions);
263 // Enable serialize to dot by specifying the target file name.
264 delegateOptions.SetSerializeToDot(filename);
265 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Colm Donelan3e32a872021-10-04 22:55:37 +0100266 tensorShape,
267 inputData,
268 inputData,
269 divData,
270 expectedResult,
271 delegateOptions);
272 }
273 CHECK(fs::exists(filename));
274 // The file should have a size greater than 0 bytes.
275 CHECK(fs::file_size(filename) > 0);
276 // Clean up.
277 fs::remove(filename);
278}
279
Jan Eilersf39f8d82021-10-26 16:57:34 +0100280void CreateFp16StringParsingTestRun(std::vector<std::string>& keys,
281 std::vector<std::string>& values,
282 std::stringstream& ss)
283{
284 StreamRedirector redirect(std::cout, ss.rdbuf());
285
286 std::vector<armnn::BackendId> backends = { armnn::Compute::CpuRef };
287 std::vector<int32_t> tensorShape { 1, 2, 2, 1 };
288 std::vector<float> inputData = { 1, 2, 3, 4 };
289 std::vector<float> divData = { 2, 2, 3, 4 };
290 std::vector<float> expectedResult = { 1, 2, 2, 2 };
291
292 // Create options_keys and options_values char array
293 size_t num_options = keys.size();
294 std::unique_ptr<const char*> options_keys =
295 std::unique_ptr<const char*>(new const char*[num_options + 1]);
296 std::unique_ptr<const char*> options_values =
297 std::unique_ptr<const char*>(new const char*[num_options + 1]);
298 for (size_t i=0; i<num_options; ++i)
299 {
300 options_keys.get()[i] = keys[i].c_str();
301 options_values.get()[i] = values[i].c_str();
302 }
303
John Mcloughlinc5ee0d72023-03-24 12:07:25 +0000304 armnnDelegate::DelegateOptions delegateOptions(options_keys.get(), options_values.get(),
305 num_options, nullptr);
Jan Eilersf39f8d82021-10-26 16:57:34 +0100306 DelegateOptionTest<float>(::tflite::TensorType_FLOAT32,
Jan Eilersf39f8d82021-10-26 16:57:34 +0100307 tensorShape,
308 inputData,
309 inputData,
310 divData,
311 expectedResult,
312 delegateOptions);
313}
314
315TEST_CASE ("ArmnnDelegateStringParsingOptionReduceFp32ToFp16")
316{
317 SUBCASE("Fp16=1")
318 {
319 std::stringstream ss;
320 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16", "logging-severity"};
321 std::vector<std::string> values { "CpuRef", "1", "1", "info"};
322 CreateFp16StringParsingTestRun(keys, values, ss);
323 CHECK(ss.str().find("convert_fp32_to_fp16") != std::string::npos);
324 CHECK(ss.str().find("convert_fp16_to_fp32") != std::string::npos);
325 }
326 SUBCASE("Fp16=true")
327 {
328 std::stringstream ss;
329 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
330 std::vector<std::string> values { "CpuRef", "TRUE", "true"};
331 CreateFp16StringParsingTestRun(keys, values, ss);
332 CHECK(ss.str().find("convert_fp32_to_fp16") != std::string::npos);
333 CHECK(ss.str().find("convert_fp16_to_fp32") != std::string::npos);
334 }
335 SUBCASE("Fp16=True")
336 {
337 std::stringstream ss;
338 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
339 std::vector<std::string> values { "CpuRef", "true", "True"};
340 CreateFp16StringParsingTestRun(keys, values, ss);
341 CHECK(ss.str().find("convert_fp32_to_fp16") != std::string::npos);
342 CHECK(ss.str().find("convert_fp16_to_fp32") != std::string::npos);
343 }
344 SUBCASE("Fp16=0")
345 {
346 std::stringstream ss;
347 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
348 std::vector<std::string> values { "CpuRef", "true", "0"};
349 CreateFp16StringParsingTestRun(keys, values, ss);
350 CHECK(ss.str().find("convert_fp32_to_fp16") == std::string::npos);
351 CHECK(ss.str().find("convert_fp16_to_fp32") == std::string::npos);
352 }
353 SUBCASE("Fp16=false")
354 {
355 std::stringstream ss;
356 std::vector<std::string> keys { "backends", "debug-data", "reduce-fp32-to-fp16"};
357 std::vector<std::string> values { "CpuRef", "1", "false"};
358 CreateFp16StringParsingTestRun(keys, values, ss);
359 CHECK(ss.str().find("convert_fp32_to_fp16") == std::string::npos);
360 CHECK(ss.str().find("convert_fp16_to_fp32") == std::string::npos);
361 }
362}
363
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000364}
365
Narumol Prangnawarat0b51d5a2021-01-20 15:58:29 +0000366} // namespace armnnDelegate