aboutsummaryrefslogtreecommitdiff
path: root/src/backends/reference/workloads/LstmUtils.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends/reference/workloads/LstmUtils.hpp')
-rw-r--r--src/backends/reference/workloads/LstmUtils.hpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/backends/reference/workloads/LstmUtils.hpp b/src/backends/reference/workloads/LstmUtils.hpp
new file mode 100644
index 0000000000..db02a84a45
--- /dev/null
+++ b/src/backends/reference/workloads/LstmUtils.hpp
@@ -0,0 +1,218 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "BaseIterator.hpp"
+#include <backendsCommon/CpuTensorHandle.hpp>
+
+namespace
+{
+
+// Helper functions ported from the Android code base
+// Refer to: android/external/tensorflow/tensorflow/contrib/lite/kernels/internal/reference/portable_tensor_utils.cc
+
+void MatrixBatchVectorMultiplyAccumulate(armnn::Decoder<float>& matrix,
+ uint32_t mRows,
+ uint32_t mCols,
+ armnn::Decoder<float>& vector,
+ uint32_t nBatch,
+ armnn::Encoder<float>& outResult)
+{
+ for (uint32_t b = 0; b < nBatch; b++)
+ {
+ for (uint32_t r = 0; r < mRows; r++)
+ {
+ vector += b * mCols;
+ for (uint32_t c = 0; c < mCols; c++)
+ {
+ outResult.Set(outResult.Get() + matrix.Get() * vector.Get());
+ ++matrix;
+ ++vector;
+ }
+ outResult += 1;
+ vector -= (b+1) * mCols;
+ }
+ matrix -= (mRows * mCols);
+ }
+ outResult -= (mRows * nBatch);
+}
+
+void VectorBatchVectorAssign(armnn::Decoder<float>& vector,
+ uint32_t vSize,
+ uint32_t nBatch,
+ armnn::Encoder<float>& outBatchVector)
+{
+ for (uint32_t b = 0; b < nBatch; b++)
+ {
+ for (uint32_t v = 0; v < vSize; v++)
+ {
+ outBatchVector.Set(vector.Get());
+ ++outBatchVector;
+ ++vector;
+ }
+ vector -= vSize;
+ }
+ outBatchVector -= (nBatch * vSize);
+}
+
+void VectorBatchVectorCwiseProductAccumulate(armnn::Decoder<float>& vector,
+ uint32_t vSize,
+ armnn::Decoder<float>& batchVector,
+ uint32_t nBatch,
+ armnn::Encoder<float>& outResult)
+{
+ for (uint32_t b = 0; b < nBatch; b++)
+ {
+ for (uint32_t v = 0; v < vSize; v++)
+ {
+ outResult.Set(outResult.Get() + vector.Get() * batchVector.Get());
+ ++outResult;
+ ++vector;
+ ++batchVector;
+ }
+ vector -= vSize;
+ }
+ batchVector -= vSize * nBatch;
+ outResult -= vSize * nBatch;
+}
+
+void Sub1Vector(armnn::Decoder<float>& vector,
+ uint32_t vSize,
+ armnn::Encoder<float>& result)
+{
+ for (uint32_t v = 0; v < vSize; v++)
+ {
+ result.Set(1.0f - vector.Get());
+ ++vector;
+ ++result;
+ }
+ vector -= vSize;
+ result -= vSize;
+}
+
+void VectorVectorCwiseProduct(armnn::Decoder<float>& vector1,
+ armnn::Decoder<float>& vector2,
+ uint32_t vSize,
+ armnn::Encoder<float>& outResult)
+{
+ for (uint32_t v = 0; v < vSize; v++)
+ {
+ outResult.Set(vector1.Get() * vector2.Get());
+ ++outResult;
+ ++vector1;
+ ++vector2;
+ }
+ outResult -= vSize;
+ vector1 -= vSize;
+ vector2 -= vSize;
+}
+
+void VectorVectorCwiseProductAccumulate(armnn::Decoder<float>& vector1,
+ armnn::Decoder<float>& vector2,
+ uint32_t vSize,
+ armnn::Encoder<float>& outResult)
+{
+ for (uint32_t v = 0; v < vSize; v++)
+ {
+ outResult.Set(outResult.Get() + vector1.Get() * vector2.Get());
+ ++outResult;
+ ++vector1;
+ ++vector2;
+ }
+ outResult -= vSize;
+ vector1 -= vSize;
+ vector2 -= vSize;
+}
+
+float Clip(float f,
+ float absLimit)
+{
+ float result = (absLimit < f) ? absLimit : f;
+ result = (-absLimit > result) ? -absLimit : result;
+ return result;
+}
+
+void ClipVector(armnn::Decoder<float>& vector,
+ uint32_t vSize,
+ float absLimit,
+ armnn::Encoder<float>& outResult)
+{
+ for (uint32_t v = 0; v < vSize; v++)
+ {
+ outResult.Set(Clip(vector.Get(), absLimit));
+ ++vector;
+ ++outResult;
+ }
+ vector -= vSize;
+ outResult -= vSize;
+}
+
+void CopyVector(armnn::Decoder<float>& vector,
+ uint32_t vSize,
+ armnn::Encoder<float>& outResult)
+{
+ for (uint32_t v = 0; v < vSize; v++)
+ {
+ outResult.Set(vector.Get());
+ ++outResult;
+ ++vector;
+ }
+ outResult -= vSize;
+ vector -= vSize;
+}
+
+void SetActivationParameters(uint32_t activation,
+ armnn::ActivationFunction& outArmnnActivation,
+ float& outA,
+ float& outB)
+{
+ switch (activation)
+ {
+ case 0: // None
+ outA = 0;
+ outB = 0;
+ return;
+
+ case 1: // Relu
+ outArmnnActivation = armnn::ActivationFunction::ReLu;
+ outA = 0;
+ outB = 0;
+ return;
+
+ case 3: // Relu6
+ outArmnnActivation = armnn::ActivationFunction::BoundedReLu;
+ outA = 6;
+ outB = 0;
+ return;
+
+ case 4: // Tanh
+ outArmnnActivation = armnn::ActivationFunction::TanH;
+ outA = 1;
+ outB = 1;
+ return;
+
+ case 6: // Sigmoid
+ outArmnnActivation = armnn::ActivationFunction::Sigmoid;
+ outA = 0;
+ outB = 0;
+ return;
+
+ default:
+ throw armnn::Exception("Unsupported activation function: " + std::to_string(activation));
+ }
+}
+
+std::unique_ptr<armnn::ScopedCpuTensorHandle> AssignScopedCpuTensorHandle(const armnn::ConstCpuTensorHandle* ptr)
+{
+ if (!ptr)
+ {
+ return nullptr;
+ }
+
+ return std::make_unique<armnn::ScopedCpuTensorHandle>(*ptr);
+}
+
+} // anonymous namespace