1*c217d954SCole Faust /*
2*c217d954SCole Faust * Copyright (c) 2019-2020 Arm Limited.
3*c217d954SCole Faust *
4*c217d954SCole Faust * SPDX-License-Identifier: MIT
5*c217d954SCole Faust *
6*c217d954SCole Faust * Permission is hereby granted, free of charge, to any person obtaining a copy
7*c217d954SCole Faust * of this software and associated documentation files (the "Software"), to
8*c217d954SCole Faust * deal in the Software without restriction, including without limitation the
9*c217d954SCole Faust * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*c217d954SCole Faust * sell copies of the Software, and to permit persons to whom the Software is
11*c217d954SCole Faust * furnished to do so, subject to the following conditions:
12*c217d954SCole Faust *
13*c217d954SCole Faust * The above copyright notice and this permission notice shall be included in all
14*c217d954SCole Faust * copies or substantial portions of the Software.
15*c217d954SCole Faust *
16*c217d954SCole Faust * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*c217d954SCole Faust * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*c217d954SCole Faust * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*c217d954SCole Faust * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*c217d954SCole Faust * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*c217d954SCole Faust * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*c217d954SCole Faust * SOFTWARE.
23*c217d954SCole Faust */
24*c217d954SCole Faust #include "arm_compute/runtime/CL/functions/CLLSTMLayerQuantized.h"
25*c217d954SCole Faust #include "tests/CL/CLAccessor.h"
26*c217d954SCole Faust #include "tests/PaddingCalculator.h"
27*c217d954SCole Faust #include "tests/Utils.h"
28*c217d954SCole Faust #include "tests/datasets/LSTMLayerDataset.h"
29*c217d954SCole Faust #include "tests/framework/Asserts.h"
30*c217d954SCole Faust #include "tests/framework/Macros.h"
31*c217d954SCole Faust #include "tests/framework/datasets/Datasets.h"
32*c217d954SCole Faust #include "tests/validation/Validation.h"
33*c217d954SCole Faust
34*c217d954SCole Faust #include <vector>
35*c217d954SCole Faust
36*c217d954SCole Faust namespace arm_compute
37*c217d954SCole Faust {
38*c217d954SCole Faust namespace test
39*c217d954SCole Faust {
40*c217d954SCole Faust namespace validation
41*c217d954SCole Faust {
42*c217d954SCole Faust namespace
43*c217d954SCole Faust {
44*c217d954SCole Faust template <typename T>
fill_tensor(CLTensor & tensor,const std::vector<T> & v)45*c217d954SCole Faust inline void fill_tensor(CLTensor &tensor, const std::vector<T> &v)
46*c217d954SCole Faust {
47*c217d954SCole Faust tensor.map(true);
48*c217d954SCole Faust // Import memory accounting for padding
49*c217d954SCole Faust TensorShape t_shape = tensor.info()->tensor_shape();
50*c217d954SCole Faust Window window;
51*c217d954SCole Faust window.use_tensor_dimensions(t_shape);
52*c217d954SCole Faust Iterator out(&tensor, window);
53*c217d954SCole Faust execute_window_loop(window, [&](const Coordinates & id)
54*c217d954SCole Faust {
55*c217d954SCole Faust *reinterpret_cast<T *>(out.ptr()) = v[coord2index(t_shape, id)];
56*c217d954SCole Faust },
57*c217d954SCole Faust out);
58*c217d954SCole Faust tensor.unmap();
59*c217d954SCole Faust }
60*c217d954SCole Faust
61*c217d954SCole Faust template <typename T>
fill_tensor(SimpleTensor<T> & tensor,const std::vector<T> & v)62*c217d954SCole Faust inline void fill_tensor(SimpleTensor<T> &tensor, const std::vector<T> &v)
63*c217d954SCole Faust {
64*c217d954SCole Faust std::memcpy(tensor.data(), v.data(), sizeof(T) * v.size());
65*c217d954SCole Faust }
66*c217d954SCole Faust
67*c217d954SCole Faust } // namespace
68*c217d954SCole Faust
69*c217d954SCole Faust TEST_SUITE(CL)
TEST_SUITE(LSTMLayerQuantized)70*c217d954SCole Faust TEST_SUITE(LSTMLayerQuantized)
71*c217d954SCole Faust
72*c217d954SCole Faust // *INDENT-OFF*
73*c217d954SCole Faust // clang-format off
74*c217d954SCole Faust TEST_SUITE(IntegrationTestCase)
75*c217d954SCole Faust TEST_SUITE(MultSmallerEq1)
76*c217d954SCole Faust TEST_CASE(RunSmall, framework::DatasetMode::PRECOMMIT)
77*c217d954SCole Faust {
78*c217d954SCole Faust const int batch_size = 2;
79*c217d954SCole Faust const int input_size = 2;
80*c217d954SCole Faust const int output_size = 4;
81*c217d954SCole Faust
82*c217d954SCole Faust QuantizationInfo qasymm(1.f / 128.f, 128);
83*c217d954SCole Faust QuantizationInfo qweights(1.f / 128.f, 128);
84*c217d954SCole Faust QuantizationInfo qsymm_3(8.f / 32768.f, 0);
85*c217d954SCole Faust QuantizationInfo qsymm_4(16.f / 32768.f, 0);
86*c217d954SCole Faust
87*c217d954SCole Faust TensorShape input_shape{ input_size, batch_size };
88*c217d954SCole Faust TensorShape input_weights_shape{ input_size, output_size };
89*c217d954SCole Faust TensorShape recurrent_weights_shape{ output_size, output_size };
90*c217d954SCole Faust TensorShape output_shape{ output_size, batch_size};
91*c217d954SCole Faust TensorShape bias_shape{ output_size };
92*c217d954SCole Faust
93*c217d954SCole Faust auto input_to_input_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
94*c217d954SCole Faust auto input_to_forget_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
95*c217d954SCole Faust auto input_to_cell_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
96*c217d954SCole Faust auto input_to_output_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
97*c217d954SCole Faust auto recurrent_to_input_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
98*c217d954SCole Faust auto recurrent_to_forget_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
99*c217d954SCole Faust auto recurrent_to_cell_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
100*c217d954SCole Faust auto recurrent_to_output_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
101*c217d954SCole Faust auto input_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
102*c217d954SCole Faust auto forget_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
103*c217d954SCole Faust auto cell_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
104*c217d954SCole Faust auto output_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
105*c217d954SCole Faust
106*c217d954SCole Faust // LSTM input
107*c217d954SCole Faust auto input = create_tensor<CLTensor>(input_shape, DataType::QASYMM8, 1, qasymm);
108*c217d954SCole Faust
109*c217d954SCole Faust // LSTM output state
110*c217d954SCole Faust auto output_state = create_tensor<CLTensor>(output_shape, DataType::QASYMM8, 1, qasymm);
111*c217d954SCole Faust
112*c217d954SCole Faust // LSTM cell state
113*c217d954SCole Faust auto cell_state = create_tensor<CLTensor>(output_shape, DataType::QSYMM16, 1, qsymm_4);
114*c217d954SCole Faust
115*c217d954SCole Faust CLLSTMLayerQuantized lstmq;
116*c217d954SCole Faust
117*c217d954SCole Faust lstmq.configure(&input, &input_to_input_weights, &input_to_forget_weights, &input_to_cell_weights, &input_to_output_weights,
118*c217d954SCole Faust &recurrent_to_input_weights, &recurrent_to_forget_weights, &recurrent_to_cell_weights, &recurrent_to_output_weights,
119*c217d954SCole Faust &input_gate_bias, &forget_gate_bias, &cell_gate_bias, &output_gate_bias, &cell_state, &output_state, &cell_state, &output_state);
120*c217d954SCole Faust
121*c217d954SCole Faust input.allocator()->allocate();
122*c217d954SCole Faust input_to_input_weights.allocator()->allocate();
123*c217d954SCole Faust input_to_forget_weights.allocator()->allocate();
124*c217d954SCole Faust input_to_cell_weights.allocator()->allocate();
125*c217d954SCole Faust input_to_output_weights.allocator()->allocate();
126*c217d954SCole Faust recurrent_to_input_weights.allocator()->allocate();
127*c217d954SCole Faust recurrent_to_forget_weights.allocator()->allocate();
128*c217d954SCole Faust recurrent_to_cell_weights.allocator()->allocate();
129*c217d954SCole Faust recurrent_to_output_weights.allocator()->allocate();
130*c217d954SCole Faust input_gate_bias.allocator()->allocate();
131*c217d954SCole Faust forget_gate_bias.allocator()->allocate();
132*c217d954SCole Faust cell_gate_bias.allocator()->allocate();
133*c217d954SCole Faust output_gate_bias.allocator()->allocate();
134*c217d954SCole Faust cell_state.allocator()->allocate();
135*c217d954SCole Faust output_state.allocator()->allocate();
136*c217d954SCole Faust
137*c217d954SCole Faust // Fill weights and biases
138*c217d954SCole Faust fill_tensor(input_to_input_weights, std::vector<uint8_t>{ 47, 168,
139*c217d954SCole Faust 66, 239,
140*c217d954SCole Faust 6, 42,
141*c217d954SCole Faust 237, 236 });
142*c217d954SCole Faust
143*c217d954SCole Faust fill_tensor(input_to_forget_weights, std::vector<uint8_t> { 204, 193,
144*c217d954SCole Faust 148, 59,
145*c217d954SCole Faust 113, 17,
146*c217d954SCole Faust 66, 197 });
147*c217d954SCole Faust
148*c217d954SCole Faust fill_tensor(input_to_cell_weights, std::vector<uint8_t> { 172, 101,
149*c217d954SCole Faust 184, 209,
150*c217d954SCole Faust 165, 82,
151*c217d954SCole Faust 108, 209 });
152*c217d954SCole Faust
153*c217d954SCole Faust fill_tensor(input_to_output_weights, std::vector<uint8_t> { 203, 244,
154*c217d954SCole Faust 219, 114,
155*c217d954SCole Faust 130, 16,
156*c217d954SCole Faust 163, 222 });
157*c217d954SCole Faust
158*c217d954SCole Faust fill_tensor(recurrent_to_input_weights, std::vector<uint8_t> { 162, 168, 7, 95,
159*c217d954SCole Faust 91, 155, 108, 216,
160*c217d954SCole Faust 255, 100, 48, 188,
161*c217d954SCole Faust 58, 37, 186, 147 });
162*c217d954SCole Faust
163*c217d954SCole Faust fill_tensor(recurrent_to_forget_weights, std::vector<uint8_t> { 46, 58, 47, 170,
164*c217d954SCole Faust 246, 96, 12, 99,
165*c217d954SCole Faust 68, 23, 186, 161,
166*c217d954SCole Faust 237, 164, 89, 6 });
167*c217d954SCole Faust
168*c217d954SCole Faust fill_tensor(recurrent_to_cell_weights, std::vector<uint8_t> { 234, 99, 71, 206,
169*c217d954SCole Faust 205, 159, 64, 253,
170*c217d954SCole Faust 191, 148, 116, 8,
171*c217d954SCole Faust 209, 136, 59, 138 });
172*c217d954SCole Faust
173*c217d954SCole Faust fill_tensor(recurrent_to_output_weights, std::vector<uint8_t> { 23, 241, 137, 36,
174*c217d954SCole Faust 206, 5, 227, 56,
175*c217d954SCole Faust 254, 176, 231, 47,
176*c217d954SCole Faust 18, 201, 161, 11 });
177*c217d954SCole Faust
178*c217d954SCole Faust fill_tensor(input_gate_bias, std::vector<int> {-103038, 30525, 115255, -38154 });
179*c217d954SCole Faust fill_tensor(forget_gate_bias, std::vector<int> { -23428, 126970, 116806, 46307 });
180*c217d954SCole Faust fill_tensor(cell_gate_bias, std::vector<int> { 128006, 69949, -42808, 42568 });
181*c217d954SCole Faust fill_tensor(output_gate_bias, std::vector<int> { -67066, -53607, 47233, 7300 });
182*c217d954SCole Faust
183*c217d954SCole Faust SimpleTensor<uint8_t> expected_output(output_shape, DataType::QASYMM8, 1, qasymm);
184*c217d954SCole Faust
185*c217d954SCole Faust // Initialize state
186*c217d954SCole Faust fill_tensor(output_state, std::vector<uint8_t> { 128, 128, 128, 128,
187*c217d954SCole Faust 128, 128, 128, 128 });
188*c217d954SCole Faust fill_tensor(cell_state, std::vector<int16_t> { 0, 0, 0, 0,
189*c217d954SCole Faust 0, 0, 0, 0 });
190*c217d954SCole Faust
191*c217d954SCole Faust // First input
192*c217d954SCole Faust fill_tensor(input, std::vector<uint8_t> { 106, 193,
193*c217d954SCole Faust 155, 150 });
194*c217d954SCole Faust
195*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> { 128, 130, 36, 134,
196*c217d954SCole Faust 128, 131, 35, 133 });
197*c217d954SCole Faust
198*c217d954SCole Faust lstmq.run();
199*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
200*c217d954SCole Faust
201*c217d954SCole Faust // Second input
202*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> { 128, 129, 12, 137,
203*c217d954SCole Faust 128, 131, 10, 136 });
204*c217d954SCole Faust lstmq.run();
205*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
206*c217d954SCole Faust
207*c217d954SCole Faust // Third input
208*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> { 128, 129, 8, 140,
209*c217d954SCole Faust 128, 130, 6, 138 });
210*c217d954SCole Faust lstmq.run();
211*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
212*c217d954SCole Faust }
213*c217d954SCole Faust
TEST_CASE(RunLarge,framework::DatasetMode::PRECOMMIT)214*c217d954SCole Faust TEST_CASE(RunLarge, framework::DatasetMode::PRECOMMIT)
215*c217d954SCole Faust {
216*c217d954SCole Faust const int batch_size = 16;
217*c217d954SCole Faust const int input_size = 8;
218*c217d954SCole Faust const int output_size = 8;
219*c217d954SCole Faust
220*c217d954SCole Faust
221*c217d954SCole Faust QuantizationInfo qasymm(1.f / 128.f, 128);
222*c217d954SCole Faust QuantizationInfo qweights(1.f / 128.f, 128);
223*c217d954SCole Faust QuantizationInfo qsymm_3(8.f / 32768.f, 0);
224*c217d954SCole Faust QuantizationInfo qsymm_4(16.f / 32768.f, 0);
225*c217d954SCole Faust
226*c217d954SCole Faust TensorShape input_shape{ input_size, batch_size };
227*c217d954SCole Faust TensorShape input_weights_shape{ input_size, output_size };
228*c217d954SCole Faust TensorShape recurrent_weights_shape{ output_size, output_size };
229*c217d954SCole Faust TensorShape output_shape{ output_size, batch_size};
230*c217d954SCole Faust TensorShape bias_shape{ output_size };
231*c217d954SCole Faust
232*c217d954SCole Faust auto input_to_input_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
233*c217d954SCole Faust auto input_to_forget_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
234*c217d954SCole Faust auto input_to_cell_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
235*c217d954SCole Faust auto input_to_output_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
236*c217d954SCole Faust auto recurrent_to_input_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
237*c217d954SCole Faust auto recurrent_to_forget_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
238*c217d954SCole Faust auto recurrent_to_cell_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
239*c217d954SCole Faust auto recurrent_to_output_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
240*c217d954SCole Faust auto input_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
241*c217d954SCole Faust auto forget_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
242*c217d954SCole Faust auto cell_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
243*c217d954SCole Faust auto output_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
244*c217d954SCole Faust
245*c217d954SCole Faust // LSTM input
246*c217d954SCole Faust auto input = create_tensor<CLTensor>(input_shape, DataType::QASYMM8, 1, qasymm);
247*c217d954SCole Faust
248*c217d954SCole Faust // LSTM output state
249*c217d954SCole Faust auto output_state = create_tensor<CLTensor>(output_shape, DataType::QASYMM8, 1, qasymm);
250*c217d954SCole Faust
251*c217d954SCole Faust // LSTM cell state
252*c217d954SCole Faust auto cell_state = create_tensor<CLTensor>(output_shape, DataType::QSYMM16, 1, qsymm_4);
253*c217d954SCole Faust
254*c217d954SCole Faust CLLSTMLayerQuantized lstmq;
255*c217d954SCole Faust
256*c217d954SCole Faust lstmq.configure(&input, &input_to_input_weights, &input_to_forget_weights, &input_to_cell_weights, &input_to_output_weights,
257*c217d954SCole Faust &recurrent_to_input_weights, &recurrent_to_forget_weights, &recurrent_to_cell_weights, &recurrent_to_output_weights,
258*c217d954SCole Faust &input_gate_bias, &forget_gate_bias, &cell_gate_bias, &output_gate_bias, &cell_state, &output_state, &cell_state, &output_state);
259*c217d954SCole Faust
260*c217d954SCole Faust input.allocator()->allocate();
261*c217d954SCole Faust input_to_input_weights.allocator()->allocate();
262*c217d954SCole Faust input_to_forget_weights.allocator()->allocate();
263*c217d954SCole Faust input_to_cell_weights.allocator()->allocate();
264*c217d954SCole Faust input_to_output_weights.allocator()->allocate();
265*c217d954SCole Faust recurrent_to_input_weights.allocator()->allocate();
266*c217d954SCole Faust recurrent_to_forget_weights.allocator()->allocate();
267*c217d954SCole Faust recurrent_to_cell_weights.allocator()->allocate();
268*c217d954SCole Faust recurrent_to_output_weights.allocator()->allocate();
269*c217d954SCole Faust input_gate_bias.allocator()->allocate();
270*c217d954SCole Faust forget_gate_bias.allocator()->allocate();
271*c217d954SCole Faust cell_gate_bias.allocator()->allocate();
272*c217d954SCole Faust output_gate_bias.allocator()->allocate();
273*c217d954SCole Faust cell_state.allocator()->allocate();
274*c217d954SCole Faust output_state.allocator()->allocate();
275*c217d954SCole Faust
276*c217d954SCole Faust // Fill weights and biases
277*c217d954SCole Faust fill_tensor(input_to_input_weights, std::vector<uint8_t>{ 141, 89, 200, 180, 46, 50, 87, 128,
278*c217d954SCole Faust 149, 227, 177, 187, 212, 229, 54, 111,
279*c217d954SCole Faust 131, 116, 3, 58, 196, 26, 131, 255,
280*c217d954SCole Faust 22, 106, 216, 69, 239, 12, 232, 207,
281*c217d954SCole Faust 184, 56, 236, 172, 28, 143, 161, 124,
282*c217d954SCole Faust 255, 33, 197, 122, 47, 197, 26, 229,
283*c217d954SCole Faust 91, 79, 11, 160, 26, 80, 100, 36,
284*c217d954SCole Faust 248, 186, 97, 61, 125, 46, 14, 100, });
285*c217d954SCole Faust
286*c217d954SCole Faust fill_tensor(input_to_forget_weights, std::vector<uint8_t> { 237, 165, 141, 249, 72, 116, 36 , 115,
287*c217d954SCole Faust 234, 213, 85, 84, 59, 62, 150, 246,
288*c217d954SCole Faust 182, 102, 158, 214, 182, 183, 94, 11,
289*c217d954SCole Faust 158, 192, 92, 189, 160, 219, 206, 249,
290*c217d954SCole Faust 88, 213, 193, 244, 151, 72, 129, 49,
291*c217d954SCole Faust 239, 83, 106, 9, 169, 187, 125, 171,
292*c217d954SCole Faust 32, 141, 126, 92, 13, 36, 224, 150,
293*c217d954SCole Faust 187, 250, 178, 169, 89, 214, 91, 173 });
294*c217d954SCole Faust
295*c217d954SCole Faust fill_tensor(input_to_cell_weights, std::vector<uint8_t> { 93, 103, 226, 139, 185, 252, 129, 171,
296*c217d954SCole Faust 159, 32, 25, 175, 224, 183, 165, 35,
297*c217d954SCole Faust 207, 69, 238, 228, 149, 214, 79, 6,
298*c217d954SCole Faust 5, 66, 102, 14, 19, 111, 36, 143,
299*c217d954SCole Faust 22, 85, 13, 78, 236, 121, 122, 77,
300*c217d954SCole Faust 249, 39, 88, 12, 205, 143, 93, 240,
301*c217d954SCole Faust 167, 89, 188, 50, 73, 69, 201, 251,
302*c217d954SCole Faust 59, 32, 203, 184, 139, 191, 199, 74});
303*c217d954SCole Faust
304*c217d954SCole Faust fill_tensor(input_to_output_weights, std::vector<uint8_t> { 205, 7, 95, 104, 252, 143, 226, 73,
305*c217d954SCole Faust 229, 114, 152, 171, 221, 153, 73, 229,
306*c217d954SCole Faust 153, 165, 223, 239, 100, 38, 172, 211,
307*c217d954SCole Faust 226, 133, 239, 207, 116, 230, 170, 100,
308*c217d954SCole Faust 241, 95, 171, 124, 63, 115, 32, 127,
309*c217d954SCole Faust 141, 239, 53, 193, 201, 53, 104, 178,
310*c217d954SCole Faust 186, 212, 167, 107, 226, 230, 71, 213,
311*c217d954SCole Faust 148, 217, 19, 248, 233, 195, 183, 156 });
312*c217d954SCole Faust
313*c217d954SCole Faust fill_tensor(recurrent_to_input_weights, std::vector<uint8_t> { 147, 112, 140, 103, 3, 255, 17, 49,
314*c217d954SCole Faust 84, 112, 144, 213, 138, 142, 112, 66,
315*c217d954SCole Faust 117, 30, 101, 35, 25, 132, 211, 229,
316*c217d954SCole Faust 183, 208, 102, 16, 38, 85, 101, 152,
317*c217d954SCole Faust 226, 83, 132, 22, 161, 110, 157, 129,
318*c217d954SCole Faust 184, 63, 168, 42, 220, 126, 209, 157,
319*c217d954SCole Faust 5, 88, 243, 83, 249, 19, 226, 209,
320*c217d954SCole Faust 173, 96, 185, 77, 146, 227, 238, 136 });
321*c217d954SCole Faust
322*c217d954SCole Faust
323*c217d954SCole Faust fill_tensor(recurrent_to_forget_weights, std::vector<uint8_t> { 52, 132, 92, 200, 213, 32, 213, 37,
324*c217d954SCole Faust 116, 142, 116, 180, 4, 172, 158, 143,
325*c217d954SCole Faust 110, 40, 99, 28, 221, 153, 133, 2,
326*c217d954SCole Faust 247, 144, 198, 100, 20, 15, 221, 196,
327*c217d954SCole Faust 159, 178, 188, 151, 171, 15, 25, 217,
328*c217d954SCole Faust 178, 109, 110, 118, 128, 39, 232, 234,
329*c217d954SCole Faust 184, 214, 177, 13, 56, 6, 28, 252,
330*c217d954SCole Faust 89, 187, 242, 59, 146, 111, 132, 129});
331*c217d954SCole Faust
332*c217d954SCole Faust fill_tensor(recurrent_to_cell_weights, std::vector<uint8_t> { 70, 44, 137, 29, 36, 127, 1, 241,
333*c217d954SCole Faust 26, 241, 142, 114, 67, 181, 49, 57,
334*c217d954SCole Faust 131, 152, 175, 77, 23, 63, 37, 124,
335*c217d954SCole Faust 150, 113, 95, 103, 110, 201, 69, 97,
336*c217d954SCole Faust 196, 242, 62, 214, 66, 19, 45, 135,
337*c217d954SCole Faust 22, 168, 149, 104, 77, 101, 36, 68,
338*c217d954SCole Faust 170, 116, 222, 100, 109, 1, 154, 18,
339*c217d954SCole Faust 133, 215, 105, 93, 31, 57, 231, 112 });
340*c217d954SCole Faust
341*c217d954SCole Faust
342*c217d954SCole Faust fill_tensor(recurrent_to_output_weights, std::vector<uint8_t> { 45 , 181 , 220 , 219 , 49 , 63 , 49 , 129,
343*c217d954SCole Faust 7 , 166 , 104 , 114 , 83 , 40 , 1 , 195,
344*c217d954SCole Faust 245 , 142 , 82 , 232 , 104 , 245 , 82 , 196,
345*c217d954SCole Faust 111 , 56 , 156 , 9 , 141 , 240 , 180 , 148,
346*c217d954SCole Faust 247 , 198 , 234 , 137 , 13 , 210 , 161 , 192,
347*c217d954SCole Faust 196 , 59 , 233 , 184 , 142 , 187 , 140 , 166,
348*c217d954SCole Faust 2 , 95 , 152 , 46 , 71 , 46 , 113 , 32,
349*c217d954SCole Faust 175 , 229 , 86 , 87 , 62 , 93 , 74 , 130});
350*c217d954SCole Faust
351*c217d954SCole Faust fill_tensor(input_gate_bias, std::vector<int> { -40040, -106916, -92315, -79123, 45160, -17954, 50962, -63758 });
352*c217d954SCole Faust fill_tensor(forget_gate_bias, std::vector<int> { -128514, 8463, -57831, 116977, 106547, -28132, -124557, 44941 });
353*c217d954SCole Faust fill_tensor(cell_gate_bias, std::vector<int> { 88388 , 123601, -116148, -13022, 21619, 48926, 57523, 39332 });
354*c217d954SCole Faust fill_tensor(output_gate_bias, std::vector<int> { 59485 , -33070, 21386, -100633, -115959, 125768, -56407, 24897 });
355*c217d954SCole Faust
356*c217d954SCole Faust SimpleTensor<uint8_t> expected_output(output_shape, DataType::QASYMM8, 1, qasymm);
357*c217d954SCole Faust
358*c217d954SCole Faust // Initialize state
359*c217d954SCole Faust fill_tensor(output_state, std::vector<uint8_t> { 128, 128, 128, 128, 128, 128, 128, 128,
360*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
361*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
362*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
363*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
364*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
365*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
366*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
367*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
368*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
369*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
370*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
371*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
372*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
373*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128,
374*c217d954SCole Faust 128, 128, 128, 128, 128, 128, 128, 128 });
375*c217d954SCole Faust
376*c217d954SCole Faust fill_tensor(cell_state, std::vector<int16_t> { 0, 0, 0, 0, 0, 0, 0, 0,
377*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
378*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
379*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
380*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
381*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
382*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
383*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
384*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
385*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
386*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
387*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
388*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
389*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
390*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0,
391*c217d954SCole Faust 0, 0, 0, 0, 0, 0, 0, 0});
392*c217d954SCole Faust
393*c217d954SCole Faust // First input
394*c217d954SCole Faust fill_tensor(input, std::vector<uint8_t> { 247, 203, 159, 131, 182, 114, 207, 195,
395*c217d954SCole Faust 48 , 61 , 154, 16, 80, 101, 116, 255,
396*c217d954SCole Faust 50 , 115 , 45, 186, 75, 212, 98, 48,
397*c217d954SCole Faust 88 , 146 , 24, 143, 218, 174, 203, 200,
398*c217d954SCole Faust 239 , 16 , 66, 136, 234, 54, 94, 51,
399*c217d954SCole Faust 101 , 128 , 220, 213, 164, 82, 137, 255,
400*c217d954SCole Faust 70 , 165 , 234, 220, 66, 35, 183, 206,
401*c217d954SCole Faust 39 , 57 , 180, 202, 23, 172, 224, 109,
402*c217d954SCole Faust 102 , 215 , 186, 82, 215, 147, 85, 187,
403*c217d954SCole Faust 96 , 249 , 59, 116, 150, 44, 167, 128,
404*c217d954SCole Faust 34 , 217 , 148, 193, 243, 38, 250, 208,
405*c217d954SCole Faust 112 , 130 , 208, 29, 16, 122, 20, 92,
406*c217d954SCole Faust 24 , 72 , 104, 29, 150, 233, 151, 19,
407*c217d954SCole Faust 158 , 192 , 254, 70, 73, 142, 106, 152,
408*c217d954SCole Faust 3 , 61 , 24, 135, 212, 9, 80, 234,
409*c217d954SCole Faust 147 , 246 , 83, 249, 49, 14, 68, 50});
410*c217d954SCole Faust
411*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> {131, 128, 128, 128, 128, 180, 129, 133,
412*c217d954SCole Faust 136, 128, 126, 128, 128, 173, 135, 130,
413*c217d954SCole Faust 160, 128, 128, 128, 128, 138, 132, 129,
414*c217d954SCole Faust 131, 128, 127, 128, 128, 169, 129, 131,
415*c217d954SCole Faust 133, 128, 128, 128, 128, 182, 130, 129,
416*c217d954SCole Faust 131, 128, 128, 128, 128, 163, 129, 130,
417*c217d954SCole Faust 131, 128, 128, 128, 128, 149, 132, 129,
418*c217d954SCole Faust 143, 128, 127, 128, 128, 150, 134, 131,
419*c217d954SCole Faust 134, 128, 128, 128, 128, 167, 130, 130,
420*c217d954SCole Faust 131, 128, 128, 128, 128, 152, 132, 129,
421*c217d954SCole Faust 128, 128, 128, 128, 128, 169, 130, 130,
422*c217d954SCole Faust 173, 128, 128, 128, 128, 148, 139, 130,
423*c217d954SCole Faust 152, 128, 128, 128, 128, 168, 139, 132,
424*c217d954SCole Faust 147, 128, 128, 128, 128, 161, 131, 132,
425*c217d954SCole Faust 130, 128, 128, 128, 128, 159, 134, 128,
426*c217d954SCole Faust 140, 128, 128, 128, 128, 133, 132, 128 });
427*c217d954SCole Faust
428*c217d954SCole Faust lstmq.run();
429*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
430*c217d954SCole Faust
431*c217d954SCole Faust // Second input
432*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> { 130, 128, 128, 128, 128, 205, 129, 137,
433*c217d954SCole Faust 135, 128, 127, 128, 128, 190, 137, 132,
434*c217d954SCole Faust 160, 128, 128, 128, 128, 142, 133, 131,
435*c217d954SCole Faust 130, 128, 128, 128, 128, 185, 129, 133,
436*c217d954SCole Faust 132, 128, 128, 128, 128, 198, 131, 130,
437*c217d954SCole Faust 130, 128, 128, 128, 128, 178, 130, 131,
438*c217d954SCole Faust 131, 128, 128, 128, 128, 158, 132, 131,
439*c217d954SCole Faust 142, 128, 127, 128, 128, 158, 135, 134,
440*c217d954SCole Faust 133, 128, 128, 128, 128, 178, 131, 132,
441*c217d954SCole Faust 131, 128, 128, 128, 128, 160, 132, 130,
442*c217d954SCole Faust 128, 128, 128, 128, 128, 190, 131, 131,
443*c217d954SCole Faust 170, 128, 128, 128, 128, 157, 142, 131,
444*c217d954SCole Faust 149, 128, 128, 128, 128, 178, 142, 135,
445*c217d954SCole Faust 145, 128, 128, 128, 129, 173, 132, 135,
446*c217d954SCole Faust 129, 128, 128, 128, 128, 171, 134, 129,
447*c217d954SCole Faust 140, 128, 128, 128, 128, 135, 132, 129});
448*c217d954SCole Faust lstmq.run();
449*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
450*c217d954SCole Faust }
451*c217d954SCole Faust TEST_SUITE_END() // MultSmallerEq1
452*c217d954SCole Faust
TEST_SUITE(MultGreater1)453*c217d954SCole Faust TEST_SUITE(MultGreater1)
454*c217d954SCole Faust TEST_CASE(RunSmall, framework::DatasetMode::PRECOMMIT)
455*c217d954SCole Faust {
456*c217d954SCole Faust //Input sequence length is 1
457*c217d954SCole Faust const int batch_size = 2;
458*c217d954SCole Faust const int input_size = 2;
459*c217d954SCole Faust const int output_size = 4;
460*c217d954SCole Faust
461*c217d954SCole Faust QuantizationInfo qasymm(1.f / 128.f, 128);
462*c217d954SCole Faust QuantizationInfo qweights(1.f / 16.f, 16);
463*c217d954SCole Faust QuantizationInfo qsymm_3(8.f / 32768.f, 0);
464*c217d954SCole Faust QuantizationInfo qsymm_4(16.f / 32768.f, 0);
465*c217d954SCole Faust
466*c217d954SCole Faust TensorShape input_shape{ input_size, batch_size };
467*c217d954SCole Faust TensorShape input_weights_shape{ input_size, output_size };
468*c217d954SCole Faust TensorShape recurrent_weights_shape{ output_size, output_size };
469*c217d954SCole Faust TensorShape output_shape{ output_size, batch_size};
470*c217d954SCole Faust TensorShape bias_shape{ output_size };
471*c217d954SCole Faust
472*c217d954SCole Faust auto input_to_input_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
473*c217d954SCole Faust auto input_to_forget_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
474*c217d954SCole Faust auto input_to_cell_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
475*c217d954SCole Faust auto input_to_output_weights = create_tensor<CLTensor>(input_weights_shape, DataType::QASYMM8, 1, qweights);
476*c217d954SCole Faust auto recurrent_to_input_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
477*c217d954SCole Faust auto recurrent_to_forget_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
478*c217d954SCole Faust auto recurrent_to_cell_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
479*c217d954SCole Faust auto recurrent_to_output_weights = create_tensor<CLTensor>(recurrent_weights_shape, DataType::QASYMM8, 1, qweights);
480*c217d954SCole Faust auto input_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
481*c217d954SCole Faust auto forget_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
482*c217d954SCole Faust auto cell_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
483*c217d954SCole Faust auto output_gate_bias = create_tensor<CLTensor>(bias_shape, DataType::S32);
484*c217d954SCole Faust
485*c217d954SCole Faust // LSTM input
486*c217d954SCole Faust auto input = create_tensor<CLTensor>(input_shape, DataType::QASYMM8, 1, qasymm);
487*c217d954SCole Faust
488*c217d954SCole Faust // LSTM output state
489*c217d954SCole Faust auto output_state = create_tensor<CLTensor>(output_shape, DataType::QASYMM8, 1, qasymm);
490*c217d954SCole Faust
491*c217d954SCole Faust // LSTM cell state
492*c217d954SCole Faust auto cell_state = create_tensor<CLTensor>(output_shape, DataType::QSYMM16, 1, qsymm_4);
493*c217d954SCole Faust
494*c217d954SCole Faust CLLSTMLayerQuantized lstmq;
495*c217d954SCole Faust
496*c217d954SCole Faust lstmq.configure(&input, &input_to_input_weights, &input_to_forget_weights, &input_to_cell_weights, &input_to_output_weights,
497*c217d954SCole Faust &recurrent_to_input_weights, &recurrent_to_forget_weights, &recurrent_to_cell_weights, &recurrent_to_output_weights,
498*c217d954SCole Faust &input_gate_bias, &forget_gate_bias, &cell_gate_bias, &output_gate_bias, &cell_state, &output_state, &cell_state, &output_state);
499*c217d954SCole Faust
500*c217d954SCole Faust input.allocator()->allocate();
501*c217d954SCole Faust input_to_input_weights.allocator()->allocate();
502*c217d954SCole Faust input_to_forget_weights.allocator()->allocate();
503*c217d954SCole Faust input_to_cell_weights.allocator()->allocate();
504*c217d954SCole Faust input_to_output_weights.allocator()->allocate();
505*c217d954SCole Faust recurrent_to_input_weights.allocator()->allocate();
506*c217d954SCole Faust recurrent_to_forget_weights.allocator()->allocate();
507*c217d954SCole Faust recurrent_to_cell_weights.allocator()->allocate();
508*c217d954SCole Faust recurrent_to_output_weights.allocator()->allocate();
509*c217d954SCole Faust input_gate_bias.allocator()->allocate();
510*c217d954SCole Faust forget_gate_bias.allocator()->allocate();
511*c217d954SCole Faust cell_gate_bias.allocator()->allocate();
512*c217d954SCole Faust output_gate_bias.allocator()->allocate();
513*c217d954SCole Faust cell_state.allocator()->allocate();
514*c217d954SCole Faust output_state.allocator()->allocate();
515*c217d954SCole Faust
516*c217d954SCole Faust // Fill weights and biases
517*c217d954SCole Faust fill_tensor(input_to_input_weights, std::vector<uint8_t>{ 122, 130,
518*c217d954SCole Faust 124, 134,
519*c217d954SCole Faust 120, 122,
520*c217d954SCole Faust 134, 134 });
521*c217d954SCole Faust
522*c217d954SCole Faust fill_tensor(input_to_forget_weights, std::vector<uint8_t> { 204, 193,
523*c217d954SCole Faust 148, 59,
524*c217d954SCole Faust 113, 17,
525*c217d954SCole Faust 66, 197 });
526*c217d954SCole Faust
527*c217d954SCole Faust fill_tensor(input_to_cell_weights, std::vector<uint8_t> { 172, 101,
528*c217d954SCole Faust 184, 209,
529*c217d954SCole Faust 165, 82,
530*c217d954SCole Faust 108, 209 });
531*c217d954SCole Faust
532*c217d954SCole Faust fill_tensor(input_to_output_weights, std::vector<uint8_t> { 203, 244,
533*c217d954SCole Faust 219, 114,
534*c217d954SCole Faust 130, 16,
535*c217d954SCole Faust 163, 222 });
536*c217d954SCole Faust
537*c217d954SCole Faust fill_tensor(recurrent_to_input_weights, std::vector<uint8_t> { 162, 168, 7, 95,
538*c217d954SCole Faust 91, 155, 108, 216,
539*c217d954SCole Faust 255, 100, 48, 188,
540*c217d954SCole Faust 58, 37, 186, 147 });
541*c217d954SCole Faust
542*c217d954SCole Faust fill_tensor(recurrent_to_forget_weights, std::vector<uint8_t> { 46, 58, 47, 170,
543*c217d954SCole Faust 246, 96, 12, 99,
544*c217d954SCole Faust 68, 23, 186, 161,
545*c217d954SCole Faust 237, 164, 89, 6 });
546*c217d954SCole Faust
547*c217d954SCole Faust fill_tensor(recurrent_to_cell_weights, std::vector<uint8_t> { 234, 99, 71, 206,
548*c217d954SCole Faust 205, 159, 64, 253,
549*c217d954SCole Faust 191, 148, 116, 8,
550*c217d954SCole Faust 209, 136, 59, 138 });
551*c217d954SCole Faust
552*c217d954SCole Faust fill_tensor(recurrent_to_output_weights, std::vector<uint8_t> { 23, 241, 137, 36,
553*c217d954SCole Faust 206, 5, 227, 56,
554*c217d954SCole Faust 254, 176, 231, 47,
555*c217d954SCole Faust 18, 201, 161, 11 });
556*c217d954SCole Faust
557*c217d954SCole Faust fill_tensor(input_gate_bias, std::vector<int> {-103038, 30525, 115255, -38154 });
558*c217d954SCole Faust fill_tensor(forget_gate_bias, std::vector<int> { -23428, 126970, 116806, 46307 });
559*c217d954SCole Faust fill_tensor(cell_gate_bias, std::vector<int> { 128006, 69949, -42808, 42568 });
560*c217d954SCole Faust fill_tensor(output_gate_bias, std::vector<int> { -67066, -53607, 47233, 7300 });
561*c217d954SCole Faust
562*c217d954SCole Faust SimpleTensor<uint8_t> expected_output(output_shape, DataType::QASYMM8, 1, qasymm);
563*c217d954SCole Faust
564*c217d954SCole Faust // Initialize state
565*c217d954SCole Faust fill_tensor(output_state, std::vector<uint8_t> { 128, 128, 128, 128,
566*c217d954SCole Faust 128, 128, 128, 128 });
567*c217d954SCole Faust fill_tensor(cell_state, std::vector<int16_t> { 0, 0, 0, 0,
568*c217d954SCole Faust 0, 0, 0, 0 });
569*c217d954SCole Faust
570*c217d954SCole Faust // First input
571*c217d954SCole Faust fill_tensor(input, std::vector<uint8_t> { 106, 193,
572*c217d954SCole Faust 155, 150 });
573*c217d954SCole Faust
574*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> { 128, 128, 31, 128,
575*c217d954SCole Faust 128, 128, 31, 128 });
576*c217d954SCole Faust
577*c217d954SCole Faust lstmq.run();
578*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
579*c217d954SCole Faust
580*c217d954SCole Faust // Second input
581*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> { 128, 128, 5, 128,
582*c217d954SCole Faust 128, 128, 5, 128 });
583*c217d954SCole Faust lstmq.run();
584*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
585*c217d954SCole Faust
586*c217d954SCole Faust // Third input
587*c217d954SCole Faust fill_tensor(expected_output, std::vector<uint8_t> { 128, 128, 1, 128,
588*c217d954SCole Faust 128, 128, 1, 128, });
589*c217d954SCole Faust lstmq.run();
590*c217d954SCole Faust validate(CLAccessor(output_state), expected_output);
591*c217d954SCole Faust }
592*c217d954SCole Faust TEST_SUITE_END() // MultGreater1
593*c217d954SCole Faust TEST_SUITE_END() // IntegrationTestCase
594*c217d954SCole Faust // clang-format on
595*c217d954SCole Faust // *INDENT-ON*
596*c217d954SCole Faust
597*c217d954SCole Faust TEST_SUITE_END() // LSTMLayerQuantized
598*c217d954SCole Faust TEST_SUITE_END() // CL
599*c217d954SCole Faust } // namespace validation
600*c217d954SCole Faust } // namespace test
601*c217d954SCole Faust } // namespace arm_compute
602