ArmNN
 20.02
RefNormalizationWorkload.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 
8 #include <armnn/Logging.hpp>
9 #include <armnn/Tensor.hpp>
11 
12 #include <Profiling.hpp>
13 
14 #include <boost/numeric/conversion/cast.hpp>
15 
16 #include "RefWorkloadUtils.hpp"
17 #include "Decoders.hpp"
18 #include "Encoders.hpp"
19 
20 using namespace armnn;
21 using namespace armnnUtils;
22 
23 namespace
24 {
25 
26 // Helper function to compute "Within" normalization using Krichevsky 2012: Local Brightness Normalization.
27 void NormalizeWithinUingLbr(Decoder<float>& inputData,
28  Encoder<float>& outputData,
29  const TensorShape& tensorShape,
30  uint32_t norm_size,
31  float alpha,
32  float beta,
33  float kappa)
34 {
35  const unsigned int batchSize = tensorShape[0];
36  const unsigned int depth = tensorShape[1];
37  const unsigned int rows = tensorShape[2];
38  const unsigned int cols = tensorShape[3];
39 
40  int radius = boost::numeric_cast<int>(norm_size / 2u); /* Strong Assumption on rounding Mode */
41 
42  for (unsigned int n = 0; n < batchSize; n++)
43  {
44  for (unsigned int c = 0; c < depth; c++)
45  {
46  for (unsigned int h = 0; h < rows; h++)
47  {
48  for (unsigned int w = 0; w < cols; w++)
49  {
50  float accumulated_scale = 0.0;
51  for (int y = -radius; y <= radius; y++)
52  {
53  for (int x = -radius; x <= radius; x++)
54  {
55  int i = boost::numeric_cast<int>(w) + x;
56  int j = boost::numeric_cast<int>(h) + y;
57 
58  if ((i < 0) || (i >= boost::numeric_cast<int>(cols)))
59  {
60  continue;
61  }
62 
63  if ((j < 0) || (j >= boost::numeric_cast<int>(rows)))
64  {
65  continue;
66  }
67 
68  unsigned int inputIndex = n * cols * rows * depth +
69  c * cols * rows +
70  boost::numeric_cast<unsigned int>(j) * cols +
71  boost::numeric_cast<unsigned int>(i);
72  inputData[inputIndex];
73  float inval = inputData.Get();
74 
75  accumulated_scale += inval*inval;
76  }
77  }
78 
79  unsigned int index = n * cols * rows * depth +
80  c * cols * rows +
81  h * cols +
82  w;
83  inputData[index];
84  outputData[index];
85  outputData.Set(inputData.Get() / (powf((kappa + (accumulated_scale * alpha)), beta)));
86  }
87  }
88  }
89  }
90 }
91 
92 // Helper function to compute "Across" normalization using Krichevsky 2012: Local Brightness Normalization.
93 void NormalizeAcrossUingLbr(Decoder<float>& inputData,
94  Encoder<float>& outputData,
95  const TensorShape& tensorShape,
96  uint32_t norm_size,
97  float alpha,
98  float beta,
99  float kappa,
100  DataLayout dataLayout)
101 {
102  DataLayoutIndexed dataLayoutIndexed(dataLayout);
103 
104  const unsigned int batchSize = tensorShape[0];
105  const unsigned int depth = tensorShape[dataLayoutIndexed.GetChannelsIndex()];
106  const unsigned int rows = tensorShape[dataLayoutIndexed.GetHeightIndex()];
107  const unsigned int cols = tensorShape[dataLayoutIndexed.GetWidthIndex()];
108 
109  int radius = boost::numeric_cast<int>(norm_size / 2u); /* Strong Assumption on rounding Mode */
110 
111  for (unsigned int n = 0; n < batchSize; n++)
112  {
113  for (unsigned int c = 0; c < depth; c++)
114  {
115  for (unsigned int h = 0; h < rows; h++)
116  {
117  for (unsigned int w = 0; w < cols; w++)
118  {
119  float accumulated_scale = 0.0;
120  for (int z = -radius; z <= radius; z++)
121  {
122  int k = boost::numeric_cast<int>(c) + z;
123 
124  if ((k < 0) || (k >= boost::numeric_cast<int>(depth)))
125  {
126  continue;
127  }
128 
129  unsigned inputIndex = dataLayoutIndexed.GetIndex(tensorShape,
130  n,
131  boost::numeric_cast<unsigned int>(k),
132  h,
133  w);
134 
135  inputData[inputIndex];
136  float inval = inputData.Get();
137 
138  accumulated_scale += inval * inval;
139  }
140 
141  float scale = kappa + (accumulated_scale * alpha);
142  scale = powf(scale, -beta);
143 
144  unsigned index = dataLayoutIndexed.GetIndex(tensorShape, n, c, h, w);
145 
146  inputData[index];
147  outputData[index];
148  outputData.Set(scale * inputData.Get());
149  }
150  }
151  }
152  }
153 }
154 
155 } // Anonymous namespace
156 
157 namespace armnn
158 {
159 
161  const WorkloadInfo& info)
162  : BaseWorkload(descriptor, info)
163 {}
164 
166 {
167  ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefNormalizationWorkload_Execute");
168 
169  const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
170 
171  auto inputDecoder = MakeDecoder<float>(inputInfo, m_Data.m_Inputs[0]->Map());
172  auto outputEncoder = MakeEncoder<float>(inputInfo, m_Data.m_Outputs[0]->Map());
173 
175  {
177  {
178  NormalizeWithinUingLbr(*inputDecoder,
179  *outputEncoder,
180  inputInfo.GetShape(),
185  }
187  {
188  NormalizeAcrossUingLbr(*inputDecoder,
189  *outputEncoder,
190  inputInfo.GetShape(),
196  }
197  else
198  {
199  ARMNN_LOG(warning) << "Illegal NORMALIZATION mode in normalization_f32";
200  return;
201  }
202  }
203  else
204  {
205  ARMNN_LOG(warning) << "Lcr method (Jarret 2009: Local Contrast Normalization) not supported yet.";
206  return;
207  }
208 }
209 
210 } // namespace armnn
DataLayout
Definition: Types.hpp:49
float m_K
Kappa value used for the across channel normalization equation.
CPU Execution: Reference C++ kernels.
float m_Alpha
Alpha value for the normalization equation.
const NormalizationQueueDescriptor m_Data
Definition: Workload.hpp:46
virtual void Set(IType right)=0
const TensorInfo & GetTensorInfo(const ITensorHandle *tensorHandle)
float32 helpers
#define ARMNN_LOG(severity)
Definition: Logging.hpp:163
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
Copyright (c) 2020 ARM Limited.
#define ARMNN_SCOPED_PROFILING_EVENT(backendId, name)
Definition: Profiling.hpp:169
NormalizationAlgorithmMethod m_NormMethodType
Normalization method algorithm to use (LocalBrightness, LocalContrast).
virtual IType Get() const =0
RefNormalizationWorkload(const NormalizationQueueDescriptor &descriptor, const WorkloadInfo &info)
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout...
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
Definition: NumericCast.hpp:33
NormalizationAlgorithmChannel m_NormChannelType
Normalization channel algorithm to use (Across, Within).
std::vector< ITensorHandle * > m_Outputs
Contains information about inputs and outputs to a layer.
std::vector< ITensorHandle * > m_Inputs
virtual void Execute() const override
Krichevsky 2012: Local Brightness Normalization.
float m_Beta
Beta value for the normalization equation.
uint32_t m_NormSize
Depth radius value.