ArmNN
 25.02
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DepthToSpace.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2019, 2024 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "DepthToSpace.hpp"
7 
9 #include <armnnUtils/Permute.hpp>
10 
11 using namespace armnnUtils;
12 
13 namespace armnn
14 {
15 
16 void DepthToSpace(const TensorInfo& inputInfo,
17  const DepthToSpaceDescriptor& descriptor,
18  const void* inputData,
19  void* outputData,
20  unsigned int dataTypeSize)
21 {
22  const unsigned int blockSize = descriptor.m_BlockSize;
23 
24  const TensorShape& inputShape = inputInfo.GetShape();
25  const unsigned int batches = inputShape[0];
26 
27  armnnUtils::DataLayoutIndexed dataLayoutIndexed(descriptor.m_DataLayout);
28  const unsigned int inDepth = inputShape[dataLayoutIndexed.GetChannelsIndex()];
29  const unsigned int inHeight = inputShape[dataLayoutIndexed.GetHeightIndex()];
30  const unsigned int inWidth = inputShape[dataLayoutIndexed.GetWidthIndex()];
31 
32  const unsigned int outDepth = inDepth / (blockSize * blockSize);
33 
34  // The 4D input data can be interpreted as 6D (implicitly reshaped) as follows:
35  //
36  // [batch, block size, block size, inDepth, inHeight, inWidth] for NCHW and
37  // [batch, inHeight, inWidth, blockSize, blockSize, outDepth] for NHWC.
38  //
39  // DepthToSpace can then be implemented as a permutation in 6D resulting in
40  // the following shapes:
41  //
42  // [batch, outDepth, inHeight, blockSize, inWidth, blockSize] for NCHW and
43  // [batch, inHeight, blockSize, inWidth, blockSize, outDepth] for NHWC.
44  //
45  // NOTE:
46  // Since 6D tensors are not currently supported, in practice we need to handle each
47  // batch separately and execute 5D permutations
48 
49  TensorShape permDestShape;
50  PermutationVector permVector{};
51  if (descriptor.m_DataLayout == DataLayout::NCHW)
52  {
53  permDestShape = TensorShape({ outDepth, inHeight, blockSize, inWidth, blockSize });
54  permVector = { 2, 4, 0, 1, 3 };
55  }
56  else
57  {
58  permDestShape = TensorShape({ inHeight, blockSize, inWidth, blockSize, outDepth });
59  permVector = { 0, 2, 1, 3, 4 };
60  }
61 
62  const unsigned int numElementsPerBatch = inputShape.GetNumElements() / batches;
63 
64  for (unsigned int batchIndex = 0u; batchIndex < batches; ++batchIndex)
65  {
66  const uintptr_t batchDataOffset = batchIndex * (numElementsPerBatch * dataTypeSize);
67 
68  armnnUtils::Permute(permDestShape,
69  permVector,
70  static_cast<const void*>(reinterpret_cast<const uint8_t*>(inputData) + batchDataOffset),
71  static_cast<void*>(reinterpret_cast<uint8_t*>(outputData) + batchDataOffset),
72  dataTypeSize);
73  }
74 }
75 
76 } // namespace armnn
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
unsigned int GetNumElements() const
Function that calculates the tensor elements by multiplying all dimension size which are Specified.
Definition: Tensor.cpp:181
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout.
unsigned int GetWidthIndex() const
unsigned int GetHeightIndex() const
unsigned int GetChannelsIndex() const
Copyright (c) 2021 ARM Limited and Contributors.
void DepthToSpace(const TensorInfo &inputInfo, const DepthToSpaceDescriptor &descriptor, const void *inputData, void *outputData, unsigned int dataTypeSize)
void Permute(const armnn::TensorShape &dstShape, const armnn::PermutationVector &mappings, const void *src, void *dst, size_t dataTypeSize)
Definition: Permute.cpp:164
A SpaceToDepthDescriptor for the SpaceToDepthLayer.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
unsigned int m_BlockSize
Scalar specifying the input block size. It must be >= 1.