xref: /aosp_15_r20/external/armnn/src/backends/backendsCommon/test/QuantizedLstmEndToEndTestImpl.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2019 Arm Ltd. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker #include "QuantizedLstmEndToEndTestImpl.hpp"
7*89c4ff92SAndroid Build Coastguard Worker 
8*89c4ff92SAndroid Build Coastguard Worker #include <CommonTestUtils.hpp>
9*89c4ff92SAndroid Build Coastguard Worker #include "EndToEndTestImpl.hpp"
10*89c4ff92SAndroid Build Coastguard Worker 
11*89c4ff92SAndroid Build Coastguard Worker #include <ResolveType.hpp>
12*89c4ff92SAndroid Build Coastguard Worker 
13*89c4ff92SAndroid Build Coastguard Worker #include <armnn/INetwork.hpp>
14*89c4ff92SAndroid Build Coastguard Worker #include <armnn/QuantizedLstmParams.hpp>
15*89c4ff92SAndroid Build Coastguard Worker 
16*89c4ff92SAndroid Build Coastguard Worker #include <armnn/utility/NumericCast.hpp>
17*89c4ff92SAndroid Build Coastguard Worker 
18*89c4ff92SAndroid Build Coastguard Worker #include <armnnTestUtils/TensorHelpers.hpp>
19*89c4ff92SAndroid Build Coastguard Worker 
20*89c4ff92SAndroid Build Coastguard Worker #include <doctest/doctest.h>
21*89c4ff92SAndroid Build Coastguard Worker 
22*89c4ff92SAndroid Build Coastguard Worker #include <type_traits>
23*89c4ff92SAndroid Build Coastguard Worker 
24*89c4ff92SAndroid Build Coastguard Worker namespace
25*89c4ff92SAndroid Build Coastguard Worker {
26*89c4ff92SAndroid Build Coastguard Worker 
CreateQuantizedLstmNetwork(armnn::TensorShape & inputShape,armnn::TensorShape & outputExpectedShape)27*89c4ff92SAndroid Build Coastguard Worker armnn::INetworkPtr CreateQuantizedLstmNetwork(armnn::TensorShape& inputShape,
28*89c4ff92SAndroid Build Coastguard Worker                                               armnn::TensorShape& outputExpectedShape)
29*89c4ff92SAndroid Build Coastguard Worker {
30*89c4ff92SAndroid Build Coastguard Worker     auto batchSize = armnn::numeric_cast<unsigned int>(inputShape[0]);
31*89c4ff92SAndroid Build Coastguard Worker     auto inputSize = armnn::numeric_cast<unsigned int>(inputShape[1]);
32*89c4ff92SAndroid Build Coastguard Worker     auto outputSize = armnn::numeric_cast<unsigned int>(outputExpectedShape[1]);
33*89c4ff92SAndroid Build Coastguard Worker 
34*89c4ff92SAndroid Build Coastguard Worker     float inputOutputScale = 0.0078125f;
35*89c4ff92SAndroid Build Coastguard Worker     int32_t inputOutputOffset = 128;
36*89c4ff92SAndroid Build Coastguard Worker 
37*89c4ff92SAndroid Build Coastguard Worker     float weightsScale = 0.00408021f;
38*89c4ff92SAndroid Build Coastguard Worker     int32_t weightsOffset = 100;
39*89c4ff92SAndroid Build Coastguard Worker 
40*89c4ff92SAndroid Build Coastguard Worker     float biasScale = 3.1876640625e-05f;
41*89c4ff92SAndroid Build Coastguard Worker     int32_t biasOffset = 0;
42*89c4ff92SAndroid Build Coastguard Worker 
43*89c4ff92SAndroid Build Coastguard Worker     float cellStateScale = 0.00048828125f;
44*89c4ff92SAndroid Build Coastguard Worker     int32_t cellStateOffset = 0;
45*89c4ff92SAndroid Build Coastguard Worker 
46*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo inputWeightsInfo({outputSize, inputSize},
47*89c4ff92SAndroid Build Coastguard Worker                                        armnn::DataType::QAsymmU8,
48*89c4ff92SAndroid Build Coastguard Worker                                        weightsScale,
49*89c4ff92SAndroid Build Coastguard Worker                                        weightsOffset,
50*89c4ff92SAndroid Build Coastguard Worker                                        true);
51*89c4ff92SAndroid Build Coastguard Worker 
52*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo recurrentWeightsInfo({outputSize, outputSize},
53*89c4ff92SAndroid Build Coastguard Worker                                            armnn::DataType::QAsymmU8,
54*89c4ff92SAndroid Build Coastguard Worker                                            weightsScale,
55*89c4ff92SAndroid Build Coastguard Worker                                            weightsOffset,
56*89c4ff92SAndroid Build Coastguard Worker                                            true);
57*89c4ff92SAndroid Build Coastguard Worker 
58*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo biasInfo({outputSize}, armnn::DataType::Signed32, biasScale, biasOffset, true);
59*89c4ff92SAndroid Build Coastguard Worker 
60*89c4ff92SAndroid Build Coastguard Worker     armnn::QuantizedLstmInputParams data;
61*89c4ff92SAndroid Build Coastguard Worker 
62*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> inputToInputWeightsVector = {146, 250, 235, 171, 10, 218, 171, 108};
63*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor inputToInputWeightsTensor(inputWeightsInfo, inputToInputWeightsVector.data());
64*89c4ff92SAndroid Build Coastguard Worker 
65*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> inputToForgetWeightsVector = {24, 50, 132, 179, 158, 110, 3, 169};
66*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor inputToForgetWeightsTensor(inputWeightsInfo, inputToForgetWeightsVector.data());
67*89c4ff92SAndroid Build Coastguard Worker 
68*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> inputToCellWeightsTensorVector = {133, 34, 29, 49, 206, 109, 54, 183};
69*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor inputToCellWeightsTensor(inputWeightsInfo, inputToCellWeightsTensorVector.data());
70*89c4ff92SAndroid Build Coastguard Worker 
71*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> inputToOutputWeightsTensorVector = {195, 187, 11, 99, 109, 10, 218, 48};
72*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor inputToOutputWeightsTensor(inputWeightsInfo, inputToOutputWeightsTensorVector.data());
73*89c4ff92SAndroid Build Coastguard Worker 
74*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> recurrentToInputWeightsTensorVector =
75*89c4ff92SAndroid Build Coastguard Worker             {254, 206, 77, 168, 71, 20, 215, 6, 223, 7, 118, 225, 59, 130, 174, 26};
76*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor recurrentToInputWeightsTensor(recurrentWeightsInfo, recurrentToInputWeightsTensorVector.data());
77*89c4ff92SAndroid Build Coastguard Worker 
78*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> recurrentToForgetWeightsTensorVector =
79*89c4ff92SAndroid Build Coastguard Worker             {137, 240, 103, 52, 68, 51, 237, 112, 0, 220, 89, 23, 69, 4, 207, 253};
80*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor recurrentToForgetWeightsTensor(recurrentWeightsInfo,
81*89c4ff92SAndroid Build Coastguard Worker                                                       recurrentToForgetWeightsTensorVector.data());
82*89c4ff92SAndroid Build Coastguard Worker 
83*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> recurrentToCellWeightsTensorVector =
84*89c4ff92SAndroid Build Coastguard Worker             {172, 60, 205, 65, 14, 0, 140, 168, 240, 223, 133, 56, 142, 64, 246, 216};
85*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor recurrentToCellWeightsTensor(recurrentWeightsInfo, recurrentToCellWeightsTensorVector.data());
86*89c4ff92SAndroid Build Coastguard Worker 
87*89c4ff92SAndroid Build Coastguard Worker     const std::vector<uint8_t> recurrentToOutputWeightsTensorVector =
88*89c4ff92SAndroid Build Coastguard Worker             {106, 214, 67, 23, 59, 158, 45, 3, 119, 132, 49, 205, 129, 218, 11, 98};
89*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor recurrentToOutputWeightsTensor(recurrentWeightsInfo,
90*89c4ff92SAndroid Build Coastguard Worker                                                       recurrentToOutputWeightsTensorVector.data());
91*89c4ff92SAndroid Build Coastguard Worker 
92*89c4ff92SAndroid Build Coastguard Worker     const std::vector<int32_t> inputGateBiasTensorVector = {-7876, 13488, -726, 32839};
93*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor inputGateBiasTensor(biasInfo, inputGateBiasTensorVector.data());
94*89c4ff92SAndroid Build Coastguard Worker 
95*89c4ff92SAndroid Build Coastguard Worker     const std::vector<int32_t> forgetGateBiasTensorVector = {9206, -46884, -11693, -38724};
96*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor forgetGateBiasTensor(biasInfo, forgetGateBiasTensorVector.data());
97*89c4ff92SAndroid Build Coastguard Worker 
98*89c4ff92SAndroid Build Coastguard Worker     const std::vector<int32_t> cellBiasTensorVector = {39481, 48624, 48976, -21419};
99*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor cellBiasTensor(biasInfo, cellBiasTensorVector.data());
100*89c4ff92SAndroid Build Coastguard Worker 
101*89c4ff92SAndroid Build Coastguard Worker     const std::vector<int32_t> outputGateBiasTensorVector = {-58999, -17050, -41852, -40538};
102*89c4ff92SAndroid Build Coastguard Worker     armnn::ConstTensor outputGateBiasTensor(biasInfo, outputGateBiasTensorVector.data());
103*89c4ff92SAndroid Build Coastguard Worker 
104*89c4ff92SAndroid Build Coastguard Worker     data.m_InputToInputWeights = &inputToInputWeightsTensor;
105*89c4ff92SAndroid Build Coastguard Worker     data.m_InputToForgetWeights = &inputToForgetWeightsTensor;
106*89c4ff92SAndroid Build Coastguard Worker     data.m_InputToCellWeights = &inputToCellWeightsTensor;
107*89c4ff92SAndroid Build Coastguard Worker     data.m_InputToOutputWeights = &inputToOutputWeightsTensor;
108*89c4ff92SAndroid Build Coastguard Worker     data.m_RecurrentToInputWeights = &recurrentToInputWeightsTensor;
109*89c4ff92SAndroid Build Coastguard Worker     data.m_RecurrentToForgetWeights = &recurrentToForgetWeightsTensor;
110*89c4ff92SAndroid Build Coastguard Worker     data.m_RecurrentToCellWeights = &recurrentToCellWeightsTensor;
111*89c4ff92SAndroid Build Coastguard Worker     data.m_RecurrentToOutputWeights = &recurrentToOutputWeightsTensor;
112*89c4ff92SAndroid Build Coastguard Worker     data.m_InputGateBias = &inputGateBiasTensor;
113*89c4ff92SAndroid Build Coastguard Worker     data.m_ForgetGateBias = &forgetGateBiasTensor;
114*89c4ff92SAndroid Build Coastguard Worker     data.m_CellBias = &cellBiasTensor;
115*89c4ff92SAndroid Build Coastguard Worker     data.m_OutputGateBias = &outputGateBiasTensor;
116*89c4ff92SAndroid Build Coastguard Worker 
117*89c4ff92SAndroid Build Coastguard Worker     armnn::INetworkPtr net(armnn::INetwork::Create());
118*89c4ff92SAndroid Build Coastguard Worker 
119*89c4ff92SAndroid Build Coastguard Worker     armnn::IConnectableLayer* const inputLayer   = net->AddInputLayer(0);
120*89c4ff92SAndroid Build Coastguard Worker     armnn::IConnectableLayer* const cellStateIn = net->AddInputLayer(1);
121*89c4ff92SAndroid Build Coastguard Worker     armnn::IConnectableLayer* const outputStateIn = net->AddInputLayer(2);
122*89c4ff92SAndroid Build Coastguard Worker     armnn::IConnectableLayer* const quantizedLstmLayer = net->AddQuantizedLstmLayer(data, "quantizedLstm");
123*89c4ff92SAndroid Build Coastguard Worker     armnn::IConnectableLayer* const cellStateOut  = net->AddOutputLayer(0);
124*89c4ff92SAndroid Build Coastguard Worker     armnn::IConnectableLayer* const outputStateOut  = net->AddOutputLayer(1);
125*89c4ff92SAndroid Build Coastguard Worker 
126*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo inputTensorInfo({batchSize , inputSize},
127*89c4ff92SAndroid Build Coastguard Worker                                       armnn::DataType::QAsymmU8,
128*89c4ff92SAndroid Build Coastguard Worker                                       inputOutputScale,
129*89c4ff92SAndroid Build Coastguard Worker                                       inputOutputOffset);
130*89c4ff92SAndroid Build Coastguard Worker 
131*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo cellStateInTensorInfo({batchSize , outputSize},
132*89c4ff92SAndroid Build Coastguard Worker                                             armnn::DataType::QSymmS16,
133*89c4ff92SAndroid Build Coastguard Worker                                             cellStateScale,
134*89c4ff92SAndroid Build Coastguard Worker                                             cellStateOffset);
135*89c4ff92SAndroid Build Coastguard Worker 
136*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo outputStateInTensorInfo({batchSize , outputSize},
137*89c4ff92SAndroid Build Coastguard Worker                                               armnn::DataType::QAsymmU8,
138*89c4ff92SAndroid Build Coastguard Worker                                               inputOutputScale,
139*89c4ff92SAndroid Build Coastguard Worker                                               inputOutputOffset);
140*89c4ff92SAndroid Build Coastguard Worker 
141*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo cellStateOutTensorInfo({batchSize, outputSize},
142*89c4ff92SAndroid Build Coastguard Worker                                              armnn::DataType::QSymmS16,
143*89c4ff92SAndroid Build Coastguard Worker                                              cellStateScale,
144*89c4ff92SAndroid Build Coastguard Worker                                              cellStateOffset);
145*89c4ff92SAndroid Build Coastguard Worker 
146*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo outputTensorInfo({batchSize, outputSize},
147*89c4ff92SAndroid Build Coastguard Worker                                        armnn::DataType::QAsymmU8,
148*89c4ff92SAndroid Build Coastguard Worker                                        inputOutputScale,
149*89c4ff92SAndroid Build Coastguard Worker                                        inputOutputOffset);
150*89c4ff92SAndroid Build Coastguard Worker 
151*89c4ff92SAndroid Build Coastguard Worker     // connect up
152*89c4ff92SAndroid Build Coastguard Worker     // inputs
153*89c4ff92SAndroid Build Coastguard Worker     Connect(inputLayer, quantizedLstmLayer, inputTensorInfo, 0, 0);
154*89c4ff92SAndroid Build Coastguard Worker     Connect(cellStateIn, quantizedLstmLayer, cellStateInTensorInfo, 0, 1);
155*89c4ff92SAndroid Build Coastguard Worker     Connect(outputStateIn, quantizedLstmLayer, outputStateInTensorInfo, 0, 2);
156*89c4ff92SAndroid Build Coastguard Worker 
157*89c4ff92SAndroid Build Coastguard Worker     // outputs
158*89c4ff92SAndroid Build Coastguard Worker     Connect(quantizedLstmLayer, cellStateOut, cellStateOutTensorInfo, 0, 0);
159*89c4ff92SAndroid Build Coastguard Worker     Connect(quantizedLstmLayer, outputStateOut, outputTensorInfo, 1, 0);
160*89c4ff92SAndroid Build Coastguard Worker 
161*89c4ff92SAndroid Build Coastguard Worker     return net;
162*89c4ff92SAndroid Build Coastguard Worker }
163*89c4ff92SAndroid Build Coastguard Worker 
164*89c4ff92SAndroid Build Coastguard Worker // Checks if two values of an arithmetic type are close enough to each other
165*89c4ff92SAndroid Build Coastguard Worker // with regard to a given tolerance value.
166*89c4ff92SAndroid Build Coastguard Worker template<typename T>
167*89c4ff92SAndroid Build Coastguard Worker typename std::enable_if<std::is_arithmetic<T>::value, bool>::type
IsCloseEnough(T value1,T value2,T tolerance)168*89c4ff92SAndroid Build Coastguard Worker IsCloseEnough(T value1, T value2, T tolerance)
169*89c4ff92SAndroid Build Coastguard Worker {
170*89c4ff92SAndroid Build Coastguard Worker     if (tolerance < 0)
171*89c4ff92SAndroid Build Coastguard Worker     {
172*89c4ff92SAndroid Build Coastguard Worker         throw armnn::InvalidArgumentException("Tolerance cannot be < 0");
173*89c4ff92SAndroid Build Coastguard Worker     }
174*89c4ff92SAndroid Build Coastguard Worker 
175*89c4ff92SAndroid Build Coastguard Worker     T diff = value1 >= value2 ? static_cast<T>(value1 - value2) : static_cast<T>(value2 - value1);
176*89c4ff92SAndroid Build Coastguard Worker     return diff <= tolerance;
177*89c4ff92SAndroid Build Coastguard Worker }
178*89c4ff92SAndroid Build Coastguard Worker 
179*89c4ff92SAndroid Build Coastguard Worker } // anonymous namespace
180*89c4ff92SAndroid Build Coastguard Worker 
QuantizedLstmEndToEnd(const std::vector<armnn::BackendId> & backends)181*89c4ff92SAndroid Build Coastguard Worker void QuantizedLstmEndToEnd(const std::vector<armnn::BackendId>& backends)
182*89c4ff92SAndroid Build Coastguard Worker {
183*89c4ff92SAndroid Build Coastguard Worker     std::vector<uint8_t> inputVector = {166, 179, 50, 150};
184*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo inputDesc({2, 2}, armnn::DataType::QAsymmU8);
185*89c4ff92SAndroid Build Coastguard Worker 
186*89c4ff92SAndroid Build Coastguard Worker     std::vector<int16_t> cellStateInVector = {876, 1034, 955, -909, 761, 1029, 796, -1036};
187*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo cellStateInDesc({2, 4}, armnn::DataType::QSymmS16);
188*89c4ff92SAndroid Build Coastguard Worker 
189*89c4ff92SAndroid Build Coastguard Worker     std::vector<uint8_t> outputStateInVector = {136, 150, 140, 115, 135, 152, 138, 112};
190*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo outputStateInDesc({2, 4}, armnn::DataType::QAsymmU8);
191*89c4ff92SAndroid Build Coastguard Worker 
192*89c4ff92SAndroid Build Coastguard Worker     std::vector<int16_t> cellStateOutVector = {1485, 1177, 1373, -1023, 1019, 1355, 1097, -1235};
193*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo cellStateOutVectorDesc({2, 4}, armnn::DataType::QSymmS16);
194*89c4ff92SAndroid Build Coastguard Worker 
195*89c4ff92SAndroid Build Coastguard Worker     std::vector<uint8_t> outputStateOutVector = {140, 151, 146, 112, 136, 156, 142, 112};
196*89c4ff92SAndroid Build Coastguard Worker     armnn::TensorInfo outputDesc({2, 4}, armnn::DataType::QAsymmU8);
197*89c4ff92SAndroid Build Coastguard Worker 
198*89c4ff92SAndroid Build Coastguard Worker     // Builds up the structure of the network
199*89c4ff92SAndroid Build Coastguard Worker     armnn::INetworkPtr net = CreateQuantizedLstmNetwork(inputDesc.GetShape(), outputDesc.GetShape());
200*89c4ff92SAndroid Build Coastguard Worker 
201*89c4ff92SAndroid Build Coastguard Worker     IRuntime::CreationOptions options;
202*89c4ff92SAndroid Build Coastguard Worker     IRuntimePtr runtime(IRuntime::Create(options));
203*89c4ff92SAndroid Build Coastguard Worker 
204*89c4ff92SAndroid Build Coastguard Worker     // optimize the network
205*89c4ff92SAndroid Build Coastguard Worker     IOptimizedNetworkPtr optNet = Optimize(*net, backends, runtime->GetDeviceSpec());
206*89c4ff92SAndroid Build Coastguard Worker 
207*89c4ff92SAndroid Build Coastguard Worker     // Loads it into the runtime.
208*89c4ff92SAndroid Build Coastguard Worker     NetworkId netId;
209*89c4ff92SAndroid Build Coastguard Worker     runtime->LoadNetwork(netId, std::move(optNet));
210*89c4ff92SAndroid Build Coastguard Worker 
211*89c4ff92SAndroid Build Coastguard Worker     InputTensors inputTensors;
212*89c4ff92SAndroid Build Coastguard Worker     inputTensors.reserve(3);
213*89c4ff92SAndroid Build Coastguard Worker 
214*89c4ff92SAndroid Build Coastguard Worker     // input
215*89c4ff92SAndroid Build Coastguard Worker     TensorInfo inputTensorInfo0 = runtime->GetInputTensorInfo(netId, 0);
216*89c4ff92SAndroid Build Coastguard Worker     TensorInfo inputTensorInfo1 = runtime->GetInputTensorInfo(netId, 1);
217*89c4ff92SAndroid Build Coastguard Worker     TensorInfo inputTensorInfo2 = runtime->GetInputTensorInfo(netId, 2);
218*89c4ff92SAndroid Build Coastguard Worker     inputTensorInfo0.SetConstant(true);
219*89c4ff92SAndroid Build Coastguard Worker     inputTensorInfo1.SetConstant(true);
220*89c4ff92SAndroid Build Coastguard Worker     inputTensorInfo2.SetConstant(true);
221*89c4ff92SAndroid Build Coastguard Worker 
222*89c4ff92SAndroid Build Coastguard Worker     inputTensors.push_back({0, ConstTensor(inputTensorInfo0, inputVector.data())});
223*89c4ff92SAndroid Build Coastguard Worker     inputTensors.push_back({1, ConstTensor(inputTensorInfo1, cellStateInVector.data())});
224*89c4ff92SAndroid Build Coastguard Worker     inputTensors.push_back({2, ConstTensor(inputTensorInfo2, outputStateInVector.data())});
225*89c4ff92SAndroid Build Coastguard Worker 
226*89c4ff92SAndroid Build Coastguard Worker     OutputTensors outputTensors;
227*89c4ff92SAndroid Build Coastguard Worker     outputTensors.reserve(2);
228*89c4ff92SAndroid Build Coastguard Worker 
229*89c4ff92SAndroid Build Coastguard Worker     //output
230*89c4ff92SAndroid Build Coastguard Worker     std::vector<int16_t> cellStateOutResult(cellStateOutVector.size());
231*89c4ff92SAndroid Build Coastguard Worker     std::vector<uint8_t> outputStateOutResult(outputStateOutVector.size());
232*89c4ff92SAndroid Build Coastguard Worker     outputTensors.push_back({0, Tensor(runtime->GetOutputTensorInfo(netId, 0), cellStateOutResult.data())});
233*89c4ff92SAndroid Build Coastguard Worker     outputTensors.push_back({1, Tensor(runtime->GetOutputTensorInfo(netId, 1), outputStateOutResult.data())});
234*89c4ff92SAndroid Build Coastguard Worker 
235*89c4ff92SAndroid Build Coastguard Worker     // Does the inference.
236*89c4ff92SAndroid Build Coastguard Worker     runtime->EnqueueWorkload(netId, inputTensors, outputTensors);
237*89c4ff92SAndroid Build Coastguard Worker 
238*89c4ff92SAndroid Build Coastguard Worker     // Checks the results
239*89c4ff92SAndroid Build Coastguard Worker     constexpr int16_t toleranceInt16 = 2;
240*89c4ff92SAndroid Build Coastguard Worker     for (unsigned int i = 0u; i < cellStateOutResult.size(); ++i)
241*89c4ff92SAndroid Build Coastguard Worker     {
242*89c4ff92SAndroid Build Coastguard Worker         CHECK(IsCloseEnough(cellStateOutVector[i], cellStateOutResult[i], toleranceInt16));
243*89c4ff92SAndroid Build Coastguard Worker     }
244*89c4ff92SAndroid Build Coastguard Worker 
245*89c4ff92SAndroid Build Coastguard Worker     constexpr uint8_t toleranceUint8 = 1;
246*89c4ff92SAndroid Build Coastguard Worker     for (unsigned int i = 0u; i < outputStateOutResult.size(); ++i)
247*89c4ff92SAndroid Build Coastguard Worker     {
248*89c4ff92SAndroid Build Coastguard Worker         CHECK(IsCloseEnough(outputStateOutVector[i], outputStateOutResult[i], toleranceUint8));
249*89c4ff92SAndroid Build Coastguard Worker     }
250*89c4ff92SAndroid Build Coastguard Worker }
251