Publishing 2019 R1.1 content and Myriad plugin sources (#162)
[platform/upstream/dldt.git] / inference-engine / src / vpu / graph_transformer / src / stages / pooling.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <vpu/frontend/frontend.hpp>
6
7 #include <vector>
8 #include <unordered_set>
9 #include <memory>
10 #include <set>
11
12 #include <ie_layers_internal.hpp>
13
14 #include <vpu/compile_env.hpp>
15 #include <vpu/stub_stage.hpp>
16
17 namespace vpu {
18
19 void FrontEnd::parsePooling(
20         const Model::Ptr& model,
21         const ie::CNNLayerPtr& layer,
22         const DataVector& inputs,
23         const DataVector& outputs) {
24     const auto& env = CompileEnv::get();
25
26     IE_ASSERT(inputs.size() == 1);
27     IE_ASSERT(outputs.size() == 1);
28
29     auto input = inputs[0];
30     auto output = outputs[0];
31
32     if (!(input->desc().numDims() == 3 || input->desc().numDims() == 4)) {
33         VPU_THROW_EXCEPTION << "Pooling supports only 3D or 4D input";
34     }
35     if (output->desc().numDims() != input->desc().numDims()) {
36         VPU_THROW_EXCEPTION << "Pooling supports only same num dims in input and output";
37     }
38
39     //
40     // Extract parameters
41     //
42
43     auto poolLayer = std::dynamic_pointer_cast<ie::PoolingLayer>(layer);
44     IE_ASSERT(poolLayer != nullptr);
45
46     int kernelSizeX = poolLayer->_kernel_x;
47     int kernelSizeY = poolLayer->_kernel_y;
48
49     int kernelStrideX = poolLayer->_stride_x;
50     int kernelStrideY = poolLayer->_stride_y;
51
52     auto paddings = getPaddings(*poolLayer);
53     int padLeft = paddings.begin.exist(ie::X_AXIS) ? paddings.begin[ie::X_AXIS] : 0;
54     int padRight = paddings.end.exist(ie::X_AXIS) ? paddings.end[ie::X_AXIS] : padLeft;
55     int padTop = paddings.begin.exist(ie::Y_AXIS) ? paddings.begin[ie::Y_AXIS] : 0;
56     int padBottom = paddings.end.exist(ie::Y_AXIS) ? paddings.end[ie::Y_AXIS] : padTop;
57
58     auto poolType = poolLayer->_type;
59
60     auto excludePad = poolLayer->_exclude_pad;
61
62     //
63     // Check if HW is applicable
64     //
65
66     auto stageType = StageType::None;
67     auto tryHW = env.config.hwOptimization;
68
69     if (poolType == ie::PoolingLayer::MAX) {
70         stageType = StageType::StubMaxPool;
71     } else if (poolType == ie::PoolingLayer::AVG) {
72         stageType = StageType::StubAvgPool;
73     } else {
74         VPU_THROW_EXCEPTION << "Pooling Layer " << poolLayer->name << " has unsupported type: " << poolType;
75     }
76
77     // HW restrictions
78     if (kernelStrideX != kernelStrideY) {
79         tryHW = false;
80     }
81
82     // check if HW pooling has correct output size
83     {
84         int iw = input->desc().dim(Dim::W);
85         int ih = input->desc().dim(Dim::H);
86
87         int ow = output->desc().dim(Dim::W);
88         int oh = output->desc().dim(Dim::H);
89
90         // take additional hw paddings into account
91         if ((iw % 2 == 1) && (kernelSizeX % 2 == 0) && (padRight == 0)) iw++;
92         if ((ih % 2 == 1) && (kernelSizeY % 2 == 0) && (padBottom == 0)) ih++;
93
94         int tempX = iw + (padLeft + padRight) - kernelSizeX;
95         int tempY = ih + (padBottom + padTop) - kernelSizeY;
96
97         int outWidthWithOutCeil = (tempX + kernelStrideX) / kernelStrideX;
98         int outHeightWithOutCeil = (tempY + kernelStrideX) / kernelStrideX;
99
100         int outWidthWithCeil =  static_cast<int>(std::ceil(static_cast<double>(tempX) / kernelStrideX + 1));
101         int outHeightWithCeil = static_cast<int>(std::ceil(static_cast<double>(tempY) / kernelStrideX + 1));
102
103         if ((ow != outWidthWithCeil) && (ow != outWidthWithOutCeil)) {
104             tryHW = false;
105         }
106
107         if ((oh != outHeightWithCeil) && (oh != outHeightWithOutCeil)) {
108             tryHW = false;
109         }
110     }
111
112     // HW restrictions
113     if (kernelSizeX > 15 ||
114         kernelSizeY > 15 ||
115         kernelStrideX > 8) {
116         tryHW = false;
117     }
118
119     // TODO: 3x3s2 Avg pooling is not supported by HW
120     if (kernelSizeX == 3 && kernelSizeY == 3 && kernelStrideX == 2 && poolType == ie::PoolingLayer::AVG) {
121         tryHW = false;
122     }
123
124     // TODO: Avg pooling with even kernel size and odd input is not supported
125     if ((kernelSizeX % 2 == 0 || kernelSizeY % 2 == 0)) {
126         if (input->desc().dim(Dim::W) % 2 == 1 || input->desc().dim(Dim::H) % 2 == 1) {
127             if (poolType == ie::PoolingLayer::PoolType::AVG) {
128                 tryHW = false;
129             }
130         }
131     }
132
133     // TODO : 5x5s3 Avg pooling hangs device
134     if (kernelSizeX == 5 && kernelSizeY == 5 && kernelStrideX == 3 && poolType == ie::PoolingLayer::PoolType::AVG) {
135         tryHW = false;
136     }
137
138     // TODO : 2x2s2 1278x718 HW MAX pool works worse than SW version
139     if ((kernelSizeX % 2 == 0 || kernelSizeY % 2 == 0)) {
140         if (input->desc().dim(Dim::W) > 1000 || input->desc().dim(Dim::H) > 700) {
141             tryHW = false;
142         }
143     }
144
145     //  FIX #14949, enable HW AVG pooling, need SW postproc
146     if (excludePad && poolType == ie::PoolingLayer::PoolType::AVG) {
147         if (output->desc().dim(Dim::W) == 5 &&
148             output->desc().dim(Dim::H) == 5 &&
149             kernelSizeX == 5 &&
150             kernelSizeY == 5) {
151             tryHW = false;
152         }
153     }
154
155
156     if (env.netConfig.hwDisabled(layer->name)) {
157         tryHW = false;
158     }
159
160     //
161     // Create stub stage
162     //
163
164     auto stage = model->addNewStage<StubStage>(
165         layer->name,
166         stageType,
167         layer,
168         {input},
169         {output});
170
171     stage->attrs().set<int>("kernelSizeX", kernelSizeX);
172     stage->attrs().set<int>("kernelSizeY", kernelSizeY);
173
174     stage->attrs().set<int>("kernelStrideX", kernelStrideX);
175     stage->attrs().set<int>("kernelStrideY", kernelStrideY);
176
177     stage->attrs().set<int>("padLeft", padLeft);
178     stage->attrs().set<int>("padRight", padRight);
179     stage->attrs().set<int>("padTop", padTop);
180     stage->attrs().set<int>("padBottom", padBottom);
181
182     stage->attrs().set<bool>("excludePad", excludePad);
183
184     stage->attrs().set<bool>("tryHW", tryHW);
185 }
186
187 }  // namespace vpu