• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2017,2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "DebugTestImpl.hpp"
7 
8 #include <armnnUtils/QuantizeHelper.hpp>
9 #include <armnnUtils/Filesystem.hpp>
10 #include <ResolveType.hpp>
11 
12 #include <armnnTestUtils/TensorCopyUtils.hpp>
13 #include <armnnTestUtils/WorkloadTestUtils.hpp>
14 
15 #include <armnnTestUtils/TensorHelpers.hpp>
16 
17 #include <doctest/doctest.h>
18 #include <armnnUtils/Filesystem.hpp>
19 
20 namespace
21 {
22 
23 template<typename T, std::size_t Dim>
DebugTestImpl(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,armnn::TensorInfo & inputTensorInfo,armnn::TensorInfo & outputTensorInfo,std::vector<float> & inputData,std::vector<float> & outputExpectedData,armnn::DebugQueueDescriptor descriptor,const std::string expectedStringOutput,const std::string & layerName,bool toFile,const float qScale=1.0f,const int32_t qOffset=0)24 LayerTestResult<T, Dim> DebugTestImpl(
25     armnn::IWorkloadFactory& workloadFactory,
26     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
27     armnn::TensorInfo& inputTensorInfo,
28     armnn::TensorInfo& outputTensorInfo,
29     std::vector<float>& inputData,
30     std::vector<float>& outputExpectedData,
31     armnn::DebugQueueDescriptor descriptor,
32     const std::string expectedStringOutput,
33     const std::string& layerName,
34     bool toFile,
35     const float qScale = 1.0f,
36     const int32_t qOffset = 0)
37 {
38     IgnoreUnused(memoryManager);
39     if(armnn::IsQuantizedType<T>())
40     {
41         inputTensorInfo.SetQuantizationScale(qScale);
42         inputTensorInfo.SetQuantizationOffset(qOffset);
43 
44         outputTensorInfo.SetQuantizationScale(qScale);
45         outputTensorInfo.SetQuantizationOffset(qOffset);
46     }
47 
48     std::vector<T> input = armnnUtils::QuantizedVector<T>(inputData, qScale, qOffset);
49 
50     std::vector<T> actualOutput(outputTensorInfo.GetNumElements());
51     std::vector<T> expectedOutput = armnnUtils::QuantizedVector<T>(outputExpectedData, qScale, qOffset);
52 
53     ARMNN_NO_DEPRECATE_WARN_BEGIN
54     std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
55     std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
56     ARMNN_NO_DEPRECATE_WARN_END
57 
58     armnn::WorkloadInfo info;
59     AddInputToWorkload(descriptor, info, inputTensorInfo, inputHandle.get());
60     AddOutputToWorkload(descriptor, info, outputTensorInfo, outputHandle.get());
61 
62     std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateWorkload(armnn::LayerType::Debug,
63                                                                                 descriptor,
64                                                                                 info);
65 
66     inputHandle->Allocate();
67     outputHandle->Allocate();
68 
69     CopyDataToITensorHandle(inputHandle.get(), input.data());
70 
71     if (toFile)
72     {
73         // Given that this is dependent on an ExNet switch, we need to explicitly set the directory that the
74         //  files are stored in as this happens within the ExNet flow
75         auto tmpDir = armnnUtils::Filesystem::CreateDirectory("/ArmNNIntermediateLayerOutputs");
76         std::string full_path = tmpDir + layerName + ".numpy";
77 
78         ExecuteWorkload(*workload, memoryManager);
79 
80         armnnUtils::Filesystem::FileContents output = armnnUtils::Filesystem::ReadFileContentsIntoString(full_path);
81         CHECK((output == expectedStringOutput));
82 
83         // Clean up afterwards.
84         armnnUtils::Filesystem::RemoveDirectoryAndContents(tmpDir);
85     }
86     else
87     {
88         std::ostringstream oss;
89         std::streambuf* coutStreambuf = std::cout.rdbuf();
90         std::cout.rdbuf(oss.rdbuf());
91 
92         ExecuteWorkload(*workload, memoryManager);
93 
94         std::cout.rdbuf(coutStreambuf);
95         CHECK(oss.str() == expectedStringOutput);
96     }
97 
98     CopyDataFromITensorHandle(actualOutput.data(), outputHandle.get());
99 
100     return LayerTestResult<T, Dim>(actualOutput,
101                                    expectedOutput,
102                                    outputHandle->GetShape(),
103                                    outputTensorInfo.GetShape());
104 }
105 
106 template <armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Debug4dTest(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)107 LayerTestResult<T, 4> Debug4dTest(
108     armnn::IWorkloadFactory& workloadFactory,
109     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
110     bool toFile = false)
111 {
112     armnn::TensorInfo inputTensorInfo;
113     armnn::TensorInfo outputTensorInfo;
114 
115     unsigned int inputShape[]  = {1, 2, 2, 3};
116     unsigned int outputShape[] = {1, 2, 2, 3};
117 
118     armnn::DebugQueueDescriptor desc;
119     desc.m_Guid = 1;
120     desc.m_LayerName = "TestOutput";
121     desc.m_SlotIndex = 0;
122     desc.m_LayerOutputToFile = toFile;
123 
124     inputTensorInfo = armnn::TensorInfo(4, inputShape, ArmnnType);
125     outputTensorInfo = armnn::TensorInfo(4, outputShape, ArmnnType);
126 
127     std::vector<float> input = std::vector<float>(
128     {
129         1.0f,   2.0f,  3.0f,
130         4.0f,   5.0f,  6.0f,
131         7.0f,   8.0f,  9.0f,
132         10.0f, 11.0f, 12.0f,
133     });
134 
135     std::vector<float> outputExpected = std::vector<float>(
136     {
137         1.0f,   2.0f,  3.0f,
138         4.0f,   5.0f,  6.0f,
139         7.0f,   8.0f,  9.0f,
140         10.0f, 11.0f, 12.0f,
141     });
142 
143     const std::string expectedStringOutput =
144         "{ \"layerGuid\": 1,"
145         " \"layerName\": \"TestOutput\","
146         " \"outputSlot\": 0,"
147         " \"shape\": [1, 2, 2, 3],"
148         " \"min\": 1, \"max\": 12,"
149         " \"data\": [[[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]] }\n";
150 
151     return DebugTestImpl<T, 4>(workloadFactory,
152                                memoryManager,
153                                inputTensorInfo,
154                                outputTensorInfo,
155                                input,
156                                outputExpected,
157                                desc,
158                                expectedStringOutput,
159                                desc.m_LayerName,
160                                toFile);
161 }
162 
163 template <armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Debug3dTest(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)164 LayerTestResult<T, 3> Debug3dTest(
165     armnn::IWorkloadFactory& workloadFactory,
166     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
167     bool toFile = false)
168 {
169     armnn::TensorInfo inputTensorInfo;
170     armnn::TensorInfo outputTensorInfo;
171 
172     unsigned int inputShape[]  = {3, 3, 1};
173     unsigned int outputShape[] = {3, 3, 1};
174 
175     armnn::DebugQueueDescriptor desc;
176     desc.m_Guid = 1;
177     desc.m_LayerName = "TestOutput";
178     desc.m_SlotIndex = 0;
179     desc.m_LayerOutputToFile = toFile;
180 
181     inputTensorInfo = armnn::TensorInfo(3, inputShape, ArmnnType);
182     outputTensorInfo = armnn::TensorInfo(3, outputShape, ArmnnType);
183 
184     std::vector<float> input = std::vector<float>(
185     {
186         1.0f, 2.0f, 3.0f,
187         4.0f, 5.0f, 6.0f,
188         7.0f, 8.0f, 9.0f,
189     });
190 
191     std::vector<float> outputExpected = std::vector<float>(
192     {
193         1.0f, 2.0f, 3.0f,
194         4.0f, 5.0f, 6.0f,
195         7.0f, 8.0f, 9.0f,
196     });
197 
198     const std::string expectedStringOutput =
199         "{ \"layerGuid\": 1,"
200         " \"layerName\": \"TestOutput\","
201         " \"outputSlot\": 0,"
202         " \"shape\": [3, 3, 1],"
203         " \"min\": 1, \"max\": 9,"
204         " \"data\": [[[1], [2], [3]], [[4], [5], [6]], [[7], [8], [9]]] }\n";
205 
206     return DebugTestImpl<T, 3>(workloadFactory,
207                                memoryManager,
208                                inputTensorInfo,
209                                outputTensorInfo,
210                                input,
211                                outputExpected,
212                                desc,
213                                expectedStringOutput,
214                                desc.m_LayerName,
215                                toFile);
216 }
217 
218 template <armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Debug2dTest(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)219 LayerTestResult<T, 2> Debug2dTest(
220     armnn::IWorkloadFactory& workloadFactory,
221     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
222     bool toFile = false)
223 {
224     armnn::TensorInfo inputTensorInfo;
225     armnn::TensorInfo outputTensorInfo;
226 
227     unsigned int inputShape[]  = {2, 2};
228     unsigned int outputShape[] = {2, 2};
229 
230     armnn::DebugQueueDescriptor desc;
231     desc.m_Guid = 1;
232     desc.m_LayerName = "TestOutput";
233     desc.m_SlotIndex = 0;
234     desc.m_LayerOutputToFile = toFile;
235 
236     inputTensorInfo = armnn::TensorInfo(2, inputShape, ArmnnType);
237     outputTensorInfo = armnn::TensorInfo(2, outputShape, ArmnnType);
238 
239     std::vector<float> input = std::vector<float>(
240     {
241         1.0f, 2.0f,
242         3.0f, 4.0f,
243     });
244 
245     std::vector<float> outputExpected = std::vector<float>(
246     {
247         1.0f, 2.0f,
248         3.0f, 4.0f,
249     });
250 
251     const std::string expectedStringOutput =
252         "{ \"layerGuid\": 1,"
253         " \"layerName\": \"TestOutput\","
254         " \"outputSlot\": 0,"
255         " \"shape\": [2, 2],"
256         " \"min\": 1, \"max\": 4,"
257         " \"data\": [[1, 2], [3, 4]] }\n";
258 
259     return DebugTestImpl<T, 2>(workloadFactory,
260                                memoryManager,
261                                inputTensorInfo,
262                                outputTensorInfo,
263                                input,
264                                outputExpected,
265                                desc,
266                                expectedStringOutput,
267                                desc.m_LayerName,
268                                toFile);
269 }
270 
271 template <armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Debug1dTest(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)272 LayerTestResult<T, 1> Debug1dTest(
273     armnn::IWorkloadFactory& workloadFactory,
274     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
275     bool toFile = false)
276 {
277     armnn::TensorInfo inputTensorInfo;
278     armnn::TensorInfo outputTensorInfo;
279 
280     unsigned int inputShape[]  = {4};
281     unsigned int outputShape[] = {4};
282 
283     armnn::DebugQueueDescriptor desc;
284     desc.m_Guid = 1;
285     desc.m_LayerName = "TestOutput";
286     desc.m_SlotIndex = 0;
287     desc.m_LayerOutputToFile = toFile;
288 
289     inputTensorInfo = armnn::TensorInfo(1, inputShape, ArmnnType);
290     outputTensorInfo = armnn::TensorInfo(1, outputShape, ArmnnType);
291 
292     std::vector<float> input = std::vector<float>(
293     {
294         1.0f, 2.0f, 3.0f, 4.0f,
295     });
296 
297     std::vector<float> outputExpected = std::vector<float>(
298     {
299         1.0f, 2.0f, 3.0f, 4.0f,
300     });
301 
302     const std::string expectedStringOutput =
303         "{ \"layerGuid\": 1,"
304         " \"layerName\": \"TestOutput\","
305         " \"outputSlot\": 0,"
306         " \"shape\": [4],"
307         " \"min\": 1, \"max\": 4,"
308         " \"data\": [1, 2, 3, 4] }\n";
309 
310     return DebugTestImpl<T, 1>(workloadFactory,
311                                memoryManager,
312                                inputTensorInfo,
313                                outputTensorInfo,
314                                input,
315                                outputExpected,
316                                desc,
317                                expectedStringOutput,
318                                desc.m_LayerName,
319                                toFile);
320 }
321 
322 } // anonymous namespace
323 
Debug4dFloat32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)324 LayerTestResult<float, 4> Debug4dFloat32Test(
325     armnn::IWorkloadFactory& workloadFactory,
326     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
327     bool toFile = false)
328 {
329     return Debug4dTest<armnn::DataType::Float32>(workloadFactory, memoryManager, toFile);
330 }
331 
Debug3dFloat32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)332 LayerTestResult<float, 3> Debug3dFloat32Test(
333     armnn::IWorkloadFactory& workloadFactory,
334     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
335     bool toFile = false)
336 {
337     return Debug3dTest<armnn::DataType::Float32>(workloadFactory, memoryManager, toFile);
338 }
339 
Debug2dFloat32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)340 LayerTestResult<float, 2> Debug2dFloat32Test(
341     armnn::IWorkloadFactory& workloadFactory,
342     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
343     bool toFile = false)
344 {
345     return Debug2dTest<armnn::DataType::Float32>(workloadFactory, memoryManager, toFile);
346 }
347 
Debug1dFloat32Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)348 LayerTestResult<float, 1> Debug1dFloat32Test(
349     armnn::IWorkloadFactory& workloadFactory,
350     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
351     bool toFile = false)
352 {
353     return Debug1dTest<armnn::DataType::Float32>(workloadFactory, memoryManager, toFile);
354 }
355 
Debug4dBFloat16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)356 LayerTestResult<armnn::BFloat16, 4> Debug4dBFloat16Test(
357     armnn::IWorkloadFactory& workloadFactory,
358     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
359     bool toFile = false)
360 {
361     return Debug4dTest<armnn::DataType::BFloat16>(workloadFactory, memoryManager, toFile);
362 }
363 
Debug3dBFloat16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)364 LayerTestResult<armnn::BFloat16, 3> Debug3dBFloat16Test(
365     armnn::IWorkloadFactory& workloadFactory,
366     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
367     bool toFile = false)
368 {
369     return Debug3dTest<armnn::DataType::BFloat16>(workloadFactory, memoryManager, toFile);
370 }
371 
Debug2dBFloat16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)372 LayerTestResult<armnn::BFloat16, 2> Debug2dBFloat16Test(
373     armnn::IWorkloadFactory& workloadFactory,
374     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
375     bool toFile = false)
376 {
377     return Debug2dTest<armnn::DataType::BFloat16>(workloadFactory, memoryManager, toFile);
378 }
379 
Debug1dBFloat16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)380 LayerTestResult<armnn::BFloat16, 1> Debug1dBFloat16Test(
381     armnn::IWorkloadFactory& workloadFactory,
382     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
383     bool toFile = false)
384 {
385     return Debug1dTest<armnn::DataType::BFloat16>(workloadFactory, memoryManager, toFile);
386 }
387 
Debug4dUint8Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)388 LayerTestResult<uint8_t, 4> Debug4dUint8Test(
389     armnn::IWorkloadFactory& workloadFactory,
390     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
391     bool toFile = false)
392 {
393     return Debug4dTest<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, toFile);
394 }
395 
Debug3dUint8Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)396 LayerTestResult<uint8_t, 3> Debug3dUint8Test(
397     armnn::IWorkloadFactory& workloadFactory,
398     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
399     bool toFile = false)
400 {
401     return Debug3dTest<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, toFile);
402 }
403 
Debug2dUint8Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)404 LayerTestResult<uint8_t, 2> Debug2dUint8Test(
405     armnn::IWorkloadFactory& workloadFactory,
406     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
407     bool toFile = false)
408 {
409     return Debug2dTest<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, toFile);
410 }
411 
Debug1dUint8Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)412 LayerTestResult<uint8_t, 1> Debug1dUint8Test(
413     armnn::IWorkloadFactory& workloadFactory,
414     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
415     bool toFile = false)
416 {
417     return Debug1dTest<armnn::DataType::QAsymmU8>(workloadFactory, memoryManager, toFile);
418 }
419 
Debug4dInt16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)420 LayerTestResult<int16_t, 4> Debug4dInt16Test(
421     armnn::IWorkloadFactory& workloadFactory,
422     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
423     bool toFile = false)
424 {
425     return Debug4dTest<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, toFile);
426 }
427 
Debug3dInt16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)428 LayerTestResult<int16_t, 3> Debug3dInt16Test(
429     armnn::IWorkloadFactory& workloadFactory,
430     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
431     bool toFile = false)
432 {
433     return Debug3dTest<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, toFile);
434 }
435 
Debug2dInt16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)436 LayerTestResult<int16_t, 2> Debug2dInt16Test(
437     armnn::IWorkloadFactory& workloadFactory,
438     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
439     bool toFile = false)
440 {
441     return Debug2dTest<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, toFile);
442 }
443 
Debug1dInt16Test(armnn::IWorkloadFactory & workloadFactory,const armnn::IBackendInternal::IMemoryManagerSharedPtr & memoryManager,bool toFile=false)444 LayerTestResult<int16_t, 1> Debug1dInt16Test(
445     armnn::IWorkloadFactory& workloadFactory,
446     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
447     bool toFile = false)
448 {
449     return Debug1dTest<armnn::DataType::QSymmS16>(workloadFactory, memoryManager, toFile);
450 }
451