// // Copyright © 2017 Arm Ltd. All rights reserved. // SPDX-License-Identifier: MIT // #include "RefNormalizationFloat32Workload.hpp" #include "RefWorkloadUtils.hpp" #include "TensorBufferArrayView.hpp" #include "Profiling.hpp" #include #include #include namespace armnn { // Helper function to compute "Within" normalization using Krichevsky 2012: Local Brightness Normalization. static void NormalizeWithinUingLbr(const float* inputData, float* outputData, const TensorShape& tensorShape, uint32_t norm_size, float alpha, float beta, float kappa) { const unsigned int batchSize = tensorShape[0]; const unsigned int depth = tensorShape[1]; const unsigned int rows = tensorShape[2]; const unsigned int cols = tensorShape[3]; int radius = boost::numeric_cast(norm_size / 2u); /* Strong Assumption on rounding Mode */ for (unsigned int n = 0; n < batchSize; n++) { for (unsigned int c = 0; c < depth; c++) { for (unsigned int h = 0; h < rows; h++) { for (unsigned int w = 0; w < cols; w++) { float accumulated_scale = 0.0; for (int y = -radius; y <= radius; y++) { for (int x = -radius; x <= radius; x++) { int i = boost::numeric_cast(w) + x; int j = boost::numeric_cast(h) + y; if ((i < 0) || (i >= boost::numeric_cast(cols))) { continue; } if ((j < 0) || (j >= boost::numeric_cast(rows))) { continue; } float inval = inputData[n * cols * rows * depth + c * cols * rows + boost::numeric_cast(j) * cols + boost::numeric_cast(i)]; accumulated_scale += inval*inval; } } outputData[n * cols * rows * depth + c * cols * rows + h * cols + w] = inputData[n * cols * rows * depth + c * cols * rows + h * cols + w] / (powf((kappa + (accumulated_scale * alpha)), beta)); } } } } } // Helper function to compute "Across" normalization using Krichevsky 2012: Local Brightness Normalization. void NormalizeAcrossUingLbr(const float* inputData, float* outputData, const TensorShape& tensorShape, uint32_t norm_size, float alpha, float beta, float kappa, DataLayout dataLayout) { TensorBufferArrayView input(tensorShape, inputData, dataLayout); TensorBufferArrayView output(tensorShape, outputData, dataLayout); DataLayoutIndexed dataLayoutIndexed(dataLayout); const unsigned int batchSize = tensorShape[0]; const unsigned int depth = tensorShape[dataLayoutIndexed.GetChannelsIndex()]; const unsigned int rows = tensorShape[dataLayoutIndexed.GetHeightIndex()]; const unsigned int cols = tensorShape[dataLayoutIndexed.GetWidthIndex()]; int radius = boost::numeric_cast(norm_size / 2u); /* Strong Assumption on rounding Mode */ for (unsigned int n = 0; n < batchSize; n++) { for (unsigned int c = 0; c < depth; c++) { for (unsigned int h = 0; h < rows; h++) { for (unsigned int w = 0; w < cols; w++) { float accumulated_scale = 0.0; for (int z = -radius; z <= radius; z++) { int k = boost::numeric_cast(c) + z; if ((k < 0) || (k >= boost::numeric_cast(depth))) { continue; } float inval = input.Get(n, boost::numeric_cast(k), h, w); accumulated_scale += inval * inval; } float scale = kappa + (accumulated_scale * alpha); scale = powf(scale, -beta); output.Get(n, c, h, w) = scale * input.Get(n, c, h, w); } } } } } void RefNormalizationFloat32Workload::Execute() const { ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefNormalizationFloat32Workload_Execute"); const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]); float* outputData = GetOutputTensorDataFloat(0, m_Data); const float* inputData = GetInputTensorDataFloat(0, m_Data); if (NormalizationAlgorithmMethod::LocalBrightness == m_Data.m_Parameters.m_NormMethodType) { if (NormalizationAlgorithmChannel::Within == m_Data.m_Parameters.m_NormChannelType) { NormalizeWithinUingLbr(inputData, outputData, inputInfo.GetShape(), m_Data.m_Parameters.m_NormSize, m_Data.m_Parameters.m_Alpha, m_Data.m_Parameters.m_Beta, m_Data.m_Parameters.m_K); } else if (NormalizationAlgorithmChannel::Across == m_Data.m_Parameters.m_NormChannelType) { NormalizeAcrossUingLbr(inputData, outputData, inputInfo.GetShape(), m_Data.m_Parameters.m_NormSize, m_Data.m_Parameters.m_Alpha, m_Data.m_Parameters.m_Beta, m_Data.m_Parameters.m_K, m_Data.m_Parameters.m_DataLayout); } else { BOOST_LOG_TRIVIAL(warning) << "Illegal NORMALIZATION mode in normalization_f32"; return; } } else { BOOST_LOG_TRIVIAL(warning) << "Lcr method (Jarret 2009: Local Contrast Normalization) not supported yet."; return; } } } //namespace armnn