2 * Copyright (c) 2022 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "kernels/SVDF.h"
18 #include "kernels/TestUtils.h"
19 #include "luci_interpreter/TestMemoryManager.h"
21 namespace luci_interpreter
28 using namespace testing;
30 class SVDFTest : public ::testing::Test
33 void SetUp() override { _memory_manager = std::make_unique<TestMemoryManager>(); }
35 std::unique_ptr<IMemoryManager> _memory_manager;
38 TEST_F(SVDFTest, FullIntegerTest)
40 const int32_t batches = 2;
41 const int32_t input_size = 3;
42 const int32_t units = 4;
43 const int32_t memory_size = 10;
44 const int32_t rank = 1;
45 const int32_t num_filters = units * rank;
47 Shape input_shape{batches, input_size};
48 Shape weight_feature_shape{num_filters, input_size};
49 Shape weight_time_shape{num_filters, memory_size};
50 Shape bias_shape{units};
51 Shape activation_state_shape{batches, memory_size * num_filters};
53 std::vector<float> input_data{0.49837467, 0.19278903, 0.26584083,
54 0.17660543, 0.52949083, -0.77931279};
56 std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667, 0.37613347,
57 0.22197971, 0.12416199, 0.27901134, 0.27557442,
58 0.3905206, -0.36137494, -0.06634006, -0.10640851};
60 std::vector<float> weight_time_data{
61 -0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
62 0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
64 0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
65 -0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
67 -0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
68 0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
70 -0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
71 -0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657};
73 std::vector<float> bias_data{-0.0976817, 0.15294972, 0.39635518, -0.02702999};
75 std::pair<float, int32_t> input_quant_param = quantizationParams<int8_t>(-1, 1);
76 std::pair<float, int32_t> weight_feature_quant_param = quantizationParams<int8_t>(-0.5, 0.5);
77 std::pair<float, int32_t> weight_time_quant_param = quantizationParams<int16_t>(-1, 1);
78 std::pair<float, int32_t> bias_quant_param = quantizationParams<int32_t>(-512, 512);
79 std::pair<float, int32_t> activation_state_quant_param = quantizationParams<int16_t>(-16, 16);
81 std::pair<float, int32_t> output_quant_param = quantizationParams<int8_t>(-0.5, 0.5);
84 makeInputTensor<DataType::S8>(input_shape, input_quant_param.first, input_quant_param.second,
85 input_data, _memory_manager.get());
86 Tensor weight_feature_tensor = makeInputTensor<DataType::S8>(
87 weight_feature_shape, weight_feature_quant_param.first, weight_feature_quant_param.second,
88 weight_feature_data, _memory_manager.get());
89 Tensor weight_time_tensor = makeInputTensor<DataType::S16>(
90 weight_time_shape, weight_time_quant_param.first, weight_time_quant_param.second,
91 weight_time_data, _memory_manager.get());
92 Tensor bias_tensor = makeInputTensor<DataType::S32>(
93 bias_shape, bias_quant_param.first, bias_quant_param.second, bias_data, _memory_manager.get());
94 Tensor activation_state_tensor = makeOutputTensor(
95 DataType::S16, activation_state_quant_param.first, activation_state_quant_param.second);
96 activation_state_tensor.resize(activation_state_shape);
97 Tensor output_tensor =
98 makeOutputTensor(DataType::S8, output_quant_param.first, output_quant_param.second);
100 Tensor scratchpad_activation_state(DataType::S16, Shape({}), {}, "");
101 Tensor scratchpad_1(DataType::S32, Shape({}), {}, "");
102 Tensor scratchpad_2(DataType::S32, Shape({}), {}, "");
103 Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
104 Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
105 Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
106 Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
109 params.activation = Activation::RELU;
110 params.asymmetric_quantize_inputs = false;
111 params.svdf_rank = rank;
113 SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, &bias_tensor,
114 &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
115 &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
117 _memory_manager->allocate_memory(output_tensor);
118 _memory_manager->allocate_memory(scratchpad_activation_state);
119 _memory_manager->allocate_memory(scratchpad_1);
120 _memory_manager->allocate_memory(scratchpad_2);
121 _memory_manager->allocate_memory(scratchpad_3);
122 _memory_manager->allocate_memory(scratchpad_4);
123 _memory_manager->allocate_memory(scratchpad_5);
124 _memory_manager->allocate_memory(scratchpad_6);
127 std::vector<int8_t> ref_output_data{-9, 24, 31, 1, -10, 10, -3, 0};
129 std::vector<int32_t> ref_output_shape{batches, units};
130 EXPECT_THAT(extractTensorData<int8_t>(output_tensor), ref_output_data);
131 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
134 TEST_F(SVDFTest, FloatTest)
136 const int32_t batches = 2;
137 const int32_t input_size = 3;
138 const int32_t units = 4;
139 const int32_t memory_size = 10;
140 const int32_t rank = 1;
141 const int32_t num_filters = units * rank;
143 Shape input_shape{batches, input_size};
144 Shape weight_feature_shape{num_filters, input_size};
145 Shape weight_time_shape{num_filters, memory_size};
146 Shape activation_state_shape{batches, memory_size * num_filters};
148 std::vector<float> input_data{0.12609188, -0.46347019, -0.89598465,
149 0.35867718, 0.36897406, 0.73463392};
151 std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667, 0.37613347,
152 0.22197971, 0.12416199, 0.27901134, 0.27557442,
153 0.3905206, -0.36137494, -0.06634006, -0.10640851};
155 std::vector<float> weight_time_data{
156 -0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
157 0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
159 0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
160 -0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
162 -0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
163 0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
165 -0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
166 -0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657};
168 Tensor input_tensor =
169 makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
170 Tensor weight_feature_tensor = makeInputTensor<DataType::FLOAT32>(
171 weight_feature_shape, weight_feature_data, _memory_manager.get());
172 Tensor weight_time_tensor =
173 makeInputTensor<DataType::FLOAT32>(weight_time_shape, weight_time_data, _memory_manager.get());
174 Tensor activation_state_tensor = makeOutputTensor(DataType::FLOAT32);
175 activation_state_tensor.resize(activation_state_shape);
176 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
178 Tensor scratchpad_activation_state(DataType::FLOAT32, Shape({}), {}, "");
179 Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
180 Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
181 Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
182 Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
183 Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
184 Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
187 params.activation = Activation::NONE;
188 params.asymmetric_quantize_inputs = false;
189 params.svdf_rank = rank;
191 SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, nullptr,
192 &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
193 &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
195 _memory_manager->allocate_memory(output_tensor);
196 _memory_manager->allocate_memory(scratchpad_activation_state);
197 _memory_manager->allocate_memory(scratchpad_1);
198 _memory_manager->allocate_memory(scratchpad_2);
199 _memory_manager->allocate_memory(scratchpad_3);
200 _memory_manager->allocate_memory(scratchpad_4);
201 _memory_manager->allocate_memory(scratchpad_5);
202 _memory_manager->allocate_memory(scratchpad_6);
205 std::vector<float> ref_output_data{0.014899, -0.0517661, -0.143725, -0.00271883,
206 -0.03004015, 0.09565311, 0.1587342, 0.00784263};
208 std::vector<float> ref_output_shape{batches, units};
209 const float tolerance = 1e-5;
210 EXPECT_THAT(extractTensorData<float>(output_tensor), FloatArrayNear(ref_output_data, tolerance));
211 EXPECT_THAT(extractTensorShape(output_tensor), ::testing::ElementsAreArray(ref_output_shape));
214 TEST_F(SVDFTest, Unsupported_Type_Configure_NEG)
216 const int32_t batches = 2;
217 const int32_t input_size = 3;
218 const int32_t units = 4;
219 const int32_t memory_size = 10;
220 const int32_t rank = 1;
221 const int32_t num_filters = units * rank;
223 Shape input_shape{batches, input_size};
224 Shape weight_feature_shape{num_filters, input_size};
225 Shape weight_time_shape{num_filters, memory_size};
226 Shape activation_state_shape{batches, memory_size * num_filters};
228 std::vector<int32_t> input_data{0, 1, 3, 4, 4, -2};
230 std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667, 0.37613347,
231 0.22197971, 0.12416199, 0.27901134, 0.27557442,
232 0.3905206, -0.36137494, -0.06634006, -0.10640851};
234 std::vector<float> weight_time_data{
235 -0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
236 0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
238 0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
239 -0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
241 -0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
242 0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
244 -0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
245 -0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657};
247 Tensor input_tensor =
248 makeInputTensor<DataType::S32>(input_shape, input_data, _memory_manager.get());
249 Tensor weight_feature_tensor = makeInputTensor<DataType::FLOAT32>(
250 weight_feature_shape, weight_feature_data, _memory_manager.get());
251 Tensor weight_time_tensor =
252 makeInputTensor<DataType::FLOAT32>(weight_time_shape, weight_time_data, _memory_manager.get());
253 Tensor activation_state_tensor = makeOutputTensor(DataType::FLOAT32);
254 activation_state_tensor.resize(activation_state_shape);
255 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
257 Tensor scratchpad_activation_state(DataType::FLOAT32, Shape({}), {}, "");
258 Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
259 Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
260 Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
261 Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
262 Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
263 Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
266 params.activation = Activation::NONE;
267 params.asymmetric_quantize_inputs = false;
268 params.svdf_rank = rank;
270 SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, nullptr,
271 &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
272 &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
273 EXPECT_ANY_THROW(kernel.configure());
276 TEST_F(SVDFTest, Invalid_Input_Shape_NEG)
278 const int32_t batches = 2;
279 const int32_t right_input_size = 3;
280 const int32_t wrong_input_size = 4;
281 const int32_t units = 4;
282 const int32_t memory_size = 10;
283 const int32_t rank = 1;
284 const int32_t num_filters = units * rank;
286 Shape input_shape{batches, wrong_input_size};
287 Shape weight_feature_shape{num_filters, right_input_size};
288 Shape weight_time_shape{num_filters, memory_size};
289 Shape activation_state_shape{batches, memory_size * num_filters};
291 std::vector<float> input_data{0, 1, 3, 2, 4, 4, -2, 1};
293 std::vector<float> weight_feature_data{-0.31930989, -0.36118156, 0.0079667, 0.37613347,
294 0.22197971, 0.12416199, 0.27901134, 0.27557442,
295 0.3905206, -0.36137494, -0.06634006, -0.10640851};
297 std::vector<float> weight_time_data{
298 -0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
299 0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
301 0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
302 -0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
304 -0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
305 0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
307 -0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
308 -0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657};
310 Tensor input_tensor =
311 makeInputTensor<DataType::FLOAT32>(input_shape, input_data, _memory_manager.get());
312 Tensor weight_feature_tensor = makeInputTensor<DataType::FLOAT32>(
313 weight_feature_shape, weight_feature_data, _memory_manager.get());
314 Tensor weight_time_tensor =
315 makeInputTensor<DataType::FLOAT32>(weight_time_shape, weight_time_data, _memory_manager.get());
316 Tensor activation_state_tensor = makeOutputTensor(DataType::FLOAT32);
317 activation_state_tensor.resize(activation_state_shape);
318 Tensor output_tensor = makeOutputTensor(DataType::FLOAT32);
320 Tensor scratchpad_activation_state(DataType::FLOAT32, Shape({}), {}, "");
321 Tensor scratchpad_1(DataType::FLOAT32, Shape({}), {}, "");
322 Tensor scratchpad_2(DataType::FLOAT32, Shape({}), {}, "");
323 Tensor scratchpad_3(DataType::FLOAT32, Shape({}), {}, "");
324 Tensor scratchpad_4(DataType::FLOAT32, Shape({}), {}, "");
325 Tensor scratchpad_5(DataType::FLOAT32, Shape({}), {}, "");
326 Tensor scratchpad_6(DataType::FLOAT32, Shape({}), {}, "");
329 params.activation = Activation::NONE;
330 params.asymmetric_quantize_inputs = false;
331 params.svdf_rank = rank;
333 SVDF kernel(&input_tensor, &weight_feature_tensor, &weight_time_tensor, nullptr,
334 &activation_state_tensor, &output_tensor, &scratchpad_activation_state, &scratchpad_1,
335 &scratchpad_2, &scratchpad_3, &scratchpad_4, &scratchpad_5, &scratchpad_6, params);
336 EXPECT_ANY_THROW(kernel.configure());
340 } // namespace kernels
341 } // namespace luci_interpreter