|
| 1 | +/* Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. |
| 2 | +
|
| 3 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +you may not use this file except in compliance with the License. |
| 5 | +You may obtain a copy of the License at |
| 6 | +
|
| 7 | +http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +
|
| 9 | +Unless required by applicable law or agreed to in writing, software |
| 10 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +See the License for the specific language governing permissions and |
| 13 | +limitations under the License. */ |
| 14 | +#include "paddle/fluid/inference/tensorrt/convert/op_converter.h" |
| 15 | +#include "paddle/fluid/inference/tensorrt/plugin/pool3d_op_plugin.h" |
| 16 | + |
| 17 | +namespace paddle { |
| 18 | +namespace framework { |
| 19 | +class Scope; |
| 20 | + |
| 21 | +namespace proto { |
| 22 | +class OpDesc; |
| 23 | +} // namespace proto |
| 24 | +} // namespace framework |
| 25 | +} // namespace paddle |
| 26 | + |
| 27 | +namespace paddle { |
| 28 | +namespace inference { |
| 29 | +namespace tensorrt { |
| 30 | + |
| 31 | +inline void DealCeilMode(const nvinfer1::Dims &input_shape, |
| 32 | + std::vector<int> ksize, std::vector<int> strides, |
| 33 | + std::vector<int> paddings, nvinfer1::DimsCHW *pre_pad, |
| 34 | + nvinfer1::DimsCHW *post_pad, int input_dims) { |
| 35 | + int input_depth = input_shape.d[input_dims - 3]; |
| 36 | + int input_height = input_shape.d[input_dims - 2]; |
| 37 | + int input_width = input_shape.d[input_dims - 1]; |
| 38 | + |
| 39 | + int floor_d_output_size = |
| 40 | + (input_depth - ksize[0] + 2 * paddings[0]) / strides[0] + 1; |
| 41 | + int ceil_d_output_size = |
| 42 | + (input_depth - ksize[0] + 2 * paddings[0] + strides[0] - 1) / strides[0] + |
| 43 | + 1; |
| 44 | + |
| 45 | + int floor_h_output_size = |
| 46 | + (input_height - ksize[1] + 2 * paddings[1]) / strides[1] + 1; |
| 47 | + int ceil_h_output_size = |
| 48 | + (input_height - ksize[1] + 2 * paddings[1] + strides[1] - 1) / |
| 49 | + strides[1] + |
| 50 | + 1; |
| 51 | + |
| 52 | + int floor_w_output_size = |
| 53 | + (input_width - ksize[2] + 2 * paddings[2]) / strides[2] + 1; |
| 54 | + int ceil_w_output_size = |
| 55 | + (input_width - ksize[2] + 2 * paddings[2] + strides[2] - 1) / strides[2] + |
| 56 | + 1; |
| 57 | + |
| 58 | + if (floor_d_output_size != ceil_d_output_size) { |
| 59 | + post_pad->c() = strides[0] - 1; |
| 60 | + } |
| 61 | + |
| 62 | + if (floor_h_output_size != ceil_h_output_size) { |
| 63 | + post_pad->h() = strides[1] - 1; |
| 64 | + } |
| 65 | + |
| 66 | + if (floor_w_output_size != ceil_w_output_size) { |
| 67 | + post_pad->w() = strides[2] - 1; |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | +class Pool3dOpConverter : public OpConverter { |
| 72 | + public: |
| 73 | + void operator()(const framework::proto::OpDesc &op, |
| 74 | + const framework::Scope &scope, bool test_mode) override { |
| 75 | + VLOG(4) |
| 76 | + << "convert a fluid pool3d op to tensorrt pool3d layer without bias"; |
| 77 | + framework::OpDesc op_desc(op, nullptr); |
| 78 | + auto *input1 = engine_->GetITensor(op_desc.Input("X")[0]); |
| 79 | + nvinfer1::Dims input_shape = input1->getDimensions(); |
| 80 | + int input_dims = input_shape.nbDims; |
| 81 | + |
| 82 | + bool global_pooling = |
| 83 | + BOOST_GET_CONST(bool, op_desc.GetAttr("global_pooling")); |
| 84 | + std::string pool_type = |
| 85 | + BOOST_GET_CONST(std::string, op_desc.GetAttr("pooling_type")); |
| 86 | + std::vector<int> ksize = |
| 87 | + BOOST_GET_CONST(std::vector<int>, op_desc.GetAttr("ksize")); |
| 88 | + std::vector<int> strides = |
| 89 | + BOOST_GET_CONST(std::vector<int>, op_desc.GetAttr("strides")); |
| 90 | + std::vector<int> paddings = |
| 91 | + BOOST_GET_CONST(std::vector<int>, op_desc.GetAttr("paddings")); |
| 92 | + bool exclusive = op_desc.HasAttr("exclusive") |
| 93 | + ? BOOST_GET_CONST(bool, op_desc.GetAttr("exclusive")) |
| 94 | + : true; |
| 95 | + bool ceil_mode = BOOST_GET_CONST(bool, op_desc.GetAttr("ceil_mode")); |
| 96 | + bool adaptive = false; |
| 97 | + if (op_desc.HasAttr("adaptive")) |
| 98 | + adaptive = BOOST_GET_CONST(bool, op_desc.GetAttr("adaptive")); |
| 99 | + std::string padding_algorithm = "EXPLICIT"; |
| 100 | + if (op_desc.HasAttr("padding_algorithm")) |
| 101 | + padding_algorithm = |
| 102 | + BOOST_GET_CONST(std::string, op_desc.GetAttr("padding_algorithm")); |
| 103 | + if (padding_algorithm == "VALID" || padding_algorithm == "SAME") { |
| 104 | + std::fill(paddings.begin(), paddings.end(), 0); |
| 105 | + } |
| 106 | + |
| 107 | + nvinfer1::PoolingType nv_pool_type = nvinfer1::PoolingType::kMAX; |
| 108 | + nvinfer1::ReduceOperation reduce_operation = |
| 109 | + nvinfer1::ReduceOperation::kMAX; |
| 110 | + plugin::Pool3DPlugin::Pool3DType plugin_pool_type = |
| 111 | + plugin::Pool3DPlugin::Pool3DType::max; |
| 112 | + if (pool_type == "max") { |
| 113 | + nv_pool_type = nvinfer1::PoolingType::kMAX; |
| 114 | + reduce_operation = nvinfer1::ReduceOperation::kMAX; |
| 115 | + plugin_pool_type = plugin::Pool3DPlugin::Pool3DType::max; |
| 116 | + } else if (pool_type == "avg") { |
| 117 | + nv_pool_type = nvinfer1::PoolingType::kAVERAGE; |
| 118 | + reduce_operation = nvinfer1::ReduceOperation::kAVG; |
| 119 | + plugin_pool_type = plugin::Pool3DPlugin::Pool3DType::avg; |
| 120 | + } |
| 121 | + nvinfer1::DimsCHW nv_ksize(ksize[0], ksize[1], ksize[2]); |
| 122 | + nvinfer1::DimsCHW nv_strides(strides[0], strides[1], strides[2]); |
| 123 | + nvinfer1::DimsCHW nv_paddings(paddings[0], paddings[1], paddings[2]); |
| 124 | + nvinfer1::ILayer *layer = nullptr; |
| 125 | + if (op_desc.HasAttr("enable_int8")) { |
| 126 | + CHECK(op_desc.HasAttr("X_scale")); |
| 127 | + float input_scale = BOOST_GET_CONST(float, op_desc.GetAttr("X_scale")); |
| 128 | + engine_->SetTensorDynamicRange(input1, input_scale); |
| 129 | + } |
| 130 | + |
| 131 | + if (engine_->with_dynamic_shape()) { |
| 132 | + if (!adaptive && !global_pooling && !ceil_mode) { |
| 133 | + auto *pool_layer = TRT_ENGINE_ADD_LAYER(engine_, PoolingNd, *input1, |
| 134 | + nv_pool_type, nv_ksize); |
| 135 | + pool_layer->setStrideNd(nv_strides); |
| 136 | + pool_layer->setPaddingNd(nv_paddings); |
| 137 | + pool_layer->setAverageCountExcludesPadding(exclusive); |
| 138 | + layer = pool_layer; |
| 139 | + } else if (global_pooling) { |
| 140 | + auto *reduce_layer = TRT_ENGINE_ADD_LAYER(engine_, Reduce, *input1, |
| 141 | + reduce_operation, 28, true); |
| 142 | + layer = reduce_layer; |
| 143 | + } else { |
| 144 | + plugin::Pool3DPluginDynamic *plugin = new plugin::Pool3DPluginDynamic( |
| 145 | + ceil_mode, pool_type, adaptive, ksize, strides, paddings, |
| 146 | + global_pooling); |
| 147 | + layer = engine_->AddDynamicPlugin(&input1, 1, plugin); |
| 148 | + } |
| 149 | + auto output_name = op_desc.Output("Out")[0]; |
| 150 | + layer->setName(("pool3d (Output: " + output_name + ")").c_str()); |
| 151 | + layer->getOutput(0)->setName(output_name.c_str()); |
| 152 | + engine_->SetITensor(output_name, layer->getOutput(0)); |
| 153 | + if (test_mode) { |
| 154 | + engine_->DeclareOutput(output_name); |
| 155 | + } |
| 156 | + return; |
| 157 | + } |
| 158 | + |
| 159 | + if (global_pooling == true) { |
| 160 | + auto *reduce_layer = TRT_ENGINE_ADD_LAYER(engine_, Reduce, *input1, |
| 161 | + reduce_operation, 14, true); |
| 162 | + layer = reduce_layer; |
| 163 | + auto output_name = op_desc.Output("Out")[0]; |
| 164 | + layer->setName(("pool3d (Output: " + output_name + ")").c_str()); |
| 165 | + layer->getOutput(0)->setName(output_name.c_str()); |
| 166 | + engine_->SetITensor(output_name, layer->getOutput(0)); |
| 167 | + if (test_mode) { |
| 168 | + engine_->DeclareOutput(output_name); |
| 169 | + } |
| 170 | + return; |
| 171 | + } |
| 172 | + |
| 173 | + if (!adaptive) { |
| 174 | + if (!ceil_mode) { |
| 175 | + auto *pool_layer = TRT_ENGINE_ADD_LAYER(engine_, PoolingNd, *input1, |
| 176 | + nv_pool_type, nv_ksize); |
| 177 | + PADDLE_ENFORCE_NOT_NULL( |
| 178 | + pool_layer, |
| 179 | + platform::errors::Fatal( |
| 180 | + "trt pool layer in converter could not be created.")); |
| 181 | + pool_layer->setStrideNd(nv_strides); |
| 182 | + pool_layer->setPaddingNd(nv_paddings); |
| 183 | + pool_layer->setAverageCountExcludesPadding(exclusive); |
| 184 | + layer = pool_layer; |
| 185 | + } else { |
| 186 | + std::vector<int> input_shape_v; |
| 187 | + for (int i = 0; i < input_dims; i++) { |
| 188 | + input_shape_v.push_back(input_shape.d[i]); |
| 189 | + } |
| 190 | + plugin::Pool3DPlugin *plugin = |
| 191 | + new plugin::Pool3DPlugin(ceil_mode, plugin_pool_type, adaptive, |
| 192 | + ksize, strides, paddings, input_shape_v); |
| 193 | + auto *pool_layer = engine_->AddPluginV2Ext(&input1, 1, plugin); |
| 194 | + PADDLE_ENFORCE_NOT_NULL( |
| 195 | + pool_layer, |
| 196 | + platform::errors::Fatal( |
| 197 | + "trt pool3d plugin layer in converter could not be created.")); |
| 198 | + layer = pool_layer; |
| 199 | + } |
| 200 | + } else { |
| 201 | + // Average pooling needs to exclude the padding pixels from the average |
| 202 | + // mean. |
| 203 | + // It is not supported well by TRT, we use a plugin here. |
| 204 | + std::vector<int> input_shape_v; |
| 205 | + for (int i = 0; i < input_dims; i++) { |
| 206 | + input_shape_v.push_back(input_shape.d[i]); |
| 207 | + } |
| 208 | + plugin::Pool3DPlugin *plugin = |
| 209 | + new plugin::Pool3DPlugin(ceil_mode, plugin_pool_type, adaptive, ksize, |
| 210 | + strides, paddings, input_shape_v); |
| 211 | + auto *pool_layer = engine_->AddPluginV2Ext(&input1, 1, plugin); |
| 212 | + PADDLE_ENFORCE_NOT_NULL( |
| 213 | + pool_layer, |
| 214 | + platform::errors::Fatal( |
| 215 | + "trt pool3d plugin layer in converter could not be created.")); |
| 216 | + layer = pool_layer; |
| 217 | + } |
| 218 | + auto output_name = op_desc.Output("Out")[0]; |
| 219 | + RreplenishLayerAndOutput(layer, "pool3d", {output_name}, test_mode); |
| 220 | + } |
| 221 | +}; |
| 222 | + |
| 223 | +} // namespace tensorrt |
| 224 | +} // namespace inference |
| 225 | +} // namespace paddle |
| 226 | + |
| 227 | +USE_OP(pool3d); |
| 228 | +REGISTER_TRT_OP_CONVERTER(pool3d, Pool3dOpConverter); |
0 commit comments