From 30a627aaf3af775620cda524058a4baccf7b109b Mon Sep 17 00:00:00 2001 From: Chen Weihang Date: Mon, 15 Mar 2021 10:06:20 +0800 Subject: [PATCH] Normalized function parameter writing (#31588) --- .../extension/include/ext_op_meta_info.h | 251 ++++++++++-------- .../fluid/tests/custom_op/attr_test_op.cc | 181 ++++++++++--- .../fluid/tests/custom_op/custom_concat_op.cc | 7 +- .../tests/custom_op/test_custom_attrs_jit.py | 38 ++- 4 files changed, 316 insertions(+), 161 deletions(-) diff --git a/paddle/fluid/extension/include/ext_op_meta_info.h b/paddle/fluid/extension/include/ext_op_meta_info.h index 5b8d5a0bf5a..bad1d6ad9f0 100644 --- a/paddle/fluid/extension/include/ext_op_meta_info.h +++ b/paddle/fluid/extension/include/ext_op_meta_info.h @@ -80,30 +80,31 @@ inline std::string Vec(const std::string& t_name) { ////////////////////// Kernel Function (PD_KERNEL) //////////////////////// // Record Op kernel core function -using KernelFunc = std::vector (*)( - std::vector inputs, std::vector> vec_inputs, - std::vector attrs); - -#define PD_SPECIALIZE_ComputeCallHelper(attr_type) \ - template \ - struct ComputeCallHelper { \ - template \ - static Return Compute(std::vector inputs, \ - std::vector> vec_inputs, \ - std::vector attrs, \ - const PreviousArgs&... pargs) { \ - try { \ - attr_type arg = boost::any_cast(attrs[attr_idx]); \ - return ComputeCallHelper::template Compute< \ - in_idx, vec_in_idx, attr_idx + 1>(inputs, vec_inputs, attrs, \ - pargs..., arg); \ - } catch (boost::bad_any_cast&) { \ - PD_THROW( \ - "Attribute cast error in custom operator. Expected " #attr_type \ - " value."); \ - } \ - } \ +using KernelFunc = + std::vector (*)(const std::vector& inputs, + const std::vector>& vec_inputs, + const std::vector& attrs); + +#define PD_SPECIALIZE_ComputeCallHelper(attr_type) \ + template \ + struct ComputeCallHelper { \ + template \ + static Return Compute(const std::vector& inputs, \ + const std::vector>& vec_inputs, \ + const std::vector& attrs, \ + const PreviousArgs&... pargs) { \ + try { \ + attr_type arg = boost::any_cast(attrs[attr_idx]); \ + return ComputeCallHelper::template Compute< \ + in_idx, vec_in_idx, attr_idx + 1>(inputs, vec_inputs, attrs, \ + pargs..., arg); \ + } catch (boost::bad_any_cast&) { \ + PD_THROW( \ + "Attribute cast error in custom operator. Expected " #attr_type \ + " value."); \ + } \ + } \ } template @@ -114,9 +115,9 @@ struct KernelFuncImpl; template struct KernelFuncImpl { - static Return Compute(std::vector inputs, - std::vector> vec_inputs, - std::vector attrs) { + static Return Compute(const std::vector& inputs, + const std::vector>& vec_inputs, + const std::vector& attrs) { return ComputeCallHelper>::template Compute<0, 0, 0>( inputs, vec_inputs, attrs); } @@ -125,14 +126,13 @@ struct KernelFuncImpl { template struct ComputeCallHelper; - // for Tensor input template struct ComputeCallHelper { template - static Return Compute(std::vector inputs, - std::vector> vec_inputs, - std::vector attrs, + static Return Compute(const std::vector& inputs, + const std::vector>& vec_inputs, + const std::vector& attrs, const PreviousArgs&... pargs) { const Tensor& arg = inputs[in_idx]; return ComputeCallHelper::template Compute { } }; - // for std::vector input template struct ComputeCallHelper&, Tail...> { template - static Return Compute(std::vector inputs, - std::vector> vec_inputs, - std::vector attrs, + static Return Compute(const std::vector& inputs, + const std::vector>& vec_inputs, + const std::vector& attrs, const PreviousArgs&... pargs) { const std::vector& arg = vec_inputs[vec_in_idx]; return ComputeCallHelper::template Compute< @@ -157,6 +156,23 @@ struct KernelFuncImpl { } }; + PD_SPECIALIZE_ComputeCallHelper(const bool&); + PD_SPECIALIZE_ComputeCallHelper(const int&); + PD_SPECIALIZE_ComputeCallHelper(const float&); + PD_SPECIALIZE_ComputeCallHelper(const int64_t&); + PD_SPECIALIZE_ComputeCallHelper(const std::string&); + PD_SPECIALIZE_ComputeCallHelper(const std::vector&); + PD_SPECIALIZE_ComputeCallHelper(const std::vector&); + PD_SPECIALIZE_ComputeCallHelper(const std::vector&); + PD_SPECIALIZE_ComputeCallHelper(const std::vector&); + // TODO(chenweihang): support other attribute type if needed. + // Why not support other attribute type here? + // - boost::blank, std::vector and std::vector + // are not used in op + // - BlockDesc* and std::vector are used in framework + + // NOTE(chenweihang): Used to be compatible with the 2.0.1 released + // interface, and will be deprecated in the future PD_SPECIALIZE_ComputeCallHelper(bool); PD_SPECIALIZE_ComputeCallHelper(int); PD_SPECIALIZE_ComputeCallHelper(float); @@ -166,18 +182,15 @@ struct KernelFuncImpl { PD_SPECIALIZE_ComputeCallHelper(std::vector); PD_SPECIALIZE_ComputeCallHelper(std::vector); PD_SPECIALIZE_ComputeCallHelper(std::vector); - // TODO(chenweihang): support other attribute type if needed. - // Why not support other attribute type here? - // - boost::blank, std::vector and std::vector - // are not used in op - // - BlockDesc* and std::vector are used in framework + // end: base template template struct ComputeCallHelper> { template - static Return Compute(std::vector inputs, - std::vector> vec_inputs, - std::vector attrs, const Args&... args) { + static Return Compute(const std::vector& inputs, + const std::vector>& vec_inputs, + const std::vector& attrs, + const Args&... args) { return impl_fn(args...); } }; @@ -190,8 +203,40 @@ struct KernelFuncImpl { // Record Op infershape core function using InferShapeFunc = std::vector> (*)( - std::vector> input_shapes, - std::vector>> vec_input_shapes); + const std::vector>& input_shapes, + const std::vector>>& vec_input_shapes); + +#define PD_SPECIALIZE_InferShapeCallHelper_FOR_SHAPE(input_type) \ + template \ + struct InferShapeCallHelper { \ + template \ + static Return InferShape( \ + const std::vector>& input_shapes, \ + const std::vector>>& \ + vec_input_shapes, \ + const PreviousArgs&... pargs) { \ + input_type arg = input_shapes[in_idx]; \ + return InferShapeCallHelper::template InferShape( \ + input_shapes, vec_input_shapes, pargs..., arg); \ + } \ + } + +#define PD_SPECIALIZE_InferShapeCallHelper_FOR_SHAPES(input_type) \ + template \ + struct InferShapeCallHelper { \ + template \ + static Return InferShape( \ + const std::vector>& input_shapes, \ + const std::vector>>& \ + vec_input_shapes, \ + const PreviousArgs&... pargs) { \ + input_type arg = vec_input_shapes[vec_in_idx]; \ + return InferShapeCallHelper::template InferShape< \ + in_idx, vec_in_idx + 1>(input_shapes, vec_input_shapes, pargs..., \ + arg); \ + } \ + } template struct InferShapeFuncImpl; @@ -199,8 +244,8 @@ struct InferShapeFuncImpl; template struct InferShapeFuncImpl { static Return InferShape( - std::vector> input_shapes, - std::vector>> vec_input_shapes) { + const std::vector>& input_shapes, + const std::vector>>& vec_input_shapes) { return InferShapeCallHelper>::template InferShape<0, 0>( input_shapes, vec_input_shapes); @@ -210,41 +255,23 @@ struct InferShapeFuncImpl { template struct InferShapeCallHelper; - template - struct InferShapeCallHelper, Tail...> { - template - static Return InferShape( - std::vector> input_shapes, - std::vector>> vec_input_shapes, - const PreviousArgs&... pargs) { - std::vector arg = input_shapes[in_idx]; - return InferShapeCallHelper::template InferShape( - input_shapes, vec_input_shapes, pargs..., arg); - } - }; + PD_SPECIALIZE_InferShapeCallHelper_FOR_SHAPE(const std::vector&); + PD_SPECIALIZE_InferShapeCallHelper_FOR_SHAPES( + const std::vector>&); - template - struct InferShapeCallHelper>, Tail...> { - template - static Return InferShape( - std::vector> input_shapes, - std::vector>> vec_input_shapes, - const PreviousArgs&... pargs) { - std::vector> arg = vec_input_shapes[vec_in_idx]; - return InferShapeCallHelper::template InferShape( - input_shapes, vec_input_shapes, pargs..., arg); - } - }; + // NOTE(chenweihang): Used to be compatible with the 2.0.1 released + // interface, and will be deprecated in the future + PD_SPECIALIZE_InferShapeCallHelper_FOR_SHAPE(std::vector); + PD_SPECIALIZE_InferShapeCallHelper_FOR_SHAPES( + std::vector>); // end: base template template struct InferShapeCallHelper> { template static Return InferShape( - std::vector> input_shapes, - std::vector>> vec_input_shapes, + const std::vector>& input_shapes, + const std::vector>>& vec_input_shapes, const Args&... args) { return impl_fn(args...); } @@ -258,8 +285,38 @@ struct InferShapeFuncImpl { // Record Op Infer dtype core function using InferDtypeFunc = std::vector (*)( - std::vector input_dtypes, - std::vector> vec_input_dtypes); + const std::vector& input_dtypes, + const std::vector>& vec_input_dtypes); + +#define PD_SPECIALIZE_InferDtypeCallHelper_TO_DTYPE(input_type) \ + template \ + struct InferDtypeCallHelper { \ + template \ + static Return InferDtype( \ + const std::vector& input_dtypes, \ + const std::vector>& vec_input_dtypes, \ + const PreviousArgs&... pargs) { \ + input_type arg = input_dtypes[in_idx]; \ + return InferDtypeCallHelper::template InferDtype( \ + input_dtypes, vec_input_dtypes, pargs..., arg); \ + } \ + } + +#define PD_SPECIALIZE_InferDtypeCallHelper_FOR_DTYPES(input_type) \ + template \ + struct InferDtypeCallHelper { \ + template \ + static Return InferDtype( \ + const std::vector& input_dtypes, \ + const std::vector>& vec_input_dtypes, \ + const PreviousArgs&... pargs) { \ + input_type arg = vec_input_dtypes[vec_in_idx]; \ + return InferDtypeCallHelper::template InferDtype< \ + in_idx, vec_in_idx + 1>(input_dtypes, vec_input_dtypes, pargs..., \ + arg); \ + } \ + } template struct InferDtypeFuncImpl; @@ -267,8 +324,8 @@ struct InferDtypeFuncImpl; template struct InferDtypeFuncImpl { static Return InferDtype( - std::vector input_dtypes, - std::vector> vec_input_dtypes) { + const std::vector& input_dtypes, + const std::vector>& vec_input_dtypes) { return InferDtypeCallHelper>::template InferDtype<0, 0>( input_dtypes, vec_input_dtypes); @@ -278,41 +335,21 @@ struct InferDtypeFuncImpl { template struct InferDtypeCallHelper; - template - struct InferDtypeCallHelper { - template - static Return InferDtype( - std::vector input_dtypes, - std::vector> vec_input_dtypes, - const PreviousArgs&... pargs) { - DataType arg = input_dtypes[in_idx]; - return InferDtypeCallHelper::template InferDtype( - input_dtypes, vec_input_dtypes, pargs..., arg); - } - }; + PD_SPECIALIZE_InferDtypeCallHelper_TO_DTYPE(const DataType&); + PD_SPECIALIZE_InferDtypeCallHelper_FOR_DTYPES(const std::vector&); - template - struct InferDtypeCallHelper, Tail...> { - template - static Return InferDtype( - std::vector input_dtypes, - std::vector> vec_input_dtypes, - const PreviousArgs&... pargs) { - std::vector arg = vec_input_dtypes[vec_in_idx]; - return InferDtypeCallHelper::template InferDtype( - input_dtypes, vec_input_dtypes, pargs..., arg); - } - }; + // NOTE(chenweihang): Used to be compatible with the 2.0.1 released + // interface, and will be deprecated in the future + PD_SPECIALIZE_InferDtypeCallHelper_TO_DTYPE(DataType); + PD_SPECIALIZE_InferDtypeCallHelper_FOR_DTYPES(std::vector); // end: base template template struct InferDtypeCallHelper> { template static Return InferDtype( - std::vector input_dtypes, - std::vector> vec_input_dtypes, + const std::vector& input_dtypes, + const std::vector>& vec_input_dtypes, const Args&... args) { return impl_fn(args...); } diff --git a/python/paddle/fluid/tests/custom_op/attr_test_op.cc b/python/paddle/fluid/tests/custom_op/attr_test_op.cc index 97aae106137..1edc10b8a8a 100644 --- a/python/paddle/fluid/tests/custom_op/attr_test_op.cc +++ b/python/paddle/fluid/tests/custom_op/attr_test_op.cc @@ -27,27 +27,15 @@ void assign_cpu_kernel(const data_t* x_data, } } -std::vector AttrTestForward( - const paddle::Tensor& x, - bool bool_attr, - int int_attr, - float float_attr, - int64_t int64_attr, - std::string str_attr, - std::vector int_vec_attr, - std::vector float_vec_attr, - std::vector int64_vec_attr, - std::vector str_vec_attr) { - auto out = paddle::Tensor(paddle::PlaceType::kCPU); - out.reshape(x.shape()); - - PD_DISPATCH_FLOATING_TYPES( - x.type(), "assign_cpu_kernel", ([&] { - assign_cpu_kernel( - x.data(), out.mutable_data(), x.size()); - })); - - // Check attrs value +void CheckAllForwardAttrs(const bool& bool_attr, + const int& int_attr, + const float& float_attr, + const int64_t& int64_attr, + const std::string& str_attr, + const std::vector& int_vec_attr, + const std::vector& float_vec_attr, + const std::vector& int64_vec_attr, + const std::vector& str_vec_attr) { if (bool_attr != true) { throw std::runtime_error("bool_attr value error."); } @@ -103,26 +91,11 @@ std::vector AttrTestForward( } } } - - return {out}; } -// The attrs of backward op must be the subset of attrs of forward op -std::vector AttrTestBackward( - const paddle::Tensor& grad_out, - int int_attr, - std::vector float_vec_attr, - std::vector str_vec_attr) { - auto grad_x = paddle::Tensor(paddle::PlaceType::kCPU); - grad_x.reshape(grad_out.shape()); - - PD_DISPATCH_FLOATING_TYPES(grad_out.type(), "assign_cpu_kernel", ([&] { - assign_cpu_kernel( - grad_out.data(), - grad_x.mutable_data(), - grad_out.size()); - })); - +void CheckAllBackwardAttrs(const int& int_attr, + const std::vector& float_vec_attr, + const std::vector& str_vec_attr) { if (int_attr != 10) { throw std::runtime_error("int_attr value error."); } @@ -146,6 +119,114 @@ std::vector AttrTestBackward( } } } +} + +std::vector AttrTestForward( + const paddle::Tensor& x, + bool bool_attr, + int int_attr, + float float_attr, + int64_t int64_attr, + std::string str_attr, + std::vector int_vec_attr, + std::vector float_vec_attr, + std::vector int64_vec_attr, + std::vector str_vec_attr) { + auto out = paddle::Tensor(paddle::PlaceType::kCPU); + out.reshape(x.shape()); + + PD_DISPATCH_FLOATING_TYPES( + x.type(), "assign_cpu_kernel", ([&] { + assign_cpu_kernel( + x.data(), out.mutable_data(), x.size()); + })); + + // Check attrs value + CheckAllForwardAttrs(bool_attr, + int_attr, + float_attr, + int64_attr, + str_attr, + int_vec_attr, + float_vec_attr, + int64_vec_attr, + str_vec_attr); + + return {out}; +} + +// The attrs of backward op must be the subset of attrs of forward op +std::vector AttrTestBackward( + const paddle::Tensor& grad_out, + int int_attr, + std::vector float_vec_attr, + std::vector str_vec_attr) { + auto grad_x = paddle::Tensor(paddle::PlaceType::kCPU); + grad_x.reshape(grad_out.shape()); + + PD_DISPATCH_FLOATING_TYPES(grad_out.type(), "assign_cpu_kernel", ([&] { + assign_cpu_kernel( + grad_out.data(), + grad_x.mutable_data(), + grad_out.size()); + })); + + CheckAllBackwardAttrs(int_attr, float_vec_attr, str_vec_attr); + + return {grad_x}; +} + +std::vector ConstAttrTestForward( + const paddle::Tensor& x, + const bool& bool_attr, + const int& int_attr, + const float& float_attr, + const int64_t& int64_attr, + const std::string& str_attr, + const std::vector& int_vec_attr, + const std::vector& float_vec_attr, + const std::vector& int64_vec_attr, + const std::vector& str_vec_attr) { + auto out = paddle::Tensor(paddle::PlaceType::kCPU); + out.reshape(x.shape()); + + PD_DISPATCH_FLOATING_TYPES( + x.type(), "assign_cpu_kernel", ([&] { + assign_cpu_kernel( + x.data(), out.mutable_data(), x.size()); + })); + + // Check attrs value + CheckAllForwardAttrs(bool_attr, + int_attr, + float_attr, + int64_attr, + str_attr, + int_vec_attr, + float_vec_attr, + int64_vec_attr, + str_vec_attr); + + return {out}; +} + +// The attrs of backward op must be the subset of attrs of forward op +std::vector ConstAttrTestBackward( + const paddle::Tensor& grad_out, + const int& int_attr, + const std::vector& float_vec_attr, + const std::vector& str_vec_attr) { + auto grad_x = paddle::Tensor(paddle::PlaceType::kCPU); + grad_x.reshape(grad_out.shape()); + + PD_DISPATCH_FLOATING_TYPES(grad_out.type(), "assign_cpu_kernel", ([&] { + assign_cpu_kernel( + grad_out.data(), + grad_x.mutable_data(), + grad_out.size()); + })); + + CheckAllBackwardAttrs(int_attr, float_vec_attr, str_vec_attr); return {grad_x}; } @@ -171,3 +252,25 @@ PD_BUILD_GRAD_OP(attr_test) "float_vec_attr: std::vector", "str_vec_attr: std::vector"}) .SetKernelFn(PD_KERNEL(AttrTestBackward)); + +PD_BUILD_OP(const_attr_test) + .Inputs({"X"}) + .Outputs({"Out"}) + .Attrs({"bool_attr: bool", + "int_attr: int", + "float_attr: float", + "int64_attr: int64_t", + "str_attr: std::string", + "int_vec_attr: std::vector", + "float_vec_attr: std::vector", + "int64_vec_attr: std::vector", + "str_vec_attr: std::vector"}) + .SetKernelFn(PD_KERNEL(AttrTestForward)); + +PD_BUILD_GRAD_OP(const_attr_test) + .Inputs({paddle::Grad("Out")}) + .Outputs({paddle::Grad("X")}) + .Attrs({"int_attr: int", + "float_vec_attr: std::vector", + "str_vec_attr: std::vector"}) + .SetKernelFn(PD_KERNEL(AttrTestBackward)); diff --git a/python/paddle/fluid/tests/custom_op/custom_concat_op.cc b/python/paddle/fluid/tests/custom_op/custom_concat_op.cc index 4ea39303991..2d8d0ccb88f 100644 --- a/python/paddle/fluid/tests/custom_op/custom_concat_op.cc +++ b/python/paddle/fluid/tests/custom_op/custom_concat_op.cc @@ -122,13 +122,14 @@ std::vector ConcatBackwardDynamicAxis( } std::vector> ConcatInferShapeDynamicAxis( - std::vector> input_shapes, - std::vector axis_shape) { + const std::vector>& input_shapes, + const std::vector& axis_shape) { return {std::vector(input_shapes[0].size(), -1)}; } std::vector ConcatInferDtypeDynamicAxis( - std::vector input_dtypes, paddle::DataType axis_dtype) { + const std::vector& input_dtypes, + const paddle::DataType& axis_dtype) { return {input_dtypes[0]}; } diff --git a/python/paddle/fluid/tests/custom_op/test_custom_attrs_jit.py b/python/paddle/fluid/tests/custom_op/test_custom_attrs_jit.py index a6278e3ffc3..1c9c6eedbae 100644 --- a/python/paddle/fluid/tests/custom_op/test_custom_attrs_jit.py +++ b/python/paddle/fluid/tests/custom_op/test_custom_attrs_jit.py @@ -40,24 +40,38 @@ custom_attrs = load( class TestJitCustomAttrs(unittest.TestCase): - def test_attr_value(self): + def setUp(self): paddle.set_device('cpu') # prepare test value - bool_attr = True - int_attr = 10 - float_attr = 3.14 - int64_attr = 10000000000 - str_attr = "StrAttr" - int_vec_attr = [10, 10, 10] - float_vec_attr = [3.14, 3.14, 3.14] - int64_vec_attr = [10000000000, 10000000000, 10000000000] - str_vec_attr = ["StrAttr", "StrAttr", "StrAttr"] + self.bool_attr = True + self.int_attr = 10 + self.float_attr = 3.14 + self.int64_attr = 10000000000 + self.str_attr = "StrAttr" + self.int_vec_attr = [10, 10, 10] + self.float_vec_attr = [3.14, 3.14, 3.14] + self.int64_vec_attr = [10000000000, 10000000000, 10000000000] + self.str_vec_attr = ["StrAttr", "StrAttr", "StrAttr"] + def test_attr_value(self): x = paddle.ones([2, 2], dtype='float32') x.stop_gradient = False out = custom_attrs.attr_test( - x, bool_attr, int_attr, float_attr, int64_attr, str_attr, - int_vec_attr, float_vec_attr, int64_vec_attr, str_vec_attr) + x, self.bool_attr, self.int_attr, self.float_attr, self.int64_attr, + self.str_attr, self.int_vec_attr, self.float_vec_attr, + self.int64_vec_attr, self.str_vec_attr) + out.stop_gradient = False + out.backward() + + self.assertTrue(np.array_equal(x.numpy(), out.numpy())) + + def test_const_attr_value(self): + x = paddle.ones([2, 2], dtype='float32') + x.stop_gradient = False + out = custom_attrs.const_attr_test( + x, self.bool_attr, self.int_attr, self.float_attr, self.int64_attr, + self.str_attr, self.int_vec_attr, self.float_vec_attr, + self.int64_vec_attr, self.str_vec_attr) out.stop_gradient = False out.backward() -- GitLab