Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / src / graph_optimizer / prepare_padding.cpp
1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
18
19 #include "pooling_inst.h"
20 #include "program_node.h"
21 #include "pass_manager.h"
22 #include "convolution_inst.h"
23 #include "sliding_window_utils.h"
24
25 using namespace cldnn;
26
27 void prepare_padding::run(program_impl& p)
28 {
29     if (output_size_handling_enabled)
30     {
31         // Prepare upper padding for primitives that support output_size parameter.
32         for (const auto& node : p.get_processing_order())
33         {
34             if (node->is_type<convolution>())
35             {
36                 auto& prim_node = node->as<convolution>();
37                 const auto& prim = prim_node.get_primitive();
38
39                 if (!prim->with_output_size)
40                     continue;
41
42                 auto filter_size = prim_node.weights(0).get_output_layout().size;
43
44                 auto needed_padding = calc_sliding_window_needed_input_padding(
45                     prim_node.input().get_output_layout(),
46                     prim->output_size, filter_size, prim->input_offset, prim->stride, prim->dilation, false, 1);
47                 p.apply_needed_padding(prim_node, prim_node.input(), needed_padding);
48             }
49             else if (node->is_type<deconvolution>())
50             {
51                 auto& prim_node = node->as<deconvolution>();
52                 const auto& prim = prim_node.get_primitive();
53
54                 if (!prim->with_output_size)
55                     continue;
56
57                 auto filter_size = prim_node.weights(0).get_output_layout().size;
58
59                 auto needed_padding = calc_sliding_window_needed_input_padding(
60                     prim_node.input().get_output_layout(),
61                     prim->output_size, filter_size, prim->input_offset, prim->stride, { 1, 1, 1, 1 }, true, 1);
62
63                 p.apply_needed_padding(prim_node, prim_node.input(), needed_padding);
64             }
65             else if (node->is_type<pooling>())
66             {
67                 auto& prim_node = node->as<pooling>();
68                 const auto& prim = prim_node.get_primitive();
69
70                 if (!prim->with_output_size)
71                     continue;
72
73                 // NOTE: Currently there is no pooling implementation/pooling mode which does not check input data range.
74                 // There is no need to add padding requirements on pooling inputs.
75                 //auto needed_padding = calc_sliding_window_needed_input_padding(
76                 //    prim_node.input().get_output_layout(),
77                 //    prim->output_size, prim->size, prim->input_offset, prim->stride, {1, 1, 1, 1}, false, 1);
78                 auto needed_padding = prim_node.input().get_output_layout().data_padding;
79
80                 p.apply_needed_padding(prim_node, prim_node.input(), needed_padding);
81             }
82         }
83     }
84
85     // Prepare optimized padding for bfyx convolution.
86     for (auto& pair : p.nodes_map)
87     {
88         if (pair.second->type() != convolution::type_id())
89             continue;
90
91         auto& node = pair.second->as<convolution>();
92         if (node.get_dependencies().empty())
93             continue;
94
95         auto conv = node.get_primitive();
96         auto& conv_input_node = node.get_dependency(0);
97         auto conv_layout = node.get_output_layout();
98
99         // right now output padding optimization is only available for bfyx format and data type = float32
100         if (conv_layout.format != cldnn::format::bfyx
101             && conv_layout.format != cldnn::format::bf8_xy16
102             && conv_layout.format != cldnn::format::byxf_af32
103             && conv_layout.format != cldnn::format::fs_bs_yx_bsv4_fsv32
104             && conv_layout.format != cldnn::format::b_fs_yx_fsv4)
105         {
106             continue;
107         }
108
109         // We shoudn't apply any padding to nodes which are marked as outputs
110         if (conv_input_node.is_output())
111             continue;
112
113         // Calculating input padding needed for convolution
114         auto& filter_node = node.as<convolution>().weights(0);
115         auto filter_prim = filter_node.get_primitive();
116
117         layout filter_layout = filter_node.get_output_layout();
118
119         // convolution have only one input primitive
120         auto prev_prim_output_layout = conv_input_node.get_output_layout();
121
122         // Compute initial required paddings for primitive used as input for convolution.
123         auto input_offset = conv->input_offset;
124         auto stride = conv->stride;
125         auto dilation = conv->dilation;
126
127         auto input_limit_x = input_offset.spatial[0] + (conv_layout.size.spatial[0] - 1) * stride.spatial[0] + (filter_layout.size.spatial[0] - 1) * dilation.spatial[0] + 1;
128         auto input_limit_y = input_offset.spatial[1] + (conv_layout.size.spatial[1] - 1) * stride.spatial[1] + (filter_layout.size.spatial[1] - 1) * dilation.spatial[1] + 1;
129
130         auto left_padding = std::max(-input_offset.spatial[0], 0);
131         auto top_padding = std::max(-input_offset.spatial[1], 0);
132         auto right_padding = std::max(input_limit_x - prev_prim_output_layout.size.spatial[0], 0);
133         auto bottom_padding = std::max(input_limit_y - prev_prim_output_layout.size.spatial[1], 0);
134
135         // Adjust right padding, so entire buffer size in X dimension is properly aligned.
136         // TODO: NOTE: Will be reenabled with next check-in once heuristic for line-aligned algorithm will be added.
137         //auto needed_buffer_size_x = static_cast<cldnn::tensor::value_type>(
138         //    round_up_to(left_padding + prev_prim_output_layout.size.spatial[0] + right_padding, 16));
139         //right_padding = needed_buffer_size_x - left_padding - prev_prim_output_layout.size.spatial[0];
140
141         cldnn::padding needed_padding({ 0, 0, left_padding, top_padding }, { 0, 0, right_padding, bottom_padding }, 0);
142         needed_padding = padding::max(prev_prim_output_layout.data_padding, needed_padding);
143
144         p.apply_needed_padding(node, conv_input_node, needed_padding);
145     }
146 }