26 case PoolingAlgorithm::Max:
28 return std::numeric_limits<float>::lowest();
30 case PoolingAlgorithm::Average:
31 case PoolingAlgorithm::L2:
42 using Accumulator = std::function<void(
float & accu,
float value)>;
48 case PoolingAlgorithm::Max:
50 return [](
float & accu,
float value) {
57 case PoolingAlgorithm::Average:
59 return [](
float & accu,
float value) {
64 case PoolingAlgorithm::L2:
66 return [](
float & accu,
float value) {
67 accu += (value*value);
78 using Executor = std::function<void(
float & accumulated,
float kernelSize)>;
84 case PoolingAlgorithm::Max:
86 return [](
float & ,
float ) {};
89 case PoolingAlgorithm::Average:
91 return [](
float & accumulated,
float kernelSize) {
92 accumulated /= kernelSize;
96 case PoolingAlgorithm::L2:
98 return [](
float & accumulated,
float kernelSize) {
99 accumulated = sqrtf(accumulated / kernelSize);
110 bool OnPaddingOnly(
int start,
int end,
int maxRange)
112 if (end <= 0 || start > maxRange)
123 bool ClampRange(
int & start,
int & end,
int maxRange)
125 if (start < 0 || end > maxRange)
127 start = std::min(std::max(start, 0), maxRange);
128 end = std::min(std::max(end, 0), maxRange);
137 int CalculateIndex(
int channels,
int depth,
int height,
int width,
138 int n,
int c,
int z,
int y,
int x,
144 int outputIndex = n * depth * height * width * channels +
145 z * height * width * channels +
146 y * width * channels +
153 int outputIndex = n * channels * depth * height * width +
154 c * depth * height * width +
186 const int batchSize = armnn::numeric_cast<int>(outputInfo.
GetShape()[0]);
187 const int channels = armnn::numeric_cast<int>(outputInfo.
GetShape()[channelsIndex]);
189 const int depthOutput = armnn::numeric_cast<int>(outputInfo.
GetShape()[depthIndex]);
190 const int heightOutput = armnn::numeric_cast<int>(outputInfo.
GetShape()[heightIndex]);
191 const int widthOutput = armnn::numeric_cast<int>(outputInfo.
GetShape()[widthIndex]);
193 const int depthInput = armnn::numeric_cast<int>(inputInfo.
GetShape()[depthIndex]);
194 const int heightInput = armnn::numeric_cast<int>(inputInfo.
GetShape()[heightIndex]);
195 const int widthInput = armnn::numeric_cast<int>(inputInfo.
GetShape()[widthIndex]);
197 const int padLeft = armnn::numeric_cast<int>(params.
m_PadLeft);
198 const int padRight = armnn::numeric_cast<int>(params.
m_PadRight);
199 const int padTop = armnn::numeric_cast<int>(params.
m_PadTop);
200 const int padBottom = armnn::numeric_cast<int>(params.
m_PadBottom);
201 const int padFront = armnn::numeric_cast<int>(params.
m_PadFront);
202 const int padBack = armnn::numeric_cast<int>(params.
m_PadBack);
204 const int strideX = armnn::numeric_cast<int>(params.
m_StrideX);
205 const int strideY = armnn::numeric_cast<int>(params.
m_StrideY);
206 const int strideZ = armnn::numeric_cast<int>(params.
m_StrideZ);
208 const int poolHeight = armnn::numeric_cast<int>(params.
m_PoolHeight);
209 const int poolWidth = armnn::numeric_cast<int>(params.
m_PoolWidth);
210 const int poolDepth = armnn::numeric_cast<int>(params.
m_PoolDepth);
212 float defaultInitializer = DefaultInitializer(params.
m_PoolType);
213 Accumulator accumulate = GetAccumulator(params.
m_PoolType);
214 Executor execute = GetExecutor(params.
m_PoolType);
226 for (
int n = 0; n < batchSize; n++)
228 for (
int c = 0; c < channels; c++)
230 for (
int zOutput = 0; zOutput < depthOutput; zOutput++)
233 int dstart = (zOutput * strideZ) - padFront;
234 int dend = dstart + poolDepth;
237 dend = std::min(dend, depthInput + padBack);
239 int depth = dend - dstart;
240 bool dclamped = ClampRange(dstart, dend, depthInput);
241 int depthClamped = dend - dstart;
243 for (
int yOutput = 0; yOutput < heightOutput; yOutput++)
245 int hstart = (yOutput * strideY) - padTop;
246 int hend = hstart + poolHeight;
249 hend = std::min(hend, heightInput + padBottom);
251 int height = hend - hstart;
252 bool hclamped = ClampRange(hstart, hend, heightInput);
253 int heightClamped = hend - hstart;
255 for (
int xOutput = 0; xOutput < widthOutput; xOutput++)
257 int wstart = (xOutput * strideX) - padLeft;
258 int wend = wstart + poolWidth;
261 wend = std::min(wend, widthInput + padRight);
263 int width = wend - wstart;
264 bool wclamped = ClampRange(wstart, wend, widthInput);
265 int widthClamped = wend - wstart;
267 float result = defaultInitializer;
268 float poolAreaSize = armnn::numeric_cast<float>(depth * height * width);
275 if (OnPaddingOnly(dstart, dend, depthInput) ||
276 OnPaddingOnly(hstart, hend, heightInput) ||
277 OnPaddingOnly(wstart, wend, widthInput))
281 int outputIndex = CalculateIndex(channels, depthOutput, heightOutput, widthOutput,
282 n, c, zOutput, yOutput, xOutput, dataLayout);
284 rOutputEncoder[
static_cast<unsigned int>(outputIndex)];
285 rOutputEncoder.
Set(result);
290 bool clamped = (dclamped | hclamped | wclamped);
296 poolAreaSize = armnn::numeric_cast<float>(depthClamped * heightClamped * widthClamped);
299 for (
auto zInput = dstart; zInput < dend; zInput++)
301 for (
auto yInput = hstart; yInput < hend; yInput++)
303 for (
auto xInput = wstart; xInput < wend; xInput++)
306 int inputIndex = CalculateIndex(channels, depthInput, heightInput, widthInput,
307 n, c, zInput, yInput, xInput, dataLayout);
309 accumulate(result, decodedInputVec[
static_cast<unsigned int>(inputIndex)]);
314 execute(result, poolAreaSize);
316 int outputIndex = CalculateIndex(channels, depthOutput, heightOutput, widthOutput,
317 n, c, zOutput, yOutput, xOutput, dataLayout);
319 rOutputEncoder[
static_cast<unsigned int>(outputIndex)];
320 rOutputEncoder.
Set(result);