1 //
2 // Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include <reference/workloads/Decoders.hpp>
7
8 #include <fmt/format.h>
9
10 #include <doctest/doctest.h>
11
12 TEST_SUITE("RefPerChannelDecoder")
13 {
14 template<typename T>
CompareVector(std::vector<T> vec1,std::vector<T> vec2)15 void CompareVector(std::vector<T> vec1, std::vector<T> vec2)
16 {
17 CHECK(vec1.size() == vec2.size());
18
19 bool mismatch = false;
20 for (uint32_t i = 0; i < vec1.size(); ++i)
21 {
22 if (vec1[i] != vec2[i])
23 {
24 MESSAGE(fmt::format("Vector value mismatch: index={} {} != {}",
25 i,
26 vec1[i],
27 vec2[i]));
28
29 mismatch = true;
30 }
31 }
32
33 if (mismatch)
34 {
35 FAIL("Error in CompareVector. Vectors don't match.");
36 }
37 }
38
39 // Ensure quantization works for none depthwise convolutions
40 TEST_CASE("RefPerChannelDecoderTest1")
41 {
42 using namespace armnn;
43 std::vector<int8_t> input =
44 {
45 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
46 };
47
48 std::vector<float> expOutput =
49 {
50 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f,
51 24.0f, 26.0f, 28.0f, 30.0f, 32.0f, 34.0f, 36.0f, 38.0f, 40.0f, 42.0f, 44.0f, 46.0f
52 };
53
54 TensorInfo tensorInfo ({2,2,2,3},DataType::QSymmS8,{1.0f, 2.0f},0);
55 auto decoder = MakeDecoder<float>(tensorInfo, input.data());
56
57 std::vector<float> output = decoder->DecodeTensor(tensorInfo.GetShape());
58
59 CompareVector(output, expOutput);
60 }
61
62 // Ensure quantization works for depthwise convolutions M=1
63 TEST_CASE("RefPerChannelDecoderTest2")
64 {
65 using namespace armnn;
66 std::vector<int8_t> input =
67 {
68 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
69 };
70
71 std::vector<float> expOutput =
72 {
73 0.0f, 1.0f, 2.0f, 3.0f,
74 8.0f, 10.0f, 12.0f, 14.0f,
75 24.0f, 27.0f, 30.0f, 33.0f,
76 48.0f, 52.0f, 56.0f, 60.0f
77 };
78
79 // [O,1,H,W] = [I*M,1,H,W] = [4*1,1,2,2]
80 TensorInfo tensorInfo ({4,1,2,2},DataType::QSymmS8,{1.0f, 2.0f, 3.0f, 4.0f},0);
81 auto decoder = MakeDecoder<float>(tensorInfo, input.data());
82
83 std::vector<float> output = decoder->DecodeTensor(tensorInfo.GetShape(), true);
84
85 CompareVector(output, expOutput);
86 }
87
88 // Ensure quantization works for depthwise convolutions M=2
89 TEST_CASE("RefPerChannelDecoderTest3")
90 {
91 using namespace armnn;
92 std::vector<int8_t> input =
93 {
94 0, 1, 2, 3,
95 4, 5, 6, 7,
96 8, 9, 10, 11,
97 12, 13, 14, 15,
98 16, 17, 18, 19,
99 20, 21, 22, 23
100 };
101
102 std::vector<float> expOutput =
103 {
104 0.0f, 1.0f, 2.0f, 3.0f,
105 8.0f, 10.0f, 12.0f, 14.0f,
106 24.0f, 27.0f, 30.0f, 33.0f,
107 48.0f, 52.0f, 56.0f, 60.0f,
108 80.0f, 85.0f, 90.0f, 95.0f,
109 120.0f, 126.0f, 132.0f, 138.0f
110 };
111
112 // [O,1,H,W] = [I*M,1,H,W] = [3*2,1,2,2]
113 TensorInfo tensorInfo ({6,1,2,2},DataType::QSymmS8,{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f},0);
114 auto decoder = MakeDecoder<float>(tensorInfo, input.data());
115
116 std::vector<float> output = decoder->DecodeTensor(tensorInfo.GetShape(), true);
117
118 CompareVector(output, expOutput);
119 }
120
121 // Ensure quantization works for depthwise convolutions M=2 for int32
122 TEST_CASE("RefPerChannelDecoderTest4")
123 {
124 using namespace armnn;
125 std::vector<int32_t> input =
126 {
127 0, 1, 2, 3,
128 4, 5, 6, 7,
129 8, 9, 10, 11,
130 12, 13, 14, 15,
131 16, 17, 18, 19,
132 20, 21, 22, 23
133 };
134
135 std::vector<float> expOutput =
136 {
137 0.0f, 1.0f, 2.0f, 3.0f,
138 8.0f, 10.0f, 12.0f, 14.0f,
139 24.0f, 27.0f, 30.0f, 33.0f,
140 48.0f, 52.0f, 56.0f, 60.0f,
141 80.0f, 85.0f, 90.0f, 95.0f,
142 120.0f, 126.0f, 132.0f, 138.0f
143 };
144
145 // [O,1,H,W] = [I*M,1,H,W] = [3*2,1,2,2]
146 TensorInfo tensorInfo ({6,1,2,2},DataType::Signed32,{1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f},0);
147 auto decoder = MakeDecoder<float>(tensorInfo, input.data());
148
149 std::vector<float> output = decoder->DecodeTensor(tensorInfo.GetShape(), true);
150
151 CompareVector(output, expOutput);
152 }
153
154 }
155