2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
5 #include "DepthwiseConvolution2dLayer.hpp"
7 #include "LayerCloneBase.hpp"
9 #include <armnn/TypesUtils.hpp>
10 #include <backends/CpuTensorHandle.hpp>
11 #include <backends/WorkloadFactory.hpp>
16 DepthwiseConvolution2dLayer::DepthwiseConvolution2dLayer(const DepthwiseConvolution2dDescriptor& param,
18 : LayerWithParameters(1, 1, LayerType::DepthwiseConvolution2d, param, name)
22 std::unique_ptr<IWorkload> DepthwiseConvolution2dLayer::CreateWorkload(const Graph& graph,
23 const IWorkloadFactory& factory) const
25 DepthwiseConvolution2dQueueDescriptor descriptor;
27 descriptor.m_Weight = m_Weight.get();
28 if (m_Param.m_BiasEnabled)
30 descriptor.m_Bias = m_Bias.get();
32 return factory.CreateDepthwiseConvolution2d(descriptor, PrepInfoAndDesc(descriptor, graph));
35 DepthwiseConvolution2dLayer* DepthwiseConvolution2dLayer::Clone(Graph& graph) const
37 auto layer = CloneBase<DepthwiseConvolution2dLayer>(graph, m_Param, GetName());
38 layer->m_Weight = m_Weight ? std::make_unique<ScopedCpuTensorHandle>(*m_Weight) : nullptr;
40 if (layer->m_Param.m_BiasEnabled)
42 layer->m_Bias = m_Bias ? std::make_unique<ScopedCpuTensorHandle>(*m_Bias) : nullptr;
45 return std::move(layer);
48 void DepthwiseConvolution2dLayer::ValidateTensorShapesFromInputs()
50 ConditionalThrow<LayerValidationException>(GetInputSlot(0).GetConnection() != nullptr,
51 "DepthwiseConvolution2dLayer: InputSlot must be connected to an OutputSlot");
52 ConditionalThrow<LayerValidationException>(GetInputSlot(0).GetConnection()->IsTensorInfoSet(),
53 "DepthwiseConvolution2dLayer: TensorInfo must be set on connected OutputSlot.");
55 IOutputSlot* input = GetInputSlot(0).GetConnection();
56 const TensorShape& inputShape = input->GetTensorInfo().GetShape();
57 const TensorShape filterShape = m_Weight->GetTensorInfo().GetShape();
59 BOOST_ASSERT_MSG(inputShape.GetNumDimensions() == 4, "Convolutions will always have 4D input.");
61 unsigned int inWidth = inputShape[3];
62 unsigned int inHeight = inputShape[2];
63 unsigned int inBatchSize = inputShape[0];
65 unsigned int filterWidth = filterShape[3];
66 unsigned int readWidth = (inWidth + m_Param.m_PadLeft + m_Param.m_PadRight) - (filterWidth);
67 unsigned int outWidth = 1+(readWidth / m_Param.m_StrideX);
69 unsigned int filterHeight = filterShape[2];
70 unsigned int readHeight = (inHeight + m_Param.m_PadTop + m_Param.m_PadBottom) - (filterHeight);
71 unsigned int outHeight = 1+(readHeight / m_Param.m_StrideY);
72 unsigned int depthMultiplier = filterShape[0];
74 unsigned int outChannels = filterShape[1]*depthMultiplier;
75 unsigned int outBatchSize = inBatchSize;
77 TensorShape outShape({outBatchSize, outChannels, outHeight, outWidth});
78 ConditionalThrowIfNotEqual<LayerValidationException>(
79 "DepthwiseConvolution2dLayer: "
80 "TensorShape set on OutputSlot[0] does not match the inferred shape.",
81 GetOutputSlot(0).GetTensorInfo().GetShape(),