ArmNN
 24.02
LstmUtils.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 //#pragma once
7 
8 #include "LstmUtils.hpp"
9 #include "BaseIterator.hpp"
11 
12 
13 // Helper functions ported from the Android code base
14 // Refer to: android/external/tensorflow/tensorflow/contrib/lite/kernels/internal/reference/portable_tensor_utils.cc
15 
17  uint32_t vSize,
18  armnn::Decoder<float>& batchVector,
19  uint32_t nBatch,
20  armnn::Encoder<float>& outResult )
21 {
22  for (uint32_t b = 0; b < nBatch; b++)
23  {
24  for (uint32_t v = 0; v < vSize; v++)
25  {
26  outResult.Set(batchVector.Get() + vector.Get());
27  ++outResult;
28  ++vector;
29  ++batchVector;
30  }
31  vector -= vSize;
32  }
33  batchVector -= vSize * nBatch;
34  outResult -= vSize * nBatch;
35 }
36 
37 
38 // Layer norm for each batch.
39 // normalization_epsilon is added to avoid divergence.
41  armnn::Encoder<float>& output_vector,
42  uint32_t v_size,
43  uint32_t n_batch,
44  float normalization_epsilon)
45 {
46  for (uint32_t batch = 0; batch < n_batch; ++batch) {
47  float sum = 0.0f;
48  float sum_sq = 0.0f;
49  for (uint32_t i = 0; i < v_size; ++i) {
50  sum += input_vector.Get();
51  sum_sq += input_vector.Get() * input_vector.Get();
52  ++input_vector;
53  }
54  input_vector -= v_size;
55 
56  const float mean = sum / static_cast<float>(v_size);
57  float stddev_inv = 0.0f;
58  const float variance = sum_sq / static_cast<float>(v_size) - mean * mean;
59  if (variance == 0) {
60  stddev_inv = 1.0f / std::sqrt(normalization_epsilon);
61  } else {
62  stddev_inv = 1.0f / std::sqrt(variance);
63  }
64 
65  for (uint32_t i = 0; i < v_size; ++i) {
66  output_vector.Set((input_vector.Get() - mean) * stddev_inv);
67  ++output_vector;
68  ++input_vector;
69  }
70  // Don't reset iterator to handle next batch
71  }
72  output_vector -= v_size * n_batch;
73  input_vector -= v_size * n_batch;
74 }
75 
77  uint32_t vSize)
78 {
79  for (uint32_t v = 0; v < vSize; v++)
80  {
81  vector.Set(0.0f);
82  ++vector;
83  }
84  vector -= vSize;
85 }
86 
88  uint32_t mRows,
89  uint32_t mCols,
90  armnn::Decoder<float>& vector,
91  uint32_t nBatch,
92  armnn::Encoder<float>& outResult)
93 {
94  for (uint32_t b = 0; b < nBatch; b++)
95  {
96  for (uint32_t r = 0; r < mRows; r++)
97  {
98  vector += b * mCols;
99  for (uint32_t c = 0; c < mCols; c++)
100  {
101  outResult.Set(outResult.Get() + matrix.Get() * vector.Get());
102  ++matrix;
103  ++vector;
104  }
105  outResult += 1;
106  vector -= (b+1) * mCols;
107  }
108  matrix -= (mRows * mCols);
109  }
110  outResult -= (mRows * nBatch);
111 }
112 
114  uint32_t vSize,
115  uint32_t nBatch,
116  armnn::Encoder<float>& outBatchVector)
117 {
118  for (uint32_t b = 0; b < nBatch; b++)
119  {
120  for (uint32_t v = 0; v < vSize; v++)
121  {
122  outBatchVector.Set(vector.Get());
123  ++outBatchVector;
124  ++vector;
125  }
126  vector -= vSize;
127  }
128  outBatchVector -= (nBatch * vSize);
129 }
130 
132  uint32_t vSize,
133  armnn::Decoder<float>& batchVector,
134  uint32_t nBatch,
135  armnn::Encoder<float>& outResult)
136 {
137  for (uint32_t b = 0; b < nBatch; b++)
138  {
139  for (uint32_t v = 0; v < vSize; v++)
140  {
141  outResult.Set(outResult.Get() + vector.Get() * batchVector.Get());
142  ++outResult;
143  ++vector;
144  ++batchVector;
145  }
146  vector -= vSize;
147  }
148  batchVector -= vSize * nBatch;
149  outResult -= vSize * nBatch;
150 }
151 
153  uint32_t vSize,
154  armnn::Decoder<float>& batchVector,
155  uint32_t nBatch,
156  armnn::Encoder<float>& outResult)
157 {
158  for (uint32_t b = 0; b < nBatch; b++)
159  {
160  for (uint32_t v = 0; v < vSize; v++)
161  {
162  outResult.Set(vector.Get() * batchVector.Get());
163  ++outResult;
164  ++vector;
165  ++batchVector;
166  }
167  vector -= vSize;
168  }
169  batchVector -= vSize * nBatch;
170  outResult -= vSize * nBatch;
171 }
172 
174  uint32_t vSize,
175  armnn::Encoder<float>& result)
176 {
177  for (uint32_t v = 0; v < vSize; v++)
178  {
179  result.Set(1.0f - vector.Get());
180  ++vector;
181  ++result;
182  }
183  vector -= vSize;
184  result -= vSize;
185 }
186 
188  armnn::Decoder<float>& vector2,
189  uint32_t vSize,
190  armnn::Encoder<float>& outResult)
191 {
192  for (uint32_t v = 0; v < vSize; v++)
193  {
194  outResult.Set(vector1.Get() * vector2.Get());
195  ++outResult;
196  ++vector1;
197  ++vector2;
198  }
199  outResult -= vSize;
200  vector1 -= vSize;
201  vector2 -= vSize;
202 }
203 
205  armnn::Decoder<float>& vector2,
206  uint32_t vSize,
207  armnn::Encoder<float>& outResult)
208 {
209  for (uint32_t v = 0; v < vSize; v++)
210  {
211  outResult.Set(outResult.Get() + vector1.Get() * vector2.Get());
212  ++outResult;
213  ++vector1;
214  ++vector2;
215  }
216  outResult -= vSize;
217  vector1 -= vSize;
218  vector2 -= vSize;
219 }
220 
221 float Clip(float f,
222  float absLimit)
223 {
224  float result = (absLimit < f) ? absLimit : f;
225  result = (-absLimit > result) ? -absLimit : result;
226  return result;
227 }
228 
230  uint32_t vSize,
231  float absLimit,
232  armnn::Encoder<float>& outResult)
233 {
234  for (uint32_t v = 0; v < vSize; v++)
235  {
236  outResult.Set(Clip(vector.Get(), absLimit));
237  ++vector;
238  ++outResult;
239  }
240  vector -= vSize;
241  outResult -= vSize;
242 }
243 
245  uint32_t vSize,
246  armnn::Encoder<float>& outResult)
247 {
248  for (uint32_t v = 0; v < vSize; v++)
249  {
250  outResult.Set(vector.Get());
251  ++outResult;
252  ++vector;
253  }
254  outResult -= vSize;
255  vector -= vSize;
256 }
257 
258 void SetActivationParameters(uint32_t activation,
259  armnn::ActivationFunction& outArmnnActivation,
260  float& outA,
261  float& outB)
262 {
263  switch (activation)
264  {
265  case 0: // None
266  outA = 0;
267  outB = 0;
268  return;
269 
270  case 1: // Relu
271  outArmnnActivation = armnn::ActivationFunction::ReLu;
272  outA = 0;
273  outB = 0;
274  return;
275 
276  case 3: // Relu6
277  outArmnnActivation = armnn::ActivationFunction::BoundedReLu;
278  outA = 6;
279  outB = 0;
280  return;
281 
282  case 4: // Tanh
283  outArmnnActivation = armnn::ActivationFunction::TanH;
284  outA = 1;
285  outB = 1;
286  return;
287 
288  case 6: // Sigmoid
289  outArmnnActivation = armnn::ActivationFunction::Sigmoid;
290  outA = 0;
291  outB = 0;
292  return;
293 
294  default:
295  throw armnn::Exception("Unsupported activation function: " + std::to_string(activation));
296  }
297 }
298 
299 std::unique_ptr<armnn::ScopedTensorHandle> AssignScopedTensorHandle(const armnn::ConstTensorHandle *ptr)
300 {
301  if (!ptr)
302  {
303  return nullptr;
304  }
305 
306  return std::make_unique<armnn::ScopedTensorHandle>(*ptr);
307 }
VectorVectorCwiseProduct
void VectorVectorCwiseProduct(armnn::Decoder< float > &vector1, armnn::Decoder< float > &vector2, uint32_t vSize, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:187
armnn::Decoder< float >
armnn::Encoder::Set
virtual void Set(IType right)=0
MeanStddevNormalization
void MeanStddevNormalization(armnn::Decoder< float > &input_vector, armnn::Encoder< float > &output_vector, uint32_t v_size, uint32_t n_batch, float normalization_epsilon)
Definition: LstmUtils.cpp:40
VectorBatchVectorCwiseProductAccumulate
void VectorBatchVectorCwiseProductAccumulate(armnn::Decoder< float > &vector, uint32_t vSize, armnn::Decoder< float > &batchVector, uint32_t nBatch, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:131
BaseIterator.hpp
armnn::ConstTensorHandle
Definition: TensorHandle.hpp:24
VectorBatchVectorAdd
void VectorBatchVectorAdd(armnn::Decoder< float > &vector, uint32_t vSize, armnn::Decoder< float > &batchVector, uint32_t nBatch, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:16
armnn::Encoder::Get
virtual IType Get() const =0
armnn::ActivationFunction::TanH
@ TanH
VectorBatchVectorCwiseProduct
void VectorBatchVectorCwiseProduct(armnn::Decoder< float > &vector, uint32_t vSize, armnn::Decoder< float > &batchVector, uint32_t nBatch, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:152
ClipVector
void ClipVector(armnn::Decoder< float > &vector, uint32_t vSize, float absLimit, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:229
AssignScopedTensorHandle
std::unique_ptr< armnn::ScopedTensorHandle > AssignScopedTensorHandle(const armnn::ConstTensorHandle *ptr)
Definition: LstmUtils.cpp:299
MatrixBatchVectorMultiplyAccumulate
void MatrixBatchVectorMultiplyAccumulate(armnn::Decoder< float > &matrix, uint32_t mRows, uint32_t mCols, armnn::Decoder< float > &vector, uint32_t nBatch, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:87
armnn::ActivationFunction::BoundedReLu
@ BoundedReLu
min(a, max(b, input)) ReLu1 & ReLu6.
CopyVector
void CopyVector(armnn::Decoder< float > &vector, uint32_t vSize, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:244
Sub1Vector
void Sub1Vector(armnn::Decoder< float > &vector, uint32_t vSize, armnn::Encoder< float > &result)
Definition: LstmUtils.cpp:173
armnn::Encoder< float >
Clip
float Clip(float f, float absLimit)
Definition: LstmUtils.cpp:221
armnn::Exception
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
armnn::ActivationFunction
ActivationFunction
Definition: Types.hpp:86
armnn::Decoder::Get
virtual IType Get() const =0
ZeroVector
void ZeroVector(armnn::Encoder< float > &vector, uint32_t vSize)
Definition: LstmUtils.cpp:76
TensorHandle.hpp
VectorVectorCwiseProductAccumulate
void VectorVectorCwiseProductAccumulate(armnn::Decoder< float > &vector1, armnn::Decoder< float > &vector2, uint32_t vSize, armnn::Encoder< float > &outResult)
Definition: LstmUtils.cpp:204
armnn::ActivationFunction::ReLu
@ ReLu
SetActivationParameters
void SetActivationParameters(uint32_t activation, armnn::ActivationFunction &outArmnnActivation, float &outA, float &outB)
Definition: LstmUtils.cpp:258
LstmUtils.hpp
armnn::ActivationFunction::Sigmoid
@ Sigmoid
VectorBatchVectorAssign
void VectorBatchVectorAssign(armnn::Decoder< float > &vector, uint32_t vSize, uint32_t nBatch, armnn::Encoder< float > &outBatchVector)
Definition: LstmUtils.cpp:113