ArmNN
 22.05.01
PermuteDepthwiseConv2dWeights.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include "Optimization.hpp"
8 #include "NetworkUtils.hpp"
9 
10 #include <armnnUtils/Permute.hpp>
11 
12 #include <fmt/format.h>
13 
14 namespace armnn
15 {
16 namespace optimizations
17 {
18 
20 {
21 public:
22 
23  void Run(Graph& graph, Layer& layer) const
24  {
26  {
27  AddPermuteLayer(graph, PolymorphicDowncast<DepthwiseConvolution2dLayer*>(&layer));
28  }
29  }
30 
31 protected:
34 
35 private:
36  /// ArmNN format for weights for depthwise is [1, H, W, C] independently of the input/output layout
37  ///
38  /// ACL format for weights for depthwise is:
39  /// - [1, H, W, C] for [N, H, W, C] input/output layout (matches with ArmNN)
40  /// - [1, C, H, W] for [N, C, H, W] input/output layout
41  ///
42  /// Therefore ArmNN weights have to be permuted when input/output layout is [N, C, H, W] to pass them to ACL.
43  static void AddPermuteLayer(Graph& graph, DepthwiseConvolution2dLayer* layer)
44  {
46  TensorInfo weightInfo = layer->GetInputSlot(1).GetConnectedOutputSlot()->GetTensorInfo();
48  {
49  // No permutation required. Input and weights data layouts are the same.
50  return;
51  }
53  {
54  // Weights permutation required. Weights [N,H,W,C] and input [N,C,H,W] data layouts are different.
55  // [ 1, H, W, I*M] --> [ 1, I * M, H, W ]
56  PermutationVector permutationVector = { 0, 2, 3, 1 };
57  TensorInfo weightsPermuted = armnnUtils::Permuted(weightInfo, permutationVector);
58 
59  // Inserts NewLayer so layers don't need to be re-sorted.
60  PermuteLayer* permuteLayer =
61  graph.InsertNewLayer<PermuteLayer>(layer->GetInputSlot(1),
62  PermuteDescriptor(permutationVector),
63  "permute_layer");
64  permuteLayer->GetOutputSlot().SetTensorInfo(weightsPermuted);
65 
66  // Assign Permute BackendId to be the same as the Depthwise Conv2d BackendId.
67  // Needed as backends have already been assigned at this stage.
68  permuteLayer->SetBackendId(layer->GetBackendId());
69  }
70  else
71  {
72  throw InvalidArgumentException(fmt::format("Unknown data layout for tensor info conversion: {}",
74  }
75  }
76 };
77 
79 
80 } // namespace optimizations
81 } // namespace armnn
constexpr const char * GetDataLayoutName(DataLayout dataLayout)
Definition: TypesUtils.hpp:222
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
This layer represents a depthwise convolution 2d operation.
Copyright (c) 2021 ARM Limited and Contributors.
const Parameters & GetParameters() const override
If the layer has a descriptor return it.
void SetBackendId(const BackendId &id)
Definition: Layer.hpp:276
This layer represents a permutation operation.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:322
LayerType GetType() const override
Returns the armnn::LayerType of this layer.
Definition: Layer.hpp:271
const OutputSlot * GetConnectedOutputSlot() const
Definition: Layer.hpp:56
const BackendId & GetBackendId() const
Definition: Layer.hpp:275
void SetTensorInfo(const TensorInfo &tensorInfo) override
Definition: Layer.cpp:87
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:324
LayerT * InsertNewLayer(InputSlot &insertBefore, Args &&... args)
Inserts a new layer between the output slot currently connected to insertBefore and insertBefore itse...
Definition: Graph.hpp:440
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:92
armnn::TensorShape Permuted(const armnn::TensorShape &srcShape, const armnn::PermutationVector &mappings)
Definition: Permute.cpp:98
A PermuteDescriptor for the PermuteLayer.