blob: 3a2f2b965853871bc66d902f2aad8b14a5544af8 [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
Matteo Martincigh21350152018-11-28 16:22:22 +000018using namespace armnnUtils;
19
telsoa014fcda012018-03-09 14:13:49 +000020namespace armnn
21{
22
telsoa01c577f2c2018-08-31 09:22:23 +010023// Helper function to compute "Within" normalization using Krichevsky 2012: Local Brightness Normalization.
telsoa014fcda012018-03-09 14:13:49 +000024static void NormalizeWithinUingLbr(const float* inputData,
25 float* outputData,
26 const TensorShape& tensorShape,
27 uint32_t norm_size,
28 float alpha,
29 float beta,
30 float kappa)
31{
32 const unsigned int batchSize = tensorShape[0];
33 const unsigned int depth = tensorShape[1];
34 const unsigned int rows = tensorShape[2];
35 const unsigned int cols = tensorShape[3];
36
37 int radius = boost::numeric_cast<int>(norm_size / 2u); /* Strong Assumption on rounding Mode */
38
39 for (unsigned int n = 0; n < batchSize; n++)
40 {
41 for (unsigned int c = 0; c < depth; c++)
42 {
43 for (unsigned int h = 0; h < rows; h++)
44 {
45 for (unsigned int w = 0; w < cols; w++)
46 {
47 float accumulated_scale = 0.0;
48 for (int y = -radius; y <= radius; y++)
49 {
50 for (int x = -radius; x <= radius; x++)
51 {
52 int i = boost::numeric_cast<int>(w) + x;
53 int j = boost::numeric_cast<int>(h) + y;
54
55 if ((i < 0) || (i >= boost::numeric_cast<int>(cols)))
56 {
57 continue;
58 }
59
60 if ((j < 0) || (j >= boost::numeric_cast<int>(rows)))
61 {
62 continue;
63 }
64
65 float inval = inputData[n * cols * rows * depth +
66 c * cols * rows +
67 boost::numeric_cast<unsigned int>(j) * cols +
68 boost::numeric_cast<unsigned int>(i)];
69
70 accumulated_scale += inval*inval;
71 }
72 }
73 outputData[n * cols * rows * depth +
74 c * cols * rows +
75 h * cols +
76 w] = inputData[n * cols * rows * depth +
77 c * cols * rows +
78 h * cols +
79 w] / (powf((kappa + (accumulated_scale * alpha)), beta));
80 }
81 }
82 }
83 }
84}
85
telsoa01c577f2c2018-08-31 09:22:23 +010086// Helper function to compute "Across" normalization using Krichevsky 2012: Local Brightness Normalization.
telsoa014fcda012018-03-09 14:13:49 +000087void NormalizeAcrossUingLbr(const float* inputData,
88 float* outputData,
89 const TensorShape& tensorShape,
90 uint32_t norm_size,
91 float alpha,
92 float beta,
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +010093 float kappa,
94 DataLayout dataLayout)
telsoa014fcda012018-03-09 14:13:49 +000095{
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +010096 TensorBufferArrayView<const float> input(tensorShape,
97 inputData,
98 dataLayout);
99 TensorBufferArrayView<float> output(tensorShape,
100 outputData,
101 dataLayout);
102
103 DataLayoutIndexed dataLayoutIndexed(dataLayout);
104
telsoa014fcda012018-03-09 14:13:49 +0000105 const unsigned int batchSize = tensorShape[0];
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100106 const unsigned int depth = tensorShape[dataLayoutIndexed.GetChannelsIndex()];
107 const unsigned int rows = tensorShape[dataLayoutIndexed.GetHeightIndex()];
108 const unsigned int cols = tensorShape[dataLayoutIndexed.GetWidthIndex()];
telsoa014fcda012018-03-09 14:13:49 +0000109
110 int radius = boost::numeric_cast<int>(norm_size / 2u); /* Strong Assumption on rounding Mode */
111
112 for (unsigned int n = 0; n < batchSize; n++)
113 {
114 for (unsigned int c = 0; c < depth; c++)
115 {
116 for (unsigned int h = 0; h < rows; h++)
117 {
118 for (unsigned int w = 0; w < cols; w++)
119 {
120 float accumulated_scale = 0.0;
121 for (int z = -radius; z <= radius; z++)
122 {
123 int k = boost::numeric_cast<int>(c) + z;
124
125 if ((k < 0) || (k >= boost::numeric_cast<int>(depth)))
126 {
127 continue;
128 }
129
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100130 float inval = input.Get(n, boost::numeric_cast<unsigned int>(k), h, w);
telsoa014fcda012018-03-09 14:13:49 +0000131
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100132 accumulated_scale += inval * inval;
telsoa014fcda012018-03-09 14:13:49 +0000133 }
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100134
telsoa014fcda012018-03-09 14:13:49 +0000135 float scale = kappa + (accumulated_scale * alpha);
136 scale = powf(scale, -beta);
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100137
138 output.Get(n, c, h, w) = scale * input.Get(n, c, h, w);
telsoa014fcda012018-03-09 14:13:49 +0000139 }
140 }
141 }
142 }
143}
144
145void RefNormalizationFloat32Workload::Execute() const
146{
147 ARMNN_SCOPED_PROFILING_EVENT(Compute::CpuRef, "RefNormalizationFloat32Workload_Execute");
148
149 const TensorInfo& inputInfo = GetTensorInfo(m_Data.m_Inputs[0]);
150
151 float* outputData = GetOutputTensorDataFloat(0, m_Data);
152 const float* inputData = GetInputTensorDataFloat(0, m_Data);
153
telsoa014fcda012018-03-09 14:13:49 +0000154 if (NormalizationAlgorithmMethod::LocalBrightness == m_Data.m_Parameters.m_NormMethodType)
155 {
156 if (NormalizationAlgorithmChannel::Within == m_Data.m_Parameters.m_NormChannelType)
157 {
158 NormalizeWithinUingLbr(inputData,
159 outputData,
160 inputInfo.GetShape(),
161 m_Data.m_Parameters.m_NormSize,
162 m_Data.m_Parameters.m_Alpha,
163 m_Data.m_Parameters.m_Beta,
164 m_Data.m_Parameters.m_K);
165 }
166 else if (NormalizationAlgorithmChannel::Across == m_Data.m_Parameters.m_NormChannelType)
167 {
168 NormalizeAcrossUingLbr(inputData,
169 outputData,
170 inputInfo.GetShape(),
171 m_Data.m_Parameters.m_NormSize,
172 m_Data.m_Parameters.m_Alpha,
173 m_Data.m_Parameters.m_Beta,
Matteo Martincigh8e6f92d2018-10-18 08:45:39 +0100174 m_Data.m_Parameters.m_K,
175 m_Data.m_Parameters.m_DataLayout);
telsoa014fcda012018-03-09 14:13:49 +0000176 }
177 else
178 {
179 BOOST_LOG_TRIVIAL(warning) << "Illegal NORMALIZATION mode in normalization_f32";
180 return;
181 }
182 }
183 else
184 {
185 BOOST_LOG_TRIVIAL(warning) << "Lcr method (Jarret 2009: Local Contrast Normalization) not supported yet.";
186 return;
187 }
188}
189
190} //namespace armnn