blob: 7da4c0fb0f78877310f39ded60c0de7ebe33ed8f [file] [log] [blame]
Jan Eilers53ef7952021-06-02 12:01:25 +01001//
2// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include <reference/workloads/Decoders.hpp>
7#include <armnn/utility/NumericCast.hpp>
8
9#include <fmt/format.h>
10
11#include <boost/test/unit_test.hpp>
12#include <chrono>
13
14
15template<typename T>
16void CompareVector(std::vector<T> vec1, std::vector<T> vec2)
17{
18 BOOST_TEST(vec1.size() == vec2.size());
19
20 bool mismatch = false;
21 for (uint i = 0; i < vec1.size(); ++i)
22 {
23 if (vec1[i] != vec2[i])
24 {
25 /*std::stringstream ss;
26 ss << "Vector value mismatch: index=" << i << " " << vec1[i] << "!=" << vec2[i];*/
27 BOOST_TEST_MESSAGE(fmt::format("Vector value mismatch: index={} {} != {}",
28 i,
29 vec1[i],
30 vec2[i]));
31 mismatch = true;
32 }
33 }
34
35 if (mismatch)
36 {
37 BOOST_FAIL("Error in CompareVector. Vectors don't match.");
38 }
39}
40
41using namespace armnn;
42
43// Basically a per axis decoder but without any decoding/quantization
44class MockPerAxisIterator : public PerAxisIterator<const int8_t, Decoder<int8_t>>
45{
46public:
47 MockPerAxisIterator(const int8_t* data, const armnn::TensorShape& tensorShape, const unsigned int axis)
48 : PerAxisIterator(data, tensorShape, axis), m_NumElements(tensorShape.GetNumElements())
49 {}
50
51 int8_t Get() const override
52 {
53 return *m_Iterator;
54 }
55
56 virtual std::vector<float> DecodeTensor(const TensorShape &tensorShape,
57 bool isDepthwise = false) override
58 {
59 IgnoreUnused(tensorShape, isDepthwise);
60 return std::vector<float>{};
61 };
62
63 // Iterates over data using operator[] and returns vector
64 std::vector<int8_t> Loop()
65 {
66 std::vector<int8_t> vec;
67 for (uint32_t i = 0; i < m_NumElements; ++i)
68 {
69 this->operator[](i);
70 vec.emplace_back(Get());
71 }
72 return vec;
73 }
74
75 unsigned int GetAxisIndex()
76 {
77 return m_AxisIndex;
78 }
79 unsigned int m_NumElements;
80};
81
82BOOST_AUTO_TEST_SUITE(RefPerAxisIterator)
83
84// Test Loop (Equivalent to DecodeTensor) and Axis = 0
85BOOST_AUTO_TEST_CASE(PerAxisIteratorTest1)
86{
87 std::vector<int8_t> input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
88 TensorInfo tensorInfo ({3,1,2,2},DataType::QSymmS8);
89
90 // test axis=0
91 std::vector<int8_t> expOutput = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
92 auto iterator = MockPerAxisIterator(input.data(), tensorInfo.GetShape(), 0);
93 std::vector<int8_t> output = iterator.Loop();
94 CompareVector(output, expOutput);
95
96 // Set iterator to index and check if the axis index is correct
97 iterator[5];
98 BOOST_TEST(iterator.GetAxisIndex() == 1u);
99
100 iterator[1];
101 BOOST_TEST(iterator.GetAxisIndex() == 0u);
102
103 iterator[10];
104 BOOST_TEST(iterator.GetAxisIndex() == 2u);
105}
106
107// Test Axis = 1
108BOOST_AUTO_TEST_CASE(PerAxisIteratorTest2)
109{
110 std::vector<int8_t> input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
111 TensorInfo tensorInfo ({3,1,2,2},DataType::QSymmS8);
112
113 // test axis=1
114 std::vector<int8_t> expOutput = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
115 auto iterator = MockPerAxisIterator(input.data(), tensorInfo.GetShape(), 1);
116 std::vector<int8_t> output = iterator.Loop();
117 CompareVector(output, expOutput);
118
119 // Set iterator to index and check if the axis index is correct
120 iterator[5];
121 BOOST_TEST(iterator.GetAxisIndex() == 0u);
122
123 iterator[1];
124 BOOST_TEST(iterator.GetAxisIndex() == 0u);
125
126 iterator[10];
127 BOOST_TEST(iterator.GetAxisIndex() == 0u);
128}
129
130// Test Axis = 2
131BOOST_AUTO_TEST_CASE(PerAxisIteratorTest3)
132{
133 std::vector<int8_t> input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
134 TensorInfo tensorInfo ({3,1,2,2},DataType::QSymmS8);
135
136 // test axis=2
137 std::vector<int8_t> expOutput = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
138 auto iterator = MockPerAxisIterator(input.data(), tensorInfo.GetShape(), 2);
139 std::vector<int8_t> output = iterator.Loop();
140 CompareVector(output, expOutput);
141
142 // Set iterator to index and check if the axis index is correct
143 iterator[5];
144 BOOST_TEST(iterator.GetAxisIndex() == 0u);
145
146 iterator[1];
147 BOOST_TEST(iterator.GetAxisIndex() == 0u);
148
149 iterator[10];
150 BOOST_TEST(iterator.GetAxisIndex() == 1u);
151}
152
153// Test Axis = 3
154BOOST_AUTO_TEST_CASE(PerAxisIteratorTest4)
155{
156 std::vector<int8_t> input = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
157 TensorInfo tensorInfo ({3,1,2,2},DataType::QSymmS8);
158
159 // test axis=3
160 std::vector<int8_t> expOutput = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
161 auto iterator = MockPerAxisIterator(input.data(), tensorInfo.GetShape(), 3);
162 std::vector<int8_t> output = iterator.Loop();
163 CompareVector(output, expOutput);
164
165 // Set iterator to index and check if the axis index is correct
166 iterator[5];
167 BOOST_TEST(iterator.GetAxisIndex() == 1u);
168
169 iterator[1];
170 BOOST_TEST(iterator.GetAxisIndex() == 1u);
171
172 iterator[10];
173 BOOST_TEST(iterator.GetAxisIndex() == 0u);
174}
175
176
177// Test Axis = 1. Different tensor shape
178BOOST_AUTO_TEST_CASE(PerAxisIteratorTest5)
179{
180 using namespace armnn;
181 std::vector<int8_t> input =
182 {
183 0, 1, 2, 3,
184 4, 5, 6, 7,
185 8, 9, 10, 11,
186 12, 13, 14, 15
187 };
188
189 std::vector<int8_t> expOutput =
190 {
191 0, 1, 2, 3,
192 4, 5, 6, 7,
193 8, 9, 10, 11,
194 12, 13, 14, 15
195 };
196
197 TensorInfo tensorInfo ({2,2,2,2},DataType::QSymmS8);
198 auto iterator = MockPerAxisIterator(input.data(), tensorInfo.GetShape(), 1);
199 std::vector<int8_t> output = iterator.Loop();
200 CompareVector(output, expOutput);
201
202 // Set iterator to index and check if the axis index is correct
203 iterator[5];
204 BOOST_TEST(iterator.GetAxisIndex() == 1u);
205
206 iterator[1];
207 BOOST_TEST(iterator.GetAxisIndex() == 0u);
208
209 iterator[10];
210 BOOST_TEST(iterator.GetAxisIndex() == 0u);
211}
212
213// Test the increment and decrement operator
214BOOST_AUTO_TEST_CASE(PerAxisIteratorTest7)
215{
216 using namespace armnn;
217 std::vector<int8_t> input =
218 {
219 0, 1, 2, 3,
220 4, 5, 6, 7,
221 8, 9, 10, 11
222 };
223
224 std::vector<int8_t> expOutput =
225 {
226 0, 1, 2, 3,
227 4, 5, 6, 7,
228 8, 9, 10, 11
229 };
230
231 TensorInfo tensorInfo ({3,1,2,2},DataType::QSymmS8);
232 auto iterator = MockPerAxisIterator(input.data(), tensorInfo.GetShape(), 2);
233
234 iterator += 3;
235 BOOST_TEST(iterator.Get(), expOutput[3]);
236 BOOST_TEST(iterator.GetAxisIndex() == 1u);
237
238 iterator += 3;
239 BOOST_TEST(iterator.Get(), expOutput[6]);
240 BOOST_TEST(iterator.GetAxisIndex() == 1u);
241
242 iterator -= 2;
243 BOOST_TEST(iterator.Get(), expOutput[4]);
244 BOOST_TEST(iterator.GetAxisIndex() == 0u);
245
246 iterator -= 1;
247 BOOST_TEST(iterator.Get(), expOutput[3]);
248 BOOST_TEST(iterator.GetAxisIndex() == 1u);
249}
250
251
252BOOST_AUTO_TEST_SUITE_END()