• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "SpaceToDepthEndToEndTestImpl.hpp"
7 #include "ResolveType.hpp"
8 #include "EndToEndTestImpl.hpp"
9 
10 #include <armnn/INetwork.hpp>
11 
12 #include <armnnUtils/Permute.hpp>
13 #include <armnnUtils/DataLayoutIndexed.hpp>
14 
15 #include <armnnTestUtils/DataLayoutUtils.hpp>
16 
17 #include <TestUtils.hpp>
18 
19 #include <doctest/doctest.h>
20 
21 namespace
22 {
23 
24 template<typename armnn::DataType DataType>
CreateSpaceToDepthNetwork(const armnn::TensorShape & inputShape,const armnn::TensorShape & outputShape,const armnn::DataLayout dataLayout,unsigned int blockSize,const float qScale=1.0f,const int32_t qOffset=0)25 armnn::INetworkPtr CreateSpaceToDepthNetwork(const armnn::TensorShape& inputShape,
26                                              const armnn::TensorShape& outputShape,
27                                              const armnn::DataLayout dataLayout,
28                                              unsigned int blockSize,
29                                              const float qScale = 1.0f,
30                                              const int32_t qOffset = 0)
31 {
32     using namespace armnn;
33 
34     // Builds up the structure of the network.
35     INetworkPtr net(INetwork::Create());
36 
37     TensorInfo inputTensorInfo(inputShape, DataType, qScale, qOffset, true);
38 
39     armnnUtils::DataLayoutIndexed dimensionIndices(dataLayout);
40     if (inputShape[dimensionIndices.GetHeightIndex()] % blockSize!=0
41         || inputShape[dimensionIndices.GetWidthIndex()] % blockSize!=0)
42     {
43         throw InvalidArgumentException("Input shape must be divisible by block size in all spatial dimensions");
44     }
45 
46     SpaceToDepthDescriptor spaceToDepthDesc;
47     spaceToDepthDesc.m_BlockSize = blockSize;
48     spaceToDepthDesc.m_DataLayout = dataLayout;
49 
50     IConnectableLayer* SpaceToDepth = net->AddSpaceToDepthLayer(spaceToDepthDesc, "SpaceToDepth");
51     IConnectableLayer* input        = net->AddInputLayer(0, "input");
52     Connect(input, SpaceToDepth, inputTensorInfo, 0, 0);
53 
54     TensorInfo outputTensorInfo(outputShape, DataType, qScale, qOffset);
55     IConnectableLayer* output = net->AddOutputLayer(0, "output");
56     Connect(SpaceToDepth, output, outputTensorInfo, 0, 0);
57 
58     return net;
59 }
60 
SpaceToDepthEndToEnd(const std::vector<armnn::BackendId> & backends,const armnn::DataLayout & dataLayout,armnn::TensorInfo & inputTensorInfo,armnn::TensorInfo & outputTensorInfo,std::vector<float> & inputData,std::vector<float> & expectedOutputData,const unsigned int blockSize)61 void SpaceToDepthEndToEnd(const std::vector<armnn::BackendId>& backends,
62                           const armnn::DataLayout& dataLayout,
63                           armnn::TensorInfo& inputTensorInfo,
64                           armnn::TensorInfo& outputTensorInfo,
65                           std::vector<float>& inputData,
66                           std::vector<float>& expectedOutputData,
67                           const unsigned int blockSize)
68 {
69     using namespace armnn;
70 
71     if (dataLayout == DataLayout::NCHW)
72     {
73         PermuteTensorNhwcToNchw<float>(inputTensorInfo, inputData);
74         PermuteTensorNhwcToNchw<float>(outputTensorInfo, expectedOutputData);
75     }
76 
77     // Builds up the structure of the network
78     INetworkPtr net = CreateSpaceToDepthNetwork<DataType::Float32>(
79             inputTensorInfo.GetShape(),
80             outputTensorInfo.GetShape(),
81             dataLayout,
82             blockSize);
83 
84     CHECK(net);
85 
86     std::map<int, std::vector<float>> inputTensorData = { { 0, inputData } };
87     std::map<int, std::vector<float>> expectedOutputTensorData = { { 0, expectedOutputData } };
88 
89     EndToEndLayerTestImpl<DataType::Float32, DataType::Float32>(
90             move(net),
91             inputTensorData,
92             expectedOutputTensorData,
93             backends);
94 }
95 
96 } // anonymous namespace
97 
SpaceToDepthNhwcEndToEndTest1(const std::vector<armnn::BackendId> & defaultBackends)98 void SpaceToDepthNhwcEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
99 {
100     using namespace armnn;
101 
102     const unsigned int blockSize = 2;
103 
104     TensorShape inputShape{1, 2, 2, 1};
105     TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
106 
107     TensorShape outputShape{1, 1, 1, 4};
108     TensorInfo outputTensorInfo(outputShape, DataType::Float32);
109 
110     std::vector<float> inputData = std::vector<float>(
111     {
112         1.0f, 2.0f, 3.0f, 4.0f
113     });
114 
115     std::vector<float> expectedOutputData = std::vector<float>(
116     {
117         1.0f, 2.0f, 3.0f, 4.0f
118     });
119 
120     SpaceToDepthEndToEnd(defaultBackends,
121                          DataLayout::NHWC,
122                          inputTensorInfo,
123                          outputTensorInfo,
124                          inputData,
125                          expectedOutputData,
126                          blockSize);
127 }
128 
SpaceToDepthNchwEndToEndTest1(const std::vector<armnn::BackendId> & defaultBackends)129 void SpaceToDepthNchwEndToEndTest1(const std::vector<armnn::BackendId>& defaultBackends)
130 {
131     using namespace armnn;
132 
133     const unsigned int blockSize = 2;
134 
135     TensorShape inputShape{1, 2, 2, 1};
136     TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
137 
138     TensorShape outputShape{1, 1, 1, 4};
139     TensorInfo outputTensorInfo(outputShape, DataType::Float32);
140 
141     std::vector<float> inputData = std::vector<float>(
142     {
143         1.0f, 2.0f, 3.0f, 4.0f
144     });
145 
146     std::vector<float> expectedOutputData = std::vector<float>(
147     {
148         1.0f, 2.0f, 3.0f, 4.0f
149     });
150 
151     SpaceToDepthEndToEnd(defaultBackends,
152                          DataLayout::NCHW,
153                          inputTensorInfo,
154                          outputTensorInfo,
155                          inputData,
156                          expectedOutputData,
157                          blockSize);
158 }
159 
SpaceToDepthNhwcEndToEndTest2(const std::vector<armnn::BackendId> & defaultBackends)160 void SpaceToDepthNhwcEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
161 {
162     using namespace armnn;
163 
164     const unsigned int blockSize = 2;
165 
166     TensorShape inputShape{1, 2, 2, 2};
167     TensorShape outputShape{1, 1, 1, 8};
168 
169     TensorInfo outputTensorInfo(outputShape, DataType::Float32);
170     TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
171 
172     std::vector<float> inputData = std::vector<float>(
173     {
174         1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
175     });
176 
177     std::vector<float> expectedOutputData = std::vector<float>(
178     {
179         1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
180     });
181 
182     SpaceToDepthEndToEnd(defaultBackends,
183                          DataLayout::NHWC,
184                          inputTensorInfo,
185                          outputTensorInfo,
186                          inputData,
187                          expectedOutputData,
188                          blockSize);
189 }
190 
SpaceToDepthNchwEndToEndTest2(const std::vector<armnn::BackendId> & defaultBackends)191 void SpaceToDepthNchwEndToEndTest2(const std::vector<armnn::BackendId>& defaultBackends)
192 {
193     using namespace armnn;
194 
195     const unsigned int blockSize = 2;
196 
197     TensorShape inputShape{1, 2, 2, 2};
198     TensorShape outputShape{1, 1, 1, 8};
199 
200     TensorInfo inputTensorInfo(inputShape, DataType::Float32, 0.0f, 0, true);
201     TensorInfo outputTensorInfo(outputShape, DataType::Float32);
202 
203 
204     std::vector<float> inputData = std::vector<float>(
205     {
206         1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
207     });
208 
209     std::vector<float> expectedOutputData = std::vector<float>(
210     {
211         1.4f, 2.3f, 3.2f, 4.1f, 5.4f, 6.3f, 7.2f, 8.1f
212     });
213 
214     SpaceToDepthEndToEnd(defaultBackends,
215                          DataLayout::NCHW,
216                          inputTensorInfo,
217                          outputTensorInfo,
218                          inputData,
219                          expectedOutputData,
220                          blockSize);
221 }
222