giuros01 | 1bf5e28 | 2018-12-21 14:57:48 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2019 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> |
| 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) |
| 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 | |
| 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 |
Isabella Gottardi | 685c181 | 2019-01-11 16:35:36 +0000 | [diff] [blame] | 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 }); |
giuros01 | 1bf5e28 | 2018-12-21 14:57:48 +0000 | [diff] [blame] | 134 | validate(Accessor(output), expected_output); |
| 135 | } |
| 136 | |
| 137 | TEST_CASE(Quantized, framework::DatasetMode::ALL) |
| 138 | { |
| 139 | const unsigned int k = 5; |
| 140 | |
Isabella Gottardi | 685c181 | 2019-01-11 16:35:36 +0000 | [diff] [blame] | 141 | Tensor predictions = create_tensor<Tensor>(TensorShape(10, 20), DataType::QASYMM8, 1, QuantizationInfo()); |
giuros01 | 1bf5e28 | 2018-12-21 14:57:48 +0000 | [diff] [blame] | 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 |
Isabella Gottardi | 685c181 | 2019-01-11 16:35:36 +0000 | [diff] [blame] | 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 }); |
giuros01 | 1bf5e28 | 2018-12-21 14:57:48 +0000 | [diff] [blame] | 187 | validate(Accessor(output), expected_output); |
| 188 | } |
| 189 | |
| 190 | TEST_SUITE_END() // TopKV |
| 191 | TEST_SUITE_END() // CPP |
| 192 | } // namespace validation |
| 193 | } // namespace test |
| 194 | } // namespace arm_compute |