• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
10 #include <armnn/backends/TensorHandle.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 
VectorBatchVectorAdd(armnn::Decoder<float> & vector,uint32_t vSize,armnn::Decoder<float> & batchVector,uint32_t nBatch,armnn::Encoder<float> & outResult)16 void VectorBatchVectorAdd(armnn::Decoder<float>& vector,
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.
MeanStddevNormalization(armnn::Decoder<float> & input_vector,armnn::Encoder<float> & output_vector,uint32_t v_size,uint32_t n_batch,float normalization_epsilon)40 void MeanStddevNormalization(armnn::Decoder<float>& input_vector,
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 
ZeroVector(armnn::Encoder<float> & vector,uint32_t vSize)76 void ZeroVector(armnn::Encoder<float>& vector,
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 
MatrixBatchVectorMultiplyAccumulate(armnn::Decoder<float> & matrix,uint32_t mRows,uint32_t mCols,armnn::Decoder<float> & vector,uint32_t nBatch,armnn::Encoder<float> & outResult)87 void MatrixBatchVectorMultiplyAccumulate(armnn::Decoder<float>& matrix,
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 
VectorBatchVectorAssign(armnn::Decoder<float> & vector,uint32_t vSize,uint32_t nBatch,armnn::Encoder<float> & outBatchVector)113 void VectorBatchVectorAssign(armnn::Decoder<float>& vector,
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 
VectorBatchVectorCwiseProductAccumulate(armnn::Decoder<float> & vector,uint32_t vSize,armnn::Decoder<float> & batchVector,uint32_t nBatch,armnn::Encoder<float> & outResult)131 void VectorBatchVectorCwiseProductAccumulate(armnn::Decoder<float>& vector,
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 
VectorBatchVectorCwiseProduct(armnn::Decoder<float> & vector,uint32_t vSize,armnn::Decoder<float> & batchVector,uint32_t nBatch,armnn::Encoder<float> & outResult)152 void VectorBatchVectorCwiseProduct(armnn::Decoder<float>& vector,
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 
Sub1Vector(armnn::Decoder<float> & vector,uint32_t vSize,armnn::Encoder<float> & result)173 void Sub1Vector(armnn::Decoder<float>& vector,
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 
VectorVectorCwiseProduct(armnn::Decoder<float> & vector1,armnn::Decoder<float> & vector2,uint32_t vSize,armnn::Encoder<float> & outResult)187 void VectorVectorCwiseProduct(armnn::Decoder<float>& vector1,
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 
VectorVectorCwiseProductAccumulate(armnn::Decoder<float> & vector1,armnn::Decoder<float> & vector2,uint32_t vSize,armnn::Encoder<float> & outResult)204 void VectorVectorCwiseProductAccumulate(armnn::Decoder<float>& vector1,
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 
Clip(float f,float absLimit)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 
ClipVector(armnn::Decoder<float> & vector,uint32_t vSize,float absLimit,armnn::Encoder<float> & outResult)229 void ClipVector(armnn::Decoder<float>& vector,
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 
CopyVector(armnn::Decoder<float> & vector,uint32_t vSize,armnn::Encoder<float> & outResult)244 void CopyVector(armnn::Decoder<float>& vector,
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 
SetActivationParameters(uint32_t activation,armnn::ActivationFunction & outArmnnActivation,float & outA,float & outB)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 
AssignScopedTensorHandle(const armnn::ConstTensorHandle * ptr)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 }
308