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