From 119816f98b339e013ef16ea044aafb90517f2bfe Mon Sep 17 00:00:00 2001 From: chentianyu03 Date: Mon, 4 Apr 2022 11:33:28 +0800 Subject: [PATCH] [Yaml]Add concat grad yaml (#41365) * add concat_grad kernel * fix error * remove comment code * fix outs nullptr error * change to phi header * add concat_grad declare for standalone_executor_test * add concat_grad yaml * add concat api * fix test concat op error * fix test concat op error --- paddle/phi/api/lib/CMakeLists.txt | 2 +- paddle/phi/api/lib/api_custom_impl.cc | 66 +++++++++++++++++++ paddle/phi/api/lib/api_custom_impl.h | 4 ++ paddle/phi/infermeta/multiary.cc | 7 ++ paddle/phi/infermeta/multiary.h | 3 + python/paddle/fluid/layers/tensor.py | 10 ++- .../fluid/tests/unittests/test_concat_op.py | 26 +++++--- python/paddle/utils/code_gen/api.yaml | 1 + python/paddle/utils/code_gen/backward.yaml | 6 ++ 9 files changed, 115 insertions(+), 10 deletions(-) diff --git a/paddle/phi/api/lib/CMakeLists.txt b/paddle/phi/api/lib/CMakeLists.txt index af253301915..d4d8a0fa8a3 100644 --- a/paddle/phi/api/lib/CMakeLists.txt +++ b/paddle/phi/api/lib/CMakeLists.txt @@ -165,7 +165,7 @@ cc_library(context_pool SRCS context_pool.cc DEPS phi_context phi_enforce place) cc_library(kernel_dispatch SRCS kernel_dispatch.cc DEPS phi_tensor_raw phi_context kernel_factory context_pool) cc_library(api_gen_utils SRCS api_gen_utils.cc DEPS phi_tensor_raw selected_rows sparse_csr_tensor sparse_coo_tensor) cc_library(phi_data_transform SRCS data_transform.cc DEPS phi_tensor_raw transfer_layout_kernel cast_kernel data_device_transform) -cc_library(api_custom_impl SRCS api_custom_impl.cc DEPS phi_tensor_raw phi kernel_dispatch api_gen_utils phi_data_transform) +cc_library(api_custom_impl SRCS api_custom_impl.cc DEPS phi_tensor_raw phi kernel_dispatch api_gen_utils phi_data_transform backward_infermeta) cc_library(sparse_api_custom_impl SRCS sparse_api_custom_impl.cc DEPS phi_tensor_raw phi kernel_dispatch api_gen_utils phi_data_transform) cc_library(phi_function_api SRCS ${api_source_file} DEPS phi_tensor_raw phi kernel_dispatch api_gen_utils phi_data_transform api_custom_impl) diff --git a/paddle/phi/api/lib/api_custom_impl.cc b/paddle/phi/api/lib/api_custom_impl.cc index 3818572db0c..ce49680586c 100644 --- a/paddle/phi/api/lib/api_custom_impl.cc +++ b/paddle/phi/api/lib/api_custom_impl.cc @@ -21,6 +21,7 @@ limitations under the License. */ #include "paddle/phi/core/compat/convert_utils.h" #include "paddle/phi/core/kernel_registry.h" #include "paddle/phi/core/meta_tensor.h" +#include "paddle/phi/infermeta/backward.h" #include "paddle/phi/infermeta/binary.h" #include "paddle/phi/infermeta/multiary.h" #include "paddle/phi/infermeta/nullary.h" @@ -166,5 +167,70 @@ std::vector split_impl(const Tensor& x, return out; } +std::vector concat_grad_impl(const std::vector& x, + const Tensor& out_grad, + const Scalar& axis) { + auto kernel_key_set = ParseKernelKeyByInputArgs(out_grad); + auto kernel_key = kernel_key_set.GetHighestPriorityKernelKey(); + + Backend kernel_backend = kernel_key.backend(); + DataLayout kernel_layout = kernel_key.layout(); + DataType kernel_data_type = kernel_key.dtype(); + + auto kernel = phi::KernelFactory::Instance().SelectKernelOrThrowError( + "concat_grad", {kernel_backend, kernel_layout, kernel_data_type}); + VLOG(6) << "concat_grad API kernel key: [" << kernel_backend << ", " + << kernel_layout << ", " << kernel_data_type << "]"; + VLOG(6) << "concat_grad API kernel: " << kernel; + + auto* dev_ctx = GetDeviceContextByBackend(kernel_backend); + + // std::unique_ptr> + auto dense_x = PrepareData(x, kernel.InputAt(0), {}); + auto dense_out_grad = PrepareData(out_grad, kernel.InputAt(1), {}); + + // Calculate the number of out tensors + size_t out_number = x.size(); + std::vector x_grad; + auto dense_x_grad = SetKernelOutput(out_number, kernel_backend, &x_grad); + + std::vector meta_x; + meta_x.reserve(x.size()); + std::vector meta_x_ptrs; + meta_x_ptrs.reserve(x.size()); + for (const auto& t : *dense_x) { + meta_x.push_back(t); + meta_x_ptrs.push_back(&meta_x.back()); + } + + std::vector meta_x_grad; + meta_x_grad.reserve(x.size()); + std::vector meta_x_grad_ptrs; + meta_x_grad_ptrs.reserve(x.size()); + for (size_t i = 0; i < out_number; ++i) { + meta_x_grad.push_back(*dense_x_grad[i]); + meta_x_grad_ptrs.push_back(&meta_x_grad.back()); + } + + phi::UnchangedMultiInferMeta(meta_x_ptrs, meta_x_grad_ptrs); + + std::vector dense_x_ptr; + dense_x_ptr.reserve(x.size()); + for (const auto& t : *dense_x) { + dense_x_ptr.push_back(&t); + } + + using kernel_signature = void (*)(const platform::DeviceContext&, + const std::vector&, + const phi::DenseTensor&, + const phi::Scalar&, + std::vector); + auto* kernel_fn = kernel.GetVariadicKernelFn(); + (*kernel_fn)( + *dev_ctx, dense_x_ptr, *dense_out_grad, phi::Scalar(axis), dense_x_grad); + + return x_grad; +} + } // namespace experimental } // namespace paddle diff --git a/paddle/phi/api/lib/api_custom_impl.h b/paddle/phi/api/lib/api_custom_impl.h index f9a11b4bd96..1f84eab1035 100644 --- a/paddle/phi/api/lib/api_custom_impl.h +++ b/paddle/phi/api/lib/api_custom_impl.h @@ -31,5 +31,9 @@ std::vector split_impl(const Tensor& x, const IntArray& num_or_sections, const Scalar& axis); +std::vector concat_grad_impl(const std::vector& x, + const Tensor& out_grad, + const Scalar& axis); + } // namespace experimental } // namespace paddle diff --git a/paddle/phi/infermeta/multiary.cc b/paddle/phi/infermeta/multiary.cc index 42041af2dfe..76951669c66 100644 --- a/paddle/phi/infermeta/multiary.cc +++ b/paddle/phi/infermeta/multiary.cc @@ -1909,6 +1909,13 @@ void StackInferMeta(const std::vector& x, out->share_lod(*x.at(0)); } +void UnchangedMultiInferMeta(const std::vector& x, + std::vector out) { + for (size_t i = 0; i < x.size(); ++i) { + out[i]->share_meta(*x[i]); + } +} + void WarpctcInferMeta(const MetaTensor& logits, const MetaTensor& label, const paddle::optional logits_length, diff --git a/paddle/phi/infermeta/multiary.h b/paddle/phi/infermeta/multiary.h index 0b1ccfcb905..c63960c7b9b 100644 --- a/paddle/phi/infermeta/multiary.h +++ b/paddle/phi/infermeta/multiary.h @@ -289,6 +289,9 @@ void StackInferMeta(const std::vector& x, int axis, MetaTensor* out); +void UnchangedMultiInferMeta(const std::vector& x, + std::vector out); + void WarpctcInferMeta(const MetaTensor& logits, const MetaTensor& label, const paddle::optional logits_length, diff --git a/python/paddle/fluid/layers/tensor.py b/python/paddle/fluid/layers/tensor.py index b47ddd0dc9f..a49b4b79fbf 100644 --- a/python/paddle/fluid/layers/tensor.py +++ b/python/paddle/fluid/layers/tensor.py @@ -323,7 +323,15 @@ def concat(input, axis=0, name=None): # [14 15 16]] """ - if _non_static_mode(): + if in_dygraph_mode(): + if isinstance(axis, Variable): + axis = axis.numpy() + axis = axis.item(0) + if not isinstance(input, Variable): + input = [t for t in input if t.shape.count(0) == 0] + return _C_ops.final_state_concat(input, axis) + + if _in_legacy_dygraph(): if isinstance(axis, Variable): axis = axis.numpy() axis = axis.item(0) diff --git a/python/paddle/fluid/tests/unittests/test_concat_op.py b/python/paddle/fluid/tests/unittests/test_concat_op.py index 4feca1b9250..629ddb31d7b 100644 --- a/python/paddle/fluid/tests/unittests/test_concat_op.py +++ b/python/paddle/fluid/tests/unittests/test_concat_op.py @@ -19,6 +19,7 @@ import numpy as np from paddle.fluid.tests.unittests.op_test import OpTest, skip_check_grad_ci, convert_float_to_uint16 import paddle.fluid as fluid from paddle.fluid import compiler, Program, program_guard, core +from paddle.fluid.framework import _test_eager_guard import paddle @@ -49,7 +50,7 @@ class TestConcatOp(OpTest): place = core.CUDAPlace(0) self.check_output_with_place(place) else: - self.check_output() + self.check_output(check_eager=True) def test_check_grad(self): if self.dtype == np.uint16: @@ -58,9 +59,9 @@ class TestConcatOp(OpTest): self.check_grad_with_place(place, ['x1'], 'Out') self.check_grad_with_place(place, ['x2'], 'Out') else: - self.check_grad(['x0'], 'Out') - self.check_grad(['x1'], 'Out') - self.check_grad(['x2'], 'Out') + self.check_grad(['x0'], 'Out', check_eager=True) + self.check_grad(['x1'], 'Out', check_eager=True) + self.check_grad(['x2'], 'Out', check_eager=True) def init_test_data(self): if self.dtype == np.uint16: @@ -124,6 +125,7 @@ class TestConcatOp6(TestConcatOp): def setUp(self): self.op_type = "concat" self.dtype = self.get_dtype() + self.python_api = paddle.concat self.init_test_data() self.lod = [[20, 80]] self.out_lod = [[20, 80, 20, 80, 20, 80]] @@ -141,12 +143,12 @@ class TestConcatOp6(TestConcatOp): self.outputs = {'Out': (out, self.out_lod)} def test_check_output(self): - self.check_output(check_dygraph=False) + self.check_output(check_eager=True) def test_check_grad(self): - self.check_grad(['x0'], 'Out', check_dygraph=False) - self.check_grad(['x1'], 'Out', check_dygraph=False) - self.check_grad(['x2'], 'Out', check_dygraph=False) + self.check_grad(['x0'], 'Out', check_eager=True) + self.check_grad(['x1'], 'Out', check_eager=True) + self.check_grad(['x2'], 'Out', check_eager=True) def init_test_data(self): self.x0 = np.random.random([100]).astype(self.dtype) @@ -159,6 +161,7 @@ def create_test_AxisTensor(parent): class TestConcatAxisTensor(parent): def setUp(self): self.op_type = "concat" + self.python_api = paddle.concat self.dtype = self.get_dtype() self.init_test_data() @@ -334,6 +337,12 @@ class TestConcatAPI(unittest.TestCase): self.assertEqual((out1.numpy() == np_out1).all(), True) self.assertEqual((out2.numpy() == np_out2).all(), True) + def test_eager(self): + with _test_eager_guard(): + self.test_api() + self.test_fluid_api() + self.test_imperative() + def test_errors(self): with program_guard(Program(), Program()): # The item in input must be Variable. @@ -370,6 +379,7 @@ class TestConcatAPIWithLoDTensorArray(unittest.TestCase): def setUp(self): self.axis = 1 + self.python = paddle.concat self.iter_num = 3 self.input_shape = [2, 3] self.x = np.random.random(self.input_shape).astype("float32") diff --git a/python/paddle/utils/code_gen/api.yaml b/python/paddle/utils/code_gen/api.yaml index f38a9bc619e..4f05f107bc2 100644 --- a/python/paddle/utils/code_gen/api.yaml +++ b/python/paddle/utils/code_gen/api.yaml @@ -320,6 +320,7 @@ param : [x, axis] kernel : func : concat + backward : concat_grad - api : conj args : (Tensor x) diff --git a/python/paddle/utils/code_gen/backward.yaml b/python/paddle/utils/code_gen/backward.yaml index 7b6c3832866..db1fe6cdf52 100644 --- a/python/paddle/utils/code_gen/backward.yaml +++ b/python/paddle/utils/code_gen/backward.yaml @@ -179,6 +179,12 @@ kernel : func : cholesky_solve_grad +- backward_api : concat_grad + forward : concat (Tensor[] x, Scalar axis) -> Tensor(out) + args : (Tensor[] x, Tensor out_grad, Scalar axis = 0) + output : Tensor[](x_grad) + invoke : concat_grad_impl(x, out_grad, axis) + - backward_api : conv2d_transpose_grad forward : conv2d_transpose(Tensor x, Tensor filter, int[] strides, int[] paddings, int[] output_padding, int[] output_size, str padding_algorithm, int groups, int[] dilations, str data_format) -> Tensor(out) args : (Tensor x, Tensor filter, Tensor out_grad, int[] strides, int[] paddings, int[] output_padding, int[] output_size, str padding_algorithm, int groups, int[] dilations, str data_format) -- GitLab