blob: acbfe0cc90dcf71d96eb28e0f6735f6124b03ab0 [file] [log] [blame]
Aron Virginas-Tar735a4502019-06-26 15:02:47 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "TransposeConvolution2d.hpp"
7
8#include <DataLayoutIndexed.hpp>
9
10namespace armnn
11{
12
13using namespace armnnUtils;
14
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010015void TransposeConvolution2dImpl(const TransposeConvolution2dDescriptor& descriptor,
16 const TensorShape& inputShape,
17 Decoder<float>& inputDecoder,
18 const TensorShape& outputShape,
19 Encoder<float>& outputEncoder,
20 const TensorShape& weightsShape,
21 Decoder<float>& weightsDecoder,
22 Decoder<float>* biasesDecoder)
23{
24 if (descriptor.m_BiasEnabled && !biasesDecoder)
25 {
26 throw InvalidArgumentException("Biases enabled but no bias data provided");
27 }
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010028 const DataLayoutIndexed dataLayoutIndexed(descriptor.m_DataLayout);
Mike Kellya24d9c72019-08-13 10:06:25 +010029 const unsigned int channelsIndex = dataLayoutIndexed.GetChannelsIndex();
30 const unsigned int heightIndex = dataLayoutIndexed.GetHeightIndex();
31 const unsigned int widthIndex = dataLayoutIndexed.GetWidthIndex();
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010032
Mike Kellya24d9c72019-08-13 10:06:25 +010033 unsigned int numBatches = inputShape[0];
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010034
Mike Kellya24d9c72019-08-13 10:06:25 +010035 unsigned int inputWidth = inputShape[widthIndex];
36 unsigned int inputHeight = inputShape[heightIndex];
37 unsigned int inputDepth = inputShape[channelsIndex];
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010038
Mike Kellya24d9c72019-08-13 10:06:25 +010039 unsigned int weightsHeight = weightsShape[heightIndex];
40 unsigned int weightsWidth = weightsShape[widthIndex];
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010041
Mike Kellya24d9c72019-08-13 10:06:25 +010042 unsigned int outputHeight = outputShape[heightIndex];
43 unsigned int outputWidth = outputShape[widthIndex];
44 unsigned int outputDepth = outputShape[channelsIndex];
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010045
Mike Kellya24d9c72019-08-13 10:06:25 +010046 unsigned int paddingLeft = descriptor.m_PadLeft;
47 unsigned int paddingTop = descriptor.m_PadTop;
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010048
Mike Kellya24d9c72019-08-13 10:06:25 +010049 unsigned int strideX = descriptor.m_StrideX;
50 unsigned int strideY = descriptor.m_StrideY;
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010051
Mike Kellya24d9c72019-08-13 10:06:25 +010052 // Set the initial output values to be logically 0 otherwise the algorithm doesn't work.
53 for (unsigned int i = 0u; i < outputShape.GetNumElements(); ++i)
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010054 {
Mike Kellya24d9c72019-08-13 10:06:25 +010055 outputEncoder.Set(0.f);
56 ++outputEncoder;
57 }
58
59 for (unsigned int batch = 0u; batch < numBatches; ++batch)
60 {
61 for (unsigned int yInput = 0u; yInput < inputHeight; ++yInput)
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010062 {
Mike Kellya24d9c72019-08-13 10:06:25 +010063 for (unsigned int xInput = 0u; xInput < inputWidth; ++xInput)
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010064 {
Mike Kellya24d9c72019-08-13 10:06:25 +010065 unsigned int xOutputOrigin = xInput * strideX - paddingLeft;
66 unsigned int yOutputOrigin = yInput * strideY - paddingTop;
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010067
Mike Kellya24d9c72019-08-13 10:06:25 +010068 for (unsigned int dOutput = 0u; dOutput < outputDepth; ++dOutput)
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010069 {
Mike Kellya24d9c72019-08-13 10:06:25 +010070 for (unsigned int yWeights = 0u; yWeights < weightsHeight; ++yWeights)
Aron Virginas-Tar735a4502019-06-26 15:02:47 +010071 {
Aron Virginas-Tar0558ca42019-08-14 11:39:50 +010072 for (unsigned int xWeights = 0u; xWeights < weightsWidth; ++xWeights)
Mike Kellya24d9c72019-08-13 10:06:25 +010073 {
74 unsigned int yOutput = yOutputOrigin + yWeights;
75 unsigned int xOutput = xOutputOrigin + xWeights;
76
77 if (yOutput < outputHeight && xOutput< outputWidth)
78 {
79 for (unsigned int dInput = 0u; dInput < inputDepth; dInput++)
80 {
81 const unsigned int inputIndex =
82 dataLayoutIndexed.GetIndex(inputShape, batch, dInput, yInput, xInput);
83 inputDecoder[inputIndex];
84
85 const unsigned int weightsIndex =
86 dataLayoutIndexed.GetIndex(weightsShape, batch, dOutput, yWeights, xWeights);
87 weightsDecoder[weightsIndex];
88
89 const unsigned int outputIndex =
90 dataLayoutIndexed.GetIndex(outputShape, batch, dOutput, yOutput, xOutput);
91 outputEncoder[outputIndex];
92
93 float output = outputEncoder.Get();
94 output += inputDecoder.Get() * weightsDecoder.Get();
95
96 outputEncoder.Set(output);
97 }
98 }
99 }
100 }
101 }
102 }
103 }
104 }
105
106 // Apply bias (if enabled)
107 if (descriptor.m_BiasEnabled)
108 {
109 outputEncoder[0];
110 Decoder<float>& rBiasesDecoder = *biasesDecoder;
111
112 for (unsigned int batch = 0u; batch < numBatches; ++batch)
113 {
114 for (unsigned int dOutput = 0u; dOutput < outputDepth; ++dOutput)
115 {
116 rBiasesDecoder[dOutput];
117 for (unsigned int yOutput = 0u; yOutput < outputHeight; ++yOutput)
118 {
119 for (unsigned int xOutput = 0u; xOutput < outputWidth; ++xOutput)
120 {
121 const unsigned int outputIndex =
122 dataLayoutIndexed.GetIndex(outputShape, batch, dOutput, yOutput, xOutput);
123
124 outputEncoder[outputIndex];
125 outputEncoder.Set(outputEncoder.Get() + rBiasesDecoder.Get());
Aron Virginas-Tar735a4502019-06-26 15:02:47 +0100126 }
127 }
128 }
129 }
130 }
131}
132
Mike Kellya24d9c72019-08-13 10:06:25 +0100133} // namespace armnn