From 1b1d6d3f2e61584ce54cb809202f1c9cfdaedadd Mon Sep 17 00:00:00 2001 From: xiaoxiaohehe001 <49090790+xiaoxiaohehe001@users.noreply.github.com> Date: Thu, 1 Dec 2022 18:53:23 +0800 Subject: [PATCH] [Paddle Inference] Add sign and not trt converter (#48557) --- .../inference/tensorrt/convert/unary_op.cc | 22 +++ paddle/fluid/inference/tensorrt/op_teller.cc | 50 ++++-- .../ir/inference/test_trt_convert_unary.py | 149 +++++++++++++++++- 3 files changed, 209 insertions(+), 12 deletions(-) mode change 100755 => 100644 paddle/fluid/inference/tensorrt/op_teller.cc diff --git a/paddle/fluid/inference/tensorrt/convert/unary_op.cc b/paddle/fluid/inference/tensorrt/convert/unary_op.cc index cbf2139a3c4..342b966bdce 100644 --- a/paddle/fluid/inference/tensorrt/convert/unary_op.cc +++ b/paddle/fluid/inference/tensorrt/convert/unary_op.cc @@ -90,7 +90,11 @@ const std::unordered_map> {"floor", {nvinfer1::UnaryOperation::kFLOOR}}, {"rsqrt", {nvinfer1::UnaryOperation::kSQRT, nvinfer1::UnaryOperation::kRECIP}}, + {"logical_not", {nvinfer1::UnaryOperation::kNOT}}, {"reciprocal", {nvinfer1::UnaryOperation::kRECIP}}, +#if IS_TRT_VERSION_GE(8200) + {"sign", {nvinfer1::UnaryOperation::kSIGN}}, +#endif #if IS_TRT_VERSION_GE(7000) {"erf", {nvinfer1::UnaryOperation::kERF}}, #endif @@ -167,10 +171,24 @@ class RsqrtOpConverter : public UnaryOpConverter { public: RsqrtOpConverter() { op_type_ = "rsqrt"; } }; + +class LogicalNotOpConverter : public UnaryOpConverter { + public: + LogicalNotOpConverter() { op_type_ = "logical_not"; } +}; + class ReciprocalOpConverter : public UnaryOpConverter { public: ReciprocalOpConverter() { op_type_ = "reciprocal"; } }; + +#if IS_TRT_VERSION_GE(8200) +class SignOpConverter : public UnaryOpConverter { + public: + SignOpConverter() { op_type_ = "sign"; } +}; +#endif + #if IS_TRT_VERSION_GE(7000) class ErfOpConverter : public UnaryOpConverter { public: @@ -199,7 +217,11 @@ REGISTER_TRT_OP_CONVERTER(atanh, AtanhOpConverter); REGISTER_TRT_OP_CONVERTER(ceil, CeilOpConverter); REGISTER_TRT_OP_CONVERTER(floor, FloorOpConverter); REGISTER_TRT_OP_CONVERTER(rsqrt, RsqrtOpConverter); +REGISTER_TRT_OP_CONVERTER(logical_not, LogicalNotOpConverter); REGISTER_TRT_OP_CONVERTER(reciprocal, ReciprocalOpConverter); +#if IS_TRT_VERSION_GE(8200) +REGISTER_TRT_OP_CONVERTER(sign, SignOpConverter); +#endif #if IS_TRT_VERSION_GE(7000) REGISTER_TRT_OP_CONVERTER(erf, ErfOpConverter); #endif diff --git a/paddle/fluid/inference/tensorrt/op_teller.cc b/paddle/fluid/inference/tensorrt/op_teller.cc old mode 100755 new mode 100644 index 58f99ff3d2f..ce14e506dd6 --- a/paddle/fluid/inference/tensorrt/op_teller.cc +++ b/paddle/fluid/inference/tensorrt/op_teller.cc @@ -79,17 +79,18 @@ struct SimpleOpTypeSetTeller : public Teller { desc.HasAttr("skip_quant")) return false; std::unordered_set act_op_list = { - "relu", "relu6", "sigmoid", - "elu", "selu", "softsign", - "softplus", "stanh", "thresholded_relu", - "exp", "log", "sqrt", - "abs", "sin", "cos", - "tan", "tanh", "sinh", - "cosh", "asin", "acos", - "atan", "asinh", "atanh", - "ceil", "floor", "erf", - "reciprocal", "silu", "celu", - "tanh_shrink", "logsigmoid"}; + "relu", "relu6", "sigmoid", + "elu", "selu", "softsign", + "softplus", "stanh", "thresholded_relu", + "exp", "log", "sqrt", + "abs", "sin", "cos", + "tan", "tanh", "sinh", + "cosh", "asin", "acos", + "atan", "asinh", "atanh", + "ceil", "floor", "erf", + "reciprocal", "silu", "celu", + "tanh_shrink", "logsigmoid", "sign", + "logical_not"}; if (act_op_list.find(op_type) != act_op_list.end()) { auto* block = desc.Block(); if (block == nullptr) { @@ -336,6 +337,29 @@ struct SimpleOpTypeSetTeller : public Teller { } } + if (op_type == "sign") { +#if IS_TRT_VERSION_GE(8200) + if (!with_dynamic_shape) { + return false; + } +#else + VLOG(3) << "sign op is only supported by trt8.2 above "; + return false; +#endif + } + + if (op_type == "logical_not") { +#if IS_TRT_VERSION_GE(8400) + if (!with_dynamic_shape) { + return false; + } +#else + VLOG(3) << "logical_not op is only supported by trt8.4 above because of " + "cast op"; + return false; +#endif + } + if (op_type == "matmul_v2") { if (!with_dynamic_shape) { return false; @@ -2341,7 +2365,9 @@ struct SimpleOpTypeSetTeller : public Teller { "ceil", "floor", "rsqrt", + "sign", "reciprocal", + "logical_not", "erf", "softmax", "sigmoid", @@ -2471,7 +2497,9 @@ struct SimpleOpTypeSetTeller : public Teller { "ceil", "floor", "rsqrt", + "sign", "reciprocal", + "logical_not", "erf", "softmax", "sigmoid", diff --git a/python/paddle/fluid/tests/unittests/ir/inference/test_trt_convert_unary.py b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_convert_unary.py index e5c763b822b..ba364220e39 100644 --- a/python/paddle/fluid/tests/unittests/ir/inference/test_trt_convert_unary.py +++ b/python/paddle/fluid/tests/unittests/ir/inference/test_trt_convert_unary.py @@ -59,8 +59,10 @@ class TrtConvertActivationTest(TrtLayerAutoScanTest): "floor", "rsqrt", "reciprocal", + "sign", ]: self.dims = dims + self.op_type = op_type dics = [{}] ops_config = [ @@ -121,7 +123,14 @@ class TrtConvertActivationTest(TrtLayerAutoScanTest): self.dynamic_shape.opt_input_shape = {} def generate_trt_nodes_num(attrs, dynamic_shape): - if self.dims == 1: + ver = paddle_infer.get_trt_compile_version() + if self.dims == 1 or ( + self.op_type == "sign" + and ( + not dynamic_shape + or ver[0] * 1000 + ver[1] * 100 + ver[2] * 10 < 8200 + ) + ): return 0, 3 return 1, 2 @@ -155,5 +164,143 @@ class TrtConvertActivationTest(TrtLayerAutoScanTest): self.run_test() +class TrtConvertLogicalNotTest(TrtLayerAutoScanTest): + def is_program_valid(self, program_config: ProgramConfig) -> bool: + return True + + def sample_program_configs(self): + def generate_input(shape): + return np.random.random(shape).astype(np.float32) + + for shape in [[2, 16], [2, 16, 32], [1, 32, 16, 32]]: + for op_type in ["logical_not"]: + for axis in [-1]: + self.dims = len(shape) + dics = [ + {"axis": axis}, + {"in_dtype": 5, "out_dtype": 0}, + {"in_dtype": 0, "out_dtype": 5}, + ] + ops_config = [ + { + "op_type": "cast", + "op_inputs": {"X": ["input_data"]}, + "op_outputs": {"Out": ["cast_output_data1"]}, + "op_attrs": dics[1], + "outputs_dtype": {"cast_output_data1": np.bool}, + }, + { + "op_type": op_type, + "op_inputs": { + "X": ["cast_output_data1"], + }, + "op_outputs": {"Out": ["cast_output_data0"]}, + "op_attrs": dics[0], + "outputs_dtype": {"cast_output_data0": np.bool}, + }, + { + "op_type": "cast", + "op_inputs": {"X": ["cast_output_data0"]}, + "op_outputs": {"Out": ["output_data"]}, + "op_attrs": dics[2], + }, + ] + ops = self.generate_op_config(ops_config) + + program_config = ProgramConfig( + ops=ops, + weights={}, + inputs={ + "input_data": TensorConfig( + data_gen=partial(generate_input, shape) + ), + }, + outputs=["output_data"], + ) + + yield program_config + + def sample_predictor_configs( + self, program_config + ) -> (paddle_infer.Config, List[int], float): + def generate_dynamic_shape(attrs): + if self.dims == 2: + self.dynamic_shape.min_input_shape = { + "input_data": [2, 16], + } + self.dynamic_shape.max_input_shape = { + "input_data": [2, 16], + } + self.dynamic_shape.opt_input_shape = { + "input_data": [2, 16], + } + if self.dims == 3: + self.dynamic_shape.min_input_shape = { + "input_data": [2, 16, 32], + } + self.dynamic_shape.max_input_shape = { + "input_data": [2, 16, 32], + } + self.dynamic_shape.opt_input_shape = { + "input_data": [2, 16, 32], + } + if self.dims == 4: + self.dynamic_shape.min_input_shape = { + "input_data": [1, 32, 16, 32], + } + self.dynamic_shape.max_input_shape = { + "input_data": [1, 32, 16, 32], + } + self.dynamic_shape.opt_input_shape = { + "input_data": [1, 32, 16, 32], + } + + def clear_dynamic_shape(): + self.dynamic_shape.max_input_shape = {} + self.dynamic_shape.min_input_shape = {} + self.dynamic_shape.opt_input_shape = {} + + def generate_trt_nodes_num(attrs, dynamic_shape): + if dynamic_shape: + ver = paddle_infer.get_trt_compile_version() + if ver[0] * 1000 + ver[1] * 100 + ver[2] * 10 < 8400: + return 0, 5 + return 1, 2 + return 0, 5 + + 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-3, 1e-3) + + # 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-3, 1e-3) + + def add_skip_trt_case(self): + pass + + def test(self): + self.add_skip_trt_case() + self.run_test() + + if __name__ == "__main__": unittest.main() -- GitLab