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