blob: 4cec02338a4db399b617ba5851b4e4ea2219a5a8 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5
6#include "RefNormalizationFloat32Workload.hpp"
7
8#include "RefWorkloadUtils.hpp"
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +01009#include "TensorBufferArrayView.hpp"
telsoa014fcda012018-03-09 14:13:49 +000010
11#include "Profiling.hpp"
12
13#include <armnn/Tensor.hpp>
14
15#include <boost/log/trivial.hpp>
16#include <boost/numeric/conversion/cast.hpp>
17
18namespace armnn
19{
20
telsoa01c577f2c2018-08-31 09:22:23 +010021// Helper function to compute "Within" normalization using Krichevsky 2012: Local Brightness Normalization.
telsoa014fcda012018-03-09 14:13:49 +000022static void NormalizeWithinUingLbr(const float* inputData,
23 float* outputData,
24 const TensorShape& tensorShape,
25 uint32_t norm_size,
26 float alpha,
27 float beta,
28 float kappa)
29{
30 const unsigned int batchSize = tensorShape[0];
31 const unsigned int depth = tensorShape[1];
32 const unsigned int rows = tensorShape[2];
33 const unsigned int cols = tensorShape[3];
34
35 int radius = boost::numeric_cast<int>(norm_size / 2u); /* Strong Assumption on rounding Mode */
36
37 for (unsigned int n = 0; n < batchSize; n++)
38 {
39 for (unsigned int c = 0; c < depth; c++)
40 {
41 for (unsigned int h = 0; h < rows; h++)
42 {
43 for (unsigned int w = 0; w < cols; w++)
44 {
45 float accumulated_scale = 0.0;
46 for (int y = -radius; y <= radius; y++)
47 {
48 for (int x = -radius; x <= radius; x++)
49 {
50 int i = boost::numeric_cast<int>(w) + x;
51 int j = boost::numeric_cast<int>(h) + y;
52
53 if ((i < 0) || (i >= boost::numeric_cast<int>(cols)))
54 {
55 continue;
56 }
57
58 if ((j < 0) || (j >= boost::numeric_cast<int>(rows)))
59 {
60 continue;
61 }
62
63 float inval = inputData[n * cols * rows * depth +
64 c * cols * rows +
65 boost::numeric_cast<unsigned int>(j) * cols +
66 boost::numeric_cast<unsigned int>(i)];
67
68 accumulated_scale += inval*inval;
69 }
70 }
71 outputData[n * cols * rows * depth +
72 c * cols * rows +
73 h * cols +
74 w] = inputData[n * cols * rows * depth +
75 c * cols * rows +
76 h * cols +
77 w] / (powf((kappa + (accumulated_scale * alpha)), beta));
78 }
79 }
80 }
81 }
82}
83
telsoa01c577f2c2018-08-31 09:22:23 +010084// Helper function to compute "Across" normalization using Krichevsky 2012: Local Brightness Normalization.
telsoa014fcda012018-03-09 14:13:49 +000085void NormalizeAcrossUingLbr(const float* inputData,
86 float* outputData,
87 const TensorShape& tensorShape,
88 uint32_t norm_size,
89 float alpha,
90 float beta,
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +010091 float kappa,
92 DataLayout dataLayout)
telsoa014fcda012018-03-09 14:13:49 +000093{
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +010094 TensorBufferArrayView<const float> input(tensorShape,
95 inputData,
96 dataLayout);
97 TensorBufferArrayView<float> output(tensorShape,
98 outputData,
99 dataLayout);
100
101 DataLayoutIndexed dataLayoutIndexed(dataLayout);
102
telsoa014fcda012018-03-09 14:13:49 +0000103 const unsigned int batchSize = tensorShape[0];
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100104 const unsigned int depth = tensorShape[dataLayoutIndexed.GetChannelsIndex()];
105 const unsigned int rows = tensorShape[dataLayoutIndexed.GetHeightIndex()];
106 const unsigned int cols = tensorShape[dataLayoutIndexed.GetWidthIndex()];
telsoa014fcda012018-03-09 14:13:49 +0000107
108 int radius = boost::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 = boost::numeric_cast<int>(c) + z;
122
123 if ((k < 0) || (k >= boost::numeric_cast<int>(depth)))
124 {
125 continue;
126 }
127
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100128 float inval = input.Get(n, boost::numeric_cast<unsigned int>(k), h, w);
telsoa014fcda012018-03-09 14:13:49 +0000129
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100130 accumulated_scale += inval * inval;
telsoa014fcda012018-03-09 14:13:49 +0000131 }
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100132
telsoa014fcda012018-03-09 14:13:49 +0000133 float scale = kappa + (accumulated_scale * alpha);
134 scale = powf(scale, -beta);
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100135
136 output.Get(n, c, h, w) = scale * input.Get(n, c, h, w);
telsoa014fcda012018-03-09 14:13:49 +0000137 }
138 }
139 }
140 }
141}
142
143void RefNormalizationFloat32Workload::Execute() const
144{
145 ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefNormalizationFloat32Workload_Execute");
146
147 const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
148
149 float* outputData = GetOutputTensorDataFloat(0, m_Data);
150 const float* inputData = GetInputTensorDataFloat(0, m_Data);
151
telsoa014fcda012018-03-09 14:13:49 +0000152 if (NormalizationAlgorithmMethod::LocalBrightness == m_Data.m_Parameters.m_NormMethodType)
153 {
154 if (NormalizationAlgorithmChannel::Within == m_Data.m_Parameters.m_NormChannelType)
155 {
156 NormalizeWithinUingLbr(inputData,
157 outputData,
158 inputInfo.GetShape(),
159 m_Data.m_Parameters.m_NormSize,
160 m_Data.m_Parameters.m_Alpha,
161 m_Data.m_Parameters.m_Beta,
162 m_Data.m_Parameters.m_K);
163 }
164 else if (NormalizationAlgorithmChannel::Across == m_Data.m_Parameters.m_NormChannelType)
165 {
166 NormalizeAcrossUingLbr(inputData,
167 outputData,
168 inputInfo.GetShape(),
169 m_Data.m_Parameters.m_NormSize,
170 m_Data.m_Parameters.m_Alpha,
171 m_Data.m_Parameters.m_Beta,
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100172 m_Data.m_Parameters.m_K,
173 m_Data.m_Parameters.m_DataLayout);
telsoa014fcda012018-03-09 14:13:49 +0000174 }
175 else
176 {
177 BOOST_LOG_TRIVIAL(warning) << "Illegal NORMALIZATION mode in normalization_f32";
178 return;
179 }
180 }
181 else
182 {
183 BOOST_LOG_TRIVIAL(warning) << "Lcr method (Jarret 2009: Local Contrast Normalization) not supported yet.";
184 return;
185 }
186}
187
188} //namespace armnn