diff --git a/paddle/fluid/inference/tensorrt/op_teller.cc b/paddle/fluid/inference/tensorrt/op_teller.cc index 04752871bd63d3c6c5b9b591e04643b33a8c220a..c92a85269e2abb0168004367c3c0e06d49a978f9 100644 --- a/paddle/fluid/inference/tensorrt/op_teller.cc +++ b/paddle/fluid/inference/tensorrt/op_teller.cc @@ -562,7 +562,7 @@ bool OpTeller::Tell(const framework::ir::Node* node, bool use_no_calib_int8, if (op_type == "slice") { if (!desc.HasAttr("axes") || !desc.HasAttr("starts") || - !desc.HasAttr("ends")) { + !desc.HasAttr("ends") || !desc.HasAttr("decrease_axis")) { return false; } else { std::vector axes = @@ -571,9 +571,16 @@ bool OpTeller::Tell(const framework::ir::Node* node, bool use_no_calib_int8, BOOST_GET_CONST(std::vector, desc.GetAttr("starts")); std::vector ends = BOOST_GET_CONST(std::vector, desc.GetAttr("ends")); + std::vector decrease_axis = + BOOST_GET_CONST(std::vector, desc.GetAttr("decrease_axis")); if (axes.size() != starts.size() || axes.size() != ends.size()) { return false; } + if (decrease_axis.size() > 0) { + VLOG(3) << "Invalid slice decrease_axis. decrease_axis.size() > 0" + "is not supported in TensorRT"; + return false; + } if (!with_dynamic_shape) { for (size_t i = 0; i < axes.size(); i++) { if (axes[i] == 0) { diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_trt_convert_slice.py b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_convert_slice.py new file mode 100644 index 0000000000000000000000000000000000000000..725a3085550de9cc65d108d1437eb182959342be --- /dev/null +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_convert_slice.py @@ -0,0 +1,150 @@ +# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from trt_layer_auto_scan_test import TrtLayerAutoScanTest, SkipReasons +from program_config import TensorConfig, ProgramConfig +import numpy as np +import paddle.inference as paddle_infer +from functools import partial +from typing import Optional, List, Callable, Dict, Any, Set +import unittest + + +class TrtConvertSliceTest(TrtLayerAutoScanTest): + def is_program_valid(self, program_config: ProgramConfig) -> bool: + inputs = program_config.inputs + weights = program_config.weights + attrs = [ + program_config.ops[i].attrs + for i in range(len(program_config.ops)) + ] + + for x in attrs[0]["decrease_axis"]: + if x < 0: + return False + for x in range(len(attrs[0]["axes"])): + start = 0 + end = 0 + if attrs[0]["starts"][x] < 0: + start = attrs[0]["starts"][x] + inputs['input_data'].shape[ + attrs[0]["axes"][x]] + else: + start = attrs[0]["starts"][x] + if attrs[0]["ends"][x] < 0: + end = attrs[0]["ends"][x] + inputs['input_data'].shape[attrs[0][ + "axes"][x]] + else: + end = attrs[0]["ends"][x] + start = max(0, start) + end = max(0, end) + if start >= end: + return False + + return True + + def sample_program_configs(self): + def generate_input1(attrs: List[Dict[str, Any]]): + return np.ones([1, 3, 64, 64]).astype(np.float32) + + for axes in [[0, 1], [1, 3], [2, 3]]: + for starts in [[0, 1], [-4, -3]]: + for ends in [[2, 2], [-1, -2], [5, 5]]: + for decrease_axis in [[], [1], [2], [-1], [-100]]: + for infer_flags in [[-1]]: + dics = [{ + "axes": axes, + "starts": starts, + "ends": ends, + "decrease_axis": decrease_axis, + "infer_flags": infer_flags + }] + + ops_config = [{ + "op_type": "slice", + "op_inputs": { + "Input": ["input_data"] + }, + "op_outputs": { + "Out": ["slice_output_data"] + }, + "op_attrs": dics[0] + }] + ops = self.generate_op_config(ops_config) + + program_config = ProgramConfig( + ops=ops, + weights={}, + inputs={ + "input_data": TensorConfig(data_gen=partial( + generate_input1, dics)) + }, + outputs=["slice_output_data"]) + + yield program_config + + def sample_predictor_configs( + self, program_config) -> (paddle_infer.Config, List[int], float): + def generate_dynamic_shape(attrs): + self.dynamic_shape.min_input_shape = {"input_data": [1, 3, 32, 32]} + self.dynamic_shape.max_input_shape = {"input_data": [4, 3, 64, 64]} + self.dynamic_shape.opt_input_shape = {"input_data": [1, 3, 64, 64]} + + def clear_dynamic_shape(): + self.dynamic_shape.min_input_shape = {} + self.dynamic_shape.max_input_shape = {} + self.dynamic_shape.opt_input_shape = {} + + def generate_trt_nodes_num(attrs, dynamic_shape): + inputs = program_config.inputs + if len(attrs[0]["decrease_axis"]) != 0: + return 0, 3 + if dynamic_shape: + for i in range(len(attrs[0]["starts"])): + if attrs[0]["starts"][i] < 0 or attrs[0]["ends"][i] < 0: + return 0, 3 + if not dynamic_shape: + for x in attrs[0]["axes"]: + if x == 0: + return 0, 3 + return 1, 2 + + attrs = [ + program_config.ops[i].attrs + for i in range(len(program_config.ops)) + ] + + # for static_shape + clear_dynamic_shape() + self.trt_param.precision = paddle_infer.PrecisionType.Float32 + yield self.create_inference_config(), generate_trt_nodes_num( + attrs, False), 1e-5 + self.trt_param.precision = paddle_infer.PrecisionType.Half + yield self.create_inference_config(), generate_trt_nodes_num( + attrs, False), 1e-4 + + # for dynamic_shape + generate_dynamic_shape(attrs) + self.trt_param.precision = paddle_infer.PrecisionType.Float32 + yield self.create_inference_config(), generate_trt_nodes_num(attrs, + True), 1e-5 + self.trt_param.precision = paddle_infer.PrecisionType.Half + yield self.create_inference_config(), generate_trt_nodes_num(attrs, + True), 1e-4 + + def test(self): + self.run_test() + + +if __name__ == "__main__": + unittest.main()