• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019-2020 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "arm_compute/core/Types.h"
25 #include "arm_compute/runtime/CPP/functions/CPPTopKV.h"
26 #include "arm_compute/runtime/Tensor.h"
27 #include "arm_compute/runtime/TensorAllocator.h"
28 #include "tests/NEON/Accessor.h"
29 #include "tests/PaddingCalculator.h"
30 #include "tests/datasets/ShapeDatasets.h"
31 #include "tests/framework/Asserts.h"
32 #include "tests/framework/Macros.h"
33 #include "tests/framework/datasets/Datasets.h"
34 #include "tests/validation/Validation.h"
35 #include "tests/validation/fixtures/PermuteFixture.h"
36 
37 namespace arm_compute
38 {
39 namespace test
40 {
41 namespace validation
42 {
43 namespace
44 {
45 template <typename U, typename T>
fill_tensor(U && tensor,const std::vector<T> & v)46 inline void fill_tensor(U &&tensor, const std::vector<T> &v)
47 {
48     std::memcpy(tensor.data(), v.data(), sizeof(T) * v.size());
49 }
50 } // namespace
51 
52 TEST_SUITE(CPP)
TEST_SUITE(TopKV)53 TEST_SUITE(TopKV)
54 
55 // *INDENT-OFF*
56 // clang-format off
57 DATA_TEST_CASE(Validate, framework::DatasetMode::ALL, zip(zip(zip(zip(
58         framework::dataset::make("PredictionsInfo", { TensorInfo(TensorShape(20, 10), 1, DataType::F32),
59                                                 TensorInfo(TensorShape(10, 20), 1, DataType::F16),  // Mismatching batch_size
60                                                 TensorInfo(TensorShape(20, 10), 1, DataType::S8), // Unsupported data type
61                                                 TensorInfo(TensorShape(10, 10, 10), 1, DataType::F32), // Wrong predictions dimensions
62                                                 TensorInfo(TensorShape(20, 10), 1, DataType::F32)}), // Wrong output dimension
63         framework::dataset::make("TargetsInfo",{ TensorInfo(TensorShape(10), 1, DataType::U32),
64                                                 TensorInfo(TensorShape(10), 1, DataType::U32),
65                                                 TensorInfo(TensorShape(10), 1, DataType::U32),
66                                                 TensorInfo(TensorShape(10), 1, DataType::U32),
67                                                 TensorInfo(TensorShape(10), 1, DataType::U32)})),
68         framework::dataset::make("OutputInfo",{ TensorInfo(TensorShape(10), 1, DataType::U8),
69                                                 TensorInfo(TensorShape(10), 1, DataType::U8),
70                                                 TensorInfo(TensorShape(10), 1, DataType::U8),
71                                                 TensorInfo(TensorShape(10), 1, DataType::U8),
72                                                 TensorInfo(TensorShape(1), 1, DataType::U8)})),
73 
74         framework::dataset::make("k",{ 0, 1, 2, 3, 4 })),
75         framework::dataset::make("Expected", {true, false, false, false, false })),
76         prediction_info, targets_info, output_info, k, expected)
77 {
78     const Status status = CPPTopKV::validate(&prediction_info.clone()->set_is_resizable(false),&targets_info.clone()->set_is_resizable(false), &output_info.clone()->set_is_resizable(false), k);
79     ARM_COMPUTE_EXPECT(bool(status) == expected, framework::LogLevel::ERRORS);
80 }
81 // clang-format on
82 // *INDENT-ON*
83 
TEST_CASE(Float,framework::DatasetMode::ALL)84 TEST_CASE(Float, framework::DatasetMode::ALL)
85 {
86     const unsigned int k = 5;
87 
88     Tensor predictions = create_tensor<Tensor>(TensorShape(10, 20), DataType::F32);
89     Tensor targets     = create_tensor<Tensor>(TensorShape(20), DataType::U32);
90 
91     predictions.allocator()->allocate();
92     targets.allocator()->allocate();
93 
94     // Fill the tensors with random pre-generated values
95     fill_tensor(Accessor(predictions), std::vector<float>
96     {
97         0.8147, 0.6557, 0.4387, 0.7513, 0.3517, 0.1622, 0.1067, 0.8530, 0.7803, 0.5470,
98         0.9058, 0.0357, 0.3816, 0.2551, 0.8308, 0.7943, 0.9619, 0.6221, 0.3897, 0.2963,
99         0.1270, 0.8491, 0.7655, 0.5060, 0.5853, 0.3112, 0.0046, 0.3510, 0.2417, 0.7447,
100         0.9134, 0.9340, 0.7952, 0.6991, 0.5497, 0.5285, 0.7749, 0.5132, 0.4039, 0.1890,
101         0.6324, 0.6787, 0.1869, 0.8909, 0.9172, 0.1656, 0.8173, 0.4018, 0.0965, 0.6868,
102         0.0975, 0.7577, 0.4898, 0.9593, 0.2858, 0.6020, 0.8687, 0.0760, 0.1320, 0.1835,
103         0.2785, 0.7431, 0.4456, 0.5472, 0.7572, 0.2630, 0.0844, 0.2399, 0.9421, 0.3685,
104         0.5469, 0.3922, 0.6463, 0.1386, 0.7537, 0.6541, 0.3998, 0.1233, 0.9561, 0.6256,
105         0.9575, 0.6555, 0.7094, 0.1493, 0.3804, 0.6892, 0.2599, 0.1839, 0.5752, 0.7802,
106         0.9649, 0.1712, 0.7547, 0.2575, 0.5678, 0.7482, 0.8001, 0.2400, 0.0598, 0.0811,
107         0.1576, 0.7060, 0.2760, 0.8407, 0.0759, 0.4505, 0.4314, 0.4173, 0.2348, 0.9294,
108         0.9706, 0.0318, 0.6797, 0.2543, 0.0540, 0.0838, 0.9106, 0.0497, 0.3532, 0.7757,
109         0.9572, 0.2769, 0.6551, 0.8143, 0.5308, 0.2290, 0.1818, 0.9027, 0.8212, 0.4868,
110         0.4854, 0.0462, 0.1626, 0.2435, 0.7792, 0.9133, 0.2638, 0.9448, 0.0154, 0.4359,
111         0.8003, 0.0971, 0.1190, 0.9293, 0.9340, 0.1524, 0.1455, 0.4909, 0.0430, 0.4468,
112         0.1419, 0.8235, 0.4984, 0.3500, 0.1299, 0.8258, 0.1361, 0.4893, 0.1690, 0.3063,
113         0.4218, 0.6948, 0.9597, 0.1966, 0.5688, 0.5383, 0.8693, 0.3377, 0.6491, 0.5085,
114         0.9157, 0.3171, 0.3404, 0.2511, 0.4694, 0.9961, 0.5797, 0.9001, 0.7317, 0.5108,
115         0.7922, 0.9502, 0.5853, 0.6160, 0.0119, 0.0782, 0.5499, 0.3692, 0.6477, 0.8176,
116         0.9595, 0.0344, 0.2238, 0.4733, 0.3371, 0.4427, 0.1450, 0.1112, 0.4509, 0.7948
117     });
118 
119     fill_tensor(Accessor(targets), std::vector<int> { 1, 5, 7, 2, 8, 1, 2, 1, 2, 4, 3, 9, 4, 1, 9, 9, 4, 1, 2, 4 });
120 
121     // Determine the output through the CPP kernel
122     Tensor   output;
123     CPPTopKV topkv;
124     topkv.configure(&predictions, &targets, &output, k);
125 
126     output.allocator()->allocate();
127 
128     // Run the kernel
129     topkv.run();
130 
131     // Validate against the expected values
132     SimpleTensor<uint8_t> expected_output(TensorShape(20), DataType::U8);
133     fill_tensor(expected_output, std::vector<uint8_t> { 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0 });
134     validate(Accessor(output), expected_output);
135 }
136 
TEST_CASE(QASYMM8,framework::DatasetMode::ALL)137 TEST_CASE(QASYMM8, framework::DatasetMode::ALL)
138 {
139     const unsigned int k = 5;
140 
141     Tensor predictions = create_tensor<Tensor>(TensorShape(10, 20), DataType::QASYMM8, 1, QuantizationInfo());
142     Tensor targets     = create_tensor<Tensor>(TensorShape(20), DataType::U32);
143 
144     predictions.allocator()->allocate();
145     targets.allocator()->allocate();
146 
147     // Fill the tensors with random pre-generated values
148     fill_tensor(Accessor(predictions), std::vector<uint8_t>
149     {
150         133, 235, 69, 118, 140, 179, 189, 203, 137, 157,
151         242, 1, 196, 170, 166, 25, 102, 244, 24, 254,
152         164, 119, 49, 198, 140, 135, 175, 84, 29, 136,
153         246, 109, 74, 90, 185, 136, 181, 172, 35, 123,
154         62, 118, 24, 170, 134, 221, 114, 113, 174, 206,
155         174, 198, 148, 107, 255, 125, 6, 214, 127, 59,
156         75, 83, 175, 216, 56, 101, 85, 197, 49, 128,
157         172, 201, 140, 214, 28, 172, 109, 43, 127, 231,
158         178, 121, 109, 66, 29, 190, 70, 221, 38, 148,
159         18, 10, 165, 158, 17, 134, 51, 254, 15, 217,
160         66, 46, 166, 150, 104, 90, 211, 132, 218, 190,
161         58, 185, 174, 139, 115, 39, 111, 227, 144, 151,
162         171, 122, 163, 223, 94, 151, 228, 151, 238, 64,
163         217, 40, 242, 68, 196, 68, 101, 40, 179, 171,
164         89, 88, 54, 82, 161, 12, 197, 52, 150, 22,
165         200, 156, 182, 31, 198, 194, 102, 105, 209, 161,
166         173, 50, 61, 241, 239, 63, 207, 192, 226, 170,
167         2, 190, 31, 166, 250, 114, 194, 212, 254, 187,
168         155, 63, 156, 123, 50, 177, 97, 203, 1, 229,
169         100, 235, 116, 164, 36, 92, 56, 82, 222, 252
170     });
171 
172     fill_tensor(Accessor(targets), std::vector<int> { 1, 5, 7, 2, 8, 1, 2, 1, 2, 4, 3, 9, 4, 1, 9, 9, 4, 1, 2, 4 });
173 
174     // Determine the output through the CPP kernel
175     Tensor   output;
176     CPPTopKV topkv;
177     topkv.configure(&predictions, &targets, &output, k);
178 
179     output.allocator()->allocate();
180 
181     // Run the kernel
182     topkv.run();
183 
184     // Validate against the expected values
185     SimpleTensor<uint8_t> expected_output(TensorShape(20), DataType::U8);
186     fill_tensor(expected_output, std::vector<uint8_t> { 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0 });
187     validate(Accessor(output), expected_output);
188 }
189 
TEST_CASE(QASYMM8_SIGNED,framework::DatasetMode::ALL)190 TEST_CASE(QASYMM8_SIGNED, framework::DatasetMode::ALL)
191 {
192     const unsigned int k = 5;
193 
194     Tensor predictions = create_tensor<Tensor>(TensorShape(10, 20), DataType::QASYMM8_SIGNED, 1, QuantizationInfo());
195     Tensor targets     = create_tensor<Tensor>(TensorShape(20), DataType::U32);
196 
197     predictions.allocator()->allocate();
198     targets.allocator()->allocate();
199 
200     // Fill the tensors with random pre-generated values
201     fill_tensor(Accessor(predictions), std::vector<int8_t>
202     {
203         123, -34, 69, 118, 20, -45, 99, -98, 127, 117,  //-34
204         -99, 1, -128, 90, 60, 25, 102, 76, 24, -110,    //25
205         99, 119, 49, 43, -40, 60, 43, 84, 29, 67,       //84
206         33, 109, 74, 90, 90, 44, 98, 90, 35, 123,       //74
207         62, 118, 24, -32, 34, 21, 114, 113, 124, 20,    //124
208         74, 98, 48, 107, 127, 125, 6, -98, 127, 59,     //98
209         75, 83, 75, -118, 56, 101, 85, 97, 49, 127,     //75
210         72, -20, 40, 14, 28, -30, 109, 43, 127, -31,    //-20
211         78, 121, 109, 66, 29, 90, 70, 21, 38, 48,       //109
212         18, 10, 115, 124, 17, 123, 51, 54, 15, 17,      //17
213         66, 46, -66, 125, 104, 90, 123, 113, -54, -126, //125
214         58, -85, 74, 39, 115, 39, 111, -27, 44, 51,     //51
215         71, 122, -34, -123, 94, 113, 125, 111, 38, 64,  //94
216         -17, 40, 42, 68, 96, 68, 101, 40, 79, 71,       //40
217         89, 88, 54, 82, 127, 12, 112, 52, 125, 22,      //22
218         -128, 56, 82, 31, 98, 94, 102, 105, 127, 123,   //123
219         112, 50, 61, 41, 39, 63, -77, 92, 26, 70,       //39
220         2, 90, 31, 99, -34, 114, 112, 126, 127, 87,     //90
221         125, 63, 56, 123, 50, -77, 97, -93, 1, 29,      //56
222         100, -35, 116, 64, 36, 92, 56, 82, -22, -118    //36
223     });
224 
225     fill_tensor(Accessor(targets), std::vector<int> { 1, 5, 7, 2, 8, 1, 2, 1, 2, 4, 3, 9, 4, 1, 9, 9, 4, 1, 2, 4 });
226 
227     // Determine the output through the CPP kernel
228     Tensor   output;
229     CPPTopKV topkv;
230     topkv.configure(&predictions, &targets, &output, k);
231 
232     output.allocator()->allocate();
233 
234     // Run the kernel
235     topkv.run();
236 
237     // Validate against the expected values
238     SimpleTensor<int8_t> expected_output(TensorShape(20), DataType::U8);
239     fill_tensor(expected_output, std::vector<int8_t> { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0 });
240     validate(Accessor(output), expected_output);
241 }
242 
243 TEST_SUITE_END() // TopKV
244 TEST_SUITE_END() // CPP
245 } // namespace validation
246 } // namespace test
247 } // namespace arm_compute
248