aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFerran Balaguer <ferran.balaguer@arm.com>2019-07-25 12:12:39 +0100
committerMatteo Martincigh <matteo.martincigh@arm.com>2019-07-29 13:55:18 +0000
commitb2397fd9d68f12792b04dd90ae72dfb8cb9f4a60 (patch)
tree69833c482fd57df20e478398abdf932205bf99bb
parenta3609ccd88a9c403e086e88cad063adedbcad5fd (diff)
downloadandroid-nn-driver-b2397fd9d68f12792b04dd90ae72dfb8cb9f4a60.tar.gz
IVGCVSW-3398 Add LSTM normalization parameters to HAL 1.2
* Adding LSTM processing function in HAL 1.2 with normalization parameters * Refactoring LSTM tests !armnn:1608 Signed-off-by: Ferran Balaguer <ferran.balaguer@arm.com> Change-Id: I0e00f14ef078a333e9f2f23d6278a5d92a3001d6
-rw-r--r--1.2/ArmnnDriverImpl.cpp2
-rw-r--r--1.2/HalPolicy.cpp429
-rw-r--r--1.2/HalPolicy.hpp2
-rw-r--r--test/1.0/Lstm.cpp34
-rw-r--r--test/1.1/Lstm.cpp34
-rw-r--r--test/1.2/Lstm.cpp44
-rw-r--r--test/Android.mk9
-rw-r--r--test/DriverTestHelpers.cpp46
-rw-r--r--test/DriverTestHelpers.hpp48
-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);
+}