2 // Copyright (c) 2018 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
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"
25 using namespace cldnn;
27 void prepare_padding::run(program_impl& p)
29 if (output_size_handling_enabled)
31 // Prepare upper padding for primitives that support output_size parameter.
32 for (const auto& node : p.get_processing_order())
34 if (node->is_type<convolution>())
36 auto& prim_node = node->as<convolution>();
37 const auto& prim = prim_node.get_primitive();
39 if (!prim->with_output_size)
42 auto filter_size = prim_node.weights(0).get_output_layout().size;
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);
49 else if (node->is_type<deconvolution>())
51 auto& prim_node = node->as<deconvolution>();
52 const auto& prim = prim_node.get_primitive();
54 if (!prim->with_output_size)
57 auto filter_size = prim_node.weights(0).get_output_layout().size;
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);
63 p.apply_needed_padding(prim_node, prim_node.input(), needed_padding);
65 else if (node->is_type<pooling>())
67 auto& prim_node = node->as<pooling>();
68 const auto& prim = prim_node.get_primitive();
70 if (!prim->with_output_size)
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;
80 p.apply_needed_padding(prim_node, prim_node.input(), needed_padding);
85 // Prepare optimized padding for bfyx convolution.
86 for (auto& pair : p.nodes_map)
88 if (pair.second->type() != convolution::type_id())
91 auto& node = pair.second->as<convolution>();
92 if (node.get_dependencies().empty())
95 auto conv = node.get_primitive();
96 auto& conv_input_node = node.get_dependency(0);
97 auto conv_layout = node.get_output_layout();
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)
109 // We shoudn't apply any padding to nodes which are marked as outputs
110 if (conv_input_node.is_output())
113 // Calculating input padding needed for convolution
114 auto& filter_node = node.as<convolution>().weights(0);
115 auto filter_prim = filter_node.get_primitive();
117 layout filter_layout = filter_node.get_output_layout();
119 // convolution have only one input primitive
120 auto prev_prim_output_layout = conv_input_node.get_output_layout();
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;
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;
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);
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];
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);
144 p.apply_needed_padding(node, conv_input_node, needed_padding);