diff options
-rw-r--r-- | 1.2/ArmnnDriverImpl.cpp | 2 | ||||
-rw-r--r-- | 1.2/HalPolicy.cpp | 429 | ||||
-rw-r--r-- | 1.2/HalPolicy.hpp | 2 | ||||
-rw-r--r-- | test/1.0/Lstm.cpp | 34 | ||||
-rw-r--r-- | test/1.1/Lstm.cpp | 34 | ||||
-rw-r--r-- | test/1.2/Lstm.cpp | 44 | ||||
-rw-r--r-- | test/Android.mk | 9 | ||||
-rw-r--r-- | test/DriverTestHelpers.cpp | 46 | ||||
-rw-r--r-- | test/DriverTestHelpers.hpp | 48 | ||||
-rw-r--r-- | test/Lstm.hpp (renamed from test/Lstm.cpp) | 848 |
10 files changed, 1339 insertions, 157 deletions
diff --git a/1.2/ArmnnDriverImpl.cpp b/1.2/ArmnnDriverImpl.cpp index 82eacde8..8a444e5d 100644 --- a/1.2/ArmnnDriverImpl.cpp +++ b/1.2/ArmnnDriverImpl.cpp @@ -49,7 +49,7 @@ void NotifyCallbackAndCheck(const sp<V1_2::IPreparedModelCallback>& callback, ErrorStatus errorStatus, const sp<V1_2::IPreparedModel>& preparedModelPtr) { - Return<void> returned = callback->notify(errorStatus, preparedModelPtr); + Return<void> returned = callback->notify_1_2(errorStatus, preparedModelPtr); // This check is required, if the callback fails and it isn't checked it will bring down the service if (!returned.isOk()) { diff --git a/1.2/HalPolicy.cpp b/1.2/HalPolicy.cpp index 9cad29fa..8dbfd897 100644 --- a/1.2/HalPolicy.cpp +++ b/1.2/HalPolicy.cpp @@ -36,7 +36,6 @@ bool HandledByV1_0(V1_2::OperationType operationType) case V1_0::OperationType::LOCAL_RESPONSE_NORMALIZATION: case V1_0::OperationType::LOGISTIC: case V1_0::OperationType::LSH_PROJECTION: - case V1_0::OperationType::LSTM: case V1_0::OperationType::MUL: case V1_0::OperationType::RESHAPE: case V1_0::OperationType::RNN: @@ -164,6 +163,8 @@ bool HalPolicy::ConvertOperation(const Operation& operation, const Model& model, return ConvertSpaceToDepth(operation, model, data); case V1_2::OperationType::TANH: return ConvertTanH(operation, model, data); + case V1_2::OperationType::LSTM: + return ConvertLstm(operation, model, data); default: return Fail("%s: Operation type %s not supported in ArmnnDriver", __func__, toString(operation.type).c_str()); @@ -1008,5 +1009,431 @@ bool HalPolicy::ConvertTanH(const Operation& operation, const Model& model, Conv return ::ConvertTanH<hal_1_2::HalPolicy>(operation, model, data); } +bool HalPolicy::ConvertLstm(const Operation& operation, const Model& model, ConversionData& data) +{ + // Inputs: + // 00: The input: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, input_size], where + // “batch_size” corresponds to the batching dimension, and “input_size” is the size of the input. + LayerInputHandle input = ConvertToLayerInputHandle<hal_1_2::HalPolicy>(operation, 0, model, data); + if (!input.IsValid()) + { + return Fail("%s: Could not read input 0: input", __func__); + } + // 18: The output state: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. + LayerInputHandle outputStateIn = ConvertToLayerInputHandle<hal_1_2::HalPolicy>(operation, 18, model, data); + if (!outputStateIn.IsValid()) + { + return Fail("%s: Could not read input 18: outputStateIn", __func__); + } + // 19: The cell state: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units]. + LayerInputHandle cellStateIn = ConvertToLayerInputHandle<hal_1_2::HalPolicy>(operation, 19, model, data); + if (!cellStateIn.IsValid()) + { + return Fail("%s: Could not read input 19: cellStateIn", __func__); + } + + // Get the mandatory input tensors: + // 02: The input-to-forget weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size]. + const ConstTensorPin inputToForgetWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 2, model, data); + // 03: The input-to-cell weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size]. + const ConstTensorPin inputToCellWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 3, model, data); + // 04: The input-to-output weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size]. + const ConstTensorPin inputToOutputWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 4, model, data); + // 06: The recurrent-to-forget weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + const ConstTensorPin recurrentToForgetWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 6, model, data); + // 07: The recurrent-to-cell weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + const ConstTensorPin recurrentToCellWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 7, model, data); + // 08: The recurrent-to-output weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + const ConstTensorPin recurrentToOutputWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 8, model, data); + // 13: The forget gate bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + const ConstTensorPin forgetGateBiasPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 13, model, data); + // 14: The cell bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + const ConstTensorPin cellBiasPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 14, model, data); + // 15: The output gate bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + const ConstTensorPin outputGateBiasPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, 15, model, data); + + if (!inputToForgetWeightsPin.IsValid() || + !inputToCellWeightsPin.IsValid() || + !inputToOutputWeightsPin.IsValid() || + !recurrentToForgetWeightsPin.IsValid() || + !recurrentToCellWeightsPin.IsValid() || + !recurrentToOutputWeightsPin.IsValid() || + !forgetGateBiasPin.IsValid() || + !cellBiasPin.IsValid() || + !outputGateBiasPin.IsValid()) + { + return Fail("%s: Operation has invalid tensor inputs", __func__); + } + + // Get the optional input tensors: + // 01: The input-to-input weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size], where “num_units” corresponds to the number of cell units. + const ConstTensorPin inputToInputWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 1, + model, + data, + g_DontPermute, + nullptr, + true); + + // 05: The recurrent-to-input weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size], where “output_size” corresponds to either the number of cell units (i.e., + // “num_units”), or the second dimension of the “projection_weights”, if defined. + const ConstTensorPin recurrentToInputWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 5, + model, + data, + g_DontPermute, + nullptr, + true); + + // 09: The cell-to-input weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + const ConstTensorPin cellToInputWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 9, + model, + data, + g_DontPermute, + nullptr, + true); + + // 10: The cell-to-forget weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + const ConstTensorPin cellToForgetWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 10, + model, + data, + g_DontPermute, + nullptr, + true); + + // 11: The cell-to-output weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + const ConstTensorPin cellToOutputWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 11, + model, + data, + g_DontPermute, + nullptr, + true); + + // 12: The input gate bias: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + const ConstTensorPin inputGateBiasPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 12, + model, + data, + g_DontPermute, + nullptr, + true); + + // 16: The projection weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [output_size, num_units]. + const ConstTensorPin projectionWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 16, + model, + data, + g_DontPermute, + nullptr, + true); + + // 17: The projection bias: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [output_size]. + const ConstTensorPin projectionBiasPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 17, + model, + data, + g_DontPermute, + nullptr, + true); + + if ((!inputToInputWeightsPin.IsValid() && !inputToInputWeightsPin.IsOptional()) || + (!recurrentToInputWeightsPin.IsValid() && !recurrentToInputWeightsPin.IsOptional()) || + (!cellToInputWeightsPin.IsValid() && !cellToInputWeightsPin.IsOptional()) || + (!cellToForgetWeightsPin.IsValid() && !cellToForgetWeightsPin.IsOptional()) || + (!cellToOutputWeightsPin.IsValid() && !cellToOutputWeightsPin.IsOptional()) || + (!inputGateBiasPin.IsValid() && !inputGateBiasPin.IsOptional()) || + (!projectionWeightsPin.IsValid() && !projectionWeightsPin.IsOptional()) || + (!projectionBiasPin.IsValid() && !projectionBiasPin.IsOptional())) + { + return Fail("%s: Operation has invalid tensor inputs", __func__); + } + + // Get the mandatory input scalars (actually 1-D tensors of size 1): + // 20: The activation function: A value indicating the activation function: + // 0: None; 1: Relu; 3: Relu6; 4: Tanh; 6: Sigmoid. + // 21: The clipping threshold: for the cell state, such that values are bound within [-cell_clip, cell_clip]. + // If set to 0.0 then clipping is disabled. + // 22: The clipping threshold: for the output from the projection layer, such that values are bound within + // [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled. + ActivationFn activation; + float cellClip; + float projClip; + if (!GetInputActivationFunctionFromTensor<hal_1_2::HalPolicy>(operation, 20, activation, model, data) || + !GetInputScalar<hal_1_2::HalPolicy>(operation, 21, OperandType::FLOAT32, cellClip, model, data) || + !GetInputScalar<hal_1_2::HalPolicy>(operation, 22, OperandType::FLOAT32, projClip, model, data)) + { + return Fail("%s: Operation has invalid scalar inputs", __func__); + } + + // Get the normalization tensors + // 23: The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + const ConstTensorPin inputLayerNormWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 23, + model, + data, + g_DontPermute, + nullptr, + true); + + // 24: The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + const ConstTensorPin forgetLayerNormWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 24, + model, + data, + g_DontPermute, + nullptr, + true); + + // 25: The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + const ConstTensorPin cellLayerNormWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 25, + model, + data, + g_DontPermute, + nullptr, + true); + + // 26: The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + const ConstTensorPin outputLayerNormWeightsPin = + ConvertOperationInputToConstTensorPin<hal_1_2::HalPolicy>(operation, + 26, + model, + data, + g_DontPermute, + nullptr, + true); + + // Outputs: + // 00: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] + // with CIFG, or [batch_size, num_units * 3] without CIFG. + const Operand* scratchBuffer = GetOutputOperand<hal_1_2::HalPolicy>(operation, 0, model); + if (!scratchBuffer) + { + return Fail("%s: Could not read output 0: scratchBuffer", __func__); + } + // 01: The output state (out): A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. + const Operand* outputStateOut = GetOutputOperand<hal_1_2::HalPolicy>(operation, 1, model); + if (!outputStateOut) + { + return Fail("%s: Could not read output 1: outputStateOut", __func__); + } + // 02: The cell state (out): A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units]. + const Operand* cellStateOut = GetOutputOperand<hal_1_2::HalPolicy>(operation, 2, model); + if (!cellStateOut) + { + return Fail("%s: Could not read output 2: cellStateOut", __func__); + } + // 03: The output: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. This is + // effectively the same as the current “output state (out)” value. + const Operand* output = GetOutputOperand<hal_1_2::HalPolicy>(operation, 3, model); + if (!output) + { + return Fail("%s: Could not read output 3: output", __func__); + } + + // set the params structure for the AddLstmLayer call + armnn::LstmInputParams params; + params.m_InputToInputWeights = inputToInputWeightsPin.GetConstTensorPtr(); + params.m_InputToForgetWeights = inputToForgetWeightsPin.GetConstTensorPtr(); + params.m_InputToCellWeights = inputToCellWeightsPin.GetConstTensorPtr(); + params.m_InputToOutputWeights = inputToOutputWeightsPin.GetConstTensorPtr(); + params.m_RecurrentToInputWeights = recurrentToInputWeightsPin.GetConstTensorPtr(); + params.m_RecurrentToForgetWeights = recurrentToForgetWeightsPin.GetConstTensorPtr(); + params.m_RecurrentToCellWeights = recurrentToCellWeightsPin.GetConstTensorPtr(); + params.m_RecurrentToOutputWeights = recurrentToOutputWeightsPin.GetConstTensorPtr(); + params.m_CellToInputWeights = cellToInputWeightsPin.GetConstTensorPtr(); + params.m_CellToForgetWeights = cellToForgetWeightsPin.GetConstTensorPtr(); + params.m_CellToOutputWeights = cellToOutputWeightsPin.GetConstTensorPtr(); + params.m_InputGateBias = inputGateBiasPin.GetConstTensorPtr(); + params.m_ForgetGateBias = forgetGateBiasPin.GetConstTensorPtr(); + params.m_CellBias = cellBiasPin.GetConstTensorPtr(); + params.m_OutputGateBias = outputGateBiasPin.GetConstTensorPtr(); + params.m_ProjectionWeights = projectionWeightsPin.GetConstTensorPtr(); + params.m_ProjectionBias = projectionBiasPin.GetConstTensorPtr(); + params.m_InputLayerNormWeights = inputLayerNormWeightsPin.GetConstTensorPtr(); + params.m_ForgetLayerNormWeights = forgetLayerNormWeightsPin.GetConstTensorPtr(); + params.m_CellLayerNormWeights = cellLayerNormWeightsPin.GetConstTensorPtr(); + params.m_OutputLayerNormWeights = outputLayerNormWeightsPin.GetConstTensorPtr(); + + // set the layer descriptor + armnn::LstmDescriptor desc; + desc.m_ActivationFunc = activation; + desc.m_ClippingThresCell = cellClip; + desc.m_ClippingThresProj = projClip; + desc.m_CifgEnabled = (params.m_InputToInputWeights == nullptr || + params.m_RecurrentToInputWeights == nullptr || + params.m_InputGateBias == nullptr); + desc.m_PeepholeEnabled = (params.m_CellToForgetWeights != nullptr || + params.m_CellToOutputWeights != nullptr); + desc.m_ProjectionEnabled = (params.m_ProjectionWeights != nullptr); + desc.m_LayerNormEnabled = (params.m_InputLayerNormWeights != nullptr || + params.m_ForgetLayerNormWeights != nullptr || + params.m_CellLayerNormWeights != nullptr || + params.m_OutputLayerNormWeights != nullptr); + + // validate the optional input groups + if (desc.m_CifgEnabled && + (params.m_InputToInputWeights != nullptr || + params.m_RecurrentToInputWeights != nullptr || + params.m_InputGateBias != nullptr)) + { + return Fail("%s: All, or none, of input-to-input weights, recurrent-to-input weights," + " and input gate bias must be provided", __func__); + } + + if (!desc.m_ProjectionEnabled && params.m_ProjectionBias != nullptr) + { + return Fail("%s: projection bias should not be provided without projection weights", __func__); + } + + if (desc.m_PeepholeEnabled && + (params.m_CellToForgetWeights == nullptr || + params.m_CellToOutputWeights == nullptr || + (!desc.m_CifgEnabled && params.m_CellToInputWeights == nullptr))) + { + return Fail("%s: All, or none, of cell-to-forget weights and cell-to-output weights must be provided" + " and, if CIFG is not enabled, cell-to-input weights must also be provided", __func__); + } + + if (desc.m_LayerNormEnabled && + (params.m_ForgetLayerNormWeights == nullptr || + params.m_CellLayerNormWeights == nullptr || + params.m_OutputLayerNormWeights == nullptr || + (!desc.m_CifgEnabled && params.m_InputLayerNormWeights == nullptr))) + { + return Fail("%s: All, or none, of forget-norm weights, cell-norm weights and output-norm weights must be" + " provided and, if CIFG is not enabled, input-norm weights must also be provided", __func__); + } + + // Check if the layer is supported + // Inputs + const armnn::TensorInfo& inputInfo = input.GetTensorInfo(); + const armnn::TensorInfo& outputStateInInfo = outputStateIn.GetTensorInfo(); + const armnn::TensorInfo& cellStateInInfo = cellStateIn.GetTensorInfo(); + + // Outputs + const armnn::TensorInfo& scratchBufferInfo = GetTensorInfoForOperand(*scratchBuffer); + const armnn::TensorInfo& outputStateOutInfo = GetTensorInfoForOperand(*outputStateOut); + const armnn::TensorInfo& cellStateOutInfo = GetTensorInfoForOperand(*cellStateOut); + const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output); + + // Basic parameters + armnn::LstmInputParamsInfo paramsInfo; + paramsInfo.m_InputToForgetWeights = &(params.m_InputToForgetWeights->GetInfo()); + paramsInfo.m_InputToCellWeights = &(params.m_InputToCellWeights->GetInfo()); + paramsInfo.m_InputToOutputWeights = &(params.m_InputToOutputWeights->GetInfo()); + paramsInfo.m_RecurrentToForgetWeights = &(params.m_RecurrentToForgetWeights->GetInfo()); + paramsInfo.m_RecurrentToCellWeights = &(params.m_RecurrentToCellWeights->GetInfo()); + paramsInfo.m_RecurrentToOutputWeights = &(params.m_RecurrentToOutputWeights->GetInfo()); + paramsInfo.m_ForgetGateBias = &(params.m_ForgetGateBias->GetInfo()); + paramsInfo.m_CellBias = &(params.m_CellBias->GetInfo()); + paramsInfo.m_OutputGateBias = &(params.m_OutputGateBias->GetInfo()); + + // Optional parameters + if(!desc.m_CifgEnabled) + { + paramsInfo.m_InputToInputWeights = &(params.m_InputToInputWeights->GetInfo()); + paramsInfo.m_RecurrentToInputWeights = &(params.m_RecurrentToInputWeights->GetInfo()); + if (params.m_CellToInputWeights != nullptr) + { + paramsInfo.m_CellToInputWeights = &(params.m_CellToInputWeights->GetInfo()); + } + paramsInfo.m_InputGateBias = &(params.m_InputGateBias->GetInfo()); + } + + if(desc.m_ProjectionEnabled) + { + paramsInfo.m_ProjectionWeights = &(params.m_ProjectionWeights->GetInfo()); + if (params.m_ProjectionBias != nullptr) + { + paramsInfo.m_ProjectionBias = &(params.m_ProjectionBias->GetInfo()); + } + } + + if(desc.m_PeepholeEnabled) + { + paramsInfo.m_CellToForgetWeights = &(params.m_CellToForgetWeights->GetInfo()); + paramsInfo.m_CellToOutputWeights = &(params.m_CellToOutputWeights->GetInfo()); + } + + if (desc.m_LayerNormEnabled) + { + if(!desc.m_CifgEnabled) + { + paramsInfo.m_InputLayerNormWeights = &(params.m_InputLayerNormWeights->GetInfo()); + } + paramsInfo.m_ForgetLayerNormWeights = &(params.m_ForgetLayerNormWeights->GetInfo()); + paramsInfo.m_CellLayerNormWeights = &(params.m_CellLayerNormWeights->GetInfo()); + paramsInfo.m_OutputLayerNormWeights = &(params.m_OutputLayerNormWeights->GetInfo()); + } + + bool isSupported = false; + FORWARD_LAYER_SUPPORT_FUNC(__func__, + IsLstmSupported, + data.m_Backends, + isSupported, + inputInfo, + outputStateInInfo, + cellStateInInfo, + scratchBufferInfo, + outputStateOutInfo, + cellStateOutInfo, + outputInfo, + desc, + paramsInfo); + if (!isSupported) + { + return false; + } + + // Add the layer + armnn::IConnectableLayer* layer = data.m_Network->AddLstmLayer(desc, params, "Lstm"); + + input.Connect(layer->GetInputSlot(0)); + outputStateIn.Connect(layer->GetInputSlot(1)); + cellStateIn.Connect(layer->GetInputSlot(2)); + + return (SetupAndTrackLayerOutputSlot<hal_1_2::HalPolicy>(operation, 0, *layer, 0, model, data) && + SetupAndTrackLayerOutputSlot<hal_1_2::HalPolicy>(operation, 1, *layer, 1, model, data) && + SetupAndTrackLayerOutputSlot<hal_1_2::HalPolicy>(operation, 2, *layer, 2, model, data) && + SetupAndTrackLayerOutputSlot<hal_1_2::HalPolicy>(operation, 3, *layer, 3, model, data)); +} + } // namespace hal_1_2 } // namespace armnn_driver diff --git a/1.2/HalPolicy.hpp b/1.2/HalPolicy.hpp index f689613f..74683136 100644 --- a/1.2/HalPolicy.hpp +++ b/1.2/HalPolicy.hpp @@ -67,6 +67,8 @@ private: static bool ConvertSpaceToDepth(const Operation& operation, const Model& model, ConversionData& data); static bool ConvertTanH(const Operation& operation, const Model& model, ConversionData& data); + + static bool ConvertLstm(const Operation& operation, const Model& model, ConversionData& data); }; } // namespace hal_1_2 diff --git a/test/1.0/Lstm.cpp b/test/1.0/Lstm.cpp new file mode 100644 index 00000000..5f0a209d --- /dev/null +++ b/test/1.0/Lstm.cpp @@ -0,0 +1,34 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "../Lstm.hpp" + +#include <boost/test/data/test_case.hpp> + +BOOST_AUTO_TEST_SUITE(LstmTests) + +using namespace armnn_driver; + +BOOST_DATA_TEST_CASE(LstmNoCifgNoPeepholeNoProjectionTest, COMPUTE_DEVICES) +{ + LstmNoCifgNoPeepholeNoProjection<hal_1_0::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionTest, COMPUTE_DEVICES) +{ + LstmCifgPeepholeNoProjection<hal_1_0::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmNoCifgPeepholeProjectionTest, COMPUTE_DEVICES) +{ + LstmNoCifgPeepholeProjection<hal_1_0::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionBatch2Test, COMPUTE_DEVICES) +{ + LstmCifgPeepholeNoProjectionBatch2<hal_1_0::HalPolicy>(sample); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/1.1/Lstm.cpp b/test/1.1/Lstm.cpp new file mode 100644 index 00000000..703597e5 --- /dev/null +++ b/test/1.1/Lstm.cpp @@ -0,0 +1,34 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "../Lstm.hpp" + +#include <boost/test/data/test_case.hpp> + +BOOST_AUTO_TEST_SUITE(LstmTests) + +using namespace armnn_driver; + +BOOST_DATA_TEST_CASE(LstmNoCifgNoPeepholeNoProjectionTest, COMPUTE_DEVICES) +{ + LstmNoCifgNoPeepholeNoProjection<hal_1_1::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionTest, COMPUTE_DEVICES) +{ + LstmCifgPeepholeNoProjection<hal_1_1::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmNoCifgPeepholeProjectionTest, COMPUTE_DEVICES) +{ + LstmNoCifgPeepholeProjection<hal_1_1::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionBatch2Test, COMPUTE_DEVICES) +{ + LstmCifgPeepholeNoProjectionBatch2<hal_1_1::HalPolicy>(sample); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/1.2/Lstm.cpp b/test/1.2/Lstm.cpp new file mode 100644 index 00000000..a76b7610 --- /dev/null +++ b/test/1.2/Lstm.cpp @@ -0,0 +1,44 @@ +// +// Copyright © 2017 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "../Lstm.hpp" + +#include <boost/test/data/test_case.hpp> + +BOOST_AUTO_TEST_SUITE(LstmTests) + +using namespace armnn_driver; + +BOOST_DATA_TEST_CASE(LstmNoCifgNoPeepholeNoProjectionTest, COMPUTE_DEVICES) +{ + LstmNoCifgNoPeepholeNoProjection<hal_1_2::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionTest, COMPUTE_DEVICES) +{ + LstmCifgPeepholeNoProjection<hal_1_2::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmNoCifgPeepholeProjectionTest, COMPUTE_DEVICES) +{ + LstmNoCifgPeepholeProjection<hal_1_2::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionBatch2Test, COMPUTE_DEVICES) +{ + LstmCifgPeepholeNoProjectionBatch2<hal_1_2::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmNoCifgPeepholeProjectionNoClippingLayerNormTest, COMPUTE_DEVICES) +{ + LstmNoCifgPeepholeProjectionNoClippingLayerNorm<hal_1_2::HalPolicy>(sample); +} + +BOOST_DATA_TEST_CASE(LstmCifgPeepholeProjectionNoClippingLayerNormTest, COMPUTE_DEVICES) +{ + LstmCifgPeepholeProjectionNoClippingLayerNorm<hal_1_2::HalPolicy>(sample); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/Android.mk b/test/Android.mk index a078e0a3..2f0e03ec 100644 --- a/test/Android.mk +++ b/test/Android.mk @@ -57,6 +57,7 @@ endif # PLATFORM_VERSION == Q or later LOCAL_SRC_FILES := \ 1.0/Convolution2D.cpp \ 1.0/FullyConnectedReshape.cpp \ + 1.0/Lstm.cpp \ Tests.cpp \ UtilsTests.cpp \ Concurrent.cpp \ @@ -64,7 +65,6 @@ LOCAL_SRC_FILES := \ GenericLayerTests.cpp \ DriverTestHelpers.cpp \ SystemProperties.cpp \ - Lstm.cpp \ Concat.cpp \ TestTensor.cpp @@ -160,6 +160,8 @@ LOCAL_SRC_FILES := \ 1.1/Convolution2D.cpp \ 1.1/Mean.cpp \ 1.1/Transpose.cpp \ + 1.0/Lstm.cpp \ + 1.1/Lstm.cpp \ Tests.cpp \ UtilsTests.cpp \ Concurrent.cpp \ @@ -167,7 +169,6 @@ LOCAL_SRC_FILES := \ GenericLayerTests.cpp \ DriverTestHelpers.cpp \ SystemProperties.cpp \ - Lstm.cpp \ Concat.cpp \ TestTensor.cpp @@ -257,6 +258,9 @@ LOCAL_SRC_FILES := \ 1.1/Transpose.cpp \ 1.2/Dilation.cpp \ 1.2/Capabilities.cpp \ + 1.0/Lstm.cpp \ + 1.1/Lstm.cpp \ + 1.2/Lstm.cpp \ Tests.cpp \ UtilsTests.cpp \ Concurrent.cpp \ @@ -264,7 +268,6 @@ LOCAL_SRC_FILES := \ GenericLayerTests.cpp \ DriverTestHelpers.cpp \ SystemProperties.cpp \ - Lstm.cpp \ Concat.cpp \ TestTensor.cpp diff --git a/test/DriverTestHelpers.cpp b/test/DriverTestHelpers.cpp index 675757f0..4c26174b 100644 --- a/test/DriverTestHelpers.cpp +++ b/test/DriverTestHelpers.cpp @@ -61,6 +61,26 @@ Return<void> PreparedModelCallback::notify(ErrorStatus status, return Void(); } +#ifdef ARMNN_ANDROID_NN_V1_2 + +Return<void> PreparedModelCallback_1_2::notify(ErrorStatus status, + const android::sp<V1_0::IPreparedModel>& preparedModel) +{ + m_ErrorStatus = status; + m_PreparedModel = preparedModel; + return Void(); +} + +Return<void> PreparedModelCallback_1_2::notify_1_2(ErrorStatus status, + const android::sp<V1_2::IPreparedModel>& preparedModel) +{ + m_ErrorStatus = status; + m_PreparedModel_1_2 = preparedModel; + return Void(); +} + +#endif + // lifted from common/Utils.cpp hidl_memory allocateSharedMemory(int64_t size) { @@ -147,6 +167,32 @@ android::sp<V1_0::IPreparedModel> PrepareModelWithStatus(const V1_1::Model& mode #endif +#ifdef ARMNN_ANDROID_NN_V1_2 + +android::sp<V1_2::IPreparedModel> PrepareModelWithStatus_1_2(const armnn_driver::hal_1_2::HalPolicy::Model& model, + armnn_driver::ArmnnDriver& driver, + ErrorStatus& prepareStatus, + ErrorStatus expectedStatus) +{ + android::sp<PreparedModelCallback_1_2> cb(new PreparedModelCallback_1_2()); + + android::hardware::hidl_vec<android::hardware::hidl_handle> emptyHandle1; + android::hardware::hidl_vec<android::hardware::hidl_handle> emptyHandle2; + armnn_driver::ArmnnDriver::HidlToken emptyToken; + + driver.prepareModel_1_2(model, V1_1::ExecutionPreference::LOW_POWER, emptyHandle1, emptyHandle2, emptyToken, cb); + + prepareStatus = cb->GetErrorStatus(); + BOOST_TEST(prepareStatus == expectedStatus); + if (expectedStatus == ErrorStatus::NONE) + { + BOOST_TEST((cb->GetPreparedModel_1_2() != nullptr)); + } + return cb->GetPreparedModel_1_2(); +} + +#endif + ErrorStatus Execute(android::sp<V1_0::IPreparedModel> preparedModel, const Request& request, ErrorStatus expectedStatus) diff --git a/test/DriverTestHelpers.hpp b/test/DriverTestHelpers.hpp index 980b3a72..c6f3f1fe 100644 --- a/test/DriverTestHelpers.hpp +++ b/test/DriverTestHelpers.hpp @@ -67,6 +67,36 @@ private: android::sp<V1_0::IPreparedModel> m_PreparedModel; }; +#ifdef ARMNN_ANDROID_NN_V1_2 + +class PreparedModelCallback_1_2 : public V1_2::IPreparedModelCallback +{ +public: + PreparedModelCallback_1_2() + : m_ErrorStatus(ErrorStatus::NONE) + , m_PreparedModel() + , m_PreparedModel_1_2() + { } + ~PreparedModelCallback_1_2() override { } + + Return<void> notify(ErrorStatus status, const android::sp<V1_0::IPreparedModel>& preparedModel) override; + + Return<void> notify_1_2(ErrorStatus status, const android::sp<V1_2::IPreparedModel>& preparedModel) override; + + ErrorStatus GetErrorStatus() { return m_ErrorStatus; } + + android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; } + + android::sp<V1_2::IPreparedModel> GetPreparedModel_1_2() { return m_PreparedModel_1_2; } + +private: + ErrorStatus m_ErrorStatus; + android::sp<V1_0::IPreparedModel> m_PreparedModel; + android::sp<V1_2::IPreparedModel> m_PreparedModel_1_2; +}; + +#endif + hidl_memory allocateSharedMemory(int64_t size); android::sp<IMemory> AddPoolAndGetData(uint32_t size, Request& request); @@ -259,6 +289,24 @@ android::sp<V1_0::IPreparedModel> PrepareModel(const HalModel& model, return PrepareModelWithStatus(model, driver, prepareStatus); } +#ifdef ARMNN_ANDROID_NN_V1_2 + +android::sp<V1_2::IPreparedModel> PrepareModelWithStatus_1_2(const armnn_driver::hal_1_2::HalPolicy::Model& model, + armnn_driver::ArmnnDriver& driver, + ErrorStatus& prepareStatus, + ErrorStatus expectedStatus = ErrorStatus::NONE); + +template<typename HalModel> +android::sp<V1_2::IPreparedModel> PrepareModel_1_2(const HalModel& model, + armnn_driver::ArmnnDriver& driver) +{ + ErrorStatus prepareStatus = ErrorStatus::NONE; + return PrepareModelWithStatus_1_2(model, driver, prepareStatus); +} + +#endif + + ErrorStatus Execute(android::sp<V1_0::IPreparedModel> preparedModel, const Request& request, ErrorStatus expectedStatus = ErrorStatus::NONE); diff --git a/test/Lstm.cpp b/test/Lstm.hpp index 579524ca..3d9bf77f 100644 --- a/test/Lstm.cpp +++ b/test/Lstm.hpp @@ -2,24 +2,16 @@ // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // -#include "DriverTestHelpers.hpp" -#include "OperationsUtils.h" -#include "../1.0/HalPolicy.hpp" +#pragma once + +#include "DriverTestHelpers.hpp" #include <boost/array.hpp> -#include <boost/test/unit_test.hpp> -#include <boost/test/data/test_case.hpp> #include <boost/math/special_functions/relative_difference.hpp> -#include <log/log.h> - -#include <cmath> - -BOOST_AUTO_TEST_SUITE(LstmTests) using ArmnnDriver = armnn_driver::ArmnnDriver; using DriverOptions = armnn_driver::DriverOptions; -using HalPolicy = armnn_driver::hal_1_0::HalPolicy; using namespace driverTestHelpers; using namespace android::hardware; @@ -71,10 +63,43 @@ OperandLifeTime CreateNoValueLifeTime(const hidl_vec<uint32_t>& dimensions) } return OperandLifeTime::CONSTANT_COPY; } + +template<typename HalModel> +void ExecuteModel(const HalModel& model, armnn_driver::ArmnnDriver& driver, const Request& request) +{ + android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, driver); + if (preparedModel.get() != nullptr) + { + Execute(preparedModel, request); + } +} + +#ifdef ARMNN_ANDROID_NN_V1_2 + +template<> +void ExecuteModel<armnn_driver::hal_1_2::HalPolicy::Model>(const armnn_driver::hal_1_2::HalPolicy::Model& model, + armnn_driver::ArmnnDriver& driver, + const Request& request) +{ + android::sp<V1_2::IPreparedModel> preparedModel = PrepareModel_1_2(model, driver); + if (preparedModel.get() != nullptr) + { + Execute(preparedModel, request); + } +} + +#endif + } // anonymous namespace -// Add our own tests here since we fail the lstm tests which Google supplies (because of non-const weights) +#ifndef ARMCOMPUTECL_ENABLED +static const boost::array<armnn::Compute, 1> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef }}; +#else +static const boost::array<armnn::Compute, 2> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef, armnn::Compute::GpuAcc }}; +#endif +// Add our own tests here since we fail the lstm tests which Google supplies (because of non-const weights) +template <typename HalPolicy> void LstmTestImpl(const hidl_vec<uint32_t>& inputDimensions, const std::vector<float>& inputValue, const hidl_vec<uint32_t>& inputToInputWeightsDimensions, @@ -121,6 +146,14 @@ void LstmTestImpl(const hidl_vec<uint32_t>& inputDimensions, const std::vector<float>& cellClippingThresholdValue, const hidl_vec<uint32_t>& projectionClippingThresholdDimensions, const std::vector<float>& projectionClippingThresholdValue, + const hidl_vec<uint32_t>& inputLayerNormWeightsDimensions, + const std::vector<float>& inputLayerNormWeightsValue, + const hidl_vec<uint32_t>& forgetLayerNormWeightsDimensions, + const std::vector<float>& forgetLayerNormWeightsValue, + const hidl_vec<uint32_t>& cellLayerNormWeightsDimensions, + const std::vector<float>& cellLayerNormWeightsValue, + const hidl_vec<uint32_t>& outputLayerNormWeightsDimensions, + const std::vector<float>& outputLayerNormWeightsValue, const hidl_vec<uint32_t>& scratchBufferDimensions, const std::vector<float>& scratchBufferValue, const hidl_vec<uint32_t>& outputStateOutDimensions, @@ -132,7 +165,8 @@ void LstmTestImpl(const hidl_vec<uint32_t>& inputDimensions, armnn::Compute compute) { auto driver = std::make_unique<ArmnnDriver>(DriverOptions(compute)); - HalPolicy::Model model = {}; + using Model = typename HalPolicy::Model; + Model model = {}; // Inputs: // 00: The input: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, input_size], where @@ -241,6 +275,47 @@ void LstmTestImpl(const hidl_vec<uint32_t>& inputDimensions, projectionClippingThresholdValue, HalPolicy::OperandType::FLOAT32); + bool normalizationEnabled = false; + + // If any of the tensors have a value all normalization tensors are set + if (!inputLayerNormWeightsValue.empty() || + !forgetLayerNormWeightsValue.empty() || + !cellLayerNormWeightsValue.empty() || + !outputLayerNormWeightsValue.empty()) + { + // Normalization: + // 23:The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + AddTensorOperand<HalPolicy>(model, + inputLayerNormWeightsDimensions, + inputLayerNormWeightsValue, + HalPolicy::OperandType::TENSOR_FLOAT32, + CreateNoValueLifeTime(inputLayerNormWeightsDimensions)); + // 24:The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + AddTensorOperand<HalPolicy>(model, + forgetLayerNormWeightsDimensions, + forgetLayerNormWeightsValue, + HalPolicy::OperandType::TENSOR_FLOAT32, + CreateNoValueLifeTime(forgetLayerNormWeightsDimensions)); + // 25:The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + AddTensorOperand<HalPolicy>(model, + cellLayerNormWeightsDimensions, + cellLayerNormWeightsValue, + HalPolicy::OperandType::TENSOR_FLOAT32, + CreateNoValueLifeTime(cellLayerNormWeightsDimensions)); + // 26:The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + AddTensorOperand<HalPolicy>(model, + outputLayerNormWeightsDimensions, + outputLayerNormWeightsValue, + HalPolicy::OperandType::TENSOR_FLOAT32, + CreateNoValueLifeTime(outputLayerNormWeightsDimensions)); + + normalizationEnabled = true; + } + // Outputs: // 0: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] with // CIFG, or [batch_size, num_units * 3] without CIFG. @@ -256,9 +331,19 @@ void LstmTestImpl(const hidl_vec<uint32_t>& inputDimensions, // make the lstm operation model.operations.resize(1); model.operations[0].type = HalPolicy::OperationType::LSTM; - model.operations[0].inputs = - hidl_vec<uint32_t> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}; - model.operations[0].outputs = hidl_vec<uint32_t> {23, 24, 25, 26}; + + if (normalizationEnabled) + { + model.operations[0].inputs = hidl_vec<uint32_t> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; + model.operations[0].outputs = hidl_vec<uint32_t> {27, 28, 29, 30}; + } + else + { + model.operations[0].inputs = hidl_vec<uint32_t> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22}; + model.operations[0].outputs = hidl_vec<uint32_t> {23, 24, 25, 26}; + } // define the input values hidl_vec<RequestArgument> inputArguments; @@ -296,11 +381,7 @@ void LstmTestImpl(const hidl_vec<uint32_t>& inputDimensions, float* outputData = static_cast<float*>(static_cast<void*>(outputMemory->getPointer())); // make the prepared model and run the execution - android::sp<V1_0::IPreparedModel> preparedModel = PrepareModel(model, *driver); - if (preparedModel.get() != nullptr) - { - Execute(preparedModel, request); - } + ExecuteModel(model, *driver, request); // check the results for (size_t i = 0; i < outputStateOutValue.size(); ++i) @@ -320,6 +401,7 @@ void LstmTestImpl(const hidl_vec<uint32_t>& inputDimensions, } } +template <typename HalPolicy> void LstmNoCifgNoPeepholeNoProjection(armnn::Compute compute) { // This replicates android/frameworks/ml/nn/runtime/test/generated/vts_models/lstm.model.cpp @@ -443,6 +525,24 @@ void LstmNoCifgNoPeepholeNoProjection(armnn::Compute compute) hidl_vec<uint32_t> projectionClippingThresholdDimensions{}; std::vector<float> projectionClippingThresholdValue{0.0f}; + // Normalization: + // 23:The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + hidl_vec<uint32_t> inputLayerNormWeightsDimensions{0}; + std::vector<float> inputLayerNormWeightsValue; + // 24:The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + hidl_vec<uint32_t> forgetLayerNormWeightsDimensions{0}; + std::vector<float> forgetLayerNormWeightsValue; + // 25:The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + hidl_vec<uint32_t> cellLayerNormWeightsDimensions{0}; + std::vector<float> cellLayerNormWeightsValue; + // 26:The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + hidl_vec<uint32_t> outputLayerNormWeightsDimensions{0}; + std::vector<float> outputLayerNormWeightsValue; + // Outputs: // 0: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] with // CIFG, or [batch_size, num_units * 3] without CIFG. @@ -463,36 +563,41 @@ void LstmNoCifgNoPeepholeNoProjection(armnn::Compute compute) hidl_vec<uint32_t> outputDimensions{batchSize, outputSize}; std::vector<float> outputValue {-0.02973187f, 0.1229473f, 0.20885126f, -0.15358765f}; - LstmTestImpl(inputDimensions, inputValue, - inputToInputWeightsDimensions, inputToInputWeightsValue, - inputToForgetWeightsDimensions, inputToForgetWeightsValue, - inputToCellWeightsDimensions, inputToCellWeightsValue, - inputToOutputWeightsDimensions, inputToOutputWeightsValue, - recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, - recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, - recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, - recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, - cellToInputWeightsDimensions, cellToInputWeightsValue, - cellToForgetWeightsDimensions, cellToForgetWeightsValue, - cellToOutputWeightsDimensions, cellToOutputWeightsValue, - inputGateBiasDimensions, inputGateBiasValue, - forgetGateBiasDimensions, forgetGateBiasValue, - cellBiasDimensions, cellBiasValue, - outputGateBiasDimensions, outputGateBiasValue, - projectionWeightsDimensions, projectionWeightsValue, - projectionBiasDimensions, projectionBiasValue, - outputStateInDimensions, outputStateInValue, - cellStateInDimensions, cellStateInValue, - activationFunctionDimensions, activationFunctionValue, - cellClippingThresholdDimensions, cellClippingThresholdValue, - projectionClippingThresholdDimensions, projectionClippingThresholdValue, - scratchBufferDimensions, scratchBufferValue, - outputStateOutDimensions, outputStateOutValue, - cellStateOutDimensions, cellStateOutValue, - outputDimensions, outputValue, - compute); + LstmTestImpl<HalPolicy>(inputDimensions, inputValue, + inputToInputWeightsDimensions, inputToInputWeightsValue, + inputToForgetWeightsDimensions, inputToForgetWeightsValue, + inputToCellWeightsDimensions, inputToCellWeightsValue, + inputToOutputWeightsDimensions, inputToOutputWeightsValue, + recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, + recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, + recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, + recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, + cellToInputWeightsDimensions, cellToInputWeightsValue, + cellToForgetWeightsDimensions, cellToForgetWeightsValue, + cellToOutputWeightsDimensions, cellToOutputWeightsValue, + inputGateBiasDimensions, inputGateBiasValue, + forgetGateBiasDimensions, forgetGateBiasValue, + cellBiasDimensions, cellBiasValue, + outputGateBiasDimensions, outputGateBiasValue, + projectionWeightsDimensions, projectionWeightsValue, + projectionBiasDimensions, projectionBiasValue, + outputStateInDimensions, outputStateInValue, + cellStateInDimensions, cellStateInValue, + activationFunctionDimensions, activationFunctionValue, + cellClippingThresholdDimensions, cellClippingThresholdValue, + projectionClippingThresholdDimensions, projectionClippingThresholdValue, + inputLayerNormWeightsDimensions, inputLayerNormWeightsValue, + forgetLayerNormWeightsDimensions, forgetLayerNormWeightsValue, + cellLayerNormWeightsDimensions, cellLayerNormWeightsValue, + outputLayerNormWeightsDimensions, outputLayerNormWeightsValue, + scratchBufferDimensions, scratchBufferValue, + outputStateOutDimensions, outputStateOutValue, + cellStateOutDimensions, cellStateOutValue, + outputDimensions, outputValue, + compute); } +template <typename HalPolicy> void LstmCifgPeepholeNoProjection(armnn::Compute compute) { // This replicates android/frameworks/ml/nn/runtime/test/generated/vts_models/lstm2.model.cpp @@ -610,6 +715,24 @@ void LstmCifgPeepholeNoProjection(armnn::Compute compute) hidl_vec<uint32_t> projectionClippingThresholdDimensions{}; std::vector<float> projectionClippingThresholdValue{0.0f}; + // Normalization: + // 23:The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + hidl_vec<uint32_t> inputLayerNormWeightsDimensions{0}; + std::vector<float> inputLayerNormWeightsValue; + // 24:The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + hidl_vec<uint32_t> forgetLayerNormWeightsDimensions{0}; + std::vector<float> forgetLayerNormWeightsValue; + // 25:The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + hidl_vec<uint32_t> cellLayerNormWeightsDimensions{0}; + std::vector<float> cellLayerNormWeightsValue; + // 26:The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + hidl_vec<uint32_t> outputLayerNormWeightsDimensions{0}; + std::vector<float> outputLayerNormWeightsValue; + // Outputs: // 0: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] with // CIFG, or [batch_size, num_units * 3] without CIFG. @@ -630,36 +753,41 @@ void LstmCifgPeepholeNoProjection(armnn::Compute compute) hidl_vec<uint32_t> outputDimensions{batchSize, outputSize}; std::vector<float> outputValue{-0.36444446f, -0.00352185f, 0.12886585f, -0.05163646f}; - LstmTestImpl(inputDimensions, inputValue, - inputToInputWeightsDimensions, inputToInputWeightsValue, - inputToForgetWeightsDimensions, inputToForgetWeightsValue, - inputToCellWeightsDimensions, inputToCellWeightsValue, - inputToOutputWeightsDimensions, inputToOutputWeightsValue, - recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, - recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, - recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, - recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, - cellToInputWeightsDimensions, cellToInputWeightsValue, - cellToForgetWeightsDimensions, cellToForgetWeightsValue, - cellToOutputWeightsDimensions, cellToOutputWeightsValue, - inputGateBiasDimensions, inputGateBiasValue, - forgetGateBiasDimensions, forgetGateBiasValue, - cellBiasDimensions, cellBiasValue, - outputGateBiasDimensions, outputGateBiasValue, - projectionWeightsDimensions, projectionWeightsValue, - projectionBiasDimensions, projectionBiasValue, - outputStateInDimensions, outputStateInValue, - cellStateInDimensions, cellStateInValue, - activationFunctionDimensions, activationFunctionValue, - cellClippingThresholdDimensions, cellClippingThresholdValue, - projectionClippingThresholdDimensions, projectionClippingThresholdValue, - scratchBufferDimensions, scratchBufferValue, - outputStateOutDimensions, outputStateOutValue, - cellStateOutDimensions, cellStateOutValue, - outputDimensions, outputValue, - compute); + LstmTestImpl<HalPolicy>(inputDimensions, inputValue, + inputToInputWeightsDimensions, inputToInputWeightsValue, + inputToForgetWeightsDimensions, inputToForgetWeightsValue, + inputToCellWeightsDimensions, inputToCellWeightsValue, + inputToOutputWeightsDimensions, inputToOutputWeightsValue, + recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, + recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, + recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, + recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, + cellToInputWeightsDimensions, cellToInputWeightsValue, + cellToForgetWeightsDimensions, cellToForgetWeightsValue, + cellToOutputWeightsDimensions, cellToOutputWeightsValue, + inputGateBiasDimensions, inputGateBiasValue, + forgetGateBiasDimensions, forgetGateBiasValue, + cellBiasDimensions, cellBiasValue, + outputGateBiasDimensions, outputGateBiasValue, + projectionWeightsDimensions, projectionWeightsValue, + projectionBiasDimensions, projectionBiasValue, + outputStateInDimensions, outputStateInValue, + cellStateInDimensions, cellStateInValue, + activationFunctionDimensions, activationFunctionValue, + cellClippingThresholdDimensions, cellClippingThresholdValue, + projectionClippingThresholdDimensions, projectionClippingThresholdValue, + inputLayerNormWeightsDimensions, inputLayerNormWeightsValue, + forgetLayerNormWeightsDimensions, forgetLayerNormWeightsValue, + cellLayerNormWeightsDimensions, cellLayerNormWeightsValue, + outputLayerNormWeightsDimensions, outputLayerNormWeightsValue, + scratchBufferDimensions, scratchBufferValue, + outputStateOutDimensions, outputStateOutValue, + cellStateOutDimensions, cellStateOutValue, + outputDimensions, outputValue, + compute); } +template <typename HalPolicy> void LstmNoCifgPeepholeProjection(armnn::Compute compute) { // This replicates android/frameworks/ml/nn/runtime/test/generated/vts_models/lstm3.model.cpp @@ -1284,6 +1412,24 @@ void LstmNoCifgPeepholeProjection(armnn::Compute compute) hidl_vec<uint32_t> projectionClippingThresholdDimensions{}; std::vector<float> projectionClippingThresholdValue{0.0f}; + // Normalization: + // 23:The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + hidl_vec<uint32_t> inputLayerNormWeightsDimensions{0}; + std::vector<float> inputLayerNormWeightsValue; + // 24:The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + hidl_vec<uint32_t> forgetLayerNormWeightsDimensions{0}; + std::vector<float> forgetLayerNormWeightsValue; + // 25:The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + hidl_vec<uint32_t> cellLayerNormWeightsDimensions{0}; + std::vector<float> cellLayerNormWeightsValue; + // 26:The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + hidl_vec<uint32_t> outputLayerNormWeightsDimensions{0}; + std::vector<float> outputLayerNormWeightsValue; + // Outputs: // 0: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] with // CIFG, or [batch_size, num_units * 3] without CIFG. @@ -1326,36 +1472,41 @@ void LstmNoCifgPeepholeProjection(armnn::Compute compute) 0.00422612f, -0.0345232f, 0.00223253f, -0.00957321f, 0.0210624f, 0.013331f, 0.0150954f, 0.02168f }; - LstmTestImpl(inputDimensions, inputValue, - inputToInputWeightsDimensions, inputToInputWeightsValue, - inputToForgetWeightsDimensions, inputToForgetWeightsValue, - inputToCellWeightsDimensions, inputToCellWeightsValue, - inputToOutputWeightsDimensions, inputToOutputWeightsValue, - recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, - recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, - recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, - recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, - cellToInputWeightsDimensions, cellToInputWeightsValue, - cellToForgetWeightsDimensions, cellToForgetWeightsValue, - cellToOutputWeightsDimensions, cellToOutputWeightsValue, - inputGateBiasDimensions, inputGateBiasValue, - forgetGateBiasDimensions, forgetGateBiasValue, - cellBiasDimensions, cellBiasValue, - outputGateBiasDimensions, outputGateBiasValue, - projectionWeightsDimensions, projectionWeightsValue, - projectionBiasDimensions, projectionBiasValue, - outputStateInDimensions, outputStateInValue, - cellStateInDimensions, cellStateInValue, - activationFunctionDimensions, activationFunctionValue, - cellClippingThresholdDimensions, cellClippingThresholdValue, - projectionClippingThresholdDimensions, projectionClippingThresholdValue, - scratchBufferDimensions, scratchBufferValue, - outputStateOutDimensions, outputStateOutValue, - cellStateOutDimensions, cellStateOutValue, - outputDimensions, outputValue, - compute); + LstmTestImpl<HalPolicy>(inputDimensions, inputValue, + inputToInputWeightsDimensions, inputToInputWeightsValue, + inputToForgetWeightsDimensions, inputToForgetWeightsValue, + inputToCellWeightsDimensions, inputToCellWeightsValue, + inputToOutputWeightsDimensions, inputToOutputWeightsValue, + recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, + recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, + recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, + recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, + cellToInputWeightsDimensions, cellToInputWeightsValue, + cellToForgetWeightsDimensions, cellToForgetWeightsValue, + cellToOutputWeightsDimensions, cellToOutputWeightsValue, + inputGateBiasDimensions, inputGateBiasValue, + forgetGateBiasDimensions, forgetGateBiasValue, + cellBiasDimensions, cellBiasValue, + outputGateBiasDimensions, outputGateBiasValue, + projectionWeightsDimensions, projectionWeightsValue, + projectionBiasDimensions, projectionBiasValue, + outputStateInDimensions, outputStateInValue, + cellStateInDimensions, cellStateInValue, + activationFunctionDimensions, activationFunctionValue, + cellClippingThresholdDimensions, cellClippingThresholdValue, + projectionClippingThresholdDimensions, projectionClippingThresholdValue, + inputLayerNormWeightsDimensions, inputLayerNormWeightsValue, + forgetLayerNormWeightsDimensions, forgetLayerNormWeightsValue, + cellLayerNormWeightsDimensions, cellLayerNormWeightsValue, + outputLayerNormWeightsDimensions, outputLayerNormWeightsValue, + scratchBufferDimensions, scratchBufferValue, + outputStateOutDimensions, outputStateOutValue, + cellStateOutDimensions, cellStateOutValue, + outputDimensions, outputValue, + compute); } +template <typename HalPolicy> void LstmCifgPeepholeNoProjectionBatch2(armnn::Compute compute) { // This replicates android/frameworks/ml/nn/runtime/test/generated/vts_models/lstm2.model.cpp @@ -1474,6 +1625,24 @@ void LstmCifgPeepholeNoProjectionBatch2(armnn::Compute compute) hidl_vec<uint32_t> projectionClippingThresholdDimensions{}; std::vector<float> projectionClippingThresholdValue{0.0f}; + // Normalization: + // 23:The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + hidl_vec<uint32_t> inputLayerNormWeightsDimensions{0}; + std::vector<float> inputLayerNormWeightsValue; + // 24:The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + hidl_vec<uint32_t> forgetLayerNormWeightsDimensions{0}; + std::vector<float> forgetLayerNormWeightsValue; + // 25:The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + hidl_vec<uint32_t> cellLayerNormWeightsDimensions{0}; + std::vector<float> cellLayerNormWeightsValue; + // 26:The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + hidl_vec<uint32_t> outputLayerNormWeightsDimensions{0}; + std::vector<float> outputLayerNormWeightsValue; + // Outputs: // 0: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] with // CIFG, or [batch_size, num_units * 3] without CIFG. @@ -1497,59 +1666,434 @@ void LstmCifgPeepholeNoProjectionBatch2(armnn::Compute compute) std::vector<float> outputValue{-0.36444446f, -0.00352185f, 0.12886585f, -0.05163646f, -0.42734814f, -0.00478661f, 0.13455015f, -0.03560682f}; - LstmTestImpl(inputDimensions, inputValue, - inputToInputWeightsDimensions, inputToInputWeightsValue, - inputToForgetWeightsDimensions, inputToForgetWeightsValue, - inputToCellWeightsDimensions, inputToCellWeightsValue, - inputToOutputWeightsDimensions, inputToOutputWeightsValue, - recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, - recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, - recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, - recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, - cellToInputWeightsDimensions, cellToInputWeightsValue, - cellToForgetWeightsDimensions, cellToForgetWeightsValue, - cellToOutputWeightsDimensions, cellToOutputWeightsValue, - inputGateBiasDimensions, inputGateBiasValue, - forgetGateBiasDimensions, forgetGateBiasValue, - cellBiasDimensions, cellBiasValue, - outputGateBiasDimensions, outputGateBiasValue, - projectionWeightsDimensions, projectionWeightsValue, - projectionBiasDimensions, projectionBiasValue, - outputStateInDimensions, outputStateInValue, - cellStateInDimensions, cellStateInValue, - activationFunctionDimensions, activationFunctionValue, - cellClippingThresholdDimensions, cellClippingThresholdValue, - projectionClippingThresholdDimensions, projectionClippingThresholdValue, - scratchBufferDimensions, scratchBufferValue, - outputStateOutDimensions, outputStateOutValue, - cellStateOutDimensions, cellStateOutValue, - outputDimensions, outputValue, - compute); + LstmTestImpl<HalPolicy>(inputDimensions, inputValue, + inputToInputWeightsDimensions, inputToInputWeightsValue, + inputToForgetWeightsDimensions, inputToForgetWeightsValue, + inputToCellWeightsDimensions, inputToCellWeightsValue, + inputToOutputWeightsDimensions, inputToOutputWeightsValue, + recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, + recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, + recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, + recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, + cellToInputWeightsDimensions, cellToInputWeightsValue, + cellToForgetWeightsDimensions, cellToForgetWeightsValue, + cellToOutputWeightsDimensions, cellToOutputWeightsValue, + inputGateBiasDimensions, inputGateBiasValue, + forgetGateBiasDimensions, forgetGateBiasValue, + cellBiasDimensions, cellBiasValue, + outputGateBiasDimensions, outputGateBiasValue, + projectionWeightsDimensions, projectionWeightsValue, + projectionBiasDimensions, projectionBiasValue, + outputStateInDimensions, outputStateInValue, + cellStateInDimensions, cellStateInValue, + activationFunctionDimensions, activationFunctionValue, + cellClippingThresholdDimensions, cellClippingThresholdValue, + projectionClippingThresholdDimensions, projectionClippingThresholdValue, + inputLayerNormWeightsDimensions, inputLayerNormWeightsValue, + forgetLayerNormWeightsDimensions, forgetLayerNormWeightsValue, + cellLayerNormWeightsDimensions, cellLayerNormWeightsValue, + outputLayerNormWeightsDimensions, outputLayerNormWeightsValue, + scratchBufferDimensions, scratchBufferValue, + outputStateOutDimensions, outputStateOutValue, + cellStateOutDimensions, cellStateOutValue, + outputDimensions, outputValue, + compute); } -#ifndef ARMCOMPUTECL_ENABLED - static const boost::array<armnn::Compute, 1> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef }}; -#else - static const boost::array<armnn::Compute, 2> COMPUTE_DEVICES = {{ armnn::Compute::CpuRef, armnn::Compute::GpuAcc }}; -#endif -BOOST_DATA_TEST_CASE(LstmNoCifgNoPeepholeNoProjectionTest, COMPUTE_DEVICES) +template <typename HalPolicy> +void LstmNoCifgPeepholeProjectionNoClippingLayerNorm(armnn::Compute compute) { - LstmNoCifgNoPeepholeNoProjection(sample); -} + // This replicates android/frameworks/ml/nn/runtime/test/generated/vts_models/layer_norm_lstm.model.cpp + // with values from android/frameworks/ml/nn/runtime/test/generated/examples/layer_norm_lstm.example.cpp + // and weights, biases and scalars passed as CONSTANT_COPY tensors (instead of MODEL_INPUT tensors). -BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionTest, COMPUTE_DEVICES) -{ - LstmCifgPeepholeNoProjection(sample); -} + uint32_t batchSize = 2; + uint32_t inputSize = 5; + uint32_t numUnits = 4; + uint32_t outputSize = 3; -BOOST_DATA_TEST_CASE(LstmNoCifgPeepholeProjectionTest, COMPUTE_DEVICES) -{ - LstmNoCifgPeepholeProjection(sample); + // Inputs: + // 00: The input: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, input_size], where + // “batch_size” corresponds to the batching dimension, and “input_size” is the size of the input. + hidl_vec<uint32_t> inputDimensions{batchSize, inputSize}; + std::vector<float> inputValue{ 0.7f, 0.8f, 0.1f, 0.2f, 0.3f, // batch 0 + 0.3f, 0.2f, 0.9f, 0.8f, 0.1f}; // batch 1 + + // 01: The input-to-input weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size], where “num_units” corresponds to the number of cell units. + hidl_vec<uint32_t> inputToInputWeightsDimensions{numUnits, inputSize}; + std::vector<float> inputToInputWeightsValue{ 0.5, 0.6, 0.7, -0.8, -0.9, + 0.1, 0.2, 0.3, -0.4, 0.5, + -0.8, 0.7, -0.6, 0.5, -0.4, + -0.5, -0.4, -0.3, -0.2, -0.1}; + // 02: The input-to-forget weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size]. + hidl_vec<uint32_t> inputToForgetWeightsDimensions{numUnits, inputSize}; + std::vector<float> inputToForgetWeightsValue{-0.6, -0.1, 0.3, 0.2, 0.9, + -0.5, -0.2, -0.4, 0.3, -0.8, + -0.4, 0.3, -0.5, -0.4, -0.6, + 0.3, -0.4, -0.6, -0.5, -0.5}; + // 03: The input-to-cell weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units, input_size]. + hidl_vec<uint32_t> inputToCellWeightsDimensions{numUnits, inputSize}; + std::vector<float> inputToCellWeightsValue{-0.4, -0.3, -0.2, -0.1, -0.5, + 0.5, -0.2, -0.3, -0.2, -0.6, + 0.6, -0.1, -0.4, -0.3, -0.7, + 0.7, -0.9, -0.5, 0.8, 0.6}; + // 04: The input-to-output weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size]. + hidl_vec<uint32_t> inputToOutputWeightsDimensions{numUnits, inputSize}; + std::vector<float> inputToOutputWeightsValue{-0.8, -0.4, -0.2, -0.9, -0.1, + -0.7, 0.3, -0.3, -0.8, -0.2, + 0.6, -0.2, 0.4, -0.7, -0.3, + -0.5, 0.1, 0.5, -0.6, -0.4}; + // 05: The recurrent-to-input weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size], where “output_size” corresponds to either the number of cell units (i.e., + // “num_units”), or the second dimension of the “projection_weights”, if defined. + hidl_vec<uint32_t> recurrentToInputWeightsDimensions{numUnits, outputSize}; + std::vector<float> recurrentToInputWeightsValue{-0.2, -0.3, 0.4, + 0.1, -0.5, 0.9, + -0.2, -0.3, -0.7, + 0.05, -0.2, -0.6}; + // 06: The recurrent-to-forget weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + hidl_vec<uint32_t> recurrentToForgetWeightsDimensions{numUnits, outputSize}; + std::vector<float> recurrentToForgetWeightsValue{-0.5, -0.3, -0.5, + -0.2, 0.6, 0.4, + 0.9, 0.3, -0.1, + 0.2, 0.5, 0.2}; + // 07: The recurrent-to-cell weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + hidl_vec<uint32_t> recurrentToCellWeightsDimensions{numUnits, outputSize}; + std::vector<float> recurrentToCellWeightsValue{-0.3, 0.2, 0.1, + -0.3, 0.8,-0.08, + -0.2, 0.3, 0.8, + -0.6, -0.1, 0.2}; + // 08: The recurrent-to-output weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + hidl_vec<uint32_t> recurrentToOutputWeightsDimensions{numUnits, outputSize}; + std::vector<float> recurrentToOutputWeightsValue{ 0.3, -0.1, 0.1, + -0.2, -0.5, -0.7, + -0.2, -0.6, -0.1, + -0.4, -0.7, -0.2}; + // 09: The cell-to-input weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellToInputWeightsDimensions{numUnits}; + std::vector<float> cellToInputWeightsValue{0.05, 0.1, 0.25, 0.15}; + // 10: The cell-to-forget weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellToForgetWeightsDimensions{numUnits}; + std::vector<float> cellToForgetWeightsValue{-0.02, -0.15, -0.25, -0.03}; + // 11: The cell-to-output weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellToOutputWeightsDimensions{numUnits}; + std::vector<float> cellToOutputWeightsValue{0.1, -0.1, -0.5, 0.05}; + // 12: The input gate bias: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> inputGateBiasDimensions{numUnits}; + std::vector<float> inputGateBiasValue{0.03, 0.15, 0.22, 0.38}; + // 13: The forget gate bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> forgetGateBiasDimensions{numUnits}; + std::vector<float> forgetGateBiasValue{0.1, -0.3, -0.2, 0.1}; + // 14: The cell bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellBiasDimensions{numUnits}; + std::vector<float> cellBiasValue{-0.05, 0.72, 0.25, 0.08}; + // 15: The output gate bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> outputGateBiasDimensions{numUnits}; + std::vector<float> outputGateBiasValue{0.05, -0.01, 0.2, 0.1}; + // 16: The projection weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [output_size, num_units]. + hidl_vec<uint32_t> projectionWeightsDimensions{numUnits, outputSize}; + std::vector<float> projectionWeightsValue{-0.1, 0.2, 0.01, + -0.2, 0.1, 0.5, + 0.3, 0.08, 0.07, + 0.2, -0.4, 0.2}; + // 17: The projection bias: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [output_size]. + hidl_vec<uint32_t> projectionBiasDimensions{outputSize}; + std::vector<float> projectionBiasValue(outputSize, 0.0f); + // 18: The output state: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. + hidl_vec<uint32_t> outputStateInDimensions{batchSize, outputSize}; + std::vector<float> outputStateInValue(batchSize * outputSize, 0.0f); + // 19: The cell state: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units]. + hidl_vec<uint32_t> cellStateInDimensions{batchSize, numUnits}; + std::vector<float> cellStateInValue(batchSize * numUnits, 0.0f); + + // Constant scalar values (the VTS test adds these as tensors of dim {}) + // 20: The activation function: A value indicating the activation function: + // 0: None; 1: Relu; 3: Relu6; 4: Tanh; 6: Sigmoid. + hidl_vec<uint32_t> activationFunctionDimensions{}; + std::vector<int32_t> activationFunctionValue{4}; + // 21: The clipping threshold: for the cell state, such that values are bound within [-cell_clip, cell_clip]. + // If set to 0.0 then clipping is disabled. + hidl_vec<uint32_t> cellClippingThresholdDimensions{}; + std::vector<float> cellClippingThresholdValue{0.0f}; + // 22: The clipping threshold: for the output from the projection layer, such that values are bound within + // [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled. + hidl_vec<uint32_t> projectionClippingThresholdDimensions{}; + std::vector<float> projectionClippingThresholdValue{0.0f}; + + // Normalization: + // 23: The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + hidl_vec<uint32_t> inputLayerNormWeightsDimensions{numUnits}; + std::vector<float> inputLayerNormWeightsValue{0.1, 0.2, 0.3, 0.5}; + // 24: The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + hidl_vec<uint32_t> forgetLayerNormWeightsDimensions{numUnits}; + std::vector<float> forgetLayerNormWeightsValue{0.2, 0.2, 0.4, 0.3}; + // 25: The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + hidl_vec<uint32_t> cellLayerNormWeightsDimensions{numUnits}; + std::vector<float> cellLayerNormWeightsValue{0.7, 0.2, 0.3, 0.8}; + // 26: The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + hidl_vec<uint32_t> outputLayerNormWeightsDimensions{numUnits}; + std::vector<float> outputLayerNormWeightsValue{0.6, 0.2, 0.2, 0.5}; + + // Outputs: + // 0: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] with + // CIFG, or [batch_size, num_units * 3] without CIFG. + // HOWEVER, by looking at the code, seems that it's the opposite: (cifg ? 3 : 4) * numUnits + // Refer to: android/frameworks/ml/nn/common/operations/LSTM.cpp:319 + // android/frameworks/ml/nn/common/operations/LSTMTest.cpp:114 + // tensorflow/tensorflow/contrib/lite/kernels/lstm.cc:332 + hidl_vec<uint32_t> scratchBufferDimensions{batchSize, numUnits * 4}; + std::vector<float> scratchBufferValue(batchSize * numUnits * 4, 0.0f); + // 1: The output state (out): A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. + hidl_vec<uint32_t> outputStateOutDimensions{batchSize, outputSize}; + std::vector<float> outputStateOutValue { 0.02440767f, 0.12802738f, -0.00170918f, + -0.00692428f, 0.08487406f, 0.06344498f}; + // 2: The cell state (out): A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units]. + hidl_vec<uint32_t> cellStateOutDimensions{batchSize, numUnits}; + std::vector<float> cellStateOutValue {-0.45177122f, 0.37691566f, 0.22542511f, 0.23240635f, + -0.25258583f, 0.33042118f, 0.01730525f, 0.36660123f}; + // 3: The output: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. This is + // effectively the same as the current “output state (out)” value. + hidl_vec<uint32_t> outputDimensions{batchSize, outputSize}; + std::vector<float> outputValue{ 0.02440767f, 0.12802738f, -0.00170918f, + -0.00692428f, 0.08487406f, 0.06344498f}; + + LstmTestImpl<HalPolicy>(inputDimensions, inputValue, + inputToInputWeightsDimensions, inputToInputWeightsValue, + inputToForgetWeightsDimensions, inputToForgetWeightsValue, + inputToCellWeightsDimensions, inputToCellWeightsValue, + inputToOutputWeightsDimensions, inputToOutputWeightsValue, + recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, + recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, + recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, + recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, + cellToInputWeightsDimensions, cellToInputWeightsValue, + cellToForgetWeightsDimensions, cellToForgetWeightsValue, + cellToOutputWeightsDimensions, cellToOutputWeightsValue, + inputGateBiasDimensions, inputGateBiasValue, + forgetGateBiasDimensions, forgetGateBiasValue, + cellBiasDimensions, cellBiasValue, + outputGateBiasDimensions, outputGateBiasValue, + projectionWeightsDimensions, projectionWeightsValue, + projectionBiasDimensions, projectionBiasValue, + outputStateInDimensions, outputStateInValue, + cellStateInDimensions, cellStateInValue, + activationFunctionDimensions, activationFunctionValue, + cellClippingThresholdDimensions, cellClippingThresholdValue, + projectionClippingThresholdDimensions, projectionClippingThresholdValue, + inputLayerNormWeightsDimensions, inputLayerNormWeightsValue, + forgetLayerNormWeightsDimensions, forgetLayerNormWeightsValue, + cellLayerNormWeightsDimensions, cellLayerNormWeightsValue, + outputLayerNormWeightsDimensions, outputLayerNormWeightsValue, + scratchBufferDimensions, scratchBufferValue, + outputStateOutDimensions, outputStateOutValue, + cellStateOutDimensions, cellStateOutValue, + outputDimensions, outputValue, + compute); } -BOOST_DATA_TEST_CASE(LstmCifgPeepholeNoProjectionBatch2Test, COMPUTE_DEVICES) +template <typename HalPolicy> +void LstmCifgPeepholeProjectionNoClippingLayerNorm(armnn::Compute compute) { - LstmCifgPeepholeNoProjectionBatch2(sample); -} + // This replicates android/frameworks/ml/nn/runtime/test/generated/vts_models/layer_norm_lstm.model.cpp + // with values from android/frameworks/ml/nn/runtime/test/generated/examples/layer_norm_lstm.example.cpp + // and weights, biases and scalars passed as CONSTANT_COPY tensors (instead of MODEL_INPUT tensors). + + uint32_t batchSize = 2; + uint32_t inputSize = 5; + uint32_t numUnits = 4; + uint32_t outputSize = 3; -BOOST_AUTO_TEST_SUITE_END() + // Inputs: + // 00: The input: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, input_size], where + // “batch_size” corresponds to the batching dimension, and “input_size” is the size of the input. + hidl_vec<uint32_t> inputDimensions{batchSize, inputSize}; + std::vector<float> inputValue{ 0.7f, 0.8f, 0.1f, 0.2f, 0.3f, // batch 0 + 0.3f, 0.2f, 0.9f, 0.8f, 0.1f}; // batch 1 + + // 01: The input-to-input weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size], where “num_units” corresponds to the number of cell units. + hidl_vec<uint32_t> inputToInputWeightsDimensions{0}; + std::vector<float> inputToInputWeightsValue; + // 02: The input-to-forget weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size]. + hidl_vec<uint32_t> inputToForgetWeightsDimensions{numUnits, inputSize}; + std::vector<float> inputToForgetWeightsValue{-0.6, -0.1, 0.3, 0.2, 0.9, + -0.5, -0.2, -0.4, 0.3, -0.8, + -0.4, 0.3, -0.5, -0.4, -0.6, + 0.3, -0.4, -0.6, -0.5, -0.5}; + // 03: The input-to-cell weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units, input_size]. + hidl_vec<uint32_t> inputToCellWeightsDimensions{numUnits, inputSize}; + std::vector<float> inputToCellWeightsValue{-0.4, -0.3, -0.2, -0.1, -0.5, + 0.5, -0.2, -0.3, -0.2, -0.6, + 0.6, -0.1, -0.4, -0.3, -0.7, + 0.7, -0.9, -0.5, 0.8, 0.6}; + // 04: The input-to-output weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, input_size]. + hidl_vec<uint32_t> inputToOutputWeightsDimensions{numUnits, inputSize}; + std::vector<float> inputToOutputWeightsValue{-0.8, -0.4, -0.2, -0.9, -0.1, + -0.7, 0.3, -0.3, -0.8, -0.2, + 0.6, -0.2, 0.4, -0.7, -0.3, + -0.5, 0.1, 0.5, -0.6, -0.4}; + // 05: The recurrent-to-input weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size], where “output_size” corresponds to either the number of cell units (i.e., + // “num_units”), or the second dimension of the “projection_weights”, if defined. + hidl_vec<uint32_t> recurrentToInputWeightsDimensions{0}; + std::vector<float> recurrentToInputWeightsValue; + // 06: The recurrent-to-forget weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + hidl_vec<uint32_t> recurrentToForgetWeightsDimensions{numUnits, outputSize}; + std::vector<float> recurrentToForgetWeightsValue{-0.5, -0.3, -0.5, + -0.2, 0.6, 0.4, + 0.9, 0.3, -0.1, + 0.2, 0.5, 0.2}; + // 07: The recurrent-to-cell weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + hidl_vec<uint32_t> recurrentToCellWeightsDimensions{numUnits, outputSize}; + std::vector<float> recurrentToCellWeightsValue{-0.3, 0.2, 0.1, + -0.3, 0.8,-0.08, + -0.2, 0.3, 0.8, + -0.6, -0.1, 0.2}; + // 08: The recurrent-to-output weights: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [num_units, output_size]. + hidl_vec<uint32_t> recurrentToOutputWeightsDimensions{numUnits, outputSize}; + std::vector<float> recurrentToOutputWeightsValue{ 0.3, -0.1, 0.1, + -0.2, -0.5, -0.7, + -0.2, -0.6, -0.1, + -0.4, -0.7, -0.2}; + // 09: The cell-to-input weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellToInputWeightsDimensions{0}; + std::vector<float> cellToInputWeightsValue; + // 10: The cell-to-forget weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellToForgetWeightsDimensions{numUnits}; + std::vector<float> cellToForgetWeightsValue{-0.02, -0.15, -0.25, -0.03}; + // 11: The cell-to-output weights: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellToOutputWeightsDimensions{numUnits}; + std::vector<float> cellToOutputWeightsValue{0.1, -0.1, -0.5, 0.05}; + // 12: The input gate bias: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> inputGateBiasDimensions{0}; + std::vector<float> inputGateBiasValue; + // 13: The forget gate bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> forgetGateBiasDimensions{numUnits}; + std::vector<float> forgetGateBiasValue{0.1, -0.3, -0.2, 0.1}; + // 14: The cell bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> cellBiasDimensions{numUnits}; + std::vector<float> cellBiasValue{-0.05, 0.72, 0.25, 0.08}; + // 15: The output gate bias: A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [num_units]. + hidl_vec<uint32_t> outputGateBiasDimensions{numUnits}; + std::vector<float> outputGateBiasValue{0.05, -0.01, 0.2, 0.1}; + // 16: The projection weights: Optional. A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape + // [output_size, num_units]. + hidl_vec<uint32_t> projectionWeightsDimensions{numUnits, outputSize}; + std::vector<float> projectionWeightsValue{-0.1, 0.2, 0.01, + -0.2, 0.1, 0.5, + 0.3, 0.08, 0.07, + 0.2, -0.4, 0.2}; + // 17: The projection bias: Optional. A 1-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [output_size]. + hidl_vec<uint32_t> projectionBiasDimensions{outputSize}; + std::vector<float> projectionBiasValue(outputSize, 0.0f); + // 18: The output state: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. + hidl_vec<uint32_t> outputStateInDimensions{batchSize, outputSize}; + std::vector<float> outputStateInValue(batchSize * outputSize, 0.0f); + // 19: The cell state: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units]. + hidl_vec<uint32_t> cellStateInDimensions{batchSize, numUnits}; + std::vector<float> cellStateInValue(batchSize * numUnits, 0.0f); + + // Constant scalar values (the VTS test adds these as tensors of dim {}) + // 20: The activation function: A value indicating the activation function: + // 0: None; 1: Relu; 3: Relu6; 4: Tanh; 6: Sigmoid. + hidl_vec<uint32_t> activationFunctionDimensions{}; + std::vector<int32_t> activationFunctionValue{4}; + // 21: The clipping threshold: for the cell state, such that values are bound within [-cell_clip, cell_clip]. + // If set to 0.0 then clipping is disabled. + hidl_vec<uint32_t> cellClippingThresholdDimensions{}; + std::vector<float> cellClippingThresholdValue{0.0f}; + // 22: The clipping threshold: for the output from the projection layer, such that values are bound within + // [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled. + hidl_vec<uint32_t> projectionClippingThresholdDimensions{}; + std::vector<float> projectionClippingThresholdValue{0.0f}; + + // Normalization: + // 23: The input layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at input gate. + hidl_vec<uint32_t> inputLayerNormWeightsDimensions{numUnits}; + std::vector<float> inputLayerNormWeightsValue{0.1, 0.2, 0.3, 0.5}; + // 24: The forget layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at forget gate. + hidl_vec<uint32_t> forgetLayerNormWeightsDimensions{numUnits}; + std::vector<float> forgetLayerNormWeightsValue{0.2, 0.2, 0.4, 0.3}; + // 25: The cell layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at cell gate. + hidl_vec<uint32_t> cellLayerNormWeightsDimensions{numUnits}; + std::vector<float> cellLayerNormWeightsValue{0.7, 0.2, 0.3, 0.8}; + // 26: The output layer normalization weights. A 1-D tensor of shape [num_units]. + // Used to rescale normalized inputs to activation at output gate. + hidl_vec<uint32_t> outputLayerNormWeightsDimensions{numUnits}; + std::vector<float> outputLayerNormWeightsValue{0.6, 0.2, 0.2, 0.5}; + + // Outputs: + // 0: The scratch buffer: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units * 4] with + // CIFG, or [batch_size, num_units * 3] without CIFG. + // HOWEVER, by looking at the code, seems that it's the opposite: (cifg ? 3 : 4) * numUnits + // Refer to: android/frameworks/ml/nn/common/operations/LSTM.cpp:319 + // android/frameworks/ml/nn/common/operations/LSTMTest.cpp:114 + // tensorflow/tensorflow/contrib/lite/kernels/lstm.cc:332 + hidl_vec<uint32_t> scratchBufferDimensions{batchSize, numUnits * 3}; + std::vector<float> scratchBufferValue(batchSize * numUnits * 3, 0.0f); + // 1: The output state (out): A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. + hidl_vec<uint32_t> outputStateOutDimensions{batchSize, outputSize}; + std::vector<float> outputStateOutValue { 0.02129706f, 0.14081624f, 0.01127331f, + -0.02263505f, 0.09169482f, 0.07691758f}; + // 2: The cell state (out): A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, num_units]. + hidl_vec<uint32_t> cellStateOutDimensions{batchSize, numUnits}; + std::vector<float> cellStateOutValue{-0.35102980f, 0.42610350f, 0.21463650f, 0.27716520f, + -0.18855170f, 0.32522000f, 0.02036650f, 0.48967660f}; + // 3: The output: A 2-D tensor of ANEURALNETWORKS_TENSOR_FLOAT32, of shape [batch_size, output_size]. This is + // effectively the same as the current “output state (out)” value. + hidl_vec<uint32_t> outputDimensions{batchSize, outputSize}; + std::vector<float> outputValue{ 0.02129706f, 0.14081624f, 0.01127331f, + -0.02263505f, 0.09169482f, 0.07691758f}; + + LstmTestImpl<HalPolicy>(inputDimensions, inputValue, + inputToInputWeightsDimensions, inputToInputWeightsValue, + inputToForgetWeightsDimensions, inputToForgetWeightsValue, + inputToCellWeightsDimensions, inputToCellWeightsValue, + inputToOutputWeightsDimensions, inputToOutputWeightsValue, + recurrentToInputWeightsDimensions, recurrentToInputWeightsValue, + recurrentToForgetWeightsDimensions, recurrentToForgetWeightsValue, + recurrentToCellWeightsDimensions, recurrentToCellWeightsValue, + recurrentToOutputWeightsDimensions, recurrentToOutputWeightsValue, + cellToInputWeightsDimensions, cellToInputWeightsValue, + cellToForgetWeightsDimensions, cellToForgetWeightsValue, + cellToOutputWeightsDimensions, cellToOutputWeightsValue, + inputGateBiasDimensions, inputGateBiasValue, + forgetGateBiasDimensions, forgetGateBiasValue, + cellBiasDimensions, cellBiasValue, + outputGateBiasDimensions, outputGateBiasValue, + projectionWeightsDimensions, projectionWeightsValue, + projectionBiasDimensions, projectionBiasValue, + outputStateInDimensions, outputStateInValue, + cellStateInDimensions, cellStateInValue, + activationFunctionDimensions, activationFunctionValue, + cellClippingThresholdDimensions, cellClippingThresholdValue, + projectionClippingThresholdDimensions, projectionClippingThresholdValue, + inputLayerNormWeightsDimensions, inputLayerNormWeightsValue, + forgetLayerNormWeightsDimensions, forgetLayerNormWeightsValue, + cellLayerNormWeightsDimensions, cellLayerNormWeightsValue, + outputLayerNormWeightsDimensions, outputLayerNormWeightsValue, + scratchBufferDimensions, scratchBufferValue, + outputStateOutDimensions, outputStateOutValue, + cellStateOutDimensions, cellStateOutValue, + outputDimensions, outputValue, + compute); +} |